diff --git a/CONTRIBUTING.md b/.github/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.md rename to .github/CONTRIBUTING.md diff --git a/.github/deploy_key.scitools-docs.enc b/.github/deploy_key.scitools-docs.enc new file mode 100644 index 0000000000..165a7c1970 --- /dev/null +++ b/.github/deploy_key.scitools-docs.enc @@ -0,0 +1 @@ +gAAAAABZSMeGIlHxHu4oCV_h8shbCRf1qJYoLO9Z0q9uKRDTlytoigzlvfxhN-9WMjc3Js1f1Zg55PfEpTOpL82p6QHF-gqW0k0qGjanO3lnQzM6EzIu3KyJPrVrL-O6edwoPMYKqwsNO3VQHNuEspsFKY0TbjnTPHc45SPU5LjEGX4c_SADSDcLDJm2rbrU2eVkT-gFHy_-ZzK0Di83WlDc79YzIkVe5BAn5PbWv3O9BROR4fJzecbjmWRT_rp1cqI_gaUpVcwTdRK3II9YnazBtW4h2WbCeTcySLD7N4o9K0P71SR6gG_XFbpML3Haf5IUdRi0qPBuvJ_4YVnnuJo6mhiIOJfUEcNj_bbLOYVzPmKyQMHvrPf_lK5JhdX6MUvqluhqHuc0i_z_j1O2y32lB7b1iiY6eE_BsNlXJHlOX1GiXkX0nZLI48p-D22jya44WshWSnVcoalcCDkdbvdFbpOscwXDR3nB-PCOmRUF_d1BlMbp1if-VP0yt3tJ_5yyCrqSRWwFusaibQTF6yoImetl7Am95hh2FjFDNkalHqtarnUv86w-26v1ukcTIjJ0iHzNbCK1m0VMkvE6uDeqRgIZnVKON5cesmM3YbulRrHpaOiSly_sMhLhfg5jTxAuOa319AQGoHEOcRLRUYdw2TQkDEiHGiUh_U4-nC7GTGDGcXyeBIa4ciuC2Qi0QXf9qyEGoIRcU8BP34LDNdtovJoZOBDzhr5Ajnu7yA3GB3TD_kiZrgm6agFuu7a51OMfjezhwGzUJ4X-empPctwm9woOJmPCTFqCvxB2VwVV0L6yngsTooyAHCi5st_AG-p5FIT3VZGx7EgCd68ze9XlRoACoe9XOdSFklbaSMGRbJlvKCPAA0zj4__PfIhlD8Cxwwjq_VXlSr_QxygIGZJlhkT46P9TroolgdipaBp1aQ3_PKHfgw5Y9ZqBKCZF5DOJejqUbfVKUp2JdqoX3yQBD0ByQFdfCuLvoiYcM2ofKdIMvel3Jwn0Nx4NYR2qg3h7FYti0jdrNlC89gnL4tKsf0DAGxZ1UYmqQMWJ3-GKCKrlKyeaHYB2djPRGP8VeoRZh_UorSNHU56KSztK_hTP6P0nFymRJRUSRBMKTaTfJf1aBlk9zJHSe9hOKwxyUNkwcTftGn5P0WNcnaTk3ecTVe-1QJKbPWwMBDzqQtTCsCizgN4UdQsmy4iMYq-LT2TC-JXXo0CPTNDybUj92wSa7KeKTvKnbN8DMZbGRdgy5BOSGw4hMIoIFSB-6tnBIvTntNfMT9ac9e9jKm47Q4qXpaeF3AsvBqxkMRQLaYVppPng6cA49VjJQDZ0gTdPKSSKZkApfeeQL0LLCGwzQ4C52TWK2NJSQ3pvRYI1F0taDQWopIiwFfox-OSYnOJECHkHjxaxhHQzVb3w47xKKZNXbLb-LV7QI-kGuKLfoqO1lq94cw1H-EVrXaGJcDDLjK2jRgdVfDyPsHMcW1oUDJqu8gQ6fCXYPbqJzdmFNFsc1hywHWCU7crV61D2QubwzbLRnP8053MvsMnbdhWtwocTlvvdG-qW6CiEA9Eanfpf0RW1W9oh6yQJ__0vS9UWswqq5ahkkpHY9LTE0US4L3xbFOrq7HgbA2jelTdPVfxo3BfUHuL8oKpFDTzgZi07gNmkhIZfpuXj2KFnm9XM31AsY6V2rXL0xSx-9rvi4FP0LK6V5vQ8OKI8aRPCDyzLUv2xnayMW4yaYg3GHD5yo7pIOswKc6GOEmetPnay3j0dVN3hfpkpfJWhss3vjZ2Zl0NmjJ7OuS25tjUGLy82A1yFSpL8mKRkHZJuMDZbd_Or6gaPVoVT_Otbkh-6pMZuDeOHOUfgey0Z374jCjRpyQ9k-Fpw8ykow8iIIQ088kC5CeQy6jRhD7mO3iR4-U1XKDJQNlNg1z_JYyDrwykp7FFN2sQn7RRYHIXx2iMrEDXdrdTrujMFN6omC13yDuXJukAgZb6zBBUTlonxRUBjUJWt2P-1sRRTsG8mr9EaE5K-xhR5Ust_37L3svNQ0vwLtPLIpWGZHhD8P_dYNR2RL4679xyzI8A7wLY82wFBHrcghAd4UtLJH9ul6IuS_CaVo-gbfowNRaQ0Zw7WHZGIXpZWEx1_zck6qDEaCY8TpQeciBWpH5uJDSYqdLdMwigdQEGzAJ1DHSWsyTrmOR7Lhwi9WqOzfWe4ahxAkAUH_Jdr_i-nGfl_x3OgQdHM7jWVMXDcXEmR0bkw-s0EKXCn20q2bxDkm5SUWkYtWAZ2aZRgo4wHOqGBcP99xZ25mq9uxtNOkLBF81lnVbn_4BAZBNnnKwwj4SafeIW4KR1ZOpnEI47sGUR6NhEk9VtJsv0zeZIv8VjRbNLh3QCxkNMue60SjJ48kjotZSX1RQJN0xwPftiABBf8MX9tyZe8emQvPeIcdQTSQPnYEUx22xZGeeJTNrZ9soQyP6mrkkRihp6o9tG7HT9QEVLGM19wAigwAAMMXGqdGzWwpar30JtJU94gAmIlwFUJqeO_fdJKFspnUyJ6gt5_oHsKNEV7Uz5EJwGpa94tlPJXjvZpu-wWQfu8U0trTU2mTCA0bmZIDID-Xk4vCW_SD4OVnsvWyga4QHSg3AqVTjnjlapAjsYcFjiOo2C_U3besloprpyuAwpTdn7zdfMHIJO0ckBFnXlk8XB3kT0YGrCpBvW6gYMXlnePVcr3wJehCvMg1Q9Dc5fVQUqt65zcjbgiudfzFGtTe9T4f1IttoAtrJgTN4W1mtbZzSK864I_ngaX5YWgZSinjkbocCCFEJDcbiXMnV7OWOZefqW6VZu4BZKEKlN9k2kH3UCECCK3uRAQIPn_48DgaVnAff2-fMADltiosSPJ_a3057acJP0cf-1QsJuV7r3zdzL3shgrMRjpSsSTCYdMhZ6disFGcJg7hJJvtH1FieZ76jps5FYi5lE8Ua9yBKlG4dCGuUBnikvpfy2FLMLFNn-iXLflu2oiBbcLvn_ReZUnFIR6KgGRN8xKEBaXATQVtb2E678GtQptK8PHP2DoAtbsIXUDn60YH04D9pEck8NnmWYAz7sWbiL6OKdaO7jQep4mt3CgkyFC0NCKP9zCbVNtmfHRVmHtckjgfHF-tK_v59KeAuwWPtm7ow2BjynAK42IGR9nWtQFRUZIboaND8UF76YGKFF7kOf_XTvoNrVTCRkD6b8KJy2IFfdoHP6WET9QLvwDSXgYLPlCX9z7aQ_lc57u5d_dGO-7NZ_Qbs69ByyIvQoztVBjw6fa7EzSwccqPfMQL_fiecNCng-r4gHaH6TlgSbfqQOISHxTtvmbym1no560ZsHfnQfuL6BCI8s6OoygxhOnQhaDqyOUVBut_x3VR_DKFMyUazXYNgLbRsdITaAvR-0gIx5TAX9n3A4HwHuiBZCtwRYaiJnW8FX9lk1Y_g5UHL2OC3rsNFui3aBLzAFhx58lALxnxhlUItuHHK9BgexnR2yCj2nOWLoWQzfFaf2_fpjEh_QBHTqUxdQZ8ighg_8lh6hmLbW4PcUxKX71RFmikLyS3-idlzsiEomNlPNaVllRF21vE6dR-nZ6xsxzTvNB4wumP2irQ9mFBTN1WpiLMyNoEEucA2I848YHUfkZrjTG_dcCQNp7H_2gKdIsZ135lUEG6lYfhLMHTmP5uYxxx3Pipjp6wF2GFCsZPIlIPsgrhbSxqkWg1EOViHtpw6ypFKn7wQHHfnrnHkFWnrKbMARVBjJUB-FhK4b6qLU_k_MTMipemneMUFXlj3EkEhKM18MIHGkIOkwG5QtPYcjUAf_2sZlxSMVnh6sQ8kVwF6lfk_l8jhoO93HUTntZUSv7GrE3s80yJgII4Qw37AdgcJiAkoPn1-17HfSsAy6uRh5-OvrCtkDqQxfuJSyn_4pRMh6hZT7N9pI5limMXXn2nHnxU93UT3qU-smA8q0ECfvK3JwoaYy_llSx0wSBvpmxjLQ302sFYM5FVZ9zRbHuLCCZShVopiyMDLHVJe_1g9Ou1KL-h6RVZgg3Ttyb5m2KDfoHEVLeZkW81YLCsyo7uNb6SVRM-615TIVGT6Eq7oJ6wO2LMDKjEpHKFiOFpY2fpR8noM81UqgLddYfl_lei7RVjaNO98otqE4iSNtpgJgyhAx4CdYm__yQRSXhckR4K7yAhM9Kh5BLbQQnf2_0WS1sWTmNMZZNMfOSqmTCRVwcYvg4TDGOA-vZARbZW1M7npVMldV_SbvgcEZD6InY9c40eheRqS0YD2W2HEZIiNeLRw0y5WBcYuJIpXhI3ViTXx-frJnv0Mo9uwmuLbJmWFcn6RdIVcU68_oPZZlZD4Vm7SjikbuZKF1BF3lXamTTDIBcWiDLwuNDv2lUkURDCWa5WJsfUCfTAJ6PTe8= \ No newline at end of file diff --git a/.gitignore b/.gitignore index da0c85eaab..f0420cbc22 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,10 @@ *.py[co] +# Environment file which should be autogenerated +*conda_requirements.txt* + # Packages -*.egg +*.egg? *.egg-info dist build @@ -15,10 +18,12 @@ develop-eggs # Installer logs pip-log.txt +pip-cache # Unit test / coverage reports .coverage .tox +.pytest_cache #Translations *.mo @@ -31,17 +36,30 @@ lib/iris/std_names.py # Iris test result files lib/iris/tests/result_image_comparison/ +iris_image_test_output/ +*.ESMF_LogFile + +# Iris test lock file +lib/iris/tests/results/imagerepo.lock # Pydev/Eclipse files .project .pydevproject .settings +# PyCharm files +/.idea +*.cover + # Auto generated documentation files docs/iris/src/_static/random_image.js docs/iris/src/_templates/gallery.html docs/iris/src/examples/ docs/iris/src/iris/ +docs/iris/src/matplotlibrc + +# Example test results +docs/iris/iris_image_test_output/ # Created by editiors *~ diff --git a/.mailmap b/.mailmap new file mode 100644 index 0000000000..910e72cd99 --- /dev/null +++ b/.mailmap @@ -0,0 +1,13 @@ +Mark Hedley +Mark Hedley +Ed Campbell +Andrew Dawson +Andrew Dawson +Andrew Dawson +Ian Edwards +Danny Rice + +Laura Dreyer + +Ruth Comer + diff --git a/.stickler.yml b/.stickler.yml new file mode 100644 index 0000000000..31d097914e --- /dev/null +++ b/.stickler.yml @@ -0,0 +1,6 @@ +linters: + flake8: + +files: + ignore: + - 'lib/iris/fileformats/um_cf_map.py' diff --git a/.travis.yml b/.travis.yml index 1b7a5be8fb..ac5d341307 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,143 +1,167 @@ -# -# Based on pelson's travis work for cartopy. -# -# Please update the cartopy, test data, and sample data git references below if appropriate. +# Please update the test data git references below if appropriate. # # Note: Contrary to the travis documentation, # http://about.travis-ci.org/docs/user/languages/python/#Travis-CI-Uses-Isolated-virtualenvs -# we will use the system python because it takes too long to install scipy from source. -# +# we will use conda to give us a much faster setup time. language: python python: - 2.7 + - 3.6 +sudo: false + +env: + matrix: + - TEST_TARGET=default TEST_MINIMAL=true + - TEST_TARGET=default + - TEST_TARGET=example + - TEST_TARGET=doctest + + global: + # The decryption key for the encrypted .github/deploy_key.scitools-docs.enc. + - secure: "N9/qBUT5CqfC7KQBDy5mIWZcGNuUJk3e/qmKJpotWYV+zwOI4GghJsRce6nFnlRiwl65l5oBEcvf3+sBvUfbZqh7U0MdHpw2tHhr2FSCmMB3bkvARZblh9M37f4da9G9VmRkqnyBM5G5TImXtoq4dusvNWKvLW0qETciaipq7ws=" git: - depth: 0 + # We need a deep clone so that we can compute the age of the files using their git history. + depth: 10000 install: - - - export BIGGUS_REF="da8f19f197adff77e8071b0e04269c8b888a1fbf" - - export BIGGUS_SUFFIX=$(echo "${BIGGUS_REF}" | sed "s/^v//") - - - export CARTOPY_REF="v0.10.0" - - export CARTOPY_SUFFIX=$(echo "${CARTOPY_REF}" | sed "s/^v//") - - - export IRIS_TEST_DATA_REF="3378fe68c00ca7f31895ab6630a59a39ccef94e3" - - export IRIS_TEST_DATA_SUFFIX=$(echo "${IRIS_TEST_DATA_REF}" | sed "s/^v//") - - - export IRIS_SAMPLE_DATA_REF="2e7c73504e3d675d97dc8a2c2939f9fd2cfe51f1" - - export IRIS_SAMPLE_DATA_SUFFIX=$(echo "${IRIS_SAMPLE_DATA_REF}" | sed "s/^v//") - -# Switch off virtualenv so we can use apt-get for Python packages. - - deactivate - -# add repo - - ./.travis_no_output sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3E5C1192 - - ./.travis_no_output sudo add-apt-repository -y ppa:ubuntugis/ppa -# access to scipy 0.12.0 https://launchpad.net/~pylab/+archive/stable - - sudo add-apt-repository -y ppa:pylab/stable - - ./.travis_no_output sudo apt-get update - -# install deps - - ./.travis_no_output sudo apt-get install python-scipy cython python-pip - - ./.travis_no_output sudo /usr/bin/pip install numpy==1.7.2 - - ./.travis_no_output sudo /usr/bin/pip install --use-mirrors shapely nose - - ./.travis_no_output sudo /usr/bin/pip install --use-mirrors pyshp pep8 mock - - ./.travis_no_output sudo /usr/bin/pip install --use-mirrors setuptools - - ./.travis_no_output sudo /usr/bin/pip install matplotlib==1.3.1 - - ./.travis_no_output sudo apt-get install libgeos-dev libproj-dev - - ./.travis_no_output sudo apt-get install libudunits2-dev libhdf5-serial-dev netcdf-bin libnetcdf-dev - - ./.travis_no_output sudo apt-get install make unzip python-sphinx graphviz - - ./.travis_no_output sudo /usr/bin/pip install netCDF4==1.0.2 - - ./.travis_no_output sudo /usr/bin/pip install pyke - - ./.travis_no_output sudo /usr/bin/pip install pandas==0.12.0 - - ./.travis_no_output sudo apt-get install openjdk-7-jre - - sudo apt-get install python-gdal - - export LD_LIBRARY_PATH=/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/server:$LD_LIBRARY_PATH - -# cfchecker - - ./.travis_no_output sudo /usr/bin/pip install cdat-lite -# cfchecker via pip normally works, but we've found the pip interface to fail intermittently, -# therefore we specify the full download url. -# - ./.travis_no_output sudo /usr/bin/pip install cfchecker - - ./.travis_no_output sudo /usr/bin/pip install https://pypi.python.org/packages/source/c/cfchecker/cfchecker-2.0.3.tar.gz#md5=54e780e8688ac743d1e21448a3901061 - - - echo '#!/usr/bin/env sh' > cfchecker - - echo "cfchecks -s `pwd`/etc/cf-standard-name-table.xml -a `pwd`/etc/area-type-table.xml -u /usr/share/xml/udunits/udunits2.xml \$1" >> cfchecker - - ./.travis_no_output sudo cp cfchecker /usr/local/bin/cfchecker - - ./.travis_no_output sudo chmod a+x /usr/local/bin/cfchecker - -# grib api - - ./.travis_no_output sudo apt-get install libjasper-dev - - ./.travis_no_output sudo apt-get build-dep libgrib-api-1.9.9 libgrib-api-dev libgrib-api-tools - - ./.travis_no_output wget https://software.ecmwf.int/wiki/download/attachments/3473437/grib_api-1.9.16.tar.gz --no-check-certificate - - ./.travis_no_output tar -xvf grib_api-1.9.16.tar.gz - - cd grib_api-1.9.16/ - - ../.travis_no_output CFLAGS="-fPIC" ./configure --with-jasper=/usr/local/lib --disable-fortran --enable-python - - ../.travis_no_output make - - ../.travis_no_output sudo make install - - cd python - - ../../.travis_no_output sudo /usr/bin/python setup.py install - - cd ../.. - -# biggus - - ./.travis_no_output wget -O biggus.zip https://github.com/SciTools/biggus/archive/${BIGGUS_REF}.zip - - ./.travis_no_output unzip -q biggus.zip - - ln -s $(pwd)/biggus-${BIGGUS_SUFFIX} biggus - - cd biggus - - ../.travis_no_output /usr/bin/python setup.py install --user - - cd .. - -# cartopy - - ./.travis_no_output wget -O cartopy.zip https://github.com/SciTools/cartopy/archive/${CARTOPY_REF}.zip - - ./.travis_no_output unzip -q cartopy.zip - - ln -s $(pwd)/cartopy-${CARTOPY_SUFFIX} cartopy - - cd cartopy - - ../.travis_no_output /usr/bin/python setup.py install --user - - cd .. + - > + export IRIS_TEST_DATA_REF="2f3a6bcf25f81bd152b3d66223394074c9069a96"; + export IRIS_TEST_DATA_SUFFIX=$(echo "${IRIS_TEST_DATA_REF}" | sed "s/^v//"); + + # Cut short doctest phase under Python 2 : now only supports Python 3 + # SEE : https://github.com/SciTools/iris/pull/3134 + # ------------ + - > + if [[ $TEST_TARGET == 'doctest' && ${TRAVIS_PYTHON_VERSION} != 3* ]]; then + echo "DOCTEST phase only valid in Python 3 : ABORTING during 'install'." + exit 0 + fi + + # Install miniconda + # ----------------- + - > + echo 'Installing miniconda'; + export CONDA_BASE=https://repo.continuum.io/miniconda/Miniconda; + if [[ "$TRAVIS_PYTHON_VERSION" == 2* ]]; then + wget --quiet ${CONDA_BASE}2-latest-Linux-x86_64.sh -O miniconda.sh; + else + wget --quiet ${CONDA_BASE}3-latest-Linux-x86_64.sh -O miniconda.sh; + fi; + bash miniconda.sh -b -p $HOME/miniconda; + export PATH="$HOME/miniconda/bin:$PATH"; + + # Create the basic testing environment + # ------------------------------------ + # Explicitly add defaults channel, see https://github.com/conda/conda/issues/2675 + - > + echo 'Configure conda and create an environment'; + conda config --set always_yes yes --set changeps1 no; + conda config --set show_channel_urls True; + conda config --add channels conda-forge; + conda update --quiet conda; + ENV_NAME='test-environment'; + conda create --quiet -n $ENV_NAME python=$TRAVIS_PYTHON_VERSION pip; + source activate $ENV_NAME; + + # Customise the testing environment + # --------------------------------- + - > + echo 'Install Iris dependencies'; + CONDA_REQS_FLAGS=""; + CONDA_REQS_GROUPS="test"; + if [[ "$TRAVIS_PYTHON_VERSION" == 2* ]]; then + CONDA_REQS_FLAGS="${CONDA_REQS_FLAGS} --py2"; + fi; + if [[ "$TEST_MINIMAL" != true ]]; then + CONDA_REQS_GROUPS="${CONDA_REQS_GROUPS} all"; + fi; + if [[ "${TEST_TARGET}" == 'doctest' ]]; then + CONDA_REQS_GROUPS="${CONDA_REQS_GROUPS} docs"; + fi; + CONDA_REQS_FILE=conda-requirements.txt; + python requirements/gen_conda_requirements.py ${CONDA_REQS_FLAGS} --groups ${CONDA_REQS_GROUPS} > ${CONDA_REQS_FILE}; + cat ${CONDA_REQS_FILE}; + conda install --quiet -n $ENV_NAME --file ${CONDA_REQS_FILE}; + + - PREFIX=$HOME/miniconda/envs/$ENV_NAME + + # Output debug info + - > + conda list -n $ENV_NAME; + conda list -n $ENV_NAME --explicit; + conda info -a; # Pre-load Natural Earth data to avoid multiple, overlapping downloads. # i.e. There should be no DownloadWarning reports in the log. - - /usr/bin/python -c 'import cartopy; cartopy.io.shapereader.natural_earth()' - -# mo_unpack - - ./.travis_no_output wget https://puma.nerc.ac.uk/trac/UM_TOOLS/raw-attachment/wiki/unpack/unpack-030712.tgz - - ./.travis_no_output tar -xf unpack-030712.tgz - - cd unpack-030712/libmo_unpack -#? - gcc -c -fPIC -O4 -mfpmath=sse -msse -I include -D_LARGEFILE_SOURCE -D_LARGEFILE_SOURCE64 -D_FILE_OFFSET_BITS=64 *.c - - ../../.travis_no_output gcc -c -fPIC -O4 -mfpmath=sse -msse -I include -D_LARGEFILE_SOURCE *.c - - ../../.travis_no_output gcc -shared -Wl,-soname,libmo_unpack.so -o lib/libmo_unpack.so *.o - - ../../.travis_no_output sudo cp lib/* /usr/local/lib - - ../../.travis_no_output sudo cp include/* /usr/local/include - - cd ../.. + - python -c 'import cartopy; cartopy.io.shapereader.natural_earth()' # iris test data - - ./.travis_no_output wget -O iris-test-data.zip https://github.com/SciTools/iris-test-data/archive/${IRIS_TEST_DATA_REF}.zip - - ./.travis_no_output unzip -q iris-test-data.zip - - ln -s $(pwd)/iris-test-data-${IRIS_TEST_DATA_SUFFIX} iris-test-data - -# iris sample data - - ./.travis_no_output wget -O iris-sample-data.zip https://github.com/SciTools/iris-sample-data/archive/${IRIS_SAMPLE_DATA_REF}.zip - - ./.travis_no_output unzip -q iris-sample-data.zip - - ln -s $(pwd)/iris-sample-data-${IRIS_SAMPLE_DATA_SUFFIX} iris-sample-data - -# iris - - ./.travis_no_output /usr/bin/python setup.py --with-unpack build_ext --inplace -I/usr/local/include -L/usr/local/lib -R/usr/local/lib - - ./.travis_no_output /usr/bin/python setup.py std_names - - echo "[Resources]" > lib/iris/etc/site.cfg - - echo "sample_data_dir = $(pwd)/iris-sample-data/sample_data" >> lib/iris/etc/site.cfg - - echo "test_data_dir = $(pwd)/iris-test-data/test_data" >> lib/iris/etc/site.cfg - - ln -s $(pwd)/lib/iris /home/travis/.local/lib/python2.7/site-packages/iris - - ./.travis_no_output /usr/bin/python setup.py pyke_rules + - > + if [[ "$TEST_MINIMAL" != true ]]; then + wget --quiet -O iris-test-data.zip https://github.com/SciTools/iris-test-data/archive/${IRIS_TEST_DATA_REF}.zip; + unzip -q iris-test-data.zip; + mv "iris-test-data-${IRIS_TEST_DATA_SUFFIX}" iris-test-data; + fi + +# set config paths + - > + SITE_CFG=lib/iris/etc/site.cfg; + echo "[Resources]" > $SITE_CFG; + echo "test_data_dir = $(pwd)/iris-test-data/test_data" >> $SITE_CFG; + echo "doc_dir = $(pwd)/docs/iris" >> $SITE_CFG; + echo "[System]" >> $SITE_CFG; + echo "udunits2_path = $PREFIX/lib/libudunits2.so" >> $SITE_CFG; + + - python setup.py --quiet install + + # JUST FOR NOW : Install latest version of iris-grib. + # TODO : remove when iris doesn't do an integration test requiring iris-grib. + - if [[ "$TEST_MINIMAL" != true && ${TRAVIS_PYTHON_VERSION} == 2* ]]; then + conda install --quiet -n $ENV_NAME python-ecmwf_grib; + pip install git+https://github.com/SciTools/iris-grib.git@v0.11.0; + fi script: - - /usr/bin/python setup.py test --example-tests - - - cd $(pwd)/docs/iris -# Make html produces an error when run on Travis that does not affect any downstream functionality but causes the build to fail spuriously. -# The following gets around this error, which should be investigated further in the future. - - echo `make clean html` - - - make doctest + - if [[ $TEST_TARGET == 'default' ]]; then + python -m iris.tests.runner --default-tests --system-tests --coding-tests --print-failed-images --num-processors=3; + fi + - if [[ $TEST_TARGET == 'example' ]]; then + python -m iris.tests.runner --example-tests --print-failed-images --num-processors=3; + fi + + # Capture install-dir: As a test command must be last for get Travis to check + # the RC, so it's best to start each operation with an absolute cd. + - INSTALL_DIR=$(pwd) + + - > + if [[ $TEST_TARGET == 'doctest' ]]; then + MPL_RC_DIR=$HOME/.config/matplotlib; + mkdir -p $MPL_RC_DIR; + echo 'backend : agg' > $MPL_RC_DIR/matplotlibrc; + echo 'image.cmap : viridis' >> $MPL_RC_DIR/matplotlibrc; + cd $INSTALL_DIR/docs/iris; + make clean html && make doctest; + fi + + # Split the organisation out of the slug. See https://stackoverflow.com/a/5257398/741316 for description. + - ORG=(${TRAVIS_REPO_SLUG//\// }) + + # When we merge a change, and we are running in python 3, push some docs. + - if [[ $TEST_TARGET == 'doctest' && ${TRAVIS_EVENT_TYPE} == 'push' && ${TRAVIS_PYTHON_VERSION} == 3* && ${ORG} == "SciTools" ]]; then + cd $INSTALL_DIR; + pip install doctr; + doctr deploy --deploy-repo SciTools-docs/iris --built-docs docs/iris/build/html + --key-path .github/deploy_key.scitools-docs.enc + --no-require-master + ${TRAVIS_BRANCH:-${TRAVIS_TAG}}; + fi + + # An extra call to check "whatsnew" contributions are valid, because the + # Iris test for it needs a *developer* install to be able to find the docs. + - if [[ $TEST_TARGET == 'doctest' ]]; then + cd $INSTALL_DIR/docs/iris/src/whatsnew; + python aggregate_directory.py --checkonly; + fi diff --git a/.travis_no_output b/.travis_no_output deleted file mode 100755 index 8f5ccd5eca..0000000000 --- a/.travis_no_output +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash - -# used by .travis.yml to filter output if there were no problems with the -# command, otherwise the stdout and stderr are outputted. - - -stdout_tmp=/tmp/output.stdout.txt -stderr_tmp=/tmp/output.stderr.txt - -eval $@ > $stdout_tmp 2> $stderr_tmp - -result=$? -if [[ $result -ne 0 ]] ; then - echo "Failed (exit code $result)" - cat $stderr_tmp > /dev/stderr - cat $stdout_tmp > /dev/stdout -fi; - -exit $result - diff --git a/CHANGES b/CHANGES index c0bcb1623e..2364de84a4 100644 --- a/CHANGES +++ b/CHANGES @@ -343,6 +343,25 @@ Deprecations ---------------------------- +Release 0.9.1 (11 Sep, 2012) +============================ + +Features added +-------------- +* Fixed an issue with netCDF loading that failed to close file handles. + +Incompatible changes +-------------------- +* None + +Deprecations +------------ +* None + + +---------------------------- + + Release 0.9 (14 Aug, 2012) ========================== diff --git a/INSTALL b/INSTALL index c045433fa3..c8a61769fe 100644 --- a/INSTALL +++ b/INSTALL @@ -1,151 +1,95 @@ -Installing Iris currently requires you to build it from source. The -latest release is available from https://github.com/SciTools/iris. +You can either install Iris using the conda package manager or from source. -Iris makes use of a range of other libraries and python modules. These -dependencies must be in place before you can successfully install -Iris. Once you have satisfied the requirements detailed below, -extract the iris source package, cd to the new directory, and enter:: +Installing using conda +---------------------- - python setup.py install +Iris is available using conda for the following platforms: + * Linux 64-bit, + * Mac OSX 64-bit, and + * Windows 32-bit and 64-bit. +To install Iris using conda, you must first download and install conda, +for example from http://conda.pydata.org/miniconda.html. -In-place build - an alternative for developers -============================================== -We strongly encourage people to contribute to Iris and for this type of -development activity an in-place build can be useful. Once you've cloned -the Iris git repository you can perform an in-place build by entering:: - - python setup.py std_names - python setup.py build_ext --inplace - -Details of other setup.py options and commands can be found by entering:: - - python setup.py --help - -and:: - - python setup.py --help-commands - +Once conda is installed, you can install Iris using conda on any platform with +the following command:: + conda install -c conda-forge iris -Build requirements -================== -These are external packages which you will need to install before -installing Iris. +If you wish to run any of the code examples +(see http://scitools.org.uk/iris/docs/latest/examples/index.html) you will also +need the Iris sample data. This can also be installed using conda:: -Many of these packages are available in Linux package managers -such as aptitude and yum. For example, it may be possible to install -Numpy using:: + conda install -c conda-forge iris-sample-data - apt-get install python-numpy +Further documentation on using conda and the features it provides can be found +at http://conda.pydata.org/docs/intro.html. -If you are installing dependencies with a package manager on Linux, -you may need to install the development packages (look for a "-dev" -postfix) in addition to the core packages. -python 2.7 or later (http://www.python.org/) - Iris requires Python 2.7 or later, but is not currently compatible with Python 3. +Installing from source +---------------------- -numpy 1.6 or later (http://numpy.scipy.org/) - Python package for scientific computing including a powerful N-dimensional array object. +The latest Iris source release is available from +https://github.com/SciTools/iris. -scipy 0.10 or later (http://www.scipy.org/) - Python package for scientific computing. +Iris makes use of a range of other libraries and python modules. These +dependencies must be in place before you can successfully install +Iris. Once you have satisfied the requirements detailed in the +``requirements`` directory, go to the root of Iris' and run:: -udunits2 2.1.24 or later (http://www.unidata.ucar.edu/downloads/udunits/index.jsp) - C library for units of physical quantities. + pip install . -netcdf4-python 0.9.9 or later (http://netcdf4-python.googlecode.com/) - Python interface to the netCDF version 4 C library. -PyKE 1.1.1 or later (http://pyke.sourceforge.net/) - Python knowledge-based inference engine. - -setuptools 0.6c11 or later (http://pypi.python.org/pypi/setuptools/) - Python package for installing/removing python packages. - -cartopy 0.8.0 or later (http://github.com/SciTools/cartopy/) - Python package which provides cartographic tools for python. - -Optional --------- -These are optional packages which you may want to install to enable -additonal Iris functionality such as plotting and -loading/saving GRIB. These packages are required for the full Iris test -suite to run. +In-place build - an alternative for developers +============================================== +We are very keen to encourage contributions to Iris. For this type of +development activity an in-place build can be useful. Once you've cloned +the Iris git repository you can perform an in-place build with:: -gdal 1.9.1 or later (https://pypi.python.org/pypi/GDAL/) - Python package for the Geospatial Data Abstraction Library (GDAL). + pip install -e . -graphviz 2.18 or later (http://www.graphviz.org/) - Graph visualisation software. -grib-api 1.9.16 or later (https://software.ecmwf.int/wiki/display/GRIB/Releases) - API for the encoding and decoding WMO FM-92 GRIB edition 1 and - edition 2 messages. A compression library such as Jasper is required - to read JPEG2000 compressed GRIB2 files. +Generating conda requirements +''''''''''''''''''''''''''''' -matplotlib 1.2.0 (http://matplotlib.sourceforge.net/) - Python package for 2D plotting. +Requirements for Iris are stored in the ``requirements`` directory in the root of the source repository. +It is possible to generate a requirements file suitable for use with conda:: -mock 1.0.1 (http://pypi.python.org/pypi/mock/) - Python mocking and patching package for testing. Note that this package - is only required to support the Iris unit tests. + python requirements/gen_conda_requirements.py > conda_requirements.txt -nose 1.1.2 or later (http://nose.readthedocs.org/en/latest/) - Python package for software testing. Iris is not compatible with nose2. +This may then be installed with:: -pandas 0.11.0 or later (http://pandas.pydata.org) - Python package providing high-performance, easy-to-use data structures and - data analysis tools. + conda create -n my_iris_env --file conda_requirements.txt -PythonImagingLibrary 1.1.7 or later (http://effbot.org/zone/pil-index.htm) - Python package for image processing. +Alternatively, a full requirements file that includes all optional dependencies can be produced with:: -shapely 1.2.14 (https://github.com/Toblerity/Shapely) - Python package for the manipulation and analysis of planar geometric objects. + python requirements/gen_conda_requirements.py --groups all > conda_requirements.txt -Packed PP -========= -The libmo_unpack library can be used by Iris for decoding/unpacking -PP files or Fields files that use an lbpack value of 1 or 4. This -library is open source, licensed under the 2-clause BSD licence. -It can be obtained from http://puma.nerc.ac.uk/trac/UM_TOOLS/wiki/unpack. +Running the tests +''''''''''''''''' -Use of this library is not enabled by default. If this library is -available its use can be enabled by installing Iris with the following -command:: +In order to run the tests, you will need to use the `test` and `docs` groups (we include the `docs` group so that you can run the pull request tests locally). +Hence the commands change to:: - python setup.py --with-unpack install + python requirements/gen_conda_requirements.py --groups test docs > conda_requirements.txt + conda create -n my_iris_env --file conda_requirements.txt + conda activate my_iris_env # or whatever other name you gave it + pip install -e . -Note that if this library and/or its associated header files are installed -in a custom location then additional compiler arguments may need to be -passed in to ensure that the Python extension module linking against it -builds correctly:: +The tests can then be run with - python setup.py --with-unpack build_ext -I \ - -L -R install + python setup.py test Custom site configuration ========================= The default site configuration values can be overridden by creating the file ``iris/etc/site.cfg``. For example, the following snippet can be used to -specify a non-standard location for your udunits library:: +specify a non-standard location for your dot executable:: [System] - udunits2_path = /path/to/libudunits2.so + dot_path = /usr/bin/dot An example configuration file is available in ``iris/etc/site.cfg.template``. See :py:func:`iris.config` for further configuration options. - - -Packaged distributions -====================== -The Enthought Python Distribution `(EPD) -`_ for Windows, OS X or -Redhat provides some of the dependencies for Iris as does `Python (x, y) -`_ which tends to be updated a -bit more frequently. - diff --git a/MANIFEST.in b/MANIFEST.in index 8d6f86d989..efd0534863 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,20 +2,20 @@ include CHANGES COPYING COPYING.LESSER INSTALL # Files from setup.py package_data that are not automatically added to source distributions -recursive-include lib/iris/tests/results *.cml *.cdl *.txt *.xml -recursive-include lib/iris/etc *.txt +recursive-include lib/iris/tests/results *.cml *.cdl *.txt *.xml *.json +recursive-include lib/iris/etc * include lib/iris/fileformats/_pyke_rules/*.k?b include lib/iris/tests/stock*.npz +include requirements/*.txt + # File required to build docs recursive-include docs Makefile *.js *.png *.py *.rst -recursive-exclude docs/iris/build * +prune docs/iris/build # Files required to build std_names module include tools/generate_std_names.py include etc/cf-standard-name-table.xml -# Extension source -recursive-include src *.c *.cc *.cpp *.h - - +global-exclude *.pyc +global-exclude __pycache__ diff --git a/README.md b/README.md index 724f41ded9..bfb1353102 100644 --- a/README.md +++ b/README.md @@ -1,66 +1,112 @@ -Iris -==== - -[![Build Status](https://secure.travis-ci.org/SciTools/iris.png)](http://travis-ci.org/SciTools/iris) - -(C) British Crown Copyright 2010 - 2014, Met Office - -Iris is a powerful, easy to use, community-driven Python library for -analysing and visualising meteorological and oceanographic data sets. - - -Installation ------------- - -Provided all of the dependencies are satisfied, Iris can be installed -using the following command: - - python setup.py install - -For more detailed instructions, including details of the dependencies, -please see INSTALL. - - -What's new ----------- - -A discussion of recent changes is given by the -"What's new" document: - -- http://scitools.org.uk/iris/docs/latest/whatsnew/index.html - -If you need complete detail, then please refer to the commit history of -the Iris project on GitHub: - -- https://github.com/SciTools/iris - - -Documentation -------------- - -The full documentation for Iris, including a user guide, example -code, and gallery, is online at: - -- http://scitools.org.uk/iris/ - - -Copyright and licence ---------------------- - -(C) British Crown Copyright 2010 - 2014, Met Office - -This file is part of Iris. - -Iris is free software: you can redistribute it and/or modify it under -the terms of the GNU Lesser General Public License as published by the -Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Iris is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with Iris. If not, see . +

+ + Iris
+

+ +

+ Iris is a powerful, format-agnostic, community-driven Python library for + analysing and visualising Earth science data +

+ +

+ + +conda-forge downloads + +Latest version + +Commits since last release + +# contributors + +Travis-CI + +zenodo +

+
+ + + +

Table of contents

+ +[](TOC) + ++ [Overview](#overview) ++ [Documentation](#documentation) ++ [Installation](#installation) ++ [Copyright and licence](#copyright-and-licence) ++ [Get in touch](#get-in-touch) ++ [Contributing](#contributing) + +[](TOC) + +# Overview + +Iris implements a data model based on the [CF conventions](http://cfconventions.org/) +giving you a powerful, format-agnostic interface for working with your data. +It excels when working with multi-dimensional Earth Science data, where tabular +representations become unwieldy and inefficient. + +[CF Standard names](http://cfconventions.org/standard-names.html), +[units](https://github.com/SciTools/cf_units), and coordinate metadata +are built into Iris, giving you a rich and expressive interface for maintaining +an accurate representation of your data. Its treatment of data and + associated metadata as first-class objects includes: + + * a visualisation interface based on [matplotlib](https://matplotlib.org/) and + [cartopy](https://scitools.org.uk/cartopy/docs/latest/), + * unit conversion, + * subsetting and extraction, + * merge and concatenate, + * aggregations and reductions (including min, max, mean and weighted averages), + * interpolation and regridding (including nearest-neighbor, linear and area-weighted), and + * operator overloads (``+``, ``-``, ``*``, ``/``, etc.) + +A number of file formats are recognised by Iris, including CF-compliant NetCDF, GRIB, +and PP, and it has a plugin architecture to allow other formats to be added seamlessly. + +Building upon [NumPy](http://www.numpy.org/) and [dask](https://dask.pydata.org/en/latest/), +Iris scales from efficient single-machine workflows right through to multi-core clusters and HPC. +Interoperability with packages from the wider scientific Python ecosystem comes from Iris' +use of standard NumPy/dask arrays as its underlying data storage. + + +# Documentation + +The documentation for Iris is available at , +including a user guide, example code, and gallery. + +# Installation + +The easiest way to install Iris is with [conda](https://conda.io/miniconda.html): + + conda install -c conda-forge iris + +Detailed instructions, including information on installing from source, +are available in [INSTALL](INSTALL). + +# Get in touch + + * Report bugs, or suggest new features using an Issue or Pull Request on [Github](https://github.com/SciTools/iris). You can also comment on existing Issues and Pull Requests. + * For discussions from a user perspective you could join our [SciTools Users Google Group](https://groups.google.com/forum/#!forum/scitools-iris). + * For those involved in developing Iris we also have an [Iris Developers Google Group](https://groups.google.com/forum/#!forum/scitools-iris-dev). + * [StackOverflow](https://stackoverflow.com/questions/tagged/python-iris) For "How do I?". + +# Copyright and licence + +Iris may be freely distributed, modified and used commercially under the terms +of its [GNU LGPLv3 license](COPYING.LESSER). + +# Contributing +Information on how to contribute can be found in the [Iris developer guide](https://scitools.org.uk/iris/docs/latest/developers_guide/index.html). +(C) British Crown Copyright 2010 - 2018, Met Office diff --git a/docs/iris/example_code/graphics/SOI_filtering.py b/docs/iris/example_code/General/SOI_filtering.py similarity index 90% rename from docs/iris/example_code/graphics/SOI_filtering.py rename to docs/iris/example_code/General/SOI_filtering.py index 3857434911..a488b5865e 100644 --- a/docs/iris/example_code/graphics/SOI_filtering.py +++ b/docs/iris/example_code/General/SOI_filtering.py @@ -38,7 +38,7 @@ def low_pass_weights(window, cutoff): The cutoff frequency in inverse time steps. """ - order = ((window - 1) // 2 ) + 1 + order = ((window - 1) // 2) + 1 nwts = 2 * order + 1 w = np.zeros([nwts]) n = nwts // 2 @@ -52,7 +52,6 @@ def low_pass_weights(window, cutoff): def main(): - # Load the monthly-valued Southern Oscillation Index (SOI) time-series. fname = iris.sample_data_path('SOI_Darwin.nc') soi = iris.load_cube(fname) @@ -62,7 +61,7 @@ def main(): # Construct 2-year (24-month) and 7-year (84-month) low pass filters # for the SOI data which is monthly. - wgts24 = low_pass_weights(window, 1. / 24.) + wgts24 = low_pass_weights(window, 1. / 24.) wgts84 = low_pass_weights(window, 1. / 84.) # Apply each filter using the rolling_window method used with the weights @@ -72,10 +71,10 @@ def main(): iris.analysis.SUM, len(wgts24), weights=wgts24) - soi84 = soi.rolling_window('time', - iris.analysis.SUM, - len(wgts84), - weights=wgts84) + soi84 = soi.rolling_window('time', + iris.analysis.SUM, + len(wgts84), + weights=wgts84) # Plot the SOI time series and both filtered versions. plt.figure(figsize=(9, 4)) @@ -90,7 +89,7 @@ def main(): plt.xlabel('Time') plt.ylabel('SOI') plt.legend(fontsize=10) - plt.show() + iplt.show() if __name__ == '__main__': diff --git a/docs/iris/example_code/General/__init__.py b/docs/iris/example_code/General/__init__.py new file mode 100644 index 0000000000..f67741cf37 --- /dev/null +++ b/docs/iris/example_code/General/__init__.py @@ -0,0 +1,4 @@ +""" +General visualisation examples +============================== +""" diff --git a/docs/iris/example_code/General/anomaly_log_colouring.py b/docs/iris/example_code/General/anomaly_log_colouring.py new file mode 100644 index 0000000000..d3f71b6ddc --- /dev/null +++ b/docs/iris/example_code/General/anomaly_log_colouring.py @@ -0,0 +1,107 @@ +""" +Colouring anomaly data with logarithmic scaling +=============================================== + +In this example, we need to plot anomaly data where the values have a +"logarithmic" significance -- i.e. we want to give approximately equal ranges +of colour between data values of, say, 1 and 10 as between 10 and 100. + +As the data range also contains zero, that obviously does not suit a simple +logarithmic interpretation. However, values of less than a certain absolute +magnitude may be considered "not significant", so we put these into a separate +"zero band" which is plotted in white. + +To do this, we create a custom value mapping function (normalization) using +the matplotlib Norm class `matplotlib.colours.SymLogNorm +`_. +We use this to make a cell-filled pseudocolour plot with a colorbar. + +NOTE: By "pseudocolour", we mean that each data point is drawn as a "cell" +region on the plot, coloured according to its data value. +This is provided in Iris by the functions :meth:`iris.plot.pcolor` and +:meth:`iris.plot.pcolormesh`, which call the underlying matplotlib +functions of the same names (i.e. `matplotlib.pyplot.pcolor +`_ +and `matplotlib.pyplot.pcolormesh +`_). +See also: http://en.wikipedia.org/wiki/False_color#Pseudocolor. + +""" +import cartopy.crs as ccrs +import iris +import iris.coord_categorisation +import iris.plot as iplt +import matplotlib.pyplot as plt +import matplotlib.colors as mcols + + +def main(): + # Load a sample air temperatures sequence. + file_path = iris.sample_data_path('E1_north_america.nc') + temperatures = iris.load_cube(file_path) + + # Create a year-number coordinate from the time information. + iris.coord_categorisation.add_year(temperatures, 'time') + + # Create a sample anomaly field for one chosen year, by extracting that + # year and subtracting the time mean. + sample_year = 1982 + year_temperature = temperatures.extract(iris.Constraint(year=sample_year)) + time_mean = temperatures.collapsed('time', iris.analysis.MEAN) + anomaly = year_temperature - time_mean + + # Construct a plot title string explaining which years are involved. + years = temperatures.coord('year').points + plot_title = 'Temperature anomaly' + plot_title += '\n{} differences from {}-{} average.'.format( + sample_year, years[0], years[-1]) + + # Define scaling levels for the logarithmic colouring. + minimum_log_level = 0.1 + maximum_scale_level = 3.0 + + # Use a standard colour map which varies blue-white-red. + # For suitable options, see the 'Diverging colormaps' section in: + # http://matplotlib.org/examples/color/colormaps_reference.html + anom_cmap = 'bwr' + + # Create a 'logarithmic' data normalization. + anom_norm = mcols.SymLogNorm(linthresh=minimum_log_level, + linscale=0, + vmin=-maximum_scale_level, + vmax=maximum_scale_level) + # Setting "linthresh=minimum_log_level" makes its non-logarithmic + # data range equal to our 'zero band'. + # Setting "linscale=0" maps the whole zero band to the middle colour value + # (i.e. 0.5), which is the neutral point of a "diverging" style colormap. + + # Create an Axes, specifying the map projection. + plt.axes(projection=ccrs.LambertConformal()) + + # Make a pseudocolour plot using this colour scheme. + mesh = iplt.pcolormesh(anomaly, cmap=anom_cmap, norm=anom_norm) + + # Add a colourbar, with extensions to show handling of out-of-range values. + bar = plt.colorbar(mesh, orientation='horizontal', extend='both') + + # Set some suitable fixed "logarithmic" colourbar tick positions. + tick_levels = [-3, -1, -0.3, 0.0, 0.3, 1, 3] + bar.set_ticks(tick_levels) + + # Modify the tick labels so that the centre one shows "+/-". + tick_levels[3] = r'$\pm${:g}'.format(minimum_log_level) + bar.set_ticklabels(tick_levels) + + # Label the colourbar to show the units. + bar.set_label('[{}, log scale]'.format(anomaly.units)) + + # Add coastlines and a title. + plt.gca().coastlines() + plt.title(plot_title) + + # Display the result. + iplt.show() + + +if __name__ == '__main__': + main() diff --git a/docs/iris/example_code/General/coriolis_plot.py b/docs/iris/example_code/General/coriolis_plot.py new file mode 100644 index 0000000000..273faf6470 --- /dev/null +++ b/docs/iris/example_code/General/coriolis_plot.py @@ -0,0 +1,79 @@ +""" +Deriving the Coriolis frequency over the globe +============================================== + +This code computes the Coriolis frequency and stores it in a cube with +associated metadata. It then plots the Coriolis frequency on an orthographic +projection. + +""" + +import cartopy.crs as ccrs +import iris +from iris.coord_systems import GeogCS +import iris.plot as iplt +import matplotlib.pyplot as plt +import numpy as np + + +def main(): + # Start with arrays for latitudes and longitudes, with a given number of + # coordinates in the arrays. + coordinate_points = 200 + longitudes = np.linspace(-180.0, 180.0, coordinate_points) + latitudes = np.linspace(-90.0, 90.0, coordinate_points) + lon2d, lat2d = np.meshgrid(longitudes, latitudes) + + # Omega is the Earth's rotation rate, expressed in radians per second + omega = 7.29e-5 + + # The data for our cube is the Coriolis frequency, + # `f = 2 * omega * sin(phi)`, which is computed for each grid point over + # the globe from the 2-dimensional latitude array. + data = 2. * omega * np.sin(np.deg2rad(lat2d)) + + # We now need to define a coordinate system for the plot. + # Here we'll use GeogCS; 6371229 is the radius of the Earth in metres. + cs = GeogCS(6371229) + + # The Iris coords module turns the latitude list into a coordinate array. + # Coords then applies an appropriate standard name and unit to it. + lat_coord = iris.coords.DimCoord(latitudes, + standard_name='latitude', + units='degrees', + coord_system=cs) + + # The above process is repeated for the longitude coordinates. + lon_coord = iris.coords.DimCoord(longitudes, + standard_name='longitude', + units='degrees', + coord_system=cs) + + # Now we add bounds to our latitude and longitude coordinates. + # We want simple, contiguous bounds for our regularly-spaced coordinate + # points so we use the guess_bounds() method of the coordinate. For more + # complex coordinates, we could derive and set the bounds manually. + lat_coord.guess_bounds() + lon_coord.guess_bounds() + + # Now we input our data array into the cube. + new_cube = iris.cube.Cube(data, + standard_name='coriolis_parameter', + units='s-1', + dim_coords_and_dims=[(lat_coord, 0), + (lon_coord, 1)]) + + # Now let's plot our cube, along with coastlines, a title and an + # appropriately-labelled colour bar: + ax = plt.axes(projection=ccrs.Orthographic()) + ax.coastlines(resolution='10m') + mesh = iplt.pcolormesh(new_cube, cmap='seismic') + tick_levels = [-0.00012, -0.00006, 0.0, 0.00006, 0.00012] + plt.colorbar(mesh, orientation='horizontal', label='s-1', + ticks=tick_levels, format='%.1e') + plt.title('Coriolis frequency') + plt.show() + + +if __name__ == '__main__': + main() diff --git a/docs/iris/example_code/General/cross_section.py b/docs/iris/example_code/General/cross_section.py new file mode 100644 index 0000000000..e0d05fb230 --- /dev/null +++ b/docs/iris/example_code/General/cross_section.py @@ -0,0 +1,42 @@ +""" +Cross section plots +=================== + +This example demonstrates contour plots of a cross-sectioned multi-dimensional +cube which features a hybrid height vertical coordinate system. + +""" + +import matplotlib.pyplot as plt + +import iris +import iris.plot as iplt +import iris.quickplot as qplt + + +def main(): + # Load some test data. + fname = iris.sample_data_path('hybrid_height.nc') + theta = iris.load_cube(fname, 'air_potential_temperature') + + # Extract a single height vs longitude cross-section. N.B. This could + # easily be changed to extract a specific slice, or even to loop over *all* + # cross section slices. + cross_section = next(theta.slices(['grid_longitude', + 'model_level_number'])) + + qplt.contourf(cross_section, coords=['grid_longitude', 'altitude'], + cmap='RdBu_r') + iplt.show() + + # Now do the equivalent plot, only against model level + plt.figure() + + qplt.contourf(cross_section, + coords=['grid_longitude', 'model_level_number'], + cmap='RdBu_r') + iplt.show() + + +if __name__ == '__main__': + main() diff --git a/docs/iris/example_code/General/custom_aggregation.py b/docs/iris/example_code/General/custom_aggregation.py new file mode 100644 index 0000000000..d8df506469 --- /dev/null +++ b/docs/iris/example_code/General/custom_aggregation.py @@ -0,0 +1,94 @@ +""" +Calculating a custom statistic +============================== + +This example shows how to define and use a custom +:class:`iris.analysis.Aggregator`, that provides a new statistical operator for +use with cube aggregation functions such as :meth:`~iris.cube.Cube.collapsed`, +:meth:`~iris.cube.Cube.aggregated_by` or +:meth:`~iris.cube.Cube.rolling_window`. + +In this case, we have a 240-year sequence of yearly average surface temperature +over North America, and we want to calculate in how many years these exceed a +certain temperature over a spell of 5 years or more. + +""" +import matplotlib.pyplot as plt +import numpy as np + +import iris +from iris.analysis import Aggregator +import iris.plot as iplt +import iris.quickplot as qplt +from iris.util import rolling_window + + +# Define a function to perform the custom statistical operation. +# Note: in order to meet the requirements of iris.analysis.Aggregator, it must +# do the calculation over an arbitrary (given) data axis. +def count_spells(data, threshold, axis, spell_length): + """ + Function to calculate the number of points in a sequence where the value + has exceeded a threshold value for at least a certain number of timepoints. + + Generalised to operate on multiple time sequences arranged on a specific + axis of a multidimensional array. + + Args: + + * data (array): + raw data to be compared with value threshold. + + * threshold (float): + threshold point for 'significant' datapoints. + + * axis (int): + number of the array dimension mapping the time sequences. + (Can also be negative, e.g. '-1' means last dimension) + + * spell_length (int): + number of consecutive times at which value > threshold to "count". + + """ + if axis < 0: + # just cope with negative axis numbers + axis += data.ndim + # Threshold the data to find the 'significant' points. + data_hits = data > threshold + # Make an array with data values "windowed" along the time axis. + hit_windows = rolling_window(data_hits, window=spell_length, axis=axis) + # Find the windows "full of True-s" (along the added 'window axis'). + full_windows = np.all(hit_windows, axis=axis+1) + # Count points fulfilling the condition (along the time axis). + spell_point_counts = np.sum(full_windows, axis=axis, dtype=int) + return spell_point_counts + + +def main(): + # Load the whole time-sequence as a single cube. + file_path = iris.sample_data_path('E1_north_america.nc') + cube = iris.load_cube(file_path) + + # Make an aggregator from the user function. + SPELL_COUNT = Aggregator('spell_count', + count_spells, + units_func=lambda units: 1) + + # Define the parameters of the test. + threshold_temperature = 280.0 + spell_years = 5 + + # Calculate the statistic. + warm_periods = cube.collapsed('time', SPELL_COUNT, + threshold=threshold_temperature, + spell_length=spell_years) + warm_periods.rename('Number of 5-year warm spells in 240 years') + + # Plot the results. + qplt.contourf(warm_periods, cmap='RdYlBu_r') + plt.gca().coastlines() + iplt.show() + + +if __name__ == '__main__': + main() diff --git a/docs/iris/example_code/General/custom_file_loading.py b/docs/iris/example_code/General/custom_file_loading.py new file mode 100644 index 0000000000..d6fddf8464 --- /dev/null +++ b/docs/iris/example_code/General/custom_file_loading.py @@ -0,0 +1,317 @@ +""" +Loading a cube from a custom file format +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This example shows how a custom text file can be loaded using the standard Iris +load mechanism. + +The first stage in the process is to define an Iris :class:`FormatSpecification +` for the file format. To create a +format specification we need to define the following: + +* format_name - Some text that describes the format specification we are + creating +* file_element - FileElement object describing the element which identifies + this FormatSpecification. + + Possible values are: + + ``iris.io.format_picker.MagicNumber(n, o)`` + The n bytes from the file at offset o. + + ``iris.io.format_picker.FileExtension()`` + The file's extension. + + ``iris.io.format_picker.LeadingLine()`` + The first line of the file. + +* file_element_value - The value that the file_element should take if a file + matches this FormatSpecification +* handler (optional) - A generator function that will be called when the file + specification has been identified. This function is provided by the user and + provides the means to parse the whole file. If no handler function is + provided, then identification is still possible without any handling. + + The handler function must define the following arguments: + + * list of filenames to process + * callback function - An optional function to filter/alter the Iris cubes + returned + + The handler function must be defined as generator which yields each cube as + they are produced. + +* priority (optional) - Integer giving a priority for considering this + specification where higher priority means sooner consideration + +In the following example, the function :func:`load_NAME_III` has been defined +to handle the loading of the raw data from the custom file format. This +function is called from :func:`NAME_to_cube` which uses this data to create and +yield Iris cubes. + +In the ``main()`` function the filenames are loaded via the ``iris.load_cube`` +function which automatically invokes the ``FormatSpecification`` we defined. +The cube returned from the load function is then used to produce a plot. + +""" +import datetime + +import matplotlib.pyplot as plt +import numpy as np + +from cf_units import Unit, CALENDAR_GREGORIAN + +import iris +import iris.coords as icoords +import iris.coord_systems as icoord_systems +import iris.fileformats +import iris.io.format_picker as format_picker +import iris.plot as iplt + + +UTC_format = '%H%M%Z %d/%m/%Y' + +FLOAT_HEADERS = ['X grid origin', 'Y grid origin', + 'X grid resolution', 'Y grid resolution'] +INT_HEADERS = ['X grid size', 'Y grid size', 'Number of fields'] +DATE_HEADERS = ['Run time', 'Start of release', 'End of release'] +COLUMN_NAMES = ['species_category', 'species', 'cell_measure', 'quantity', + 'unit', 'z_level', 'time'] + + +def load_NAME_III(filename): + """ + Loads the Met Office's NAME III grid output files returning headers, column + definitions and data arrays as 3 separate lists. + + """ + + # Loading a file gives a generator of lines which can be progressed using + # the next() function. This will come in handy as we wish to progress + # through the file line by line. + with open(filename) as file_handle: + # Define a dictionary which can hold the header metadata for this file. + headers = {} + + # Skip the NAME header of the file which looks something like + # 'NAME III (version X.X.X)'. + next(file_handle) + + # Read the next 16 lines of header information, putting the form + # "header name: header value" into a dictionary. + for _ in range(16): + header_name, header_value = next(file_handle).split(':') + + # Strip off any spurious space characters in the header name and + # value. + header_name = header_name.strip() + header_value = header_value.strip() + + # Cast some headers into floats or integers if they match a given + # header name. + if header_name in FLOAT_HEADERS: + header_value = float(header_value) + elif header_name in INT_HEADERS: + header_value = int(header_value) + elif header_name in DATE_HEADERS: + # convert the time to python datetimes + header_value = datetime.datetime.strptime(header_value, + UTC_format) + + headers[header_name] = header_value + + # Skip the next blank line in the file. + next(file_handle) + + # Read the next 7 lines of column definitions. + column_headings = {} + for column_header_name in COLUMN_NAMES: + column_headings[column_header_name] = [ + col.strip() for col in next(file_handle).split(',') + ][:-1] + + # Convert the time to python datetimes. + new_time_column_header = [] + for i, t in enumerate(column_headings['time']): + # The first 4 columns aren't time at all, so don't convert them to + # datetimes. + if i >= 4: + t = datetime.datetime.strptime(t, UTC_format) + new_time_column_header.append(t) + column_headings['time'] = new_time_column_header + + # Skip the blank line after the column headers. + next(file_handle) + + # Make a list of data arrays to hold the data for each column. + data_shape = (headers['Y grid size'], headers['X grid size']) + data_arrays = [np.zeros(data_shape, dtype=np.float32) + for i in range(headers['Number of fields'])] + + # Iterate over the remaining lines which represent the data in a column + # form. + for line in file_handle: + # Split the line by comma, removing the last empty column caused by + # the trailing comma. + vals = line.split(',')[:-1] + + # Cast the x and y grid positions to floats and convert them to + # zero based indices (the numbers are 1 based grid positions where + # 0.5 represents half a grid point.) + x = int(float(vals[0]) - 1.5) + y = int(float(vals[1]) - 1.5) + + # Populate the data arrays (i.e. all columns but the leading 4). + for i, data_array in enumerate(data_arrays): + data_array[y, x] = float(vals[i + 4]) + + return headers, column_headings, data_arrays + + +def NAME_to_cube(filenames, callback): + """ + Returns a generator of cubes given a list of filenames and a callback. + """ + + for filename in filenames: + header, column_headings, data_arrays = load_NAME_III(filename) + + for i, data_array in enumerate(data_arrays): + # turn the dictionary of column headers with a list of header + # information for each field into a dictionary of headers for just + # this field. Ignore the first 4 columns of grid position (data was + # located with the data array). + field_headings = dict((k, v[i + 4]) + for k, v in column_headings.items()) + + # make an cube + cube = iris.cube.Cube(data_array) + + # define the name and unit + name = ('%s %s' % (field_headings['species'], + field_headings['quantity'])) + name = name.upper().replace(' ', '_') + cube.rename(name) + # Some units are badly encoded in the file, fix this by putting a + # space in between. (if gs is not found, then the string will be + # returned unchanged) + cube.units = field_headings['unit'].replace('gs', 'g s') + + # define and add the singular coordinates of the field (flight + # level, time etc.) + cube.add_aux_coord(icoords.AuxCoord(field_headings['z_level'], + long_name='flight_level', + units='1')) + + # define the time unit and use it to serialise the datetime for the + # time coordinate + time_unit = Unit('hours since epoch', calendar=CALENDAR_GREGORIAN) + time_coord = icoords.AuxCoord( + time_unit.date2num(field_headings['time']), + standard_name='time', + units=time_unit) + cube.add_aux_coord(time_coord) + + # build a coordinate system which can be referenced by latitude and + # longitude coordinates + lat_lon_coord_system = icoord_systems.GeogCS(6371229) + + # build regular latitude and longitude coordinates which have + # bounds + start = header['X grid origin'] + header['X grid resolution'] + step = header['X grid resolution'] + count = header['X grid size'] + pts = start + np.arange(count, dtype=np.float32) * step + lon_coord = icoords.DimCoord(pts, standard_name='longitude', + units='degrees', + coord_system=lat_lon_coord_system) + lon_coord.guess_bounds() + + start = header['Y grid origin'] + header['Y grid resolution'] + step = header['Y grid resolution'] + count = header['Y grid size'] + pts = start + np.arange(count, dtype=np.float32) * step + lat_coord = icoords.DimCoord(pts, standard_name='latitude', + units='degrees', + coord_system=lat_lon_coord_system) + lat_coord.guess_bounds() + + # add the latitude and longitude coordinates to the cube, with + # mappings to data dimensions + cube.add_dim_coord(lat_coord, 0) + cube.add_dim_coord(lon_coord, 1) + + # implement standard iris callback capability. Although callbacks + # are not used in this example, the standard mechanism for a custom + # loader to implement a callback is shown: + cube = iris.io.run_callback(callback, cube, + [header, field_headings, data_array], + filename) + + # yield the cube created (the loop will continue when the next() + # element is requested) + yield cube + + +# Create a format_picker specification of the NAME file format giving it a +# priority greater than the built in NAME loader. +_NAME_III_spec = format_picker.FormatSpecification( + 'Name III', + format_picker.LeadingLine(), + lambda line: line.startswith(b"NAME III"), + NAME_to_cube, + priority=6) + +# Register the NAME loader with iris +iris.fileformats.FORMAT_AGENT.add_spec(_NAME_III_spec) + + +# --------------------------------------------- +# | Using the new loader | +# --------------------------------------------- + +def main(): + fname = iris.sample_data_path('NAME_output.txt') + + boundary_volc_ash_constraint = iris.Constraint( + 'VOLCANIC_ASH_AIR_CONCENTRATION', + flight_level='From FL000 - FL200') + + # Callback shown as None to illustrate where a cube-level callback function + # would be used if required + cube = iris.load_cube(fname, boundary_volc_ash_constraint, callback=None) + + # draw contour levels for the data (the top level is just a catch-all) + levels = (0.0002, 0.002, 0.004, 1e10) + cs = iplt.contourf(cube, levels=levels, + colors=('#80ffff', '#939598', '#e00404'), + ) + + # draw a black outline at the lowest contour to highlight affected areas + iplt.contour(cube, levels=(levels[0], 100), + colors='black') + + # set an extent and a background image for the map + ax = plt.gca() + ax.set_extent((-90, 20, 20, 75)) + ax.stock_img('ne_shaded') + + # make a legend, with custom labels, for the coloured contour set + artists, _ = cs.legend_elements() + labels = [ + r'$%s < x \leq %s$' % (levels[0], levels[1]), + r'$%s < x \leq %s$' % (levels[1], levels[2]), + r'$x > %s$' % levels[2] + ] + ax.legend(artists, labels, title='Ash concentration / g m-3', + loc='upper left') + + time = cube.coord('time') + time_date = time.units.num2date(time.points[0]).strftime(UTC_format) + plt.title('Volcanic ash concentration forecast\nvalid at %s' % time_date) + + iplt.show() + + +if __name__ == '__main__': + main() diff --git a/docs/iris/example_code/General/global_map.py b/docs/iris/example_code/General/global_map.py new file mode 100644 index 0000000000..4ed8b97443 --- /dev/null +++ b/docs/iris/example_code/General/global_map.py @@ -0,0 +1,35 @@ +""" +Quickplot of a 2d cube on a map +=============================== + +This example demonstrates a contour plot of global air temperature. The plot +title and the labels for the axes are automatically derived from the metadata. + +""" +import cartopy.crs as ccrs +import matplotlib.pyplot as plt + +import iris +import iris.plot as iplt +import iris.quickplot as qplt + + +def main(): + fname = iris.sample_data_path('air_temp.pp') + temperature = iris.load_cube(fname) + + # Plot #1: contourf with axes longitude from -180 to 180 + plt.figure(figsize=(12, 5)) + plt.subplot(121) + qplt.contourf(temperature, 15) + plt.gca().coastlines() + + # Plot #2: contourf with axes longitude from 0 to 360 + proj = ccrs.PlateCarree(central_longitude=-180.0) + plt.subplot(122, projection=proj) + qplt.contourf(temperature, 15) + plt.gca().coastlines() + iplt.show() + +if __name__ == '__main__': + main() diff --git a/docs/iris/example_code/General/inset_plot.py b/docs/iris/example_code/General/inset_plot.py new file mode 100644 index 0000000000..f2ae2d1155 --- /dev/null +++ b/docs/iris/example_code/General/inset_plot.py @@ -0,0 +1,66 @@ +""" +Test Data Showing Inset Plots +============================= + +This example demonstrates the use of a single 3D data cube with time, latitude +and longitude dimensions to plot a temperature series for a single latitude +coordinate, with an inset plot of the data region. + +""" + +import matplotlib.pyplot as plt +import numpy as np +import iris +import cartopy.crs as ccrs +import iris.quickplot as qplt +import iris.plot as iplt + + +def main(): + cube1 = iris.load_cube(iris.sample_data_path('ostia_monthly.nc')) + # Slice into cube to retrieve data for the inset map showing the + # data region + region = cube1[-1, :, :] + # Average over latitude to reduce cube to 1 dimension + plot_line = region.collapsed('latitude', iris.analysis.MEAN) + + # Open a window for plotting + fig = plt.figure() + # Add a single subplot (axes). Could also use "ax_main = plt.subplot()" + ax_main = fig.add_subplot(1, 1, 1) + # Produce a quick plot of the 1D cube + qplt.plot(plot_line) + + # Set x limits to match the data + ax_main.set_xlim(0, plot_line.coord('longitude').points.max()) + # Adjust the y limits so that the inset map won't clash with main plot + ax_main.set_ylim(294, 310) + ax_main.set_title('Meridional Mean Temperature') + # Add grid lines + ax_main.grid() + + # Add a second set of axes specifying the fractional coordinates within + # the figure with bottom left corner at x=0.55, y=0.58 with width + # 0.3 and height 0.25. + # Also specify the projection + ax_sub = fig.add_axes([0.55, 0.58, 0.3, 0.25], + projection=ccrs.Mollweide(central_longitude=180)) + + # Use iris.plot (iplt) here so colour bar properties can be specified + # Also use a sequential colour scheme to reduce confusion for those with + # colour-blindness + iplt.pcolormesh(region, cmap='Blues') + # Manually set the orientation and tick marks on your colour bar + ticklist = np.linspace(np.min(region.data), np.max(region.data), 4) + plt.colorbar(orientation='horizontal', ticks=ticklist) + ax_sub.set_title('Data Region') + # Add coastlines + ax_sub.coastlines() + # request to show entire map, using the colour mesh on the data region only + ax_sub.set_global() + + qplt.show() + + +if __name__ == '__main__': + main() diff --git a/docs/iris/example_code/graphics/lineplot_with_legend.py b/docs/iris/example_code/General/lineplot_with_legend.py similarity index 96% rename from docs/iris/example_code/graphics/lineplot_with_legend.py rename to docs/iris/example_code/General/lineplot_with_legend.py index 4409674e0b..4ce80a9569 100644 --- a/docs/iris/example_code/graphics/lineplot_with_legend.py +++ b/docs/iris/example_code/General/lineplot_with_legend.py @@ -6,6 +6,7 @@ import matplotlib.pyplot as plt import iris +import iris.plot as iplt import iris.quickplot as qplt @@ -39,7 +40,7 @@ def main(): plt.axis('tight') # Finally, show it. - plt.show() + iplt.show() if __name__ == '__main__': diff --git a/docs/iris/example_code/General/orca_projection.py b/docs/iris/example_code/General/orca_projection.py new file mode 100644 index 0000000000..fb44221221 --- /dev/null +++ b/docs/iris/example_code/General/orca_projection.py @@ -0,0 +1,58 @@ +""" +Tri-Polar Grid Projected Plotting +================================= + +This example demonstrates cell plots of data on the semi-structured ORCA2 model +grid. + +First, the data is projected into the PlateCarree coordinate reference system. + +Second four pcolormesh plots are created from this projected dataset, +using different projections for the output image. + +""" + +import matplotlib.pyplot as plt + +import cartopy.crs as ccrs +import iris +import iris.analysis.cartography +import iris.plot as iplt +import iris.quickplot as qplt + + +def main(): + # Load data + filepath = iris.sample_data_path('orca2_votemper.nc') + cube = iris.load_cube(filepath) + + # Choose plot projections + projections = {} + projections['Mollweide'] = ccrs.Mollweide() + projections['PlateCarree'] = ccrs.PlateCarree() + projections['NorthPolarStereo'] = ccrs.NorthPolarStereo() + projections['Orthographic'] = ccrs.Orthographic(central_longitude=-90, + central_latitude=45) + + pcarree = projections['PlateCarree'] + # Transform cube to target projection + new_cube, extent = iris.analysis.cartography.project(cube, pcarree, + nx=400, ny=200) + + # Plot data in each projection + for name in sorted(projections): + fig = plt.figure() + fig.suptitle('ORCA2 Data Projected to {}'.format(name)) + # Set up axes and title + ax = plt.subplot(projection=projections[name]) + # Set limits + ax.set_global() + # plot with Iris quickplot pcolormesh + qplt.pcolormesh(new_cube) + # Draw coastlines + ax.coastlines() + + iplt.show() + +if __name__ == '__main__': + main() diff --git a/docs/iris/example_code/graphics/polar_stereo.py b/docs/iris/example_code/General/polar_stereo.py similarity index 92% rename from docs/iris/example_code/graphics/polar_stereo.py rename to docs/iris/example_code/General/polar_stereo.py index b8a963d8b4..f1cefdc903 100644 --- a/docs/iris/example_code/graphics/polar_stereo.py +++ b/docs/iris/example_code/General/polar_stereo.py @@ -10,6 +10,7 @@ import matplotlib.pyplot as plt import iris +import iris.plot as iplt import iris.quickplot as qplt @@ -20,7 +21,7 @@ def main(): ax = plt.gca() ax.coastlines() ax.gridlines() - plt.show() + iplt.show() if __name__ == '__main__': diff --git a/docs/iris/example_code/General/polynomial_fit.py b/docs/iris/example_code/General/polynomial_fit.py new file mode 100644 index 0000000000..84f3265dd1 --- /dev/null +++ b/docs/iris/example_code/General/polynomial_fit.py @@ -0,0 +1,52 @@ +""" +Fitting a polynomial +==================== + +This example demonstrates computing a polynomial fit to 1D data from an Iris +cube, adding the fit to the cube's metadata, and plotting both the 1D data and +the fit. + +""" + +import matplotlib.pyplot as plt +import numpy as np + +import iris +import iris.quickplot as qplt + + +def main(): + # Load some test data. + fname = iris.sample_data_path('A1B_north_america.nc') + cube = iris.load_cube(fname) + + # Extract a single time series at a latitude and longitude point. + location = next(cube.slices(['time'])) + + # Calculate a polynomial fit to the data at this time series. + x_points = location.coord('time').points + y_points = location.data + degree = 2 + + p = np.polyfit(x_points, y_points, degree) + y_fitted = np.polyval(p, x_points) + + # Add the polynomial fit values to the time series to take + # full advantage of Iris plotting functionality. + long_name = 'degree_{}_polynomial_fit_of_{}'.format(degree, cube.name()) + fit = iris.coords.AuxCoord(y_fitted, long_name=long_name, + units=location.units) + location.add_aux_coord(fit, 0) + + qplt.plot(location.coord('time'), location, label='data') + qplt.plot(location.coord('time'), + location.coord(long_name), + 'g-', label='polynomial fit') + plt.legend(loc='best') + plt.title('Trend of US air temperature over time') + + qplt.show() + + +if __name__ == '__main__': + main() diff --git a/docs/iris/example_code/General/projections_and_annotations.py b/docs/iris/example_code/General/projections_and_annotations.py new file mode 100644 index 0000000000..b4cb8b1eb7 --- /dev/null +++ b/docs/iris/example_code/General/projections_and_annotations.py @@ -0,0 +1,115 @@ +""" +Plotting in different projections +================================= + +This example shows how to overlay data and graphics in different projections, +demonstrating various features of Iris, Cartopy and matplotlib. + +We wish to overlay two datasets, defined on different rotated-pole grids. +To display both together, we make a pseudocoloured plot of the first, overlaid +with contour lines from the second. +We also add some lines and text annotations drawn in various projections. + +We plot these over a specified region, in two different map projections. + +""" +import cartopy.crs as ccrs +import iris +import iris.plot as iplt +import numpy as np +import matplotlib.pyplot as plt + + +# Define a Cartopy 'ordinary' lat-lon coordinate reference system. +crs_latlon = ccrs.PlateCarree() + + +def make_plot(projection_name, projection_crs): + + # Create a matplotlib Figure. + plt.figure() + + # Add a matplotlib Axes, specifying the required display projection. + # NOTE: specifying 'projection' (a "cartopy.crs.Projection") makes the + # resulting Axes a "cartopy.mpl.geoaxes.GeoAxes", which supports plotting + # in different coordinate systems. + ax = plt.axes(projection=projection_crs) + + # Set display limits to include a set region of latitude * longitude. + # (Note: Cartopy-specific). + ax.set_extent((-80.0, 20.0, 10.0, 80.0), crs=crs_latlon) + + # Add coastlines and meridians/parallels (Cartopy-specific). + ax.coastlines(linewidth=0.75, color='navy') + ax.gridlines(crs=crs_latlon, linestyle='-') + + # Plot the first dataset as a pseudocolour filled plot. + maindata_filepath = iris.sample_data_path('rotated_pole.nc') + main_data = iris.load_cube(maindata_filepath) + # NOTE: iplt.pcolormesh calls "pyplot.pcolormesh", passing in a coordinate + # system with the 'transform' keyword: This enables the Axes (a cartopy + # GeoAxes) to reproject the plot into the display projection. + iplt.pcolormesh(main_data, cmap='RdBu_r') + + # Overplot the other dataset (which has a different grid), as contours. + overlay_filepath = iris.sample_data_path('space_weather.nc') + overlay_data = iris.load_cube(overlay_filepath, 'total electron content') + # NOTE: as above, "iris.plot.contour" calls "pyplot.contour" with a + # 'transform' keyword, enabling Cartopy reprojection. + iplt.contour(overlay_data, 20, + linewidths=2.0, colors='darkgreen', linestyles='-') + + # Draw a margin line, some way in from the border of the 'main' data... + # First calculate rectangle corners, 7% in from each corner of the data. + x_coord, y_coord = main_data.coord(axis='x'), main_data.coord(axis='y') + x_start, x_end = np.min(x_coord.points), np.max(x_coord.points) + y_start, y_end = np.min(y_coord.points), np.max(y_coord.points) + margin = 0.07 + margin_fractions = np.array([margin, 1.0 - margin]) + x_lower, x_upper = x_start + (x_end - x_start) * margin_fractions + y_lower, y_upper = y_start + (y_end - y_start) * margin_fractions + box_x_points = x_lower + (x_upper - x_lower) * np.array([0, 1, 1, 0, 0]) + box_y_points = y_lower + (y_upper - y_lower) * np.array([0, 0, 1, 1, 0]) + # Get the Iris coordinate sytem of the X coordinate (Y should be the same). + cs_data1 = x_coord.coord_system + # Construct an equivalent Cartopy coordinate reference system ("crs"). + crs_data1 = cs_data1.as_cartopy_crs() + # Draw the rectangle in this crs, with matplotlib "pyplot.plot". + # NOTE: the 'transform' keyword specifies a non-display coordinate system + # for the plot points (as used by the "iris.plot" functions). + plt.plot(box_x_points, box_y_points, transform=crs_data1, + linewidth=2.0, color='white', linestyle='--') + + # Mark some particular places with a small circle and a name label... + # Define some test points with latitude and longitude coordinates. + city_data = [('London', 51.5072, 0.1275), + ('Halifax, NS', 44.67, -63.61), + ('Reykjavik', 64.1333, -21.9333)] + # Place a single marker point and a text annotation at each place. + for name, lat, lon in city_data: + plt.plot(lon, lat, marker='o', markersize=7.0, markeredgewidth=2.5, + markerfacecolor='black', markeredgecolor='white', + transform=crs_latlon) + # NOTE: the "plt.annotate call" does not have a "transform=" keyword, + # so for this one we transform the coordinates with a Cartopy call. + at_x, at_y = ax.projection.transform_point(lon, lat, + src_crs=crs_latlon) + plt.annotate( + name, xy=(at_x, at_y), xytext=(30, 20), textcoords='offset points', + color='black', backgroundcolor='white', size='large', + arrowprops=dict(arrowstyle='->', color='white', linewidth=2.5)) + + # Add a title, and display. + plt.title('A pseudocolour plot on the {} projection,\n' + 'with overlaid contours.'.format(projection_name)) + iplt.show() + + +def main(): + # Demonstrate with two different display projections. + make_plot('Equidistant Cylindrical', ccrs.PlateCarree()) + make_plot('North Polar Stereographic', ccrs.NorthPolarStereo()) + + +if __name__ == '__main__': + main() diff --git a/docs/iris/example_code/graphics/rotated_pole_mapping.py b/docs/iris/example_code/General/rotated_pole_mapping.py similarity index 94% rename from docs/iris/example_code/graphics/rotated_pole_mapping.py rename to docs/iris/example_code/General/rotated_pole_mapping.py index d458ab3043..e175e6fe74 100644 --- a/docs/iris/example_code/graphics/rotated_pole_mapping.py +++ b/docs/iris/example_code/General/rotated_pole_mapping.py @@ -21,6 +21,7 @@ def main(): + # Load some test data. fname = iris.sample_data_path('rotated_pole.nc') air_pressure = iris.load_cube(fname) @@ -30,20 +31,20 @@ def main(): cb = plt.colorbar(points, orientation='horizontal') cb.set_label(air_pressure.units) plt.gca().coastlines() - plt.show() + iplt.show() # Plot #2: Contourf of the point based data plt.figure() qplt.contourf(air_pressure, 15) plt.gca().coastlines() - plt.show() + iplt.show() # Plot #3: Contourf overlayed by coloured point data plt.figure() qplt.contourf(air_pressure) iplt.points(air_pressure, c=air_pressure.data) plt.gca().coastlines() - plt.show() + iplt.show() # For the purposes of this example, add some bounds to the latitude # and longitude @@ -56,7 +57,7 @@ def main(): iplt.pcolormesh(air_pressure) plt.gca().stock_img() plt.gca().coastlines() - plt.show() + iplt.show() if __name__ == '__main__': diff --git a/docs/iris/example_code/Meteorology/COP_1d_plot.py b/docs/iris/example_code/Meteorology/COP_1d_plot.py new file mode 100644 index 0000000000..53bff28b7e --- /dev/null +++ b/docs/iris/example_code/Meteorology/COP_1d_plot.py @@ -0,0 +1,108 @@ +""" +Global average annual temperature plot +====================================== + +Produces a time-series plot of North American temperature forecasts for 2 +different emission scenarios. Constraining data to a limited spatial area also +features in this example. + +The data used comes from the HadGEM2-AO model simulations for the A1B and E1 +scenarios, both of which were derived using the IMAGE Integrated Assessment +Model (Johns et al. 2011; Lowe et al. 2009). + +References +---------- + + Johns T.C., et al. (2011) Climate change under aggressive mitigation: the + ENSEMBLES multi-model experiment. Climate Dynamics, Vol 37, No. 9-10, + doi:10.1007/s00382-011-1005-5. + + Lowe J.A., C.D. Hewitt, D.P. Van Vuuren, T.C. Johns, E. Stehfest, J-F. + Royer, and P. van der Linden, 2009. New Study For Climate Modeling, + Analyses, and Scenarios. Eos Trans. AGU, Vol 90, No. 21, + doi:10.1029/2009EO210001. + +.. seealso:: + + Further details on the aggregation functionality being used in this example + can be found in :ref:`cube-statistics`. + +""" +import numpy as np +import matplotlib.pyplot as plt +import iris +import iris.plot as iplt +import iris.quickplot as qplt + +import iris.analysis.cartography + + +def main(): + # Load data into three Cubes, one for each set of NetCDF files. + e1 = iris.load_cube(iris.sample_data_path('E1_north_america.nc')) + + a1b = iris.load_cube(iris.sample_data_path('A1B_north_america.nc')) + + # load in the global pre-industrial mean temperature, and limit the domain + # to the same North American region that e1 and a1b are at. + north_america = iris.Constraint(longitude=lambda v: 225 <= v <= 315, + latitude=lambda v: 15 <= v <= 60) + pre_industrial = iris.load_cube(iris.sample_data_path('pre-industrial.pp'), + north_america) + + # Generate area-weights array. As e1 and a1b are on the same grid we can + # do this just once and re-use. This method requires bounds on lat/lon + # coords, so let's add some in sensible locations using the "guess_bounds" + # method. + e1.coord('latitude').guess_bounds() + e1.coord('longitude').guess_bounds() + e1_grid_areas = iris.analysis.cartography.area_weights(e1) + pre_industrial.coord('latitude').guess_bounds() + pre_industrial.coord('longitude').guess_bounds() + pre_grid_areas = iris.analysis.cartography.area_weights(pre_industrial) + + # Perform the area-weighted mean for each of the datasets using the + # computed grid-box areas. + pre_industrial_mean = pre_industrial.collapsed(['latitude', 'longitude'], + iris.analysis.MEAN, + weights=pre_grid_areas) + e1_mean = e1.collapsed(['latitude', 'longitude'], + iris.analysis.MEAN, + weights=e1_grid_areas) + a1b_mean = a1b.collapsed(['latitude', 'longitude'], + iris.analysis.MEAN, + weights=e1_grid_areas) + + # Plot the datasets + qplt.plot(e1_mean, label='E1 scenario', lw=1.5, color='blue') + qplt.plot(a1b_mean, label='A1B-Image scenario', lw=1.5, color='red') + + # Draw a horizontal line showing the pre-industrial mean + plt.axhline(y=pre_industrial_mean.data, color='gray', linestyle='dashed', + label='pre-industrial', lw=1.5) + + # Constrain the period 1860-1999 and extract the observed data from a1b + constraint = iris.Constraint(time=lambda + cell: 1860 <= cell.point.year <= 1999) + observed = a1b_mean.extract(constraint) + # Assert that this data set is the same as the e1 scenario: + # they share data up to the 1999 cut off. + assert np.all(np.isclose(observed.data, + e1_mean.extract(constraint).data)) + + # Plot the observed data + qplt.plot(observed, label='observed', color='black', lw=1.5) + + # Add a legend and title + plt.legend(loc="upper left") + plt.title('North American mean air temperature', fontsize=18) + + plt.xlabel('Time / year') + + plt.grid() + + iplt.show() + + +if __name__ == '__main__': + main() diff --git a/docs/iris/example_code/Meteorology/COP_maps.py b/docs/iris/example_code/Meteorology/COP_maps.py new file mode 100644 index 0000000000..aa5049feb9 --- /dev/null +++ b/docs/iris/example_code/Meteorology/COP_maps.py @@ -0,0 +1,149 @@ +""" +Global average annual temperature maps +====================================== + +Produces maps of global temperature forecasts from the A1B and E1 scenarios. + +The data used comes from the HadGEM2-AO model simulations for the A1B and E1 +scenarios, both of which were derived using the IMAGE Integrated Assessment +Model (Johns et al. 2011; Lowe et al. 2009). + +References +---------- + + Johns T.C., et al. (2011) Climate change under aggressive mitigation: the + ENSEMBLES multi-model experiment. Climate Dynamics, Vol 37, No. 9-10, + doi:10.1007/s00382-011-1005-5. + + Lowe J.A., C.D. Hewitt, D.P. Van Vuuren, T.C. Johns, E. Stehfest, J-F. + Royer, and P. van der Linden, 2009. New Study For Climate Modeling, + Analyses, and Scenarios. Eos Trans. AGU, Vol 90, No. 21, + doi:10.1029/2009EO210001. + +""" +from six.moves import zip + +import os.path +import matplotlib.pyplot as plt +import numpy as np + +import iris +import iris.coords as coords +import iris.plot as iplt + + +def cop_metadata_callback(cube, field, filename): + """ + A function which adds an "Experiment" coordinate which comes from the + filename. + """ + + # Extract the experiment name (such as a1b or e1) from the filename (in + # this case it is just the parent folder's name) + containing_folder = os.path.dirname(filename) + experiment_label = os.path.basename(containing_folder) + + # Create a coordinate with the experiment label in it + exp_coord = coords.AuxCoord(experiment_label, long_name='Experiment', + units='no_unit') + + # and add it to the cube + cube.add_aux_coord(exp_coord) + + +def main(): + # Load e1 and a1 using the callback to update the metadata + e1 = iris.load_cube(iris.sample_data_path('E1.2098.pp'), + callback=cop_metadata_callback) + a1b = iris.load_cube(iris.sample_data_path('A1B.2098.pp'), + callback=cop_metadata_callback) + + # Load the global average data and add an 'Experiment' coord it + global_avg = iris.load_cube(iris.sample_data_path('pre-industrial.pp')) + + # Define evenly spaced contour levels: -2.5, -1.5, ... 15.5, 16.5 with the + # specific colours + levels = np.arange(20) - 2.5 + red = np.array([0, 0, 221, 239, 229, 217, 239, 234, 228, 222, 205, 196, + 161, 137, 116, 89, 77, 60, 51]) / 256. + green = np.array([16, 217, 242, 243, 235, 225, 190, 160, 128, 87, 72, 59, + 33, 21, 29, 30, 30, 29, 26]) / 256. + blue = np.array([255, 255, 243, 169, 99, 51, 63, 37, 39, 21, 27, 23, 22, + 26, 29, 28, 27, 25, 22]) / 256. + + # Put those colours into an array which can be passed to contourf as the + # specific colours for each level + colors = np.array([red, green, blue]).T + + # Subtract the global + + # Iterate over each latitude longitude slice for both e1 and a1b scenarios + # simultaneously + for e1_slice, a1b_slice in zip(e1.slices(['latitude', 'longitude']), + a1b.slices(['latitude', 'longitude'])): + + time_coord = a1b_slice.coord('time') + + # Calculate the difference from the mean + delta_e1 = e1_slice - global_avg + delta_a1b = a1b_slice - global_avg + + # Make a wider than normal figure to house two maps side-by-side + fig = plt.figure(figsize=(12, 5)) + + # Get the time datetime from the coordinate + time = time_coord.units.num2date(time_coord.points[0]) + # Set a title for the entire figure, giving the time in a nice format + # of "MonthName Year". Also, set the y value for the title so that it + # is not tight to the top of the plot. + fig.suptitle( + 'Annual Temperature Predictions for ' + time.strftime("%Y"), + y=0.9, + fontsize=18) + + # Add the first subplot showing the E1 scenario + plt.subplot(121) + plt.title('HadGEM2 E1 Scenario', fontsize=10) + iplt.contourf(delta_e1, levels, colors=colors, extend='both') + plt.gca().coastlines() + # get the current axes' subplot for use later on + plt1_ax = plt.gca() + + # Add the second subplot showing the A1B scenario + plt.subplot(122) + plt.title('HadGEM2 A1B-Image Scenario', fontsize=10) + contour_result = iplt.contourf(delta_a1b, levels, colors=colors, + extend='both') + plt.gca().coastlines() + # get the current axes' subplot for use later on + plt2_ax = plt.gca() + + # Now add a colourbar who's leftmost point is the same as the leftmost + # point of the left hand plot and rightmost point is the rightmost + # point of the right hand plot + + # Get the positions of the 2nd plot and the left position of the 1st + # plot + left, bottom, width, height = plt2_ax.get_position().bounds + first_plot_left = plt1_ax.get_position().bounds[0] + + # the width of the colorbar should now be simple + width = left - first_plot_left + width + + # Add axes to the figure, to place the colour bar + colorbar_axes = fig.add_axes([first_plot_left, bottom + 0.07, + width, 0.03]) + + # Add the colour bar + cbar = plt.colorbar(contour_result, colorbar_axes, + orientation='horizontal') + + # Label the colour bar and add ticks + cbar.set_label(e1_slice.units) + cbar.ax.tick_params(length=0) + + iplt.show() + + +if __name__ == '__main__': + main() diff --git a/docs/iris/example_code/graphics/TEC.py b/docs/iris/example_code/Meteorology/TEC.py similarity index 96% rename from docs/iris/example_code/graphics/TEC.py rename to docs/iris/example_code/Meteorology/TEC.py index 2c5ed15af7..43f69fcea0 100644 --- a/docs/iris/example_code/graphics/TEC.py +++ b/docs/iris/example_code/Meteorology/TEC.py @@ -15,6 +15,7 @@ import numpy.ma as ma import iris +import iris.plot as iplt import iris.quickplot as qplt @@ -33,7 +34,7 @@ def main(): plt.ylabel('latitude / degrees') plt.gca().stock_img() plt.gca().coastlines() - plt.show() + iplt.show() if __name__ == '__main__': diff --git a/docs/iris/example_code/Meteorology/__init__.py b/docs/iris/example_code/Meteorology/__init__.py new file mode 100644 index 0000000000..39c05d08c6 --- /dev/null +++ b/docs/iris/example_code/Meteorology/__init__.py @@ -0,0 +1,4 @@ +""" +Meteorology visualisation examples +================================== +""" diff --git a/docs/iris/example_code/graphics/deriving_phenomena.py b/docs/iris/example_code/Meteorology/deriving_phenomena.py similarity index 93% rename from docs/iris/example_code/graphics/deriving_phenomena.py rename to docs/iris/example_code/Meteorology/deriving_phenomena.py index f8fb86012a..d34a2c8b78 100644 --- a/docs/iris/example_code/graphics/deriving_phenomena.py +++ b/docs/iris/example_code/Meteorology/deriving_phenomena.py @@ -15,6 +15,7 @@ import iris import iris.coords as coords import iris.iterate +import iris.plot as iplt import iris.quickplot as qplt @@ -29,7 +30,7 @@ def limit_colorbar_ticks(contour_object): # Matplotlib v1.3.x it is simply the colorbar. try: colorbar = contour_object.colorbar[0] - except AttributeError: + except (AttributeError, TypeError): colorbar = contour_object.colorbar colorbar.locator = matplotlib.ticker.MaxNLocator(4) @@ -72,6 +73,10 @@ def main(): coords=['grid_latitude', 'grid_longitude']) + # For the purposes of this example, we only want to demonstrate the first + # plot. + lat_lon_slice_pairs = [next(lat_lon_slice_pairs)] + plt.figure(figsize=(8, 4)) for exner_slice, air_temp_slice in lat_lon_slice_pairs: plt.subplot(121) @@ -84,11 +89,7 @@ def main(): plt.subplot(122) cont = qplt.contourf(air_temp_slice) limit_colorbar_ticks(cont) - plt.show() - - # For the purposes of this example, break after the first loop - we - # only want to demonstrate the first plot. - break + iplt.show() if __name__ == '__main__': diff --git a/docs/iris/example_code/Meteorology/hovmoller.py b/docs/iris/example_code/Meteorology/hovmoller.py new file mode 100644 index 0000000000..5d8b0852ac --- /dev/null +++ b/docs/iris/example_code/Meteorology/hovmoller.py @@ -0,0 +1,49 @@ +""" +Hovmoller diagram of monthly surface temperature +================================================ + +This example demonstrates the creation of a Hovmoller diagram with fine control +over plot ticks and labels. The data comes from the Met Office OSTIA project +and has been pre-processed to calculate the monthly mean sea surface +temperature. + +""" +import matplotlib.pyplot as plt +import matplotlib.dates as mdates + +import iris +import iris.plot as iplt +import iris.quickplot as qplt + + +def main(): + # load a single cube of surface temperature between +/- 5 latitude + fname = iris.sample_data_path('ostia_monthly.nc') + cube = iris.load_cube(fname, + iris.Constraint('surface_temperature', + latitude=lambda v: -5 < v < 5)) + + # Take the mean over latitude + cube = cube.collapsed('latitude', iris.analysis.MEAN) + + # Now that we have our data in a nice way, lets create the plot + # contour with 20 levels + qplt.contourf(cube, 20) + + # Put a custom label on the y axis + plt.ylabel('Time / years') + + # Stop matplotlib providing clever axes range padding + plt.axis('tight') + + # As we are plotting annual variability, put years as the y ticks + plt.gca().yaxis.set_major_locator(mdates.YearLocator()) + + # And format the ticks to just show the year + plt.gca().yaxis.set_major_formatter(mdates.DateFormatter('%Y')) + + iplt.show() + + +if __name__ == '__main__': + main() diff --git a/docs/iris/example_code/Meteorology/lagged_ensemble.py b/docs/iris/example_code/Meteorology/lagged_ensemble.py new file mode 100644 index 0000000000..7898d26392 --- /dev/null +++ b/docs/iris/example_code/Meteorology/lagged_ensemble.py @@ -0,0 +1,157 @@ +""" +Seasonal ensemble model plots +============================= + +This example demonstrates the loading of a lagged ensemble dataset from the +GloSea4 model, which is then used to produce two types of plot: + + * The first shows the "postage stamp" style image with an array of 14 images, + one for each ensemble member with a shared colorbar. (The missing image in + this example represents ensemble member number 6 which was a failed run) + + * The second plot shows the data limited to a region of interest, in this case + a region defined for forecasting ENSO (El Nino-Southern Oscillation), which, + for the purposes of this example, has had the ensemble mean subtracted from + each ensemble member to give an anomaly surface temperature. In practice a + better approach would be to take the climatological mean, calibrated to the + model, from each ensemble member. + +""" +import matplotlib.pyplot as plt +import numpy as np + +import iris +import iris.plot as iplt + + +def realization_metadata(cube, field, fname): + """ + A function which modifies the cube's metadata to add a "realization" + (ensemble member) coordinate from the filename if one doesn't already exist + in the cube. + + """ + # add an ensemble member coordinate if one doesn't already exist + if not cube.coords('realization'): + # the ensemble member is encoded in the filename as *_???.pp where ??? + # is the ensemble member + realization_number = fname[-6:-3] + + import iris.coords + realization_coord = iris.coords.AuxCoord(np.int32(realization_number), + 'realization') + cube.add_aux_coord(realization_coord) + + +def main(): + # extract surface temperature cubes which have an ensemble member + # coordinate, adding appropriate lagged ensemble metadata + surface_temp = iris.load_cube( + iris.sample_data_path('GloSea4', 'ensemble_???.pp'), + iris.Constraint('surface_temperature', realization=lambda value: True), + callback=realization_metadata, + ) + + # ------------------------------------------------------------------------- + # Plot #1: Ensemble postage stamps + # ------------------------------------------------------------------------- + + # for the purposes of this example, take the last time element of the cube + last_timestep = surface_temp[:, -1, :, :] + + # Make 50 evenly spaced levels which span the dataset + contour_levels = np.linspace(np.min(last_timestep.data), + np.max(last_timestep.data), + 50) + + # Create a wider than normal figure to support our many plots + plt.figure(figsize=(12, 6), dpi=100) + + # Also manually adjust the spacings which are used when creating subplots + plt.gcf().subplots_adjust(hspace=0.05, wspace=0.05, top=0.95, bottom=0.05, + left=0.075, right=0.925) + + # iterate over all possible latitude longitude slices + for cube in last_timestep.slices(['latitude', 'longitude']): + + # get the ensemble member number from the ensemble coordinate + ens_member = cube.coord('realization').points[0] + + # plot the data in a 4x4 grid, with each plot's position in the grid + # being determined by ensemble member number the special case for the + # 13th ensemble member is to have the plot at the bottom right + if ens_member == 13: + plt.subplot(4, 4, 16) + else: + plt.subplot(4, 4, ens_member+1) + + cf = iplt.contourf(cube, contour_levels) + + # add coastlines + plt.gca().coastlines() + + # make an axes to put the shared colorbar in + colorbar_axes = plt.gcf().add_axes([0.35, 0.1, 0.3, 0.05]) + colorbar = plt.colorbar(cf, colorbar_axes, orientation='horizontal') + colorbar.set_label('%s' % last_timestep.units) + + # limit the colorbar to 8 tick marks + import matplotlib.ticker + colorbar.locator = matplotlib.ticker.MaxNLocator(8) + colorbar.update_ticks() + + # get the time for the entire plot + time_coord = last_timestep.coord('time') + time = time_coord.units.num2date(time_coord.bounds[0, 0]) + + # set a global title for the postage stamps with the date formated by + # "monthname year" + plt.suptitle('Surface temperature ensemble forecasts for %s' % ( + time.strftime('%B %Y'), )) + + iplt.show() + + # ------------------------------------------------------------------------- + # Plot #2: ENSO plumes + # ------------------------------------------------------------------------- + + # Nino 3.4 lies between: 170W and 120W, 5N and 5S, so define a constraint + # which matches this + nino_3_4_constraint = iris.Constraint( + longitude=lambda v: -170+360 <= v <= -120+360, + latitude=lambda v: -5 <= v <= 5) + + nino_cube = surface_temp.extract(nino_3_4_constraint) + + # Subsetting a circular longitude coordinate always results in a circular + # coordinate, so set the coordinate to be non-circular + nino_cube.coord('longitude').circular = False + + # Calculate the horizontal mean for the nino region + mean = nino_cube.collapsed(['latitude', 'longitude'], iris.analysis.MEAN) + + # Calculate the ensemble mean of the horizontal mean. To do this, remove + # the "forecast_period" and "forecast_reference_time" coordinates which + # span both "relalization" and "time". + mean.remove_coord("forecast_reference_time") + mean.remove_coord("forecast_period") + ensemble_mean = mean.collapsed('realization', iris.analysis.MEAN) + + # take the ensemble mean from each ensemble member + mean -= ensemble_mean.data + + plt.figure() + + for ensemble_member in mean.slices(['time']): + # draw each ensemble member as a dashed line in black + iplt.plot(ensemble_member, '--k') + + plt.title('Mean temperature anomaly for ENSO 3.4 region') + plt.xlabel('Time') + plt.ylabel('Temperature anomaly / K') + + iplt.show() + + +if __name__ == '__main__': + main() diff --git a/docs/iris/example_code/Meteorology/wind_speed.py b/docs/iris/example_code/Meteorology/wind_speed.py new file mode 100644 index 0000000000..231defb25b --- /dev/null +++ b/docs/iris/example_code/Meteorology/wind_speed.py @@ -0,0 +1,85 @@ +""" +Plotting wind direction using quiver +=========================================================== + +This example demonstrates using quiver to plot wind speed contours and wind +direction arrows from wind vector component input data. The vector components +are co-located in space in this case. + +For the second plot, the data used for the arrows is normalised to produce +arrows with a uniform size on the plot. + +""" + +import matplotlib.pyplot as plt +import numpy as np + +import iris +import iris.coord_categorisation +import iris.quickplot as qplt + +import cartopy +import cartopy.feature as cfeat +import cartopy.crs as ccrs + + +def main(): + # Load the u and v components of wind from a pp file + infile = iris.sample_data_path('wind_speed_lake_victoria.pp') + + uwind = iris.load_cube(infile, 'x_wind') + vwind = iris.load_cube(infile, 'y_wind') + + ulon = uwind.coord('longitude') + vlon = vwind.coord('longitude') + + # The longitude points go from 180 to 540, so subtract 360 from them + ulon.points = ulon.points - 360.0 + vlon.points = vlon.points - 360.0 + + # Create a cube containing the wind speed + windspeed = (uwind ** 2 + vwind ** 2) ** 0.5 + windspeed.rename('windspeed') + + x = ulon.points + y = uwind.coord('latitude').points + u = uwind.data + v = vwind.data + + # Set up axes to show the lake + lakes = cfeat.NaturalEarthFeature('physical', 'lakes', '50m', + facecolor='none') + + plt.figure() + ax = plt.axes(projection=ccrs.PlateCarree()) + ax.add_feature(lakes) + + # Get the coordinate reference system used by the data + transform = ulon.coord_system.as_cartopy_projection() + + # Plot the wind speed as a contour plot + qplt.contourf(windspeed, 20) + + # Add arrows to show the wind vectors + plt.quiver(x, y, u, v, pivot='middle', transform=transform) + + plt.title("Wind speed over Lake Victoria") + qplt.show() + + # Normalise the data for uniform arrow size + u_norm = u / np.sqrt(u ** 2.0 + v ** 2.0) + v_norm = v / np.sqrt(u ** 2.0 + v ** 2.0) + + plt.figure() + ax = plt.axes(projection=ccrs.PlateCarree()) + ax.add_feature(lakes) + + qplt.contourf(windspeed, 20) + + plt.quiver(x, y, u_norm, v_norm, pivot='middle', transform=transform) + + plt.title("Wind speed over Lake Victoria") + qplt.show() + +if __name__ == '__main__': + main() diff --git a/docs/iris/example_code/Oceanography/__init__.py b/docs/iris/example_code/Oceanography/__init__.py new file mode 100644 index 0000000000..afac828a05 --- /dev/null +++ b/docs/iris/example_code/Oceanography/__init__.py @@ -0,0 +1,4 @@ +""" +Oceanography visualisation examples +=================================== +""" diff --git a/docs/iris/example_code/graphics/atlantic_profiles.py b/docs/iris/example_code/Oceanography/atlantic_profiles.py similarity index 97% rename from docs/iris/example_code/graphics/atlantic_profiles.py rename to docs/iris/example_code/Oceanography/atlantic_profiles.py index e0ee6a78cf..b3d76ea632 100644 --- a/docs/iris/example_code/graphics/atlantic_profiles.py +++ b/docs/iris/example_code/Oceanography/atlantic_profiles.py @@ -22,7 +22,6 @@ def main(): - # Load the gridded temperature and salinity data. fname = iris.sample_data_path('atlantic_profiles.nc') cubes = iris.load(fname) @@ -43,7 +42,7 @@ def main(): # them in this order places the depth coordinate on the y-axis. # The first plot is in the default axes. We'll use the same color for the # curve and its axes/tick labels. - fig = plt.figure(figsize=(5, 6)) + plt.figure(figsize=(5, 6)) temperature_color = (.3, .4, .5) ax1 = plt.gca() iplt.plot(theta_1000m, theta_1000m.coord('depth'), linewidth=2, @@ -62,7 +61,7 @@ def main(): for ticklabel in ax2.get_xticklabels(): ticklabel.set_color(salinity_color) plt.tight_layout() - plt.show() + iplt.show() # Now plot a T-S diagram using scatter. We'll use all the profiles here, # and each point will be coloured according to its depth. @@ -76,7 +75,7 @@ def main(): cb = plt.colorbar(orientation='horizontal') cb.set_label('Depth / m') plt.tight_layout() - plt.show() + iplt.show() if __name__ == '__main__': diff --git a/docs/iris/example_code/graphics/COP_1d_plot.py b/docs/iris/example_code/graphics/COP_1d_plot.py deleted file mode 100644 index ba117f3542..0000000000 --- a/docs/iris/example_code/graphics/COP_1d_plot.py +++ /dev/null @@ -1,99 +0,0 @@ -""" -Global average annual temperature plot -====================================== - -Produces a time-series plot of North American temperature forecasts for 2 different emission scenarios. -Constraining data to a limited spatial area also features in this example. - -The data used comes from the HadGEM2-AO model simulations for the A1B and E1 scenarios, both of which -were derived using the IMAGE Integrated Assessment Model (Johns et al. 2010; Lowe et al. 2009). - -References ----------- - - Johns T.C., et al. (2010) Climate change under aggressive mitigation: The ENSEMBLES multi-model - experiment. Climate Dynamics (submitted) - - Lowe J.A., C.D. Hewitt, D.P. Van Vuuren, T.C. Johns, E. Stehfest, J-F. Royer, and P. van der Linden, 2009. - New Study For Climate Modeling, Analyses, and Scenarios. Eos Trans. AGU, Vol 90, No. 21. - -""" -import numpy as np -import matplotlib.pyplot as plt -import iris -import iris.plot as iplt -import iris.quickplot as qplt - -import iris.analysis.cartography -import matplotlib.dates as mdates - - -def main(): - # Load data into three Cubes, one for each set of PP files - e1 = iris.load_cube(iris.sample_data_path('E1_north_america.nc')) - - a1b = iris.load_cube(iris.sample_data_path('A1B_north_america.nc')) - - # load in the global pre-industrial mean temperature, and limit the domain to - # the same North American region that e1 and a1b are at. - north_america = iris.Constraint( - longitude=lambda v: 225 <= v <= 315, - latitude=lambda v: 15 <= v <= 60, - ) - pre_industrial = iris.load_cube(iris.sample_data_path('pre-industrial.pp'), - north_america) - - # Generate area-weights array. As e1 and a1b are on the same grid we can - # do this just once and re-use. - # This method requires bounds on lat/lon coords, so first we must guess - # these. - e1.coord('latitude').guess_bounds() - e1.coord('longitude').guess_bounds() - e1_grid_areas = iris.analysis.cartography.area_weights(e1) - pre_industrial.coord('latitude').guess_bounds() - pre_industrial.coord('longitude').guess_bounds() - pre_grid_areas = iris.analysis.cartography.area_weights(pre_industrial) - - # Now perform an area-weighted collape for each dataset: - pre_industrial_mean = pre_industrial.collapsed(['latitude', 'longitude'], - iris.analysis.MEAN, - weights=pre_grid_areas) - e1_mean = e1.collapsed(['latitude', 'longitude'], - iris.analysis.MEAN, - weights=e1_grid_areas) - a1b_mean = a1b.collapsed(['latitude', 'longitude'], - iris.analysis.MEAN, - weights=e1_grid_areas) - - # Show ticks 30 years apart - plt.gca().xaxis.set_major_locator(mdates.YearLocator(30)) - - # Label the ticks with year data - plt.gca().format_xdata = mdates.DateFormatter('%Y') - - # Plot the datasets - qplt.plot(e1_mean, label='E1 scenario', lw=1.5, color='blue') - qplt.plot(a1b_mean, label='A1B-Image scenario', lw=1.5, color='red') - - # Draw a horizontal line showing the pre industrial mean - plt.axhline(y=pre_industrial_mean.data, color='gray', linestyle='dashed', label='pre-industrial', lw=1.5) - - # Establish where r and t have the same data, i.e. the observations - common = np.where(a1b_mean.data == e1_mean.data)[0] - observed = a1b_mean[common] - - # Plot the observed data - qplt.plot(observed, label='observed', color='black', lw=1.5) - - # Add a legend and title - plt.legend(loc="upper left") - plt.title('North American mean air temperature', fontsize=18) - - plt.xlabel('Time / year') - - plt.grid() - - iplt.show() - -if __name__ == '__main__': - main() diff --git a/docs/iris/example_code/graphics/COP_maps.py b/docs/iris/example_code/graphics/COP_maps.py deleted file mode 100644 index 358683bf1a..0000000000 --- a/docs/iris/example_code/graphics/COP_maps.py +++ /dev/null @@ -1,126 +0,0 @@ -""" -Global average annual temperature maps -====================================== - -Produces maps of global temperature forecasts from the A1B and E1 scenarios. - -The data used comes from the HadGEM2-AO model simulations for the A1B and E1 scenarios, both of which were derived using the IMAGE -Integrated Assessment Model (Johns et al. 2010; Lowe et al. 2009). - -References ----------- - - Johns T.C., et al. (2010) Climate change under aggressive mitigation: The ENSEMBLES multi-model experiment. Climate - Dynamics (submitted) - - Lowe J.A., C.D. Hewitt, D.P. Van Vuuren, T.C. Johns, E. Stehfest, J-F. Royer, and P. van der Linden, 2009. New - Study For Climate Modeling, Analyses, and Scenarios. Eos Trans. AGU, Vol 90, No. 21. - - -""" -import os.path -import itertools -import matplotlib.pyplot as plt -import numpy as np - -import iris -import iris.coords as coords -import iris.plot as iplt - - -def cop_metadata_callback(cube, field, filename): - """ A function which adds an "Experiment" coordinate which comes from the filename. """ - - # Extract the experiment name (such as a1b or e1) from the filename (in this case it is just the parent folder's name) - containing_folder = os.path.dirname(filename) - experiment_label = os.path.basename(containing_folder) - - # Create a coordinate with the experiment label in it - exp_coord = coords.AuxCoord(experiment_label, long_name='Experiment', units='no_unit') - - # and add it to the cube - cube.add_aux_coord(exp_coord) - - -def main(): - # Load e1 and a1 using the callback to update the metadata - e1 = iris.load_cube(iris.sample_data_path('E1.2098.pp'), - callback=cop_metadata_callback) - a1b = iris.load_cube(iris.sample_data_path('A1B.2098.pp'), - callback=cop_metadata_callback) - - # Load the global average data and add an 'Experiment' coord it - global_avg = iris.load_cube(iris.sample_data_path('pre-industrial.pp')) - - # Define evenly spaced contour levels: -2.5, -1.5, ... 15.5, 16.5 with the specific colours - levels = np.arange(20) - 2.5 - red = np.array([0, 0, 221, 239, 229, 217, 239, 234, 228, 222, 205, 196, 161, 137, 116, 89, 77, 60, 51]) / 256. - green = np.array([16, 217, 242, 243, 235, 225, 190, 160, 128, 87, 72, 59, 33, 21, 29, 30, 30, 29, 26]) / 256. - blue = np.array([255, 255, 243, 169, 99, 51, 63, 37, 39, 21, 27, 23, 22, 26, 29, 28, 27, 25, 22]) / 256. - - # Put those colours into an array which can be passed to conourf as the specific colours for each level - colors = np.array([red, green, blue]).T - - # Subtract the global - - - # Iterate over each latitude longitude slice for both e1 and a1b scenarios simultaneously - for e1_slice, a1b_slice in itertools.izip(e1.slices(['latitude', 'longitude']), a1b.slices(['latitude', 'longitude'])): - - time_coord = a1b_slice.coord('time') - - # Calculate the difference from the mean - delta_e1 = e1_slice - global_avg - delta_a1b = a1b_slice - global_avg - - # Make a wider than normal figure to house two maps side-by-side - fig = plt.figure(figsize=(12, 5)) - - # Get the time datetime from the coordinate - time = time_coord.units.num2date(time_coord.points[0]) - # Set a title for the entire figure, giving the time in a nice format of "MonthName Year". Also, set the y value for the - # title so that it is not tight to the top of the plot. - fig.suptitle('Annual Temperature Predictions for ' + time.strftime("%Y"), y=0.9, fontsize=18) - - # Add the first subplot showing the E1 scenario - plt.subplot(121) - plt.title('HadGEM2 E1 Scenario', fontsize=10) - iplt.contourf(delta_e1, levels, colors=colors, linewidth=0, extend='both') - plt.gca().coastlines() - # get the current axes' subplot for use later on - plt1_ax = plt.gca() - - # Add the second subplot showing the A1B scenario - plt.subplot(122) - plt.title('HadGEM2 A1B-Image Scenario', fontsize=10) - contour_result = iplt.contourf(delta_a1b, levels, colors=colors, linewidth=0, extend='both') - plt.gca().coastlines() - # get the current axes' subplot for use later on - plt2_ax = plt.gca() - - - # Now add a colourbar who's leftmost point is the same as the leftmost point of the left hand plot - # and rightmost point is the rightmost point of the right hand plot - - # Get the positions of the 2nd plot and the left position of the 1st plot - left, bottom, width, height = plt2_ax.get_position().bounds - first_plot_left = plt1_ax.get_position().bounds[0] - - # the width of the colorbar should now be simple - width = left - first_plot_left + width - - # Add axes to the figure, to place the colour bar - colorbar_axes = fig.add_axes([first_plot_left, bottom + 0.07, width, 0.03]) - - # Add the colour bar - cbar = plt.colorbar(contour_result, colorbar_axes, orientation='horizontal') - - # Label the colour bar and add ticks - cbar.set_label(e1_slice.units) - cbar.ax.tick_params(length=0) - - plt.show() - - -if __name__ == '__main__': - main() diff --git a/docs/iris/example_code/graphics/__init__.py b/docs/iris/example_code/graphics/__init__.py deleted file mode 100644 index 7cabf49449..0000000000 --- a/docs/iris/example_code/graphics/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -""" -Visualisation examples -====================== -""" diff --git a/docs/iris/example_code/graphics/cross_section.py b/docs/iris/example_code/graphics/cross_section.py deleted file mode 100644 index a4f751caaa..0000000000 --- a/docs/iris/example_code/graphics/cross_section.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Cross section plots -=================== - -This example demonstrates contour plots of a cross-sectioned multi-dimensional cube which features -a hybrid height vertical coordinate system. - -""" - -import matplotlib.pyplot as plt - -import iris -import iris.quickplot as qplt - - -def main(): - fname = iris.sample_data_path('hybrid_height.nc') - theta = iris.load_cube(fname) - - # Extract a single height vs longitude cross-section. N.B. This could easily be changed to - # extract a specific slice, or even to loop over *all* cross section slices. - cross_section = theta.slices(['grid_longitude', 'model_level_number']).next() - - qplt.contourf(cross_section, coords=['grid_longitude', 'altitude']) - plt.show() - - # Now do the equivalent plot, only against model level - plt.figure() - - qplt.contourf(cross_section, coords=['grid_longitude', 'model_level_number']) - plt.show() - - -if __name__ == '__main__': - main() diff --git a/docs/iris/example_code/graphics/custom_file_loading.py b/docs/iris/example_code/graphics/custom_file_loading.py deleted file mode 100644 index 592e408600..0000000000 --- a/docs/iris/example_code/graphics/custom_file_loading.py +++ /dev/null @@ -1,250 +0,0 @@ -""" -Loading a cube from a custom file format -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -This example shows how a custom text file can be loaded using the standard Iris load mechanism. - -The first stage in the process is to define an Iris :class:`FormatSpecification ` for the file format. -To create a format specification we need to define the following: - -* format_name - Some text that describes the format specification we are creating -* file_element - FileElement object describing the element which identifies - this FormatSpecification. - Possible values are: - - ``iris.io.format_picker.MagicNumber(n, o)`` - The n bytes from the file \ - at offset o. - - ``iris.io.format_picker.FileExtension()`` - The file's extension. - - ``iris.io.format_picker.LeadingLine()`` - The first line of the file. - -* file_element_value - The value that the file_element should take if a file matches this FormatSpecification -* handler (optional) - A generator function that will be called when the file specification has been identified. This function is - provided by the user and provides the means to parse the whole file. If no handler function is provided, then identification - is still possible without any handling. - - The handler function must define the following arguments: - - * list of filenames to process - * callback function - An optional function to filter/alter the Iris cubes returned - - The handler function must be defined as generator which yields each cube as they are produced. - -* priority (optional) - Integer giving a priority for considering this specification where higher priority means sooner consideration - -In the following example, the function :func:`load_NAME_III` has been defined to handle the loading of the raw data from the custom file format. -This function is called from :func:`NAME_to_cube` which uses this data to create and yield Iris cubes. - -In the ``main()`` function the filenames are loaded via the ``iris.load_cube`` function which automatically -invokes the ``FormatSpecification`` we defined. The cube returned from the load function is then used to produce a plot. - -""" -import datetime - -import matplotlib.pyplot as plt -import numpy as np - -import iris -import iris.coords as icoords -import iris.coord_systems as icoord_systems -import iris.fileformats -import iris.io.format_picker as format_picker -import iris.plot as iplt - - -UTC_format = '%H%M%Z %d/%m/%Y' - - -def load_NAME_III(filename): - """ - Loads the Met Office's NAME III grid output files returning headers, column definitions and data arrays as 3 separate lists. - - """ - - # loading a file gives a generator of lines which can be progressed using the next() method. - # This will come in handy as we wish to progress through the file line by line. - file_handle = file(filename) - - # define a dictionary which can hold the header metadata about this file - headers = {} - - # skip the NAME header of the file which looks something like 'NAME III (version X.X.X)' - file_handle.next() - - # read the next 16 lines of header information, putting the form "header name: header value" into a dictionary - for _ in range(16): - header_name, header_value = file_handle.next().split(':') - - # strip off any spurious space characters in the header name and value - header_name = header_name.strip() - header_value = header_value.strip() - - # cast some headers into floats or integers if they match a given header name - if header_name in ['X grid origin', 'Y grid origin', 'X grid resolution', 'Y grid resolution']: - header_value = float(header_value) - elif header_name in ['X grid size', 'Y grid size', 'Number of fields']: - header_value = int(header_value) - elif header_name in ['Run time', 'Start of release', 'End of release']: - # convert the time to python datetimes - header_value = datetime.datetime.strptime(header_value, UTC_format) - - headers[header_name] = header_value - - # skip the next blank line in the file. - file_handle.next() - - # Read the next 7 lines of column definitions - column_headings = {} - for column_header_name in ['species_category', 'species', 'cell_measure', 'quantity', 'unit', 'z_level', 'time']: - column_headings[column_header_name] = [col.strip() for col in file_handle.next().split(',')][:-1] - - # convert the time to python datetimes - new_time_column_header = [] - for i, t in enumerate(column_headings['time']): - # the first 4 columns aren't time at all, so don't convert them to datetimes - if i >= 4: - new_time_column_header.append(datetime.datetime.strptime(t, UTC_format)) - else: - new_time_column_header.append(t) - column_headings['time'] = new_time_column_header - - # skip the blank line after the column headers - file_handle.next() - - # make a list of data arrays to hold the data for each column - data_shape = (headers['Y grid size'], headers['X grid size']) - data_arrays = [np.zeros(data_shape, dtype=np.float32) for i in range(headers['Number of fields'])] - - # iterate over the remaining lines which represent the data in a column form - for line in file_handle: - - # split the line by comma, removing the last empty column caused by the trailing comma - vals = line.split(',')[:-1] - - # cast the x and y grid positions to floats and convert them to zero based indices - # (the numbers are 1 based grid positions where 0.5 represents half a grid point.) - x = float(vals[0]) - 1.5 - y = float(vals[1]) - 1.5 - - # populate the data arrays (i.e. all columns but the leading 4) - for i, data_array in enumerate(data_arrays): - data_array[y, x] = float(vals[i + 4]) - - return headers, column_headings, data_arrays - - -def NAME_to_cube(filenames, callback): - """Returns a generator of cubes given a list of filenames and a callback.""" - - for filename in filenames: - header, column_headings, data_arrays = load_NAME_III(filename) - - for i, data_array in enumerate(data_arrays): - # turn the dictionary of column headers with a list of header information for each field into a dictionary of - # headers for just this field. Ignore the first 4 columns of grid position (data was located with the data array). - field_headings = dict([(k, v[i + 4]) for k, v in column_headings.iteritems()]) - - # make an cube - cube = iris.cube.Cube(data_array) - - # define the name and unit - name = ('%s %s' % (field_headings['species'], field_headings['quantity'])).upper().replace(' ', '_') - cube.rename(name) - # Some units are badly encoded in the file, fix this by putting a space in between. (if gs is not found, then the - # string will be returned unchanged) - cube.units = field_headings['unit'].replace('gs', 'g s') - - # define and add the singular coordinates of the field (flight level, time etc.) - cube.add_aux_coord(icoords.AuxCoord(field_headings['z_level'], long_name='flight_level', units='1')) - - # define the time unit and use it to serialise the datetime for the time coordinate - time_unit = iris.unit.Unit('hours since epoch', calendar=iris.unit.CALENDAR_GREGORIAN) - time_coord = icoords.AuxCoord(time_unit.date2num(field_headings['time']), standard_name='time', units=time_unit) - cube.add_aux_coord(time_coord) - - # build a coordinate system which can be referenced by latitude and longitude coordinates - lat_lon_coord_system = icoord_systems.GeogCS(6371229) - - # build regular latitude and longitude coordinates which have bounds - start = header['X grid origin'] + header['X grid resolution'] - step = header['X grid resolution'] - count = header['X grid size'] - pts = start + np.arange(count, dtype=np.float32) * step - lon_coord = icoords.DimCoord(pts, standard_name='longitude', units='degrees', coord_system=lat_lon_coord_system) - lon_coord.guess_bounds() - - start = header['Y grid origin'] + header['Y grid resolution'] - step = header['Y grid resolution'] - count = header['Y grid size'] - pts = start + np.arange(count, dtype=np.float32) * step - lat_coord = icoords.DimCoord(pts, standard_name='latitude', units='degrees', coord_system=lat_lon_coord_system) - lat_coord.guess_bounds() - - # add the latitude and longitude coordinates to the cube, with mappings to data dimensions - cube.add_dim_coord(lat_coord, 0) - cube.add_dim_coord(lon_coord, 1) - - # implement standard iris callback capability. Although callbacks are not used in this example, the standard - # mechanism for a custom loader to implement a callback is shown: - cube = iris.io.run_callback(callback, cube, [header, field_headings, data_array], filename) - - # yield the cube created (the loop will continue when the next() element is requested) - yield cube - - -# Create a format_picker specification of the NAME file format giving it a -# priority greater than the built in NAME loader. -_NAME_III_spec = format_picker.FormatSpecification('Name III', format_picker.LeadingLine(), - lambda line: line.startswith("NAME III"), NAME_to_cube, - priority=6) - -# Register the NAME loader with iris -iris.fileformats.FORMAT_AGENT.add_spec(_NAME_III_spec) - - - -# --------------------------------------------- -# | Using the new loader | -# --------------------------------------------- - -def main(): - fname = iris.sample_data_path('NAME_output.txt') - - boundary_volc_ash_constraint = iris.Constraint('VOLCANIC_ASH_AIR_CONCENTRATION', flight_level='From FL000 - FL200') - - # Callback shown as None to illustrate where a cube-level callback function would be used if required - cube = iris.load_cube(fname, boundary_volc_ash_constraint, callback=None) - - # draw contour levels for the data (the top level is just a catch-all) - levels = (0.0002, 0.002, 0.004, 1e10) - cs = iplt.contourf(cube, levels=levels, - colors=('#80ffff', '#939598', '#e00404'), - ) - - # draw a black outline at the lowest contour to highlight affected areas - iplt.contour(cube, levels=(levels[0], 100), - colors='black') - - # set an extent and a background image for the map - ax = plt.gca() - ax.set_extent((-90, 20, 20, 75)) - ax.stock_img('ne_shaded') - - # make a legend, with custom labels, for the coloured contour set - artists, _ = cs.legend_elements() - labels = [ - r'$%s < x \leq %s$' % (levels[0], levels[1]), - r'$%s < x \leq %s$' % (levels[1], levels[2]), - r'$x > %s$' % levels[2]] - ax.legend(artists, labels, title='Ash concentration / g m-3', loc='upper left') - - time = cube.coord('time') - time_date = time.units.num2date(time.points[0]).strftime(UTC_format) - plt.title('Volcanic ash concentration forecast\nvalid at %s' % time_date) - - plt.show() - - -if __name__ == '__main__': - main() diff --git a/docs/iris/example_code/graphics/global_map.py b/docs/iris/example_code/graphics/global_map.py deleted file mode 100644 index 01fc09eb6b..0000000000 --- a/docs/iris/example_code/graphics/global_map.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -Quickplot of a 2d cube on a map -=============================== - -This example demonstrates a contour plot of global air temperature. -The plot title and the labels for the axes are automatically derived from the metadata. - -""" -import matplotlib.pyplot as plt - -import iris -import iris.quickplot as qplt - - -def main(): - fname = iris.sample_data_path('air_temp.pp') - temperature = iris.load_cube(fname) - - qplt.contourf(temperature, 15) - plt.gca().coastlines() - plt.show() - - -if __name__ == '__main__': - main() diff --git a/docs/iris/example_code/graphics/hovmoller.py b/docs/iris/example_code/graphics/hovmoller.py deleted file mode 100644 index a036d8f7cd..0000000000 --- a/docs/iris/example_code/graphics/hovmoller.py +++ /dev/null @@ -1,47 +0,0 @@ -""" -Hovmoller diagram of monthly surface temperature -================================================ - -This example demonstrates the creation of a Hovmoller diagram with fine control over plot ticks and labels. -The data comes from the Met Office OSTIA project and has been pre-processed to calculate the monthly mean sea -surface temperature. - -""" -import matplotlib.pyplot as plt -import matplotlib.dates as mdates - -import iris -import iris.quickplot as qplt -import iris.unit - - -def main(): - fname = iris.sample_data_path('ostia_monthly.nc') - - # load a single cube of surface temperature between +/- 5 latitude - cube = iris.load_cube(fname, iris.Constraint('surface_temperature', latitude=lambda v: -5 < v < 5)) - - # Take the mean over latitude - cube = cube.collapsed('latitude', iris.analysis.MEAN) - - # Now that we have our data in a nice way, lets create the plot - # contour with 20 levels - qplt.contourf(cube, 20) - - # Put a custom label on the y axis - plt.ylabel('Time / years') - - # Stop matplotlib providing clever axes range padding - plt.axis('tight') - - # As we are plotting annual variability, put years as the y ticks - plt.gca().yaxis.set_major_locator(mdates.YearLocator()) - - # And format the ticks to just show the year - plt.gca().yaxis.set_major_formatter(mdates.DateFormatter('%Y')) - - plt.show() - - -if __name__ == '__main__': - main() diff --git a/docs/iris/example_code/graphics/lagged_ensemble.py b/docs/iris/example_code/graphics/lagged_ensemble.py deleted file mode 100644 index 399948d2e0..0000000000 --- a/docs/iris/example_code/graphics/lagged_ensemble.py +++ /dev/null @@ -1,139 +0,0 @@ -""" -Seasonal ensemble model plots -============================= - -This example demonstrates the loading of a lagged ensemble dataset from the GloSea4 model, which is then used to -produce two types of plot: - - * The first shows the "postage stamp" style image with an array of 14 images, one for each ensemble member with - a shared colorbar. (The missing image in this example represents ensemble member number 6 which was a failed run) - - * The second plot shows the data limited to a region of interest, in this case a region defined for forecasting - ENSO (El Nino-Southern Oscillation), which, for the purposes of this example, has had the ensemble mean subtracted - from each ensemble member to give an anomaly surface temperature. In practice a better approach would be to take the - climatological mean, calibrated to the model, from each ensemble member. - -""" -import matplotlib.pyplot as plt -import numpy as np - -import iris -import iris.plot as iplt - - -def realization_metadata(cube, field, fname): - """ - A function which modifies the cube's metadata to add a "realization" (ensemble member) coordinate from the filename if one - doesn't already exist in the cube. - - """ - # add an ensemble member coordinate if one doesn't already exist - if not cube.coords('realization'): - # the ensemble member is encoded in the filename as *_???.pp where ??? is the ensemble member - realization_number = fname[-6:-3] - - import iris.coords - realization_coord = iris.coords.AuxCoord(np.int32(realization_number), 'realization') - cube.add_aux_coord(realization_coord) - - -def main(): - # extract surface temperature cubes which have an ensemble member coordinate, adding appropriate lagged ensemble metadata - surface_temp = iris.load_cube(iris.sample_data_path('GloSea4', 'ensemble_???.pp'), - iris.Constraint('surface_temperature', realization=lambda value: True), - callback=realization_metadata, - ) - - # ---------------------------------------------------------------------------------------------------------------- - # Plot #1: Ensemble postage stamps - # ---------------------------------------------------------------------------------------------------------------- - - # for the purposes of this example, take the last time element of the cube - last_timestep = surface_temp[:, -1, :, :] - - # Make 50 evenly spaced levels which span the dataset - contour_levels = np.linspace(np.min(last_timestep.data), np.max(last_timestep.data), 50) - - # Create a wider than normal figure to support our many plots - plt.figure(figsize=(12, 6), dpi=100) - - # Also manually adjust the spacings which are used when creating subplots - plt.gcf().subplots_adjust(hspace=0.05, wspace=0.05, top=0.95, bottom=0.05, left=0.075, right=0.925) - - # iterate over all possible latitude longitude slices - for cube in last_timestep.slices(['latitude', 'longitude']): - - # get the ensemble member number from the ensemble coordinate - ens_member = cube.coord('realization').points[0] - - # plot the data in a 4x4 grid, with each plot's position in the grid being determined by ensemble member number - # the special case for the 13th ensemble member is to have the plot at the bottom right - if ens_member == 13: - plt.subplot(4, 4, 16) - else: - plt.subplot(4, 4, ens_member+1) - - cf = iplt.contourf(cube, contour_levels) - - # add coastlines - plt.gca().coastlines() - - # make an axes to put the shared colorbar in - colorbar_axes = plt.gcf().add_axes([0.35, 0.1, 0.3, 0.05]) - colorbar = plt.colorbar(cf, colorbar_axes, orientation='horizontal') - colorbar.set_label('%s' % last_timestep.units) - - # limit the colorbar to 8 tick marks - import matplotlib.ticker - colorbar.locator = matplotlib.ticker.MaxNLocator(8) - colorbar.update_ticks() - - # get the time for the entire plot - time_coord = last_timestep.coord('time') - time = time_coord.units.num2date(time_coord.bounds[0, 0]) - - # set a global title for the postage stamps with the date formated by "monthname year" - plt.suptitle('Surface temperature ensemble forecasts for %s' % time.strftime('%B %Y')) - - iplt.show() - - - # ---------------------------------------------------------------------------------------------------------------- - # Plot #2: ENSO plumes - # ---------------------------------------------------------------------------------------------------------------- - - # Nino 3.4 lies between: 170W and 120W, 5N and 5S, so define a constraint which matches this - nino_3_4_constraint = iris.Constraint(longitude=lambda v: -170+360 <= v <= -120+360, latitude=lambda v: -5 <= v <= 5) - - nino_cube = surface_temp.extract(nino_3_4_constraint) - - # Subsetting a circular longitude coordinate always results in a circular coordinate, so set the coordinate to be non-circular - nino_cube.coord('longitude').circular = False - - # Calculate the horizontal mean for the nino region - mean = nino_cube.collapsed(['latitude', 'longitude'], iris.analysis.MEAN) - - # Calculate the ensemble mean of the horizontal mean. To do this, remove the "forecast_period" and - # "forecast_reference_time" coordinates which span both "relalization" and "time". - mean.remove_coord("forecast_reference_time") - mean.remove_coord("forecast_period") - ensemble_mean = mean.collapsed('realization', iris.analysis.MEAN) - - # take the ensemble mean from each ensemble member - mean -= ensemble_mean.data - - plt.figure() - - for ensemble_member in mean.slices(['time']): - # draw each ensemble member as a dashed line in black - iplt.plot(ensemble_member, '--k') - - plt.title('Mean temperature anomaly for ENSO 3.4 region') - plt.xlabel('Time') - plt.ylabel('Temperature anomaly / K') - - plt.show() - - -if __name__ == '__main__': - main() diff --git a/docs/iris/example_tests/__init__.py b/docs/iris/example_tests/__init__.py index 98ca81e740..174361337f 100644 --- a/docs/iris/example_tests/__init__.py +++ b/docs/iris/example_tests/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2012, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -14,3 +14,6 @@ # # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/docs/iris/example_tests/extest_util.py b/docs/iris/example_tests/extest_util.py index e550eed865..3d9017b6ee 100644 --- a/docs/iris/example_tests/extest_util.py +++ b/docs/iris/example_tests/extest_util.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2016, Met Office # # This file is part of Iris. # @@ -21,20 +21,26 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa import contextlib import os.path +import warnings import sys import matplotlib.pyplot as plt +import iris +from iris._deprecation import IrisDeprecation import iris.plot as iplt import iris.quickplot as qplt -from iris.tests import _DEFAULT_IMAGE_TOLERANCE EXAMPLE_DIRECTORY = os.path.join(os.path.dirname(os.path.dirname(__file__)), - 'example_code', 'graphics') + 'example_code') +EXAMPLE_DIRECTORIES = [os.path.join(EXAMPLE_DIRECTORY, the_dir) + for the_dir in os.listdir(EXAMPLE_DIRECTORY)] @contextlib.contextmanager @@ -47,13 +53,13 @@ def add_examples_to_path(): """ orig_sys_path = sys.path sys.path = sys.path[:] - sys.path.append(EXAMPLE_DIRECTORY) + sys.path += EXAMPLE_DIRECTORIES yield sys.path = orig_sys_path @contextlib.contextmanager -def show_replaced_by_check_graphic(test_case, tol=_DEFAULT_IMAGE_TOLERANCE): +def show_replaced_by_check_graphic(test_case): """ Creates a context manager which can be used to replace the functionality of matplotlib.pyplot.show with a function which calls the check_graphic @@ -62,9 +68,30 @@ def show_replaced_by_check_graphic(test_case, tol=_DEFAULT_IMAGE_TOLERANCE): """ def replacement_show(): # form a closure on test_case and tolerance - test_case.check_graphic(tol=tol) + test_case.check_graphic() orig_show = plt.show plt.show = iplt.show = qplt.show = replacement_show yield plt.show = iplt.show = qplt.show = orig_show + + +@contextlib.contextmanager +def fail_any_deprecation_warnings(): + """ + Create a context in which any deprecation warning will cause an error. + + The context also resets all the iris.FUTURE settings to the defaults, as + otherwise changes made in one test can affect subsequent ones. + + """ + with warnings.catch_warnings(): + # Detect and error all and any Iris deprecation warnings. + warnings.simplefilter("error", IrisDeprecation) + # Run with all default settings in iris.FUTURE. + default_future_kwargs = iris.Future().__dict__.copy() + for dead_option in iris.Future.deprecated_options: + # Avoid a warning when setting these ! + del default_future_kwargs[dead_option] + with iris.FUTURE.context(**default_future_kwargs): + yield diff --git a/docs/iris/example_tests/test_COP_1d_plot.py b/docs/iris/example_tests/test_COP_1d_plot.py index bb3bcf6ccf..f356423b25 100644 --- a/docs/iris/example_tests/test_COP_1d_plot.py +++ b/docs/iris/example_tests/test_COP_1d_plot.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2016, Met Office # # This file is part of Iris. # @@ -15,21 +15,26 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa -# Import Iris tests first so that some things can be initialised before importing anything else. +# Import Iris tests first so that some things can be initialised before +# importing anything else. import iris.tests as tests -import extest_util - -with extest_util.add_examples_to_path(): - import COP_1d_plot +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) class TestCOP1DPlot(tests.GraphicsTest): """Test the COP_1d_plot example code.""" def test_COP_1d_plot(self): - with extest_util.show_replaced_by_check_graphic(self): - COP_1d_plot.main() + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import COP_1d_plot + with show_replaced_by_check_graphic(self): + COP_1d_plot.main() if __name__ == '__main__': diff --git a/docs/iris/example_tests/test_COP_maps.py b/docs/iris/example_tests/test_COP_maps.py index 7a6395b850..10dcbcc816 100644 --- a/docs/iris/example_tests/test_COP_maps.py +++ b/docs/iris/example_tests/test_COP_maps.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2016, Met Office # # This file is part of Iris. # @@ -15,21 +15,26 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa -# Import Iris tests first so that some things can be initialised before importing anything else. +# Import Iris tests first so that some things can be initialised before +# importing anything else. import iris.tests as tests -import extest_util - -with extest_util.add_examples_to_path(): - import COP_maps +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) class TestCOPMaps(tests.GraphicsTest): """Test the COP_maps example code.""" def test_cop_maps(self): - with extest_util.show_replaced_by_check_graphic(self): - COP_maps.main() + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import COP_maps + with show_replaced_by_check_graphic(self): + COP_maps.main() if __name__ == '__main__': diff --git a/docs/iris/example_tests/test_SOI_filtering.py b/docs/iris/example_tests/test_SOI_filtering.py index a0b58b952d..ea2c48920e 100644 --- a/docs/iris/example_tests/test_SOI_filtering.py +++ b/docs/iris/example_tests/test_SOI_filtering.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2012 - 2014, Met Office +# (C) British Crown Copyright 2012 - 2016, Met Office # # This file is part of Iris. # @@ -15,21 +15,26 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa -# Import Iris tests first so that some things can be initialised before importing anything else. +# Import Iris tests first so that some things can be initialised before +# importing anything else. import iris.tests as tests -import extest_util - -with extest_util.add_examples_to_path(): - import SOI_filtering +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) class TestSOIFiltering(tests.GraphicsTest): """Test the SOI_filtering example code.""" def test_soi_filtering(self): - with extest_util.show_replaced_by_check_graphic(self): - SOI_filtering.main() + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import SOI_filtering + with show_replaced_by_check_graphic(self): + SOI_filtering.main() if __name__ == '__main__': diff --git a/docs/iris/example_tests/test_TEC.py b/docs/iris/example_tests/test_TEC.py index 138dbbbd1f..e6e27c46bd 100644 --- a/docs/iris/example_tests/test_TEC.py +++ b/docs/iris/example_tests/test_TEC.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2016, Met Office # # This file is part of Iris. # @@ -15,21 +15,26 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa -# Import Iris tests first so that some things can be initialised before importing anything else. +# Import Iris tests first so that some things can be initialised before +# importing anything else. import iris.tests as tests -import extest_util - -with extest_util.add_examples_to_path(): - import TEC +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) class TestTEC(tests.GraphicsTest): """Test the TEC example code.""" def test_TEC(self): - with extest_util.show_replaced_by_check_graphic(self): - TEC.main() + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import TEC + with show_replaced_by_check_graphic(self): + TEC.main() if __name__ == '__main__': diff --git a/docs/iris/example_tests/test_anomaly_log_colouring.py b/docs/iris/example_tests/test_anomaly_log_colouring.py new file mode 100644 index 0000000000..faa040c0e6 --- /dev/null +++ b/docs/iris/example_tests/test_anomaly_log_colouring.py @@ -0,0 +1,41 @@ +# (C) British Crown Copyright 2014 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import Iris tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) + + +class TestAnomalyLogColouring(tests.GraphicsTest): + """Test the anomaly colouring example code.""" + def test_anomaly_log_colouring(self): + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import anomaly_log_colouring + with show_replaced_by_check_graphic(self): + anomaly_log_colouring.main() + + +if __name__ == '__main__': + tests.main() diff --git a/docs/iris/example_tests/test_atlantic_profiles.py b/docs/iris/example_tests/test_atlantic_profiles.py index 024b093bb4..63d6b7b754 100644 --- a/docs/iris/example_tests/test_atlantic_profiles.py +++ b/docs/iris/example_tests/test_atlantic_profiles.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office +# (C) British Crown Copyright 2013 - 2016, Met Office # # This file is part of Iris. # @@ -15,22 +15,26 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # Import Iris tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import extest_util - -with extest_util.add_examples_to_path(): - import atlantic_profiles +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) class TestAtlanticProfiles(tests.GraphicsTest): """Test the atlantic_profiles example code.""" def test_atlantic_profiles(self): - with extest_util.show_replaced_by_check_graphic(self, tol=14.0): - atlantic_profiles.main() + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import atlantic_profiles + with show_replaced_by_check_graphic(self): + atlantic_profiles.main() if __name__ == '__main__': diff --git a/docs/iris/example_tests/test_coriolis_plot.py b/docs/iris/example_tests/test_coriolis_plot.py new file mode 100644 index 0000000000..71a2334488 --- /dev/null +++ b/docs/iris/example_tests/test_coriolis_plot.py @@ -0,0 +1,40 @@ +# (C) British Crown Copyright 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import Iris tests first so that some things can be initialised before +# importing anything else. + +import iris.tests as tests + +from . import extest_util + +with extest_util.add_examples_to_path(): + import coriolis_plot + + +class TestCoriolisPlot(tests.GraphicsTest): + """Test the Coriolis Plot example code.""" + def test_coriolis_plot(self): + with extest_util.show_replaced_by_check_graphic(self): + coriolis_plot.main() + + +if __name__ == '__main__': + tests.main() diff --git a/docs/iris/example_tests/test_cross_section.py b/docs/iris/example_tests/test_cross_section.py index 4e667bce96..ad62f51b01 100644 --- a/docs/iris/example_tests/test_cross_section.py +++ b/docs/iris/example_tests/test_cross_section.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2016, Met Office # # This file is part of Iris. # @@ -15,21 +15,26 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa -# Import Iris tests first so that some things can be initialised before importing anything else. +# Import Iris tests first so that some things can be initialised before +# importing anything else. import iris.tests as tests -import extest_util - -with extest_util.add_examples_to_path(): - import cross_section +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) class TestCrossSection(tests.GraphicsTest): """Test the cross_section example code.""" def test_cross_section(self): - with extest_util.show_replaced_by_check_graphic(self): - cross_section.main() + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import cross_section + with show_replaced_by_check_graphic(self): + cross_section.main() if __name__ == '__main__': diff --git a/docs/iris/example_tests/test_custom_aggregation.py b/docs/iris/example_tests/test_custom_aggregation.py new file mode 100644 index 0000000000..319078a3a4 --- /dev/null +++ b/docs/iris/example_tests/test_custom_aggregation.py @@ -0,0 +1,41 @@ +# (C) British Crown Copyright 2013 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import Iris tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) + + +class TestCustomAggregation(tests.GraphicsTest): + """Test the custom aggregation example code.""" + def test_custom_aggregation(self): + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import custom_aggregation + with show_replaced_by_check_graphic(self): + custom_aggregation.main() + + +if __name__ == '__main__': + tests.main() diff --git a/docs/iris/example_tests/test_custom_file_loading.py b/docs/iris/example_tests/test_custom_file_loading.py index 688796bcdb..b0231d474e 100644 --- a/docs/iris/example_tests/test_custom_file_loading.py +++ b/docs/iris/example_tests/test_custom_file_loading.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2016, Met Office # # This file is part of Iris. # @@ -15,21 +15,26 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa -# Import Iris tests first so that some things can be initialised before importing anything else. +# Import Iris tests first so that some things can be initialised before +# importing anything else. import iris.tests as tests -import extest_util - -with extest_util.add_examples_to_path(): - import custom_file_loading +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) class TestCustomFileLoading(tests.GraphicsTest): """Test the custom_file_loading example code.""" def test_custom_file_loading(self): - with extest_util.show_replaced_by_check_graphic(self): - custom_file_loading.main() + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import custom_file_loading + with show_replaced_by_check_graphic(self): + custom_file_loading.main() if __name__ == '__main__': diff --git a/docs/iris/example_tests/test_deriving_phenomena.py b/docs/iris/example_tests/test_deriving_phenomena.py index 28930ce25b..bad47fe438 100644 --- a/docs/iris/example_tests/test_deriving_phenomena.py +++ b/docs/iris/example_tests/test_deriving_phenomena.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2016, Met Office # # This file is part of Iris. # @@ -15,21 +15,26 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa -# Import Iris tests first so that some things can be initialised before importing anything else. +# Import Iris tests first so that some things can be initialised before +# importing anything else. import iris.tests as tests -import extest_util - -with extest_util.add_examples_to_path(): - import deriving_phenomena +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) class TestDerivingPhenomena(tests.GraphicsTest): """Test the deriving_phenomena example code.""" def test_deriving_phenomena(self): - with extest_util.show_replaced_by_check_graphic(self): - deriving_phenomena.main() + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import deriving_phenomena + with show_replaced_by_check_graphic(self): + deriving_phenomena.main() if __name__ == '__main__': diff --git a/docs/iris/example_tests/test_global_map.py b/docs/iris/example_tests/test_global_map.py index 659b5c630c..eee10d6187 100644 --- a/docs/iris/example_tests/test_global_map.py +++ b/docs/iris/example_tests/test_global_map.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2016, Met Office # # This file is part of Iris. # @@ -15,21 +15,26 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa -# Import Iris tests first so that some things can be initialised before importing anything else. +# Import Iris tests first so that some things can be initialised before +# importing anything else. import iris.tests as tests -import extest_util - -with extest_util.add_examples_to_path(): - import global_map +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) class TestGlobalMap(tests.GraphicsTest): """Test the global_map example code.""" def test_global_map(self): - with extest_util.show_replaced_by_check_graphic(self): - global_map.main() + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import global_map + with show_replaced_by_check_graphic(self): + global_map.main() if __name__ == '__main__': diff --git a/docs/iris/example_tests/test_hovmoller.py b/docs/iris/example_tests/test_hovmoller.py index 110556bedf..ff0f37b1eb 100644 --- a/docs/iris/example_tests/test_hovmoller.py +++ b/docs/iris/example_tests/test_hovmoller.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2016, Met Office # # This file is part of Iris. # @@ -15,21 +15,26 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa -# Import Iris tests first so that some things can be initialised before importing anything else. +# Import Iris tests first so that some things can be initialised before +# importing anything else. import iris.tests as tests -import extest_util - -with extest_util.add_examples_to_path(): - import hovmoller +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) class TestGlobalMap(tests.GraphicsTest): """Test the hovmoller example code.""" def test_hovmoller(self): - with extest_util.show_replaced_by_check_graphic(self): - hovmoller.main() + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import hovmoller + with show_replaced_by_check_graphic(self): + hovmoller.main() if __name__ == '__main__': diff --git a/docs/iris/example_tests/test_inset_plot.py b/docs/iris/example_tests/test_inset_plot.py new file mode 100644 index 0000000000..67c4eb9e66 --- /dev/null +++ b/docs/iris/example_tests/test_inset_plot.py @@ -0,0 +1,42 @@ +# (C) British Crown Copyright 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import Iris tests first so that some things can be initialised before +# importing anything else. + +import iris.tests as tests + +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) + + +class TestInsetPlot(tests.GraphicsTest): + """Test the inset plot example code.""" + def test_inset_plot(self): + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import inset_plot + with show_replaced_by_check_graphic(self): + inset_plot.main() + + +if __name__ == '__main__': + tests.main() diff --git a/docs/iris/example_tests/test_lagged_ensemble.py b/docs/iris/example_tests/test_lagged_ensemble.py index fb862991ab..faa7960dbb 100644 --- a/docs/iris/example_tests/test_lagged_ensemble.py +++ b/docs/iris/example_tests/test_lagged_ensemble.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2016, Met Office # # This file is part of Iris. # @@ -15,21 +15,26 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa -# Import Iris tests first so that some things can be initialised before importing anything else. +# Import Iris tests first so that some things can be initialised before +# importing anything else. import iris.tests as tests -import extest_util - -with extest_util.add_examples_to_path(): - import lagged_ensemble +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) class TestLaggedEnsemble(tests.GraphicsTest): """Test the lagged ensemble example code.""" def test_lagged_ensemble(self): - with extest_util.show_replaced_by_check_graphic(self): - lagged_ensemble.main() + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import lagged_ensemble + with show_replaced_by_check_graphic(self): + lagged_ensemble.main() if __name__ == '__main__': diff --git a/docs/iris/example_tests/test_lineplot_with_legend.py b/docs/iris/example_tests/test_lineplot_with_legend.py index 99ef30d6ad..a7f9e54b6f 100644 --- a/docs/iris/example_tests/test_lineplot_with_legend.py +++ b/docs/iris/example_tests/test_lineplot_with_legend.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2016, Met Office # # This file is part of Iris. # @@ -15,21 +15,26 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa -# Import Iris tests first so that some things can be initialised before importing anything else. +# Import Iris tests first so that some things can be initialised before +# importing anything else. import iris.tests as tests -import extest_util - -with extest_util.add_examples_to_path(): - import lineplot_with_legend +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) class TestLineplotWithLegend(tests.GraphicsTest): """Test the lineplot_with_legend example code.""" def test_lineplot_with_legend(self): - with extest_util.show_replaced_by_check_graphic(self): - lineplot_with_legend.main() + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import lineplot_with_legend + with show_replaced_by_check_graphic(self): + lineplot_with_legend.main() if __name__ == '__main__': diff --git a/docs/iris/example_tests/test_orca_projection.py b/docs/iris/example_tests/test_orca_projection.py new file mode 100644 index 0000000000..5d7b5e4114 --- /dev/null +++ b/docs/iris/example_tests/test_orca_projection.py @@ -0,0 +1,41 @@ +# (C) British Crown Copyright 2014 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import Iris tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) + + +class TestOrcaProjection(tests.GraphicsTest): + """Test the orca projection example code.""" + def test_orca_projection(self): + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import orca_projection + with show_replaced_by_check_graphic(self): + orca_projection.main() + + +if __name__ == '__main__': + tests.main() diff --git a/docs/iris/example_tests/test_polar_stereo.py b/docs/iris/example_tests/test_polar_stereo.py index 3979531691..c2bbc0e02b 100644 --- a/docs/iris/example_tests/test_polar_stereo.py +++ b/docs/iris/example_tests/test_polar_stereo.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2016, Met Office # # This file is part of Iris. # @@ -15,22 +15,27 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa -# Import Iris tests first so that some things can be initialised -# before importing anything else. +# Import Iris tests first so that some things can be initialised before +# importing anything else. import iris.tests as tests -import extest_util - -with extest_util.add_examples_to_path(): - import polar_stereo +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) +@tests.skip_grib class TestPolarStereo(tests.GraphicsTest): """Test the polar_stereo example code.""" def test_polar_stereo(self): - with extest_util.show_replaced_by_check_graphic(self): - polar_stereo.main() + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import polar_stereo + with show_replaced_by_check_graphic(self): + polar_stereo.main() if __name__ == '__main__': diff --git a/docs/iris/example_tests/test_polynomial_fit.py b/docs/iris/example_tests/test_polynomial_fit.py new file mode 100644 index 0000000000..c56834a961 --- /dev/null +++ b/docs/iris/example_tests/test_polynomial_fit.py @@ -0,0 +1,41 @@ +# (C) British Crown Copyright 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import Iris tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) + + +class TestPolynomialFit(tests.GraphicsTest): + """Test the polynomial_fit example code.""" + def test_polynomial_fit(self): + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import polynomial_fit + with show_replaced_by_check_graphic(self): + polynomial_fit.main() + + +if __name__ == '__main__': + tests.main() diff --git a/docs/iris/example_tests/test_projections_and_annotations.py b/docs/iris/example_tests/test_projections_and_annotations.py new file mode 100644 index 0000000000..adfcc45026 --- /dev/null +++ b/docs/iris/example_tests/test_projections_and_annotations.py @@ -0,0 +1,41 @@ +# (C) British Crown Copyright 2014 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import Iris tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) + + +class TestProjectionsAndAnnotations(tests.GraphicsTest): + """Test the atlantic_profiles example code.""" + def test_projections_and_annotations(self): + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import projections_and_annotations + with show_replaced_by_check_graphic(self): + projections_and_annotations.main() + + +if __name__ == '__main__': + tests.main() diff --git a/docs/iris/example_tests/test_rotated_pole_mapping.py b/docs/iris/example_tests/test_rotated_pole_mapping.py index 75d61ff975..672ba50434 100644 --- a/docs/iris/example_tests/test_rotated_pole_mapping.py +++ b/docs/iris/example_tests/test_rotated_pole_mapping.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2016, Met Office # # This file is part of Iris. # @@ -15,21 +15,26 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa -# Import Iris tests first so that some things can be initialised before importing anything else. +# Import Iris tests first so that some things can be initialised before +# importing anything else. import iris.tests as tests -import extest_util - -with extest_util.add_examples_to_path(): - import rotated_pole_mapping +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) class TestRotatedPoleMapping(tests.GraphicsTest): """Test the rotated_pole_mapping example code.""" def test_rotated_pole_mapping(self): - with extest_util.show_replaced_by_check_graphic(self): - rotated_pole_mapping.main() + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import rotated_pole_mapping + with show_replaced_by_check_graphic(self): + rotated_pole_mapping.main() if __name__ == '__main__': diff --git a/docs/iris/example_tests/test_wind_speed.py b/docs/iris/example_tests/test_wind_speed.py new file mode 100644 index 0000000000..dacf146c91 --- /dev/null +++ b/docs/iris/example_tests/test_wind_speed.py @@ -0,0 +1,41 @@ +# (C) British Crown Copyright 2010 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import Iris tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from .extest_util import (add_examples_to_path, + show_replaced_by_check_graphic, + fail_any_deprecation_warnings) + + +class TestWindSpeed(tests.GraphicsTest): + """Test the wind_speed example code.""" + def test_wind_speed(self): + with fail_any_deprecation_warnings(): + with add_examples_to_path(): + import wind_speed + with show_replaced_by_check_graphic(self): + wind_speed.main() + + +if __name__ == '__main__': + tests.main() diff --git a/docs/iris/src/_static/bullet_off.png b/docs/iris/src/_static/bullet_off.png deleted file mode 100644 index 601df8d186..0000000000 Binary files a/docs/iris/src/_static/bullet_off.png and /dev/null differ diff --git a/docs/iris/src/_static/bullet_on.png b/docs/iris/src/_static/bullet_on.png deleted file mode 100644 index f341ede7ac..0000000000 Binary files a/docs/iris/src/_static/bullet_on.png and /dev/null differ diff --git a/docs/iris/src/_static/favicon-16x16.png b/docs/iris/src/_static/favicon-16x16.png new file mode 100644 index 0000000000..54a743670f Binary files /dev/null and b/docs/iris/src/_static/favicon-16x16.png differ diff --git a/docs/iris/src/_static/favicon-32x32.png b/docs/iris/src/_static/favicon-32x32.png new file mode 100644 index 0000000000..e3fadd6c65 Binary files /dev/null and b/docs/iris/src/_static/favicon-32x32.png differ diff --git a/docs/iris/src/_static/logo_banner.png b/docs/iris/src/_static/logo_banner.png new file mode 100644 index 0000000000..132ba19c22 Binary files /dev/null and b/docs/iris/src/_static/logo_banner.png differ diff --git a/docs/iris/src/_static/style.css b/docs/iris/src/_static/style.css index 157298d781..69fa84394e 100644 --- a/docs/iris/src/_static/style.css +++ b/docs/iris/src/_static/style.css @@ -1,3 +1,99 @@ +body { + font-family: 'Noto Sans', sans-serif; +} + .sidebar { z-index: 10; } -.highlight { background: none; } +.highlight { background: none; } + +p.hr_p { + overflow: hidden; + text-align: center; +} +p.hr_p a { + font-size: small; + color: #1C86EE; +} +p.hr_p:before, +p.hr_p:after { + background-color: #abc; + border: 1px solid #abc; + content: ""; + display: inline-block; + height: 1px; + position: relative; + vertical-align: middle; + width: 50%; +} +p.hr_p:before { + right: 0.5em; + margin-left: -50%; +} +p.hr_p:after { + left: 0.5em; + margin-right: -50%; +} + +.header-content { + background-color: white; + text-align: left; + padding: 0px; + height: 149px; +} + +.header-content img { + height: 100px; + vertical-align: middle; + float: left; + margin: 20px 2em 0.8em 4%; + padding: 0px; +} + +.header-content .strapline { + display: inline-block; + width: calc(100% - 110px - 2em - 4%); +} + +.strapline p { + font-size: medium; + font-family: 'Alike', serif; + font-weight: bold; + color: #444444; + max-width: 52ch; + margin-top: 0.25em; +} + +.header-content h1 { + font-size: 3.5rem; + font-family: 'Alike', serif; + margin-top: 40px; + padding: 0px; + color: #323232; + padding-bottom: 0.2em; +} + +.header-content h1 span.version { + font-size: 1.5rem; +} + +.github-forkme { + position: absolute; + top: 0; + right: 80px; + border: 0; +} + +/* Take into account the resizing effect of the page (which has a minimum */ +/* width of 740px + 80px margins). */ +@media screen and (max-width: calc(740px + 80px + 80px)) { + .github-forkme { + right: calc(100% - 740px - 80px); + } +} + +@media screen and (max-width: calc(740px + 80px)) { + .github-forkme { + left: calc(740px + 80px - 149px); + right: 0px; + } +} diff --git a/docs/iris/src/_templates/index.html b/docs/iris/src/_templates/index.html index b77baac715..31acded447 100644 --- a/docs/iris/src/_templates/index.html +++ b/docs/iris/src/_templates/index.html @@ -1,27 +1,49 @@ {% extends "layout.html" %} {% set title = 'Iris documentation homepage' %} {% block extrahead %} +{{ super() }} - + + + + + + + + {% endblock %} @@ -19,13 +24,28 @@ {% block relbar1 %} -
-

-Logo - Iris {{version}} -

+ + Fork Iris on GitHub + + + +
+ + Iris logo + +
+

+ Iris v2.2 +

+

+ A powerful, format-agnostic, community-driven Python library for analysing and + visualising Earth science data. +

+
+ {{ super() }} {% endblock %} @@ -36,7 +56,7 @@ + + {% endblock %} diff --git a/docs/iris/src/conf.py b/docs/iris/src/conf.py index d718da291f..6cdfe634c4 100644 --- a/docs/iris/src/conf.py +++ b/docs/iris/src/conf.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -15,6 +15,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # -*- coding: utf-8 -*- # @@ -29,7 +31,9 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys, os +import datetime +import os +import sys # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -44,8 +48,7 @@ # Temporary value for use by LaTeX and 'man' output. # Deleted at the end of the module. -_authors = ('Byron Blay', 'Ed Campbell', 'Philip Elson', 'Richard Hattersley', - 'Bill Little') +_authors = ('Iris developers') # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' @@ -53,24 +56,29 @@ # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', - 'sphinx.ext.coverage', - 'sphinx.ext.pngmath', 'sphinx.ext.autosummary', + 'sphinx.ext.coverage', + 'sphinx.ext.doctest', + 'sphinx.ext.extlinks', 'sphinx.ext.graphviz', + 'sphinx.ext.imgmath', 'sphinx.ext.intersphinx', - 'sphinx.ext.doctest', 'matplotlib.sphinxext.mathmpl', 'matplotlib.sphinxext.only_directives', - - #'matplotlib.sphinxext.plot_directive', - 'plot_directive', + 'matplotlib.sphinxext.plot_directive', # better class documentation 'custom_class_autodoc', + # Data instance __repr__ filter. + 'custom_data_autodoc', + 'gen_example_directory', 'generate_package_rst', 'gen_gallery', + + # Add labels to figures automatically + 'auto_label_figures', ] # list of packages to document @@ -92,7 +100,8 @@ project = u'Iris' # define the copyright information for latex builds. Note, for html builds, # the copyright exists directly inside "_templates/layout.html" -copyright = u'British Crown Copyright 2010 - 2013, Met Office' +upper_copy_year = datetime.datetime.now().year +copyright = u'British Crown Copyright 2010 - {}, Met Office'.format(upper_copy_year) # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -139,20 +148,28 @@ # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' -# Definer the default highlight language. This also allows the >>> removal +# Define the default highlight language. This also allows the >>> removal # javascript (copybutton.js) to function. -highlight_language = 'python' +highlight_language = 'default' # A list of ignored prefixes for module index sorting. modindex_common_prefix = ['iris'] intersphinx_mapping = { - 'python': ('http://docs.python.org/2.7', None), - 'numpy': ('http://docs.scipy.org/doc/numpy/', None), - 'scipy': ('http://docs.scipy.org/doc/scipy/reference/', None), - 'matplotlib': ('http://matplotlib.sourceforge.net/', None), + 'cartopy': ('http://scitools.org.uk/cartopy/docs/latest/', None), + 'iris-grib': ('http://iris-grib.readthedocs.io/en/latest/', None), + 'matplotlib': ('http://matplotlib.org/', None), + 'numpy': ('http://docs.scipy.org/doc/numpy/', None), + 'python': ('http://docs.python.org/2.7', None), + 'scipy': ('http://docs.scipy.org/doc/scipy/reference/', None), } +# -- Extlinks extension ------------------------------------------------------- + +extlinks = {'issue': ('https://github.com/SciTools/iris/issues/%s', + 'Issue #'), + 'pull': ('https://github.com/SciTools/iris/pull/%s', 'PR #'), + } # -- Doctest ------------------------------------------------------------------ @@ -179,6 +196,8 @@ # documentation. #html_theme_options = {} +html_context = {'copyright_years': '2010 - {}'.format(upper_copy_year)} + # Add any paths that contain custom themes here, relative to this directory. html_theme_path = [] diff --git a/docs/iris/src/contents.rst b/docs/iris/src/contents.rst index 61b08a1d94..ecaf025a7a 100644 --- a/docs/iris/src/contents.rst +++ b/docs/iris/src/contents.rst @@ -17,11 +17,16 @@ Iris documentation table of contents iris/iris.rst +.. toctree:: + :maxdepth: 2 + + whatsnew/index.rst + .. toctree:: :maxdepth: 1 - whatsnew/1.6.rst examples/index.rst developers_guide/index.rst + whitepapers/index.rst copyright.rst diff --git a/docs/iris/src/copyright.rst b/docs/iris/src/copyright.rst index 02c9431b51..ed611c5ba8 100644 --- a/docs/iris/src/copyright.rst +++ b/docs/iris/src/copyright.rst @@ -7,14 +7,14 @@ Iris copyright, licensing and contributors Iris code --------- -All Iris source code, unless explicitly stated, is |copy| ``British Crown copyright, 2013`` and +All Iris source code, unless explicitly stated, is |copy| ``British Crown copyright, 2014`` and is licensed under the **GNU Lesser General Public License** as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. You should find all source files with the following header: .. admonition:: Code License - |copy| British Crown Copyright 2010 - 2013, Met Office + |copy| British Crown Copyright 2010 - 2014, Met Office This file is part of Iris. @@ -40,7 +40,7 @@ are licensed under the UK's Open Government Licence: .. admonition:: Documentation, example and data license - |copy| British Crown copyright, 2013. + |copy| British Crown copyright, 2014. You may use and re-use the information featured on this website (not including logos) free of charge in any format or medium, under the terms of the diff --git a/docs/iris/src/developers_guide/deprecations.rst b/docs/iris/src/developers_guide/deprecations.rst new file mode 100644 index 0000000000..c7a6888984 --- /dev/null +++ b/docs/iris/src/developers_guide/deprecations.rst @@ -0,0 +1,120 @@ +.. _iris_development_deprecations: + +Deprecations +************ + +If you need to make a backwards-incompatible change to a public API +[#public-api]_ that has been included in a release (e.g. deleting a +method), then you must first deprecate the old behaviour in at least +one release, before removing/updating it in the next +`major release `_. + + +Adding a deprecation +==================== + +.. _removing-a-public-api: + +Removing a public API +--------------------- + +The simplest form of deprecation occurs when you need to remove a public +API. The public API in question is deprecated for a period before it is +removed to allow time for user code to be updated. Sometimes the +deprecation is accompanied by the introduction of a new public API. + +Under these circumstances the following points apply: + + - Using the deprecated API must result in a concise deprecation warning which + is an instance of :class:`iris.IrisDeprecation`. + It is easiest to call + :func:`iris._deprecation.warn_deprecated`, which is a + simple wrapper to :func:`warnings.warn` with the signature + `warn_deprecation(message, **kwargs)`. + - Where possible, your deprecation warning should include advice on + how to avoid using the deprecated API. For example, you might + reference a preferred API, or more detailed documentation elsewhere. + - You must update the docstring for the deprecated API to include a + Sphinx deprecation directive: + + :literal:`.. deprecated:: ` + + where you should replace `` with the major and minor version + of Iris in which this API is first deprecated. For example: `1.8`. + + As with the deprecation warning, you should include advice on how to + avoid using the deprecated API within the content of this directive. + Feel free to include more detail in the updated docstring than in the + deprecation warning. + - You should check the documentation for references to the deprecated + API and update them as appropriate. + +Changing a default +------------------ + +When you need to change the default behaviour of a public API the +situation is slightly more complex. The recommended solution is to use +the :data:`iris.FUTURE` object. The :data:`iris.FUTURE` object provides +boolean attributes that allow user code to control at run-time the +default behaviour of corresponding public APIs. When a boolean attribute +is set to `False` it causes the corresponding public API to use its +deprecated default behaviour. When a boolean attribute is set to `True` +it causes the corresponding public API to use its new default behaviour. + +The following points apply in addition to those for removing a public +API: + + - You should add a new boolean attribute to :data:`iris.FUTURE` (by + modifying :class:`iris.Future`) that controls the default behaviour + of the public API that needs updating. The initial state of the new + boolean attribute should be `False`. You should name the new boolean + attribute to indicate that setting it to `True` will select the new + default behaviour. + - You should include a reference to this :data:`iris.FUTURE` flag in your + deprecation warning and corresponding Sphinx deprecation directive. + + +Removing a deprecation +====================== + +When the time comes to make a new major release you should locate any +deprecated APIs within the code that satisfy the one release +minimum period described previously. Locating deprecated APIs can easily +be done by searching for the Sphinx deprecation directives and/or +deprecation warnings. + +Removing a public API +--------------------- + +The deprecated API should be removed and any corresponding documentation +and/or example code should be removed/updated as appropriate. + +.. _iris_developer_future: + +Changing a default +------------------ + + - You should update the initial state of the relevant boolean attribute + of :data:`iris.FUTURE` to `True`. + - You should deprecate setting the relevant boolean attribute of + :class:`iris.Future` in the same way as described in + :ref:`removing-a-public-api`. + + +.. rubric:: Footnotes + +.. [#public-api] A name without a leading underscore in any of its + components, with the exception of the :mod:`iris.experimental` and + :mod:`iris.tests` packages. + + Example public names are: + - `iris.this.` + - `iris.this.that` + + Example private names are: + - `iris._this` + - `iris.this._that` + - `iris._this.that` + - `iris._this._that` + - `iris.experimental.something` + - `iris.tests.get_data_path` diff --git a/docs/iris/src/developers_guide/documenting/index.rst b/docs/iris/src/developers_guide/documenting/index.rst index 9b46682b33..b30a16b2a6 100644 --- a/docs/iris/src/developers_guide/documenting/index.rst +++ b/docs/iris/src/developers_guide/documenting/index.rst @@ -7,3 +7,4 @@ docstrings.rst rest_guide.rst + whats_new_contributions.rst diff --git a/docs/iris/src/developers_guide/documenting/whats_new_contributions.rst b/docs/iris/src/developers_guide/documenting/whats_new_contributions.rst new file mode 100644 index 0000000000..203a422457 --- /dev/null +++ b/docs/iris/src/developers_guide/documenting/whats_new_contributions.rst @@ -0,0 +1,123 @@ +.. _whats_new_contributions: + +================================= +Contributing a "What's New" entry +================================= + +Iris has an aggregator for building a draft what's new document for each +release. The draft what's new document is built from contributions by code authors. +This means contributions to the what's new document are written by the +developer most familiar with the change made. + +A contribution provides an entry in the what's new document, which describes a +change that improved Iris in some way. This change may be a new feature in Iris +or the fix for a bug introduced in a previous release. The contribution should +be included as part of the Iris Pull Request that introduces the change. + +When a new release is prepared, the what's new contributions are combined into +a draft what's new document for the release. + + +Writing a Contribution +====================== + +As introduced above, a contribution is the description of a change to Iris +which improved Iris in some way. As such, a single Iris Pull Request may +contain multiple changes that are worth highlighting as contributions to the +what's new document. + +Each contribution will ideally be written as a single concise bullet point. +The content of the bullet point should highlight the change that has been made +to Iris, targeting an Iris user as the audience. + +A contribution is a feature summary by the code author, which avoids the +release developer having to personally review the change in detail : +It is not in itself the final documentation content, +so it does not have to be perfect or complete in every respect. + + +Adding Contribution Files +========================= + +Each release must have a directory called ``contributions_``, +which should be created following the release of the current version of Iris. Each +release directory must be placed in ``docs/iris/src/whatsnew/``. +Contributions to the what's new must be written in markdown and placed into this +directory in text files. The filename for each item should be structured as follows: + +``__.txt`` + +Category +-------- +The category must be one of the following: + +*newfeature* + Features that are new or changed to add functionality. +*bugfix* + A bugfix. +*incompatiblechange* + A change that causes an incompatibility with prior versions of Iris. +*deprecate* + Deprecations of functionality. +*docchange* + Changes to documentation. + +Date +---- + +The date must be a hyphen-separated date in the format of: + + * a four digit year, + * a three character month name, and + * a two digit day. + +For example: + + * 2012-Jan-30 + * 2014-May-03 + * 2015-Feb-19 + +Summary +------- + +The summary can be any remaining filename characters, and simply provides a +short identifying description of the change. + +For example: + + * whats-new-aggregator + * using_mo_pack + * correction-to-bilinear-regrid + * GRIB2_pdt11 + + +Complete Examples +----------------- + +Some sample what's new contribution filenames: + + * bugfix_2015-Aug-18_partial_pp_constraints.txt + * deprecate_2015-Nov-01_unit-module.txt + * incompatiblechange_2015-Oct-12_GRIB_optional_Python3_unavailable.txt + * newfeature_2015-Jul-03_pearsonr_rewrite.txt + +.. note:: + A test in the standard test suite ensures that all the contents of the + latest contributions directory conform to this naming scheme. + + +Compiling a Draft +================= + +Compiling a draft from the supplied contributions should be done when preparing +a release. Running ``docs/iris/src/whatsnew/aggregate_directory.py`` with the +release number as the argument will create a draft what's new with the name +``.rst`` file for the specified release, by aggregating the individual +contributions from the relevant folder. +Omitting the release number will build the latest version for which a +contributions folder is present. +This command fails if a file with the relevant name already exists. + +The resulting draft document is only a starting point, which the release +developer will then edit to produce the final 'What's new in Iris x.x' +documentation. diff --git a/docs/iris/src/developers_guide/gitwash/development_workflow.rst b/docs/iris/src/developers_guide/gitwash/development_workflow.rst index c752197a77..4da6b700ba 100644 --- a/docs/iris/src/developers_guide/gitwash/development_workflow.rst +++ b/docs/iris/src/developers_guide/gitwash/development_workflow.rst @@ -144,6 +144,12 @@ In more detail #. To push the changes up to your forked repo on github, do a ``git push`` (see `git push`_). +Testing your changes +==================== + +Once you are happy with your changes, work thorough the :ref:`pr_check` and make sure +your branch passess all the relevant tests. + Ask for your changes to be reviewed or merged ============================================= @@ -334,7 +340,7 @@ Rewriting commit history Do this only for your own feature branches. -There's an embarassing typo in a commit you made? Or perhaps the you +There's an embarrassing typo in a commit you made? Or perhaps the you made several false starts you would like the posterity not to see. This can be done via *interactive rebasing*. diff --git a/docs/iris/src/developers_guide/gitwash/following_latest.rst b/docs/iris/src/developers_guide/gitwash/following_latest.rst deleted file mode 100644 index 90e1d96f0d..0000000000 --- a/docs/iris/src/developers_guide/gitwash/following_latest.rst +++ /dev/null @@ -1,36 +0,0 @@ -.. _following-latest: - -============================= - Following the latest source -============================= - -These are the instructions if you just want to follow the latest -*iris* source, but you don't need to do any development for now. - -The steps are: - -* :ref:`install-git` -* get local copy of the `iris github`_ git repository -* update local copy from time to time - -Get the local copy of the code -============================== - -From the command line:: - - git clone git://github.com/SciTools/iris.git - -You now have a copy of the code tree in the new ``iris`` directory. - -Updating the code -================= - -From time to time you may want to pull down the latest code. Do this with:: - - cd iris - git pull - -The tree in ``iris`` will now have the latest changes from the initial -repository. - -.. include:: links.inc diff --git a/docs/iris/src/developers_guide/gitwash/git_install.rst b/docs/iris/src/developers_guide/gitwash/git_install.rst index 72a6b91175..3be5149b90 100644 --- a/docs/iris/src/developers_guide/gitwash/git_install.rst +++ b/docs/iris/src/developers_guide/gitwash/git_install.rst @@ -8,8 +8,8 @@ Overview ======== ================ ============= -Debian / Ubuntu ``sudo apt-get install git-core`` -Fedora ``sudo yum install git-core`` +Debian / Ubuntu ``sudo apt-get install git`` +Fedora ``sudo yum install git`` Windows Download and install msysGit_ OS X Use the git-osx-installer_ ================ ============= diff --git a/docs/iris/src/developers_guide/gitwash/git_resources.rst b/docs/iris/src/developers_guide/gitwash/git_resources.rst index ba7b275e05..d18b0ef48b 100644 --- a/docs/iris/src/developers_guide/gitwash/git_resources.rst +++ b/docs/iris/src/developers_guide/gitwash/git_resources.rst @@ -9,9 +9,9 @@ Tutorials and summaries * `github help`_ has an excellent series of how-to guides. * `learn.github`_ has an excellent series of tutorials -* The `pro git book`_ is a good in-depth book on git. +* The `pro git book`_ is a good in-depth book on git. * A `git cheat sheet`_ is a page giving summaries of common commands. -* The `git user manual`_ +* The `git user manual`_ * The `git tutorial`_ * The `git community book`_ * `git ready`_ |emdash| a nice series of tutorials diff --git a/docs/iris/src/developers_guide/gitwash/index.rst b/docs/iris/src/developers_guide/gitwash/index.rst index ab6437049d..35eee1944a 100644 --- a/docs/iris/src/developers_guide/gitwash/index.rst +++ b/docs/iris/src/developers_guide/gitwash/index.rst @@ -10,8 +10,6 @@ Contents: git_intro git_install - following_latest - patching git_development git_resources diff --git a/docs/iris/src/developers_guide/gitwash/known_projects.inc b/docs/iris/src/developers_guide/gitwash/known_projects.inc index 2972352877..1761d975aa 100644 --- a/docs/iris/src/developers_guide/gitwash/known_projects.inc +++ b/docs/iris/src/developers_guide/gitwash/known_projects.inc @@ -1,41 +1,41 @@ .. Known projects .. PROJECTNAME placeholders -.. _PROJECTNAME: http://neuroimaging.scipy.org -.. _`PROJECTNAME github`: http://github.com/nipy -.. _`PROJECTNAME mailing list`: http://projects.scipy.org/mailman/listinfo/nipy-devel +.. _PROJECTNAME: http://nipy.org +.. _`PROJECTNAME github`: https://github.com/nipy +.. _`PROJECTNAME mailing list`: https://mail.python.org/mailman/listinfo/neuroimaging .. numpy -.. _numpy: hhttp://numpy.scipy.org -.. _`numpy github`: http://github.com/numpy/numpy +.. _numpy: http://www.numpy.org +.. _`numpy github`: https://github.com/numpy/numpy .. _`numpy mailing list`: http://mail.scipy.org/mailman/listinfo/numpy-discussion .. scipy -.. _scipy: http://www.scipy.org -.. _`scipy github`: http://github.com/scipy/scipy +.. _scipy: https://www.scipy.org +.. _`scipy github`: https://github.com/scipy/scipy .. _`scipy mailing list`: http://mail.scipy.org/mailman/listinfo/scipy-dev .. nipy .. _nipy: http://nipy.org/nipy -.. _`nipy github`: http://github.com/nipy/nipy -.. _`nipy mailing list`: http://mail.scipy.org/mailman/listinfo/nipy-devel +.. _`nipy github`: https://github.com/nipy/nipy +.. _`nipy mailing list`: https://mail.python.org/mailman/listinfo/neuroimaging .. ipython -.. _ipython: http://ipython.scipy.org -.. _`ipython github`: http://github.com/ipython/ipython +.. _ipython: https://ipython.org +.. _`ipython github`: https://github.com/ipython/ipython .. _`ipython mailing list`: http://mail.scipy.org/mailman/listinfo/IPython-dev .. dipy .. _dipy: http://nipy.org/dipy -.. _`dipy github`: http://github.com/Garyfallidis/dipy -.. _`dipy mailing list`: http://mail.scipy.org/mailman/listinfo/nipy-devel +.. _`dipy github`: https://github.com/Garyfallidis/dipy +.. _`dipy mailing list`: https://mail.python.org/mailman/listinfo/neuroimaging .. nibabel .. _nibabel: http://nipy.org/nibabel -.. _`nibabel github`: http://github.com/nipy/nibabel -.. _`nibabel mailing list`: http://mail.scipy.org/mailman/listinfo/nipy-devel +.. _`nibabel github`: https://github.com/nipy/nibabel +.. _`nibabel mailing list`: https://mail.python.org/mailman/listinfo/neuroimaging .. marsbar .. _marsbar: http://marsbar.sourceforge.net -.. _`marsbar github`: http://github.com/matthew-brett/marsbar +.. _`marsbar github`: https://github.com/matthew-brett/marsbar .. _`MarsBaR mailing list`: https://lists.sourceforge.net/lists/listinfo/marsbar-users diff --git a/docs/iris/src/developers_guide/gitwash/patching.rst b/docs/iris/src/developers_guide/gitwash/patching.rst deleted file mode 100644 index 85bde9fea6..0000000000 --- a/docs/iris/src/developers_guide/gitwash/patching.rst +++ /dev/null @@ -1,134 +0,0 @@ -================ - Making a patch -================ - -You've discovered a bug or something else you want to change -in `iris`_ .. |emdash| excellent! - -You've worked out a way to fix it |emdash| even better! - -You want to tell us about it |emdash| best of all! - -The easiest way is to make a *patch* or set of patches. Here -we explain how. Making a patch is the simplest and quickest, -but if you're going to be doing anything more than simple -quick things, please consider following the -:ref:`git-development` model instead. - -.. _making-patches: - -Making patches -============== - -Overview --------- - -:: - - # tell git who you are - git config --global user.email you@yourdomain.example.com - git config --global user.name "Your Name Comes Here" - # get the repository if you don't have it - git clone git://github.com/SciTools/iris.git - # make a branch for your patching - cd iris - git branch the-fix-im-thinking-of - git checkout the-fix-im-thinking-of - # hack, hack, hack - # Tell git about any new files you've made - git add somewhere/tests/test_my_bug.py - # commit work in progress as you go - git commit -am 'BF - added tests for Funny bug' - # hack hack, hack - git commit -am 'BF - added fix for Funny bug' - # make the patch files - git format-patch -M -C master - -Then, send the generated patch files to the `iris -mailing list`_ |emdash| where we will thank you warmly. - -In detail ---------- - -#. Tell git who you are so it can label the commits you've - made:: - - git config --global user.email you@yourdomain.example.com - git config --global user.name "Your Name Comes Here" - -#. If you don't already have one, clone a copy of the - `iris`_ repository:: - - git clone git://github.com/SciTools/iris.git - cd iris - -#. Make a 'feature branch'. This will be where you work on - your bug fix. It's nice and safe and leaves you with - access to an unmodified copy of the code in the main - branch:: - - git branch the-fix-im-thinking-of - git checkout the-fix-im-thinking-of - -#. Do some edits, and commit them as you go:: - - # hack, hack, hack - # Tell git about any new files you've made - git add somewhere/tests/test_my_bug.py - # commit work in progress as you go - git commit -am 'BF - added tests for Funny bug' - # hack hack, hack - git commit -am 'BF - added fix for Funny bug' - - Note the ``-am`` options to ``commit``. The ``m`` flag just - signals that you're going to type a message on the command - line. The ``a`` flag |emdash| you can just take on faith |emdash| - or see `why the -a flag?`_. - -#. When you have finished, check you have committed all your - changes:: - - git status - -#. Finally, make your commits into patches. You want all the - commits since you branched from the ``master`` branch:: - - git format-patch -M -C master - - You will now have several files named for the commits:: - - 0001-BF-added-tests-for-Funny-bug.patch - 0002-BF-added-fix-for-Funny-bug.patch - - Send these files to the `iris mailing list`_. - -When you are done, to switch back to the main copy of the -code, just return to the ``master`` branch:: - - git checkout master - -Moving from patching to development -=================================== - -If you find you have done some patches, and you have one or -more feature branches, you will probably want to switch to -development mode. You can do this with the repository you -have. - -Fork the `iris`_ repository on github |emdash| :ref:`forking`. -Then:: - - # checkout and refresh master branch from main repo - git checkout master - git pull origin master - # rename pointer to main repository to 'upstream' - git remote rename origin upstream - # point your repo to default read / write to your fork on github - git remote add origin git@github.com:your-user-name/iris.git - # push up any branches you've made and want to keep - git push origin the-fix-im-thinking-of - -Then you can, if you want, follow the -:ref:`development-workflow`. - -.. include:: links.inc diff --git a/docs/iris/src/developers_guide/gitwash/this_project.inc b/docs/iris/src/developers_guide/gitwash/this_project.inc index a8cae31d22..38219bf4b4 100644 --- a/docs/iris/src/developers_guide/gitwash/this_project.inc +++ b/docs/iris/src/developers_guide/gitwash/this_project.inc @@ -2,4 +2,4 @@ .. _`iris`: http://scitools.org.uk/iris .. _`iris github`: http://github.com/SciTools/iris -.. _`iris mailing list`: http://scitools.org.uk/mailman/listinfo +.. _`iris mailing list`: https://groups.google.com/forum/#!forum/scitools-iris diff --git a/docs/iris/src/developers_guide/gitwash_build.sh b/docs/iris/src/developers_guide/gitwash_build.sh index 1041007cdc..e1c4cdb2af 100755 --- a/docs/iris/src/developers_guide/gitwash_build.sh +++ b/docs/iris/src/developers_guide/gitwash_build.sh @@ -5,4 +5,4 @@ echo echo "Building gitwash ..." echo -python gitwash_dumper.py --repo-name=iris --github-user=SciTools --gitwash-url=https://github.com/matthew-brett/gitwash.git --project-url=http://scitools.org.uk/iris --project-ml-url=http://scitools.org.uk/mailman/listinfo ./ iris +python gitwash_dumper.py --repo-name=iris --github-user=SciTools --gitwash-url=https://github.com/matthew-brett/gitwash.git --project-url=http://scitools.org.uk/iris --project-ml-url=https://groups.google.com/forum/#!forum/scitools-iris ./ iris diff --git a/docs/iris/src/developers_guide/gitwash_dumper.py b/docs/iris/src/developers_guide/gitwash_dumper.py index 71370e3a91..999a738fa6 100644 --- a/docs/iris/src/developers_guide/gitwash_dumper.py +++ b/docs/iris/src/developers_guide/gitwash_dumper.py @@ -1,6 +1,9 @@ #!/usr/bin/env python ''' Checkout gitwash repo into directory and do search replace on name ''' +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + import os from os.path import join as pjoin import shutil @@ -54,16 +57,19 @@ def filename_search_replace(sr_pairs, filename, backup=False): ''' Search and replace for expressions in files ''' - in_txt = open(filename, 'rt').read(-1) + with open(filename, 'rt') as in_fh: + in_txt = in_fh.read(-1) out_txt = in_txt[:] for in_exp, out_exp in sr_pairs: in_exp = re.compile(in_exp) out_txt = in_exp.sub(out_exp, out_txt) if in_txt == out_txt: return False - open(filename, 'wt').write(out_txt) + with open(filename, 'wt') as out_fh: + out_fh.write(out_txt) if backup: - open(filename + '.bak', 'wt').write(in_txt) + with open(filename + '.bak', 'wt') as bak_fh: + bak_fh.write(in_txt) return True @@ -79,7 +85,7 @@ def copy_replace(replace_pairs, for rep_glob in rep_globs: fnames += fnmatch.filter(out_fnames, rep_glob) if verbose: - print '\n'.join(fnames) + print('\n'.join(fnames)) for fname in fnames: filename_search_replace(replace_pairs, fname, False) for in_exp, out_exp in renames: @@ -114,7 +120,8 @@ def make_link_targets(proj_name, .. _`proj_name`: url .. _`proj_name` mailing list: url """ - link_contents = open(known_link_fname, 'rt').readlines() + with open(known_link_fname, 'rt') as link_fh: + link_contents = link_fh.readlines() have_url = not url is None have_ml_url = not ml_url is None have_gh_url = None @@ -147,9 +154,8 @@ def make_link_targets(proj_name, return # A neat little header line lines = ['.. %s\n' % proj_name] + lines - out_links = open(out_link_fname, 'wt') - out_links.writelines(lines) - out_links.close() + with open(out_link_fname, 'wt') as out_links: + out_links.writelines(lines) USAGE = ''' diff --git a/docs/iris/src/developers_guide/graphics_tests.rst b/docs/iris/src/developers_guide/graphics_tests.rst new file mode 100644 index 0000000000..684ccfa4ab --- /dev/null +++ b/docs/iris/src/developers_guide/graphics_tests.rst @@ -0,0 +1,117 @@ +.. _developer_graphics_tests: + +Graphics tests +************** + +The only practical way of testing plotting functionality is to check actual +output plots. +For this, a basic 'graphics test' assertion operation is provided in the method +:meth:`iris.tests.IrisTest.check_graphic` : This tests plotted output for a +match against a stored reference. +A "graphics test" is any test which employs this. + +At present (Iris version 1.10), such tests include the testing for modules +`iris.tests.test_plot` and `iris.tests.test_quickplot`, and also some other +'legacy' style tests (as described in :ref:`developer_tests`). +It is conceivable that new 'graphics tests' of this sort can still be added. +However, as graphics tests are inherently "integration" style rather than true +unit tests, results can differ with the installed versions of dependent +libraries (see below), so this is not recommended except where no alternative +is practical. + +Testing actual plot results introduces some significant difficulties : + * Graphics tests are inherently 'integration' style tests, so results will + often vary with the versions of key dependencies, i.e. the exact versions of + third-party modules which are installed : Obviously, results will depend on + the matplotlib version, but they can also depend on numpy and other + installed packages. + * Although it seems possible in principle to accommodate 'small' result changes + by distinguishing plots which are 'nearly the same' from those which are + 'significantly different', in practice no *automatic* scheme for this can be + perfect : That is, any calculated tolerance in output matching will allow + some changes which a human would judge as a significant error. + * Storing a variety of alternative 'acceptable' results as reference images + can easily lead to uncontrolled increases in the size of the repository, + given multiple independent sources of variation. + + +Graphics Testing Strategy +========================= + +Prior to Iris 1.10, all graphics tests compared against a stored reference +image with a small tolerance on pixel values. + +From Iris v1.11 onward, we want to support testing Iris against multiple +versions of matplotlib (and some other dependencies). +To make this manageable, we have now rewritten "check_graphic" to allow +multiple alternative 'correct' results without including many more images in +the Iris repository. +This consists of : + + * using a perceptual 'image hash' of the outputs (see + https://github.com/JohannesBuchner/imagehash) as the basis for checking + test results. + * storing the hashes of 'known accepted results' for each test in a + database in the repo (which is actually stored in + ``lib/iris/tests/results/imagerepo.json``). + * storing associated reference images for each hash value in a separate public + repository, currently in https://github.com/SciTools/test-images-scitools , + allowing human-eye judgement of 'valid equivalent' results. + * a new version of the 'iris/tests/idiff.py' assists in comparing proposed + new 'correct' result images with the existing accepted ones. + +BRIEF... +There should be sufficient work-flow detail here to allow an iris developer to: + + * understand the new check graphic test process + * understand the steps to take and tools to use to add a new graphic test + * understand the steps to take and tools to use to diagnose and fix an graphic test failure + + +Basic workflow +============== + +If you notice that a graphics test in the Iris testing suite has failed +following changes in Iris or any of its dependencies, this is the process +you now need to follow: + +#. Create a directory in iris/lib/iris/tests called 'result_image_comparison'. +#. From your Iris root directory, run the tests by using the command: + ``python setup.py test``. +#. Navigate to iris/lib/iris/tests and run the command: ``python idiff.py``. + This will open a window for you to visually inspect the changes to the + graphic and then either accept or reject the new result. +#. Upon acceptance of a change or a new image, a copy of the output PNG file + is added to the reference image repository in + https://github.com/SciTools/test-images-scitools. The file is named + according to the image hash value, as ``.png``. +#. The hash value of the new result is added into the relevant set of 'valid + result hashes' in the image result database file, + ``tests/results/imagerepo.json``. +#. The tests must now be re-run, and the 'new' result should be accepted. + Occasionally there are several graphics checks in a single test, only the + first of which will be run should it fail. If this is the case, then you + may well encounter further graphical test failures in your next runs, and + you must repeat the process until all the graphical tests pass. +#. To add your changes to Iris, you need to make two pull requests. The first + should be made to the test-images-scitools repository, and this should + contain all the newly-generated png files copied into the folder named + 'image_files'. +#. The second pull request should be created in the Iris repository, and should + only include the change to the image results database + (``tests/results/imagerepo.json``) : + This pull request must contain a reference to the matching one in + test-images-scitools. + +Note: the Iris pull-request will not test out successfully in Travis until the +test-images-scitools pull request has been merged : This is because there is +an Iris test which ensures the existence of the reference images (uris) for all +the targets in the image results database. + + +Fixing a failing graphics test +============================== + + +Adding a new graphics test +========================== diff --git a/docs/iris/src/developers_guide/index.rst b/docs/iris/src/developers_guide/index.rst index 62ce6e2327..a1ecd0756f 100644 --- a/docs/iris/src/developers_guide/index.rst +++ b/docs/iris/src/developers_guide/index.rst @@ -36,3 +36,5 @@ gitwash/index.rst pulls.rst tests.rst + deprecations.rst + release.rst diff --git a/docs/iris/src/developers_guide/pulls.rst b/docs/iris/src/developers_guide/pulls.rst index f2828dff7c..6546a15642 100644 --- a/docs/iris/src/developers_guide/pulls.rst +++ b/docs/iris/src/developers_guide/pulls.rst @@ -1,3 +1,5 @@ +.. _pr_check: + Pull Request Check List *********************** @@ -16,56 +18,99 @@ is merged. Before submitting a pull request please consider this list. The Iris Check List ==================== -* Have you provided a helpful description of the Pull Request? What has - changed and why. This should include: - * the aim of the change - the problem addressed, a link to the issue; - * how the change has been delivered. +* Have you provided a helpful description of the Pull Request? + I.E. what has changed and why. This should include: -* Do new files pass PEP8? - * PEP8_ is the Python source code style guide. - * There is a python module for checking pep8 compliance: python-pep8_ + * the aim of the change ; the problem addressed ; a link to the issue. + * how the change has been delivered. + * a "What's New" entry, submitted as a new file added in the pull request. + See `Contributing a "What's New" entry`_. * Do all the tests pass locally? + * The Iris tests may be run with ``python setup.py test`` which has a command line utility included. - * Coding standards, including PEP8_ compliance and copyright message (including - the correct year of the latest change), are tested. -* Has a new test been provided? +* Have new tests been provided for all additional functionality? + +* Do all modified and new sourcefiles pass PEP8? + + * PEP8_ is the Python source code style guide. + * There is a python module for checking pep8 compliance: python-pep8_ + * a standard Iris test checks that all sourcefiles meet PEP8 compliance + (see "iris.tests.test_coding_standards.TestCodeFormat"). + +* Do all modified and new sourcefiles have a correct, up-to-date copyright + header? + + * a standard Iris test checks that all sourcefiles include a copyright + message, including the correct year of the latest change + (see "iris.tests.test_coding_standards.TestLicenseHeaders"). -* Has iris-test-data been updated? - * iris-test-data_ is a github project containing all the data to support the - tests. - * If this has been updated a reference to the relevant pull request should be - provided. +* Has the documentation been updated to explain all new or changed features? -* Has the the documentation been updated to explain the new feature or bug fix? - * with reference to the developer guide on docstrings_ + * refer to the developer guide on docstrings_ -* Have code examples been provided inside the relevant docstrings? +* Have code examples been provided inside docstrings, where relevant? -* Has iris-sample-data been updated? - * iris-sample-data_ is a github project containing all the data to support - the gallery and examples. + * these are strongly recommended as concrete (working) examples always + considerably enhance the documentation. + + * live test code can be included in docstrings. + + * See for example :data:`iris.cube.Cube.data` + * Details at http://www.sphinx-doc.org/en/stable/ext/doctest.html + + * The documentation tests may be run with ``make doctest``, from within the + ``./docs/iris`` subdirectory. + +* Have you provided a 'whats new' contribution? + + * this should be done for all changes that affect API or behaviour. + See :ref:`whats_new_contributions` * Does the documentation build without errors? + * The documentation is built using ``make html`` in ``./docs/iris``. -* Do the documentation tests pass? - * ``make doctest``, ``make extest`` in ``./docs/iris``. +* Do the documentation and code-example tests pass? -* Is there an associated iris-code-generators pull request? - * iris-code-generators_ is a github project which provides processes for - generating a small subset of the Iris source code files from other - information sources. + * Run with ``make doctest`` and ``make extest``, from within the subdirectory + ``./docs/iris``. + * note that code examples must *not* raise deprecations. This is now checked + and will result in an error. + When an existing code example encounters a deprecation, it must be fixed. * Has the travis file been updated to reflect any dependency updates? + * ``./.travis.yml`` is used to manage the continuous integration testing. + * the files ``./conda-requirements.yml`` and + ``./minimal-conda-requirements.yml`` are used to define the software + environments used, using the conda_ package manager. + +* Have you provided updates to supporting projects for test or example data? + + * the following separate repos are used to manage larger files used by tests + and code examples : + + * iris-test-data_ is a github project containing all the data to support the + tests. + * iris-sample-data_ is a github project containing all the data to support + the gallery and examples. + * test-images-scitools_ is a github project containing reference plot images + to support iris graphics tests : see :ref:`developer_graphics_tests`. + + * If new files are required by tests or code examples, they must be added to + the appropriate supporting project via a suitable pull-request. + This new 'supporting pull request' should be referenced in the main Iris + pull request, and must be accepted and merged before the Iris one can be. .. _PEP8: http://www.python.org/dev/peps/pep-0008/ .. _python-pep8: https://pypi.python.org/pypi/pep8 +.. _conda: http://conda.readthedocs.io/en/latest/ .. _iris-test-data: https://github.com/SciTools/iris-test-data .. _iris-sample-data: https://github.com/SciTools/iris-sample-data -.. _iris-code-generators: https://github.com/SciTools/iris-code-generators +.. _test-images-scitools: https://github.com/SciTools/test-images-scitools .. _docstrings: http://scitools.org.uk/iris/docs/latest/developers_guide/documenting/docstrings.html +.. _Contributing a "What's New" entry: http://scitools.org.uk/iris/docs/latest/developers_guide/documenting/whats_new_contributions.html diff --git a/docs/iris/src/developers_guide/release.rst b/docs/iris/src/developers_guide/release.rst new file mode 100644 index 0000000000..437478a6a0 --- /dev/null +++ b/docs/iris/src/developers_guide/release.rst @@ -0,0 +1,75 @@ +.. _iris_development_releases: + +Releases +******** + +A release of Iris is a tag on the SciTools/Iris Github repository. + +Release Branch +============== + +Once the features intended for the release are on master, a release branch should be created, in the SciTools/Iris repository. This will have the name: + + :literal:`{major release number}.{minor release number}.x` + +for example: + + :literal:`v1.9.x` + +This branch shall be used to finalise the release details in preparation for the release candidate. + +Release Candidate +================= + +Prior to a release, a release candidate tag may be created, marked as a pre-release in github, with a tag ending with :literal:`rc` followed by a number, e.g.: + + :literal:`v1.9.0rc1` + +If created, the pre-release shall be available for at least one week prior to the release being cut. User groups should be notified of the existence of the pre-release and encouraged to test the functionality. + +A pre-release is expected for a minor release, but not normally provided for a point release. + +If new features are required for a release after a release candidate has been cut, a new pre-release shall be issued first. + +Documentation +============= + +The documentation should include all of the what's new snippets, which must be compiled into a what's new. This content should be reviewed and adapted as required and the snippets removed from the branch to produce a coherent what's new page. + +Upon release, the documentation shall be added to the SciTools scitools.org.uk github project's gh-pages branch as the latest documentation. + +Testing the Conda Recipe +======================== + +Before a release is cut, the SciTools conda-recipes-scitools recipe for Iris shall be tested to build the release branch of Iris; this test recipe shall not be merged onto conda-recipes-scitools. + +The Release +=========== + +The final steps are to change the version string in the source of :literal:`Iris.__init__.py` and include the release date in the relevant what's new page within the documentation. + +Once all checks are complete, the release is cut by the creation of a new tag in the SciTools Iris repository. + +Conda Recipe +============ + +Once a release is cut, the SciTools conda-recipes-scitools recipe for Iris shall be updated to build the latest release of Iris and push this artefact to anaconda.org. The build and push is all automated as part of the merge process. + +Merge Back +========== + +After the release is cut, the changes shall be merged back onto the scitools master. + +To achieve this, first cut a local branch from the release branch, :literal:`{release}.x`. Next add a commit changing the release string to match the release string on scitools/master. +This branch can now be proposed as a pull request to master. This work flow ensures that the commit identifiers are consistent between the :literal:`.x` branch and :literal:`master`. + +Point Releases +============== + +Bug fixes may be implemented and targeted as the :literal:`.x` branch. These should lead to a new point release, another tag. +For example, a fix for a problem with 1.9.0 will be merged into 1.9.x, and then released by tagging 1.9.1. + +New features shall not be included in a point release, these are for bug fixes. + +A point release does not require a release candidate, but the rest of the release process is to be followed, including the merge back of changes into :literal:`master`. + diff --git a/docs/iris/src/developers_guide/tests.rst b/docs/iris/src/developers_guide/tests.rst index 4ad9e0de0b..929073b569 100644 --- a/docs/iris/src/developers_guide/tests.rst +++ b/docs/iris/src/developers_guide/tests.rst @@ -1,6 +1,11 @@ +.. _developer_tests: + Testing ******* +The Iris tests may be run with ``python setup.py test`` which has a +command line utility included. + There are three categories of tests within Iris: - Unit tests - Integration tests @@ -125,3 +130,25 @@ developers locate relevant tests. It is recommended they are named according to the capabilities under test, e.g. `metadata/test_pp_preservation.py`, and not named according to the module(s) under test. + + +Graphics tests +================= +Certain Iris tests are based on checking plotted images. +This the only way of testing the modules :mod:`iris.plot` and +:mod:`iris.quickplot`, but is also used for some other legacy and integration- +style testcases. + +Prior to Iris version 1.10, a single reference image for each testcase was +stored in the main Iris repository, and a 'tolerant' comparison was performed +against this. + +From version 1.11 onwards, graphics testcase outputs are compared against +possibly *multiple* known-good images, of which only the signature is stored. +This uses a sophisticated perceptual "image hashing" scheme (see: +). +Only imagehash signatures are stored in the Iris repo itself, thus freeing up +valuable space. Meanwhile, the actual reference *images* -- which are required +for human-eyes evaluation of proposed new "good results" -- are all stored +elsewhere in a separate public repository. +See :ref:`developer_graphics_tests`. diff --git a/docs/iris/src/installing.rst b/docs/iris/src/installing.rst index fc563bc094..6b6999ab82 100644 --- a/docs/iris/src/installing.rst +++ b/docs/iris/src/installing.rst @@ -1,3 +1,5 @@ +.. _installing_iris: + **************** Installing Iris **************** diff --git a/docs/iris/src/sphinxext/auto_label_figures.py b/docs/iris/src/sphinxext/auto_label_figures.py new file mode 100644 index 0000000000..00f3aa96dc --- /dev/null +++ b/docs/iris/src/sphinxext/auto_label_figures.py @@ -0,0 +1,39 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import os +from docutils import nodes + + +def auto_label_figures(app, doctree): + """ + Add a label on every figure. + """ + + for fig in doctree.traverse(condition=nodes.figure): + for img in fig.traverse(condition=nodes.image): + fname, ext = os.path.splitext(img['uri']) + if ext == '.png': + fname = os.path.basename(fname).replace('_', '-') + fig['ids'].append(fname) + + +def setup(app): + app.connect('doctree-read', auto_label_figures) diff --git a/docs/iris/src/sphinxext/custom_class_autodoc.py b/docs/iris/src/sphinxext/custom_class_autodoc.py index af2bd1ec27..af8309b2d3 100644 --- a/docs/iris/src/sphinxext/custom_class_autodoc.py +++ b/docs/iris/src/sphinxext/custom_class_autodoc.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -15,6 +15,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa from sphinx.ext import autodoc from sphinx.ext.autodoc import * @@ -26,23 +28,12 @@ class ClassWithConstructorDocumenter(autodoc.ClassDocumenter): priority = 1000000 def get_object_members(self, want_all): - r,f = autodoc.ClassDocumenter.get_object_members(self, want_all) - #print 'CALLED OBJECT MEMBERS....', r, f - return r, f - -# def filter_members(self, members, want_all): -# res = autodoc.ClassDocumenter.filter_members(self, members, want_all) -# for (membername, member) in members: -# if membername in ['__init__', '__new__']: -# # final argument is "isattr" - no its not an attribute it is a contructor method. -# res.insert(0, [membername, member, False]) -# return res + return autodoc.ClassDocumenter.get_object_members(self, want_all) @staticmethod def can_document_member(member, mname, isattr, self): - #print ' asked me if I can document....', member, mname, isattr, self - #print ' gave them :', autodoc.ClassDocumenter.can_document_member(member, mname, isattr, self) - return autodoc.ClassDocumenter.can_document_member(member, mname, isattr, self) + return autodoc.ClassDocumenter.can_document_member(member, mname, + isattr, self) def get_doc(self, encoding=None): content = self.env.config.autoclass_content @@ -57,7 +48,7 @@ def get_doc(self, encoding=None): if content in ('both', 'init'): constructor = self.get_constructor() if constructor: - initdocstring = self.get_attr( constructor, '__doc__', None) + initdocstring = self.get_attr(constructor, '__doc__', None) else: initdocstring = None if initdocstring: @@ -74,22 +65,21 @@ def get_constructor(self): initmeth = self.get_attr(self.object, '__new__', None) if initmeth is None or initmeth is object.__new__ or not \ - (inspect.ismethod(initmeth) or inspect.isfunction(initmeth)): - initmeth = None + (inspect.ismethod(initmeth) or inspect.isfunction(initmeth)): + initmeth = None if initmeth is None: initmeth = self.get_attr(self.object, '__init__', None) - if initmeth is None or initmeth is object.__init__ or initmeth is object.__new__ or not \ - (inspect.ismethod(initmeth) or inspect.isfunction(initmeth)): + if initmeth is None or initmeth is object.__init__ or \ + initmeth is object.__new__ or not \ + (inspect.ismethod(initmeth) or inspect.isfunction(initmeth)): initmeth = None return initmeth - def format_args(self): initmeth = self.get_constructor() - #print 'DOING FORMAT ARGS: ', initmeth, self.object try: argspec = inspect.getargspec(initmeth) except TypeError: diff --git a/docs/iris/src/sphinxext/custom_data_autodoc.py b/docs/iris/src/sphinxext/custom_data_autodoc.py new file mode 100644 index 0000000000..29a4fda94c --- /dev/null +++ b/docs/iris/src/sphinxext/custom_data_autodoc.py @@ -0,0 +1,62 @@ +# (C) British Crown Copyright 2010 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +from sphinx.ext.autodoc import DataDocumenter, ModuleLevelDocumenter +try: + # Use 'object_description' in place of the former 'safe_repr' function. + from sphinx.util.inspect import object_description as safe_repr +except ImportError: + # 'safe_repr' is the old usage, for Sphinx<1.3. + from sphinx.util.inspect import safe_repr + +from iris.analysis import Aggregator + + +class IrisDataDocumenter(DataDocumenter): + priority = 100 + + def add_directive_header(self, sig): + ModuleLevelDocumenter.add_directive_header(self, sig) + if not self.options.annotation: + try: + objrepr = safe_repr(self.object) + except ValueError: + pass + else: + self.add_line(u' :annotation:', '') + elif self.options.annotation is object(): + pass + else: + self.add_line( + u' :annotation: {}'.format(self.options.annotation), + '') + + +def handler(app, what, name, obj, options, signature, return_annotation): + if what == 'data': + if isinstance(obj, object) and issubclass(obj.__class__, Aggregator): + signature = '()' + return_annotation = '{} instance.'.format(obj.__class__.__name__) + return signature, return_annotation + + +def setup(app): + app.add_autodocumenter(IrisDataDocumenter) + app.connect('autodoc-process-signature', handler) diff --git a/docs/iris/src/sphinxext/gen_example_directory.py b/docs/iris/src/sphinxext/gen_example_directory.py index 46107b602b..60863010c5 100644 --- a/docs/iris/src/sphinxext/gen_example_directory.py +++ b/docs/iris/src/sphinxext/gen_example_directory.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -16,23 +16,28 @@ # along with Iris. If not, see . -""" +''' Generate the rst files for the examples -""" +''' + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + import os import re +import shutil import sys def out_of_date(original, derived): - """ + ''' Returns True if derivative is out-of-date wrt original, both of which are full file paths. - TODO: this check isn't adequate in some cases. Eg, if we discover + TODO: this check isn't adequate in some cases, e.g., if we discover a bug when building the examples, the original and derived will be unchanged but we still want to force a rebuild. - """ + ''' return (not os.path.exists(derived) or os.stat(derived).st_mtime < os.stat(original).st_mtime) @@ -40,14 +45,15 @@ def out_of_date(original, derived): docstring_regex = re.compile(r'[\'\"]{3}(.*?)[\'\"]{3}', re.DOTALL) -noplot_regex = re.compile(r"#\s*-\*-\s*noplot\s*-\*-") +noplot_regex = re.compile(r'#\s*-\*-\s*noplot\s*-\*-') def generate_example_rst(app): - # example code can be found at the same level as the documentation src folder + # Example code can be found at the same level as the documentation + # src folder. rootdir = os.path.join(os.path.dirname(app.builder.srcdir), 'example_code') - # examples are build as a subfolder of the src folder + # Examples are built as a subfolder of the src folder. exampledir = os.path.join(app.builder.srcdir, 'examples') if not os.path.exists(exampledir): @@ -56,28 +62,29 @@ def generate_example_rst(app): datad = {} for root, subFolders, files in os.walk(rootdir): for fname in files: - if ( fname.startswith('.') or fname.startswith('#') or fname.startswith('_') or - fname.find('.svn')>=0 or not fname.endswith('.py') ): + if (fname.startswith('.') or fname.startswith('#') or + fname.startswith('_') or fname.find('.svn') >= 0 or + not fname.endswith('.py')): continue - fullpath = os.path.join(root,fname) - contents = file(fullpath).read() + fullpath = os.path.join(root, fname) + with open(fullpath) as fh: + contents = fh.read() # indent relpath = os.path.split(root)[-1] datad.setdefault(relpath, []).append((fullpath, fname, contents)) - subdirs = datad.keys() - subdirs.sort() + subdirs = sorted(datad.keys()) - fhindex = file(os.path.join(exampledir, 'index.rst'), 'w') - fhindex.write("""\ + index = [] + index.append('''\ Iris examples ============= .. toctree:: :maxdepth: 2 -""") +''') for subdir in subdirs: rstdir = os.path.join(exampledir, subdir) @@ -92,79 +99,84 @@ def generate_example_rst(app): if not os.path.exists(outputdir): os.makedirs(outputdir) - subdirIndexFile = os.path.join(rstdir, 'index.rst') - fhsubdirIndex = file(subdirIndexFile, 'w') - fhindex.write(' %s/index.rst\n\n' % subdir) - + index.append(' {}/index.rst\n'.format(subdir)) subdir_root_path = os.path.join(rootdir, subdir) + subdirIndex = [] - # use the __init__.py file's docstring for the subdir example page (if __init__ exists) + # Use the __init__.py file's docstring for the subdir example page (if + # __init__ exists). if os.path.exists(os.path.join(subdir_root_path, '__init__.py')): import imp - mod = imp.load_source(subdir, os.path.join(subdir_root_path, '__init__.py')) - fhsubdirIndex.writelines(mod.__doc__) + mod = imp.load_source( + subdir, + os.path.join(subdir_root_path, '__init__.py')) + subdirIndex.append(mod.__doc__) else: - fhsubdirIndex.writelines(['Examples in %s\n' % subdir, '='*50]) - - # append the code to produce the toctree - fhsubdirIndex.write("""\ + line = 'Examples in {}\n'.format(subdir) + subdirIndex.extend([line, '=' * len(line)]) + # Append the code to produce the toctree. + subdirIndex.append(''' .. toctree:: :maxdepth: 1 -""") +''') - sys.stdout.write(subdir + ", ") + sys.stdout.write(subdir + ', ') sys.stdout.flush() - data = datad[subdir] - data.sort() + data = sorted(datad[subdir]) for fullpath, fname, contents in data: basename, ext = os.path.splitext(fname) outputfile = os.path.join(outputdir, fname) - #thumbfile = os.path.join(thumb_dir, '%s.png'%basename) - #print ' static_dir=%s, basename=%s, fullpath=%s, fname=%s, thumb_dir=%s, thumbfile=%s'%(static_dir, basename, fullpath, fname, thumb_dir, thumbfile) - rstfile = '%s.rst'%basename + rstfile = '{}.rst'.format(basename) outrstfile = os.path.join(rstdir, rstfile) - fhsubdirIndex.write(' %s\n'%rstfile) + subdirIndex.append(' {}\n'.format(rstfile)) if not out_of_date(fullpath, outrstfile): continue - fh = file(outrstfile, 'w') - fh.write('.. _%s-%s:\n\n'%(subdir, basename)) + out = [] + out.append('.. _{}-{}:\n\n'.format(subdir, basename)) + + # Copy the example code to be in the src examples directory. This + # means we can define a simple relative path in the plot directive, + # which can also copy the file into the resulting build directory. + shutil.copy(fullpath, rstdir) docstring_results = docstring_regex.search(contents) if docstring_results is not None: - fh.write( docstring_results.group(1) ) + out.append(docstring_results.group(1)) else: - title = '%s example code: %s'%(subdir, fname) - #title = ' %s example code: %s'%(thumbfile, subdir, fname) - fh.write(title + '\n') - fh.write('='*len(title) + '\n\n') + title = '{} example code: {}'.format(subdir, fname) + out.append(title + '\n') + out.append('=' * len(title) + '\n\n') if not noplot_regex.search(contents): - fh.write("\n\n.. plot:: %s\n\n::\n\n" % fullpath) + rel_example = os.path.relpath(outputfile, app.builder.outdir) + out.append('\n\n.. plot:: {}\n'.format(rel_example)) + out.append(' :include-source:\n\n') else: - fh.write("[`source code <%s>`_]\n\n::\n\n" % fname) - # write the py file contents (we didnt need to do this for plot as the plot directive does this for us. - fhstatic = file(outputfile, 'w') - fhstatic.write(contents) - fhstatic.close() + out.append('[`source code <{}>`_]\n\n'.format(fname)) + out.append('.. literalinclude:: {}\n\n'.format(fname)) + # Write the .py file contents (we didn't need to do this for + # plots as the plot directive does this for us.) + with open(outputfile, 'w') as fhstatic: + fhstatic.write(contents) - # indent the contents - contents = '\n'.join([' %s'%row.rstrip() for row in contents.split('\n')]) - fh.write(contents) - fh.write('\n\n\n\n\n') + with open(outrstfile, 'w') as fh: + fh.writelines(out) - fh.close() + subdirIndexFile = os.path.join(rstdir, 'index.rst') + with open(subdirIndexFile, 'w') as fhsubdirIndex: + fhsubdirIndex.writelines(subdirIndex) - fhsubdirIndex.close() + with open(os.path.join(exampledir, 'index.rst'), 'w') as fhindex: + fhindex.writelines(index) - fhindex.close() def setup(app): app.connect('builder-inited', generate_example_rst) diff --git a/docs/iris/src/sphinxext/gen_gallery.py b/docs/iris/src/sphinxext/gen_gallery.py index 109280fa2d..1dabf919f7 100644 --- a/docs/iris/src/sphinxext/gen_gallery.py +++ b/docs/iris/src/sphinxext/gen_gallery.py @@ -1,62 +1,125 @@ # -# (C) Copyright 2010 MATPLOTLIB (vn 1.0.1) +# (C) Copyright 2012 MATPLOTLIB (vn 1.2.0) # -# generate a thumbnail gallery of examples -template = """\ -{%% extends "layout.html" %%} -{%% set title = "Thumbnail gallery" %%} +''' +Generate a thumbnail gallery of examples. +''' + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import os +import glob +import re +import warnings + +import matplotlib.image as image +from sphinx.util import status_iterator + +from sphinx.util import status_iterator +template = '''\ +{{% extends "layout.html" %}} +{{% set title = "Thumbnail gallery" %}} -{%% block body %%} + +{{% block body %}}

Click on any image to see full size image and source code


-%s -{%% endblock %%} -""" + -import os, glob, re, warnings -import matplotlib.image as image +{} +{{% endblock %}} +''' + +multiimage = re.compile('(.*?)(_\d\d){1,2}') -multiimage = re.compile('(.*)_\d\d') def make_thumbnail(args): image.thumbnail(args[0], args[1], 0.4) + def out_of_date(original, derived): return (not os.path.exists(derived) or os.stat(derived).st_mtime < os.stat(original).st_mtime) + def gen_gallery(app, doctree): if app.builder.name != 'html': return outdir = app.builder.outdir + rootdir = 'examples' - rootdir = os.path.join('plot_directive','example_code') - - # images we want to skip for the gallery because they are an unusual + # Images we want to skip for the gallery because they are an unusual # size that doesn't layout well in a table, or because they may be - # redundant with other images or uninteresting + # redundant with other images or uninteresting. skips = set([ 'mathtext_examples', 'matshow_02', 'matshow_03', - 'matplotlib_icon', - ]) + 'matplotlib_icon']) - data = [] thumbnails = {} + rows = [] + random_image = [] + toc_rows = [] + + link_template = ('' + '{alternative_text}' + '') + + header_template = ('
' + '

{}' + '' + '

') + + toc_template = ('
  • ' + '{}' + '
  • ') + + random_image_content_template = ''' +// This file was automatically generated by gen_gallery.py & should not be +// modified directly. + +images = new Array(); + +{} + +''' + + random_image_template = "['{thumbfile}', '{full_image}', '{link}'];" + random_image_join = 'images[{}] = {}' + + dirs = ('General', 'Meteorology', 'Oceanography') + + for subdir in dirs: + rows.append(header_template.format(subdir, subdir, subdir)) + toc_rows.append(toc_template.format(subdir, subdir)) - for subdir in ('graphics', ): origdir = os.path.join(os.path.dirname(outdir), rootdir, subdir) + if not os.path.exists(origdir): + origdir = os.path.join(os.path.dirname(outdir), 'plot_directive', + rootdir, subdir) thumbdir = os.path.join(outdir, rootdir, subdir, 'thumbnails') if not os.path.exists(thumbdir): os.makedirs(thumbdir) + + data = [] + for filename in sorted(glob.glob(os.path.join(origdir, '*.png'))): - if filename.endswith("hires.png"): + if filename.endswith('hires.png'): continue path, filename = os.path.split(filename) @@ -64,85 +127,78 @@ def gen_gallery(app, doctree): if basename in skips: continue - # Create thumbnails based on images in tmpdir, and place - # them within the build tree + # Create thumbnails based on images in tmpdir, and place them + # within the build tree. orig_path = str(os.path.join(origdir, filename)) thumb_path = str(os.path.join(thumbdir, filename)) if out_of_date(orig_path, thumb_path) or True: thumbnails[orig_path] = thumb_path m = multiimage.match(basename) - if m is None: - pyfile = '%s.py'%basename - else: + if m is not None: basename = m.group(1) - pyfile = '%s.py'%basename data.append((subdir, basename, - os.path.join(rootdir, subdir, 'thumbnails', filename))) - - link_template = """\ - %(alternative_text)s - """ - - random_image_content_template = ''' -// This file was automatically generated by gen_gallery.py & should not be modified directly. - -images = new Array(); - -%s - -''' - - random_image_template = "['%(thumbfile)s', '%(full_image)s', '%(link)s', 'Iris examples.'];" - random_image_join = 'images[%s] = %s' - - if len(data) == 0: - warnings.warn("No thumbnails were found") - return - - rows = [] - random_image = [] - for (subdir, basename, thumbfile) in data: - if thumbfile is not None: - link = 'examples/%s/%s.html#%s'%(subdir, basename, os.path.splitext(os.path.basename(thumbfile))[0].replace('_', '-')) - rows.append(link_template % {'href': link, 'thumb_file': thumbfile, 'alternative_text': basename}) - random_image.append(random_image_template % {'link':link, 'thumbfile':thumbfile, 'basename':basename, 'full_image':'_images/' + os.path.basename(thumbfile)} ) - - random_image_content = random_image_content_template % '\n'.join([random_image_join % (i, line) for i, line in enumerate(random_image)]) - random_image_script_path = os.path.join(app.builder.srcdir, '_static', 'random_image.js') - file(random_image_script_path, 'w').write(random_image_content) - + os.path.join(rootdir, subdir, 'thumbnails', + filename))) + + for (subdir, basename, thumbfile) in data: + if thumbfile is not None: + anchor = os.path.basename(thumbfile) + anchor = os.path.splitext(anchor)[0].replace('_', '-') + link = 'examples/{}/{}.html#{}'.format( + subdir, + basename, + anchor) + rows.append(link_template.format( + href=link, + thumb_file=thumbfile, + alternative_text=basename)) + random_image.append(random_image_template.format( + link=link, + thumbfile=thumbfile, + basename=basename, + full_image='_images/' + os.path.basename(thumbfile))) + + if len(data) == 0: + warnings.warn('No thumbnails were found in {}'.format(subdir)) + + # Close out the
    opened up at the top of this loop. + rows.append('
    ') + + # Generate JS list of images for front page. + random_image_content = '\n'.join([random_image_join.format(i, line) + for i, line in enumerate(random_image)]) + random_image_content = random_image_content_template.format( + random_image_content) + random_image_script_path = os.path.join(app.builder.srcdir, + '_static', + 'random_image.js') + with open(random_image_script_path, 'w') as fh: + fh.write(random_image_content) + + content = template.format('\n'.join(toc_rows), + '\n'.join(rows)) # Only write out the file if the contents have actually changed. - # Otherwise, this triggers a full rebuild of the docs - content = template%'\n'.join(rows) - gallery_path = os.path.join(app.builder.srcdir, '_templates', 'gallery.html') + # Otherwise, this triggers a full rebuild of the docs. + + gallery_path = os.path.join(app.builder.srcdir, + '_templates', + 'gallery.html') if os.path.exists(gallery_path): - fh = file(gallery_path, 'r') - regenerate = fh.read() != content - fh.close() + with open(gallery_path, 'r') as fh: + regenerate = fh.read() != content else: regenerate = True if regenerate: - fh = file(gallery_path, 'w') - fh.write(content) - fh.close() - - try: - import multiprocessing - app.builder.info("generating thumbnails... ", nonl=True) - pool = multiprocessing.Pool() - pool.map(make_thumbnail, thumbnails.iteritems()) - pool.close() - pool.join() - app.builder.info("done") - - except ImportError: - for key in app.builder.status_iterator( - thumbnails.iterkeys(), "generating thumbnails... ", - length=len(thumbnails)): - image.thumbnail(key, thumbnails[key], 0.3) + with open(gallery_path, 'w') as fh: + fh.write(content) + + for key in status_iterator(thumbnails, 'generating thumbnails... ', + length=len(thumbnails)): + image.thumbnail(key, thumbnails[key], 0.3) + def setup(app): app.connect('env-updated', gen_gallery) diff --git a/docs/iris/src/sphinxext/gen_rst.py b/docs/iris/src/sphinxext/gen_rst.py deleted file mode 100644 index b640f60bf4..0000000000 --- a/docs/iris/src/sphinxext/gen_rst.py +++ /dev/null @@ -1,147 +0,0 @@ -# -# (C) Copyright 2010 MATPLOTLIB (vn 1.0.1) -# -""" -generate the rst files for the examples by iterating over the pylab examples -""" -import os -import re -import sys -fileList = [] - -def out_of_date(original, derived): - """ - Returns True if derivative is out-of-date wrt original, - both of which are full file paths. - - TODO: this check isn't adequate in some cases. Eg, if we discover - a bug when building the examples, the original and derived will be - unchanged but we still want to force a rebuild. - """ - return (not os.path.exists(derived) or - os.stat(derived).st_mtime < os.stat(original).st_mtime) - -noplot_regex = re.compile(r"#\s*-\*-\s*noplot\s*-\*-") - -def generate_example_rst(app): - rootdir = os.path.join(os.path.dirname(app.builder.srcdir), 'example_code') - exampledir = os.path.join(app.builder.srcdir, 'examples') - if not os.path.exists(exampledir): - os.makedirs(exampledir) - - datad = {} - for root, subFolders, files in os.walk(rootdir): - for fname in files: - if ( fname.startswith('.') or fname.startswith('#') or fname.startswith('_') or - fname.find('.svn')>=0 or not fname.endswith('.py') ): - continue - - fullpath = os.path.join(root,fname) - contents = file(fullpath).read() - # indent - relpath = os.path.split(root)[-1] - datad.setdefault(relpath, []).append((fullpath, fname, contents)) - - subdirs = datad.keys() - subdirs.sort() - - fhindex = file(os.path.join(exampledir, 'index.rst'), 'w') - fhindex.write("""\ -.. _examples-index: - -#################### -Iris Examples -#################### - -.. toctree:: - :maxdepth: 2 - -""") - - for subdir in subdirs: - rstdir = os.path.join(exampledir, subdir) - if not os.path.exists(rstdir): - os.makedirs(rstdir) - - outputdir = os.path.join(app.builder.outdir, 'examples') - if not os.path.exists(outputdir): - os.makedirs(outputdir) - - outputdir = os.path.join(outputdir, subdir) - if not os.path.exists(outputdir): - os.makedirs(outputdir) - - subdirIndexFile = os.path.join(rstdir, 'index.rst') - fhsubdirIndex = file(subdirIndexFile, 'w') - fhindex.write(' %s/index.rst\n\n'%subdir) - - fhsubdirIndex.write("""\ -.. _%s-examples-index: - -############################################## -%s Examples -############################################## - -.. toctree:: - :maxdepth: 1 - -"""%(subdir, subdir)) - - sys.stdout.write(subdir + ", ") - sys.stdout.flush() - - data = datad[subdir] - data.sort() - - for fullpath, fname, contents in data: - basename, ext = os.path.splitext(fname) - outputfile = os.path.join(outputdir, fname) - #thumbfile = os.path.join(thumb_dir, '%s.png'%basename) - #print ' static_dir=%s, basename=%s, fullpath=%s, fname=%s, thumb_dir=%s, thumbfile=%s'%(static_dir, basename, fullpath, fname, thumb_dir, thumbfile) - - rstfile = '%s.rst'%basename - outrstfile = os.path.join(rstdir, rstfile) - - fhsubdirIndex.write(' %s\n'%rstfile) - - if not out_of_date(fullpath, outrstfile): - continue - - fh = file(outrstfile, 'w') - fh.write('.. _%s-%s:\n\n'%(subdir, basename)) - title = '%s example code: %s'%(subdir, fname) - #title = ' %s example code: %s'%(thumbfile, subdir, fname) - - - fh.write(title + '\n') - fh.write('='*len(title) + '\n\n') - - do_plot = (subdir in ('graphics', - ) and - not noplot_regex.search(contents)) - - if do_plot: - fh.write("\n\n.. plot:: %s\n\n::\n\n" % fullpath) - else: - fh.write("[`source code <%s>`_]\n\n::\n\n" % fname) - fhstatic = file(outputfile, 'w') - fhstatic.write(contents) - fhstatic.close() - - # indent the contents - contents = '\n'.join([' %s'%row.rstrip() for row in contents.split('\n')]) - fh.write(contents) - - #fh.write('\n\nKeywords: python, matplotlib, pylab, example, codex (see :ref:`how-to-search-examples`)') - fh.write('\n\n') - - fh.close() - - fhsubdirIndex.close() - - fhindex.close() - - print - -def setup(app): - app.connect('builder-inited', generate_example_rst) diff --git a/docs/iris/src/sphinxext/generate_package_rst.py b/docs/iris/src/sphinxext/generate_package_rst.py index 41ba121978..f67efc7ebc 100644 --- a/docs/iris/src/sphinxext/generate_package_rst.py +++ b/docs/iris/src/sphinxext/generate_package_rst.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -15,6 +15,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa import os import sys @@ -23,187 +25,289 @@ document_dict = { - # Use autoclass for classes - 'class': ''' -%(object_docstring)s + # Use autoclass for classes. + 'class': ''' +{object_docstring} .. - .. autoclass:: %(object_name)s + .. autoclass:: {object_name} :members: :undoc-members: + :inherited-members: ''', - 'function': ''' -.. autofunction:: %(object_name)s + 'function': ''' +.. autofunction:: {object_name} ''', - # For everything else, let automodule do some magic... - None: ''' + # For everything else, let automodule do some magic... + None: ''' -.. autodata:: %(object_name)s +.. autodata:: {object_name} '''} -def lookup_object_type(obj): - if inspect.isclass(obj): - return 'class' - elif inspect.isfunction(obj): - return 'function' - else: - return None +horizontal_sep = ''' +.. raw:: html +

    ↑ top ↑

    + - tmp = '' - for element, obj in document_these: - tmp += '----------\n' + document_dict[lookup_object_type(obj)] % {'object_name': import_name + '.' + element, - 'object_name_header_line':'+' * len(import_name + '.' + element), - 'object_docstring': inspect.getdoc(obj), - } +''' - module_elements = '\n'.join([' * :py:obj:`%s`' % (element) for element, obj in document_these]) +def lookup_object_type(obj): + if inspect.isclass(obj): + return 'class' + elif inspect.isfunction(obj): + return 'function' + else: + return None + - tmp = r'''.. _%(import_name)s: +def auto_doc_module(file_path, import_name, root_package, + package_toc=None, title=None): + doc = r'''.. _{import_name}: -%(title_underline)s -%(title)s -%(title_underline)s +{title_underline} +{title} +{title_underline} -%(sidebar)s +{sidebar} -.. currentmodule:: %(root_package)s +.. currentmodule:: {root_package} -.. automodule:: %(import_name)s +.. automodule:: {import_name} In this module: -%(module_elements)s +{module_elements} -''' + tmp +''' if package_toc: - sidebar = """ + sidebar = ''' .. sidebar:: Modules in this package -%(package_toc_tree)s +{package_toc_tree} - """ % {'package_toc_tree': package_toc} + '''.format(package_toc_tree=package_toc) else: - sidebar = '' + sidebar = '' + + try: + mod = __import__(import_name) + except ImportError as e: + message = r'''.. error:: + + This module could not be imported. Some dependencies are missing:: + + ''' + str(e) + return doc.format(title=title or import_name, + title_underline='=' * len(title or import_name), + import_name=import_name, root_package=root_package, + sidebar=sidebar, module_elements=message) + + mod = sys.modules[import_name] + elems = dir(mod) + + if '__all__' in elems: + document_these = [(attr_name, getattr(mod, attr_name)) + for attr_name in mod.__all__] + else: + document_these = [(attr_name, getattr(mod, attr_name)) + for attr_name in elems + if (not attr_name.startswith('_') and + not inspect.ismodule(getattr(mod, attr_name)))] + + def is_from_this_module(arg): + name = arg[0] + obj = arg[1] + return (hasattr(obj, '__module__') and + obj.__module__ == mod.__name__) + + sort_order = {'class': 2, 'function': 1} + + # Sort them according to sort_order dict. + def sort_key(arg): + name = arg[0] + obj = arg[1] + return sort_order.get(lookup_object_type(obj), 0) + + document_these = filter(is_from_this_module, document_these) + document_these = sorted(document_these, key=sort_key) - return tmp % {'title': title or import_name, 'title_underline': '=' * len(title or import_name), 'import_name': import_name, 'root_package':root_package, 'sidebar':sidebar, 'module_elements': module_elements} + lines = [] + for element, obj in document_these: + object_name = import_name + '.' + element + obj_content = document_dict[lookup_object_type(obj)].format( + object_name=object_name, + object_name_header_line='+' * len(object_name), + object_docstring=inspect.getdoc(obj)) + lines.append(obj_content) + + lines = horizontal_sep.join(lines) + + module_elements = '\n'.join(' * :py:obj:`{}`'.format(element) + for element, obj in document_these) + + lines = doc + lines + return lines.format(title=title or import_name, + title_underline='=' * len(title or import_name), + import_name=import_name, root_package=root_package, + sidebar=sidebar, module_elements=module_elements) def auto_doc_package(file_path, import_name, root_package, sub_packages): + max_depth = 1 if import_name == 'iris' else 2 package_toc = '\n '.join(sub_packages) package_toc = ''' .. toctree:: - :maxdepth: 2 + :maxdepth: {:d} :titlesonly: - %s + {} -''' % package_toc +'''.format(max_depth, package_toc) if '.' in import_name: title = None else: title = import_name.capitalize() + ' reference documentation' - return auto_doc_module(file_path, import_name, root_package, package_toc=package_toc, title=title) + return auto_doc_module(file_path, import_name, root_package, + package_toc=package_toc, title=title) def auto_package_build(app): - root_package = app.config.autopackage_name if root_package is None: - raise ValueError('set the autopackage_name variable in the conf.py file') + raise ValueError('set the autopackage_name variable in the ' + 'conf.py file') if not isinstance(root_package, list): - raise ValueError("autopackage was expecting a list of packages to document e.g. ['itertools']") + raise ValueError('autopackage was expecting a list of packages to ' + 'document e.g. ["itertools"]') for package in root_package: do_package(package) def do_package(package_name): - out_dir = package_name + os.path.sep - # import the root package. If this fails then an import error will be raised. + # Import the root package. If this fails then an import error will be + # raised. module = __import__(package_name) root_package = package_name rootdir = os.path.dirname(module.__file__) - package_folder = [] module_folders = {} for root, subFolders, files in os.walk(rootdir): for fname in files: name, ext = os.path.splitext(fname) - # skip some non-relevant files - if ( fname.startswith('.') or fname.startswith('#') or re.search("^_[^_]", fname) or - fname.find('.svn')>=0 or not (ext in ['.py', '.so']) ): + # Skip some non-relevant files. + if (fname.startswith('.') or fname.startswith('#') or + re.search('^_[^_]', fname) or fname.find('.svn') >= 0 or + not (ext in ['.py', '.so'])): continue - rel_path = root_package + os.path.join(root, fname).split(rootdir)[-1] - mod_folder = root_package + os.path.join(root).split(rootdir)[-1].replace('/','.') + # Handle new shared library naming conventions + if ext == '.so': + name = name.split('.', 1)[0] + + rel_path = root_package + \ + os.path.join(root, fname).split(rootdir)[-1] + mod_folder = root_package + \ + os.path.join(root).split(rootdir)[-1].replace('/', '.') - # only add to package folder list if it contains an __init__ script + # Only add this package to folder list if it contains an __init__ + # script. if name == '__init__': package_folder.append([mod_folder, rel_path]) else: import_name = mod_folder + '.' + name - module_folders.setdefault(mod_folder, []).append([import_name, rel_path]) + mf_list = module_folders.setdefault(mod_folder, []) + mf_list.append((import_name, rel_path)) if not os.path.exists(out_dir): os.makedirs(out_dir) for package, package_path in package_folder: - if '._' in package or 'test' in package: + if '._' in package or 'test' in package: continue - sub_packages = (spackage for spackage, spackage_path in package_folder if spackage != package and spackage.startswith(package)) - paths = [os.path.join(*spackage.rsplit('.', 2)[-2:None])+'.rst' for spackage in sub_packages] - paths.extend( [os.path.join(os.path.basename(os.path.dirname(path)), os.path.splitext(os.path.basename(path))[0]) for imp_name, path in module_folders.get(package, [])]) - paths.sort() - doc = auto_doc_package(package_path, package, root_package, paths) - - package_dir = out_dir + package.replace('.', os.path.sep) - if not os.path.exists(package_dir): - os.makedirs(out_dir + package.replace('.', os.path.sep)) - - out_path = package_dir + '.rst' - if not os.path.exists(out_path) or doc != ''.join(file(out_path, 'r').readlines()): - print 'creating out of date/non-existant document %s' % out_path - file(out_path, 'w').write(doc) - - for import_name, module_path in module_folders.get(package, []): - doc = auto_doc_module(module_path, import_name, root_package) - out_path = out_dir + import_name.replace('.', os.path.sep) + '.rst' - if not os.path.exists(out_path) or doc != ''.join(file(out_path, 'r').readlines()): - print 'creating out of date/non-existant document %s' % out_path - file(out_path, 'w').write(doc) + paths = [] + for spackage, spackage_path in package_folder: + # Ignore this packages, packages that are not children of this + # one, test packages, private packages, and packages that are + # subpackages of subpackages (they'll be part of the subpackage). + if spackage == package: + continue + if not spackage.startswith(package): + continue + if spackage.count('.') > package.count('.') + 1: + continue + if 'test' in spackage: + continue + + split_path = spackage.rsplit('.', 2)[-2:] + if any(part[0] == '_' for part in split_path): + continue + + paths.append(os.path.join(*split_path) + '.rst') + + paths.extend(os.path.join(os.path.basename(os.path.dirname(path)), + os.path.basename(path).split('.', 1)[0]) + for imp_name, path in module_folders.get(package, [])) + + paths.sort() + doc = auto_doc_package(package_path, package, root_package, paths) + + package_dir = out_dir + package.replace('.', os.path.sep) + if not os.path.exists(package_dir): + os.makedirs(out_dir + package.replace('.', os.path.sep)) + + out_path = package_dir + '.rst' + if not os.path.exists(out_path): + print('Creating non-existent document {} ...'.format(out_path)) + with open(out_path, 'w') as fh: + fh.write(doc) + else: + with open(out_path, 'r') as fh: + existing_content = ''.join(fh.readlines()) + if doc != existing_content: + print('Creating out of date document {} ...'.format( + out_path)) + with open(out_path, 'w') as fh: + fh.write(doc) + + for import_name, module_path in module_folders.get(package, []): + doc = auto_doc_module(module_path, import_name, root_package) + out_path = out_dir + import_name.replace('.', os.path.sep) + '.rst' + if not os.path.exists(out_path): + print('Creating non-existent document {} ...'.format( + out_path)) + with open(out_path, 'w') as fh: + fh.write(doc) + else: + with open(out_path, 'r') as fh: + existing_content = ''.join(fh.readlines()) + if doc != existing_content: + print('Creating out of date document {} ...'.format( + out_path)) + with open(out_path, 'w') as fh: + fh.write(doc) def setup(app): diff --git a/docs/iris/src/sphinxext/plot_directive.py b/docs/iris/src/sphinxext/plot_directive.py deleted file mode 100644 index 7c54b8edaf..0000000000 --- a/docs/iris/src/sphinxext/plot_directive.py +++ /dev/null @@ -1,513 +0,0 @@ -# -# (C) Copyright 2010 MATPLOTLIB (vn 1.0.1) -# - -"""A special directive for including a matplotlib plot. - -The source code for the plot may be included in one of two ways: - - 1. A path to a source file as the argument to the directive:: - - .. plot:: path/to/plot.py - - When a path to a source file is given, the content of the - directive may optionally contain a caption for the plot:: - - .. plot:: path/to/plot.py - - This is the caption for the plot - - Additionally, one my specify the name of a function to call (with - no arguments) immediately after importing the module:: - - .. plot:: path/to/plot.py plot_function1 - - 2. Included as inline content to the directive:: - - .. plot:: - - import matplotlib.pyplot as plt - import matplotlib.image as mpimg - import numpy as np - img = mpimg.imread('_static/stinkbug.png') - imgplot = plt.imshow(img) - -In HTML output, `plot` will include a .png file with a link to a high-res -.png and .pdf. In LaTeX output, it will include a .pdf. - -To customize the size of the plot, this directive supports all of the -options of the `image` directive, except for `target` (since plot will -add its own target). These include `alt`, `height`, `width`, `scale`, -`align` and `class`. - -Additionally, if the `:include-source:` option is provided, the -literal source will be displayed inline in the text, (as well as a -link to the source in HTML). If this source file is in a non-UTF8 or -non-ASCII encoding, the encoding must be specified using the -`:encoding:` option. - -The set of file formats to generate can be specified with the -`plot_formats` configuration variable. - - -Error handling: - -Any errors generated during the running of the code are emitted as warnings -using the Python `warnings` module, using a custom category called -`PlotWarning`. To turn the warnings into fatal errors that stop the -documentation build, after adjusting your `sys.path` in your `conf.py` Sphinx -configuration file, use:: - - import plot_directive - warnings.simplefilter('error', plot_directive.PlotWarning) -""" - -import sys, os, shutil, imp, warnings, cStringIO, re -try: - from hashlib import md5 -except ImportError: - from md5 import md5 - -from docutils.parsers.rst import directives -try: - # docutils 0.4 - from docutils.parsers.rst.directives.images import align -except ImportError: - # docutils 0.5 - from docutils.parsers.rst.directives.images import Image - align = Image.align -import sphinx - -sphinx_version = sphinx.__version__.split(".") -# The split is necessary for sphinx beta versions where the string is -# '6b1' -sphinx_version = tuple([int(re.split('[a-z]', x)[0]) - for x in sphinx_version[:2]]) - -import matplotlib -import matplotlib.cbook as cbook -matplotlib.use('Agg') -import matplotlib.pyplot as plt -import matplotlib.image as image -from matplotlib import _pylab_helpers - - -class PlotWarning(Warning): - """Warning category for all warnings generated by this directive. - - By printing our warnings with this category, it becomes possible to turn - them into errors by using in your conf.py:: - - warnings.simplefilter('error', plot_directive.PlotWarning) - - This way, you can ensure that your docs only build if all your examples - actually run successfully. - """ - pass - - -# os.path.relpath is new in Python 2.6 -if hasattr(os.path, 'relpath'): - relpath = os.path.relpath -else: - # This code is snagged from Python 2.6 - - def relpath(target, base=os.curdir): - """ - Return a relative path to the target from either the current dir or an optional base dir. - Base can be a directory specified either as absolute or relative to current dir. - """ - - if not os.path.exists(target): - raise OSError, 'Target does not exist: '+target - - if not os.path.isdir(base): - raise OSError, 'Base is not a directory or does not exist: '+base - - base_list = (os.path.abspath(base)).split(os.sep) - target_list = (os.path.abspath(target)).split(os.sep) - - # On the windows platform the target may be on a completely - # different drive from the base. - if os.name in ['nt','dos','os2'] and base_list[0] <> target_list[0]: - raise OSError, 'Target is on a different drive to base. Target: '+target_list[0].upper()+', base: '+base_list[0].upper() - - # Starting from the filepath root, work out how much of the - # filepath is shared by base and target. - for i in range(min(len(base_list), len(target_list))): - if base_list[i] <> target_list[i]: break - else: - # If we broke out of the loop, i is pointing to the first - # differing path elements. If we didn't break out of the - # loop, i is pointing to identical path elements. - # Increment i so that in all cases it points to the first - # differing path elements. - i+=1 - - rel_list = [os.pardir] * (len(base_list)-i) + target_list[i:] - if rel_list: - return os.path.join(*rel_list) - else: - return "" - -template = """ -.. htmlonly:: - - %(links)s - - .. figure:: %(prefix)s%(tmpdir)s/%(outname)s.png -%(options)s - -%(caption)s - -.. latexonly:: - .. figure:: %(prefix)s%(tmpdir)s/%(outname)s.pdf -%(options)s - -%(caption)s - -""" - -exception_template = """ -.. htmlonly:: - - [`source code <%(linkdir)s/%(basename)s.py>`__] - -Exception occurred rendering plot. - -""" - -template_content_indent = ' ' - -def out_of_date(original, derived): - """ - Returns True if derivative is out-of-date wrt original, - both of which are full file paths. - """ - return (not os.path.exists(derived) or - (os.path.exists(original) and - os.stat(derived).st_mtime < os.stat(original).st_mtime)) - -def run_code(plot_path, function_name, plot_code): - """ - Import a Python module from a path, and run the function given by - name, if function_name is not None. - """ - # Change the working directory to the directory of the example, so - # it can get at its data files, if any. Add its path to sys.path - # so it can import any helper modules sitting beside it. - if plot_code is not None: -# exec_code = 'import numpy as np; import matplotlib.pyplot as plt\n%s'%plot_code - exec_code = plot_code - exec(exec_code) - else: - pwd = os.getcwd() - path, fname = os.path.split(plot_path) - sys.path.insert(0, os.path.abspath(path)) - stdout = sys.stdout - sys.stdout = cStringIO.StringIO() - os.chdir(path) - fd = None - try: - fd = open(fname) - module = imp.load_module( - "__main__", fd, fname, ('py', 'r', imp.PY_SOURCE)) - finally: - del sys.path[0] - os.chdir(pwd) - sys.stdout = stdout - if fd is not None: - fd.close() - - if function_name is not None: - getattr(module, function_name)() - -def run_savefig(plot_path, basename, tmpdir, destdir, formats): - """ - Once a plot script has been imported, this function runs savefig - on all of the figures in all of the desired formats. - """ - fig_managers = _pylab_helpers.Gcf.get_all_fig_managers() - for i, figman in enumerate(fig_managers): - for j, (format, dpi) in enumerate(formats): - if len(fig_managers) == 1: - outname = basename - else: - outname = "%s_%02d" % (basename, i) - outname = outname + "." + format - outpath = os.path.join(tmpdir, outname) - try: - figman.canvas.figure.savefig(outpath, dpi=dpi) - except: - s = cbook.exception_to_str("Exception saving plot %s" % plot_path) - warnings.warn(s, PlotWarning) - return 0 - if j > 0: - shutil.copyfile(outpath, os.path.join(destdir, outname)) - - return len(fig_managers) - -def clear_state(): - plt.close('all') - matplotlib.rcdefaults() - # Set a default figure size that doesn't overflow typical browser - # windows. The script is free to override it if necessary. - matplotlib.rcParams['figure.figsize'] = (8, 6.5) - -def render_figures(plot_path, function_name, plot_code, tmpdir, destdir, - formats): - """ - Run a pyplot script and save the low and high res PNGs and a PDF - in outdir. - """ - plot_path = str(plot_path) # todo, why is unicode breaking this - basedir, fname = os.path.split(plot_path) - basename, ext = os.path.splitext(fname) - - all_exists = True - - # Look for single-figure output files first - for format, dpi in formats: - outname = os.path.join(tmpdir, '%s.%s' % (basename, format)) - if out_of_date(plot_path, outname): - all_exists = False - break - - if all_exists: - return 1 - - # Then look for multi-figure output files, assuming - # if we have some we have all... - i = 0 - while True: - all_exists = True - for format, dpi in formats: - outname = os.path.join( - tmpdir, '%s_%02d.%s' % (basename, i, format)) - if out_of_date(plot_path, outname): - all_exists = False - break - if all_exists: - i += 1 - else: - break - - if i != 0: - return i - - # We didn't find the files, so build them - - clear_state() - try: - run_code(plot_path, function_name, plot_code) - except: - s = cbook.exception_to_str("Exception running plot %s" % plot_path) - warnings.warn(s, PlotWarning) - return 0 - - num_figs = run_savefig(plot_path, basename, tmpdir, destdir, formats) - - if '__plot__' in sys.modules: - del sys.modules['__plot__'] - - return num_figs - -def _plot_directive(plot_path, basedir, function_name, plot_code, caption, - options, state_machine): - formats = setup.config.plot_formats - if type(formats) == str: - formats = eval(formats) - - fname = os.path.basename(plot_path) - basename, ext = os.path.splitext(fname) - - # Get the directory of the rst file, and determine the relative - # path from the resulting html file to the plot_directive links - # (linkdir). This relative path is used for html links *only*, - # and not the embedded image. That is given an absolute path to - # the temporary directory, and then sphinx moves the file to - # build/html/_images for us later. - rstdir, rstfile = os.path.split(state_machine.document.attributes['source']) - outdir = os.path.join('plot_directive', basedir) - reldir = relpath(setup.confdir, rstdir) - linkdir = os.path.join(reldir, outdir) - - # tmpdir is where we build all the output files. This way the - # plots won't have to be redone when generating latex after html. - - # Prior to Sphinx 0.6, absolute image paths were treated as - # relative to the root of the filesystem. 0.6 and after, they are - # treated as relative to the root of the documentation tree. We - # need to support both methods here. - tmpdir = os.path.join('build', outdir) - tmpdir = os.path.join(os.path.dirname(setup.app.builder.outdir), 'plot_directive') - tmpdir = os.path.join(tmpdir, outdir) - tmpdir = os.path.abspath(tmpdir) - if sphinx_version < (0, 6): - prefix = '' - else: - prefix = '/' - if not os.path.exists(tmpdir): - cbook.mkdirs(tmpdir) - - # destdir is the directory within the output to store files - # that we'll be linking to -- not the embedded images. - destdir = os.path.abspath(os.path.join(setup.app.builder.outdir, outdir)) - if not os.path.exists(destdir): - cbook.mkdirs(destdir) - - # Properly indent the caption - caption = '\n'.join(template_content_indent + line.strip() - for line in caption.split('\n')) - - # Generate the figures, and return the number of them - num_figs = render_figures(plot_path, function_name, plot_code, tmpdir, - destdir, formats) - - # Now start generating the lines of output - lines = [] - - if plot_code is None: - shutil.copyfile(plot_path, os.path.join(destdir, fname)) - - if options.has_key('include-source'): - if plot_code is None: - if sphinx_version > (1,): - include_prefix = '/' - else: - include_prefix = setup.app.builder.srcdir - - lines.extend( - ['.. include:: %s' % os.path.join(include_prefix, plot_path), - ' :literal:']) - if options.has_key('encoding'): - lines.append(' :encoding: %s' % options['encoding']) - del options['encoding'] - else: - lines.extend(['::', '']) - lines.extend([' %s' % row.rstrip() - for row in plot_code.split('\n')]) - lines.append('') - del options['include-source'] - else: - lines = [] - - if num_figs > 0: - options = ['%s:%s: %s' % (template_content_indent, key, val) - for key, val in options.items()] - options = "\n".join(options) - - for i in range(num_figs): - if num_figs == 1: - outname = basename - else: - outname = "%s_%02d" % (basename, i) - - # Copy the linked-to files to the destination within the build tree, - # and add a link for them - links = [] - for format, dpi in formats[1:]: - links.append('`%s <%s/%s.%s>`__' % (format, linkdir, outname, format)) - if plot_code is None: - links.append('`source code <%(linkdir)s/%(basename)s.py>`__') - if len(links): - links = ('.. _%s: \n\n' % outname) + '[%s]' % (', '.join(links) % locals()) - else: - links = '' - - lines.extend((template % locals()).split('\n')) - else: - lines.extend((exception_template % locals()).split('\n')) - - if len(lines): - state_machine.insert_input( - lines, state_machine.input_lines.source(0)) - - return [] - -def plot_directive(name, arguments, options, content, lineno, - content_offset, block_text, state, state_machine): - """ - Handle the arguments to the plot directive. The real work happens - in _plot_directive. - """ - # The user may provide a filename *or* Python code content, but not both - if len(arguments): - plot_path = directives.uri(arguments[0]) - basedir = relpath(os.path.dirname(plot_path), setup.app.builder.srcdir) - - # If there is content, it will be passed as a caption. - - # Indent to match expansion below. XXX - The number of spaces matches - # that of the 'options' expansion further down. This should be moved - # to common code to prevent them from diverging accidentally. - caption = '\n'.join(content) - - # If the optional function name is provided, use it - if len(arguments) == 2: - function_name = arguments[1] - else: - function_name = None - - return _plot_directive(plot_path, basedir, function_name, None, caption, - options, state_machine) - else: - plot_code = '\n'.join(content) - - # Since we don't have a filename, use a hash based on the content - plot_path = md5(plot_code).hexdigest()[-10:] - - return _plot_directive(plot_path, 'inline', None, plot_code, '', options, - state_machine) - -def mark_plot_labels(app, document): - """ - To make plots referenceable, we need to move the reference from - the "htmlonly" (or "latexonly") node to the actual figure node - itself. - """ - for name, explicit in document.nametypes.iteritems(): - if not explicit: - continue - labelid = document.nameids[name] - if labelid is None: - continue - node = document.ids[labelid] - if node.tagname in ('html_only', 'latex_only'): - for n in node: - if n.tagname == 'figure': - sectname = name - for c in n: - if c.tagname == 'caption': - sectname = c.astext() - break - - node['ids'].remove(labelid) - node['names'].remove(name) - n['ids'].append(labelid) - n['names'].append(name) - document.settings.env.labels[name] = \ - document.settings.env.docname, labelid, sectname - break - -def setup(app): - setup.app = app - setup.config = app.config - setup.confdir = app.confdir - - options = {'alt': directives.unchanged, - 'height': directives.length_or_unitless, - 'width': directives.length_or_percentage_or_unitless, - 'scale': directives.nonnegative_int, - 'align': align, - 'class': directives.class_option, - 'include-source': directives.flag, - 'encoding': directives.encoding } - - app.add_directive('plot', plot_directive, True, (0, 2, 0), **options) - app.add_config_value( - 'plot_formats', - [('png', 100), ('hires.png', 200), ('pdf', 250)], - True) - - app.connect('doctree-read', mark_plot_labels) diff --git a/docs/iris/src/userguide/change_management_goals.txt b/docs/iris/src/userguide/change_management_goals.txt new file mode 100644 index 0000000000..afed1ebb98 --- /dev/null +++ b/docs/iris/src/userguide/change_management_goals.txt @@ -0,0 +1,9 @@ +To reduce code maintenance problems to an absolute minimum, Iris applies +defined change management procedures to ensure that : + + * you can be confident that your code will still work with a future release + + * you will be aware of future incompatibility problems in advance + + * you can defer making code compatibility changes for some time, until it suits you + diff --git a/docs/iris/src/userguide/code_maintenance.rst b/docs/iris/src/userguide/code_maintenance.rst new file mode 100644 index 0000000000..00ba30506c --- /dev/null +++ b/docs/iris/src/userguide/code_maintenance.rst @@ -0,0 +1,60 @@ +Code Maintenance +================ + +From a user point of view "code maintenance" means ensuring that your existing +working code stays working, in the face of changes to Iris. + + +Stability and Change +--------------------- + +In practice, as Iris develops, most users will want to periodically upgrade +their installed version to access new features or at least bugfixes. + +This is obvious if you are still developing other code that uses Iris, or using +code from other sources. +However, even if you have only legacy code that remains untouched, some code +maintenance effort is probably still necessary : + + * On the one hand, *in principle*, working code will go on working, as long + as you don't change anything else. + + * However, such "version statis" can easily become a growing burden, if you + are simply waiting until an update becomes unavoidable : Often, that will + eventually occur when you need to update some other software component, + for some completely unconnected reason. + + +Principles of Change Management +------------------------------- + +When you upgrade software to a new version, you often find that you need to +rewrite your legacy code, simply to keep it working. + +In Iris, however, we aim to reduce code maintenance problems to an absolute +minimum by following defined change management rules. +These ensure that, *within a major release number* : + + * you can be confident that your code will still work with subsequent minor + releases + + * you will be aware of future incompatibility problems in advance + + * you can defer making code compatibility changes for some time, until it + suits you + +The above applies to minor version upgrades : e.g. code that works with version +"1.4.2" should still work with a subsequent minor release such as "1.5.0" or +"1.7.2". + +A *major* release however, e.g. "v2.0.0" or "v3.0.0", can include more +significant changes, including so-called "breaking" changes: This means that +existing code may need to be modified to make it work with the new version. + +Since breaking change can only occur at major releases, these are the *only* +times we can alter or remove existing behaviours (even deprecated +ones). This is what a major release is for : it enables the removal and +replacement of old features. + +Of course, even at a major release, we do still aim to keep breaking changes to +a minimum. diff --git a/docs/iris/src/userguide/concat.png b/docs/iris/src/userguide/concat.png new file mode 100644 index 0000000000..eb3d84046e Binary files /dev/null and b/docs/iris/src/userguide/concat.png differ diff --git a/docs/iris/src/userguide/concat.svg b/docs/iris/src/userguide/concat.svg new file mode 100644 index 0000000000..0234b37bfa --- /dev/null +++ b/docs/iris/src/userguide/concat.svg @@ -0,0 +1,782 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + x + + + + + + + + + + + + + + + + + 0 + + 1 + 2 + 3 + 0 + 1 + 2 + 3 + + + + + + t + y + t + y + + + + + + + + + + + + diff --git a/docs/iris/src/userguide/cube_maths.rst b/docs/iris/src/userguide/cube_maths.rst index ced04358c1..6c6f846bc3 100644 --- a/docs/iris/src/userguide/cube_maths.rst +++ b/docs/iris/src/userguide/cube_maths.rst @@ -36,7 +36,7 @@ Let's load some air temperature which runs from 1860 to 2100:: air_temp = iris.load_cube(filename, 'air_temperature') We can now get the first and last time slices using indexing -(see :doc:`reducing_a_cube` for a reminder):: +(see :ref:`subsetting_a_cube` for a reminder):: t_first = air_temp[0, :, :] t_last = air_temp[-1, :, :] @@ -44,15 +44,15 @@ We can now get the first and last time slices using indexing .. testsetup:: filename = iris.sample_data_path('E1_north_america.nc') - cube = iris.load_cube(filename, 'air_temperature') - t_first = cube[0, :, :] - t_last = cube[-1, :, :] + air_temp = iris.load_cube(filename, 'air_temperature') + t_first = air_temp[0, :, :] + t_last = air_temp[-1, :, :] And finally we can subtract the two. The result is a cube of the same size as the original two time slices, but with the data representing their difference: - >>> print t_last - t_first + >>> print(t_last - t_first) unknown / (K) (latitude: 37; longitude: 49) Dimension coordinates: latitude x - @@ -66,10 +66,98 @@ but with the data representing their difference: Notice that the coordinates "time" and "forecast_period" have been removed from the resultant cube; - this is because these coordinates differed between the two input cubes. - For more control on whether or not coordinates should be automatically - ignored :func:`iris.analysis.maths.subtract` can be used instead. + this is because these coordinates differed between the two input cubes. + + +.. _cube-maths_anomaly: + +Calculating a cube anomaly +-------------------------- + +In section :doc:`cube_statistics` we discussed how the dimensionality of a cube +can be reduced using the :meth:`Cube.collapsed ` method +to calculate a statistic over a dimension. + +Let's use that method to calculate a mean of our air temperature time-series, +which we'll then use to calculate a time mean anomaly and highlight the powerful +benefits of cube broadcasting. + +First, let's remind ourselves of the shape of our air temperature time-series +cube:: + + >>> print(air_temp.summary(True)) + air_temperature / (K) (time: 240; latitude: 37; longitude: 49) + +Now, we'll calculate the time-series mean using the +:meth:`Cube.collapsed ` method:: + + >>> air_temp_mean = air_temp.collapsed('time', iris.analysis.MEAN) + >>> print(air_temp_mean.summary(True)) + air_temperature / (K) (latitude: 37; longitude: 49) + +As expected the *time* dimension has been collapsed, reducing the +dimensionality of the resultant *air_temp_mean* cube. This time-series mean can +now be used to calculate the time mean anomaly against the original +time-series:: + + >>> anomaly = air_temp - air_temp_mean + >>> print(anomaly.summary(True)) + unknown / (K) (time: 240; latitude: 37; longitude: 49) + +Notice that the calculation of the *anomaly* involves subtracting a +*2d* cube from a *3d* cube to yield a *3d* result. This is only possible +because cube broadcasting is performed during cube arithmetic operations. + +Cube broadcasting follows similar broadcasting rules as +`NumPy `_, but +the additional richness of Iris coordinate meta-data provides an enhanced +capability beyond the basic broadcasting behaviour of NumPy. + +As the coordinate meta-data of a cube uniquely describes each dimension, it is +possible to leverage this knowledge to identify the similar dimensions involved +in a cube arithmetic operation. This essentially means that we are no longer +restricted to performing arithmetic on cubes with identical shapes. + +This extended broadcasting behaviour is highlighted in the following +examples. The first of these shows that it is possible to involve the +transpose of the air temperature time-series in an arithmetic operation with +itself. + +Let's first create the transpose of the air temperature time-series:: + + >>> air_temp_T = air_temp.copy() + >>> air_temp_T.transpose() + >>> print(air_temp_T.summary(True)) + air_temperature / (K) (longitude: 49; latitude: 37; time: 240) + +Now add the transpose to the original time-series:: + + >>> result = air_temp + air_temp_T + >>> print(result.summary(True)) + unknown / (K) (time: 240; latitude: 37; longitude: 49) + +Notice that the *result* is the same dimensionality and shape as *air_temp*. +Let's check that the arithmetic operation has calculated a result that +we would intuitively expect:: + + >>> result == 2 * air_temp + True + +Let's extend this example slightly, by taking a slice from the middle +*latitude* dimension of the transpose cube:: + + >>> air_temp_T_slice = air_temp_T[:, 0, :] + >>> print(air_temp_T_slice.summary(True)) + air_temperature / (K) (longitude: 49; time: 240) + +Compared to our original time-series, the *air_temp_T_slice* cube has one +less dimension *and* it's shape if different. However, this doesn't prevent +us from performing cube arithmetic with it, thanks to the extended cube +broadcasting behaviour:: + >>> result = air_temp - air_temp_T_slice + >>> print(result.summary(True)) + unknown / (K) (time: 240; latitude: 37; longitude: 49) Combining multiple phenomena to form a new one ---------------------------------------------- @@ -120,7 +208,7 @@ The result could now be plotted using the guidance provided in the .. htmlonly:: A very similar example to this can be found in - :doc:`/examples/graphics/deriving_phenomena`. + :doc:`/examples/Meteorology/deriving_phenomena`. .. latexonly:: diff --git a/docs/iris/src/userguide/cube_statistics.rst b/docs/iris/src/userguide/cube_statistics.rst index 5bb76e4bd2..96e4776cf7 100644 --- a/docs/iris/src/userguide/cube_statistics.rst +++ b/docs/iris/src/userguide/cube_statistics.rst @@ -1,7 +1,11 @@ +.. _cube-statistics: + =============== Cube statistics =============== +.. _cube-statistics-collapsing: + Collapsing entire data dimensions --------------------------------- @@ -17,19 +21,21 @@ Collapsing entire data dimensions grid_areas = iris.analysis.cartography.area_weights(cube) -In the section :doc:`reducing_a_cube` we saw how to extract a subset of a cube -in order to reduce either its dimensionality or its resolution. +In the :doc:`subsetting_a_cube` section we saw how to extract a subset of a +cube in order to reduce either its dimensionality or its resolution. Instead of simply extracting a sub-region of the data, we can produce statistical functions of the data values across a particular dimension, such as a 'mean over time' or 'minimum over latitude'. +.. _cube-statistics_forecast_printout: + For instance, suppose we have a cube: >>> import iris >>> filename = iris.sample_data_path('uk_hires.pp') >>> cube = iris.load_cube(filename, 'air_potential_temperature') - >>> print cube + >>> print(cube) air_potential_temperature / (K) (time: 3; model_level_number: 7; grid_latitude: 204; grid_longitude: 187) Dimension coordinates: time x - - - @@ -47,7 +53,8 @@ For instance, suppose we have a cube: forecast_reference_time: 2009-11-19 04:00:00 Attributes: STASH: m01s00i004 - source: Data from Met Office Unified Model 7.03 + source: Data from Met Office Unified Model + um_version: 7.3 In this case we have a 4 dimensional cube; @@ -57,7 +64,7 @@ we can pass the coordinate name and the aggregation definition to the >>> import iris.analysis >>> vertical_mean = cube.collapsed('model_level_number', iris.analysis.MEAN) - >>> print vertical_mean + >>> print(vertical_mean) air_potential_temperature / (K) (time: 3; grid_latitude: 204; grid_longitude: 187) Dimension coordinates: time x - - @@ -70,12 +77,13 @@ we can pass the coordinate name and the aggregation definition to the altitude - x x Scalar coordinates: forecast_reference_time: 2009-11-19 04:00:00 - level_height: 696.667 m, bound=(0.0, 1393.33) m + level_height: 696.6666 m, bound=(0.0, 1393.3333) m model_level_number: 10, bound=(1, 19) - sigma: 0.92293, bound=(0.84586, 1.0) + sigma: 0.92292976, bound=(0.8458596, 1.0) Attributes: STASH: m01s00i004 - source: Data from Met Office Unified Model 7.03 + source: Data from Met Office Unified Model + um_version: 7.3 Cell methods: mean: model_level_number @@ -84,6 +92,16 @@ Similarly other analysis operators such as ``MAX``, ``MIN`` and ``STD_DEV`` can be used instead of ``MEAN``, see :mod:`iris.analysis` for a full list of currently supported operators. +For an example of using this functionality, the +:ref:`Hovmoller diagram ` example found +in the gallery takes a zonal mean of an ``XYT`` cube by using the +``collapsed`` method with ``latitude`` and ``iris.analysis.MEAN`` as arguments. + +You cannot partially collapse a multi-dimensional coordinate. See +:ref:`cube.collapsed ` for more +information. + +.. _cube-statistics-collapsing-average: Area averaging ^^^^^^^^^^^^^^ @@ -108,7 +126,7 @@ These areas can now be passed to the ``collapsed`` method as weights: .. doctest:: >>> new_cube = cube.collapsed(['grid_longitude', 'grid_latitude'], iris.analysis.MEAN, weights=grid_areas) - >>> print new_cube + >>> print(new_cube) air_potential_temperature / (K) (time: 3; model_level_number: 7) Dimension coordinates: time x - @@ -121,16 +139,21 @@ These areas can now be passed to the ``collapsed`` method as weights: altitude - x Scalar coordinates: forecast_reference_time: 2009-11-19 04:00:00 - grid_latitude: 1.51455 degrees, bound=(0.1443, 2.8848) degrees - grid_longitude: 358.749 degrees, bound=(357.494, 360.005) degrees + grid_latitude: 1.5145501 degrees, bound=(0.14430022, 2.8848) degrees + grid_longitude: 358.74948 degrees, bound=(357.494, 360.00497) degrees surface_altitude: 399.625 m, bound=(-14.0, 813.25) m Attributes: STASH: m01s00i004 - source: Data from Met Office Unified Model 7.03 + source: Data from Met Office Unified Model + um_version: 7.3 Cell methods: mean: grid_longitude, grid_latitude +Several examples of area averaging exist in the gallery which may be of interest, +including an example on taking a :ref:`global area-weighted mean +`. +.. _cube-statistics-aggregated-by: Partially reducing data dimensions ---------------------------------- @@ -175,6 +198,7 @@ to represent the climatological seasons and the season year respectively:: .. testsetup:: aggregation + import datetime import iris filename = iris.sample_data_path('ostia_monthly.nc') @@ -193,7 +217,7 @@ Printing this cube now shows that two extra coordinates exist on the cube: .. doctest:: aggregation - >>> print cube + >>> print(cube) surface_temperature / (K) (time: 54; latitude: 18; longitude: 432) Dimension coordinates: time x - - @@ -219,7 +243,7 @@ These two coordinates can now be used to aggregate by season and climate-year: >>> annual_seasonal_mean = cube.aggregated_by( ... ['clim_season', 'season_year'], ... iris.analysis.MEAN) - >>> print repr(annual_seasonal_mean) + >>> print(repr(annual_seasonal_mean)) The primary change in the cube is that the cube's data has been @@ -234,21 +258,42 @@ from the original cube: These points are individual months, so adjacent ones are often in the same season: .. doctest:: aggregation - - >>> print zip( - ... cube.coord('clim_season')[:10].points, - ... cube.coord('season_year')[:10].points) - [('mam', 2006), ('mam', 2006), ('jja', 2006), ('jja', 2006), ('jja', 2006), ('son', 2006), ('son', 2006), ('son', 2006), ('djf', 2007), ('djf', 2007)] + :options: +NORMALIZE_WHITESPACE + + >>> for season, year in zip(cube.coord('clim_season')[:10].points, + ... cube.coord('season_year')[:10].points): + ... print(season + ' ' + str(year)) + mam 2006 + mam 2006 + jja 2006 + jja 2006 + jja 2006 + son 2006 + son 2006 + son 2006 + djf 2007 + djf 2007 Compare this with the first 10 values of the new cube's coordinates: All the points now have distinct season+year values: .. doctest:: aggregation - - >>> print zip( - ... annual_seasonal_mean.coord('clim_season')[:10].points, - ... annual_seasonal_mean.coord('season_year')[:10].points) - [('mam', 2006), ('jja', 2006), ('son', 2006), ('djf', 2007), ('mam', 2007), ('jja', 2007), ('son', 2007), ('djf', 2008), ('mam', 2008), ('jja', 2008)] + :options: +NORMALIZE_WHITESPACE + + >>> for season, year in zip( + ... annual_seasonal_mean.coord('clim_season')[:10].points, + ... annual_seasonal_mean.coord('season_year')[:10].points): + ... print(season + ' ' + str(year)) + mam 2006 + jja 2006 + son 2006 + djf 2007 + mam 2007 + jja 2007 + son 2007 + djf 2008 + mam 2008 + jja 2008 Because the original data started in April 2006 we have some incomplete seasons (e.g. there were only two months worth of data for 'mam-2006'). @@ -257,7 +302,8 @@ do not cover a three month period (note: judged here as > 3*28 days): .. doctest:: aggregation - >>> spans_three_months = lambda t: (t.bound[1] - t.bound[0]) > 3*28*24.0 + >>> tdelta_3mth = datetime.timedelta(hours=3*28*24.0) + >>> spans_three_months = lambda t: (t.bound[1] - t.bound[0]) > tdelta_3mth >>> three_months_bound = iris.Constraint(time=spans_three_months) >>> full_season_means = annual_seasonal_mean.extract(three_months_bound) >>> full_season_means @@ -267,9 +313,26 @@ The final result now represents the seasonal mean temperature for 17 seasons from jja-2006 to jja-2010: .. doctest:: aggregation - - >>> print zip( - ... full_season_means.coord('clim_season').points, - ... full_season_means.coord('season_year').points) - [('jja', 2006), ('son', 2006), ('djf', 2007), ('mam', 2007), ('jja', 2007), ('son', 2007), ('djf', 2008), ('mam', 2008), ('jja', 2008), ('son', 2008), ('djf', 2009), ('mam', 2009), ('jja', 2009), ('son', 2009), ('djf', 2010), ('mam', 2010), ('jja', 2010)] + :options: +NORMALIZE_WHITESPACE + + >>> for season, year in zip(full_season_means.coord('clim_season').points, + ... full_season_means.coord('season_year').points): + ... print(season + ' ' + str(year)) + jja 2006 + son 2006 + djf 2007 + mam 2007 + jja 2007 + son 2007 + djf 2008 + mam 2008 + jja 2008 + son 2008 + djf 2009 + mam 2009 + jja 2009 + son 2009 + djf 2010 + mam 2010 + jja 2010 diff --git a/docs/iris/src/userguide/index.rst b/docs/iris/src/userguide/index.rst index 7554f41299..8c0b24bec3 100644 --- a/docs/iris/src/userguide/index.rst +++ b/docs/iris/src/userguide/index.rst @@ -6,11 +6,11 @@ Iris user guide How to use the user guide --------------------------- -If you are reading this user guide for the first time it is strongly recommended that you read the user guide -fully before experimenting with your own data files. +If you are reading this user guide for the first time it is strongly recommended that you read the user guide +fully before experimenting with your own data files. -Much of the content has supplementary links to the reference documentation; you will not need to follow these +Much of the content has supplementary links to the reference documentation; you will not need to follow these links in order to understand the guide but they may serve as a useful reference for future exploration. .. htmlonly:: @@ -27,10 +27,15 @@ User guide table of contents iris_cubes.rst loading_iris_cubes.rst + saving_iris_cubes.rst navigating_a_cube.rst - reducing_a_cube.rst + subsetting_a_cube.rst + real_and_lazy_data.rst plotting_a_cube.rst + interpolation_and_regridding.rst + merge_and_concat.rst cube_statistics.rst cube_maths.rst citation.rst + code_maintenance.rst end_of_userguide.rst diff --git a/docs/iris/src/userguide/interpolation_and_regridding.rst b/docs/iris/src/userguide/interpolation_and_regridding.rst new file mode 100644 index 0000000000..e3cd622541 --- /dev/null +++ b/docs/iris/src/userguide/interpolation_and_regridding.rst @@ -0,0 +1,412 @@ +.. _interpolation_and_regridding: + + +.. testsetup:: * + + import numpy as np + import iris + import warnings + warnings.simplefilter('ignore') + +================================= +Cube interpolation and regridding +================================= + +Iris provides powerful cube-aware interpolation and regridding functionality, +exposed through Iris cube methods. This functionality is provided by building +upon existing interpolation schemes implemented by SciPy. + +In Iris we refer to the avaliable types of interpolation and regridding as +`schemes`. The following are the interpolation schemes that are currently +available in Iris: + + * linear interpolation (:class:`iris.analysis.Linear`), and + * nearest-neighbour interpolation (:class:`iris.analysis.Nearest`). + +The following are the regridding schemes that are currently available in Iris: + + * linear regridding (:class:`iris.analysis.Linear`), + * nearest-neighbour regridding (:class:`iris.analysis.Nearest`), and + * area-weighted regridding (:class:`iris.analysis.AreaWeighted`, first-order conservative). + + +.. _interpolation: + +Interpolation +------------- + +Interpolating a cube is achieved with the :meth:`~iris.cube.Cube.interpolate` +method. This method expects two arguments: + + #. the sample points to interpolate, and + #. the second argument being the interpolation scheme to use. + +The result is a new cube, interpolated at the sample points. + +Sample points must be defined as an iterable of ``(coord, value(s))`` pairs. +The `coord` argument can be either a coordinate name or coordinate instance. +The specified coordinate must exist on the cube being interpolated! For example: + + * coordinate names and scalar sample points: ``[('latitude', 51.48), ('longitude', 0)]``, + * a coordinate instance and a scalar sample point: ``[(cube.coord('latitude'), 51.48)]``, and + * a coordinate name and a NumPy array of sample points: ``[('longitude', np.linspace(-11, 2, 14))]`` + +are all examples of valid sample points. + +The values for coordinates that correspond to date/times can be supplied as +datetime.datetime or cftime.datetime instances, +e.g. ``[('time', datetime.datetime(2009, 11, 19, 10, 30))]``). + +Let's take the air temperature cube we've seen previously: + + >>> air_temp = iris.load_cube(iris.sample_data_path('air_temp.pp')) + >>> print(air_temp) + air_temperature / (K) (latitude: 73; longitude: 96) + Dimension coordinates: + latitude x - + longitude - x + Scalar coordinates: + forecast_period: 6477 hours, bound=(-28083.0, 6477.0) hours + forecast_reference_time: 1998-03-01 03:00:00 + pressure: 1000.0 hPa + time: 1998-12-01 00:00:00, bound=(1994-12-01 00:00:00, 1998-12-01 00:00:00) + Attributes: + STASH: m01s16i203 + source: Data from Met Office Unified Model + Cell methods: + mean within years: time + mean over years: time + +We can interpolate specific values from the coordinates of the cube: + + >>> sample_points = [('latitude', 51.48), ('longitude', 0)] + >>> print(air_temp.interpolate(sample_points, iris.analysis.Linear())) + air_temperature / (K) (scalar cube) + Scalar coordinates: + forecast_period: 6477 hours, bound=(-28083.0, 6477.0) hours + forecast_reference_time: 1998-03-01 03:00:00 + latitude: 51.48 degrees + longitude: 0 degrees + pressure: 1000.0 hPa + time: 1998-12-01 00:00:00, bound=(1994-12-01 00:00:00, 1998-12-01 00:00:00) + Attributes: + STASH: m01s16i203 + source: Data from Met Office Unified Model + Cell methods: + mean within years: time + mean over years: time + +As we can see, the resulting cube is scalar and has longitude and latitude coordinates with +the values defined in our sample points. + +It isn't necessary to specify sample points for every dimension, only those that you +wish to interpolate over: + + >>> result = air_temp.interpolate([('longitude', 0)], iris.analysis.Linear()) + >>> print('Original: ' + air_temp.summary(shorten=True)) + Original: air_temperature / (K) (latitude: 73; longitude: 96) + >>> print('Interpolated: ' + result.summary(shorten=True)) + Interpolated: air_temperature / (K) (latitude: 73) + +The sample points for a coordinate can be an array of values. When multiple coordinates are +provided with arrays instead of scalar sample points, the coordinates on the resulting cube +will be orthogonal: + + >>> sample_points = [('longitude', np.linspace(-11, 2, 14)), + ... ('latitude', np.linspace(48, 60, 13))] + >>> result = air_temp.interpolate(sample_points, iris.analysis.Linear()) + >>> print(result.summary(shorten=True)) + air_temperature / (K) (latitude: 13; longitude: 14) + + +Interpolating non-horizontal coordinates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Interpolation in Iris is not limited to horizontal-spatial coordinates - any +coordinate satisfying the prerequisites of the chosen scheme may be interpolated +over. + +For instance, the :class:`iris.analysis.Linear` scheme requires 1D numeric, +monotonic, coordinates. Supposing we have a single column cube such as +the one defined below: + + >>> cube = iris.load_cube(iris.sample_data_path('hybrid_height.nc'), 'air_potential_temperature') + >>> column = cube[:, 0, 0] + >>> print(column.summary(shorten=True)) + air_potential_temperature / (K) (model_level_number: 15) + +This cube has a "hybrid-height" vertical coordinate system, meaning that the vertical +coordinate is unevenly spaced in altitude: + + >>> print(column.coord('altitude').points) + [ 418.69836 434.5705 456.7928 485.3665 520.2933 561.5752 + 609.2145 663.2141 723.57697 790.30664 863.4072 942.8823 + 1028.737 1120.9764 1219.6051 ] + +We could regularise the vertical coordinate by defining 10 equally spaced altitude +sample points between 400 and 1250 and interpolating our vertical coordinate onto +these sample points: + + >>> sample_points = [('altitude', np.linspace(400, 1250, 10))] + >>> new_column = column.interpolate(sample_points, iris.analysis.Linear()) + >>> print(new_column.summary(shorten=True)) + air_potential_temperature / (K) (model_level_number: 10) + +Let's look at the original data, the interpolation line and +the new data in a plot. This will help us to see what is going on: + +.. plot:: userguide/regridding_plots/interpolate_column.py + +The red diamonds on the extremes of the altitude values show that we have +extrapolated data beyond the range of the original data. In some cases this is +desirable but in other cases it is not. For example, this column defines +a surface altitude value of 414m, so extrapolating an "air potential temperature" +at 400m makes little physical sense in this case. + +We can control the extrapolation mode when defining the interpolation scheme. +Controlling the extrapolation mode allows us to avoid situations like the above where +extrapolating values makes little physical sense. + +The extrapolation mode is controlled by the ``extrapolation_mode`` keyword. +For the available interpolation schemes available in Iris, the ``extrapolation_mode`` +keyword must be one of: + + * ``extrapolate`` -- the extrapolation points will be calculated by extending the gradient of the closest two points, + * ``error`` -- a ValueError exception will be raised, notifying an attempt to extrapolate, + * ``nan`` -- the extrapolation points will be be set to NaN, + * ``mask`` -- the extrapolation points will always be masked, even if the source data is not a MaskedArray, or + * ``nanmask`` -- if the source data is a MaskedArray the extrapolation points will be masked. Otherwise they will be set to NaN. + +Using an extrapolation mode is achieved by constructing an interpolation scheme +with the extrapolation mode keyword set as required. The constructed scheme +is then passed to the :meth:`~iris.cube.Cube.interpolate` method. +For example, to mask values that lie beyond the range of the original data: + + >>> scheme = iris.analysis.Linear(extrapolation_mode='mask') + >>> new_column = column.interpolate(sample_points, scheme) + >>> print(new_column.coord('altitude').points) + [ nan 494.44452 588.8889 683.33325 777.77783 872.2222 + 966.66675 1061.1111 1155.5554 nan] + + +.. _caching_an_interpolator: + +Caching an interpolator +^^^^^^^^^^^^^^^^^^^^^^^ + +If you need to interpolate a cube on multiple sets of sample points you can +'cache' an interpolator to be used for each of these interpolations. This can +shorten the execution time of your code as the most computationally +intensive part of an interpolation is setting up the interpolator. + +To cache an interpolator you must set up an interpolator scheme and call the +scheme's interpolator method. The interpolator method takes as arguments: + + #. a cube to be interpolated, and + #. an iterable of coordinate names or coordinate instances of the coordinates that are to be interpolated over. + +For example: + + >>> air_temp = iris.load_cube(iris.sample_data_path('air_temp.pp')) + >>> interpolator = iris.analysis.Nearest().interpolator(air_temp, ['latitude', 'longitude']) + +When this cached interpolator is called you must pass it an iterable of sample points +that have the same form as the iterable of coordinates passed to the constructor. +So, to use the cached interpolator defined above: + + >>> latitudes = np.linspace(48, 60, 13) + >>> longitudes = np.linspace(-11, 2, 14) + >>> for lat, lon in zip(latitudes, longitudes): + ... result = interpolator([lat, lon]) + +In each case ``result`` will be a cube interpolated from the ``air_temp`` cube we +passed to interpolator. + +Note that you must specify the required extrapolation mode when setting up the cached interpolator. +For example:: + + >>> interpolator = iris.analysis.Nearest(extrapolation_mode='nan').interpolator(cube, coords) + + +.. _regridding: + +Regridding +---------- + +Regridding is conceptually a very similar process to interpolation in Iris. +The primary difference is that interpolation is based on sample points, while +regridding is based on the **horizontal** grid of *another cube*. + +Regridding a cube is achieved with the :meth:`cube.regrid() ` method. +This method expects two arguments: + + #. *another cube* that defines the target grid onto which the cube should be regridded, and + #. the regridding scheme to use. + +.. note:: + + Regridding is a common operation needed to allow comparisons of data on different grids. + The powerful mapping functionality provided by cartopy, however, means that regridding + is often not necessary if performed just for visualisation purposes. + +Let's load two cubes that have different grids and coordinate systems: + + >>> global_air_temp = iris.load_cube(iris.sample_data_path('air_temp.pp')) + >>> rotated_psl = iris.load_cube(iris.sample_data_path('rotated_pole.nc')) + +We can visually confirm that they are on different grids by plotting the two cubes: + +.. plot:: userguide/regridding_plots/regridding_plot.py + +Let's regrid the ``global_air_temp`` cube onto a rotated pole grid +using a linear regridding scheme. To achieve this we pass the ``rotated_psl`` +cube to the regridder to supply the target grid to regrid the ``global_air_temp`` +cube onto: + + >>> rotated_air_temp = global_air_temp.regrid(rotated_psl, iris.analysis.Linear()) + +.. plot:: userguide/regridding_plots/regridded_to_rotated.py + +We could regrid the pressure values onto the global grid, but this will involve +some form of extrapolation. As with interpolation, we can control the extrapolation +mode when defining the regridding scheme. + +For the available regridding schemes in Iris, the ``extrapolation_mode`` keyword +must be one of: + + * ``extrapolate`` -- + + * for :class:`~iris.analysis.Linear` the extrapolation points will be calculated by extending the gradient of the closest two points. + * for :class:`~iris.analysis.Nearest` the extrapolation points will take their value from the nearest source point. + + * ``nan`` -- the extrapolation points will be be set to NaN. + * ``error`` -- a ValueError exception will be raised, notifying an attempt to extrapolate. + * ``mask`` -- the extrapolation points will always be masked, even if the source data is not a MaskedArray. + * ``nanmask`` -- if the source data is a MaskedArray the extrapolation points will be masked. Otherwise they will be set to NaN. + +The ``rotated_psl`` cube is defined on a limited area rotated pole grid. If we regridded +the ``rotated_psl`` cube onto the global grid as defined by the ``global_air_temp`` cube +any linearly extrapolated values would quickly become dominant and highly inaccurate. +We can control this behaviour by defining the ``extrapolation_mode`` in the constructor +of the regridding scheme to mask values that lie outside of the domain of the rotated +pole grid: + + >>> scheme = iris.analysis.Linear(extrapolation_mode='mask') + >>> global_psl = rotated_psl.regrid(global_air_temp, scheme) + +.. plot:: userguide/regridding_plots/regridded_to_global.py + +Notice that although we can still see the approximate shape of the rotated pole grid, the +cells have now become rectangular in a plate carrée (equirectangular) projection. +The spatial grid of the resulting cube is really global, with a large proportion of the +data being masked. + +Area-weighted regridding +^^^^^^^^^^^^^^^^^^^^^^^^ + +It is often the case that a point-based regridding scheme (such as +:class:`iris.analysis.Linear` or :class:`iris.analysis.Nearest`) is not +appropriate when you need to conserve quantities when regridding. The +:class:`iris.analysis.AreaWeighted` scheme is less general than +:class:`~iris.analysis.Linear` or :class:`~iris.analysis.Nearest`, but is a +conservative regridding scheme, meaning that the area-weighted total is +approximately preserved across grids. + +With the :class:`~iris.analysis.AreaWeighted` regridding scheme, each target grid-box's +data is computed as a weighted mean of all grid-boxes from the source grid. The weighting +for any given target grid-box is the area of the intersection with each of the +source grid-boxes. This scheme performs well when regridding from a high +resolution source grid to a lower resolution target grid, since all source data +points will be accounted for in the target grid. + +Let's demonstrate this with the global air temperature cube we saw previously, +along with a limited area cube containing total concentration of volcanic ash: + + >>> global_air_temp = iris.load_cube(iris.sample_data_path('air_temp.pp')) + >>> print(global_air_temp.summary(shorten=True)) + air_temperature / (K) (latitude: 73; longitude: 96) + >>> + >>> regional_ash = iris.load_cube(iris.sample_data_path('NAME_output.txt')) + >>> regional_ash = regional_ash.collapsed('flight_level', iris.analysis.SUM) + >>> print(regional_ash.summary(shorten=True)) + VOLCANIC_ASH_AIR_CONCENTRATION / (g/m3) (latitude: 214; longitude: 584) + +One of the key limitations of the :class:`~iris.analysis.AreaWeighted` +regridding scheme is that the two input grids must be defined in the same +coordinate system as each other. Both input grids must also contain monotonic, +bounded, 1D spatial coordinates. + +.. note:: + + The :class:`~iris.analysis.AreaWeighted` regridding scheme requires spatial + areas, therefore the longitude and latitude coordinates must be bounded. + If the longitude and latitude bounds are not defined in the cube we can + guess the bounds based on the coordinates' point values: + + >>> global_air_temp.coord('longitude').guess_bounds() + >>> global_air_temp.coord('latitude').guess_bounds() + +Using NumPy's masked array module we can mask any data that falls below a meaningful +concentration: + + >>> regional_ash.data = np.ma.masked_less(regional_ash.data, 5e-6) + +Finally, we can regrid the data using the :class:`~iris.analysis.AreaWeighted` +regridding scheme: + + >>> scheme = iris.analysis.AreaWeighted(mdtol=0.5) + >>> global_ash = regional_ash.regrid(global_air_temp, scheme) + >>> print(global_ash.summary(shorten=True)) + VOLCANIC_ASH_AIR_CONCENTRATION / (g/m3) (latitude: 73; longitude: 96) + +Note that the :class:`~iris.analysis.AreaWeighted` regridding scheme allows us +to define a missing data tolerance (``mdtol``), which specifies the tolerated +fraction of masked data in any given target grid-box. If the fraction of masked +data within a target grid-box exceeds this value, the data in this target +grid-box will be masked in the result. + +The fraction of masked data is calculated based on the area of masked source +grid-boxes that overlaps with each target grid-box. Defining an ``mdtol`` in the +:class:`~iris.analysis.AreaWeighted` regridding scheme allows fine control +of masked data tolerance. It is worth remembering that defining an ``mdtol`` of +anything other than 1 will prevent the scheme from being fully conservative, as +some data will be disregarded if it lies close to masked data. + +To visualise the above regrid, let's plot the original data, along with 3 distinct +``mdtol`` values to compare the result: + +.. plot:: userguide/regridding_plots/regridded_to_global_area_weighted.py + + +.. _caching_a_regridder: + +Caching a regridder +^^^^^^^^^^^^^^^^^^^ + +If you need to regrid multiple cubes with a common source grid onto a common +target grid you can 'cache' a regridder to be used for each of these regrids. +This can shorten the execution time of your code as the most computationally +intensive part of a regrid is setting up the regridder. + +To cache a regridder you must set up a regridder scheme and call the +scheme's regridder method. The regridder method takes as arguments: + + #. a cube (that is to be regridded) defining the source grid, and + #. a cube defining the target grid to regrid the source cube to. + +For example: + + >>> global_air_temp = iris.load_cube(iris.sample_data_path('air_temp.pp')) + >>> rotated_psl = iris.load_cube(iris.sample_data_path('rotated_pole.nc')) + >>> regridder = iris.analysis.Nearest().regridder(global_air_temp, rotated_psl) + +When this cached regridder is called you must pass it a cube on the same grid +as the source grid cube (in this case ``global_air_temp``) that is to be +regridded to the target grid. For example:: + + >>> for cube in list_of_cubes_on_source_grid: + ... result = regridder(cube) + +In each case ``result`` will be the input cube regridded to the grid defined by +the target grid cube (in this case ``rotated_psl``) that we used to define the +cached regridder. diff --git a/docs/iris/src/userguide/iris_cubes.rst b/docs/iris/src/userguide/iris_cubes.rst index d8d5b452d7..dc423afba1 100644 --- a/docs/iris/src/userguide/iris_cubes.rst +++ b/docs/iris/src/userguide/iris_cubes.rst @@ -4,6 +4,7 @@ Introduction =================== +.. _iris_data_structures: Iris data structures -------------------- @@ -145,14 +146,16 @@ Printing a cube Every Iris cube can be printed to screen as you will see later in the user guide. It is worth familiarising yourself with the output as this is the quickest way of inspecting the contents of a cube. Here is the result of printing a real life cube: +.. _hybrid_cube_printout: + .. testcode:: :hide: import iris filename = iris.sample_data_path('uk_hires.pp') # NOTE: Every time the output of this cube changes, the full list of deductions below should be re-assessed. - print iris.load_cube(filename, 'air_potential_temperature') - + print(iris.load_cube(filename, 'air_potential_temperature')) + .. testoutput:: air_potential_temperature / (K) (time: 3; model_level_number: 7; grid_latitude: 204; grid_longitude: 187) @@ -172,7 +175,8 @@ output as this is the quickest way of inspecting the contents of a cube. Here is forecast_reference_time: 2009-11-19 04:00:00 Attributes: STASH: m01s00i004 - source: Data from Met Office Unified Model 7.03 + source: Data from Met Office Unified Model + um_version: 7.3 Using this output we can deduce that: diff --git a/docs/iris/src/userguide/loading_iris_cubes.rst b/docs/iris/src/userguide/loading_iris_cubes.rst index 781773e682..c2ba575838 100644 --- a/docs/iris/src/userguide/loading_iris_cubes.rst +++ b/docs/iris/src/userguide/loading_iris_cubes.rst @@ -29,7 +29,7 @@ In order to find out what has been loaded, the result can be printed: >>> import iris >>> filename = iris.sample_data_path('uk_hires.pp') >>> cubes = iris.load(filename) - >>> print cubes + >>> print(cubes) 0: air_potential_temperature / (K) (time: 3; model_level_number: 7; grid_latitude: 204; grid_longitude: 187) 1: surface_altitude / (m) (grid_latitude: 204; grid_longitude: 187) @@ -76,7 +76,7 @@ list indexing can be used: >>> cubes = iris.load(filename) >>> # get the first cube (list indexing is 0 based) >>> air_potential_temperature = cubes[0] - >>> print air_potential_temperature + >>> print(air_potential_temperature) air_potential_temperature / (K) (time: 3; model_level_number: 7; grid_latitude: 204; grid_longitude: 187) Dimension coordinates: time x - - - @@ -94,7 +94,8 @@ list indexing can be used: forecast_reference_time: 2009-11-19 04:00:00 Attributes: STASH: m01s00i004 - source: Data from Met Office Unified Model 7.03 + source: Data from Met Office Unified Model + um_version: 7.3 Notice that the result of printing a **cube** is a little more verbose than it was when printing a **list of cubes**. In addition to the very short summary @@ -129,6 +130,22 @@ star wildcards can be used:: cubes = iris.load(filename) +.. note:: + + The cubes returned will not necessarily be in the same order as the + order of the filenames. + +Lazy loading +------------ + +In fact when Iris loads data from most file types, it normally only reads the +essential descriptive information or metadata : the bulk of the actual data +content will only be loaded later, as it is needed. +This is referred to as 'lazy' data. It allows loading to be much quicker, and to occupy less memory. + +For more on the benefits, handling and uses of lazy data, see :doc:`Real and Lazy Data `. + + Constrained loading ----------------------- Given a large dataset, it is possible to restrict or constrain the load @@ -177,7 +194,7 @@ and a list of values can be given to constrain a coordinate to one of a collection of values:: filename = iris.sample_data_path('uk_hires.pp') - level_10_or_12_fp_6 = iris.Constraint(model_level_number=[10, 16], forecast_period=6) + level_10_or_16_fp_6 = iris.Constraint(model_level_number=[10, 16], forecast_period=6) cubes = iris.load(filename, level_10_or_16_fp_6) A common requirement is to limit the value of a coordinate to a specific range, @@ -199,6 +216,10 @@ this can be achieved by passing the constraint a function:: bottom_16_levels = lambda cell: cell <= 16 + +Note also the :ref:`warning on equality constraints with floating point coordinates `. + + Cube attributes can also be part of the constraint criteria. Supposing a cube attribute of ``STASH`` existed, as is the case when loading ``PP`` files, then specific STASH codes can be filtered:: @@ -212,6 +233,20 @@ then specific STASH codes can be filtered:: For advanced usage there are further examples in the :class:`iris.Constraint` reference documentation. + +Constraining a circular coordinate across its boundary +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Occasionally you may need to constrain your cube with a region that crosses the +boundary of a circular coordinate (this is often the meridian or the dateline / +antimeridian). An example use-case of this is to extract the entire Pacific Ocean +from a cube whose longitudes are bounded by the dateline. + +This functionality cannot be provided reliably using contraints. Instead you should use the +functionality provided by :meth:`cube.intersection ` +to extract this region. + + .. _using-time-constraints: Constraining on Time @@ -223,23 +258,19 @@ However, when constraining by time we usually want to test calendar-related aspects such as hours of the day or months of the year, so Iris provides special features to facilitate this: -Firstly, Iris can be configured so that when it evaluates Constraint -expressions, it will convert time-coordinate values (points and bounds) from -numbers into :class:`~datetime.datetime`-like objects for ease of calendar-based -testing. This feature is not backwards compatible so for now it must be -explicitly enabled by setting the "cell_datetime_objects" option in :class:`iris.Future`: +Firstly, when Iris evaluates Constraint expressions, it will convert time-coordinate +values (points and bounds) from numbers into :class:`~datetime.datetime`-like objects +for ease of calendar-based testing. >>> filename = iris.sample_data_path('uk_hires.pp') >>> cube_all = iris.load_cube(filename, 'air_potential_temperature') - >>> print 'All times :\n', cube_all.coord('time') + >>> print('All times :\n' + str(cube_all.coord('time'))) All times : DimCoord([2009-11-19 10:00:00, 2009-11-19 11:00:00, 2009-11-19 12:00:00], standard_name='time', calendar='gregorian') >>> # Define a function which accepts a datetime as its argument (this is simplified in later examples). >>> hour_11 = iris.Constraint(time=lambda cell: cell.point.hour == 11) - >>> with iris.FUTURE.context(cell_datetime_objects=True): - ... cube_11 = cube_all.extract(hour_11) - ... - >>> print 'Selected times :\n', cube_11.coord('time') + >>> cube_11 = cube_all.extract(hour_11) + >>> print('Selected times :\n' + str(cube_11.coord('time'))) Selected times : DimCoord([2009-11-19 11:00:00], standard_name='time', calendar='gregorian') @@ -251,9 +282,9 @@ then test only those 'aspects' which the PartialDateTime instance defines: >>> import datetime >>> from iris.time import PartialDateTime >>> dt = datetime.datetime(2011, 3, 7) - >>> print dt > PartialDateTime(year=2010, month=6) + >>> print(dt > PartialDateTime(year=2010, month=6)) True - >>> print dt > PartialDateTime(month=6) + >>> print(dt > PartialDateTime(month=6)) False >>> @@ -263,9 +294,9 @@ time selections when loading or extracting data. The previous constraint example can now be written as: >>> the_11th_hour = iris.Constraint(time=iris.time.PartialDateTime(hour=11)) - >>> with iris.FUTURE.context(cell_datetime_objects=True): - ... print iris.load_cube(iris.sample_data_path('uk_hires.pp'), - ... 'air_potential_temperature' & the_11th_hour).coord('time') + >>> print(iris.load_cube( + ... iris.sample_data_path('uk_hires.pp'), + ... 'air_potential_temperature' & the_11th_hour).coord('time')) DimCoord([2009-11-19 11:00:00], standard_name='time', calendar='gregorian') A more complex example might be when there exists a time sequence representing the first day of every week @@ -284,7 +315,7 @@ for many years: .. doctest:: timeseries_range :options: +NORMALIZE_WHITESPACE, +ELLIPSIS - >>> print long_ts.coord('time') + >>> print(long_ts.coord('time')) DimCoord([2007-04-09 00:00:00, 2007-04-16 00:00:00, 2007-04-23 00:00:00, ... 2010-02-01 00:00:00, 2010-02-08 00:00:00, 2010-02-15 00:00:00], @@ -298,10 +329,9 @@ functionality with PartialDateTime: >>> st_swithuns_daterange = iris.Constraint( ... time=lambda cell: PartialDateTime(month=7, day=15) < cell < PartialDateTime(month=8, day=25)) - >>> with iris.FUTURE.context(cell_datetime_objects=True): - ... within_st_swithuns = long_ts.extract(st_swithuns_daterange) + >>> within_st_swithuns = long_ts.extract(st_swithuns_daterange) ... - >>> print within_st_swithuns.coord('time') + >>> print(within_st_swithuns.coord('time')) DimCoord([2007-07-16 00:00:00, 2007-07-23 00:00:00, 2007-07-30 00:00:00, 2007-08-06 00:00:00, 2007-08-13 00:00:00, 2007-08-20 00:00:00, 2008-07-21 00:00:00, 2008-07-28 00:00:00, 2008-08-04 00:00:00, @@ -329,7 +359,7 @@ A single cube is loaded in the following example:: >>> filename = iris.sample_data_path('air_temp.pp') >>> cube = iris.load_cube(filename) - >>> print cube + >>> print(cube) air_temperature / (K) (latitude: 73; longitude: 96) Dimension coordinates: latitude x - @@ -366,7 +396,7 @@ in order to run:: import iris filename = iris.sample_data_path('uk_hires.pp') air_pot_temp = iris.load_cube(filename, 'air_potential_temperature') - print air_pot_temp + print(air_pot_temp) Should the file not produce exactly one cube with a standard name of 'air_potential_temperature', an exception will be raised. @@ -388,23 +418,8 @@ these two cubes into separate variables. using *multiple assignment*: >>> number_one, number_two = [1, 2] - >>> print number_one + >>> print(number_one) 1 - >>> print number_two + >>> print(number_two) 2 - -Saving Iris Cubes ------------------ - -The :py:func:`iris.save` function saves one or more cubes to a file. - -If the filename includes a supported suffix then Iris will use the correct saver -and the keyword argument `saver` is not required. - - >>> import iris - >>> filename = iris.sample_data_path('uk_hires.pp') - >>> cubes = iris.load(filename) - >>> iris.save(cubes, '/tmp/uk_hires.nc') - -Iris is able to save to CF NetCDF (1.5), GRIB (edition 2) and Met Office PP formats. diff --git a/docs/iris/src/userguide/merge.png b/docs/iris/src/userguide/merge.png new file mode 100644 index 0000000000..cafaa370da Binary files /dev/null and b/docs/iris/src/userguide/merge.png differ diff --git a/docs/iris/src/userguide/merge.svg b/docs/iris/src/userguide/merge.svg new file mode 100644 index 0000000000..9326bc332b --- /dev/null +++ b/docs/iris/src/userguide/merge.svg @@ -0,0 +1,714 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + y + + + + + + + + + + + + + + + + + + + + + 0 + + 1 + 2 + 3 + 0 + 1 + 2 + 3 + + + + + + + + + x + z + x + z + + + diff --git a/docs/iris/src/userguide/merge_and_concat.png b/docs/iris/src/userguide/merge_and_concat.png new file mode 100644 index 0000000000..48238287b4 Binary files /dev/null and b/docs/iris/src/userguide/merge_and_concat.png differ diff --git a/docs/iris/src/userguide/merge_and_concat.rst b/docs/iris/src/userguide/merge_and_concat.rst new file mode 100644 index 0000000000..8321f4106e --- /dev/null +++ b/docs/iris/src/userguide/merge_and_concat.rst @@ -0,0 +1,649 @@ +.. _merge_and_concat: + +===================== +Merge and Concatenate +===================== + +We saw in the :doc:`loading_iris_cubes` chapter that Iris tries to load as few cubes as +possible. This is done by collecting together multiple fields with a shared standard +name (and other key metadata) into a single multidimensional cube. The processes that +perform this behaviour in Iris are known as ``merge`` and ``concatenate``. + +This chapter describes the ``merge`` and ``concatenate`` processes; it explains +why common issues occur when using them and gives advice on how prevent these +issues from occurring. + +Both ``merge`` and ``concatenate`` take multiple cubes as input and +result in fewer cubes as output. The following diagram illustrates the two processes: + +.. image:: merge_and_concat.png + :alt: Pictographic of merge and concatenation. + :align: center + +There is one major difference between the ``merge`` and ``concatenate`` processes. + + * The ``merge`` process combines multiple input cubes into a + single resultant cube with new dimensions created from the + *scalar coordinate values* of the input cubes. + + * The ``concatenate`` process combines multiple input cubes into a + single resultant cube with the same *number of dimensions* as the input cubes, + but with the length of one or more dimensions extended by *joining together + sequential dimension coordinates*. + +Let's imagine 28 individual cubes representing the +temperature at a location ``(y, x)``; one cube for each day of February. We can use +:meth:`~iris.cube.CubeList.merge` to combine the 28 ``(y, x)`` cubes into +a single ``(t, y, x)`` cube, where the length of the ``t`` dimension is 28. + +Now imagine 12 individual cubes representing daily temperature at a time and +location ``(t, y, x)``; one cube for each month in the year. We can use +:meth:`~iris.cube.CubeList.concatenate` to combine the 12 +``(t, y, x)`` cubes into a single ``(t, y, x)`` cube, where the length +of the ``t`` dimension is now 365. + + +Merge +----- + +We've seen that the ``merge`` process combines multiple input cubes into a +single resultant cube with new dimensions created from the +*scalar coordinate values* of the input cubes. + +In order to construct new coordinates for the new dimensions, the ``merge`` process requires input cubes +with scalar coordinates that can be combined together into monotonic sequences. +The order of the input cubes does not affect the ``merge`` process. + +The ``merge`` process can produce a cube that has more than one new dimension, +if the scalar coordinate sequences form an orthogonal basis. + +.. important:: + + The shape, metadata, attributes, coordinates, coordinates metadata, fill value and + other aspects of the input cubes must be consistent across all of the input cubes. + + The ``merge`` process will fail if these are not consistent. Such failures are + covered in the :ref:`merge_concat_common_issues` section. + + +The ``merge`` process can be accessed using two methods. The two methods are +:meth:`~iris.cube.CubeList.merge` and :meth:`~iris.cube.CubeList.merge_cube`, +which are described below. + + +Using CubeList.merge +==================== + +The :meth:`CubeList.merge ` method operates on a list +of cubes and returns a new :class:`~iris.cube.CubeList` containing the cubes +that have been merged. + +.. testsetup:: merge + + import numpy as np + import iris + def _xy_cube(z): + cube = iris.cube.Cube(np.arange(20).reshape(4, 5), 'air_temperature', units='kelvin') + cube.add_dim_coord(iris.coords.DimCoord(range(4), long_name='y'), 0) + cube.add_dim_coord(iris.coords.DimCoord(range(5), long_name='x'), 1) + cube.add_aux_coord(iris.coords.DimCoord(z, long_name='z', units='meters')) + return cube + cubes = iris.cube.CubeList([_xy_cube(1), _xy_cube(2), _xy_cube(3)]) + + +Let's have a look at the :meth:`~iris.cube.CubeList.merge` method in operation. +In this example we have a list of three lateral (*x*, *y*) cubes in a +variable called ``cubes``, each with a scalar ``z`` coordinate of +differing value. We can merge these cubes by stacking the scalar ``z`` coordinates to +make a new ``z`` dimension coordinate: + +.. doctest:: merge + :options: +ELLIPSIS, +NORMALIZE_WHITESPACE + + >>> print(cubes) + 0: air_temperature / (kelvin) (y: 4; x: 5) + 1: air_temperature / (kelvin) (y: 4; x: 5) + 2: air_temperature / (kelvin) (y: 4; x: 5) + + >>> print(cubes[0]) + air_temperature / (kelvin) (y: 4; x: 5) + ... + Scalar coordinates: + z: 1 meters + >>> print(cubes[1]) + air_temperature / (kelvin) (y: 4; x: 5) + ... + Scalar coordinates: + z: 2 meters + >>> print(cubes[2]) + air_temperature / (kelvin) (y: 4; x: 5) + ... + Scalar coordinates: + z: 3 meters + + >>> print(cubes.merge()) + 0: air_temperature / (kelvin) (z: 3; y: 4; x: 5) + +The following diagram illustrates what has taken place in this example: + +.. image:: merge.png + :alt: Pictographic of merge. + :align: center + +The diagram illustrates that we have three input cubes of identical shape +that stack on the ``z`` dimension. +After merging our three input cubes we get a new :class:`~iris.cube.CubeList` containing +one cube with a new ``z`` coordinate. + + +Using CubeList.merge_cube +========================= + +The :meth:`~iris.cube.CubeList.merge_cube` method guarantees that *exactly one cube will be returned* +as a result of merging the input cubes. +If :meth:`~iris.cube.CubeList.merge_cube` cannot fulfil this guarantee, a descriptive error +will be raised providing details to help diagnose the differences between the input cubes. +In contrast, the :meth:`~iris.cube.CubeList.merge` method makes no check on the number of cubes returned. + +To demonstrate the differences between :meth:`~iris.cube.CubeList.merge` +and :meth:`~iris.cube.CubeList.merge_cube`, let's return to our three cubes +from the earlier merge example. + +For the purposes of this example a ``Conventions`` attribute has been added to the first +cube's :data:`~iris.cube.Cube.attributes` dictionary. +Remember that the attributes *must* be consistent across all cubes in order to merge +into a single cube: + +.. testsetup:: merge_vs_merge_cube + + import numpy as np + import iris + def _xy_cube(z): + cube = iris.cube.Cube(np.arange(20).reshape(4, 5), 'air_temperature', units='kelvin') + cube.add_dim_coord(iris.coords.DimCoord(range(4), long_name='y'), 0) + cube.add_dim_coord(iris.coords.DimCoord(range(5), long_name='x'), 1) + cube.add_aux_coord(iris.coords.DimCoord(z, long_name='z', units='meters')) + return cube + cubes = iris.cube.CubeList([_xy_cube(1), _xy_cube(2), _xy_cube(3)]) + cubes[0].attributes['Conventions'] = 'CF-1.5' + +.. doctest:: merge_vs_merge_cube + :options: +ELLIPSIS, +NORMALIZE_WHITESPACE + + >>> print(cubes) + 0: air_temperature / (kelvin) (y: 4; x: 5) + 1: air_temperature / (kelvin) (y: 4; x: 5) + 2: air_temperature / (kelvin) (y: 4; x: 5) + + >>> print(cubes[0].attributes) + {'Conventions': 'CF-1.5'} + >>> print(cubes[1].attributes) + {} + >>> print(cubes[2].attributes) + {} + + >>> print(cubes.merge()) + 0: air_temperature / (kelvin) (y: 4; x: 5) + 1: air_temperature / (kelvin) (z: 2; y: 4; x: 5) + + >>> print(cubes.merge_cube()) + Traceback (most recent call last): + ... + raise iris.exceptions.MergeError(msgs) + iris.exceptions.MergeError: failed to merge into a single cube. + cube.attributes keys differ: 'Conventions' + +Note that :meth:`~iris.cube.CubeList.merge` returns two cubes here. +All the cubes that can be merged have been merged. Any cubes that can't be merged are +included unchanged in the returned :class:`~iris.cube.CubeList`. +When :meth:`~iris.cube.CubeList.merge_cube` is called on ``cubes`` it raises a +descriptive error that highlights the difference in the ``attributes`` dictionaries. +It is this difference that is preventing ``cubes`` being merged into a +single cube. An example of fixing an issue like this can be found in the +:ref:`merge_concat_common_issues` section. + + +Merge in Iris load +================== + +The CubeList's :meth:`~iris.cube.CubeList.merge` method is used internally +by the three main Iris load functions introduced in :doc:`loading_iris_cubes`. +For file formats such as GRIB and PP, which store fields as many +individual 2D arrays, Iris loading uses the ``merge`` process to produce a +more intuitive higher dimensional cube of each phenomenon where possible. + +Sometimes the ``merge`` process doesn't behave as expected. In almost all +cases this is due to the input cubes containing unexpected or inconsistent metadata. +For this reason, a fourth Iris file loading function, :func:`iris.load_raw`, exists. +The :func:`~iris.load_raw` function is intended as a diagnostic tool that can be used to +load cubes from files without the ``merge`` process taking place. The return value of +:func:`iris.load_raw` is always a :class:`~iris.cube.CubeList` instance. +You can then call the :meth:`~iris.cube.CubeList.merge_cube` method on this returned +:class:`~iris.cube.CubeList` to help identify merge related load issues. + + +Concatenate +----------- + +We've seen that the ``concatenate`` process combines multiple input cubes into a +single resultant cube with the same *number of dimensions* as the input cubes, +but with the length of one or more dimensions extended by *joining together +sequential dimension coordinates*. + +In order to extend the dimensions lengths, the ``concatenate`` process requires input cubes +with dimension coordinates that can be combined together into monotonic sequences. +The order of the input cubes does not affect the ``concatenate`` process. + +.. important:: + + The shape, metadata, attributes, coordinates, coordinates metadata, fill value and + other aspects of the input cubes must be consistent across all of the input cubes. + + The ``concatenate`` process will fail if these are not consistent. Such failures are + covered in the :ref:`merge_concat_common_issues` section. + + +The ``concatenate`` process can be accessed using two methods. The two methods are +:meth:`~iris.cube.CubeList.concatenate` and :meth:`~iris.cube.CubeList.concatenate_cube`, +which are described below. + + +Using CubeList.concatenate +========================== + +The :meth:`CubeList.concatenate ` method operates on a list +of cubes and returns a new :class:`~iris.cube.CubeList` containing the cubes +that have been concatenated. + +Let's have a look at the :meth:`~iris.cube.CubeList.concatenate` method in operation. +In the example below we have three 3D ``(t, y, x)`` cubes whose ``t`` coordinates +have sequentially increasing ranges. +These cubes can be concatenated by combining the ``t`` coordinates of the input +cubes to form a new cube with an extended ``t`` coordinate: + +.. testsetup:: concatenate + + import numpy as np + import iris + def _xyt_cube(t): + cube = iris.cube.Cube(np.arange(12 * len(t)).reshape(-1, 3, 4), 'air_temperature', units='kelvin') + cube.add_dim_coord(iris.coords.DimCoord(range(3), long_name='y'), 1) + cube.add_dim_coord(iris.coords.DimCoord(range(4), long_name='x'), 2) + cube.add_dim_coord(iris.coords.DimCoord(t, long_name='t'), 0) + return cube + cubes = iris.cube.CubeList([_xyt_cube(np.arange(31)), _xyt_cube(np.arange(28) + 31), _xyt_cube(np.arange(31) + 59)]) + +.. doctest:: concatenate + :options: +ELLIPSIS, +NORMALIZE_WHITESPACE + + >>> print(cubes) + 0: air_temperature / (kelvin) (t: 31; y: 3; x: 4) + 1: air_temperature / (kelvin) (t: 28; y: 3; x: 4) + 2: air_temperature / (kelvin) (t: 31; y: 3; x: 4) + + >>> print(cubes.concatenate()) + 0: air_temperature / (kelvin) (t: 90; y: 3; x: 4) + + +The following diagram illustrates what has taken place in this example: + +.. image:: concat.png + :alt: Pictographic of concatenate. + :align: center + +The diagram illustrates that we have three 3D input cubes +that line up on the ``t`` dimension. +After concatenating our three input cubes we get a new :class:`~iris.cube.CubeList` +containing one cube with an extended ``t`` coordinate. + + +Using CubeList.concatenate_cube +=============================== + +The :meth:`~iris.cube.CubeList.concatenate_cube` method guarantees that *exactly one +cube will be returned* as a result of concatenating the input cubes. +If :meth:`~iris.cube.CubeList.concatenate_cube` cannot fulfil this guarantee, a descriptive error +will be raised providing details to help diagnose the differences between the input cubes. +In contrast, the :meth:`~iris.cube.CubeList.concatenate` method makes no check on the number +of cubes returned. + +To demonstrate the differences between :meth:`~iris.cube.CubeList.concatenate` +and :meth:`~iris.cube.CubeList.concatenate_cube`, let's return to our three cubes +from the earlier concatenate example. + +For the purposes of this example we'll add a *History* attribute to the first +cube's :data:`~iris.cube.Cube.attributes` dictionary. +Remember that the attributes *must* be consistent across all cubes in order to +concatenate into a single cube: + +.. testsetup:: concatenate_vs_concatenate_cube + + import numpy as np + import iris + def _xyt_cube(t): + cube = iris.cube.Cube(np.arange(12 * len(t)).reshape(-1, 3, 4), 'air_temperature', units='kelvin') + cube.add_dim_coord(iris.coords.DimCoord(range(3), long_name='y'), 1) + cube.add_dim_coord(iris.coords.DimCoord(range(4), long_name='x'), 2) + cube.add_dim_coord(iris.coords.DimCoord(t, long_name='t'), 0) + return cube + cubes = iris.cube.CubeList([_xyt_cube(np.arange(31)), _xyt_cube(np.arange(28) + 31), _xyt_cube(np.arange(31) + 59)]) + cubes[0].attributes['History'] = 'Created 2010-06-30' + +.. doctest:: concatenate_vs_concatenate_cube + :options: +ELLIPSIS, +NORMALIZE_WHITESPACE + + >>> print(cubes) + 0: air_temperature / (kelvin) (t: 31; y: 3; x: 4) + 1: air_temperature / (kelvin) (t: 28; y: 3; x: 4) + 2: air_temperature / (kelvin) (t: 31; y: 3; x: 4) + + >>> print(cubes[0].attributes) + {'History': 'Created 2010-06-30'} + >>> print(cubes[1].attributes) + {} + + >>> print(cubes.concatenate()) + 0: air_temperature / (kelvin) (t: 31; y: 3; x: 4) + 1: air_temperature / (kelvin) (t: 59; y: 3; x: 4) + >>> print(cubes.concatenate_cube()) + Traceback (most recent call last): + ... + raise iris.exceptions.ConcatenateError(msgs) + iris.exceptions.ConcatenateError: failed to concatenate into a single cube. + Cube metadata differs for phenomenon: air_temperature + + +Note that :meth:`~iris.cube.CubeList.concatenate` returns two cubes here. +All the cubes that can be concatenated have been concatenated. Any cubes that can't be concatenated are +included unchanged in the returned :class:`~iris.cube.CubeList`. +When :meth:`~iris.cube.CubeList.concatenate_cube` is called on ``cubes`` it raises a +descriptive error that highlights the difference in the ``attributes`` dictionaries. +It is this difference that is preventing ``cubes`` being concatenated into a +single cube. An example of fixing an issue like this can be found in the +:ref:`merge_concat_common_issues` section. + + +.. _merge_concat_common_issues: + +Common issues with merge and concatenate +---------------------------------------- + +The Iris algorithms that drive :meth:`~iris.cube.CubeList.merge` and +:meth:`~iris.cube.CubeList.concatenate` are complex and depend +on a number of different elements of the input cubes being consistent across +all input cubes. +If this consistency is not maintained then the +:meth:`~iris.cube.CubeList.merge` or +:meth:`~iris.cube.CubeList.concatenate` process can fail in a +seemingly arbitrary manner. + +The methods :meth:`~iris.cube.CubeList.merge_cube` and +:meth:`~iris.cube.CubeList.concatenate_cube` +were introduced to Iris to help you locate differences in input cubes +that prevent the input cubes merging or concatenating. +Nevertheless, certain difficulties with using +:meth:`~iris.cube.CubeList.merge` and +:meth:`~iris.cube.CubeList.concatenate` occur frequently. +This section describes these common difficulties, why they arise and +what you can do to avoid them. + + +Merge +===== + +.. _merge_issues_attrs_mismatch: + +**Attributes Mismatch** + +Differences in the :data:`~iris.cube.Cube.attributes` the input cubes probably +cause the greatest amount of merge-related difficulties. +In recognition of this, Iris has a helper function, +:func:`~iris.experimental.equalise_cubes.equalise_attributes`, to equalise +attributes differences in the input cubes. + +.. note:: + + The functionality provided by :func:`iris.util.describe_diff` and + :meth:`iris.cube.Cube.is_compatible` are **not** designed to give user + indication of whether two cubes can be merged. + +To demonstrate using :func:`~iris.experimental.equalise_cubes.equalise_attributes`, +let's return to our non-merging list of input cubes from the merge_cube example +from earlier. +We'll call :func:`~iris.experimental.equalise_cubes.equalise_attributes` on the +input cubes before merging the input cubes using :meth:`~iris.cube.CubeList.merge_cube`: + +.. doctest:: merge_vs_merge_cube + :options: +ELLIPSIS, +NORMALIZE_WHITESPACE + + >>> from iris.experimental.equalise_cubes import equalise_attributes + >>> print(cubes) + 0: air_temperature / (kelvin) (y: 4; x: 5) + 1: air_temperature / (kelvin) (y: 4; x: 5) + 2: air_temperature / (kelvin) (y: 4; x: 5) + + >>> print(cubes[0].attributes) + {'Conventions': 'CF-1.5'} + >>> print(cubes[1].attributes) + {} + >>> print(cubes[2].attributes) + {} + + >>> print(cubes.merge_cube()) + Traceback (most recent call last): + ... + raise iris.exceptions.MergeError(msgs) + iris.exceptions.MergeError: failed to merge into a single cube. + cube.attributes keys differ: 'Conventions' + + >>> equalise_attributes(cubes) + + >>> print(cubes[0].attributes) + {} + + >>> print(cubes.merge_cube()) + air_temperature / (kelvin) (z: 3; y: 4; x: 5) + Dimension coordinates: + z x - - + y - x - + x - - x + + +**Incomplete Data** + +Merging input cubes with inconsistent dimension lengths can cause misleading results. +This is a common problem when merging cubes generated by different ensemble members in a model run. + +The misleading results cause the merged cube to gain an anonymous leading dimension. +All the merged coordinates appear as auxiliary coordinates on the anonymous leading dimension. +This is shown in the example below:: + + >>> print(cube) + surface_temperature / (K) (-- : 5494; latitude: 325; longitude: 432) + Dimension coordinates: + latitude - x - + longitude - - x + Auxiliary coordinates: + forecast_month x - - + forecast_period x - - + forecast_reference_time x - - + realization x - - + time x - - + + +**Merging Duplicate Cubes** + +The Iris load process does not merge duplicate cubes (two or more identical cubes in +the input cubes) by default. +This behaviour can be changed by setting the ``unique`` keyword argument +to :meth:`~iris.cube.CubeList.merge` to ``False``. + +Merging duplicate cubes can cause misleading results. Let's demonstrate these +behaviours and misleading results with the following example. +In this example we have three input cubes. +The first has a scalar ``z`` coordinate with value 1, the second has a +scalar ``z`` coordinate with value 2 and the third has a scalar ``z`` +coordinate with value 1. +The first and third cubes are thus identical. +We will demonstrate the effect of merging the input cubes with ``unique=False`` +(duplicate cubes allowed) and ``unique=True`` (duplicate cubes not allowed, which +is the default behaviour): + +.. testsetup:: merge_duplicate + + import numpy as np + import iris + def _xy_cube(z): + cube = iris.cube.Cube(np.arange(20).reshape(4, 5), 'air_temperature', units='kelvin') + cube.add_dim_coord(iris.coords.DimCoord(range(4), long_name='y'), 0) + cube.add_dim_coord(iris.coords.DimCoord(range(5), long_name='x'), 1) + cube.add_aux_coord(iris.coords.DimCoord(z, long_name='z', units='meters')) + return cube + cubes = iris.cube.CubeList([_xy_cube(1), _xy_cube(2), _xy_cube(1)]) + +.. doctest:: merge_duplicate + :options: +ELLIPSIS, +NORMALIZE_WHITESPACE + + >>> print(cubes) + 0: air_temperature / (kelvin) (y: 4; x: 5) + 1: air_temperature / (kelvin) (y: 4; x: 5) + 2: air_temperature / (kelvin) (y: 4; x: 5) + + >>> print(cubes.merge(unique=False)) + 0: air_temperature / (kelvin) (z: 2; y: 4; x: 5) + 1: air_temperature / (kelvin) (z: 2; y: 4; x: 5) + + >>> print(cubes.merge()) # unique=True is the default. + Traceback (most recent call last): + ... + iris.exceptions.DuplicateDataError: failed to merge into a single cube. + Duplicate 'air_temperature' cube, with scalar coordinates z=Cell(point=1, bound=None) + + +Notice how merging the input cubes with duplicate cubes allowed produces a result +with **four** `z` coordinate values. +Closer inspection of these two resultant cubes demonstrates that the +scalar ``z`` coordinate with value 2 is found in both cubes. + +Trying to merge the input cubes with duplicate cubes not allowed raises an +error highlighting the presence of the duplicate cube. + + +**Single value coordinates** + +Coordinates containing only a single value can cause confusion when +combining input cubes. Remember: + +* The ``merge`` process combines multiple input cubes into a + single resultant cube with new dimensions created from the + **scalar** *coordinate values* of the input cubes. +* The ``concatenate`` process combines multiple input cubes into a + single resultant cube with the same *number of dimensions* as the input cubes, + but with the length of one or more dimensions extended by *joining together + sequential* **dimension** *coordinates*. + +In Iris terminology a **scalar** coordinate is a +coordinate of length 1 *which does not describe a data dimension*. + +Let's look at two example cubes to demonstrate this. + +If your cubes are similar to those below (the single value ``z`` coordinate +is not on a dimension) then use :meth:`~iris.cube.CubeList.merge` to +combine your cubes:: + + >>> print(cubes[0]) + air_temperature / (kelvin) (y: 4; x: 5) + Dimension coordinates: + x x - + y - x + Scalar coordinates: + z: 1 + >>> print(cubes[1]) + air_temperature / (kelvin) (y: 4; x: 5) + Dimension coordinates: + x x - + y - x + Scalar coordinates: + z: 2 + + +If your cubes are similar to those below (the single value ``z`` coordinate is +associated with a dimension) then use :meth:`~iris.cube.CubeList.concatenate` to +combine your cubes:: + + >>> print(cubes) + 0: air_temperature / (kelvin) (z: 1; y: 4; x: 5) + 1: air_temperature / (kelvin) (z: 1; y: 4; x: 5) + + +Concatenate +=========== + +**Time Units** + +Differences in the units of the time coordinates of the input cubes probably cause +the greatest amount of concatenate-related difficulties. +In recognition of this, Iris has a helper function, +:func:`~iris.util.unify_time_units`, to apply a common time unit to all the input cubes. + +To demonstrate using :func:`~iris.util.unify_time_units`, +let's adapt our list of input cubes from the ``concatenate_cube`` example from earlier. +We'll give the input cubes unequal time coordinate units and call +:func:`~iris.util.unify_time_units` on the input cubes before concatenating +the input cubes using :meth:`~iris.cube.CubeList.concatenate_cube`: + +.. testsetup:: concatenate_time_units + + import numpy as np + import iris + def _xyt_cube(t): + cube = iris.cube.Cube(np.arange(12 * len(t)).reshape(-1, 3, 4), 'air_temperature', units='kelvin') + cube.add_dim_coord(iris.coords.DimCoord(range(3), long_name='y'), 1) + cube.add_dim_coord(iris.coords.DimCoord(range(4), long_name='x'), 2) + cube.add_dim_coord(iris.coords.DimCoord(t, long_name='t'), 0) + return cube + cubes = iris.cube.CubeList([_xyt_cube(np.arange(31).astype(np.float64)), + _xyt_cube(np.arange(28).astype(np.float64) + 31), + _xyt_cube(np.arange(31).astype(np.float64) + 59)]) + cubes[0].coord('t').units = 'days since 1990-02-15' + cubes[1].coord('t').units = 'days since 1970-01-01' + cubes[2].coord('t').units = 'days since 1970-01-01' + +.. doctest:: concatenate_time_units + :options: +ELLIPSIS, +NORMALIZE_WHITESPACE + + >>> from iris.util import unify_time_units + >>> print(cubes) + 0: air_temperature / (kelvin) (t: 31; y: 3; x: 4) + 1: air_temperature / (kelvin) (t: 28; y: 3; x: 4) + 2: air_temperature / (kelvin) (t: 31; y: 3; x: 4) + + >>> print(cubes[0].coord('t').units) + days since 1990-02-15 + >>> print(cubes[1].coord('t').units) + days since 1970-01-01 + + >>> print(cubes.concatenate_cube()) + Traceback (most recent call last): + ... + ConcatenateError: failed to concatenate into a single cube. + Dimension coordinates metadata differ: t != t + + >>> unify_time_units(cubes) + + >>> print(cubes[1].coord('t').units) + days since 1990-02-15 + + >>> print(cubes.concatenate_cube()) + air_temperature / (kelvin) (t: 90; y: 3; x: 4) + Dimension coordinates: + t x - - + y - x - + x - - x + +**Attributes Mismatch** + +The ``concatenate`` process is affected by attributes mismatch on input cubes +in the same way that the ``merge`` process is. +The :ref:`Attributes Mismatch ` section earlier in this +chapter gives further information on attributes mismatch. diff --git a/docs/iris/src/userguide/merge_and_concat.svg b/docs/iris/src/userguide/merge_and_concat.svg new file mode 100644 index 0000000000..d5f79713f0 --- /dev/null +++ b/docs/iris/src/userguide/merge_and_concat.svg @@ -0,0 +1,362 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + merge + + + + + + + + concatenate + + + + + + + + + + + + + diff --git a/docs/iris/src/userguide/multi_array.svg b/docs/iris/src/userguide/multi_array.svg index 104af87a4a..d28f6d71d6 100644 --- a/docs/iris/src/userguide/multi_array.svg +++ b/docs/iris/src/userguide/multi_array.svg @@ -15,7 +15,6 @@ version="1.1" inkscape:version="0.47 r22583" sodipodi:docname="multi_array.svg" - inkscape:export-filename="/home/h02/itpe/fcm/iris/iris/active/docs/iris/src/userguide/multi_array.png" inkscape:export-xdpi="90" inkscape:export-ydpi="90"> >> import iris >>> filename = iris.sample_data_path('rotated_pole.nc') >>> cube = iris.load_cube(filename) - >>> print cube + >>> print(cube) air_pressure_at_sea_level / (Pa) (grid_latitude: 22; grid_longitude: 36) Dimension coordinates: grid_latitude x - @@ -42,9 +42,9 @@ This representation is equivalent to passing the cube to the :func:`str` functio any Python variable to get a string representation of that variable. Similarly there exist other standard functions for interrogating your variable: :func:`repr`, :func:`type` for example:: - print str(cube) - print repr(cube) - print type(cube) + print(str(cube)) + print(repr(cube)) + print(type(cube)) Other, more verbose, functions also exist which give information on **what** you can do with *any* given variable. In most cases it is reasonable to ignore anything starting with a "``_``" (underscore) or a "``__``" (double underscore):: @@ -60,27 +60,27 @@ Every cube has a standard name, long name and units which are accessed with :attr:`Cube.long_name ` and :attr:`Cube.units ` respectively:: - print cube.standard_name - print cube.long_name - print cube.units + print(cube.standard_name) + print(cube.long_name) + print(cube.units) Interrogating these with the standard :func:`type` function will tell you that ``standard_name`` and ``long_name`` are either a string or ``None``, and ``units`` is an instance of :class:`iris.unit.Unit`. You can access a string representing the "name" of a cube with the :meth:`Cube.name() ` method:: - print cube.name() + print(cube.name()) The result of which is **always** a string. Each cube also has a :mod:`numpy` array which represents the phenomenon of the cube which can be accessed with the :attr:`Cube.data ` attribute. As you can see the type is a :class:`numpy n-dimensional array `:: - print type(cube.data) + print(type(cube.data)) .. note:: - When loading some file formats in Iris, the data itself is not loaded until the **first** time that the data is requested. + When loading from most file formats in Iris, the data itself is not loaded until the **first** time that the data is requested. Hence you may have noticed that running the previous command for the first time takes a little longer than it does for subsequent calls. @@ -89,8 +89,12 @@ Each cube also has a :mod:`numpy` array which represents the phenomenon of the c For convenience :attr:`~iris.cube.Cube.shape` and :attr:`~iris.cube.Cube.ndim` attributes exists on a cube, which can tell you the shape of the cube's data without loading it:: - print cube.shape - print cube.ndim + print(cube.shape) + print(cube.ndim) + + For more on the benefits, handling and uses of lazy data, see + :doc:`Real and Lazy Data ` + You can change the units of a cube using the :meth:`~iris.cube.Cube.convert_units` method. For example:: @@ -103,7 +107,7 @@ As well as changing the value of the :attr:`~iris.cube.Cube.units` attribute thi Some cubes represent a processed phenomenon which are represented with cell methods, these can be accessed on a cube with the :attr:`Cube.cell_methods ` attribute:: - print cube.cell_methods + print(cube.cell_methods) Accessing coordinates on the cube @@ -113,7 +117,7 @@ A cube's coordinates can be retrieved via :meth:`Cube.coords >> print ', '.join(sorted(coord_names)) + >>> print(', '.join(sorted(coord_names))) forecast_period, forecast_reference_time, grid_latitude, grid_longitude, time To get an individual coordinate given its name, the :meth:`Cube.coord ` method can be used:: coord = cube.coord('grid_latitude') - print type(coord) + print(type(coord)) Every coordinate has a :attr:`Coord.standard_name `, :attr:`Coord.long_name `, and :attr:`Coord.units ` attribute:: - print coord.standard_name - print coord.long_name - print coord.units + print(coord.standard_name) + print(coord.long_name) + print(coord.units) Additionally every coordinate can provide its :attr:`~iris.coords.Coord.points` and :attr:`~iris.coords.Coord.bounds` numpy array. If the coordinate has no bounds ``None`` will be returned:: - print type(coord.points) - print type(coord.bounds) + print(type(coord.points)) + print(type(coord.bounds)) Adding metadata to a cube @@ -153,7 +157,7 @@ We can add and remove coordinates via :func:`Cube.add_dim_coord>> import iris.coords >>> new_coord = iris.coords.AuxCoord(1, long_name='my_custom_coordinate', units='no_unit') >>> cube.add_aux_coord(new_coord) - >>> print cube + >>> print(cube) air_pressure_at_sea_level / (Pa) (grid_latitude: 22; grid_longitude: 36) Dimension coordinates: grid_latitude x - @@ -195,7 +199,7 @@ model mean that the run is spread over several days. If we try to load the data directly for ``surface_temperature``: >>> filename = iris.sample_data_path('GloSea4', '*.pp') - >>> print iris.load(filename, 'surface_temperature') + >>> print(iris.load(filename, 'surface_temperature')) 0: surface_temperature / (K) (time: 6; forecast_reference_time: 2; latitude: 145; longitude: 192) 1: surface_temperature / (K) (time: 6; forecast_reference_time: 2; latitude: 145; longitude: 192) 2: surface_temperature / (K) (realization: 9; time: 6; latitude: 145; longitude: 192) @@ -210,7 +214,7 @@ which, given the filename, we could extract:: filename = iris.sample_data_path('GloSea4', 'ensemble_001.pp') realization = int(filename[-6:-3]) - print realization + print(realization) We can solve this problem by adding the appropriate metadata, on load, by using a callback function, which runs on a field by field basis *before* they are automatically merged together: @@ -230,7 +234,7 @@ by field basis *before* they are automatically merged together: filename = iris.sample_data_path('GloSea4', '*.pp') - print iris.load(filename, 'surface_temperature', callback=lagged_ensemble_callback) + print(iris.load(filename, 'surface_temperature', callback=lagged_ensemble_callback)) The result is a single cube which represents the data in a form that was expected: diff --git a/docs/iris/src/userguide/plotting_a_cube.rst b/docs/iris/src/userguide/plotting_a_cube.rst index ebb8c2e42d..d82cbbb027 100644 --- a/docs/iris/src/userguide/plotting_a_cube.rst +++ b/docs/iris/src/userguide/plotting_a_cube.rst @@ -53,7 +53,7 @@ Subsequent changes to your figure will be automatically rendered in the window. The current rendering mode can be determined as follows:: import matplotlib.pyplot as plt - print plt.isinteractive() + print(plt.isinteractive()) .. note:: @@ -64,7 +64,7 @@ The current rendering mode can be determined as follows:: import matplotlib.pyplot as plt plt.interactive(True) plt.plot([1, 2, 2.5]) - print plt.isinteractive() + print(plt.isinteractive()) Interactive mode does not clear out the figure buffer, so figures have to be explicitly closed when they are finished with:: @@ -157,12 +157,11 @@ The syntax is very similar to that which you would provide to Matplotlib's equivalent :py:func:`matplotlib.pyplot.plot` and indeed all of the keyword arguments are equivalent: -.. literalinclude:: plotting_examples/1d_simple.py - .. plot:: userguide/plotting_examples/1d_simple.py + :include-source: For more information on how this example reduced the 2D cube to 1 dimension see -the previous section entitled :doc:`reducing_a_cube`. +the previous section entitled :doc:`subsetting_a_cube`. .. note:: @@ -177,9 +176,8 @@ to a plot. For example, the previous plot can be improved quickly by replacing **iris.plot** with **iris.quickplot**: -.. literalinclude:: plotting_examples/1d_quickplot_simple.py - .. plot:: userguide/plotting_examples/1d_quickplot_simple.py + :include-source: @@ -192,9 +190,8 @@ and providing the label keyword to identify it. Once all of the lines have been added the :func:`matplotlib.pyplot.legend` function can be called to indicate that a legend is desired: -.. literalinclude:: ../../example_code/graphics/lineplot_with_legend.py - -.. plot:: ../example_code/graphics/lineplot_with_legend.py +.. plot:: ../example_code/General/lineplot_with_legend.py + :include-source: This example of consecutive ``qplt.plot`` calls coupled with the :func:`Cube.slices() ` method on a cube shows @@ -238,9 +235,8 @@ Cube contour A simple contour plot of a cube can be created with either the :func:`iris.plot.contour` or :func:`iris.quickplot.contour` functions: -.. literalinclude:: plotting_examples/cube_contour.py - .. plot:: userguide/plotting_examples/cube_contour.py + :include-source: Cube filled contour @@ -248,9 +244,8 @@ Cube filled contour Similarly a filled contour plot of a cube can be created with the :func:`iris.plot.contourf` or :func:`iris.quickplot.contourf` functions: -.. literalinclude:: plotting_examples/cube_contourf.py - .. plot:: userguide/plotting_examples/cube_contourf.py + :include-source: Cube block plot @@ -267,9 +262,8 @@ or :func:`iris.quickplot.pcolormesh`. and :func:`iris.quickplot.pcolormesh` will attempt to guess suitable values based on their points (see also :func:`iris.coords.Coord.guess_bounds()`). -.. literalinclude:: plotting_examples/cube_blockplot.py - .. plot:: userguide/plotting_examples/cube_blockplot.py + :include-source: .. _brewer-info: @@ -313,7 +307,8 @@ Plotting with Brewer ==================== To plot a cube using a Brewer colour palette, simply select one of the Iris -registered Brewer colour palettes and plot the cube as normal. +registered Brewer colour palettes and plot the cube as normal. The Brewer palettes +become available once :mod:`iris.plot` or :mod:`iris.quickplot` are imported. .. plot:: userguide/plotting_examples/cube_brewer_contourf.py :include-source: diff --git a/docs/iris/src/userguide/plotting_examples/1d_quickplot_simple.py b/docs/iris/src/userguide/plotting_examples/1d_quickplot_simple.py index d4b1fc412e..75462101a0 100644 --- a/docs/iris/src/userguide/plotting_examples/1d_quickplot_simple.py +++ b/docs/iris/src/userguide/plotting_examples/1d_quickplot_simple.py @@ -1,3 +1,7 @@ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + import matplotlib.pyplot as plt import iris diff --git a/docs/iris/src/userguide/plotting_examples/1d_simple.py b/docs/iris/src/userguide/plotting_examples/1d_simple.py index e099fe6a10..8cb3f45643 100644 --- a/docs/iris/src/userguide/plotting_examples/1d_simple.py +++ b/docs/iris/src/userguide/plotting_examples/1d_simple.py @@ -1,3 +1,7 @@ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + import matplotlib.pyplot as plt import iris diff --git a/docs/iris/src/userguide/plotting_examples/1d_with_legend.py b/docs/iris/src/userguide/plotting_examples/1d_with_legend.py index 1e47aa078d..b0aee43c4a 100644 --- a/docs/iris/src/userguide/plotting_examples/1d_with_legend.py +++ b/docs/iris/src/userguide/plotting_examples/1d_with_legend.py @@ -1,3 +1,7 @@ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + import matplotlib.pyplot as plt import iris @@ -9,7 +13,8 @@ # Load exactly one cube from the given file temperature = iris.load_cube(fname) -# We are only interested in a small number of longitudes (the 4 after and including the 5th element), so index them out +# We are only interested in a small number of longitudes (the 4 after and +# including the 5th element), so index them out temperature = temperature[5:9, :] for cube in temperature.slices('longitude'): @@ -18,9 +23,9 @@ cube_label = 'latitude: %s' % cube.coord('latitude').points[0] # Plot the cube, and associate it with a label - iplt.plot(cube, label=cube_label ) + iplt.plot(cube, label=cube_label) -#match the longitude range to global +# Match the longitude range to global max_lon = temperature.coord('longitude').points.max() min_lon = temperature.coord('longitude').points.min() plt.xlim(min_lon, max_lon) diff --git a/docs/iris/src/userguide/plotting_examples/brewer.py b/docs/iris/src/userguide/plotting_examples/brewer.py index 722925777e..2d61e276ab 100644 --- a/docs/iris/src/userguide/plotting_examples/brewer.py +++ b/docs/iris/src/userguide/plotting_examples/brewer.py @@ -1,18 +1,22 @@ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + import matplotlib.pyplot as plt import numpy as np import iris.palette -a = np.linspace(0, 1, 256).reshape(1,-1) -a = np.vstack((a,a)) +a = np.linspace(0, 1, 256).reshape(1, -1) +a = np.vstack((a, a)) maps = sorted(iris.palette.CMAP_BREWER) nmaps = len(maps) fig = plt.figure(figsize=(7, 10)) fig.subplots_adjust(top=0.99, bottom=0.01, left=0.2, right=0.99) -for i,m in enumerate(maps): +for i, m in enumerate(maps): ax = plt.subplot(nmaps, 1, i+1) plt.axis("off") plt.imshow(a, aspect='auto', cmap=plt.get_cmap(m), origin='lower') diff --git a/docs/iris/src/userguide/plotting_examples/cube_blockplot.py b/docs/iris/src/userguide/plotting_examples/cube_blockplot.py index dd7552a8bd..a6273a274c 100644 --- a/docs/iris/src/userguide/plotting_examples/cube_blockplot.py +++ b/docs/iris/src/userguide/plotting_examples/cube_blockplot.py @@ -1,3 +1,7 @@ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + import matplotlib.pyplot as plt import iris diff --git a/docs/iris/src/userguide/plotting_examples/cube_brewer_cite_contourf.py b/docs/iris/src/userguide/plotting_examples/cube_brewer_cite_contourf.py index 335bb46637..9ba68fc47a 100644 --- a/docs/iris/src/userguide/plotting_examples/cube_brewer_cite_contourf.py +++ b/docs/iris/src/userguide/plotting_examples/cube_brewer_cite_contourf.py @@ -1,4 +1,7 @@ -import matplotlib.cm as mpl_cm + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + import matplotlib.pyplot as plt import iris @@ -9,8 +12,8 @@ fname = iris.sample_data_path('air_temp.pp') temperature_cube = iris.load_cube(fname) -# Load a Cynthia Brewer palette. -brewer_cmap = mpl_cm.get_cmap('brewer_Purples_09') +# Get the Purples "Brewer" palette. +brewer_cmap = plt.get_cmap('brewer_Purples_09') # Draw the contours, with n-levels set for the map colours (9). # NOTE: needed as the map is non-interpolated, but matplotlib does not provide diff --git a/docs/iris/src/userguide/plotting_examples/cube_brewer_contourf.py b/docs/iris/src/userguide/plotting_examples/cube_brewer_contourf.py index a2f4e48034..aacf129c30 100644 --- a/docs/iris/src/userguide/plotting_examples/cube_brewer_contourf.py +++ b/docs/iris/src/userguide/plotting_examples/cube_brewer_contourf.py @@ -1,3 +1,7 @@ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + import matplotlib.cm as mpl_cm import matplotlib.pyplot as plt diff --git a/docs/iris/src/userguide/plotting_examples/cube_contour.py b/docs/iris/src/userguide/plotting_examples/cube_contour.py index 1c862f2055..0ec2fa7be4 100644 --- a/docs/iris/src/userguide/plotting_examples/cube_contour.py +++ b/docs/iris/src/userguide/plotting_examples/cube_contour.py @@ -1,3 +1,7 @@ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + import matplotlib.pyplot as plt import iris @@ -14,6 +18,6 @@ plt.gca().coastlines() # Add contour labels based on the contour we have just created. -plt.clabel(contour) +plt.clabel(contour, inline=False) plt.show() diff --git a/docs/iris/src/userguide/plotting_examples/cube_contourf.py b/docs/iris/src/userguide/plotting_examples/cube_contourf.py index 1c66cf09b3..21ebb1a214 100644 --- a/docs/iris/src/userguide/plotting_examples/cube_contourf.py +++ b/docs/iris/src/userguide/plotting_examples/cube_contourf.py @@ -1,3 +1,7 @@ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + import matplotlib.pyplot as plt import iris diff --git a/docs/iris/src/userguide/real_and_lazy_data.rst b/docs/iris/src/userguide/real_and_lazy_data.rst new file mode 100644 index 0000000000..84a35efa64 --- /dev/null +++ b/docs/iris/src/userguide/real_and_lazy_data.rst @@ -0,0 +1,235 @@ + +.. _real_and_lazy_data: + + +.. testsetup:: * + + import dask.array as da + import iris + import numpy as np + + +================== +Real and Lazy Data +================== + +We have seen in the :doc:`iris_cubes` section of the user guide that +Iris cubes contain data and metadata about a phenomenon. The data element of a cube +is always an array, but the array may be either "real" or "lazy". + +In this section of the user guide we will look specifically at the concepts of +real and lazy data as they apply to the cube and other data structures in Iris. + + +What is real and lazy data? +--------------------------- + +In Iris, we use the term **real data** to describe data arrays that are loaded +into memory. Real data is typically provided as a +`NumPy array `_, +which has a shape and data type that are used to describe the array's data points. +Each data point takes up a small amount of memory, which means large NumPy arrays can +take up a large amount of memory. + +Conversely, we use the term **lazy data** to describe data that is not loaded into memory. +(This is sometimes also referred to as **deferred data**.) +In Iris, lazy data is provided as a +`dask array `_. +A dask array also has a shape and data type +but the dask array's data points remain on disk and only loaded into memory in +small chunks when absolutely necessary. This has key performance benefits for +handling large amounts of data, where both calculation time and storage +requirements can be significantly reduced. + +In Iris, when actual data values are needed from a lazy data array, it is +*'realised'* : this means that all the actual values are read in from the file, +and a 'real' +(i.e. `numpy `_) +array replaces the lazy array within the Iris object. + +Following realisation, the Iris object just contains the actual ('real') +data, so the time cost of reading all the data is not incurred again. +From here on, access to the data is fast, but it now occupies its full memory space. + +In particular, any direct reference to a `cube.data` will realise the cube data +content : any lazy content is lost as the data is read from file, and the cube +content is replaced with a real array. +This is also referred to simply as "touching" the data. + +See the section :ref:`when_real_data` +for more examples of this. + +You can check whether a cube has real data or lazy data by using the method +:meth:`~iris.cube.Cube.has_lazy_data`. For example:: + + >>> cube = iris.load_cube(iris.sample_data_path('air_temp.pp')) + >>> cube.has_lazy_data() + True + # Realise the lazy data. + >>> cube.data + >>> cube.has_lazy_data() + False + + +Benefits +-------- + +The primary advantage of using lazy data is that it enables +`out-of-core processing `_; +that is, the loading and manipulating of datasets without loading the full data into memory. + +There are two key benefits from this : + +**Firstly**, the result of a calculation on a large dataset often occupies much +less storage space than the source data -- such as for instance a maximum data +value calculated over a large number of datafiles. +In these cases the result can be computed in sections, without ever requiring the +entire source dataset to be loaded, thus drastically reducing memory footprint. +This strategy of task division can also enable reduced execution time through the effective +use of parallel processing capabilities. + +**Secondly**, it is often simply convenient to form a calculation on a large +dataset, of which only a certain portion is required at any one time +-- for example, plotting individual timesteps from a large sequence. +In such cases, a required portion can be extracted and realised without calculating the entire result. + +.. _when_real_data: + +When does my data become real? +------------------------------ + +Certain operations, such as cube indexing and statistics, can be +performed in a lazy fashion, producing a 'lazy' result from a lazy input, so +that no realisation immediately occurs. +However other operations, such as plotting or printing data values, will always +trigger the 'realisation' of data. + +When you load a dataset using Iris the data array will almost always initially be +a lazy array. This section details some operations that will realise lazy data +as well as some operations that will maintain lazy data. We use the term **realise** +to mean converting lazy data into real data. + +Most operations on data arrays can be run equivalently on both real and lazy data. +If the data array is real then the operation will be run on the data array +immediately. The results of the operation will be available as soon as processing is completed. +If the data array is lazy then the operation will be deferred and the data array will +remain lazy until you request the result (such as when you read from ``cube.data``):: + + >>> cube = iris.load_cube(iris.sample_data_path('air_temp.pp')) + >>> cube.has_lazy_data() + True + >>> cube += 5 + >>> cube.has_lazy_data() + True + +The process by which the operation is deferred until the result is requested is +referred to as **lazy evaluation**. + +Certain operations, including regridding and plotting, can only be run on real data. +Calling such operations on lazy data will automatically realise your lazy data. + +You can also realise (and so load into memory) your cube's lazy data if you 'touch' the data. +To 'touch' the data means directly accessing the data by calling ``cube.data``, +as in the previous example. + +Core data +^^^^^^^^^ + +Cubes have the concept of "core data". This returns the cube's data in its +current state: + + * If a cube has lazy data, calling the cube's :meth:`~iris.cube.Cube.core_data` method + will return the cube's lazy dask array. Calling the cube's + :meth:`~iris.cube.Cube.core_data` method **will never realise** the cube's data. + * If a cube has real data, calling the cube's :meth:`~iris.cube.Cube.core_data` method + will return the cube's real NumPy array. + +For example:: + + >>> cube = iris.load_cube(iris.sample_data_path('air_temp.pp')) + >>> cube.has_lazy_data() + True + + >>> the_data = cube.core_data() + >>> type(the_data) + + >>> cube.has_lazy_data() + True + + # Realise the lazy data. + >>> cube.data + >>> the_data = cube.core_data() + >>> type(the_data) + + >>> cube.has_lazy_data() + False + + +Coordinates +----------- + +In the same way that Iris cubes contain a data array, Iris coordinates contain a +points array and an optional bounds array. +Coordinate points and bounds arrays can also be real or lazy: + + * A :class:`~iris.coords.DimCoord` will only ever have **real** points and bounds + arrays because of monotonicity checks that realise lazy arrays. + * An :class:`~iris.coords.AuxCoord` can have **real or lazy** points and bounds. + * An :class:`~iris.aux_factory.AuxCoordFactory` (or derived coordinate) + can have **real or lazy** points and bounds. If all of the + :class:`~iris.coords.AuxCoord` instances used to construct the derived coordinate + have real points and bounds then the derived coordinate will have real points + and bounds, otherwise the derived coordinate will have lazy points and bounds. + +Iris cubes and coordinates have very similar interfaces, which extends to accessing +coordinates' lazy points and bounds: + +.. doctest:: + + >>> cube = iris.load_cube(iris.sample_data_path('hybrid_height.nc'), 'air_potential_temperature') + + >>> dim_coord = cube.coord('model_level_number') + >>> print(dim_coord.has_lazy_points()) + False + >>> print(dim_coord.has_bounds()) + False + >>> print(dim_coord.has_lazy_bounds()) + False + + >>> aux_coord = cube.coord('sigma') + >>> print(aux_coord.has_lazy_points()) + True + >>> print(aux_coord.has_bounds()) + True + >>> print(aux_coord.has_lazy_bounds()) + True + + # Realise the lazy points. This will **not** realise the lazy bounds. + >>> points = aux_coord.points + >>> print(aux_coord.has_lazy_points()) + False + >>> print(aux_coord.has_lazy_bounds()) + True + + >>> derived_coord = cube.coord('altitude') + >>> print(derived_coord.has_lazy_points()) + True + >>> print(derived_coord.has_bounds()) + True + >>> print(derived_coord.has_lazy_bounds()) + True + +.. note:: + Printing a lazy :class:`~iris.coords.AuxCoord` will realise its points and bounds arrays! + + +Dask processing options +----------------------- + +Iris uses dask to provide lazy data arrays for both Iris cubes and coordinates, +and for computing deferred operations on lazy arrays. + +Dask provides processing options to control how deferred operations on lazy arrays +are computed. This is provided via the ``dask.set_options`` interface. See the +`dask documentation `_ +for more information on setting dask processing options. diff --git a/docs/iris/src/userguide/reducing_a_cube.rst b/docs/iris/src/userguide/reducing_a_cube.rst deleted file mode 100644 index 0ef49061e5..0000000000 --- a/docs/iris/src/userguide/reducing_a_cube.rst +++ /dev/null @@ -1,207 +0,0 @@ -.. _reducing_a_cube: - -================ - Reducing a Cube -================ - -The :doc:`loading_iris_cubes` section of the user guide showed how to load data into multidimensional Iris cubes. -However it is often necessary to reduce the dimensionality of a cube down to something more appropriate. - -Iris provides several ways of reducing both the amount of data and/or the number of dimensions in your cube depending on the circumstance. -In all cases **the subset of a valid cube is itself a valid cube**. - - -Cube extraction -^^^^^^^^^^^^^^^^ -A subset of a cube can be "extracted" from a multi-dimensional cube in order to reduce its dimensionality: - - >>> import iris - >>> filename = iris.sample_data_path('space_weather.nc') - >>> cube = iris.load_cube(filename, 'electron density') - >>> equator_slice = cube.extract(iris.Constraint(grid_latitude=0)) - >>> print equator_slice - electron density / (1E11 e/m^3) (height: 29; grid_longitude: 31) - Dimension coordinates: - height x - - grid_longitude - x - Auxiliary coordinates: - latitude - x - longitude - x - Scalar coordinates: - grid_latitude: 0.0 degrees - Attributes: - Conventions: CF-1.5 - - -In this example we start with a 3 dimensional cube, with dimensions of ``height``, ``grid_latitude`` and ``grid_longitude``, -and extract every point where the latitude is 0, resulting in a 2d cube with axes of ``height`` and ``grid_longitude``. - - -.. warning:: - - Caution is required when using equality constraints with floating point coordinates such as ``grid_latitude``. - Printing the points of a coordinate does not necessarily show the full precision of the underlying number and it - is very easy return no matches to a constraint when one was expected. - This can be avoided by using a function as the argument to the constraint:: - - def near_zero(cell): - """Returns true if the cell is between -0.1 and 0.1.""" - return -0.1 < cell < 0.1 - - equator_constraint = iris.Constraint(grid_latitude=near_zero) - - Often you will see this construct in shorthand using a lambda function definition:: - - equator_constraint = iris.Constraint(grid_latitude=lambda cell: -0.1 < cell < 0.1) - - -The extract method could be applied again to the *equator_slice* cube to get a further subset. - -For example to get a ``height`` of 9000 metres at the equator the following line extends the previous example:: - - equator_height_9km_slice = equator_slice.extract(iris.Constraint(height=9000)) - print equator_height_9km_slice - -The two steps required to get ``height`` of 9000 m at the equator can be simplified into a single constraint:: - - equator_height_9km_slice = cube.extract(iris.Constraint(grid_latitude=0, height=9000)) - print equator_height_9km_slice - -As we saw in :doc:`loading_iris_cubes` the result of :func:`iris.load` is a :class:`CubeList `. -The ``extract`` method also exists on a :class:`CubeList ` and behaves in exactly the -same way as loading with constraints: - - >>> import iris - >>> air_temp_and_fp_6 = iris.Constraint('air_potential_temperature', forecast_period=6) - >>> level_10 = iris.Constraint(model_level_number=10) - >>> filename = iris.sample_data_path('uk_hires.pp') - >>> cubes = iris.load(filename).extract(air_temp_and_fp_6 & level_10) - >>> print cubes - 0: air_potential_temperature / (K) (grid_latitude: 204; grid_longitude: 187) - >>> print cubes[0] - air_potential_temperature / (K) (grid_latitude: 204; grid_longitude: 187) - Dimension coordinates: - grid_latitude x - - grid_longitude - x - Auxiliary coordinates: - surface_altitude x x - Derived coordinates: - altitude x x - Scalar coordinates: - forecast_period: 6.0 hours - forecast_reference_time: 2009-11-19 04:00:00 - level_height: 395.0 m, bound=(360.0, 433.333) m - model_level_number: 10 - sigma: 0.954993, bound=(0.958939, 0.95068) - time: 2009-11-19 10:00:00 - Attributes: - STASH: m01s00i004 - source: Data from Met Office Unified Model 7.03 - - -Cube iteration -^^^^^^^^^^^^^^^ -A useful way of dealing with a Cube in its **entirety** is by iterating over its layers or slices. -For example, to deal with a 3 dimensional cube (z,y,x) you could iterate over all 2 dimensional slices in y and x -which make up the full 3d cube.:: - - import iris - filename = iris.sample_data_path('hybrid_height.nc') - cube = iris.load_cube(filename) - print cube - for yx_slice in cube.slices(['grid_latitude', 'grid_longitude']): - print repr(yx_slice) - -As the original cube had the shape (15, 100, 100) there were 15 latitude longitude slices and hence the -line ``print repr(yx_slice)`` was run 15 times. - -.. note:: - - The order of latitude and longitude in the list is important; had they been swapped the resultant cube slices - would have been transposed. - - For further information see :py:meth:`Cube.slices `. - - -This method can handle n-dimensional slices by providing more or fewer coordinate names in the list to **slices**:: - - import iris - filename = iris.sample_data_path('hybrid_height.nc') - cube = iris.load_cube(filename) - print cube - for i, x_slice in enumerate(cube.slices(['grid_longitude'])): - print i, repr(x_slice) - -The Python function :py:func:`enumerate` is used in this example to provide an incrementing variable **i** which is -printed with the summary of each cube slice. Note that there were 1500 1d longitude cubes as a result of -slicing the 3 dimensional cube (15, 100, 100) by longitude (i starts at 0 and 1500 = 15 * 100). - -.. hint:: - It is often useful to get a single 2d slice from a multidimensional cube in order to develop a 2d plot function, for example. - This can be achieved by using the ``next()`` method on the result of slices:: - - first_slice = cube.slices(['grid_latitude', 'grid_longitude']).next() - - Once the your code can handle a 2d slice, it is then an easy step to loop over **all** 2d slices within the bigger - cube using the slices method. - - -Cube indexing -^^^^^^^^^^^^^ -In the same way that you would expect a numeric multidimensional array to be **indexed** to take a subset of your -original array, you can **index** a Cube for the same purpose. - - -Here are some examples of array indexing in :py:mod:`numpy`:: - - import numpy as np - # create an array of 12 consecutive integers starting from 0 - a = np.arange(12) - print a - - print a[0] # first element of the array - - print a[-1] # last element of the array - - print a[0:4] # first four elements of the array (this is the same as a[:4]) - - print a[-4:] # last four elements of the array - - print a[::-1] # gives all of the array, but backwards - - # Make a 2d array by reshaping a - b = a.reshape(3, 4) - print b - - print b[0, 0] # first element of the first and second dimensions - - print b[0] # first element of the first dimension (+ every other dimension) - - # get the second element of the first dimension and all of the second dimension - # in reverse, by steps of two. - print b[1, ::-2] - - -Similarly, Iris cubes have indexing capability:: - - import iris - filename = iris.sample_data_path('hybrid_height.nc') - cube = iris.load_cube(filename) - - print cube - - # get the first element of the first dimension (+ every other dimension) - print cube[0] - - # get the last element of the first dimension (+ every other dimension) - print cube[-1] - - # get the first 4 elements of the first dimension (+ every other dimension) - print cube[0:4] - - # Get the first element of the first and third dimension (+ every other dimension) - print cube[0, :, 0] - - # Get the second element of the first dimension and all of the second dimension - # in reverse, by steps of two. - print cube[1, ::-2] diff --git a/docs/iris/src/userguide/regridding_plots/interpolate_column.py b/docs/iris/src/userguide/regridding_plots/interpolate_column.py new file mode 100644 index 0000000000..201dcda4a1 --- /dev/null +++ b/docs/iris/src/userguide/regridding_plots/interpolate_column.py @@ -0,0 +1,63 @@ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import iris +import iris.quickplot as qplt +import iris.analysis +import matplotlib.pyplot as plt +import numpy as np + + +fname = iris.sample_data_path('hybrid_height.nc') +column = iris.load_cube(fname, 'air_potential_temperature')[:, 0, 0] + +alt_coord = column.coord('altitude') + +# Interpolate the "perfect" linear interpolation. Really this is just +# a high number of interpolation points, in this case 1000 of them. +altitude_points = [('altitude', np.linspace(400, 1250, 1000))] +scheme = iris.analysis.Linear(extrapolation_mode='mask') +linear_column = column.interpolate(altitude_points, scheme) + +# Now interpolate the data onto 10 evenly spaced altitude levels, +# as we did in the example. +altitude_points = [('altitude', np.linspace(400, 1250, 10))] +scheme = iris.analysis.Linear() +new_column = column.interpolate(altitude_points, scheme) + +plt.figure(figsize=(5, 4), dpi=100) + +# Plot the black markers for the original data. +qplt.plot(column, column.coord('altitude'), + marker='o', color='black', linestyle='', markersize=3, + label='Original values', zorder=2) + +# Plot the gray line to display the linear interpolation. +qplt.plot(linear_column, linear_column.coord('altitude'), + color='gray', + label='Linear interpolation', zorder=0) + +# Plot the red markers for the new data. +qplt.plot(new_column, new_column.coord('altitude'), + marker='D', color='red', linestyle='', + label='Interpolated values', zorder=1) + +ax = plt.gca() +# Space the plot such that the labels appear correctly. +plt.subplots_adjust(left=0.17, bottom=0.14) + +# Limit the plot to a maximum of 5 ticks. +ax.xaxis.get_major_locator().set_params(nbins=5) + +# Prevent matplotlib from using "offset" notation on the xaxis. +ax.xaxis.get_major_formatter().set_useOffset(False) + +# Put some space between the line and the axes. +ax.margins(0.05) + +# Place gridlines and a legend. +ax.grid() +plt.legend(loc='lower right') + +plt.show() diff --git a/docs/iris/src/userguide/regridding_plots/regridded_to_global.py b/docs/iris/src/userguide/regridding_plots/regridded_to_global.py new file mode 100644 index 0000000000..c392de7a52 --- /dev/null +++ b/docs/iris/src/userguide/regridding_plots/regridded_to_global.py @@ -0,0 +1,26 @@ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import iris +import iris.analysis +import iris.plot as iplt +import matplotlib.pyplot as plt + + +global_air_temp = iris.load_cube(iris.sample_data_path('air_temp.pp')) +rotated_psl = iris.load_cube(iris.sample_data_path('rotated_pole.nc')) + +scheme = iris.analysis.Linear(extrapolation_mode='mask') +global_psl = rotated_psl.regrid(global_air_temp, scheme) + +plt.figure(figsize=(4, 3)) +iplt.pcolormesh(global_psl) +plt.title('Air pressure\n' + 'on a global longitude latitude grid') +ax = plt.gca() +ax.coastlines() +ax.gridlines() +ax.set_extent([-90, 70, 10, 80]) + +plt.show() diff --git a/docs/iris/src/userguide/regridding_plots/regridded_to_global_area_weighted.py b/docs/iris/src/userguide/regridding_plots/regridded_to_global_area_weighted.py new file mode 100644 index 0000000000..067a4ee2d6 --- /dev/null +++ b/docs/iris/src/userguide/regridding_plots/regridded_to_global_area_weighted.py @@ -0,0 +1,51 @@ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import iris +import iris.analysis +import iris.plot as iplt +import matplotlib.pyplot as plt +import matplotlib.colors +import numpy as np + +global_air_temp = iris.load_cube(iris.sample_data_path('air_temp.pp')) + +regional_ash = iris.load_cube(iris.sample_data_path('NAME_output.txt')) +regional_ash = regional_ash.collapsed('flight_level', iris.analysis.SUM) + +# Mask values so low that they are anomalous. +regional_ash.data = np.ma.masked_less(regional_ash.data, 5e-6) + +norm = matplotlib.colors.LogNorm(5e-6, 0.0175) + +global_air_temp.coord('longitude').guess_bounds() +global_air_temp.coord('latitude').guess_bounds() + +fig = plt.figure(figsize=(8, 4.5)) + +plt.subplot(2, 2, 1) +iplt.pcolormesh(regional_ash, norm=norm) +plt.title('Volcanic ash total\nconcentration not regridded', + size='medium') + +for subplot_num, mdtol in zip([2, 3, 4], [0, 0.5, 1]): + plt.subplot(2, 2, subplot_num) + scheme = iris.analysis.AreaWeighted(mdtol=mdtol) + global_ash = regional_ash.regrid(global_air_temp, scheme) + iplt.pcolormesh(global_ash, norm=norm) + plt.title('Volcanic ash total concentration\n' + 'regridded with AreaWeighted(mdtol={})'.format(mdtol), + size='medium') + +plt.subplots_adjust(hspace=0, wspace=0.05, + left=0.001, right=0.999, bottom=0, top=0.955) + +# Iterate over each of the figure's axes, adding coastlines, gridlines +# and setting the extent. +for ax in fig.axes: + ax.coastlines('50m') + ax.gridlines() + ax.set_extent([-80, 40, 31, 75]) + +plt.show() diff --git a/docs/iris/src/userguide/regridding_plots/regridded_to_rotated.py b/docs/iris/src/userguide/regridding_plots/regridded_to_rotated.py new file mode 100644 index 0000000000..f2c2b271df --- /dev/null +++ b/docs/iris/src/userguide/regridding_plots/regridded_to_rotated.py @@ -0,0 +1,25 @@ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import iris +import iris.analysis +import iris.plot as iplt +import matplotlib.pyplot as plt + +global_air_temp = iris.load_cube(iris.sample_data_path('air_temp.pp')) +rotated_psl = iris.load_cube(iris.sample_data_path('rotated_pole.nc')) + +rotated_air_temp = global_air_temp.regrid(rotated_psl, iris.analysis.Linear()) + + +plt.figure(figsize=(4, 3)) + +iplt.pcolormesh(rotated_air_temp, norm=plt.Normalize(260, 300)) +plt.title('Air temperature\n' + 'on a limited area rotated pole grid') +ax = plt.gca() +ax.coastlines(resolution='50m') +ax.gridlines() + +plt.show() diff --git a/docs/iris/src/userguide/regridding_plots/regridding_plot.py b/docs/iris/src/userguide/regridding_plots/regridding_plot.py new file mode 100644 index 0000000000..2419d47727 --- /dev/null +++ b/docs/iris/src/userguide/regridding_plots/regridding_plot.py @@ -0,0 +1,33 @@ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import iris +import iris.plot as iplt +import matplotlib.pyplot as plt + +# Load the data. +global_air_temp = iris.load_cube(iris.sample_data_path('air_temp.pp')) +rotated_psl = iris.load_cube(iris.sample_data_path('rotated_pole.nc')) + +plt.figure(figsize=(9, 3.5)) + +plt.subplot(1, 2, 1) +iplt.pcolormesh(global_air_temp, norm=plt.Normalize(260, 300)) +plt.title('Air temperature\n' + 'on a global longitude latitude grid') +ax = plt.gca() +ax.coastlines() +ax.gridlines() + +plt.subplot(1, 2, 2) +iplt.pcolormesh(rotated_psl) +plt.title('Air pressure\n' + 'on a limited area rotated pole grid') +ax = plt.gca() +ax.coastlines(resolution='50m') +ax.gridlines() + +plt.tight_layout() + +plt.show() diff --git a/docs/iris/src/userguide/saving_iris_cubes.rst b/docs/iris/src/userguide/saving_iris_cubes.rst new file mode 100644 index 0000000000..ecf2210810 --- /dev/null +++ b/docs/iris/src/userguide/saving_iris_cubes.rst @@ -0,0 +1,108 @@ +.. _saving_iris_cubes: + +================== +Saving Iris cubes +================== + +Iris supports the saving of cubes and cube lists to: + +* CF netCDF (1.5) +* GRIB (edition 2) +* Met Office PP + + +The :py:func:`iris.save` function saves one or more cubes to a file. + +If the filename includes a supported suffix then Iris will use the correct saver +and the keyword argument `saver` is not required. + + >>> import iris + >>> filename = iris.sample_data_path('uk_hires.pp') + >>> cubes = iris.load(filename) + >>> iris.save(cubes, '/tmp/uk_hires.nc') + +.. warning:: + + Saving a cube whose data has been loaded lazily + (if `cube.has_lazy_data()` returns `True`) to the same file it expects + to load data from will cause both the data in-memory and the data on + disk to be lost. + + .. code-block:: python + + cube = iris.load_cube('somefile.nc') + # The next line causes data loss in 'somefile.nc' and the cube. + iris.save(cube, 'somefile.nc') + + In general, overwriting a file which is the source for any lazily loaded + data can result in corruption. Users should proceed with caution when + attempting to overwrite an existing file. + + +Controlling the save process +----------------------------- + +The :py:func:`iris.save` function passes all other keywords through to the saver function defined, or automatically set from the file extension. This enables saver specific functionality to be called. + + >>> # Save a cube to PP + >>> iris.save(cubes[0], "myfile.pp") + >>> # Save a cube list to a PP file, appending to the contents of the file + >>> # if it already exists + >>> iris.save(cubes, "myfile.pp", append=True) + >>> # Save a cube to netCDF, defaults to NETCDF4 file format + >>> iris.save(cubes[0], "myfile.nc") + >>> # Save a cube list to netCDF, using the NETCDF3_CLASSIC storage option + >>> iris.save(cubes, "myfile.nc", netcdf_format="NETCDF3_CLASSIC") + +See + +* :py:func:`iris.fileformats.netcdf.save` +* :py:func:`iris.fileformats.grib.save_grib2` +* :py:func:`iris.fileformats.pp.save` + +for more details on supported arguments for the individual savers. + +Customising the save process +----------------------------- + +When saving to GRIB or PP, the save process may be intercepted between the translation step and the file writing. This enables customisation of the output messages, based on Cube metadata if required, over and above the translations supplied by Iris. + +For example, a GRIB2 message with a particular known long_name may need to be saved to a specific parameter code and type of statistical process. This can be achieved by:: + + def tweaked_messages(cube): + for cube, grib_message in iris.fileformats.grib.as_pairs(cube): + # post process the GRIB2 message, prior to saving + if cube.name() == 'carefully_customised_precipitation_amount': + gribapi.grib_set_long(grib_message, "typeOfStatisticalProcess", 1) + gribapi.grib_set_long(grib_message, "parameterCategory", 1) + gribapi.grib_set_long(grib_message, "parameterNumber", 1) + yield grib_message + iris.fileformats.grib.save_messages(tweaked_messages(cubes[0]), '/tmp/agrib2.grib2') + +Similarly a PP field may need to be written out with a specific value for LBEXP. This can be achieved by:: + + def tweaked_fields(cube): + for cube, field in iris.fileformats.pp.save_pairs_from_cube(cube): + # post process the PP field, prior to saving + if cube.name() == 'air_pressure': + field.lbexp = 'meaxp' + elif cube.name() == 'air_density': + field.lbexp = 'meaxr' + yield field + iris.fileformats.pp.save_fields(tweaked_fields(cubes[0]), '/tmp/app.pp') + + +netCDF +^^^^^^^ + +NetCDF is a flexible container for metadata and cube metadata is closely related to the CF for netCDF semantics. This means that cube metadata is well represented in netCDF files, closely resembling the in memory metadata representation. +Thus there is no provision for similar save customisation functionality for netCDF saving, all customisations should be applied to the cube prior to saving to netCDF. + +Bespoke Saver +-------------- + +A bespoke saver may be written to support an alternative file format. This can be provided to the :py:func:`iris.save` function, enabling Iris to write to a different file format. +Such a custom saver will need be written to meet the needs of the file format and to handle the metadata translation from cube metadata effectively. + +Implementing a bespoke saver is out of scope for the user guide. + diff --git a/docs/iris/src/userguide/subsetting_a_cube.rst b/docs/iris/src/userguide/subsetting_a_cube.rst new file mode 100644 index 0000000000..b61f16a043 --- /dev/null +++ b/docs/iris/src/userguide/subsetting_a_cube.rst @@ -0,0 +1,210 @@ +.. _subsetting_a_cube: + +================= +Subsetting a Cube +================= + +The :doc:`loading_iris_cubes` section of the user guide showed how to load data into multidimensional Iris cubes. +However it is often necessary to reduce the dimensionality of a cube down to something more appropriate and/or manageable. + +Iris provides several ways of reducing both the amount of data and/or the number of dimensions in your cube depending on the circumstance. +In all cases **the subset of a valid cube is itself a valid cube**. + + +Cube extraction +^^^^^^^^^^^^^^^^ +A subset of a cube can be "extracted" from a multi-dimensional cube in order to reduce its dimensionality: + + >>> import iris + >>> filename = iris.sample_data_path('space_weather.nc') + >>> cube = iris.load_cube(filename, 'electron density') + >>> equator_slice = cube.extract(iris.Constraint(grid_latitude=0)) + >>> print(equator_slice) + electron density / (1E11 e/m^3) (height: 29; grid_longitude: 31) + Dimension coordinates: + height x - + grid_longitude - x + Auxiliary coordinates: + latitude - x + longitude - x + Scalar coordinates: + grid_latitude: 0.0 degrees + Attributes: + Conventions: CF-1.5 + + +In this example we start with a 3 dimensional cube, with dimensions of ``height``, ``grid_latitude`` and ``grid_longitude``, +and extract every point where the latitude is 0, resulting in a 2d cube with axes of ``height`` and ``grid_longitude``. + + +.. _floating-point-warning: +.. warning:: + + Caution is required when using equality constraints with floating point coordinates such as ``grid_latitude``. + Printing the points of a coordinate does not necessarily show the full precision of the underlying number and it + is very easy return no matches to a constraint when one was expected. + This can be avoided by using a function as the argument to the constraint:: + + def near_zero(cell): + """Returns true if the cell is between -0.1 and 0.1.""" + return -0.1 < cell < 0.1 + + equator_constraint = iris.Constraint(grid_latitude=near_zero) + + Often you will see this construct in shorthand using a lambda function definition:: + + equator_constraint = iris.Constraint(grid_latitude=lambda cell: -0.1 < cell < 0.1) + + +The extract method could be applied again to the *equator_slice* cube to get a further subset. + +For example to get a ``height`` of 9000 metres at the equator the following line extends the previous example:: + + equator_height_9km_slice = equator_slice.extract(iris.Constraint(height=9000)) + print(equator_height_9km_slice) + +The two steps required to get ``height`` of 9000 m at the equator can be simplified into a single constraint:: + + equator_height_9km_slice = cube.extract(iris.Constraint(grid_latitude=0, height=9000)) + print(equator_height_9km_slice) + +As we saw in :doc:`loading_iris_cubes` the result of :func:`iris.load` is a :class:`CubeList `. +The ``extract`` method also exists on a :class:`CubeList ` and behaves in exactly the +same way as loading with constraints: + + >>> import iris + >>> air_temp_and_fp_6 = iris.Constraint('air_potential_temperature', forecast_period=6) + >>> level_10 = iris.Constraint(model_level_number=10) + >>> filename = iris.sample_data_path('uk_hires.pp') + >>> cubes = iris.load(filename).extract(air_temp_and_fp_6 & level_10) + >>> print(cubes) + 0: air_potential_temperature / (K) (grid_latitude: 204; grid_longitude: 187) + >>> print(cubes[0]) + air_potential_temperature / (K) (grid_latitude: 204; grid_longitude: 187) + Dimension coordinates: + grid_latitude x - + grid_longitude - x + Auxiliary coordinates: + surface_altitude x x + Derived coordinates: + altitude x x + Scalar coordinates: + forecast_period: 6.0 hours + forecast_reference_time: 2009-11-19 04:00:00 + level_height: 395.0 m, bound=(360.0, 433.3332) m + model_level_number: 10 + sigma: 0.9549927, bound=(0.9589389, 0.95068014) + time: 2009-11-19 10:00:00 + Attributes: + STASH: m01s00i004 + source: Data from Met Office Unified Model + um_version: 7.3 + + +Cube iteration +^^^^^^^^^^^^^^^ +A useful way of dealing with a Cube in its **entirety** is by iterating over its layers or slices. +For example, to deal with a 3 dimensional cube (z,y,x) you could iterate over all 2 dimensional slices in y and x +which make up the full 3d cube.:: + + import iris + filename = iris.sample_data_path('hybrid_height.nc') + cube = iris.load_cube(filename) + print(cube) + for yx_slice in cube.slices(['grid_latitude', 'grid_longitude']): + print(repr(yx_slice)) + +As the original cube had the shape (15, 100, 100) there were 15 latitude longitude slices and hence the +line ``print(repr(yx_slice))`` was run 15 times. + +.. note:: + + The order of latitude and longitude in the list is important; had they been swapped the resultant cube slices + would have been transposed. + + For further information see :py:meth:`Cube.slices `. + + +This method can handle n-dimensional slices by providing more or fewer coordinate names in the list to **slices**:: + + import iris + filename = iris.sample_data_path('hybrid_height.nc') + cube = iris.load_cube(filename) + print(cube) + for i, x_slice in enumerate(cube.slices(['grid_longitude'])): + print(i, repr(x_slice)) + +The Python function :py:func:`enumerate` is used in this example to provide an incrementing variable **i** which is +printed with the summary of each cube slice. Note that there were 1500 1d longitude cubes as a result of +slicing the 3 dimensional cube (15, 100, 100) by longitude (i starts at 0 and 1500 = 15 * 100). + +.. hint:: + It is often useful to get a single 2d slice from a multidimensional cube in order to develop a 2d plot function, for example. + This can be achieved by using the ``next()`` function on the result of + slices:: + + first_slice = next(cube.slices(['grid_latitude', 'grid_longitude'])) + + Once the your code can handle a 2d slice, it is then an easy step to loop over **all** 2d slices within the bigger + cube using the slices method. + + +Cube indexing +^^^^^^^^^^^^^ +In the same way that you would expect a numeric multidimensional array to be **indexed** to take a subset of your +original array, you can **index** a Cube for the same purpose. + + +Here are some examples of array indexing in :py:mod:`numpy`:: + + import numpy as np + # create an array of 12 consecutive integers starting from 0 + a = np.arange(12) + print(a) + + print(a[0]) # first element of the array + + print(a[-1]) # last element of the array + + print(a[0:4]) # first four elements of the array (the same as a[:4]) + + print(a[-4:]) # last four elements of the array + + print(a[::-1]) # gives all of the array, but backwards + + # Make a 2d array by reshaping a + b = a.reshape(3, 4) + print(b) + + print(b[0, 0]) # first element of the first and second dimensions + + print(b[0]) # first element of the first dimension (+ every other dimension) + + # get the second element of the first dimension and all of the second dimension + # in reverse, by steps of two. + print(b[1, ::-2]) + + +Similarly, Iris cubes have indexing capability:: + + import iris + filename = iris.sample_data_path('hybrid_height.nc') + cube = iris.load_cube(filename) + + print(cube) + + # get the first element of the first dimension (+ every other dimension) + print(cube[0]) + + # get the last element of the first dimension (+ every other dimension) + print(cube[-1]) + + # get the first 4 elements of the first dimension (+ every other dimension) + print(cube[0:4]) + + # Get the first element of the first and third dimension (+ every other dimension) + print(cube[0, :, 0]) + + # Get the second element of the first dimension and all of the second dimension + # in reverse, by steps of two. + print(cube[1, ::-2]) diff --git a/docs/iris/src/whatsnew/1.0.rst b/docs/iris/src/whatsnew/1.0.rst index 2e4c81c9f8..2a415c1bfe 100644 --- a/docs/iris/src/whatsnew/1.0.rst +++ b/docs/iris/src/whatsnew/1.0.rst @@ -5,6 +5,7 @@ What's new in Iris 1.0 :Date: 15 Oct, 2012 This document explains the new/changed features of Iris in version 1.0. +(:doc:`View all changes `.) With the release of Iris 1.0, we have broadly completed the transition to the CF data model, and established a stable foundation for future @@ -220,7 +221,7 @@ Metadata attributes Iris now stores "source" and "history" metadata in Cube attributes. For example:: - >>> print iris.tests.stock.global_pp() + >>> print(iris.tests.stock.global_pp()) air_temperature (latitude: 73; longitude: 96) ... Attributes: @@ -279,15 +280,15 @@ This functionality is provided by :func:`iris.analysis.cartography.project()`. For example:: import iris - import cartopy + import cartopy.crs as ccrs import matplotlib.pyplot as plt # Load data cube = iris.load_cube(iris.sample_data_path('air_temp.pp')) # Transform cube to target projection - target_proj = cartopy.crs.RotatedPole(pole_longitude=177.5, - pole_latitude=37.5) + target_proj = ccrs.RotatedPole(pole_longitude=177.5, + pole_latitude=37.5) new_cube, extent = iris.analysis.cartography.project(cube, target_proj) # Plot diff --git a/docs/iris/src/whatsnew/1.1.rst b/docs/iris/src/whatsnew/1.1.rst index 207a7c0f57..274ec65ff6 100644 --- a/docs/iris/src/whatsnew/1.1.rst +++ b/docs/iris/src/whatsnew/1.1.rst @@ -5,6 +5,7 @@ What's new in Iris 1.1 :Date: 7 Dec, 2012 This document explains the new/changed features of Iris in version 1.1. +(:doc:`View all changes `.) With the release of Iris 1.1, we are introducing support for Mac OS X. Version 1.1 also sees the first batch of performance enhancements, with @@ -86,7 +87,7 @@ one might do:: >>> seasons = ['mamjja', 'sondjf'] >>> iris.coord_categorisation.add_custom_season(cube, 'time', seasons) - >>> print cube.coord('season').points + >>> print(cube.coord('season').points) ['ondjfm' 'ondjfm' 'mamjja' 'mamjja' 'mamjja' 'mamjja' 'mamjja' 'mamjja' 'ondjfm' 'ondjfm' 'ondjfm' 'ondjfm'] diff --git a/docs/iris/src/whatsnew/1.10.rst b/docs/iris/src/whatsnew/1.10.rst new file mode 100644 index 0000000000..26f21c0252 --- /dev/null +++ b/docs/iris/src/whatsnew/1.10.rst @@ -0,0 +1,176 @@ +What's New in Iris 1.10 +*********************** + +:Release: 1.10 +:Date: 5th September 2016 + +This document explains the new/changed features of Iris in version 1.10 +(:doc:`View all changes `.) + +Iris 1.10 Features +================== +.. _iris_grib_added: + +* Support has now been added for the + `iris_grib `_ package, which + provides GRIB format support in an optional package, separate from Iris. + + * If ``iris_grib`` is available, it will always be used in place of the older + iris module :mod:`iris.fileformats.grib`. + + * The capabilities of ``iris_grib`` are essentially the same as the existing + :mod:`iris.fileformats.grib` when used with ``iris.FUTURE.strict_grib_load=True``, + with only small detail differences. + + * The old :mod:`iris.fileformats.grib` module is now deprecated and may shortly be + removed. + + * If you are already using the recommended :data:`iris.FUTURE` setting + ``iris.FUTURE.strict_grib_load=True`` this should not cause problems, as + the new package is all-but identical. + + * However, the option ``iris.FUTURE.strict_grib_load`` is itself now + deprecated, so you should remove code that sets it. + + * If, however, your code is still using the older "non-strict" grib + loading, then you may need to make code changes. + + * In particular, the ``field`` object passed to load callbacks is + different. + See :class:`iris.fileformats.grib.message.GribMessage` (the + ``iris_grib.message.GribMessage`` class is the same as this, for now). + + * Please exercise your code with the new iris_grib module, and let us know of + any problems you uncover, such as files that will no longer load with the + new implementation. + +* :meth:`iris.experimental.regrid.PointInCell.regridder` now works across coordinate systems, including non latlon systems. Additionally, the requirement that the source data X and Y coordinates be 2D has been removed. NB: some aspects of this change are backwards incompatible. +* Plotting non-Gregorian calendars is now supported. This adds `nc_time_axis `_ as a dependency. +* Promoting a scalar coordinate to a dimension coordinate with :func:`iris.util.new_axis` no longer loads deferred data. +* The parsing functionality for Cell Methods from netCDF files is available as part of the :mod:`iris.fileformats.netcdf` module as :func:`iris.fileformats.netcdf.parse_cell_methods`. +* Support for the NameIII Version 2 file format has been added. +* Loading netcdf data in Mercator and Stereographic projections now accepts optional extra projection parameter attributes (``false_easting``, ``false_northing`` and ``scale_factor_at_projection_origin``), if they match the default values. + + * NetCDF files which define a Mercator projection where the ``false_easting``, ``false_northing`` and ``scale_factor_at_projection_origin`` match the defaults will have the projection loaded correctly. Otherwise, a warning will be issued for each parameter that does not match the default and the projection will not be loaded. + * NetCDF files which define a Steroegraphic projection where the ``scale_factor_at_projection_origin`` is equal to 1.0 will have the projection loaded correctly. Otherwise, a warning will be issued and the projection will not be loaded. + +* The :mod:`iris.plot` routines :func:`~iris.plot.contour`, :func:`~iris.plot.contourf`, :func:`~iris.plot.outline`, :func:`~iris.plot.pcolor`, :func:`~iris.plot.pcolormesh` and :func:`~iris.plot.points` now support plotting cubes with anonymous dimensions by specifying the *numeric index* of the anonymous dimension within the ``coords`` keyword argument. + + Note that the axis of the anonymous dimension will be plotted in index space. + +* NetCDF loading and saving now supports Cubes that use the LambertConformal coordinate system. +* The experimental structured Fieldsfile loader :func:`~iris.experimental.fieldsfile.load` has been extended to also load structured PP files. + + Structured loading is a streamlined operation, offering the benefit of a significantly faster loading alternative to the more generic :func:`iris.load` mechanism. + + Note that structured loading is not an optimised wholesale replacement of :func:`iris.load`. Structured loading is restricted to input containing contiguously ordered fields for each phenomenon that repeat regularly over the same vertical levels and times. For further details, see :func:`~iris.experimental.fieldsfile.load` + +* :mod:`iris.experimental.regrid_conservative` is now compatible with ESMPy v7. +* Saving zonal (i.e. longitudinal) means to PP files now sets the '64s' bit in LBPROC. +* Loading of 'little-endian' PP files is now supported. +* All appropriate :mod:`iris.plot` functions now handle an ``axes`` keyword, allowing use of the object oriented matplotlib interface rather than pyplot. +* The ability to pass file format object lists into the rules based load pipeline, as used for GRIB, Fields Files and PP has been added. The :func:`iris.fileformats.pp.load_pairs_from_fields` and :func:`iris.fileformats.grib.load_pairs_from_fields` are provided to produce cubes from such lists. These lists may have been filtered or altered using the appropriate :mod:`iris.fileformats` modules. +* Cubes can now have an 'hour' coordinate added with :meth:`iris.coord_categorisation.add_hour`. +* Time coordinates from PP fields with an lbcode of the form 3xx23 are now correctly encoded with a 360-day calendar. +* The loading from and saving to netCDF of CF cell_measure variables is supported, along with their representation within a Cube as :attr:`~iris.cube.Cube.cell_measures`. +* Cubes with anonymous dimensions can now be concatenated. This can only occur along a dimension that is not anonymous. +* NetCDF saving of ``valid_range``, ``valid_min`` and ``valid_max`` cube attributes is now allowed. + +Bugs Fixed +========== +* Altered Cell Methods to display coordinate's standard_name rather than var_name where appropriate to avoid human confusion. +* Saving multiple cubes with netCDF4 protected attributes should now work as expected. +* Concatenating cubes with singleton dimensions (dimensions of size one) now works properly. +* Fixed the ``grid_mapping_name`` and ``secant_latitudes`` handling for the LambertConformal coordinate system. +* Fixed bug in :func:`iris.analysis.cartography.project` where the output projection coordinates didn't have units. +* Attempting to use :meth:`iris.sample_data_path` to access a file that isn't actually Iris sample data now raises a more descriptive error. A note about the appropriate use of `sample_data_path` has also been added to the documentation. +* Fixed a bug where regridding or interpolation with the :class:`~iris.analysis.Nearest` scheme returned floating-point results even when the source data was integer typed. It now always returns the same type as the source data. +* Fixed a bug where regridding circular data would ignore any source masking. This affected any regridding using the :class:`~iris.analysis.Linear` and :class:`~iris.analysis.Nearest` schemes, and also :func:`iris.analysis.interpolate.linear`. +* The ``coord_name`` parameter to :func:`~iris.fileformats.rules.scalar_cell_method` is now checked correctly. +* LBPROC is set correctly when a cube containing the minimum of a variable is saved to a PP file. The IA component of LBTIM is set correctly when saving maximum or minimum values. +* The performance of :meth:`iris.cube.Cube.extract` when a list of values is given to an instance of :class:`iris.Constraint` has been improved considerably. +* Fixed a bug with :meth:`iris.cube.Cube.data` where an :class:`numpy.ndarray` was not being returned for scalar cubes with lazy data. +* When saving in netcdf format, the units of 'latitude' and 'longitude' coordinates specified in 'degrees' are saved as 'degrees_north' and 'degrees_east' respectively, as defined in the CF conventions for netCDF files: sections 4.1 and 4.2. +* Fixed a bug with a class of pp files with lbyr == 0, where the date would cause errors when converting to a datetime object (e.g. when printing a cube). + + When processing a pp field with lbtim = 2x, lbyr == lbyrd == 0 and lbmon == lbmond, 'month' and 'month_number' coordinates are created instead of 'time'. + +* Fixed a bug in :meth:`~iris.analysis.calculus.curl` where the sign of the r-component for spherical coordinates was opposite to what was expected. +* A bug that prevented cube printing in some cases has been fixed. +* Fixed a bug where a deepcopy of a :class:`~iris.coords.DimCoord` would have writable ``points`` and ``bounds`` arrays. These arrays can now no longer be modified in-place. +* Concatenation no longer occurs when the auxiliary coordinates of the cubes do not match. This check is not applied to AuxCoords that span the dimension the concatenation is occuring along. This behaviour can be switched off by setting the ``check_aux_coords`` kwarg in :meth:`iris.cube.CubeList.concatenate` to False. +* Fixed a bug in :meth:`iris.cube.Cube.subset` where an exception would be thrown while trying to subset over a non-dimensional scalar coordinate. + +Incompatible Changes +==================== +* The source and target for :meth:`iris.experimental.regrid.PointInCell.regridder` must now have defined coordinate systems (i.e. not ``None``). Additionally, the source data X and Y coordinates must have the same cube dimensions. + +Deprecations +============ +* Deprecated the :class:`iris.Future` option + ``iris.FUTURE.strict_grib_load``. + This only affected the module :mod:`iris.fileformats.grib`, which is itself + now deprecated. + Please see :ref:`iris_grib package `, above. +* Deprecated the module :mod:`iris.fileformats.grib`. The new package + `iris_grib `_ replaces this + fuctionality, which will shortly be removed. + Please see :ref:`iris_grib package `, above. +* The use of :data:`iris.config.SAMPLE_DATA_DIR` has been deprecated and replaced by the now importable `iris_sample_data `_ package. + +* Deprecated the module :mod:`iris.analysis.interpolate`. + This contains the following public items, all of which are now deprecated and + will be removed in a future release: + + * :func:`~iris.analysis.interpolate.linear` + * :func:`~iris.analysis.interpolate.regrid` + * :func:`~iris.analysis.interpolate.regrid_to_max_resolution` + * :func:`~iris.analysis.interpolate.nearest_neighbour_indices` + * :func:`~iris.analysis.interpolate.nearest_neighbour_data_value` + * :func:`~iris.analysis.interpolate.extract_nearest_neighbour` + * class :class:`~iris.analysis.interpolate.Linear1dExtrapolator`. + + Please use the replacement facilities individually noted in the module + documentation for :mod:`iris.analysis.interpolate` +* The method :meth:`iris.cube.Cube.regridded` has been deprecated. + Please use :meth:`iris.cube.Cube.regrid` instead (see + :meth:`~iris.cube.Cube.regridded` for details). +* Deprecated :data:`iris.fileformats.grib.hindcast_workaround` and :class:`iris.fileformats.grib.GribWrapper`. The class :class:`iris.fileformats.grib.message.GribMessage` provides alternative means of working with GRIB message instances. +* Deprecated the module :mod:`iris.fileformats.ff`. Please use the replacement + facilities in module :mod:`iris.fileformats.um` : + + * :func:`iris.fileformats.um.um_to_pp` replaces :class:`iris.fileformats.ff.FF2PP`. + * :func:`iris.fileformats.um.load_cubes` replaces :func:`iris.fileformats.ff.load_cubes`. + * :func:`iris.fileformats.um.load_cubes_32bit_ieee` replaces :func:`iris.fileformats.ff.load_cubes_32bit_ieee`. + + All other public components are generally deprecated and will be removed in a future release. + +* The :func:`iris.fileformats.pp.as_pairs` and :func:`iris.fileformats.grib.as_pairs` are deprecated. These are replaced with :func:`iris.fileformats.pp.save_pairs_from_cube` and :func:`iris.fileformats.grib.save_pairs_from_cube`. +* ``iris.fileformats.pp_packing`` has been deprecated. Please install the separate `mo_pack `_ package instead. This provides the same functionality. +* Deprecated logging functions (currently used only for rules logging): + :data:`iris.config.iris.config.RULE_LOG_DIR`, + :data:`iris.config.iris.config.RULE_LOG_IGNORE` and + :data:`iris.fileformats.rules.log`. + +* Deprecated all the remaining text rules mechanisms: + :class:`iris.fileformats.rules.DebugString`, + :class:`iris.fileformats.rules.CMAttribute`, + :class:`iris.fileformats.rules.CMCustomAttribute`, + :class:`iris.fileformats.rules.CoordAndDims`, + :class:`iris.fileformats.rules.Rule`, + :class:`iris.fileformats.rules.FunctionRule`, + :class:`iris.fileformats.rules.ProcedureRule`, + :class:`iris.fileformats.rules.RulesContainer` and + :func:`iris.fileformats.rules.calculate_forecast_period`. + +* Deprecated the custom pp save rules mechanism implemented by the functions :func:`iris.fileformats.pp.add_save_rules` and :func:`iris.fileformats.pp.reset_save_rules`. The functions :func:`iris.fileformats.pp.as_fields`, :func:`iris.fileformats.pp.as_pairs` and :func:`iris.fileformats.pp.save_fields` provide alternative means of achieving the same ends. + +Documentation Changes +===================== +* It is now clear that repeated values will form a group under :meth:`iris.cube.Cube.aggregated_by` even if they aren't consecutive. Hence, the documentation for :mod:`iris.cube` has been changed to reflect this. +* The documentation for :meth:`iris.analysis.calculus.curl` has been updated for clarity. +* False claims about :meth:`iris.fileformats.pp.save`, :meth:`iris.fileformats.pp.as_pairs`, and :meth:`iris.fileformats.pp.as_fields` being able to take instances of :class:`iris.cube.CubeList` as inputs have been removed. +* A :doc:`new code example <../examples/Meteorology/wind_speed>`, demonstrating the use of a quiver plot to display wind speeds over Lake Victoria, has been added. +* The docstring for :data:`iris.analysis.SUM` has been updated to explicitly state that weights passed to it aren't normalised internally. +* A note regarding the impossibility of partially collapsing multi-dimensional coordinates has been added to the user guide. + diff --git a/docs/iris/src/whatsnew/1.11.rst b/docs/iris/src/whatsnew/1.11.rst new file mode 100644 index 0000000000..eb93ec2f8c --- /dev/null +++ b/docs/iris/src/whatsnew/1.11.rst @@ -0,0 +1,31 @@ +What's New in Iris 1.11 +*********************** + +:Release: 1.11 +:Date: 2016-11-28 + +This document explains the new/changed features of Iris in version 1.11 +(:doc:`View all changes `.) + +Iris 1.11 Features +================== +* If available, display the ``STASH`` code instead of ``unknown / (unknown)`` when printing cubes + with no ``standard_name`` and no ``units``. +* Support for saving to netCDF with data packing has been added. +* The coordinate system :class:`iris.coord_systems.LambertAzimuthalEqualArea` has been added with NetCDF saving support. + +Bugs Fixed +========== +* Fixed a floating point tolerance bug in :func:`iris.experimental.regrid.regrid_area_weighted_rectilinear_src_and_grid` + for wrapped longitudes. +* Allow :func:`iris.util.new_axis` to promote the nominated scalar coordinate of a cube + with a scalar masked constant data payload. +* Fixed a bug where :func:`iris.util._is_circular` would erroneously return false + when coordinate values are decreasing. +* When saving to NetCDF, the existing behaviour of writing string attributes as ASCII has been + maintained across known versions of netCDF4-python. + +Documentation Changes +===================== +* Fuller doc-string detail added to :func:`iris.analysis.cartography.unrotate_pole` and + :func:`iris.analysis.cartography.rotate_pole`. diff --git a/docs/iris/src/whatsnew/1.12.rst b/docs/iris/src/whatsnew/1.12.rst new file mode 100644 index 0000000000..59ea47d876 --- /dev/null +++ b/docs/iris/src/whatsnew/1.12.rst @@ -0,0 +1,131 @@ +What's New in Iris 1.12 +*********************** + +:Release: 1.12 +:Date: 2017-01-30 + +This document explains the new/changed features of Iris in version 1.12 +(:doc:`View all changes `.) + +Iris 1.12 Features +================== +.. _showcase: + +.. admonition:: Showcase Feature: New regridding schemes + + A new regridding scheme, :class:`iris.analysis.UnstructuredNearest`, + performs nearest-neighbour regridding from "unstructured" onto "structured" + grids. Here, "unstructured" means that the data has X and Y coordinate values + defined at each horizontal location, instead of the independent X and Y + dimensions that constitute a structured grid. + For example, data sampled on a trajectory or a tripolar ocean grid would be + unstructured. + + In addition, added experimental ProjectedUnstructured regridders which use + scipy.interpolate.griddata to regrid unstructured data + (see :class:`iris.experimental.regrid.ProjectedUnstructuredLinear` and + :class:`iris.experimental.regrid.ProjectedUnstructuredNearest`). The + essential purpose is the same as :class:`iris.analysis.UnstructuredNearest`. + This scheme, by comparison, is generally faster, but less accurate. + +.. admonition:: Showcase Feature: Fast UM file loading + + Support has been added for accelerated loading of UM files (PP and + Fieldsfile), when these have a suitable regular "structured" form. + + A context manager is used to enable fast um loading in all the regular Iris + load functions, such as :meth:`iris.load` and :meth:`iris.load_cube`, + when loading data from UM file types. + For example: + + >>> import iris + >>> filepath = iris.sample_data_path('uk_hires.pp') + >>> from iris.fileformats.um import structured_um_loading + >>> with structured_um_loading(): + ... cube = iris.load_cube(filepath, 'air_potential_temperature') + + This approach can deliver loading which is 10 times faster or more. + For example : + + * a 78 Gb fieldsfile of 51,840 fields loads in about 13 rather than 190 + seconds. + * a set of 25 800Mb PP files loads in about 21 rather than 220 seconds. + + You can load data with structured loading and compare the results with those + from "normal" loading to check whether they are equivalent. + + * The results will normally differ, if at all, only in having dimensions in a + different order or a different choice of dimension coordinates. + **In these cases, structured loading can be used with confidence.** + + * Ordinary Fieldsfiles (i.e. model outputs) are generally suitable for + structured loading. Many PP files also are, especially if produced + directly from Fieldsfiles, and retaining the same field ordering. + + * Some inputs however (generally PP) will be unsuitable for structured + loading : For instance if a particular combination of vertical levels and + time has been omitted, or some fields appear out of order. + + * There are also some known unsupported cases, including data which is + produced on pseudo-levels. See the detail documentation on this. + + It is the user's responsibility to use structured loading only with suitable + inputs. Otherwise, odd behaviour and even incorrect loading can result, as + input files are not checked as fully as in a normal load. + + Although the user loading call for structured loading can be just the same, + and the returned results are also often identical, structured loading is not + in fact an exact *identical* replacement for normal loading: + + * results are often somewhat different, especially regarding the order + of dimensions and the choice of dimension coordinates. + + * although both constraints and user callbacks are supported, callback + routines will generally need to be re-written. This is because a + 'raw' cube in structured loading generally covers *multiple* PPfields, + which therefore need to be handled as a collection : A grouping object + containing them is passed to the callback 'field' argument. + An example showing callbacks suitable for both normal and structured + loading can be seen `here `_. + + For full details, see : :meth:`iris.fileformats.um.structured_um_loading`. + + +* A skip pattern is introduced to the fields file loader, such that fields + which cannot be turned into iris PPField instances are skipped and the + remaining fields are loaded. This especially applies to certain types of + files that can contain fields with a non-standard LBREL value : Iris can now + load such a file, skipping the unreadable field and printing a warning + message. + +* Iris can now load PP files containing a PP field whose LBLREC value does not + match the field length recorded in the file. + A warning message is printed, and all fields up to the offending one are + loaded and returned. + Previously, this simply resulted in an unrecoverable error. + +* The transpose method of a Cube now results in a lazy transposed view of the + original rather than realising the data then transposing it. + +* The :func:`iris.analysis.cartography.area_weights` function is now more + accurate for single precision input bounds. + +* Iris is now able to read seconds in datetimes provided in NAME trajectory + files. + +* Optimisations to trajectory interpolations have resulted in a significant + speed improvement. + +* Many new and updated translations between CF spec and STASH codes. + + +Deprecations +============ +* The module :mod:`iris.experimental.fieldsfile` has been deprecated, in favour + of the new fast-loading mechanism provided by + :meth:`iris.fileformats.um.structured_um_loading`. + +Documentation Changes +===================== +* Corrected documentation of :class:`iris.analysis.AreaWeighted` scheme to make + the usage scope clearer. diff --git a/docs/iris/src/whatsnew/1.13.rst b/docs/iris/src/whatsnew/1.13.rst new file mode 100644 index 0000000000..532c160f13 --- /dev/null +++ b/docs/iris/src/whatsnew/1.13.rst @@ -0,0 +1,37 @@ +What's New in Iris 1.13 +*********************** + +:Release: 1.13 +:Date: 2017-05-17 + + +This document explains the new/changed features of Iris in version 1.13 +(:doc:`View all changes `.) + +Iris 1.13 Features +================== + +* Allow the reading of NAME trajectories stored by time instead of by particle number. +* An experimental link to python-stratify via :mod:`iris.experimental.stratify`. +* Data arrays may be shared between cubes, and subsets of cubes, by using the :meth:`iris.cube.share_data` flag. + + +Bug Fixes +========= + +* The bounds are now set correctly on the longitude coordinate if a zonal mean diagnostic has been loaded from a PP file as per the CF Standard. +* NetCDF loading will now determine whether there is a string-valued scalar label, i.e. a character variable that only has one dimension (the length of the string), and interpret this correctly. +* A line plot of geographic coordinates (e.g. drawing a trajectory) wraps around the edge of the map cleanly, rather than plotting a segment straight across the map. +* When saving to PP, lazy data is preserved when generating PP fields from cubes so that a list of cubes can be saved to PP without excessive memory requirements. +* An error is now correctly raised if a user tries to perform an arithmetic operation on two cubes with mismatching coordinates. Previously these cases were caught by the add and subtract operators, and now it is also caught by the multiply and divide operators. +* Limited area Rotated Pole datasets where the data range is ``0 <= lambda < 360``, for example as produced in New Zealand, are plotted over a sensible map extent by default. +* Removed the potential for a RuntimeWarning: overflow encountered in ``int_scalars`` which was missed during collapsed calculations. This could trip up unwary users of limited data types, such as int32 for very large numbers (e.g. seconds since 1970). +* The CF conventions state that certain ``formula_terms`` terms may be omitted and assumed to be zero (http://cfconventions.org/cf-conventions/v1.6.0/cf-conventions.html#dimensionless-v-coord) so Iris now allows factories to be constructed with missing terms. +* In the User Guide's contour plot example, clabel inline is set to be False so that it renders correctly, avoiding spurious horizontal lines across plots, although this does make labels a little harder to see. +* The computation of area weights has been changed to a more numerically stable form. The previous form converted latitude to colatitude and used difference of cosines in the cell area computation. This formulation uses latitude and difference of sines. The conversion from latitude to colatitude at lower precision causes errors when computing the cell areas. + +Testing +======= + +* Iris has adopted conda-forge to provide environments for continuous integration testing. + diff --git a/docs/iris/src/whatsnew/1.2.rst b/docs/iris/src/whatsnew/1.2.rst index df73b2bb37..720ae73376 100644 --- a/docs/iris/src/whatsnew/1.2.rst +++ b/docs/iris/src/whatsnew/1.2.rst @@ -5,6 +5,7 @@ What's new in Iris 1.2 :Date: 7th March 2013 This document explains the new/changed features of Iris in version 1.2. +(:doc:`View all changes `.) Iris 1.2 features ================= diff --git a/docs/iris/src/whatsnew/1.3.rst b/docs/iris/src/whatsnew/1.3.rst index d8b56ed1b6..dbea08ad03 100644 --- a/docs/iris/src/whatsnew/1.3.rst +++ b/docs/iris/src/whatsnew/1.3.rst @@ -5,6 +5,7 @@ What's new in Iris 1.3 :Date: 27 March 2013 This document explains the new/changed features of Iris in version 1.3. +(:doc:`View all changes `.) Iris 1.3 features ================= @@ -109,7 +110,7 @@ restriction. For example, if one began with a collection of Cubes, each containing data for a different range of times:: - >>> print cubes + >>> print(cubes) 0: air_temperature (time: 30; latitude: 145; longitude: 192) 1: air_temperature (time: 30; latitude: 145; longitude: 192) 2: air_temperature (time: 30; latitude: 145; longitude: 192) @@ -118,7 +119,7 @@ One could use :func:`iris.experimental.concatenate.concatenate()` to combine these into a single Cube as follows:: >>> new_cubes = iris.experimental.concatenate.concatenate(cubes) - >>> print new_cubes + >>> print(new_cubes) 0: air_temperature (time: 90; latitude: 145; longitude: 192) .. note:: diff --git a/docs/iris/src/whatsnew/1.4.rst b/docs/iris/src/whatsnew/1.4.rst index 5f7b9b0aab..053a6e1096 100644 --- a/docs/iris/src/whatsnew/1.4.rst +++ b/docs/iris/src/whatsnew/1.4.rst @@ -5,6 +5,7 @@ What's new in Iris 1.4 :Date: 14 June 2013 This document explains the new/changed features of Iris in version 1.4. +(:doc:`View all changes `.) Iris 1.4 features ================= diff --git a/docs/iris/src/whatsnew/1.5.rst b/docs/iris/src/whatsnew/1.5.rst index dfdb3982d6..7af1e40285 100644 --- a/docs/iris/src/whatsnew/1.5.rst +++ b/docs/iris/src/whatsnew/1.5.rst @@ -4,6 +4,8 @@ What's new in Iris 1.5 :Release: 1.5.0 :Date: 12 September 2013 +This document explains the new/changed features of Iris in version 1.5. +(:doc:`View all changes `.) Iris 1.5 features ================= @@ -34,7 +36,7 @@ Iris 1.5 features # Get cube slices corresponding to the dimension associated with longitude # and the first dimension from a multi-dimensional cube. for sub_cube in cube.slices(['longitude', 0]): - print sub_cube + print(sub_cube) * :mod:`iris.experimental.animate` now provides experimental animation support. @@ -65,7 +67,7 @@ Iris 1.5 features plt.gca().gridlines() plt.show() - .. image:: pics/transverse_merc.png + .. image:: images/transverse_merc.png * Support for loading NAME files (gridded and trajectory data). * Multi-dimensional coordinate support added for @@ -99,7 +101,7 @@ Iris 1.5 features the direction of vertical axes will be reversed if the corresponding coordinate has a "positive" attribute set to "down". - see: :ref:`graphics-atlantic_profiles` + see: :ref:`Oceanography-atlantic_profiles` * New PP stashcode translations added including 'dewpoint' and 'relative_humidity'. diff --git a/docs/iris/src/whatsnew/1.6.rst b/docs/iris/src/whatsnew/1.6.rst index 4720eb251d..4b540c6cc9 100644 --- a/docs/iris/src/whatsnew/1.6.rst +++ b/docs/iris/src/whatsnew/1.6.rst @@ -1,8 +1,11 @@ What's new in Iris 1.6 ********************** -:Release: 1.6.0 -:Date: 23rd January 2014 +:Release: 1.6.1 +:Date: 18th February 2014 + +This document explains the new/changed features of Iris in version 1.6. +(:doc:`View all changes `.) Iris 1.6 features ================= @@ -23,7 +26,7 @@ Iris 1.6 features >>> from iris.coords import DimCoord >>> iris.FUTURE.cell_datetime_objects = True >>> coord = DimCoord([1, 2, 3], 'time', units='hours since epoch') - >>> print [str(cell) for cell in coord.cells()] + >>> print([str(cell) for cell in coord.cells()]) ['1970-01-01 01:00:00', '1970-01-01 02:00:00', '1970-01-01 03:00:00'] Note that, either a :class:`datetime.datetime` or :class:`netcdftime.datetime` @@ -43,14 +46,14 @@ Iris 1.6 features .. code-block:: python - >>> print iris.FUTURE + >>> print(iris.FUTURE) Future(cell_datetime_objects=False) >>> with iris.FUTURE.context(cell_datetime_objects=True): ... # Code that expects to deal with datetime-like objects. - ... print iris.FUTURE + ... print(iris.FUTURE) ... Future(cell_datetime_objects=True) - >>> print iris.FUTURE + >>> print(iris.FUTURE) Future(cell_datetime_objects=False) .. admonition:: Showcase Feature - Partial date/time ... @@ -188,6 +191,11 @@ Incompatible changes :func:`~iris.coord_categorisation.add_weekday_shortname` :func:`~iris.coord_categorisation.add_weekday` :func:`~iris.coord_categorisation.add_season_month_initials` :func:`~iris.coord_categorisation.add_season` =============================================================== ======================================================= +* When a cube is loaded from PP or GRIB and it has both time and forecast period + coordinates, and the time coordinate has bounds, the forecast period coordinate + will now also have bounds. These bounds will be aligned with the bounds of the + time coordinate taking into account the forecast reference time. Also, + the forecast period point will now be aligned with the time point. Deprecations ============ @@ -240,12 +248,12 @@ consuming processing, or to reap the benefit of fast-loading a pickled cube. .. _rms: -The RPM aggregator supports weights +The RMS aggregator supports weights =================================== -A :data:`iris.analysis.RMS` aggregator has been extended to allow the use of +The :data:`iris.analysis.RMS` aggregator has been extended to allow the use of weights using the new keyword argument :data:`weights`. -For example, a RMS weighted cube collapse is performed as follows: +For example, an RMS weighted cube collapse is performed as follows: .. code-block:: python diff --git a/docs/iris/src/whatsnew/1.7.rst b/docs/iris/src/whatsnew/1.7.rst new file mode 100644 index 0000000000..2f3a52fbb9 --- /dev/null +++ b/docs/iris/src/whatsnew/1.7.rst @@ -0,0 +1,248 @@ +What's new in Iris 1.7 +********************** + +This document explains the new/changed features of Iris in version 1.7. +(:doc:`View all changes `.) + +:Release: 1.7.4 +:Date: 15th April 2015 + +Iris 1.7 features +================= + +.. _showcase: + +.. admonition:: Showcase: Iris is making use of Biggus + + Iris is now making extensive use of `Biggus `_ + for virtual arrays and lazy array evaluation. In practice this means that analyses + of cubes with data bigger than the available system memory are now possible. + + Other than the improved functionality the changes are mostly + transparent; for example, before the introduction of biggus, MemoryErrors + were likely for very large datasets:: + + >>> result = extremely_large_cube.collapsed('time', iris.analyis.MEAN) + MemoryError + + Now, for supported operations, the evaluation is lazy (i.e. it doesn't take + place until the actual data is subsequently requested) and can handle data + larger than available system memory:: + + >>> result = extremely_large_cube.collapsed('time', iris.analyis.MEAN) + >>> print(type(result)) + + + Memory is still a limiting factor if ever the data is desired as a NumPy array + (e.g. via :data:`cube.data `), but additional methods have + been added to the Cube to support querying and subsequently accessing the "lazy" + data form (see :meth:`~iris.cube.Cube.has_lazy_data` and + :meth:`~iris.cube.Cube.lazy_data`). + +.. admonition:: Showcase: New interpolation and regridding API + + New interpolation and regridding interfaces have been added which simplify and + extend the existing functionality. + + The interfaces are exposed on the cube in the form of the + :meth:`~iris.cube.Cube.interpolate` and :meth:`~iris.cube.Cube.regrid` methods. + Conceptually the signatures of the methods are:: + + interpolated_cube = cube.interpolate(interpolation_points, interpolation_scheme) + + and:: + + regridded_cube = cube.regrid(target_grid_cube, regridding_scheme) + + Whilst not all schemes have been migrated to the new interface, + :class:`iris.analysis.Linear` defines both linear interpolation and regridding, + and :class:`iris.analysis.AreaWeighted` defines an area weighted regridding + scheme. + +.. admonition:: Showcase: Merge and concatenate reporting + + Merge reporting is designed as an aid to the merge processes. Should merging + a :class:`~iris.cube.CubeList` fail, merge reporting means that a descriptive + error will be raised that details the differences between the cubes in the + :class:`~iris.cube.CubeList` that prevented the merge from being successful. + + A new :class:`~iris.cube.CubeList` method, called + :meth:`~iris.cube.CubeList.merge_cube`, has been introduced. Calling it on a + :class:`~iris.cube.CubeList` will result in a single merged + :class:`~iris.cube.Cube` being returned or an error message being raised + that describes why the merge process failed. + + The following example demonstrates the error message that describes a merge + failure caused by cubes having differing attributes:: + + >>> cube_list = iris.cube.CubeList((c1, c2)) + >>> cube_list.merge_cube() + Traceback (most recent call last): + ... + raise iris.exceptions.MergeError(msgs) + iris.exceptions.MergeError: failed to merge into a single cube. + cube.attributes keys differ: 'foo' + + The naming of this new method mirrors that of Iris load functions, where + one would always expect a :class:`~iris.cube.CubeList` from :func:`iris.load` + and a :class:`~iris.cube.Cube` from :func:`iris.load_cube`. + + Concatenate reporting is the equivalent process for concatenating a + :class:`~iris.cube.CubeList`. It is accessed through the method + :meth:`~iris.cube.CubeList.concatenate_cube`, which will return a single + concatenated cube or produce an error message that describes why the + concatenate process failed. + +.. admonition:: Showcase: Cube broadcasting + + When performing cube arithmetic, cubes now follow similar broadcasting rules + as NumPy arrays. + + However, the additional richness of Iris coordinate meta-data provides an + enhanced capability beyond the basic broadcasting behaviour of NumPy. + + This means that when performing cube arithmetic, the dimensionality and shape of + cubes no longer need to match. For example, if the dimensionality of a cube is + reduced by collapsing, then the result can be used to subtract from the original + cube to calculate an anomaly:: + + >>> time_mean = original_cube.collapsed('time', iris.analysis.MEAN) + >>> mean_anomaly = original_cube - time_mean + + Given both broadcasting **and** coordinate meta-data, Iris can now perform + arithmetic with cubes that have similar but not identical shape:: + + >>> similar_cube = original_cube.copy() + >>> similar_cube.transpose() + >>> zero_cube = original_cube - similar_cube + +* Merge reporting that raises a descriptive error if the merge process fails. +* Linear interpolation and regridding now make use of SciPy's RegularGridInterpolator + for much faster linear interpolation. +* NAME file loading now handles the "no time averaging" column and translates + height/altitude above ground/sea-level columns into appropriate coordinate metadata. +* The NetCDF saver has been extended to allow saving of cubes with hybrid pressure + auxiliary factories. +* PP/FF loading supports LBLEV of 9999. +* Extended GRIB1 loading to support data on hybrid pressure levels. +* :func:`iris.coord_categorisation.add_day_of_year` can be used to add categorised + day of year coordinates based on time coordinates with non-Gregorian calendars. +* Support for loading data on reduced grids from GRIB files in raw form without + automatically interpolating to a regular grid. +* The coordinate systems :class:`iris.coord_systems.Orthographic` and + :class:`iris.coord_systems.VerticalPerspective` (for imagery from geostationary + satellites) have been added. +* Extended NetCDF loading to support the "ocean sigma over z" auxiliary coordinate + factory. +* Support added for loading CF-NetCDF data with bounds arrays that are missing a + vertex dimension. +* :meth:`iris.cube.Cube.rolling_window` can now be used with string-based + :class:`iris.coords.AuxCoord` instances. +* Loading of PP and FF files has been optimised through deferring creation of + PPField attributes. +* Automatic association of a coordinate's CF formula terms variable with the + data variable associated with that coordinate. +* PP loading translates cross-section height into a dimensional auxiliary coordinate. +* String auxiliary coordinates can now be plotted with the Iris plotting wrappers. +* :func:`iris.analysis.geometry.geometry_area_weights` now allows for the calculation of + normalized cell weights. +* Many new translations between the CF spec and STASH codes or GRIB2 parameter codes. +* PP save rules add the data's UM Version to the attributes of the saved file + when appropriate. +* NetCDF reference surface variable promotion available through the + :class:`iris.FUTURE` mechanism. +* A speed improvement in calculation of :func:`iris.analysis.geometry.geometry_area_weights`. +* The mdtol keyword was added to area-weighted regridding to allow control of the + tolerance for missing data. For a further description of this concept, see + :class:`iris.analysis.AreaWeighted`. +* Handling for patching of the CF conventions global attribute via a defined + cf_patch_conventions function. +* Deferred GRIB data loading has been introduced for reduced memory consumption when + loading GRIB files. +* Concatenate reporting that raises a descriptive error if the concatenation + process fails. +* A speed improvement when loading PP or FF data and constraining on STASH code. + +Bugs fixed +========== +* Data containing more than one reference cube for constructing hybrid height + coordinates can now be loaded. +* Removed cause of increased margin of error when interpolating. +* Changed floating-point precision used when wrapping points for interpolation. +* Mappables that can be used to generate colorbars are now returned by Iris + plotting wrappers. +* NetCDF load ignores over-specified formula terms on bounded dimensionless vertical + coordinates. +* Auxiliary coordinate factory loading now correctly interprets formula term + varibles for "atmosphere hybrid sigma pressure" coordinate data. +* Corrected comparison of NumPy NaN values in cube merge process. +* Fixes for :meth:`iris.cube.Cube.intersection` to correct calculating the intersection + of a cube with split bounds, handling of circular coordinates, handling of + monotonically descending bounded coordinats and for finding a wrapped two-point + result and longitude tolerances. +* A bug affecting :meth:`iris.cube.Cube.extract` and :meth:`iris.cube.CubeList.extract` + that led to unexpected behaviour when operating on scalar cubes has been fixed. +* Aggregate_by may now be passed single-value coordinates. +* Making a copy of a :class:`iris.coords.DimCoord` no longer results in the writeable + flag on the copied points and bounds arrays being set to True. +* Can now save to PP a cube that has vertical levels but no orography. +* Fix a bug causing surface altitude and surface pressure fields to not appear + in cubes loaded with a STASH constraint. +* Fixed support for :class:`iris.fileformats.pp.STASH` objects in STASH constraints. +* A fix to avoid a problem where cube attribute names clash with NetCDF reserved attribute names. +* A fix to allow :meth:`iris.cube.CubeList.concatenate` to deal with descending coordinate order. +* Add missing NetCDF attribute `varname` when constructing a new :class:`iris.coords.AuxCoord`. +* The datatype of time arrays converted with :func:`iris.util.unify_time_units` is now preserved. + +Bugs fixed in v1.7.3 +^^^^^^^^^^^^^^^^^^^^ +* Scalar dimension coordinates can now be concatenated with :meth:`iris.cube.CubeList.concatenate`. +* Arbitrary names can no longer be set for elements of a :class:`iris.fileformats.pp.SplittableInt`. +* Cubes that contain a pseudo-level coordinate can now be saved to PP. +* Fixed a bug in the FieldsFile loader that prevented it always loading all available fields. + +Bugs fixed in v1.7.4 +^^^^^^^^^^^^^^^^^^^^ +* :meth:`Coord.guess_bounds` can now deal with circular coordinates. +* :meth:`Coord.nearest_neighbour_index` can now work with descending bounds. +* Passing `weights` to :meth:`Cube.rolling_window` no longer prevents other + keyword arguments from being passed to the aggregator. +* Several minor fixes to allow use of Iris on Windows. +* Made use of the new standard_parallels keyword in Cartopy's LambertConformal + projection (Cartopy v0.12). Older versions of Iris will not be able to + create LambertConformal coordinate systems with Cartopy >= 0.12. + +Incompatible changes +==================== +* Saving a cube with a STASH attribute to NetCDF now produces a variable + with an attribute of "um_stash_source" rather than "ukmo__um_stash_source". +* Cubes saved to NetCDF with a coordinate system referencing a spherical ellipsoid + now result in the grid mapping variable containing only the "earth_radius" attribute, + rather than the "semi_major_axis" and "semi_minor_axis". +* Collapsing a cube over all of its dimensions now results in a scalar cube rather + than a 1d cube. + +Deprecations +============ +* :func:`iris.util.ensure_array` has been deprecated. +* Deprecated the :func:`iris.fileformats.pp.reset_load_rules` and + :func:`iris.fileformats.grib.reset_load_rules` functions. +* Matplotlib is no longer a core Iris dependency. + +Documentation Changes +===================== +* New sections on :ref:`cube broadcasting ` and + :doc:`regridding and interpolation ` + have been added to the :doc:`user guide `. +* An example demonstrating custom log-scale colouring has been added. + See :ref:`General-anomaly_log_colouring`. +* An example demonstrating the creation of a custom + :class:`iris.analysis.Aggregator` has been added. + See :ref:`General-custom_aggregation`. +* An example of reprojecting data from 2D auxiliary spatial coordinates + (such as that from the ORCA grid) has been added. See :ref:`General-orca_projection`. +* A clarification of the behaviour of :func:`iris.analysis.calculus.differentiate`. +* A new :doc:`"whitepapers" ` section has been added to the documentation along + with the addition of a paper providing an :doc:`overview of the load process for UM-like + fileformats (e.g. PP and Fieldsfile) `. + diff --git a/docs/iris/src/whatsnew/1.8.rst b/docs/iris/src/whatsnew/1.8.rst new file mode 100644 index 0000000000..c763411ed8 --- /dev/null +++ b/docs/iris/src/whatsnew/1.8.rst @@ -0,0 +1,181 @@ +What's new in Iris 1.8 +********************** + +:Release: 1.8.1 +:Date: 3rd June 2015 + +This document explains the new/changed features of Iris in version 1.8. +(:doc:`View all changes `.) + +Iris 1.8 features +================= + +.. _showcase: + +.. admonition:: Showcase: Rotate winds + + Iris can now rotate and unrotate wind vector data by transforming the wind + vector data to another coordinate system. + + For example:: + + >>> from iris.analysis.cartography import rotate_winds + >>> u_cube = iris.load_cube('my_rotated_u_wind_cube.pp') + >>> v_cube = iris.load_cube('my_rotated_v_wind_cube.pp') + >>> target_cs = iris.coord_systems.GeogCS(6371229.0) + >>> u_prime, v_prime = rotate_winds(u_cube, v_cube, target_cs) + +.. admonition:: Showcase: Nearest-neighbour scheme + + A nearest-neighbour scheme for interpolation and regridding has been added + to Iris. This joins the existing :class:`~iris.analysis.Linear` and + :class:`~iris.analysis.AreaWeighted` interpolation and regridding schemes. + + For example:: + + >>> result = cube.interpolate(sample_points, iris.analysis.Nearest()) + >>> regridded_cube = cube.regrid(target_grid, iris.analysis.Nearest()) + +.. admonition:: Showcase: Slices over a coordinate + + You can slice over one or more dimensions of a cube using :meth:`iris.cube.Cube.slices_over`. + This provides similar functionality to :meth:`~iris.cube.Cube.slices` but with + almost the opposite outcome. + + Using :meth:`~iris.cube.Cube.slices` to slice a cube on a selected dimension returns + all possible slices of the cube with the selected dimension retaining its dimensionality. + Using :meth:`~iris.cube.Cube.slices_over` to slice a cube on a selected + dimension returns all possible slices of the cube over the selected dimension. + + To demonstrate this:: + + >>> cube = iris.load(iris.sample_data_path('colpex.pp'))[0] + >>> print(cube.summary(shorten=True)) + air_potential_temperature / (K) (time: 6; model_level_number: 10; grid_latitude: 83; grid_longitude: 83) + >>> my_slice = next(cube.slices('time')) + >>> my_slice_over = next(cube.slices_over('time')) + >>> print(my_slice.summary(shorten=True)) + air_potential_temperature / (K) (time: 6) + >>> print(my_slice_over.summary(shorten=True)) + air_potential_temperature / (K) (model_level_number: 10; grid_latitude: 83; grid_longitude: 83) + + +* :func:`iris.cube.CubeList.concatenate` now works with `biggus `_ arrays and so + now supports concatenation of cubes with deferred data. +* Improvements to NetCDF saving through using biggus: + + * A cube's lazy data payload will still be lazy after saving; the data will not + be loaded into memory by the save operation. + * Cubes with data payloads larger than system memory can now be saved to NetCDF + through biggus streaming the data to disk. + +* :func:`iris.util.demote_dim_coord_to_aux_coord` and :func:`iris.util.promote_aux_coord_to_dim_coord` + allow a coordinate to be easily demoted or promoted within a cube. +* :func:`iris.util.squeeze` removes all length 1 dimensions from a cube, and demotes + any associated squeeze dimension :class:`~iris.coords.DimCoord` to be a scalar coordinate. +* :meth:`iris.cube.Cube.slices_over`, which returns an iterator of all sub-cubes along a given + coordinate or dimension index. +* :meth:`iris.cube.Cube.interpolate` now accepts datetime.datetime and + netcdftime.datetime instances for date or time coordinates. +* Many new and updated translations between CF spec and STASH codes or GRIB2 parameter + codes. +* PP/FF loader creates a height coordinate at 1.5m or 10m for certain relevant stash codes. +* Lazy aggregator support for the :class:`standard deviation ` + aggregator has been added. +* A speed improvement in calculation of :func:`iris.analysis.cartography.area_weights`. +* Experimental support for unstructured grids has been added with :func:`iris.experimental.ugrid`. + This has been implemented using `UGRID `_. +* :meth:`iris.cube.CubeList.extract_overlapping` supports extraction of cubes over + regions where common coordinates overlap, over multiple coordinates. +* Warnings raised due to invalid units in loaded data have been suppressed. +* Experimental low-level read and write access for FieldsFile variants is now supported + via :class:`iris.experimental.um.FieldsFileVariant`. +* PP loader will return cubes for all fields prior to a field with a problematic + header before raising an exception. +* NetCDF loader skips invalid global attributes, raising a warning rather than raising an + exception. +* A warning is now raised rather than an exception when constructing an + :class:`~iris.aux_factory.AuxCoordFactory` fails. +* Supported :class:`aux coordinate factories ` + have been extended to include: + + * ``ocean sigma coordinate``, + * ``ocean s coordinate``, + * ``ocean s coordinate, generic form 1``, and + * ``ocean s coordinate, generic form 2``. + +* :meth:`iris.cube.Cube.intersection` now supports taking a points-only intersection. + Any bounds on intersected coordinates are ignored but retained. +* The FF loader's known handled grids now includes ``Grid 21``. +* A :class:`nearest neighbour ` scheme is now provided for + :meth:`iris.cube.Cube.interpolate` and :meth:`iris.cube.Cube.regrid`. +* :func:`iris.analysis.cartography.rotate_winds` supports transformation of wind vectors + to a different coordinate system. +* NumPy universal functions can now be applied to cubes using + :func:`iris.analysis.maths.apply_ufunc`. +* Generic functions can be applied to :class:`~iris.cube.Cube` instances using + :class:`iris.analysis.maths.IFunc`. +* The :class:`iris.analysis.Linear` scheme now supports regridding as well as interpolation. + This enables :meth:`iris.cube.Cube.regrid` to perform bilinear regridding, which now + replaces the experimental routine "iris.experimental.regrid.regrid_bilinear_rectilinear_src_and_grid". + +Bugs fixed +========== + +1.8.0 +------ +* Fix in netCDF loader to correctly determine whether the longitude coordinate + (including scalar coordinates) is circular. +* :meth:`iris.cube.Cube.intersection` now supports bounds that extend slightly beyond 360 + degrees. +* Lateral Boundary Condition (LBC) type FieldFiles are now handled correctly by the FF loader. +* Making a copy of a scalar cube with no data now correctly copies the data array. +* Height coordinates in NAME trajectory output files have been changed to match other + NAME output file formats. +* Fixed datatype when loading an ``integer_constants`` array from a FieldsFile. +* FF/PP loader adds appropriate cell methods for ``lbtim.ib = 3`` intervals. +* An exception is raised if the units of the latitude and longitude coordinates + of the cube passed into :func:`iris.analysis.cartography.area_weights` are not + convertible to radians. +* GRIB1 loader now creates a time coordinate for a time range indicator of 2. +* NetCDF loader now loads units that are empty strings as dimensionless. + +1.8.1 +------ +* The PP loader now carefully handles floating point errors in date time conversions to hours. +* The handling fill values for lazy data loaded from NetCDF files is altered, such that the + _FillValue set in the file is preserved through lazy operations. +* The risk that cube intersections could return incorrect results due to floating point + tolerances is reduced. +* The new GRIB2 loading code is altered to enable the loading of various data representation + templates; the data value unpacking is handled by the GRIB API. +* Saving cube collections to NetCDF, where multiple similar aux-factories exist within the cubes, + is now carefully handled such that extra file variables are created where required in some cases. + +1.8.2 +----- +* A fix to prevent the error: *AttributeError: 'module' object has no attribute 'date2num'*. + This was caused by the function :func:`netcdftime.date2num` being removed from the netCDF4 + package in recent versions. + +Deprecations +============ +* The original GRIB loader has been deprecated and replaced with a new + template-based GRIB loader. +* Deprecated default NetCDF save behaviour of assigning the outermost + dimension to be unlimited. Switch to the new behaviour with no auto + assignment by setting :data:`iris.FUTURE.netcdf_no_unlimited` to True. +* The former experimental method + "iris.experimental.regrid.regrid_bilinear_rectilinear_src_and_grid" has been removed, as + :class:`iris.analysis.Linear` now includes this functionality. + +Documentation Changes +===================== +* A chapter on :doc:`merge and concatenate ` has been + added to the :doc:`user guide `. +* A section on installing Iris using `conda `_ has been + added to the :doc:`install guide `. +* Updates to the chapter on + :doc:`regridding and interpolation ` + have been added to the :doc:`user guide `. + diff --git a/docs/iris/src/whatsnew/1.9.rst b/docs/iris/src/whatsnew/1.9.rst new file mode 100644 index 0000000000..7a4848b434 --- /dev/null +++ b/docs/iris/src/whatsnew/1.9.rst @@ -0,0 +1,129 @@ +What's New in Iris 1.9 +********************** + +:Release: 1.9.2 +:Date: 28th January 2016 + +This document explains the new/changed features of Iris in version 1.9 +(:doc:`View all changes `.) + +Iris 1.9 Features +================= +* Support for running on Python 3.4 has been added to the whole code base. Some features which + depend on external libraries will not be available until they also support Python 3, namely: + + * gribapi does not yet provide a Python 3 interface + +* Added the UM pseudo level type to the information made available in the STASH_TRANS table in :mod:`iris.fileformats.um._ff_cross_references` +* When reading "cell_methods" attributes from NetCDF files, allow optional whitespace before the colon. + This is not strictly in the CF spec, but is a common occurrence. +* Basic cube arithemetic (plus, minus, times, divide) now supports lazy evaluation. +* :meth:`iris.analysis.cartography.rotate_winds` can now operate much faster on multi-layer (i.e. > 2-dimensional) cubes, + as it calculates rotation coefficients only once and reuses them for additional layers. + +* Linear regridding of a multi-layer (i.e. > 2-dimensional) cube is now much faster, + as it calculates transform coefficients just once and reuses them for additional layers. +* Ensemble statistics can now be saved to GRIB2, using Product Definition Template 4.11. + +* Loading of NetCDF data with ocean vertical coordinates now returns a 'depth' in addition to an 'eta' cube. + This operates on specific defined dimensionless coordinates : see CF spec version 1.6, Appendix D. + +* :func:`iris.analysis.stats.pearsonr` updates: + + * Cubes can now be different shapes, provided one is broadcastable to the + other. + * Accepts weights keyword for weighted correlations. + * Accepts mdtol keyword for missing data tolerance level. + * Accepts common_mask keyword for restricting calculation to unmasked pairs of + cells. + +* Added a new point-in-cell regridding scheme, :class:`iris.experimental.regrid.PointInCell`. +* Added :meth:`iris.analysis.WPERCENTILE` - a new weighted aggregator for calculating + percentiles. +* Added cell-method translations for LBPROC=64 and 192 in UM files, encoding 'zonal mean' and 'zonal+time mean'. + +* Support for loading GRIB2 messages defined on a Lambert conformal grid has been added to + the GRIB2 loader. +* Data on potential-temperature (theta) levels can now be saved to GRIB2, with a fixed surface type of 107. +* Added several new helper functions for file-save customisation, + (see also : :doc:`Saving Iris Cubes `): + + * :meth:`iris.fileformats.grib.as_pairs` + * :meth:`iris.fileformats.grib.as_messages` + * :meth:`iris.fileformats.grib.save_messages` + * :meth:`iris.fileformats.pp.as_pairs` + * :meth:`iris.fileformats.pp.as_fields` + * :meth:`iris.fileformats.pp.save_fields` +* Loading data from GRIB2 now supports most of the currently defined 'data representation templates' : + code numbers 0, 1, 2, 3, 4, 40, 41, 50, 51 and 61. +* When a Fieldsfile is opened for update as a :class:`iris.experimental.um.FieldsFileVariant`, + unmodified packed data in the file can now be retained in the original form. + Previously it could only be stored in an unpacked form. +* When reading and writing NetCDF data, the CF 'flag' attributes, + "flag_masks", "flag_meanings" and "flag_values" are now preserved through Iris load and save. +* `mo_pack `_ was added as an optional dependency. + It is used to encode and decode data in WGDOS packed form. +* The :meth:`iris.experimental.um.Field.get_data` method can now be used to read Fieldsfile data + after the original :class:`iris.experimental.um.FieldsFileVariant` has been closed. + +Bugs Fixed +========== +* Fixed a bug in :meth:`iris.unit.Unit.convert` + (and the equivalent in `cf_units `_) + so that it now converts data to the native endianness, without which udunits could not read it correctly. +* Fixed a bug with loading WGDOS packed data in :mod:`iris.experimental.um`, + which could occasionally crash, with some data. +* Ignore non-numeric suffices in the numpy version string, which would otherwise crash some regridding routines. +* fixed a bug in :mod:`iris.fileformats.um_cf_map` where the standard name + for the stash code m01s12i187 was incorrectly set, such that it is inconsistent + with the stated unit of measure, 'm s-1'. The different name, a long_name + of 'change_over_time_in_upward_air_velocity_due_to_advection' with + units of 'm s-1' is now used instead. +* Fixed a bug in :meth:`iris.cube.Cube.intersection`. + When edge points were at (base + period), intersection would unnecessarily wrap the data. +* Fixed a bug in :mod:`iris.fileformats.pp`. + A previous release removed the ability to pass a partial constraint on STASH attribute. +* :meth:`iris.plot.default_projection_extent` now correctly raises an exception if a cube has X bounds but no Y bounds, or vice versa. + Previously it never failed this, as the test was wrong. +* When loading NetCDF data, a "units" attribute containing unicode characters is now transformed by backslash-replacement. + Previously this caused a crash. Note: unicode units are *not supported in the CF conventions*. +* When saving to NetCDF, factory-derived auxiliary coordinates are now correctly saved with different names when they are not identical. + Previously, such coordinates could be saved with the same name, leading to errors. +* Fixed a bug in :meth:`iris.experimental.um.FieldsFileVariant.close`, + which now correctly allocates extra blocks for larger lookups when saving. + Previously, when larger files open for update were closed, they could be written out with data overlapping the lookup table. +* Fixed a bug in :class:`iris.aux_factory.OceanSigmaZFactory` + which sometimes caused crashes when fetching the points of an "ocean sigma z" coordinate. + +Version 1.9.1 +------------- +* Fixed a unicode bug preventing standard names from being built cleanly when installing in Python3 + +Version 1.9.2 +------------- +* New warning regarding data loss if writing to an open file which is also open to read, with lazy data. +* Removal of a warning about data payload loading from concatenate. +* Updates to concatenate documentation. +* Fixed a bug with a name change in the netcdf4-python package. +* Fixed a bug building the documentation examples. +* Fixed a bug avoiding sorting classes directly when :meth:`iris.cube.Cube.coord_system` is used in Python3. +* Fixed a bug regarding unsuccessful dot import. + +Incompatible Changes +==================== +* GRIB message/file reading and writing may not be available for Python 3 due to GRIB API limitations. + +Deprecations +============ +* Deprecated :mod:`iris.unit`, with unit functionality provided by `cf_units `_ instead. +* When loading from NetCDF, a deprecation warning is emitted if there is vertical coordinate information + that *would* produce extra result cubes if :data:`iris.FUTURE.netcdf_promote` were set, + but it is *not* set. +* Deprecated :class:`iris.aux_factory.LazyArray` + +Documentation Changes +===================== +* A chapter on :doc:`saving iris cubes ` has been + added to the :doc:`user guide `. +* Added script and documentation for building a what's new page from developer-submitted contributions. + See :doc:`Contributing a "What's New" entry `. diff --git a/docs/iris/src/whatsnew/2.0.rst b/docs/iris/src/whatsnew/2.0.rst new file mode 100644 index 0000000000..43d60a8539 --- /dev/null +++ b/docs/iris/src/whatsnew/2.0.rst @@ -0,0 +1,303 @@ +What's New in Iris 2.0.0 +************************ + +:Release: 2.0.0rc1 +:Date: 2018-01-11 + + +This document explains the new/changed features of Iris in version 2.0.0 +(:doc:`View all changes `). + + +Iris 2.0.0 Features +=================== +.. _showcase: + +.. admonition:: Dask Integration + + The use of `Biggus`_ to provide support for *virtual arrays* and + *lazy evaluation* within Iris has been replaced with `Dask`_. + + In addition the concept of *lazy data*, already used for the + :class:`~iris.cube.Cube` data component, has now been extended to the + data arrays of a :class:`~iris.coords.Coord` and an + :class:`~iris.aux_factory.AuxCoordFactory`. + + This is a major feature enhancement, allowing Iris to leverage dask's rich + functionality and community knowledge. + + In particular, Dask's *threaded*, *multiprocessing* or *distributed* + `schedulers`_ can be used in order to best utilise available compute and + memory resource. For further details, see :doc:`Real and Lazy Data + `. + +* Changes to the :class:`iris.cube.Cube`: + + * The *new* :meth:`~iris.cube.Cube.core_data` method returns the *real* or + *lazy* :class:`~iris.cube.Cube` :data:`data`. + + * The *new* in-place arithmetic operators :data:`__iadd__`, :data:`__idiv__`, + :data:`__imul__`, :data:`__isub__`, and :data:`__itruediv__` have been + added to support :class:`~iris.cube.Cube` operations :data:`+=`, + :data:`/=`, :data:`*=`, and :data:`-=`. Note that, for **divison** + *__future__.division* is always in effect. + +* Changes to the :class:`iris.coords.Coord`: + + * The *new* :attr:`~iris.coords.Coord.bounds_dtype` property (read-only) + provides the :data:`dtype` of the coordinate bounds, if they exist. + + * The *new* :meth:`~iris.coords.Coord.core_points` and + :meth:`~iris.coords.Coord.core_bounds` methods return the *real* or *lazy* + :class:`~iris.coords.Coord` :data:`points` and :data:`bounds` data, + respectively. + + * The *new* :meth:`~iris.coords.Coord.has_lazy_points` and + :meth:`~iris.coords.Coord.has_lazy_bounds` boolean methods return whether + the coordinate has *lazy* :data:`points` and *lazy* :data:`bounds` data, + respectively. + + * The *new* :meth:`~iris.coords.Coord.lazy_points` and + :meth:`~iris.coords.Coord.lazy_bounds` methods return *lazy* + representations of the coordinate :data:`points` and :data:`bounds` data, + respectively. + + +The :data:`iris.FUTURE` has arrived! +------------------------------------ + +Throughout version 1 of Iris a set of toggles in +:attr:`iris.FUTURE` were maintained. These toggles allowed certain "future" +behaviour to be enabled. Since the future has now arrived in Iris 2, +all existing toggles in :attr:`iris.FUTURE` now default to :data:`True`. + + * :attr:`iris.Future.cell_datetime_objects` + + * Use of this FUTURE toggle is now deprecated. + * :class:`iris.coords.Cell` objects in time coordinates now contain datetime objects by default and not numbers. + For example:: + + >>> cube = iris.load_cube(iris.sample_data_path('air_temp.pp')) + >>> print(cube.coord('time').cell(0).point) + 1998-12-01 00:00:00 + + This change particularly impacts constraining datasets on time. All time constraints + must now be constructed with datetime objects or :class:`~iris.time.PartialDateTime` objects. + See userguide section 2.2.1 for more details on producing time constraints. + + + * :attr:`iris.Future.netcdf_promote` + + * Use of this FUTURE toggle is now deprecated. + * Removed deprecated behaviour that does not automatically promote NetCDF variables to cubes. + This change means that NetCDF variables that define reference surfaces for + dimensionless vertical coordinates will always be promoted and loaded as + independent cubes. + + * :attr:`iris.Future.netcdf_no_unlimited` + + * Use of this FUTURE toggle is now deprecated. + * Removed deprecated behaviour that automatically set the length of the outer + netCDF variable to 'UNLIMITED' on save. This change means that no cube + dimension coordinates will be automatically saved as netCDF variables with + 'UNLIMITED' length. + * You can manually specify cube dimension coordinates to save with 'UNLIMITED' + length. For example:: + + >>> iris.save(my_cube, 'my_result_file.nc', unlimited_dimensions=['latitude']) + + * :attr:`iris.Future.clip_latitudes` + + * Use of this FUTURE toggle is now deprecated. + * The :meth:`iris.coords.Coord.guess_bounds()` now limits the guessed bounds + to [-90, 90] for latitudes by default. The ability to turn this behaviour + off is now deprecated. + + +Bugs Fixed +========== + +* Indexing or slicing an :class:`~iris.coords.AuxCoord` coordinate will return a coordinate with + :data:`points` and :data:`bounds` data that are new copied arrays, rather than views onto those of + the original parent coordinate. + +* Indexing or slicing a cell measure will return a new cell measure with + :data:`data` that is a new copied array, rather than a view onto the original parent cell measure. + +* Performing an in-place arithmetic :func:`~iris.analysis.maths.add`, + :func:`~iris.analysis.maths.divide`, :func:`~iris.analysis.maths.multiply`, + or :func:`~iris.analysis.maths.subtract` operation on a + :class:`~iris.cube.Cube` with :data:`integer` or :data:`boolean` data with + a :data:`float` result will raise an :data:`ArithmeticError` exception. + +* Lazy data now refers to absolute paths rather than preserving the form that + was passed to iris.load functions. This means that it is possible to use + relative paths at load, change working directory, and still expect to be able + to load any un-loaded/lazy data. (#2325) + +* The order in which files are passed to iris.load functions is now the order in + which they are processed. (#2325) + +* Loading from netCDF files with :func:`iris.load` will load a cube for each scalar variable, + a variable that does not reference a netCDF dimension, unless that scalar variable is identified as + a CF scalar coordinate, referenced from another data variable via the 'coordinates' attribute. + Previously such data variables were ignored during load. + + +Incompatible Changes +==================== + +* The :meth:`~iris.cube.Cube.lazy_data` method no longer accepts any arguments. + Setting lazy data should now be done with :attr:`cube.data + `. + +.. admonition:: Significant Changes in Calculated Results + + Due to the replacement of `Biggus`_ with `Dask`_, as described above, the results + of certain types of calculation may have significantly different values from + those obtained in earlier versions. + This is of a much greater order than the usual small changes in floating + point results : it applies especially to any data with masked points, or of + long integer types. + +* Due to concerns regarding maintainability and API consistency the + :attr:`iris.cube.Cube.share_data` flag introduced in v1.13 has been removed. + Intra-cube data sharing is a oft-requested feature that we will be targeting + in a future Iris release. + +* Using :meth:`~iris.cube.Cube.convert_units` on a cube with unknown units will + now result in a :data:`UnitConversionError` being raised. + +* ``iris.fileformats.pp_rules`` has been renamed to + :mod:`iris.fileformats.pp_load_rules` for consistency with the new + :mod:`iris.fileformats.pp_save_rules`. + +* Fill values are no longer taken from the cube's `data` attribute when it is + a masked array. + +* When saving a cube or list of cubes in NetCDF format, a fill value or list of + fill values can be specified via a new `fill_value` argument. If a list is + supplied, each fill value will be applied to each cube in turn. If a + `fill_value` argument is not specified, the default fill value for the file + format and the cube's data type will be used. + +* When saving to PP, the "standard" BMDI of -1e30 is now always applied in + ``PPField`` generation. To save PP data with an alternative BMDI, use + :func:`iris.fileformats.pp.save_pairs_from_cube` to generate ``PPFields``, + and modify these before saving them to file. + +* A 'fill_value' key can no longer be specified as part of the `packing` + argument to `iris.save` when saving in netCDF format. Instead, a fill value or + list of fill values should be specified as a separate `fill_value` argument if + required. + +* If the `packing` argument to `iris.save` is a dictionary, an error is raised + if it contains any keys other than 'dtype', 'scale_factor' and 'add_offset'. + +* The deprecated :mod:`iris.fileformats.grib` was removed. All Iris GRIB + functionality is now delivered through :mod:`iris-grib`. + +* In Iris v1 it was possible to configure Iris to log at import time through + `iris.config.LOGGING`. This capability has been removed in Iris v2. + +* When coordinates have no well defined plot axis, :mod:`iris.plot` and + :mod:`iris.quickplot` routines now use the order of the cube's dimensions + to determine the coordinates to plot as the x and y axis of a plot. + +* The cf_units dependency version has been updated to v1.2.0, which prints + shorter unit strings. For example, the unit ``meter-second^-1`` is now + printed as ``m.s-1``. + + +Deprecation removals +-------------------- + +All deprecated functionality that was announced for removal in Iris 2.0 has +been removed. In particular: + +* The deprecated keyword arguments ``coord`` and ``name`` have been removed from + the :class:`iris.cube.Cube` constructor. + +* The deprecated methods ``iris.cube.Cube.add_history``, + ``iris.cube.Cube.assert_valid`` and ``iris.cube.Cube.regridded`` have + been removed from :class:`iris.cube.Cube`. + +* The deprecated module ``iris.fileformats.pp_packing`` has been removed. + +* The deprecated module ``iris.proxy`` has been removed. + +* The deprecated configuration variable ``SAMPLE_DATA_DIR`` has been removed + from ``iris.config`` in favour of user installation of + the ``iris-sample-data`` package. + +* The deprecated module ``iris.unit`` has been removed in favour of + :mod:`cf_units`. + +* The ``BitwiseInt`` class has been removed from :mod:`iris.fileformats.pp`. + +* Removed deprecated functions ``reset_load_rules``, ``add_save_rules``, + ``reset_save_rules`` and ``as_pairs`` from :mod:`iris.fileformats.pp`. + +* The deprecated module ``iris.analysis.interpolate`` has been removed, along + with the following deprecated classes and functions: + + * ``iris.analysis.interpolate.linear`` + * ``iris.analysis.interpolate.nearest_neighbour_data_value`` + * ``iris.analysis.interpolate.regrid`` + * ``iris.analysis.interpolate.regrid_to_max_resolution`` + * ``iris.analysis.interpolate.extract_nearest_neighbour`` + * ``iris.analysis.interpolate.nearest_neighbour_indices`` + * ``iris.analysis.interpolate.Linear1dExtrapolator`` + +* Removed deprecated module ``iris.experimental.fieldsfile``. + Note that there is no direct replacement for + ``:meth:iris.experimental.fieldsfile.load``, which specifically performed + fast loading from _either_ PP or FF files. + Instead, please use the `:meth:iris.fileformats.um.structured_um_loading` + context manager, and within that context call `:meth:iris.load`, or the format-specific + `:meth:iris.fileformats.pp.load_cubes` or + `:meth:iris.fileformats.um.load_cubes`. + +* Removed deprecated module ``iris.fileformats.ff``. + Please use facilities in :mod:`iris.fileformats.um` instead. + +* Removed deprecated and unused kwarg ``ignore`` from the following functions: + * :func:`iris.analysis.calculus.curl`, + * :func:`iris.analysis.maths.add`, and + * :func:`iris.analysis.maths.subtract`. + +* Deprecated functions ``iris.util.broadcast_weights``, + ``iris.util.ensure_array`` and ``iris.util.timers`` have been removed from + :mod:`iris.util`. + +* The following classes and functions have been removed from + :mod:`iris.fileformats.rules`: + + * ``iris.fileformat.rules.calculate_forecast_period`` + * ``iris.fileformat.rules.log`` + * ``iris.fileformat.rules.CMAttribute`` + * ``iris.fileformat.rules.CMCustomAttribute`` + * ``iris.fileformat.rules.CoordAndDims`` + * ``iris.fileformat.rules.DebugString`` + * ``iris.fileformat.rules.FunctionRule`` + * ``iris.fileformat.rules.ProcedureRule`` + * ``iris.fileformat.rules.Rule`` + * ``iris.fileformat.rules.RulesContainer`` + * ``iris.fileformat.rules.RuleResult`` + +* In addition the deprecated keyword argument ``legacy_custom_rules`` has been + removed from the :class:`iris.fileformats.rules.Loader` constructor. + + +Documentation Changes +===================== + +* A new UserGuide chapter on :doc:`Real and Lazy Data + ` has been added, and referenced from key + points in the :doc:`User Guide ` . + + +.. _Biggus: https://biggus.readthedocs.io/en/latest/ +.. _Dask: http://dask.pydata.org/en/latest/ +.. _iris_grib: https://github.com/SciTools/iris-grib/ +.. _schedulers: http://dask.pydata.org/en/latest/scheduler-overview.html diff --git a/docs/iris/src/whatsnew/2.1.rst b/docs/iris/src/whatsnew/2.1.rst new file mode 100644 index 0000000000..00f7115431 --- /dev/null +++ b/docs/iris/src/whatsnew/2.1.rst @@ -0,0 +1,83 @@ +What's New in Iris 2.1 +********************** + +:Release: 2.1 +:Date: 2018-06-06 + +This document explains the new/changed features of Iris in version 2.1 +(:doc:`older "What's New" release notes can be found here`.) + + +Iris 2.1 Dependency updates +=========================== + +* The `cf_units `_ dependency + was updated to cf_units ``v2.0``. + cf_units v2 is almost entirely backwards compatible with v1. + However the ability to preserve some aliased calendars has been removed. + For this reason, it is possible that NetCDF load of a variable with a + "standard" calendar will result in a saved NetCDF of a "gregorian" + calendar. +* Iris updated its time-handling functionality from the + `netcdf4-python `_ + ``netcdftime`` implementation to the standalone module + `cftime `_. + cftime is entirely compatible with netcdftime, but some issues may + occur where users are constructing their own datetime objects. + In this situation, simply replacing ``netcdftime.datetime`` with + ``cftime.datetime`` should be sufficient. +* Iris now requires version 2 of Matplotlib, and ``>=1.14`` of NumPy. + Full requirements can be seen in the `requirements `_ + directory of the Iris' the source. + +Iris 2.1 Features +================= + +* Added ``repr_html`` functionality to the :class:`~iris.cube.Cube` to provide + a rich html representation of cubes in Jupyter notebooks. Existing functionality + of ``print(cube)`` is maintained. + + .. image:: images/notebook_repr.png + +* Updated :func:`iris.cube.Cube.name` to return a STASH code if the cube has + one and no other valid names are present. This is now consistent with the + summary information from :func:`iris.cube.Cube.summary`. +* The partial collapse of multi-dimensional auxiliary coordinates is now + supported. Collapsed bounds span the range of the collapsed dimension(s). +* Added new function :func:`iris.cube.CubeList.realise_data` to compute + multiple lazy values in a single operation, avoiding repeated re-loading of + data or re-calculation of expressions. +* The methods :meth:`iris.cube.Cube.convert_units` and + :meth:`iris.coords.Coord.convert_units` no longer forcibly realise the cube + data or coordinate points/bounds. The converted values are now lazy arrays + if the originals were. +* Added :meth:`iris.analysis.trajectory.interpolate` that allows you to + interpolate to find values along a trajectory. +* It is now possible to add an attribute of ``missing_value`` to a cube + (:issue:`1588`). +* Iris can now represent data on the Albers Equal Area Projection, + and the NetCDF loader and saver were updated to handle this. (:issue:`2943`) +* The :class:`~iris.coord_systems.Mercator` projection has been updated to accept + the ``standard_parallel`` keyword argument (:pull:`3041`). + +Bugs Fixed +========== + +* All var names being written to NetCDF are now CF compliant. + Non alpha-numeric characters are replaced with '_', and var names now always + have a leading letter (:pull:`2930`). +* A cube resulting from a regrid operation using the `iris.analysis.AreaWeighted` + regridding scheme will now have the smallest floating point data type + to which the source cube's data type can be safely converted using NumPy's + type promotion rules. +* :mod:`iris.quickplot` labels now honour the axes being drawn to when using the + ``axes`` keyword (:pull:`3010`). + +Incompatible Changes +==================== +* The deprecated :mod:`iris.experimental.um` was removed. + Please use consider using `mule `_ + as an alternative. +* This release of Iris contains a number of updated metadata translations. + See [this changelist](https://github.com/SciTools/iris/commit/69597eb3d8501ff16ee3d56aef1f7b8f1c2bb316#diff-1680206bdc5cfaa83e14428f5ba0f848) + for further information. diff --git a/docs/iris/src/whatsnew/2.2.rst b/docs/iris/src/whatsnew/2.2.rst new file mode 100644 index 0000000000..f38bfa1bc3 --- /dev/null +++ b/docs/iris/src/whatsnew/2.2.rst @@ -0,0 +1,104 @@ +What's New in Iris 2.2 +************************ + +:Release: 2.2.0 +:Date: + + +This document explains the new/changed features of Iris in the release +of version 2.2 +(:doc:`View all changes `). + + +Iris 2.2 Features +=================== +.. _showcase: + +.. admonition:: 2-Dimensional Coordinate Plotting + + The Iris plot functions :func:`~iris.plot.pcolor` and + :func:`~iris.plot.pcolormesh` now accommodate the plotting of 2-dimensional + coordinates as well as 1-dimensional coordinates. + + To enable this feature, each coordinate passed in for plotting will be + automatically checked for contiguity. Coordinate bounds must either be + contiguous, or the cube's data must be masked at the discontiguities in + order to avoid plotting errors. + + The Iris plot function :func:`iris.plot.quiver` has been added, and this + also works with 2-dimensional plot coordinates. + +.. admonition:: 2-Dimensional Grid Vectors + + The Iris functions :func:`iris.analysis.cartography.gridcell_angles` and + :func:`iris.analysis.cartography.rotate_grid_vectors` have been added, + allowing you to convert gridcell-oriented vectors to true-North/East ones. + +.. admonition:: NetCDF Data Variable Chunk Sizes + + NetCDF data variable chunk sizes are now utilised at load time for + significant performance improvements. + +* The :class:`iris.fileformats.um.FieldCollation` objects, which are passed + into load callbacks when using + :func:`iris.fileformats.um.structured_um_loading`, now + have the additional properties: + :data:`iris.fileformats.um.FieldCollation.data_filepath` and + :data:`iris.fileformats.um.FieldCollation.data_field_indices`. + These provide the file locations of the original data fields, which are + otherwise lost in the structured loading process. + +* :func:`iris.util.reverse` can now be used to reverse a cube by specifying + one or more coordinates. + +* Time mean fields can now be saved to PP files as a cell method. + +* Cube aggregators :func:`iris.analysis.MIN`, :func:`iris.analysis.MAX`, + :func:`iris.analysis.SUM` and :func:`iris.analysis.COUNT` now perform lazy + aggregation by utilizing dask. + +* Error messages thrown upon failed addition of an + :class:`~iris.aux_factory.AuxCoordFactory` now include the name of the + required (but absent) coordinate as well as the name of the cube. + +* The function :func:`iris.util.find_discontiguities` can be used to check for + discontiguities in the bounds arrays of cube coordinates. Additionally, + discontiguous points in coordinates can be explicitly masked + using another new feature :func:`iris.util.mask_cube`. + + +Iris 2.2 Dependency updates +============================= + +* Iris is now using the latest version release of dask (currently 0.19.3) + +* Proj4 has been temporarily pinned to version < 5 while problems with the + Mollweide projection are addressed. + +* Matplotlib has been pinned to version < 3 temporarily while we account for + its changes in all SciTools libraries. + + +Bugs Fixed +========== + +* The bug has been fixed that prevented printing time coordinates with bounds + when the time coordinate was measured on a long interval (that is, ``months`` + or ``years``). + +* "Gracefully filling..." warnings are now only issued when the coordinate or + bound data is actually masked. + +* Iris can now correctly unpack a column of header objects when saving a + pandas DataFrame to a cube. + + +Documentation Changes +===================== + +* Iris' `INSTALL` document has been updated to include guidance for running + tests. + +* A link has been added to the Developers' Guide to make it easier to find the + Pull Request Check List. + diff --git a/docs/iris/src/whatsnew/aggregate_directory.py b/docs/iris/src/whatsnew/aggregate_directory.py new file mode 100644 index 0000000000..88290907ef --- /dev/null +++ b/docs/iris/src/whatsnew/aggregate_directory.py @@ -0,0 +1,307 @@ +# (C) British Crown Copyright 2015 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Build a release file from files in a contributions directory. + +Looks for directories "<...whatsnew>/contributions_". +Takes specified "xx.xx" as version, or latest found (alphabetic). +Writes a file "<...whatsnew>/.rst". + +Valid contributions filenames are of the form: + __summary.txt +Where can be any valid chars, and + is one of : + "newfeature" "bugfix" "incompatiblechange" "deprecate" "docchange", and + is in the style "2001-Jan-23". + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import datetime +from glob import glob +import os +import re +import argparse +import warnings +from operator import itemgetter +from distutils import version + +# Regular expressions: CONTRIBUTION_REGEX matches the filenames of +# contribution snippets. It is split into three sections separated by _ +# 0. String for the category. 1. ISO8601 date. 2. String for the feature name. +# RELEASE_REGEX matches the directory names, returning the release. +CONTRIBUTION_REGEX_STRING = r'(?P.*)' +CONTRIBUTION_REGEX_STRING += r'_(?P\d{4}-\w{3}-\d{2})' +CONTRIBUTION_REGEX_STRING += r'_(?P.*)\.txt$' +CONTRIBUTION_REGEX = re.compile(CONTRIBUTION_REGEX_STRING) +RELEASEDIR_PREFIX = r'contributions_' +_RELEASEDIR_REGEX_STRING = RELEASEDIR_PREFIX + r'(?P.*)$' +RELEASE_REGEX = re.compile(_RELEASEDIR_REGEX_STRING) +SOFTWARE_NAME = 'Iris' +EXTENSION = '.rst' +VALID_CATEGORIES = [ + {'Prefix': 'newfeature', 'Title': 'Features'}, + {'Prefix': 'bugfix', 'Title': 'Bugs Fixed'}, + {'Prefix': 'incompatiblechange', 'Title': 'Incompatible Changes'}, + {'Prefix': 'deprecate', 'Title': 'Deprecations'}, + {'Prefix': 'docchange', 'Title': 'Documentation Changes'} +] +VALID_CATEGORY_PREFIXES = [cat['Prefix'] for cat in VALID_CATEGORIES] + + +def _self_root_directory(): + return os.path.abspath(os.path.dirname(__file__)) + + +def _decode_contribution_filename(file_name): + file_name_elements = CONTRIBUTION_REGEX.match(file_name) + category = file_name_elements.group('category') + if category not in VALID_CATEGORY_PREFIXES: + # This is an error + raise ValueError('Unknown category in contribution filename.') + isodate = file_name_elements.group('isodate') + date_of_item = datetime.datetime.strptime(isodate, '%Y-%b-%d').date() + return category, isodate, date_of_item + + +def is_release_directory(directory_name, release): + '''Returns True if a given directory name matches the requested release.''' + result = False + directory_elements = RELEASE_REGEX.match(directory_name) + try: + release_string = directory_elements.group('release') + directory_release = version.StrictVersion(release_string) + except (AttributeError, ValueError): + pass + else: + if directory_release == release: + result = True + return result + + +def is_compiled_release(root_directory, release): + '''Returns True if the requested release.rst file exists.''' + result = False + compiled_filename = '{!s}{}'.format(release, EXTENSION) + compiled_filepath = os.path.join(root_directory, compiled_filename) + if os.path.exists(compiled_filepath) and os.path.isfile(compiled_filepath): + result = True + return result + + +def get_latest_release(root_directory=None): + """ + Implement default=latest release identification. + + Returns a valid release code. + + """ + if root_directory is None: + root_directory = _self_root_directory() + directory_contents = os.listdir(root_directory) + # Default release to latest visible dir. + possible_release_dirs = [releasedir_name + for releasedir_name in directory_contents + if RELEASE_REGEX.match(releasedir_name)] + if len(possible_release_dirs) == 0: + dirspec = os.path.join(root_directory, RELEASEDIR_PREFIX + '*') + msg = 'No valid release directories found, i.e. {!r}.' + raise ValueError(msg.format(dirspec)) + release_dirname = sorted(possible_release_dirs)[-1] + release = RELEASE_REGEX.match(release_dirname).group('release') + return release + + +def find_release_directory(root_directory, release=None, + fail_on_existing=True): + ''' + Returns the matching contribution directory or raises an exception. + + Defaults to latest-found release (from release directory names). + Optionally, fail if the matching release file already exists. + *Always* fail if no release directory exists. + + ''' + if release is None: + # Default to latest release. + release = get_latest_release(root_directory) + + if fail_on_existing: + compiled_release = is_compiled_release(root_directory, release) + if compiled_release: + msg = ('Specified release {!r} is already compiled : ' + '{!r} already exists.') + compiled_filename = str(release) + EXTENSION + raise ValueError(msg.format(release, compiled_filename)) + + directory_contents = os.listdir(root_directory) + result = None + for inode in directory_contents: + node_path = os.path.join(root_directory, inode) + if os.path.isdir(node_path): + release_directory = is_release_directory(inode, release) + if release_directory: + result = os.path.join(root_directory, inode) + break + if not result: + msg = 'Contribution folder for release {!s} does not exist : no {!r}.' + release_dirname = RELEASEDIR_PREFIX + str(release) + '/' + release_dirpath = os.path.join(root_directory, release_dirname) + raise ValueError(msg.format(release, release_dirpath)) + return result + + +def generate_header(release): + '''Return a list of text lines that make up a header for the document.''' + header_text = [] + title_template = 'What\'s New in {} {!s}\n' + title_line = title_template.format(SOFTWARE_NAME, release) + title_underline = ('*' * (len(title_line) - 1)) + '\n' + isodatestamp = datetime.date.today().strftime('%Y-%m-%d') + header_text.append(title_line) + header_text.append(title_underline) + header_text.append('\n') + header_text.append(':Release: {!s}\n'.format(release)) + header_text.append(':Date: {}\n'.format(isodatestamp)) + header_text.append('\n') + description_template = 'This document explains the new/changed features '\ + 'of {} in version {!s}\n' + header_text.append(description_template.format(SOFTWARE_NAME, release)) + header_text.append('(:doc:`View all changes `.)') + header_text.append('\n') + return header_text + + +def read_directory(directory_path): + '''Parse the items in a specified directory and return their metadata.''' + directory_contents = os.listdir(directory_path) + compilable_files_unsorted = [] + misnamed_files = [] + for file_name in directory_contents: + try: + category, isodate, date_of_item = \ + _decode_contribution_filename(file_name) + except (AttributeError, ValueError): + misnamed_files.append(file_name) + continue + compilable_files_unsorted.append({'Category': category, + 'Date': date_of_item, + 'FileName': file_name}) + compilable_files = sorted(compilable_files_unsorted, + key=itemgetter('Date'), + reverse=True) + if misnamed_files: + msg = 'Found contribution file(s) with unexpected names :' + for filename in misnamed_files: + full_path = os.path.join(directory_path, filename) + msg += '\n {}'.format(full_path) + warnings.warn(msg, UserWarning) + + return compilable_files + + +def compile_directory(directory, release): + '''Read in source files in date order and compile the text into a list.''' + source_text = read_directory(directory) + compiled_text = [] + header_text = generate_header(release) + compiled_text.extend(header_text) + for count, category in enumerate(VALID_CATEGORIES): + category_text = [] + subtitle_line = '' + if count == 0: + subtitle_line += '{} {!s} '.format(SOFTWARE_NAME, release) + subtitle_line += category['Title'] + '\n' + subtitle_underline = ('=' * (len(subtitle_line) - 1)) + '\n' + category_text.append('\n') + category_text.append(subtitle_line) + category_text.append(subtitle_underline) + category_items = [item for item in source_text + if item['Category'] == category['Prefix']] + if not category_items: + continue + for file_description in category_items: + entry_path = os.path.join(directory, file_description['FileName']) + with open(entry_path, 'r') as content_object: + text = content_object.readlines() + if not text[-1].endswith('\n'): + text[-1] += '\n' + category_text.extend(text) + compiled_text.extend(category_text) + return compiled_text + + +def check_all_contributions_valid(release=None, quiet=False): + """"Scan the contributions directory for badly-named files.""" + root_directory = _self_root_directory() + # Check there are *some* contributions directory(s), else silently pass. + contribs_spec = os.path.join(root_directory, RELEASEDIR_PREFIX + '*') + if len(glob(contribs_spec)) > 0: + # There are some contributions directories: check latest / specified. + if release is None: + release = get_latest_release() + if not quiet: + msg = 'Checking whatsnew contributions for release "{!s}".' + print(msg.format(release)) + release_directory = find_release_directory(root_directory, release, + fail_on_existing=False) + # Run the directory scan, but convert any warning into an error. + with warnings.catch_warnings(): + warnings.simplefilter('error') + compile_directory(release_directory, release) + if not quiet: + print('done.') + + +def run_compilation(release=None, quiet=False): + '''Write a draft release.rst file given a specified uncompiled release.''' + if release is None: + # This must exist ! + release = get_latest_release() + if not quiet: + msg = 'Building release document for release "{!s}".' + print(msg.format(release)) + root_directory = _self_root_directory() + release_directory = find_release_directory(root_directory, release) + compiled_text = compile_directory(release_directory, release) + compiled_filename = str(release) + EXTENSION + compiled_filepath = os.path.join(root_directory, compiled_filename) + with open(compiled_filepath, 'w') as output_object: + for string_line in compiled_text: + output_object.write(string_line) + if not quiet: + print('done.') + + +if __name__ == '__main__': + PARSER = argparse.ArgumentParser() + PARSER.add_argument("release", help="Release number to be compiled", + nargs='?', type=version.StrictVersion) + PARSER.add_argument( + '-c', '--checkonly', action='store_true', + help="Check contribution file names, do not build.") + PARSER.add_argument( + '-q', '--quiet', action='store_true', + help="Do not print progress messages.") + ARGUMENTS = PARSER.parse_args() + release = ARGUMENTS.release + quiet = ARGUMENTS.quiet + if ARGUMENTS.checkonly: + check_all_contributions_valid(release, quiet=quiet) + else: + run_compilation(release, quiet=quiet) diff --git a/docs/iris/src/whatsnew/images/notebook_repr.png b/docs/iris/src/whatsnew/images/notebook_repr.png new file mode 100644 index 0000000000..0792903986 Binary files /dev/null and b/docs/iris/src/whatsnew/images/notebook_repr.png differ diff --git a/docs/iris/src/whatsnew/pics/transverse_merc.png b/docs/iris/src/whatsnew/images/transverse_merc.png similarity index 100% rename from docs/iris/src/whatsnew/pics/transverse_merc.png rename to docs/iris/src/whatsnew/images/transverse_merc.png diff --git a/docs/iris/src/whatsnew/index.rst b/docs/iris/src/whatsnew/index.rst index 37ac7ebec0..c3a34303f0 100644 --- a/docs/iris/src/whatsnew/index.rst +++ b/docs/iris/src/whatsnew/index.rst @@ -1,13 +1,28 @@ +.. _iris_whatsnew: + What's new in Iris ****************** These "What's new" pages describe the important changes between major Iris versions. -* :doc:`What's new in Iris 1.6 <1.6>` -* :doc:`What's new in Iris 1.5 <1.5>` -* :doc:`What's new in Iris 1.4 <1.4>` -* :doc:`What's new in Iris 1.3 <1.3>` -* :doc:`What's new in Iris 1.2 <1.2>` -* :doc:`What's new in Iris 1.1 <1.1>` -* :doc:`What's new in Iris 1.0 <1.0>` +.. toctree:: + :maxdepth: 2 + + 2.2.rst + 2.1.rst + 2.0.rst + 1.13.rst + 1.12.rst + 1.11.rst + 1.10.rst + 1.9.rst + 1.8.rst + 1.7.rst + 1.6.rst + 1.5.rst + 1.4.rst + 1.3.rst + 1.2.rst + 1.1.rst + 1.0.rst diff --git a/docs/iris/src/whitepapers/change_management.rst b/docs/iris/src/whitepapers/change_management.rst new file mode 100644 index 0000000000..b279c91b96 --- /dev/null +++ b/docs/iris/src/whitepapers/change_management.rst @@ -0,0 +1,451 @@ +.. _change_management: + +Change Management in Iris from the User's perspective +***************************************************** + +As Iris changes, user code will need revising from time to time to keep it +working, or to maintain best practice. At the very least, you are advised to +review existing code to ensure it functions correctly with new releases. + +Here, we define ways to make this as easy as possible. + +.. include:: ../userguide/change_management_goals.txt + + +Key principles you can rely on +============================== + +Iris code editions are published as defined version releases, with a given +major and minor version number in the version name, "major.minor.xxx", +as explained in the :ref:`releases section ` below. + + * Code that currently works should **still work**, and have the same + results and effects, in any subsequent sub-release with the same major + release number. + + * The only time we will make changes that can break existing code is at + a **major release**. + + * At a major release, code that works **and emits no deprecation warnings** + in the latest previous (minor) release should still work, and have the + same results and effects. + + +**What can possibly go wrong ?** + +If your code produces :ref:`deprecation warnings `, then it +*could* behave differently, or fail, at the next major release. + + + +User Actions : How you should respond to changes and releases +============================================================= + +Checklist : + +* when a new **testing or candidate version** is announced + if convenient, test your working legacy code against it and report any problems. + +* when a new **minor version is released** + + * review the 'Whats New' documentation to see if it introduces any + deprecations that may affect you. + * run your working legacy code and check for any deprecation warnings, + indicating that modifications may be necessary at some point + * when convenient : + + * review existing code for use of deprecated features + * rewrite code to replace deprecated features + +* when a new major version is **announced** + ensure your code runs, without producing deprecation warnings, in the + previous minor release + +* when a new major version is **released** + check for new deprecation warnings, as for a minor release + + +Details +======= + +The Iris change process aims to minimise the negative effects of change, by +providing : + + * defined processes for release and change management + * release versioning + * backwards code compatibility through minor version releases + * a way to ensure compatibility with a new major version release + * deprecation notices and warnings to highlight all impending changes + +Our practices are intended be compatible with the principles defined in the +`SemVer project `_ . + +Key concepts covered here: + * :ref:`Release versions ` + * :ref:`Backwards compatibility ` + * :ref:`Deprecation ` + + +.. _iris_backward_compatibility: + +Backwards compatibility +----------------------- + +"Backwards-compatible" changes are those that leave any existing valid API +usages unchanged (see :ref:`terminology ` below). +Minor releases may only include backwards-compatible changes. + +The following are examples of backward-compatible changes : + + * changes to documentation + * adding to a module : new submodules, functions, classes or properties + * adding to a class : new methods or properties + * adding to a function or method : new **optional** arguments or keywords + +The following are examples of **non-** backward-compatible changes : + + * removing (which includes *renaming*) any public module or submodule + * removing any public component : a module, class, method, function or + data object property of a public API component + * removing any property of a public object + * removing an argument or keyword from a method or function + * adding a required argument to a method or function + * removing a keyword (even one that has no effect) + * changing the effect of *any* particular combination of arguments and/or + keywords + +Note that it is also possible to modify the behaviour of an existing usage by +making it depend on a newly-defined external control variable. This is +effectively a change to the 'default behaviour' of a specific usage. Although +this seems similar to adding a keyword, the cases where the new behaviour +operates and where it does not are not distinguishable by a different code +usage, which makes this somewhat dangerous. We do use this type of change, +but any behaviour 'mode' controls of this sort are usually added as part of the +:class:`iris.Future` definition. +See :ref:`Usage of iris.FUTURE `, below. + + +.. _iris_api: + +Terminology : API, features, usages and behaviours +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The API is the components of the iris module and its submodules which are +"public" : In Python, by convention, this normally means everything whose name +does not have a single leading underscore "_". +This applies to all public modules and their properties : submodules, contained +public classes, data and properties, functions and methods. +An exception is when a module or class defines an '__all__' property : In +that case, the public aspects are just the ones listed there. + +Note: these are standard Python conventions, not specific to Iris. +See: `PEP8 `_. + +The Iris project considers all public API features as "supported", which means +that we will not change or remove them without deprecation, and will undertake +to fix any bugs discovered. +We do however make an important exception for the content of the 'experimental' +module : APIs in :mod:`iris.experimental` module are published for initial +evaluation and feedback, and can be revised or removed without warning at a +subsequent release. + +A "feature" of the API includes public objects as above, but may also be used +more loosely to indicate a class or mode of behaviour, for example when a +keyword has a specific value, like "interpolate(mode='linear')". + +A "usage" is any code referring to public API elements, for example : + + * `print(iris.thing)` + * `iris.submodule.call(arg1)` + * `iris.module.call(arg1, arg2, *more_args)` + * `iris.module.call(arg1, arg2, control=3)` + * `x = iris.module.class(arg, key=4)` + +A "behaviour" is whatever Iris does when you invoke a particular API usage, +encompassing both returned values and any side effects such as code state +changes or data written to files. + +As the above code examples are all public feature usages, they should +therefore continue to work, with the same behaviours, at least until the next +**major** version release. + +.. Note:: + What is the "same" behaviour, for backwards-compatibility purposes ? + + Unfortunately, the guarantee to preserve "what Iris does" within a major + version cannot ensure *totally* identical and repeatable behaviour for any + possible usage, because this can also depend on the exact installed + versions of all dependencies (i.e. the other Python modules and system + libraries that Iris uses). + + See :ref:`iris_dependency_versions`. + + Minor-release code changes are backwards-compatible, meaning that they must + result in "the same" actions from Iris. + Ultimately, however, this is only a statement of intent, as we need freedom + to modify code with "no change" effects, yet *any* change to Iris code or + dependencies could alter total behaviour in some respects : + For instance, it could take more or less time or memory, produce results in + a different sequence, or perform a calculation slightly differently (with + possible small differences in floating point results). + + As behaviour can only be tested in specific ways on a specific + installation, so any given user installation may experience changes in + behaviour, though hopefully always slight, with a minor release change. + This applies to changes in the Iris minor release version, or a different + version of some dependency; or other changes to the operating system + environment. + + +.. _iris_change_releases: + +Releases and Versions +--------------------- + + +Iris releases have a unique identifying version string, in the form +"..", available to code as +:data:`iris.__version__` . + +This contains major and minor release numbers. The numbering and meaning of +these are defined, following the `SemVer project `_. + +The essential aspects of the ".." arrangement +are : + + * "", "" and "" are all integers, thus version + 2.12 is later than 2.2 (i.e. it is "two point twelve", not "two point one + two"). + + * "." denote the software release version. + + * A non-zero "" denotes a bugfix version, thus a release "X.Y.0" may + be followed by "X.Y.1", "X.Y.2" etc, which *only* differ by containing + bugfixes. Any bugfix release supercedes its predecessors, and does not + change any (valid) APIs or behaviour : hence, it is always advised to + replace a given version with its latest bugfix successor, and there + should be no reason not to. + + * "" is blank for formal releases. It used to indicate + provisional software for testing : The version string in a development + code branch is always labelled "-DEV", and release candidates for testing + during the release process are labelled "-rc1", "-rc2" etc. + For development code, the version number is that of the *next* release, + which this code version is progressing towards, e.g. "1.2-DEV" for all + code branches since the 1.1 release and intended for release in "1.2". + +.. note:: + Our use of "-" is typical, but does not follow strict SemVer + principles. + +The code for a specific release is identified by a git tag which is the version +string : see +:ref:`Developer's Guide section on releases `. + + +Major and Minor Releases +^^^^^^^^^^^^^^^^^^^^^^^^ + +The term "release" refers both to a specific state of the Iris code, which we +have assigned a given version string, *and* the act of defining it +(i.e. we "release a release"). + +According to `SemVer `_ principles, changes that alter the +behaviour of existing code can only be made at a **major** release, i.e. when +"X.0" is released following the last previous "(X-1).Y.Z". + +*Minor* releases, by contrast, consist of bugfixes, new features, and +deprecations : Any valid exisiting code should be unaffected by these, so it +will still run with the same results. + +At a major release, only **deprecated** behaviours and APIs can be changed or +removed. + + +.. _iris_deprecations: + +Deprecations +------------ + +A deprecation is issued when we decide that an *existing* feature needs to be +removed or modified : We add notices to the documentation, and issue a runtime +"Deprecation Warning" whenever the feature is used. + +For a wider perspective, see : ``_. +For the developer view of this, see +:ref:`Developer's Guide section on deprecations `. + +Deprecation manages incompatible changes in a strictly controlled way. +This allows APIs to evolve to the most effective form, even when that means +that existing code could behave differently or fail : This is important +because the freedom to remove features helps prevent the API becoming +progressively cluttered, and modifying existing behaviours allows us to use +the most natural code syntax for the most used features. + +We can only remove features or change behaviours at a major release. Thus, we +first deprecate the feature in a minor release, to provide adequate warning +that existing code may need to be modified. + +When we make a release that introduces a deprecation : + + * a deprecation notice appears in the + :ref:`What's New section ` + * deprecation notes are included in all relevant parts of the :ref:`reference + documentation ` + * a runtime warning is produced when the old feature is used or triggered + +In most cases, we also provide detailed advice in the documentation and/or +warning messages on how to replace existing usage with a 'new' way of doing +things. +In all cases, we must provide a transitional period where both old and new +features are available : + + * the 'old' style works as it did before + * any usage of the 'old' features will emit a + :class:`warnings.WarningMessage` message, noting that the feature is + deprecated and what to use instead + * the 'new' style can be adopted as soon as convenient + +This is to warn users : + + * not to use the deprecated features in any new code, *and* + * eventually to rewrite old code to use the newer or better alternatives + + +Deprecated features support through the Release cycle +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The whole point of a deprecation is that the feature continues to work, but +with a warning, for some time before an unavoidable change occurs. +When a version that introduces a deprecation is released, the effects are as +follows: + + * code that may be affected by the proposed change will result in + deprecation warnings + * code that currently works will, however, continue to work unchanged, at + least until the next major release + * you can avoid all deprecation warnings by suitable changes to your code + * code which uses no deprecated features, and thus produces no deprecation + warnings, will continue to work unchanged even at a **major** release + * code that generates deprecation warnings may cease to work at the next + **major** release. + + +.. _iris_future_usage: + +Future options, `iris.FUTURE` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A special approach is needed where the replacement behaviour is not controlled +by a distinct API usage. + +When we extend an API, or add a new feature, we usually add a new method or +keyword. In those cases, code using the new feature is clearly distinct from +any previous (valid) usage, so this is relatively simple to manage. +However, sometimes we really need to change the *way* an API works, without +modifying or extending (i.e. complicating) the existing user interface. +In that case, existing user code might sometimes have *different* behaviour +with the new release, which we obviously need to avoid. + +**For example :** + + We might decide there is a more useful way of loading cubes from files of a + particular input data format. + + * the user code usage is simply by calls to "iris.load" + * the change is not a bugfix, as the old way isn't actually "wrong" + * we don't want to add an extra keyword into all the relevant calls + * we don't see a longterm future for the existing behaviour : we + expect everyone to adopt the new interpretation, eventually + +For changes of this sort, the release will define a new boolean property of the +:data:`iris.FUTURE` object, as a control to select between the 'old' and 'new' +behaviours, with values False='old' and True='new'. +See :data:`iris.Future` for examples. + +In these cases, as any "deprecated usage" is not clearly distinguishable in the +form of the user code, it is **especially** important to take note of any +deprecation messages appearing when legacy code runs. + + +**Sequence of changes to `iris.FUTURE`** + +To allow user code to avoid unexpected any behavioural changes, the +:data:`iris.Future` controls follow a special management cycle, as follows +(see also the relevant :ref:`Developer Guide section `): + +At (minor) release "...": + * Changes to API: + * the new behaviour is made available, alongside the old one + + * a new future option `iris.FUTURE.` is provided to switch + between them. + + * the new option defaults to `iris.FUTURE.=False`, meaning + the 'old' behaviour is the default. + + * when any relevant API call is made that invokes the old behaviour, a + deprecation warning is emitted. + + * User actions: + + * If your code encounters the new deprecation warning, you should try + enabling the new control option, and make any necessary rewrites to + make it work. This will stop the deprecation warning appearing. + + * If you encounter problems making your code work with the new + behaviour, and don't have time to fix them, you should make your + code explicitly turn *off* the option for now, i.e. :: + `iris.FUTURE. = False`. + This locks you into the old behaviour, but your code will continue + to work, even beyond the next major release when the default + behaviour will change (see on). + +At (major) release ".0...": + * Changes to API: + * the control default is changed to `iris.FUTURE.=True` + + * the control property is *itself* deprecated, so that assigning to it + now results in a deprecation warning. + + * when any affected API call is made, a deprecation warning is (still) + emitted, if the old behaviour is in force. The "old" behaviour is, + however, still available and functional. + + * User actions: + + * If your code is already using the "new" behaviour, it will now work + without needing to set the Future option. *You should remove* the + code which enables the option, as this will now emit a deprecation + message. In the *next* major release, this would cause an error. + + * If your code is explicitly turning the option off, it will continue + to work in the same way at this point, but obviously time is + runnning out. + + * If your code is still using the old behaviour and *not* setting the + control option at all, its behaviour might now have changed + unexpectedly and you should review this. + +At (major) release "...": + * Changes to API: + * the control property is removed + * the "old" behaviour is removed + + + +.. _iris_dependency_versions: + +Versions of Installed Dependencies +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The dependencies of Iris (required and optional) are defined in +:ref:`installing_iris`. + +Iris does not specify exact required versions for its dependencies, but it may +specify a minimum acceptable version number. Iris is normally expected to be +compatible with *any* version up to the latest current release. + +When a new release of a dependency is found to cause problems, Iris may define +the supported version more precisely, but this would be a temporary fix which +should be removed in a later release. diff --git a/docs/iris/src/whitepapers/index.rst b/docs/iris/src/whitepapers/index.rst new file mode 100644 index 0000000000..dd0876d257 --- /dev/null +++ b/docs/iris/src/whitepapers/index.rst @@ -0,0 +1,12 @@ +.. _whitepapers_index: + +============================ +Iris technical 'Whitepapers' +============================ +Extra information on specific technical issues. + +.. toctree:: + :maxdepth: 1 + + um_files_loading.rst + missing_data_handling.rst diff --git a/docs/iris/src/whitepapers/missing_data_handling.rst b/docs/iris/src/whitepapers/missing_data_handling.rst new file mode 100644 index 0000000000..cd6ef038c2 --- /dev/null +++ b/docs/iris/src/whitepapers/missing_data_handling.rst @@ -0,0 +1,81 @@ +============================= +Missing Data Handling in Iris +============================= + +This document provides a brief overview of how Iris handles missing data values +when datasets are loaded as cubes, and when cubes are saved or modified. + +A missing data value, or fill-value, defines the value used within a dataset to +indicate that data point is missing or not set. +This value is included as part of a dataset's metadata. + +For example, in a gridded global ocean dataset, no data values will be recorded +over land, so land points will be missing data. +In such a case, land points could be indicated by being set to the dataset's +missing data value. + + +Loading +------- + +On load, any fill-value or missing data value defined in the loaded dataset +should be used as the ``fill_value`` of the NumPy masked array data attribute of the +:class:`~iris.cube.Cube`. This will only appear when the cube's data is realised. + + +Saving +------ + +On save, the fill-value of a cube's masked data array is **not** used in saving data. +Instead, Iris always uses the default fill-value for the fileformat, *except* +when a fill-value is specified by the user via a fileformat-specific saver. + +For example:: + + >>> iris.save(my_cube, 'my_file.nc', fill_value=-99999) + +.. note:: + Not all savers accept the ``fill_value`` keyword argument. + +Iris will check for and issue warnings of fill-value 'collisions'. +This basically means that whenever there are unmasked values that would read back +as masked, we issue a warning and suggest a workaround. + +This will occur in the following cases: + +* where masked data contains *unmasked* points matching the fill-value, or +* where unmasked data contains the fill-value (either the format-specific default fill-value, + or a fill-value specified by the user in the save call). + + +NetCDF +~~~~~~ + +NetCDF is a special case, because all ordinary variable data is "potentially masked", +owing to the use of default fill values. The default fill-value used depends on the type +of the variable data. + +The exceptions to this are: + +* One-byte values are not masked unless the variable has an explicit ``_FillValue`` attribute. + That is, there is no default fill-value for ``byte`` types in NetCDF. +* Data may be tagged with a ``_NoFill`` attribute. This is not currently officially + documented or widely implemented. +* Small integers create problems by *not* having the exemption applied to byte data. + Thus, in principle, ``int32`` data cannot use the full range of 2**16 valid values. + + +Merging +------- + +Merged data should have a fill-value equal to that of the components, if they +all have the same fill-value. If the components have differing fill-values, a +default fill-value will be used instead. + + +Other operations +---------------- + +Other operations, such as :class:`~iris.cube.Cube` arithmetic operations, +generally produce output with a default (NumPy) fill-value. That is, these operations +ignore the fill-values of the input(s) to the operation. diff --git a/docs/iris/src/whitepapers/um_files_loading.rst b/docs/iris/src/whitepapers/um_files_loading.rst new file mode 100644 index 0000000000..fd2d2a2341 --- /dev/null +++ b/docs/iris/src/whitepapers/um_files_loading.rst @@ -0,0 +1,452 @@ +.. _um_files_loading: + +.. testsetup:: + + import numpy as np + import iris + import iris.fileformats.pp + np.set_printoptions(precision=2) + + +.. testcleanup:: + + np.set_printoptions(precision=8) + + +=================================== +Iris handling of PP and Fieldsfiles +=================================== + +This document provides a basic account of how PP and Fieldsfiles data is +represented within Iris. +It describes how Iris represents data from the Met Office Unified Model (UM), +in terms of the metadata elements found in PP and Fieldsfile formats. + +For simplicity, we shall describe this mostly in terms of *loading of PP data into +Iris* (i.e. into cubes). However most of the details are identical for +Fieldsfiles, and are relevant to saving in these formats as well as loading. + +Notes: + +#. Iris treats Fieldsfile data almost exactly as if it were PP -- i.e. it + treats each field's lookup table entry like a PP header. +#. The Iris datamodel is based on + `NetCDF CF conventions `_, so most of this can + also be seen as a metadata translation between PP and CF terms, but it is + easier to discuss in terms of Iris elements. + +For details of Iris terms (cubes, coordinates, attributes), refer to +:ref:`Iris data structures `. + +For details of CF conventions, see http://cfconventions.org/. + +Overview of loading process +--------------------------- + +The basics of Iris loading are explained at :ref:`loading_iris_cubes`. +Loading as it specifically applies to PP and Fieldsfile data can be summarised +as follows: + +#. Input fields are first loaded from the given sources, using + :func:`iris.fileformats.pp.load`. This returns an iterator, which provides + a 'stream' of :class:`~iris.fileformats.pp.PPField` input field objects. + Each PPfield object represents a single source field: + + * PP header elements are provided as named object attributes (e.g. + :attr:`~iris.fileformats.pp.PPField.lbproc`). + * Some extra, calculated "convenience" properties are also provided (e.g. + :attr:`~iris.fileformats.pp.PPField.t1` and + :attr:`~iris.fileformats.pp.PPField.t2` time values). + * There is a :attr:`iris.fileformats.pp.PPField.data` attribute, but the + field data is not actually loaded unless/until this is accessed, for + greater speed and space efficiency. + +#. Each input field is translated into a two-dimensional Iris cube (with + dimensions of latitude and longitude). These are the 'raw' cubes, as + returned by :meth:`iris.load_raw`. + Within these: + + * There are 2 horizontal dimension coordinates containing the latitude + and longitude values for the field. + * Certain other header elements are interpreted as 'coordinate'-type + values applying to the input fields, and stored as auxiliary 'scalar' + (i.e. 1-D) coordinates. These include all header elements defining + vertical and time coordinate values, and also more specialised factors + such as ensemble number and pseudo-level. + * Other metadata is encoded on the cube in a variety of other forms, such + as the cube 'name' and 'units' properties, attribute values and cell + methods. + +#. Lastly, Iris attempts to merge the raw cubes into higher-dimensional ones + (using :meth:`~iris.cube.CubeList.merge`): This combines raw cubes with + different values of a scalar coordinate to produce a higher-dimensional + cube with the values contained in a new vector coordinate. Where possible, + the new vector coordinate is also a *dimension* coordinate, describing the + new dimension. + Apart from the original 2 horizontal dimensions, all cube dimensions and + dimension coordinates arise in this way -- for example, 'time', 'height', + 'forecast_period', 'realization'. + +.. note:: + This document covers the essential features of the UM data loading process. + The complete details are implemented as follows: + + * The conversion of fields to raw cubes is performed by the function + :func:`iris.fileformats.pp_rules.convert`, which is called from + :func:`iris.fileformats.pp.load_cubes` during loading. + * The corresponding save functionality for PP output is implemented by + the :func:`iris.fileformats.pp.save` function. The relevant + 'save rules' are defined in a text file + ("lib/iris/etc/pp_save_rules.txt"), in a form defined by the + :mod:`iris.fileformats.rules` module. + +The rest of this document describes various independent sections of related +metadata items. + +Horizontal Grid +--------------- + +**UM Field elements** + LBCODE, BPLAT, BPLON, BZX, BZY, BDX, BDY, X, Y, + X_LOWER_BOUNDS, Y_LOWER_BOUNDS + +**Cube components** + (unrotated) : coordinates ``longitude``, ``latitude`` + + (rotated pole) : coordinates ``grid_latitude``, ``grid_longitude`` + +**Details** + +At present, only latitude-longitude projections are supported (both normal and +rotated). +In these cases, LBCODE is typically 1 or 101 (though, in fact, cross-sections +with latitude and longitude axes are also supported). + +For an ordinary latitude-longitude grid, the cubes have coordinates called +'longitude' and 'latitude': + + * These are mapped to the appropriate data dimensions. + * They have units of 'degrees'. + * They have a coordinate system of type :class:`iris.coord_systems.GeogCS`. + * The coordinate points are normally set to the regular sequence + ``ZDX/Y + BDX/Y * (1 .. LBNPT/LBROW)`` (*except*, if BDX/BDY is zero, the + values are taken from the extra data vector X/Y, if present). + * If X/Y_LOWER_BOUNDS extra data is available, this appears as bounds values + of the horizontal cooordinates. + +For **rotated** latitude-longitude coordinates (as for LBCODE=101), the +horizontal coordinates differ only slightly -- + + * The names are 'grid_latitude' and 'grid_longitude'. + * The coord_system is a :class:`iris.coord_systems.RotatedGeogCS`, created + with a pole defined by BPLAT, BPLON. + +For example: + >>> # Load a PP field. + ... fname = iris.sample_data_path('air_temp.pp') + >>> fields_iter = iris.fileformats.pp.load(fname) + >>> field = next(fields_iter) + >>> + >>> # Show grid details and first 5 longitude values. + >>> print(' '.join(str(_) for _ in (field.lbcode, field.lbnpt, field.bzx, + ... field.bdx))) + 1 96 -3.749999 3.749999 + >>> print(field.bzx + field.bdx * np.arange(1, 6)) + [ 0. 3.75 7.5 11.25 15. ] + >>> + >>> # Show Iris equivalent information. + ... cube = iris.load_cube(fname) + >>> print(cube.coord('longitude').points[:5]) + [ 0. 3.75 7.5 11.25 15. ] + +.. note:: + Note that in Iris (as in CF) there is no special distinction between + "regular" and "irregular" coordinates. Thus on saving, X and Y extra data + sections are written only if the actual values are unevenly spaced. + + +Phenomenon identification +------------------------- + +**UM Field elements** + LBFC, LBUSER4 (aka "stashcode"), LBUSER7 (aka "model code") + +**Cube components** + ``cube.standard_name``, ``cube.units``, ``cube.attributes['STASH']`` + +**Details** + +This information is normally encoded in the cube ``standard_name`` property. +Iris identifies the stash section and item codes from LBUSER4 and the model +code in LBUSER7, and compares these against a list of phenomenon types with +known CF translations. If the stashcode is recognised, it then defines the +appropriate ``standard_name`` and ``units`` properties of the cube +(i.e. :attr:`iris.cube.Cube.standard_name` and :attr:`iris.cube.Cube.units`). + +Where any parts of the stash information are outside the valid range, Iris will +instead attempt to interpret LBFC, for which a set of known translations is +also stored. This is often the case for fieldsfiles, where LBUSER4 is +frequently left as 0. + +In all cases, Iris also constructs a :class:`~iris.fileformats.pp.STASH` item +to identify the phenomenon, which is stored as a cube attribute named +``STASH``. +This preserves the original STASH coding (as standard name translation is not +always one-to-one), and can be used when no standard_name translation is +identified (for example, to load only certain stashcodes with a constraint +-- see example at :ref:`Load constraint examples `). + +For example: + >>> # Show PPfield phenomenon details. + >>> print(field.lbuser[3]) + 16203 + >>> print(field.lbuser[6]) + 1 + >>> + >>> + >>> # Show Iris equivalents. + >>> print(cube.standard_name) + air_temperature + >>> print(cube.units) + K + >>> print(cube.attributes['STASH']) + m01s16i203 + +.. note:: + On saving data, no attempt is made to translate a cube standard_name into a + STASH code, but any attached 'STASH' attribute will be stored into the + LBUSER4 and LBUSER7 elements. + + +Vertical coordinates +-------------------- + +**UM Field elements** + LBVC, LBLEV, BRSVD1 (aka "bulev"), BRSVD2 (aka "bhulev"), BLEV, BRLEV, + BHLEV, BHRLEV + +**Cube components** + for height levels : coordinate ``height`` + + for pressure levels : coordinate ``pressure`` + + for hybrid height levels : + + * coordinates ``model_level_number``, ``sigma``, ``level_height``, + ``altitude`` + * ``cube.aux_factories()[0].orography`` + + for hybrid pressure levels : + + * coordinates ``model_level_number``, ``sigma``, ``level_pressure``, + ``air_pressure`` + * ``cube.aux_factories()[0].surface_air_pressure`` + + +**Details** + +Several vertical coordinate forms are supported, according to different values +of LBVC. The commonest ones are: + +* lbvc=1 : height levels +* lbvc=8 : pressure levels +* lbvc=65 : hybrid height + +In all these cases, vertical coordinates are created, with points and bounds +values taken from the appropriate header elements. In the raw cubes, each +vertical coordinate is just a single value, but multiple values will usually +occur. The subsequent merge operation will then convert these into +multiple-valued coordinates, and create a new vertical data dimension (i.e. a +"Z" axis) which they map onto. + +For height levels (LBVC=1): + A ``height`` coordinate is created. This has units 'm', points from + BLEV, and no bounds. When there are multiple vertical levels, this will + become a dimension coordinate mapping to the vertical dimension. + +For pressure levels (LBVC=8): + A ``pressure`` coordinate is created. This has units 'hPa', points from + BLEV, and no bounds. When there are multiple vertical levels, this will + become a dimension coordinate mapping a vertical dimension. + +For hybrid height levels (LBVC=65): + Three basic vertical coordinates are created: + + * ``model_level`` is dimensionless, with points from LBLEV and no bounds. + * ``sigma`` is dimensionless, with points from BHLEV and bounds from + BHRLEV and BHULEV. + * ``level_height`` has units of 'm', points from BLEV and bounds from + BRLEV and BULEV. + + Also in this case, a :class:`~iris.aux_factory.HybridHeightFactory` is + created, which references the 'level_height' and 'sigma' coordinates. + Following raw cube merging, an extra load stage occurs where the + attached :class:`~iris.aux_factory.HybridHeightFactory` is called to + manufacture a new ``altitude`` coordinate: + + * The altitude coordinate is 3D, mapping to the 2 horizontal + dimensions *and* the new vertical dimension. + * Its units are 'm'. + * Its points are calculated from those of the 'level_height' and + 'sigma' coordinates, and an orography field. If 'sigma' and + 'level_height' possess bounds, then bounds are also created for + 'altitude'. + + To make the altitude coordinate, there must be an orography field present + in the load sources. This is a surface altitude reference field, + identified (by stashcode) during the main loading operation, and recorded + for later use in the hybrid height calculation. If it is absent, a warning + message is printed, and no altitude coordinate is produced. + + Note that on merging hybrid height data into a cube, only the 'model_level' + coordinate becomes a dimension coordinate: The other vertical coordinates + remain as auxiliary coordinates, because they may be (variously) + multidimensional or non-monotonic. + +See an example printout of a hybrid height cube, +:ref:`here `: + + Notice that this contains all of the above coordinates -- + 'model_level_number', 'sigma', 'level_height' and the derived 'altitude'. + +.. note:: + + Hybrid pressure levels can also be handled (for LBVC=9). Without going + into details, the mechanism is very similar to that for hybrid height: + it produces basic coordinates 'model_level_number', 'sigma' and + 'level_pressure', and a manufactured 3D 'air_pressure' coordinate. + + +.. _um_time_metadata: + +Time information +---------------- + +**UM Field elements** + +* "T1" (i.e. LBYR, LBMON, LBDAT, LBHR, LBMIN, LBDAY/LBSEC), +* "T2" (i.e. LBYRD, LBMOND, LBDATD, LBHRD, LBMIND, LBDAYD/LBSECD), +* LBTIM, LBFT + +**Cube components** + coordinates ``time``, ``forecast_reference_time``, ``forecast_period`` + + +**Details** + +In Iris (as in CF) times and time intervals are both expressed as simple +numbers, following the approach of the +`UDUNITS project `_. +These values are stored as cube coordinates, where the scaling and calendar +information is contained in the :attr:`~iris.coords.Coord.units` property. + +* The units of a time interval (e.g. 'forecast_period'), can be 'seconds' or + a simple derived unit such as 'hours' or 'days' -- but it does not contain + a calendar, so 'months' or 'years' are not valid. +* The units of calendar-based times (including 'time' and + 'forecast_reference_time'), are of the general form + " since ", interpreted according to the unit's + :attr:`~iris.unit.Unit.calendar` property. The base date for this is + always 1st Jan 1970 (times before this are represented as negative values). + +The units.calendar property of time coordinates is set from the lowest decimal +digit of LBTIM, known as LBTIM.IC. Note that the non-gregorian calendars (e.g. +360-day 'model' calendar) are defined in CF, not udunits. + +There are a number of different time encoding methods used in UM data, but the +important distinctions are controlled by the next-to-lowest decimal digit of +LBTIM, known as "LBTIM.IB". +The most common cases are as follows: + +Data at a single measurement timepoint (LBTIM.IB=0): + A single ``time`` coordinate is created, with points taken from T1 values. + It has no bounds, units of 'hours since 1970-01-01 00:00:00' and a calendar + defined according to LBTIM.IC. + +Values forecast from T2, valid at T1 (LBTIM.IB=1): + Coordinates ``time` and ``forecast_reference_time`` are created from the T1 + and T2 values, respectively. These have no bounds, and units of + 'hours since 1970-01-01 00:00:00', with the appropriate calendar. + A ``forecast_period`` coordinate is also created, with values T1-T2, no + bounds and units of 'hours'. + +Time mean values between T1 and T2 (LBTIM.IB=2): + The time coordinates ``time``, ``forecast_reference_times`` and + ``forecast_reference_time``, are all present, as in the previous case. + In this case, however, the 'time' and 'forecast_period' coordinates also + have associated bounds: The 'time' bounds are from T1 to T2, and the + 'forecast_period' bounds are from "LBFT - (T2-T1)" to "LBFT". + +Note that, in those more complex cases where the input defines all three of the +'time', 'forecast_reference_time' and 'forecast_period' values, any or all of +these may become dimensions of the resulting data cube. This will depend on +the values actually present in the source fields for each of the elements. + +See an example printout of a forecast data cube, +:ref:`here ` : + + Notice that this example contains all of the above coordinates -- 'time', + 'forecast_period' and 'forecast_reference_time'. In this case the data are + forecasts, so 'time' is a dimension, 'forecast_period' varies with time and + 'forecast_reference_time' is a constant. + + +Statistical measures +-------------------- + +**UM Field elements** + LBPROC, LBTIM + +**Cube components** + ``cube.cell_methods`` + + +**Details** + +Where a field contains statistically processed data, Iris will add an +appropriate :class:`iris.coords.CellMethod` to the cube, representing the +aggregation operation which was performed. + +This is implemented for certain binary flag bits within the LBPROC element +value. For example: + +* time mean, when (LBPROC & 128): + Cube has a cell_method of the form "CellMethod('mean', 'time'). +* time period minimum value, when (LBPROC & 4096): + Cube has a cell_method of the form "CellMethod('minimum', 'time'). +* time period maximum value, when (LBPROC & 8192): + Cube has a cell_method of the form "CellMethod('maximum', 'time'). + +In all these cases, if the field LBTIM is also set to denote a time aggregate +field (i.e. "LBTIM.IB=2", see above :ref:`um_time_metadata`), then the +second-to-last digit of LBTIM, aka "LBTIM.IA" may also be non-zero, in which +case this indicates the aggregation time-interval. In that case, the +cell-method :attr:`~iris.coords.CellMethod.intervals` attribute is also set to +this many hours. + +For example: + >>> # Show stats metadata in a test PP field. + ... fname = iris.sample_data_path('pre-industrial.pp') + >>> eg_field = next(iris.fileformats.pp.load(fname)) + >>> print(eg_field.lbtim) + 622 + >>> print(eg_field.lbproc) + 128 + >>> + >>> # Print out the Iris equivalent information. + >>> print(iris.load_cube(fname).cell_methods) + (CellMethod(method='mean', coord_names=('time',), intervals=('6 hour',), comments=()),) + + +Other metadata +-------------- + +LBRSVD4 +^^^^^^^ +If non-zero, this is interpreted as an ensemble number. This produces a cube +scalar coordinate named 'realization' (as defined in the CF conventions). + +LBUSER5 +^^^^^^^ +If non-zero, this is interpreted as a 'pseudo_level' number. This produces a +cube scalar coordinate named 'pseudo_level'. In the UM documentation LBUSER5 is also sometimes referred to as LBPLEV. diff --git a/etc/area-type-table.xml b/etc/area-type-table.xml old mode 100755 new mode 100644 index 76e6e8d270..d59d6d69ca --- a/etc/area-type-table.xml +++ b/etc/area-type-table.xml @@ -1,49 +1,126 @@ - - - Area Type Table - 1 - 5 December 2008 - Program for Climate Model Diagnosis and Intercomparison - webmaster@pcmdi.llnl.gov - - - - - - - - - - - - - - - All ice floating on water including lake-ice, sea-ice, ice-shelves and icebergs. - - - - - - Floating ice excluding ice-shelves and icebergs. - - - - - - - - - - - - - - - - - - - - - + + + Area Type Table + 6 + 22 February 2017 + Centre for Environmental Data Analysis + support@ceda.ac.uk + + + + + + + + + + + + A plant that utilizes the C3 carbon fixation pathway as the sole mechanism to bind CO2 before photosynthesis reactions take place. All trees are C3 type. Grasses and crops can be C3 or C4. + + + A plant that utilizes the C4 carbon fixation pathway in which the CO2 is first bound to a compound containing four carbon atoms before photosynthesis reactions take place. All trees are C3 type. Grasses and crops can be C3 or C4. + + + + + + + + + The definition of "crops" is model dependent, for example, some models may include fruit trees as crops. + + + An area_type of "dust_aerosol" indicates that dust aerosol is present at some level in the atmospheric column above an area on the surface of the Earth. + + + An area_type of "fire" indicates that biomass fire, either flaming, smouldering, or both, is present. + + + All ice floating on water including lake-ice, sea-ice, ice-shelves and icebergs. + + + An area type of "floating ice shelf" indicates where ice shelves are present. Ice shelves are the component of ice sheets that flow over the ocean. + + + An area type of "grounded ice sheet" indicates where the ice sheet rest over bedrock and is thus grounded. It excludes ice-caps, glaciers and floating ice shelves. + + + + + + + + + An area type of "ice sheet" indicates where ice sheets are present. It includes both grounded ice sheets resting over bedrock and ice shelves flowing over the ocean, but excludes ice-caps and glaciers (in contrast to land_ice, which includes all components). + + + Floating ice excluding ice-shelves and icebergs. + + + + + + "Land ice" means glaciers, ice-caps, grounded ice sheets resting on bedrock and floating ice-shelves. + + + The area occupied by type "sea_ice" is the sum of the areas of types "sea_ice_melt_pond" and "melt_pond_free_sea_ice". + + + + + + Pastures are assumed to be anthropogenic in origin. They include anthropogenically managed pastureland and rangeland. + + + "Primary and secondary land" is land that is not in use as crop land or pasture land, including forests, grasslands, bare ground and vegetated wetlands. "Primary land" is land that has not undergone lulcc (land use or land cover change) due to human disturbance. "Secondary land" is land that has previously been used for agriculture, urban development or logging and has subsequently been abandoned. Reference: Hurtt et al. (2011), Climatic Change, 109 - 117, Harmonization of land-use scenarios for the period 1500–2100: 600 years of global gridded annual land-use transitions, wood harvest, and resulting secondary lands, doi: 10.1007/s10584-011-0153-2. "Primary and secondary land" refers to land use or management, rather than to specific categories of vegetation cover, e.g. the primary and secondary succession of plant species. + + + A primary forest is a naturally regenerated forest of native species, where there are no clearly visible indications of human activities and the ecological processes are not significantly disturbed. Reference: 'Global Forest Resources Assessment: Terms and Definitions', Forestry Department of Food and Agriculture Organization (FAO) of the United Nations, Rome 2010, www.fao.org/forestry/14241-0d7b74f45b0d2cfef31599cc17e4c28cd.pdf. Deciduous trees lose their leaves seasonally, for example, during winter in high latitudes or following seasonal variations in rainfall. + + + A primary forest is a naturally regenerated forest of native species, where there are no clearly visible indications of human activities and the ecological processes are not significantly disturbed. Reference: 'Global Forest Resources Assessment: Terms and Definitions', Forestry Department of Food and Agriculture Organization (FAO) of the United Nations, Rome 2010, www.fao.org/forestry/14241-0d7b74f45b0d2cfef31599cc17e4c28cd.pdf. Evergreen trees have leaves in all seasons. + + + An area_type of "rain" indicates that falling rain is present at some level in the atmospheric column above an area on the surface of the Earth. + + + The area occupied by type "sea" is equal to the sum of the areas of types "ice_free_sea" and "sea_ice". + + + The area occupied by type "sea_ice" within a grid cell is the sum of the areas of types "sea_ice_melt_pond" and "melt_pond_free_sea_ice". Melt ponds occur on top of the existing sea ice. The area occupied by type "sea" is equal to the sum of the areas of types "ice_free_sea" and "sea_ice". + + + The area classified as type "sea_ice" within a grid cell is unaltered when an area of type "sea_ice_melt_pond" is also present because melt ponds occur on top of the existing sea ice. + + + A secondary forest is a forest that has been logged and has recovered naturally or artificially. Reference: 'Report of the ad hoc technical expert group on forest biological diversity', United Nations Convention on Biological Diversity, www.cbd.int/forest/definitions.shtml. Deciduous trees lose their leaves seasonally, for example, during winter in high latitudes or following seasonal variations in rainfall. + + + A secondary forest is a forest that has been logged and has recovered naturally or artificially. Reference: 'Report of the ad hoc technical expert group on forest biological diversity', United Nations Convention on Biological Diversity, www.cbd.int/forest/definitions.shtml. Evergreen trees have leaves in all seasons. + + + The distinction between trees and shrubs is model dependent. + + + An area_type of "smoke" indicates that smoke aerosol is present at some level in the atmospheric column above an area on the surface of the Earth. + + + + + + + + + The distinction between trees and shrubs is model dependent. All trees are C3 plant functional type. + + + Urban land is comprised of areas where much of the land is covered by structures. Included in this category are cities, towns and villages. Reference: Anderson, J.R, E. E. Hardy, J. T. Roach and R. E. Witmer (1976), A Land Use And Land Cover Classification System For Use With Remote Sensor Data, Appendix C Land Use Definitions, Geological Survey Professional Paper 964, A revision of the land use classification system as presented in U.S. Geological Survey Circular 671, https://www.usbr.gov/lc/socal/reports/SMappend_C.pdf. + + + + + + An area_type of "volcanic_ash_cloud" indicates that volcanic ash aerosol is present at some level in the atmospheric column above an area on the surface of the Earth. + + diff --git a/etc/cf-standard-name-table.xml b/etc/cf-standard-name-table.xml index e16560f17a..0c4f59b888 100644 --- a/etc/cf-standard-name-table.xml +++ b/etc/cf-standard-name-table.xml @@ -1,16 +1,37 @@ - 23 - 2013-03-23:T12:30:00Z - Program for Climate Model Diagnosis and Intercomparison - webmaster@pcmdi.llnl.gov + 59 + 2018-09-25T14:23:22Z + Centre for Environmental Data Analysis + support@ceda.ac.uk + + s + + + The quantity with standard name acoustic_signal_roundtrip_travel_time_in_sea_water is the time taken for an acoustic signal to propagate from the emitting instrument to a reflecting surface and back again to the instrument. In the case of an instrument based on the sea floor and measuring the roundtrip time to the sea surface, the data are commonly used as a measure of ocean heat content. + + + + m + + + The diameter of a spherical particle with density 1000 kg m-3 having the same aerodynamic properties as the particles in question. + + + + m-1 s + + + The "aerodynamic_resistance" is the resistance to mixing through the boundary layer toward the surface by means of the dominant process, turbulent transport. Reference: Wesely, M. L., 1989, doi:10.1016/0004-6981(89)90153-4. + + year - "Age of sea ice" means the length of time elapsed since the ice formed. + "Age of sea ice" means the length of time elapsed since the ice formed. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. @@ -45,56 +66,63 @@ Pa 1 plev - + Air pressure is the force per unit area which would be exerted when the moving gas molecules of which the air is composed strike a theoretical surface of any orientation. Pa 26 - "anomaly" means difference from climatology. + The term "anomaly" means difference from climatology. Air pressure is the force per unit area which would be exerted when the moving gas molecules of which the air is composed strike a theoretical surface of any orientation. Pa - cloud_base refers to the base of the lowest cloud. + The phrase "cloud_base" refers to the base of the lowest cloud. Air pressure is the force per unit area which would be exerted when the moving gas molecules of which the air is composed strike a theoretical surface of any orientation. Pa - cloud_top refers to the top of the highest cloud. + The phrase "cloud_top" refers to the top of the highest cloud. Air pressure is the force per unit area which would be exerted when the moving gas molecules of which the air is composed strike a theoretical surface of any orientation. Pa - cloud_base refers to the base of the lowest cloud. Convective cloud is that produced by the convection schemes in an atmosphere model. + The phrase "cloud_base" refers to the base of the lowest cloud. Convective cloud is that produced by the convection schemes in an atmosphere model. Air pressure is the force per unit area which would be exerted when the moving gas molecules of which the air is composed strike a theoretical surface of any orientation. Pa - cloud_top refers to the top of the highest cloud. Convective cloud is that produced by the convection schemes in an atmosphere model. + The phrase "cloud_top" refers to the top of the highest cloud. Convective cloud is that produced by the convection schemes in an atmosphere model. Air pressure is the force per unit area which would be exerted when the moving gas molecules of which the air is composed strike a theoretical surface of any orientation. Pa - + Air pressure is the force per unit area which would be exerted when the moving gas molecules of which the air is composed strike a theoretical surface of any orientation. - + Pa 2 E151 psl - sea_level means mean sea level, which is close to the geoid in sea areas. Air pressure at sea level is the quantity often abbreviated as MSLP or PMSL. + Air pressure at sea level is the quantity often abbreviated as MSLP or PMSL. Air pressure is the force per unit area which would be exerted when the moving gas molecules of which the air is composed strike a theoretical surface of any orientation. "Mean sea level" means the time mean of sea surface elevation at a given location over an arbitrary period sufficient to eliminate the tidal signals. + + + + Pa + + + "Top of atmosphere model" means the upper boundary of the top layer of an atmosphere model. Air pressure is the force per unit area which would be exerted when the moving gas molecules of which the air is composed strike a theoretical surface of any orientation. @@ -118,6 +146,13 @@ cloud_top refers to the top of the highest cloud. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + K + + + The "effective cloud top defined by infrared radiation" is (approximately) the geometric height above the surface that is one optical depth at infrared wavelengths (in the region of 11 micrometers) below the cloud top that would be detected by visible and lidar techniques. Reference: Minnis, P. et al 2011 CERES Edition-2 Cloud Property Retrievals Using TRMM VIRS and Terra and Aqua MODIS Data x2014; Part I: Algorithms IEEE Transactions on Geoscience and Remote Sensing, 49(11), 4374-4400. doi: http://dx.doi.org/10.1109/TGRS.2011.2144601. + + K m-1 19 @@ -167,6 +202,13 @@ Altitude is the (geometric) height above the geoid, which is the reference geopotential surface. The geoid is similar to mean sea level. + + m + + + Altitude is the (geometric) height above the geoid, which is the reference geopotential surface. The geoid is similar to mean sea level. "Top of atmosphere model" means the upper boundary of the top layer of an atmosphere model. + + m @@ -174,6 +216,20 @@ Altitude is the (geometric) height above the geoid, which is the reference geopotential surface. The geoid is similar to mean sea level. + + m + + + "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". + + + + m + + + Global average sea level change is due to change in volume of the water in the ocean, caused by mass and/or density change, or to change in the volume of the ocean basins, caused by tectonics etc. It is sometimes called "eustatic", which is a term that also has other definitions. It differs from the change in the global average sea surface height relative to the centre of the Earth by the global average vertical movement of the ocean floor. Zero sea level change is an arbitrary level. Amplitude is the magnitude of a wave modelled by a sinusoidal function. A coordinate variable of harmonic_period should be used to specify the period of the sinusoidal wave. Because global average sea level change quantifies the change in volume of the world ocean, it is not calculated necessarily by considering local changes in mean sea level. + + degree @@ -202,11 +258,25 @@ The quantity with standard name angle_of_rotation_from_east_to_y is the angle, anticlockwise reckoned positive, between due East and (dr/dj)ik, where r(i,j,k) is the vector 3D position of the point with coordinate indices (i,j,k). It could be used for rotating vector fields between model space and latitude-longitude space. + + degree + + + Standard names for "platform" describe the motion and orientation of the vehicle from which observations are made. Platforms include, but are not limited to, satellites, aeroplanes, ships, instruments and buoys. An angle of rotation is reckoned positive in the anticlockwise direction. The "angle_of_rotation_from_solar_azimuth_to_platform_azimuth" is the angle of rotation between the solar azimuth angle and the platform azimuth angle. Solar azimuth angle is the horizontal angle between the line of sight from the observation point to the sun and a reference direction at the observation point, which is often due north. The angle is measured clockwise, starting from the reference direction. Platform azimuth angle is the horizontal angle between the line of sight from the observation point to the platform and a reference direction at the observation point, which is often due north. The angle is measured clockwise, starting from the reference direction. + + 1 - "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. The "Angstrom exponent" appears in the formula relating aerosol optical thickness to the wavelength of incident radiation: T(lambda) = T(lambda0) * [lambda/lambda0] ** (-1 * alpha) where alpha is the Angstrom exponent, lambda is the wavelength of incident radiation, lambda0 is a reference wavelength, T(lambda) and T(lambda0) are the values of aerosol optical thickness at wavelengths lambda and lambda0, respectively. + The "Angstrom exponent" appears in the formula relating aerosol optical thickness to the wavelength of incident radiation: T(lambda) = T(lambda0) * [lambda/lambda0] ** (-1 * alpha) where alpha is the Angstrom exponent, lambda is the wavelength of incident radiation, lambda0 is a reference wavelength, T(lambda) and T(lambda0) are the values of aerosol optical thickness at wavelengths lambda and lambda0, respectively. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". + + + + mol kg-1 + + + Apparent Oxygen Utilization (AOU) is the difference between measured dissolved oxygen concentration in water, and the equilibrium saturation concentration of dissolved oxygen in water with the same physical and chemical properties. Reference: Broecker, W. S. and T. H. Peng (1982), Tracers in the Sea, Lamont-Doherty Earth Observatory, Palisades, N. Y. @@ -223,13 +293,41 @@ The surface called "surface" means the lower boundary of the atmosphere. The fraction of horizontal area where the surface specified by the axes other than horizontal axes, for instance an isobaric surface, is below the (ground or sea) surface. - + + 1 + + + "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. A coordinate variable of solar_zenith_angle indicating the day extent should be specified. + + + + 1 + + + "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. A coordinate variable of solar_zenith_angle indicating the night extent should be specified. + + + 1 + "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. A coordinate variable of solar_zenith_angle indicating the twilight extent should be specified. + + + + + + A variable with the standard name of area_type contains strings which indicate the nature of the surface e.g. land, sea, sea_ice. These strings are standardised. Values must be taken from the area_type table. + + 1 + + + The asymmetry factor is the angular integral of the aerosol scattering phase function weighted by the cosine of the angle with the incident radiation flux. The asymmetry coefficient is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength is included to specify the wavelength. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". + + s-1 41 @@ -237,11 +335,11 @@ Absolute vorticity is the sum of relative vorticity and the upward component of vorticity due to the Earth's rotation. - + 1 - The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Absorption optical thickness" means that part of the atmosphere optical thickness that is caused by the absorption of incident radiation. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Absorption optical thickness" means that part of the atmosphere optical thickness that is caused by the absorption of incident radiation. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. @@ -251,32 +349,32 @@ The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Absorption optical thickness" means that part of the atmosphere optical thickness that is caused by the absorption of incident radiation. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - + 1 - The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Absorption optical thickness" means that part of the atmosphere optical thickness that is caused by the absorption of incident radiation. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Absorption optical thickness" means that part of the atmosphere optical thickness that is caused by the absorption of incident radiation. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - + 1 - The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Absorption optical thickness" means that part of the atmosphere optical thickness that is caused by the absorption of incident radiation. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Absorption optical thickness" means that part of the atmosphere optical thickness that is caused by the absorption of incident radiation. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - + 1 - The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Absorption optical thickness" means that part of the atmosphere optical thickness that is caused by the absorption of incident radiation. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Absorption optical thickness" means that part of the atmosphere optical thickness that is caused by the absorption of incident radiation. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - + 1 - The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Absorption optical thickness" means that part of the atmosphere optical thickness that is caused by the absorption of incident radiation. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Absorption optical thickness" means that part of the atmosphere optical thickness that is caused by the absorption of incident radiation. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. @@ -286,6 +384,34 @@ The atmosphere boundary layer thickness is the "depth" or "height" of the (atmosphere) planetary boundary layer. + + J kg-1 + + + Convective(ly) available potential energy (often abbreviated CAPE) is a stability measure calculated by integrating the positive temperature difference between the surrounding atmosphere and a parcel of air lifted adiabatically from a given starting height to its equilibrium level. A coordinate variable of original_air_pressure_of_lifted_parcel should be specified to indicate the starting height of the lifted parcel. CAPE exists under conditions of potential instability, and measures the potential energy per unit mass that would be released by the unstable parcel if it were able to convect upwards to equilibrium. + + + + J kg -1 + + + Convective(ly) available potential energy (often abbreviated CAPE) is a stability measure calculated by integrating the positive temperature difference between the surrounding atmosphere and a parcel of air lifted adiabatically from the surface to its equilibrium level. CAPE exists under conditions of potential instability, and measures the potential energy per unit mass that would be released by the unstable parcel if it were able to convect upwards to equilibrium. + + + + J kg -1 + + + Convective inhibition is the amount of energy per unit mass required to overcome the negatively buoyant energy exerted by the environment on a parcel of air. Convective inhibition is often abbreviated as "CIN" or "CINH". It is calculated by integrating the negative temperature difference between the surrounding atmosphere and a parcel of air lifted adiabatically from a given starting height to its equilibrium level. A coordinate variable of original_air_pressure_of_lifted_parcel should be specified to indicate the starting height of the lifted parcel. + + + + J kg -1 + + + Convective inhibition is the amount of energy per unit mass required to overcome the negatively buoyant energy exerted by the environment on a parcel of air. Convective inhibition is often abbreviated as "CIN" or "CINH". It is calculated by integrating the negative temperature difference between the surrounding atmosphere and a parcel of air lifted adiabatically from the surface to its equilibrium level. + + kg m-2 s-1 @@ -370,6 +496,34 @@ "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. + + m + + + The level of free convection is the altitude where the temperature of the environment decreases faster than the moist adiabatic lapse rate of a saturated air parcel at the same level. It is calculated by lifting a parcel of air dry adiabatically to the LCL (lifted condensation level), then moist adiabatically until the parcel temperature is equal to the ambient temperature. A coordinate variable of original_air_pressure_of_lifted_parcel should be specified to indicate the starting height of the lifted parcel. + + + + m + + + The level of free convection is the altitude where the temperature of the environment decreases faster than the moist adiabatic lapse rate of a saturated air parcel at the same level. It is calculated by lifting a parcel of air dry adiabatically from the surface to the LCL (lifting condensation level), then moist adiabatically until the parcel temperature is equal to the ambient temperature. + + + + m + + + The lifting condensation level is the height at which the relative humidity of an air parcel cooled by dry adiabatic lifting would reach 100%. A coordinate variable of original_air_pressure_of_lifted_parcel should be specified to indicate the starting height of the lifted parcel. + + + + m + + + The lifting condensation level is the height at which the relative humidity of an air parcel cooled by dry adiabatic lifting from the surface would reach 100%. + + 1 @@ -426,18 +580,18 @@ "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for ammonia is NH3. - + kg m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The chemical formula for ammonium is NH4. + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The chemical formula for ammonium is NH4. kg m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "nmvoc" means non methane volatile organic compounds. "Anthropogenic" means influenced, caused, or created by human activity. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Anthropogenic" means influenced, caused, or created by human activity. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. @@ -486,14 +640,7 @@ kg m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "nmvoc" means non methane volatile organic compounds. "Biogenic" means influenced, caused, or created by natural processes. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - - - kg m-2 - - - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Biogenic" means influenced, caused, or created by natural processes. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. @@ -619,7 +766,7 @@ kg m-2 76 clwvi - "condensed_water" means liquid and ice. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. + The phrase "condensed_water" means liquid and ice. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. @@ -647,7 +794,14 @@ kg m-2 - "condensed_water" means liquid and ice. Convective cloud is that produced by the convection schemes in an atmosphere model. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. + The phrase "condensed_water" means liquid and ice. Convective cloud is that produced by the convection schemes in an atmosphere model. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. + + + + kg m-2 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Convective cloud is that produced by the convection schemes in an atmosphere model. @@ -678,11 +832,18 @@ "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for dinitrogen pentoxide is N2O5. - + + kg m-2 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. + + + kg m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). @@ -741,6 +902,27 @@ "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical symbol for mercury is Hg. + + kg m-2 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. Graupel consists of heavily rimed snow particles, often called snow pellets; often indistinguishable from very small soft hail except when the size convention that hail must have a diameter greater than 5 mm is adopted. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Graupel. There are also separate standard names for hail. Standard names for "graupel_and_hail" should be used to describe data produced by models that do not distinguish between hail and graupel. + + + + kg m-2 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. Graupel consists of heavily rimed snow particles, often called snow pellets; often indistinguishable from very small soft hail except when the size convention that hail must have a diameter greater than 5 mm is adopted. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Graupel. Hail is precipitation in the form of balls or irregular lumps of ice, often restricted by a size convention to diameters of 5 mm or more. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Hail. Standard names for "graupel_and_hail" should be used to describe data produced by models that do not distinguish between hail and graupel. For models that do distinguish between them, separate standard names for hail and graupel are available. + + + + kg m-2 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. Hail is precipitation in the form of balls or irregular lumps of ice, often restricted by a size convention to diameters of 5 mm or more. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Hail. For diameters of less than 5 mm standard names for "graupel" should be used. Standard names for "graupel_and_hail" should be used to describe data produced by models that do not distinguish between hail and graupel. + + kg m-2 @@ -895,11 +1077,11 @@ "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for limonene is C10H16. The IUPAC name for limonene is 1-methyl-4-prop-1-en-2-yl-cyclohexene. Limonene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. - + kg m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. @@ -951,11 +1133,11 @@ "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for molecular hydrogen is H2. - + kg m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The chemical formula for the nitrate anion is NO3-. + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The chemical formula for the nitrate anion is NO3-. @@ -972,11 +1154,11 @@ "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for nitric acid is HNO3. - + kg m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. Nitric acid trihydrate, sometimes referred to as NAT, is a stable crystalline substance consisting of three molecules of water to one molecule of nitric acid. The chemical formula for nitric acid is HNO3. + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". Nitric acid trihydrate, sometimes referred to as NAT, is a stable crystalline substance consisting of three molecules of water to one molecule of nitric acid. The chemical formula for nitric acid is HNO3. @@ -1004,7 +1186,7 @@ kg m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "nmvoc" means non methane volatile organic compounds. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. @@ -1035,11 +1217,11 @@ "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for ozone is O3. - + kg m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except black carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. @@ -1063,11 +1245,11 @@ "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The term "peroxy_radicals" means all organic and inorganic peroxy radicals. This includes HO2 and all organic peroxy radicals, sometimes referred to as RO2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. - + kg m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "Primary particulate organic matter " means all organic matter emitted directly to the atmosphere as particles except black carbon. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. "Primary particulate organic matter " means all organic matter emitted directly to the atmosphere as particles except elemental carbon. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. @@ -1091,18 +1273,25 @@ "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical symbol for radon is Rn. - + + kg m-2 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. + + + kg m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The phrase "sea_salt_cation" is the term used in standard names to describe collectively the group of cationic species that occur in sea salt. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Sea salt cations are mainly sodium (Na+), but also include potassium (K+), magnesium (Mg2+), calcium (Ca2+) and rarer cations. Where possible, the data variable should be accompanied by a complete description of the ions represented, for example, by using a comment attribute. - + kg m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "Secondary particulate organic matter " means particulate organic matter formed within the atmosphere from gaseous precursors. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Secondary particulate organic matter " means particulate organic matter formed within the atmosphere from gaseous precursors. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. @@ -1112,25 +1301,25 @@ "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. - + kg m-2 trsult - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". - + kg m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The chemical formula for the sulfate anion is SO4(2-). + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The chemical formula for the sulfate anion is SO4(2-). - + kg m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The chemical formula for the sulfate anion is SO4(2-). + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The chemical formula for the sulfate anion is SO4(2-). @@ -1154,6 +1343,14 @@ "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. + + kg m-2 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Volcanic_ash" means the fine-grained products of explosive volcanic eruptions, such as minerals or crystals, older fragmented rock (e.g. andesite), and glass. Particles within a volcanic ash cloud have diameters less than 2 mm. "Volcanic_ash" does not include non-volcanic dust. + + + kg m-2 @@ -1161,11 +1358,11 @@ "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Water" means water in all phases. - + kg m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Water" means water in all phases. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Water" means water in all phases. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". @@ -1203,6 +1400,27 @@ "X_area" means the horizontal area occupied by X within the grid cell. + + mol m-2 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The construction "atmosphere_mole_content_of_X" means the vertically integrated number of moles of X above a unit area. The chemical formula of carbon monoxide is CO. + + + + mol m-2 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The construction "atmosphere_mole_content_of_X" means the vertically integrated number of moles of X above a unit area. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + + + + mol m-2 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The construction "atmosphere_mole_content_of_X" means the vertically integrated number of moles of X above a unit area. The chemical formula for nitrogen dioxide is NO2. + + mol m-2 @@ -1210,6 +1428,13 @@ "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The construction "atmosphere_mole_content_of_X" means the vertically integrated number of moles of X above a unit area. The chemical formula for ozone is O3. atmosphere_mole_content_of_ozone is usually measured in Dobson Units which are equivalent to 446.2 micromoles m-2. N.B. Data variables containing column content of ozone can be given the standard name of either equivalent_thickness_at_stp_of_atmosphere_ozone_content or atmosphere_mole_content_of_ozone.The latter name is recommended for consistency with mole content names for chemical species other than ozone. + + mol m-2 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The construction "atmosphere_mole_content_of_X" means the vertically integrated number of moles of X above a unit area. Atmosphere water vapor content is sometimes referred to as "precipitable water", although this term does not imply the water could all be precipitated. The chemical formula for water is H2O. + + mol @@ -1249,7 +1474,7 @@ mol - The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "nmvoc" means non methane volatile organic compounds. "Anthropogenic" means influenced, caused, or created by human activity. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Anthropogenic" means influenced, caused, or created by human activity. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. @@ -1291,7 +1516,7 @@ mol - The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "nmvoc" means non methane volatile organic compounds. "Biogenic" means influenced, caused, or created by natural processes. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Biogenic" means influenced, caused, or created by natural processes. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. @@ -1714,11 +1939,11 @@ The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for nitric acid is HNO3. - + mol - "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for nitric acid is HNO3. Nitric acid trihydrate, sometimes referred to as NAT, is a stable crystalline substance consisting of three molecules of water to one molecule of nitric acid. + The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". The chemical formula for nitric acid is HNO3. Nitric acid trihydrate, sometimes referred to as NAT, is a stable crystalline substance consisting of three molecules of water to one molecule of nitric acid. @@ -1753,7 +1978,7 @@ mol - The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "nmvoc" means non methane volatile organic compounds. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. @@ -1893,7 +2118,7 @@ m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. @@ -1910,11 +2135,18 @@ "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. - + + 1 + + + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + 1 - The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-"optical_thickness") on traversing the path. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. @@ -1928,7 +2160,7 @@ 1 - The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. "Cloud" means the component of extinction owing to the presence of liquid or ice water particles. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. @@ -1938,53 +2170,60 @@ The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. Convective cloud is that produced by the convection schemes in an atmosphere model. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - + + 1 + + + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + 1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-"optical_thickness") on traversing the path. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - + 1 - The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-"optical_thickness") on traversing the path. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-"optical_thickness") on traversing the path. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The chemical formula for the nitrate anion is NO3-. - + 1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - + 1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. "Pm10 aerosol" is an air pollutant with an aerodynamic diameter of less than or equal to 10 micrometers. + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - + 1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. "Pm1 aerosol" is an air pollutant with an aerodynamic diameter of less than or equal to 1 micrometer. + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. "Pm1 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 1 micrometer. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - + 1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. "Pm2p5 aerosol" is an air pollutant with an aerodynamic diameter of less than or equal to 2.5 micrometers. + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - + 1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. @@ -1994,11 +2233,18 @@ The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - + + 1 + + + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-"optical_thickness") on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + 1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "atmosphere_optical_thickness_due_to_water_in_ambient_aerosol" refers to the optical thickness due to the water that is associated with aerosol particles due to hygroscopic growth in ambient air, affecting the particle's radius and refractive index. It corresponds to the difference between the total dry aerosol optical thickness and the total ambient aerosol optical thickness. + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. The atmosphere optical thickness applies to radiation passing through the entire atmosphere. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. "atmosphere_optical_thickness_due_to_water_in_ambient_aerosol" refers to the optical thickness due to the water that is associated with aerosol particles due to hygroscopic growth in ambient air, affecting the radius and refractive index of the particle. It corresponds to the difference between the total dry aerosol optical thickness and the total ambient aerosol optical thickness. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. @@ -2029,11 +2275,41 @@ See Appendix D of the CF convention for information about dimensionless vertical coordinates. - - J kg-1 + + K - "specific" means per unit mass. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) Convective(ly) available potential energy is often abbreviated as "CAPE". + The atmosphere_stability_k_index is an index that indicates the potential of severe convection and is often referred to a simply the k index. The index is derived from the difference in air temperature between 850 and 500 hPa, the dew point temperature at 850 hPa, and the difference between the air temperature and the dew point temperature at +700 hPa. + + + + + K + + + The atmosphere_stability_showalter_index is an index used to determine convective and thunderstorm potential and is often referred to as simply the showalter index. The index is defined as the temperature difference between a parcel of air lifted from 850 to 500 hPa (wet adiabatically) and the ambient air temperature at 500 hPa. + + + + + K + + + The atmosphere_stability_total_totals_index indicates the +likelihood of severe convection and is often referred to as simply the +total totals index. The index is derived from the difference in air +temperature between 850 and 500 hPa (the vertical totals) and the +difference between the dew point temperature at 850 hPa and the air +temperature at 500 hPa (the cross totals). The vertical totals and cross +totals are summed to obtain the index. + + + + kg s-1 + + + The "meridional mass streamfunction" is a streamfunction of the zonally averaged mass transport in the meridional plane. The "Transformed Eulerian Mean" refers to a formulation of the mean equations which incorporates some eddy terms into the definition of the mean, described in Andrews et al (1987): Middle Atmospheric Dynamics. Academic Press. @@ -2043,6 +2319,13 @@ In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The atmosphere convective mass flux is the vertical transport of mass for a field of cumulus clouds or thermals, given by the product of air density and vertical velocity. For an area-average, cell_methods should specify whether the average is over all the area or the area of updrafts and/or downdrafts only. "Updraft" means that the flux is positive in the updward direction (negative downward). + + + + + The Automated Tropical Cyclone Forecasting System (ATCF) storm identifier is an 8 character string which identifies a tropical cyclone. The storm identifier has the form BBCCYYYY, where BB is the ocean basin, specifically: AL - North Atlantic basin, north of the Equator; SL - South Atlantic basin, south of the Equator; EP - North East Pacific basin, eastward of 140 degrees west longitude; CP - North Central Pacific basin, between the dateline and 140 degrees west longitude; WP - North West Pacific basin, westward of the dateline; IO - North Indian Ocean basin, north of the Equator between 40 and 100 degrees east longitude; SH - South Pacific Ocean basin and South Indian Ocean basin. CC is the cyclone number. Numbers 01 through 49 are reserved for tropical and subtropical cyclones. A cyclone number is assigned to each tropical or subtropical cyclone in each basin as it develops. Numbers are assigned in chronological order. Numbers 50 through 79 are reserved for internal use by operational forecast centers. Numbers 80 through 89 are reserved for training, exercises and testing. Numbers 90 through 99 are reserved for tropical disturbances having the potential to become tropical or subtropical cyclones. The 90's are assigned sequentially and reused throughout the calendar year. YYYY is the four-digit year. This is calendar year for the northern hemisphere. For the southern hemisphere, the year begins July 1, with calendar year plus one. Reference: Miller, R.J., Schrader, A.J., Sampson, C.R., & Tsui, T.L. (1990), The Automated Tropical Cyclone Forecasting System (ATCF), American Meteorological Society Computer Techniques, 5, 653 - 660. + + 1 @@ -2064,6 +2347,13 @@ A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). + + m + + + Barometric altitude is the altitude determined by a pressure measurement which is converted to altitude through interpolation of the International Standard Atmosphere (ICAO, 1976). A mean sea level pressure of 1013.25 hPa is used for the surface pressure. + + m s-1 @@ -2092,6 +2382,13 @@ A velocity is a vector quantity. "y" indicates a vector component along the grid y-axis, positive with increasing y. + + W m-2 + + + "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. + + kg m-2 @@ -2134,41 +2431,6 @@ "Biomass burning carbon" refers to the rate at which biomass is burned by forest fires etc., expressed as the mass of carbon which it contains. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - m s-1 - - - Bolus velocity in an ocean model means the velocity due to a scheme representing eddy-induced effects which are not resolved on the grid scale of the model. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). - - - - m s-1 - - - Bolus velocity in an ocean model means the velocity due to a scheme representing eddy-induced effects which are not resolved on the grid scale of the model. "Northward" indicates a vector component which is positive when directed northward (negative southward). - - - - m s-1 - - - A velocity is a vector quantity. "x" indicates a vector component along the grid x-axis, positive with increasing x. Bolus velocity in an ocean model means the velocity due to a scheme representing eddy-induced effects which are not resolved on the grid scale of the model. bolus_sea_water_x_velocity is used in some parameterisations of lateral diffusion in the ocean. - - - - m s-1 - - - A velocity is a vector quantity. "y" indicates a vector component along the grid y-axis, positive with increasing y. Bolus velocity in an ocean model means the velocity due to a scheme representing eddy-induced effects which are not resolved on the grid scale of the model. bolus_sea_water_y_velocity is used in some parameterisations of lateral diffusion in the ocean. - - - - m s-1 - - - Bolus velocity in an ocean model means the velocity due to a scheme representing eddy-induced effects which are not resolved on the grid scale of the model. "Upward" indicates a vector component which is positive when directed upward (negative downward). - - K 118 @@ -2183,18 +2445,25 @@ The brightness temperature of a body is the temperature of a black body which radiates the same power per unit solid angle per unit area. "anomaly" means difference from climatology. + + K + + + cloud_top refers to the top of the highest cloud. brightness_temperature of a body is the temperature of a black body which radiates the same power per unit solid angle per unit area. A coordinate variable of radiation_wavelength, sensor_band_central_radiation_wavelength, or radiation_frequency may be specified to indicate that the brightness temperature applies at specific wavelengths or frequencies. + + s-1 - Frequency is the number of oscillations of a wave per unit time. + Frequency is the number of oscillations of a wave per unit time. Brunt-Vaisala frequency is also sometimes called "buoyancy frequency" and is a measure of the vertical stratification of the medium. m2 - "X_area" means the horizontal area occupied by X within the grid cell. "Burned area" means the area of burned vegetation. + "X_area" means the horizontal area occupied by X within the grid cell. The extent of an individual grid cell is defined by the horizontal coordinates and any associated coordinate bounds or by a string valued auxiliary coordinate variable with a standard name of "region". "Burned area" means the area of burned vegetation. @@ -2204,46 +2473,81 @@ "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. "Burned area" means the area of burned vegetation. - - kg m-2 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Amount" means mass per unit area. "Water" means water in all phases, including frozen i.e. ice and snow. "Canopy" means the plant or vegetation canopy. "Canopy and surface water" means the sum of water on the ground and on the canopy. + Albedo is the ratio of outgoing to incoming shortwave irradiance, where 'shortwave irradiance' means that both the incoming and outgoing radiation are integrated across the solar spectrum. "Canopy" means the vegetative covering over a surface. The canopy is often considered to be the outer surfaces of the vegetation. Plant height and the distribution, orientation and shape of plant leaves within a canopy influence the atmospheric environment and many plant processes within the canopy. Reference: AMS Glossary http://glossary.ametsoc.org/wiki/Canopy. The surface_albedo restricted to the area type "vegetation" is related to canopy_albedo, but the former also includes the effect of radiation being reflected from the ground underneath the canopy. + + + + kg m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Amount" means mass per unit area. "Water" means water in all phases, including frozen i.e. ice and snow. "Canopy and surface water" means the sum of water on the ground and on the canopy. "Canopy" means the vegetative covering over a surface. The canopy is often considered to be the outer surfaces of the vegetation. Plant height and the distribution, orientation and shape of plant leaves within a canopy influence the atmospheric environment and many plant processes within the canopy. Reference: AMS Glossary http://glossary.ametsoc.org/wiki/Canopy. m - Height is the vertical distance above the surface. "Canopy" means the plant or vegetation canopy. + Height is the vertical distance above the surface. "Canopy" means the vegetative covering over a surface. The canopy is often considered to be the outer surfaces of the vegetation. Plant height and the distribution, orientation and shape of plant leaves within a canopy influence the atmospheric environment and many plant processes within the canopy. Reference: AMS Glossary http://glossary.ametsoc.org/wiki/Canopy. + + + + m-1 s + + + "Canopy" means the plant or vegetation canopy. The "canopy_resistance" is the resistance of a compound to uptake by the vegetation canopy. It varies both with the surface and the chemical species or physical state (gas or particle). Canopy resistance is a function of the canopy stomatal resistance (Rstom), the canopy cuticle resistance (Rcuticle), and the soil resistance (Rsoil). In the case of ozone the uptake by the cuticle is small compared to the uptake through the stomata. Reference: Kerstiens and Lendzian, 1989. This means that the cuticle transfer pathway can be neglected in model parameterizations. Reference: Ganzeveld and Jos Lelieveld , 1995, doi/10.1029/95JD02266/pdf. "Canopy" means the vegetative covering over a surface. The canopy is often considered to be the outer surfaces of the vegetation. Plant height and the distribution, orientation and shape of plant leaves within a canopy influence the atmospheric environment and many plant processes within the canopy. Reference: AMS Glossary http://glossary.ametsoc.org/wiki/Canopy. The chemical formula for ozone is O3. The IUPAC name for ozone is trioxygen. + + + + kg m-2 + + + "Amount" means mass per unit area. The phrase "canopy_snow" means snow lying on the canopy. "Canopy" means the vegetative covering over a surface. The canopy is often considered to be the outer surfaces of the vegetation. Plant height and the distribution, orientation and shape of plant leaves within a canopy influence the atmospheric environment and many plant processes within the canopy. Reference: AMS Glossary http://glossary.ametsoc.org/wiki/Canopy. K - "Canopy" means the plant or vegetation canopy. "Canopy_temperature" is the bulk temperature of the canopy, not the surface (skin) temperature. + "Canopy temperature" is the bulk temperature of the canopy, not the surface (skin) temperature. "Canopy" means the vegetative covering over a surface. The canopy is often considered to be the outer surfaces of the vegetation. Plant height and the distribution, orientation and shape of plant leaves within a canopy influence the atmospheric environment and many plant processes within the canopy. Reference: AMS Glossary http://glossary.ametsoc.org/wiki/Canopy. kg m-2 s-1 - "Canopy" means the plant or vegetation canopy. "Throughfall" is the part of the precipitation flux that reaches the ground directly through the vegetative canopy, through intershrub spaces in the canopy, and as drip from the leaves, twigs, and stems (but not including snowmelt). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + "Canopy" means the vegetative covering over a surface. The canopy is often considered to be the outer surfaces of the vegetation. Plant height and the distribution, orientation and shape of plant leaves within a canopy influence the atmospheric environment and many plant processes within the canopy. Reference: AMS Glossary http://glossary.ametsoc.org/wiki/Canopy. "Throughfall" is the part of the precipitation flux that reaches the ground directly through the vegetative canopy, through intershrub spaces in the canopy, and as drip from the leaves, twigs, and stems (but not including snowmelt). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. kg m-2 - "Amount" means mass per unit area. "Water" means water in all phases, including frozen i.e. ice and snow. "Canopy" means the plant or vegetation canopy. The canopy water is the water on the canopy. + "Amount" means mass per unit area. "Water" means water in all phases, including frozen i.e. ice and snow. The canopy water is the water on the canopy. The canopy is often considered to be the outer surfaces of the vegetation. Plant height and the distribution, orientation and shape of plant leaves within a canopy influence the atmospheric environment and many plant processes within the canopy. Reference: AMS Glossary http://glossary.ametsoc.org/wiki/Canopy. - + kg m-2 - "Content" indicates a quantity per unit area. "products_of_anthropogenic_land_use_change" means the different end-products of wood that has been removed from the environment by deforestation. Examples are paper, cardboard, furniture and timber for construction. Models that simulate land use changes have one or more pools of carbon that represent these products in order to conserve carbon and allow its eventual release into the atmosphere, for example, when the products decompose in landfill sites. "Anthropogenic" means influenced, caused, or created by human activity. + "Content" indicates a quantity per unit area. Examples of "forestry and agricultural products" are paper, cardboard, furniture, timber for construction, biofuels and food for both humans and livestock. Models that simulate land use changes have one or more pools of carbon that represent these products in order to conserve carbon and allow its eventual release into the atmosphere, for example, when the products decompose in landfill sites. + + + + kg m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Anthropogenic" means influenced, caused, or created by human activity. Examples of "forestry and agricultural products" are paper, cardboard, furniture, timber for construction, biofuels and food for both humans and livestock. Models that simulate land use changes have one or more pools of carbon that represent these products in order to conserve carbon and allow its eventual release into the atmosphere, for example, when the products decompose in landfill sites. "Anthropogenic land use change" means human changes to land, excluding forest regrowth. It includes fires ignited by humans for the purpose of land use change and the processes of eventual disposal and decomposition of wood products such as paper, cardboard, furniture and timber for construction. + + + + kg m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Litter" is dead plant material in or above the soil. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Anthropogenic" means influenced, caused, or created by human activity. "Anthropogenic land use change" means human changes to land, excluding forest regrowth. It includes fires ignited by humans for the purpose of land use change and the processes of eventual disposal and decomposition of wood products such as paper, cardboard, furniture and timber for construction. @@ -2288,6 +2592,20 @@ The surface called "surface" means the lower boundary of the atmosphere. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "wrt" means with respect to. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. See Appendix D of the CF convention for information about dimensionless vertical coordinates. + + kg m-2 + + + "Amount" means mass per unit area. Zero change in land ice amount is an arbitrary level. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. + + + + kg m-2 + + + The phrase "change_over_time_in_X" means change in a quantity X over a time-interval, which should be defined by the bounds of the time coordinate. "Amount" means mass per unit area. The phrase "ice_and_snow_on_land" means ice in glaciers, ice caps, ice sheets and shelves, river and lake ice, any other ice on a land surface, such as frozen flood water, and snow lying on such ice or on the land surface. + + kg m-2 @@ -2295,6 +2613,48 @@ "change_over_time_in_X" means change in a quantity X over a time-interval, which should be defined by the bounds of the time coordinate. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Water" means water in all phases. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + kg m-2 + + + The phrase "change_over_time_in_X" means change in a quantity X over a time-interval, which should be defined by the bounds of the time coordinate. Canopy water is the water on the canopy. "Water" means water in all phases, including frozen, i.e. ice and snow. "Amount" means mass per unit area. "Canopy" means the vegetative covering over a surface. The canopy is often considered to be the outer surfaces of the vegetation. Plant height and the distribution, orientation and shape of plant leaves within a canopy influence the atmospheric environment and many plant processes within the canopy. Reference: AMS Glossary http://glossary.ametsoc.org/wiki/Canopy. + + + + kg m-2 + + + The phrase "change_over_time_in_X" means change in a quantity X over a time-interval, which should be defined by the bounds of the time coordinate. "Water" means water in all phases. Groundwater is subsurface water below the depth of the water table. "Amount" means mass per unit area. + + + + kg m-2 + + + The phrase "change_over_time_in_X" means change in a quantity X over a time-interval, which should be defined by the bounds of the time coordinate. The surface called "surface" means the lower boundary of the atmosphere. "Amount" means mass per unit area. "Land surface liquid water amount" includes water in rivers, wetlands, lakes, reservoirs and liquid precipitation intercepted by the vegetation canopy. + + + + kg m-2 + + + The phrase "change_over_time_in_X" means change in a quantity X over a time-interval, which should be defined by the bounds of the time coordinate. "Amount" means mass per unit area. "Water" means water in all phases. The phrase "land_water_amount", often known as "Terrestrial Water Storage", includes: surface liquid water (water in rivers, wetlands, lakes, reservoirs, rainfall intercepted by the canopy); surface ice and snow (glaciers, ice caps, grounded ice sheets not displacing sea water, river and lake ice, other surface ice such as frozen flood water, snow lying on the surface and intercepted by the canopy); subsurface water (liquid and frozen soil water, groundwater). + + + + kg m-2 + + + The phrase "change_over_time_in_X" means change in a quantity X over a time-interval, which should be defined by the bounds of the time coordinate. "Content" indicates a quantity per unit area. The mass content of water in soil refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including "content_of_soil_layer" are used. "Water" means water in all phases. + + + + kg m-2 + + + The phrase "change_over_time_in_X" means change in a quantity X over a time-interval, which should be defined by the bounds of the time coordinate. "Water" means water in all phases. "River" refers to the water in the fluvial system (stream and floodplain). "Amount" means mass per unit area. + + g kg-1 @@ -2306,7 +2666,7 @@ K - "change_over_time_in_X" means change in a quantity X over a time-interval, which should be defined by the bounds of the time coordinate. Conservative Temperature is defined as part of the Thermodynamic Equation of Seawater 2010 (TEOS-10) which was adopted in 2010 by the International Oceanographic Commission (IOC). Conservative Temperature is specific potential enthalpy (which has the standard name sea_water_specific_potential_enthalpy) divided by a fixed value divided by a fixed value of the specific heat capacity of sea water, namely cp_0 = 3991.86795711963 J kg-1 K-1. Conservative Temperature is a more accurate measure of the "heat content" of sea water, by a factor of one hundred, than is potential temperature. Because of this, it can be regarded as being proportional to the heat content of sea water per unit mass. Reference: www.teos-10.org; McDougall, 2003 doi: 10.1175/1520-0485(2003)033<0945:PEACOV>2.0.CO;2. + "change_over_time_in_X" means change in a quantity X over a time-interval, which should be defined by the bounds of the time coordinate. Conservative Temperature is defined as part of the Thermodynamic Equation of Seawater 2010 (TEOS-10) which was adopted in 2010 by the International Oceanographic Commission (IOC). Conservative Temperature is specific potential enthalpy (which has the standard name sea_water_specific_potential_enthalpy) divided by a fixed value of the specific heat capacity of sea water, namely cp_0 = 3991.86795711963 J kg-1 K-1. Conservative Temperature is a more accurate measure of the "heat content" of sea water, by a factor of one hundred, than is potential temperature. Because of this, it can be regarded as being proportional to the heat content of sea water per unit mass. Reference: www.teos-10.org; McDougall, 2003 doi: 10.1175/1520-0485(2003)033<0945:PEACOV>2.0.CO;2. @@ -2338,10 +2698,10 @@ - 1e-3 + 1 - "change_over_time_in_X" means change in a quantity X over a time-interval, which should be defined by the bounds of the time coordinate. Practical Salinity, S_P, is defined on the Practical Salinity Scale of 1978 (PSS-78) and is calculated from the electrical conductivity of sea water (as well as temperature and pressure). Officially S_P is dimensionless so that, while convenient, and while it is common practice, it is not officially sanctioned to say S_P = 35 psu. Often authors use PSS-78, as in S_P = 35 PSS-78. If salinity was measured using remote sensing techniques and not conductivity, then it is recommended that additional metadata (calibration/validation information) be described in the variable comment attribute. This name should be used to describe salinity observations made from 1978 onwards (Practical Salinity is the salinity quantity stored by national data centres for post-1978 observations). The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. There are also standard names for the precisely defined salinity quantities sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Salinity quantities that do not match any of the precise definitions should be given the more general standard name of sea_water_salinity. Reference: www.teos-10.org; Lewis, 1980 doi: 10.1109/JOE.1980.1145448 + "change_over_time_in_X" means change in a quantity X over a time-interval, which should be defined by the bounds of the time coordinate. Practical Salinity, S_P, is a determination of the salinity of sea water, based on its electrical conductance. The measured conductance, corrected for temperature and pressure, is compared to the conductance of a standard potassium chloride solution, producing a value on the Practical Salinity Scale of 1978 (PSS-78). This name should not be used to describe salinity observations made before 1978, or ones not based on conductance measurements. Conversion of Practical Salinity to other precisely defined salinity measures should use the appropriate formulas specified by TEOS-10. Other standard names for precisely defined salinity quantities are sea_water_absolute_salinity (S_A); sea_water_preformed_salinity (S_*), sea_water_reference_salinity (S_R); sea_water_cox_salinity (S_C), used for salinity observations between 1967 and 1977; and sea_water_knudsen_salinity (S_K), used for salinity observations between 1901 and 1966. Salinity quantities that do not match any of the precise definitions shoul d be given the more general standard name of sea_water_salinity. Reference: www.teos-10.org; Lewis, 1980 doi:10.1109/JOE.1980.1145448. @@ -2379,11 +2739,32 @@ The surface called "surface" means the lower boundary of the atmosphere. "change_over_time_in_X" means change in a quantity X over a time-interval, which should be defined by the bounds of the time coordinate. "Amount" means mass per unit area. Surface amount refers to the amount on the ground, excluding that on the plant or vegetation canopy. + + J m-2 + + + The phrase "change_over_time_in_X" means change in a quantity X over a time-interval, which should be defined by the bounds of the time coordinate. Thermal energy is the total vibrational energy, kinetic and potential, of all the molecules and atoms in a substance. The phrase "ice_and_snow_on_land" means ice in glaciers, ice caps, ice sheets and shelves, river and lake ice, any other ice on a land surface, such as frozen flood water, and snow lying on such ice or on the land surface. + + + + J m-2 + + + The phrase "change_over_time_in_X" means change in a quantity X over a time-interval, which should be defined by the bounds of the time coordinate. "Content" indicates a quantity per unit area. Thermal energy is the total vibrational energy, kinetic and potential, of all the molecules and atoms in a substance. "Vegetation" means any living plants e.g. trees, shrubs, grass. The term "plants" refers to the kingdom of plants in the modern classification which excludes fungi. Plants are autotrophs i.e. "producers" of biomass using carbon obtained from carbon dioxide. "Litter" is dead plant material in or above the soil. It is distinct from coarse wood debris. The precise distinction between "fine" and "coarse" is model dependent. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including "content_of_soil_layer" are used. + + + + 1 + + + "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. The clear_sky area fraction is for the whole atmosphere column, as seen from the surface or the top of the atmosphere. + + 1 - The albedo of cloud. + The albedo of cloud. Albedo is the ratio of outgoing to incoming shortwave irradiance, where 'shortwave irradiance' means that both the incoming and outgoing radiation are integrated across the solar spectrum. @@ -2407,6 +2788,13 @@ cloud_base refers to the base of the lowest cloud. Altitude is the (geometric) height above the geoid, which is the reference geopotential surface. The geoid is similar to mean sea level. + + 1 + + + X_binary_mask has 1 where condition X is met, 0 elsewhere. 1 = cloud present, 0 = cloud absent (clear). If no threshold is supplied, the binary mask is 1 if there is any non-zero amount of cloud. if a threshold is supplied, it should be specified by associating a coordinate variable or scalar coordinate variable with the data variable and giving the coordinate variable a standard name of cloud_area_fraction. The values of the coordinate variable are the threshold values for the corresponding subarrays of the data variable. + + 1 @@ -2432,7 +2820,14 @@ Pa m - "Compressive strength" is a measure of the capacity of a material to withstand compressive forces. If compressive forces are exerted on a material in excess of its compressive strength, fracturing will occur. + "Compressive strength" is a measure of the capacity of a material to withstand compressive forces. If compressive forces are exerted on a material in excess of its compressive strength, fracturing will occur. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. + + + + 1 + + + The quantity with standard name concentration_of_colored_dissolved_organic_matter_in_sea_water_expressed_as_equivalent_mass_fraction_of_quinine_sulfate_dihydrate is also commonly known as Chromophoric Dissolved Organic Matter (CDOM). CDOM plays an important role in the carbon cycling and biogeochemistry of coastal waters. It occurs naturally in aquatic environments primarily as a result of tannins released from decaying plant and animal matter, which can enter coastal areas in river run-off containing organic materials leached from soils. When present in high concentrations, it imparts a brown or yellowish color to water. Its presence can negatively impact fish populations by reducing dissolved oxygen concentrations to harmful levels and by releasing nutrients and metals that contaminate the water. Increased understanding of the role of CDOM will further our ability to manage and protect coastal ecosystems. Sensors are commonly calibrated against a 100 parts per billion (ppb) quinine sulfate dihydrate solution, a fluorescent reference standard commonly used with CDOM sensors. CDOM sensors therefore report in "QSDE" (quinine sulfate dihydrate equivalents). It is important to note, however, that CDOM concentrations in QSDE are not necessarily equivalent to the in situ CDOM concentrations in ppb. @@ -2495,21 +2890,21 @@ kg m-2 63 - "Amount" means mass per unit area. + "Amount" means mass per unit area. "Precipitation" in the earth's atmosphere means precipitation of water in all phases. Convective precipitation is that produced by the convection schemes in an atmosphere model. kg m-2 s-1 prc - In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Convective precipitation is that produced by the convection schemes in an atmosphere model. "Precipitation" in the earth's atmosphere means precipitation of water in all phases. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. m s-1 - "Precipitation rate" means the depth or thickness of the layer formed by precipitation per unit time. + "Precipitation rate" means the depth or thickness of the layer formed by precipitation per unit time. Convective precipitation is that produced by the convection schemes in an atmosphere model. "Precipitation" in the earth's atmosphere means precipitation of water in all phases. @@ -2575,6 +2970,13 @@ This quantity, often used to indicate the "thermocline depth", is the depth of the maximum vertical gradient of sea water potential temperature. Depth is the vertical distance below the surface. Potential temperature is the temperature a parcel of air or sea water would have if moved adiabatically to sea level pressure. + + m + + + Depth is the vertical distance below the surface. A soil temperature profile may go through one or more local minima or maxima. The "depth at shallowest isotherm" is the depth of the occurrence closest to the soil surface of an isotherm of the temperature specified by a coordinate variable or scalar coordinate variable with standard name soil_temperature. + + m @@ -2586,7 +2988,14 @@ m - The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. (The volume enclosed between the geoid and the sea floor equals the mean volume of water in the ocean.) In an ocean GCM the geoid is the surface of zero depth, or the rigid lid if the model uses that approximation. "Depth_below_X" means the vertical distance below the named surface X. + The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. (The volume enclosed between the geoid and the sea floor equals the mean volume of water in the ocean). In an ocean GCM the geoid is the surface of zero depth, or the rigid lid if the model uses that approximation. To specify which geoid or geopotential datum is being used as a reference level, a grid_mapping variable should be attached to the data variable as described in Chapter 5.6 of the CF Convention. "Depth_below_X" means the vertical distance below the named surface X. + + + + m + + + "Depth_below_X" means the vertical distance below the named surface X. @@ -2614,21 +3023,21 @@ Pa - In some atmosphere models, the difference of air pressure from model reference is a prognostic variable, instead of the air pressure itself. The model reference air pressure is a model-dependent constant. + In some atmosphere models, the difference of air pressure from model reference is a prognostic variable, instead of the air pressure itself. The model reference air pressure is a model-dependent constant. Air pressure is the force per unit area which would be exerted when the moving gas molecules of which the air is composed strike a theoretical surface of any orientation. W m-2 - Downwelling radiation is radiation from above. It does not mean "net downward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "shortwave" means shortwave radiation. "Diffuse" radiation is radiation that has been scattered by particles in the atmosphere such as cloud droplets and aerosols. + "Diffuse" radiation is radiation that has been scattered by gas molecules in the atmosphere and by particles such as cloud droplets and aerosols. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. W m-2 - Downwelling radiation is radiation from above. It does not mean "net downward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "shortwave" means shortwave radiation. "Diffuse" radiation is radiation that has been scattered by particles in the atmosphere such as cloud droplets and aerosols. + "Diffuse" radiation is radiation that has been scattered by gas molecules in the atmosphere and by particles such as cloud droplets and aerosols. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Clear sky" means in the absence of clouds. @@ -2638,6 +3047,13 @@ The term "Exner function" is applied to various quantities in the literature. "Dimensionless Exner function" is the standard name of (p/p0)^(R/Cp), where p is pressure, p0 a reference pressure, R the gas constant and Cp the specific heat at constant pressure. This quantity is also the ratio of in-situ to potential temperature. Standard names for other variants can be defined on request. + + W m-2 + + + "Direct" (also known as "beam") radiation is radiation that has followed a direct path from the sun and is alternatively known as "direct insolation". Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + degree @@ -2649,28 +3065,42 @@ degrees - "direction_of_X" means direction of a vector, a bearing. "Displacement" means the change in geospatial position of an object that has moved over time. If possible, the time interval over which the motion took place should be specified using a bounds variable for the time coordinate variable. A displacement can be represented as a vector. Such a vector should however not be interpreted as describing a rectilinear, constant speed motion but merely as an indication that the start point of the vector is found at the tip of the vector after the time interval associated with the displacement variable. A displacement does not prescribe a trajectory. Sea ice displacement can be defined as a two-dimensional vector, with no vertical component. In that case, "displacement" is also the distance across the earth's surface calculated from the change in a moving object's geospatial position between the start and end of the time interval associated with the displacement variable. The "direction of displacement" is the angle between due north and the displacement vector. + The phrase "direction_of_X" means direction of a vector, a bearing. "Displacement" means the change in geospatial position of an object that has moved over time. If possible, the time interval over which the motion took place should be specified using a bounds variable for the time coordinate variable. A displacement can be represented as a vector. Such a vector should however not be interpreted as describing a rectilinear, constant speed motion but merely as an indication that the start point of the vector is found at the tip of the vector after the time interval associated with the displacement variable. A displacement does not prescribe a trajectory. Sea ice displacement can be defined as a two-dimensional vector, with no vertical component. In that case, "displacement" is also the distance across the earth's surface calculated from the change in a moving object's geospatial position between the start and end of the time interval associated with the displacement variable. The "direction of displacement" is the angle between due north and the displacement vector. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. degree 93 - "direction_of_X" means direction of a vector, a bearing. A velocity is a vector quantity. Sea ice velocity is defined as a two-dimensional vector, with no vertical component. + The phrase "direction_of_X" means direction of a vector, a bearing. A velocity is a vector quantity. Sea ice velocity is defined as a two-dimensional vector, with no vertical component. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - degree - 47 + + m + + + A measure of distance from the Earth's geocenter, commonly used in satellite tracks. + + + + m + + + The distance from the sun to the point of observation. + + + + m + - "direction_of_X" means direction of a vector, a bearing. A velocity is a vector quantity. + The great circle distance measured from the tropical cyclone center to the leading edge of displaced convection, which is defined as the closest point that exceeds a threshold brightness temperature at top of atmosphere limit. The threshold applied should be recorded in a coordinate variable having the standard name of toa_brightness_temperature. A coordinate variable with standard name of radiation_wavelength, sensor_band_central_radiation_wavelength, or radiation_frequency may be specified to indicate that the brightness temperature applies at specific wavelengths or frequencies. s-1 98 - "[horizontal_]divergence_of_X" means [horizontal] divergence of a vector X; if X does not have a vertical component then "horizontal" should be omitted. A velocity is a vector quantity. Sea ice velocity is defined as a two-dimensional vector, with no vertical component. + The phrase "[horizontal_]divergence_of_X" means [horizontal] divergence of a vector X; if X does not have a vertical component then "horizontal" should be omitted. A velocity is a vector quantity. Sea ice velocity is defined as a two-dimensional vector, with no vertical component. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. @@ -2680,6 +3110,13 @@ "[horizontal_]divergence_of_X" means [horizontal] divergence of a vector X; if X does not have a vertical component then "horizontal" should be omitted. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + m s-1 + + + A velocity is a vector quantity."Downward" indicates a vector component which is positive when directed downward (negative upward). Downward air velocity is the vertical component of the 3D air velocity vector. The standard name upward_air_velocity may be used for a vector component with the opposite sign convention. + + W m-2 @@ -2705,7 +3142,7 @@ Pa - "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Downward" indicates a vector component which is positive when directed downward (negative upward). "Downward eastward" indicates the ZX component of a tensor. A downward eastward stress is a downward flux of eastward momentum, which accelerates the lower medium eastward and the upper medium westward. + "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Downward" indicates a vector component which is positive when directed downward (negative upward). "Downward eastward" indicates the ZX component of a tensor. A downward eastward stress is a downward flux of eastward momentum, which accelerates the lower medium eastward and the upper medium westward. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. @@ -2740,7 +3177,7 @@ W m-2 - "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. @@ -2750,6 +3187,13 @@ "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + kg m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Groundwater is subsurface water below the depth of the water table. The quantity with standard name liquid_water_mass_flux_from_soil_to_groundwater is the downward flux of liquid water within soil at the depth of the water table, or downward flux from the base of the soil model if the water table depth is greater. + + Pa 125 @@ -2768,14 +3212,14 @@ Pa - "Northward" indicates a vector component which is positive when directed northward (negative southward). "Downward" indicates a vector component which is positive when directed downward (negative upward). "Downward northward" indicates the ZY component of a tensor. A downward northward stress is a downward flux of northward momentum, which accelerates the lower medium northward and the upper medium southward. + "Northward" indicates a vector component which is positive when directed northward (negative southward). "Downward" indicates a vector component which is positive when directed downward (negative upward). "Downward northward" indicates the ZY component of a tensor. A downward northward stress is a downward flux of northward momentum, which accelerates the lower medium northward and the upper medium southward. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. kg m-2 s-1 - "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. @@ -2789,203 +3233,231 @@ Pa - "x" indicates a vector component along the grid x-axis, positive with increasing x. "Downward" indicates a vector component which is positive when directed downward (negative upward). + "x" indicates a vector component along the grid x-axis, positive with increasing x. "Downward" indicates a vector component which is positive when directed downward (negative upward). "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. Pa - "y" indicates a vector component along the grid y-axis, positive with increasing y. "Downward" indicates a vector component which is positive when directed downward (negative upward). + "y" indicates a vector component along the grid y-axis, positive with increasing y. "Downward" indicates a vector component which is positive when directed downward (negative upward). "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. W m-2 - "longwave" means longwave radiation. Downwelling radiation is radiation from above. It does not mean "net downward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "longwave" means longwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. W m-2 - Downwelling radiation is radiation from above. It does not mean "net downward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "longwave" means longwave radiation. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "longwave" means longwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Clear sky" means in the absence of clouds. W m-2 sr-1 - "longwave" means longwave radiation. Downwelling radiation is radiation from above. It does not mean "net downward". Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "longwave" means longwave radiation. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. mol m-2 s-1 - Downwelling radiation is radiation from above. It does not mean "net downward". A photon flux is specified in terms of numbers of photons expressed in moles. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. A photon flux is specified in terms of numbers of photons expressed in moles. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + mol m-2 s-1 m-1 + + + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. A photon flux is specified in terms of numbers of photons expressed in moles. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. mol m-2 s-1 sr-1 - Downwelling radiation is radiation from above. It does not mean "net downward". Photon radiance is the photon flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. A photon flux is specified in terms of numbers of photons expressed in moles. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Photon radiance is the photon flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. A photon flux is specified in terms of numbers of photons expressed in moles. + + + + mol m-2 s-1 m-1 sr-1 + + + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Photon radiance is the photon flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. A photon flux is specified in terms of numbers of photons expressed in moles. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. mol m-2 s-1 - Downwelling radiation is radiation from above. It does not mean "net downward". Photon spherical irradiance is the photon flux incident on unit area of a hemispherical (or "2-pi") collector. A photon flux is specified in terms of numbers of photons expressed in moles. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Photon spherical irradiance is the photon flux incident on unit area of a hemispherical (or "2-pi") collector. Radiation incident on a 4-pi collector has a standard name referring to "omnidirectional spherical irradiance". A photon flux is specified in terms of numbers of photons expressed in moles. + + + + mol m-2 s-1 m-1 + + + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. Photon spherical irradiance is the photon flux incident on unit area of a hemispherical (or "2-pi") collector. The direction ("up/downwelling") is specified. Radiation incident on a 4-pi collector has a standard name referring to "omnidirectional spherical irradiance". A photon flux is specified in terms of numbers of photons expressed in moles. mol m-2 s-1 - Downwelling radiation is radiation from above. It does not mean "net downward". "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 300-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. A photon flux is specified in terms of numbers of photons expressed in moles. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 400-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. A photon flux is specified in terms of numbers of photons expressed in moles. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. mol m-2 s-1 sr-1 - Downwelling radiation is radiation from above. It does not mean "net downward". Photon radiance is the photon flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 300-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. A photon flux is specified in terms of numbers of photons expressed in moles. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Photon radiance is the photon flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 400-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. A photon flux is specified in terms of numbers of photons expressed in moles. mol m-2 s-1 - Downwelling radiation is radiation from above. It does not mean "net downward". "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 300-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. Photon spherical irradiance is the photon flux incident on unit area of a hemispherical (or "2-pi") collector. A photon flux is specified in terms of numbers of photons expressed in moles. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 400-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. Photon spherical irradiance is the photon flux incident on unit area of a hemispherical (or "2-pi") collector. The direction ("up/downwelling") is specified. Radiation incident on a 4-pi collector has a standard name referring to "omnidirectional spherical irradiance". A photon flux is specified in terms of numbers of photons expressed in moles. W m-2 sr-1 - Downwelling radiation is radiation from above. It does not mean "net downward". Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 300-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 400-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. W m-2 - Downwelling radiation is radiation from above. It does not mean "net downward". Radiative flux is the sum of shortwave and longwave radiative fluxes. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 300-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 400-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. W m-2 - Downwelling radiation is radiation from above. It does not mean "net downward". "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 300-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. Spherical irradiance is the radiation incident on unit area of a hemispherical (or "2-pi") collector. It is sometimes called "scalar irradiance". The direction (up/downwelling) is specified. Radiation incident on a 4-pi collector has standard names of "omnidirectional spherical irradiance". + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 400-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. Spherical irradiance is the radiation incident on unit area of a hemispherical (or "2-pi") collector. It is sometimes called "scalar irradiance". The direction (up/downwelling) is specified. Radiation incident on a 4-pi collector has standard names of "omnidirectional spherical irradiance". W m-2 sr-1 - Downwelling radiation is radiation from above. It does not mean "net downward". Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. - - W m-2 + + W m-2 m-1 sr-1 - Downwelling radiation is radiation from above. It does not mean "net downward". Radiative flux is the sum of shortwave and longwave radiative fluxes. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. - - W m-2 + + W m-2 m-1 sr-1 - "shortwave" means shortwave radiation. Downwelling radiation is radiation from above. It does not mean "net downward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. - + W m-2 - Downwelling radiation is radiation from above. It does not mean "net downward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "shortwave" means shortwave radiation. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiative flux is the sum of shortwave and longwave radiative fluxes. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - W m-2 + + W m-2 m-1 - Downwelling radiation is radiation from above. It does not mean "net downward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "shortwave" means shortwave radiation. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. - - W m-2 sr-1 + + W m-2 m-1 - "shortwave" means shortwave radiation. Downwelling radiation is radiation from above. It does not mean "net downward". Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. - - mol m-2 s-1 m-1 + + W m-2 - Downwelling radiation is radiation from above. It does not mean "net downward". A photon flux is specified in terms of numbers of photons expressed in moles. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - mol m-2 s-1 m-1 sr-1 + + W m-2 - Downwelling radiation is radiation from above. It does not mean "net downward". Photon radiance is the photon flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. A photon flux is specified in terms of numbers of photons expressed in moles. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Clear sky" means in the absence of clouds. - - mol m-2 s-1 m-1 + + W m-2 - Downwelling radiation is radiation from above. It does not mean "net downward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. Photon spherical irradiance is the photon flux incident on unit area of a hemispherical (or "2-pi") collector. A photon flux is specified in terms of numbers of photons expressed in moles. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase "assuming_condition" indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Clear sky" means in the absence of clouds. - - W m-2 m-1 sr-1 + + W m-2 - Downwelling radiation is radiation from above. It does not mean "net downward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - W m-2 m-1 sr-1 + + W m-2 - Downwelling radiation is radiation from above. It does not mean "net downward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - W m-2 m-1 + + W m-2 sr-1 - Downwelling radiation is radiation from above. It does not mean "net downward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. - - W m-2 m-1 + + W m-2 - Downwelling radiation is radiation from above. It does not mean "net downward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Spherical irradiance is the radiation incident on unit area of a hemispherical (or "2-pi") collector. It is sometimes called "scalar irradiance". The direction (up/downwelling) is specified. Radiation incident on a 4-pi collector has standard names of "omnidirectional spherical irradiance". - + W m-2 m-1 - Downwelling radiation is radiation from above. It does not mean "net downward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. Spherical irradiance is the radiation incident on unit area of a hemispherical (or "2-pi") collector. It is sometimes called "scalar irradiance". The direction (up/downwelling) is specified. Radiation incident on a 4-pi collector has standard names of "omnidirectional spherical irradiance". + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Spherical irradiance is the radiation incident on unit area of a hemispherical (or "2-pi") collector. It is sometimes called "scalar irradiance". The direction (up/downwelling) is specified. Radiation incident on a 4-pi collector has standard names of "omnidirectional spherical irradiance". A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. - - W m-2 + + 1 + + + Mole fraction is used in the construction "mole_fraction_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The construction "dry_atmosphere_mole_fraction" means that the quantity refers to the whole atmospheric column and is calculated as the total number of particles of X in the column divided by the number of dry air particles in the same column, i.e. the effect of water vapor is excluded. For localized values within the atmospheric medium, standard names including "in_air" are used. The chemical formula for carbon dioxide is CO2. + + + + 1 - Downwelling radiation is radiation from above. It does not mean "net downward". Spherical irradiance is the radiation incident on unit area of a hemispherical (or "2-pi") collector. It is sometimes called "scalar irradiance". The direction (up/downwelling) is specified. Radiation incident on a 4-pi collector has standard names of "omnidirectional spherical irradiance". + Mole fraction is used in the construction "mole_fraction_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The construction "dry_atmosphere_mole_fraction" means that the quantity refers to the whole atmospheric column and is calculated as the total number of particles of X in the column divided by the number of dry air particles in the same column, i.e. the effect of water vapor is excluded. For localized values within the atmospheric medium, standard names including "in_air" are used. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The chemical formula for methane is CH4. @@ -3009,6 +3481,20 @@ The WMO definition of sunshine is that the surface incident radiative flux from the solar beam (i.e. excluding diffuse skylight) exceeds 120 W m-2. "Duration" is the length of time for which a condition holds. + + 1 + + + "Dvorak current intensity number" indicates the ranking of tropical cyclone strength (ranging from 1.0 to 8.0, increasing with storm intensity). The current intensity (CI) number is derived using the Advanced Dvorak Technique based on satellite observations over time. The CI number maps to a maximum sustained 1-minute wind speed and is derived by applying a series of intensity constraints to previous Dvorak-calculated trends of the same storm. Reference: Olander, T. L., & Velden, C. S., The Advanced Dvorak Technique: Continued Development of an Objective Scheme to Estimate Tropical Cyclone Intensity Using Geostationary Infrared Satellite Imagery (2007). American Meteorological Society Weather and Forecasting, 22, 287-298. + + + + 1 + + + The Advanced Dvorak Technique (ADT) is used to derive a set of Dvorak Tropical numbers using an objective pattern recognition algorithm to determine the intensity of a tropical cyclone by matching observed brightness temperature patterns, maximum sustained winds and minimum sea level pressure to a set of pre-defined tropical cyclone structures. Dvorak Tropical numbers range from 1.0 to 8.0, increasing with storm intensity. Reference: Olander, T. L., & Velden, C. S., The Advanced Dvorak Technique: Continued Development of an Objective Scheme to Estimate Tropical Cyclone Intensity Using Geostationary Infrared Satellite Imagery (2007). American Meterorological Society Weather and Forecasting, 22, 287-298. + + K @@ -3041,7 +3527,21 @@ s-1 - A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Northward" indicates a vector component which is positive when directed northward (negative southward). Sea ice velocity is defined as a two-dimensional vector, with no vertical component. "component_derivative_of_X" means derivative of X with respect to distance in the component direction, which may be northward, southward, eastward, westward, x or y. The last two indicate derivatives along the axes of the grid, in the case where they are not true longitude and latitude. The named quantity is a component of the strain rate tensor for sea ice. + A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Northward" indicates a vector component which is positive when directed northward (negative southward). Sea ice velocity is defined as a two-dimensional vector, with no vertical component. "component_derivative_of_X" means derivative of X with respect to distance in the component direction, which may be northward, southward, eastward, westward, x or y. The last two indicate derivatives along the axes of the grid, in the case where they are not true longitude and latitude. The named quantity is a component of the strain rate tensor for sea ice. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. + + + + m s-1 + + + A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Flood water is water that covers land which is normally not covered by water. + + + + m s-1 + + + A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Land ice velocity is defined as a two-dimensional vector, with no vertical component. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. @@ -3062,14 +3562,14 @@ m - "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Displacement" means the change in geospatial position of an object that has moved over time. If possible, the time interval over which the motion took place should be specified using a bounds variable for the time coordinate variable. A displacement can be represented as a vector. Such a vector should however not be interpreted as describing a rectilinear, constant speed motion but merely as an indication that the start point of the vector is found at the tip of the vector after the time interval associated with the displacement variable. A displacement does not prescribe a trajectory. Sea ice displacement can be defined as a two-dimensional vector, with no vertical component. An eastward displacement is the distance calculated from the change in a moving object's longitude between the start and end of the time interval associated with the displacement variable. + "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Displacement" means the change in geospatial position of an object that has moved over time. If possible, the time interval over which the motion took place should be specified using a bounds variable for the time coordinate variable. A displacement can be represented as a vector. Such a vector should however not be interpreted as describing a rectilinear, constant speed motion but merely as an indication that the start point of the vector is found at the tip of the vector after the time interval associated with the displacement variable. A displacement does not prescribe a trajectory. Sea ice displacement can be defined as a two-dimensional vector, with no vertical component. An eastward displacement is the distance calculated from the change in a moving object's longitude between the start and end of the time interval associated with the displacement variable. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. m s-1 95 - A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Sea ice velocity is defined as a two-dimensional vector, with no vertical component. + A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Sea ice velocity is defined as a two-dimensional vector, with no vertical component. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. @@ -3086,11 +3586,18 @@ A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. + + m s-1 + + + "Eastward" indicates a vector component which is positive when directed eastward (negative westward). The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized mesoscale eddies occur on a spatial scale of many tens of kilometres and an evolutionary time of weeks. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. Parameterized mesoscale eddies are represented in ocean models using schemes such as the Gent-McWilliams scheme. + + m s-1 - "Eastward" indicates a vector component which is positive when directed eastward (negative westward). + "Eastward" indicates a vector component which is positive when directed eastward (negative westward). The "Transformed Eulerian Mean" refers to a formulation of the mean equations which incorporates some eddy terms into the definition of the mean, described in Andrews et al (1987): Middle Atmospheric Dynamics. Academic Press. @@ -3121,6 +3628,20 @@ "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) Wind shear is the derivative of wind with respect to height. + + m + + + The effective radius of a size distribution of particles, such as aerosols, cloud droplets or ice crystals,is the area weighted mean radius of particle size. It is calculated as the ratio of the third to the second moment of the particle size distribution. "cloud_top" refers to the top of the highest cloud. "condensed_water" means liquid and ice. + + + + m + + + The effective radius of a size distribution of particles, such as aerosols, cloud droplets or ice crystals, is the area weighted mean radius of particle size. It is calculated as the ratio of the third to the second moment of the particle size distribution. + + m @@ -3142,6 +3663,13 @@ The effective radius of a size distribution of particles, such as aerosols, cloud droplets or ice crystals, is the area weighted mean radius of particle size. It is calculated as the ratio of the third to the second moment of the particle size distribution. Convective cloud is that produced by the convection schemes in an atmosphere model. + + m + + + The effective radius of a size distribution of particles, such as aerosols, cloud droplets or ice crystals, is the area weighted mean radius of particle size. It is calculated as the ratio of the third to the second moment of the particle size distribution. The phrase "convective_liquid_water_cloud_top" refers to the top of the highest convective liquid water cloud. Convective cloud is that produced by the convection schemes in an atmosphere model. + + m @@ -3177,6 +3705,13 @@ The effective radius of a size distribution of particles, such as aerosols, cloud droplets or ice crystals, is the area weighted mean radius of particle size. It is calculated as the ratio of the third to the second moment of the particle size distribution. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). + + m + + + The effective radius of a size distribution of particles, such as aerosols, cloud droplets or ice crystals, is the area weighted mean radius of particle size. It is calculated as the ratio of the third to the second moment of the particle size distribution. The phrase "stratiform_liquid_water_cloud_top" refers to the top of the highest stratiform liquid water cloud. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). + + m @@ -3191,6 +3726,13 @@ The effective radius of a size distribution of particles, such as aerosols, cloud droplets or ice crystals, is the area weighted mean radius of particle size. It is calculated as the ratio of the third to the second moment of the particle size distribution. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). + + m + + + The diameter of an aerosol particle as selected by its electrical mobility. + + J m-2 @@ -3247,41 +3789,125 @@ - + kg m-2 - "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including content_of_soil_layer are used. "Soil carbon" is the organic matter present in soil quantified by the mass of carbon it contains. Soil carbon is returned to the atmosphere as the organic matter decays. The decay process takes varying amounts of time depending on the composition of the organic matter, the temperature and the availability of moisture. A carbon "soil pool" means the carbon contained in organic matter which has a characteristic period over which it decays and releases carbon into the atmosphere. "Fast soil pool" refers to the decay of organic matter in soil with a characteristic period of less than ten years under reference climate conditions of a temperature of 20 degrees Celsius and no water limitations. + "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including content_of_soil_layer are used. Soil carbon is returned to the atmosphere as the organic matter decays. The decay process takes varying amounts of time depending on the composition of the organic matter, the temperature and the availability of moisture. A carbon "soil pool" means the carbon contained in organic matter which has a characteristic period over which it decays and releases carbon into the atmosphere. "Fast soil pool" refers to the decay of organic matter in soil with a characteristic period of less than ten years under reference climate conditions of a temperature of 20 degrees Celsius and no water limitations. - - m + + Pa - "Floating ice" means any ice that is floating on water, e.g. on a sea or lake surface. "Thickness" means the vertical extent of the ice. + Various stability and convective potential indices are calculated by "lifting" a parcel of air: moving it dry adiabatically from a starting height (often the surface) to the Lifting Condensation Level, and then wet adiabatically from there to an ending height (often the top of the data/model/atmosphere). The quantities with standard names original_air_pressure_of_lifted_parcel and final_air_pressure_of_lifted_parcel are the ambient air pressure at the start and end of lifting, respectively. Air pressure is the force per unit area which would be exerted when the moving gas molecules of which the air is composed strike a theoretical surface of any orientation. - - s + + m2 - Forecast period is the time interval between the forecast reference time and the validity time. A period is an interval of time, or the time-period of an oscillation. + "X_area" means the horizontal area occupied by X within the grid cell. The extent of an individual grid cell is defined by the horizontal coordinates and any associated coordinate bounds or by a string valued auxiliary coordinate variable with a standard name of "region". "Fire area" means the area of detected biomass fire. - - s + + W - The forecast reference time in NWP is the "data time", the time of the analysis from which the forecast was made. It is not the time for which the forecast is valid; the standard name of time should be used for that time. + The product of the irradiance (the power per unit area) of a biomass fire and the corresponding fire area. A data variable containing the area affected by fire should be given the standard name fire_area. - - 1 + + K + + + The overall temperature of a fire area due to contributions from smoldering and flaming biomass. A data variable containing the area affected by fire should be given the standard name fire_area. + + + + m2 + + + "X_area" means the horizontal area occupied by X within the grid cell. The extent of an individual grid cell is defined by the horizontal coordinates and any associated coordinate bounds or by a string valued auxiliary coordinate variable with a standard name of "region". A "floating ice shelf", sometimes called a "floating ice sheet", indicates where an ice sheet extending from a land area flows over sea water. + + + + 1 + + + "X_area_fraction" means the fraction of horizontal area occupied by X. A "floating ice shelf", sometimes called a "floating ice sheet", indicates where an ice sheet extending from a land area flows over sea water. + + + + m + + + "Floating ice" means any ice that is floating on water, e.g. on a sea or lake surface. "Thickness" means the vertical extent of the ice. + + + + s + + + The quantity with standard name flood_water_duration_above_threshold is the time elapsed between the instant when the flood depth first rises above a given threshold until the time falls below the same threshold for the last time at a given point in space. If a threshold is supplied, it should be specified by associating a coordinate variable or scalar coordinate variable with the data variable and giving the coordinate variable a standard name of flood_water_thickness. The values of the coordinate variable are the threshold values for the corresponding subarrays of the data variable. If no threshold is specified, its value is taken to be zero. Flood water is water that covers land which is normally not covered by water. + + + + m s-1 + + + Speed is the magnitude of velocity. Flood water is water that covers land which is normally not covered by water. + + + + m + + + The flood_water_thickness is the vertical distance between the surface of the flood water and the surface of the solid ground, as measured at a given point in space. The standard name ground_level_altitude is used for a data variable giving the geometric height of the ground surface above the geoid. "Flood water" is water that covers land which is normally not covered by water. + + + + 1 + + + Fog means water droplets or minute ice crystals close to the surface which reduce visibility in air to less than 1000m. "X_area_fraction" means the fraction of horizontal area occupied by X. + + + + s + + + Forecast period is the time interval between the forecast reference time and the validity time. A period is an interval of time, or the time-period of an oscillation. + + + + s + + + The forecast reference time in NWP is the "data time", the time of the analysis from which the forecast was made. It is not the time for which the forecast is valid; the standard name of time should be used for that time. + + + + 1 Fractional saturation is the ratio of some measure of concentration to the saturated value of the same quantity. + + 1 + + + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The surface called "surface" means the lower boundary of the atmosphere. The quantity with standard name fraction_of_surface_downwelling_photosynthetic_radiative_flux_absorbed_by_vegetation, often called Fraction of Absorbed Photosynthetically Active Radiation (FAPAR), is the fraction of incoming solar radiation in the photosynthetically active radiation spectral region that is absorbed by a vegetation canopy. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 400-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of "radiation_wavelength". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Vegetation" means any plants e.g. trees, shrubs, grass. The term "plants" refers to the kingdom of plants in the modern classification which excludes fungi. Plants are autotrophs i.e. "producers" of biomass using carbon obtained from carbon dioxide. + + + + 1 + + + "X_area_fraction" means the fraction of horizontal area occupied by X. Sea ice area fraction is area of the sea surface occupied by sea ice. The area threshold value must be specified by supplying a coordinate variable or scalar coordinate variable with the standard name of sea_ice_area_fraction. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. + + m @@ -3296,6 +3922,13 @@ + + m-2 s-1 + + + A lightning flash is a compound event, usually consisting of several discharges. Frequency is the number of oscillations of a wave, or the number of occurrences of an event, per unit time. + + kg m-2 @@ -3307,7 +3940,7 @@ m - The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. (The volume enclosed between the geoid and the sea floor equals the mean volume of water in the ocean.) In an ocean GCM the geoid is the surface of zero depth, or the rigid lid if the model uses that approximation. A reference ellipsoid is a regular mathematical figure that approximates the irregular shape of the geoid. A number of reference ellipsoids are defined for use in the field of geodesy. + The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. (The volume enclosed between the geoid and the sea floor equals the mean volume of water in the ocean). In an ocean GCM the geoid is the surface of zero depth, or the rigid lid if the model uses that approximation. A reference ellipsoid is a regular mathematical figure that approximates the irregular shape of the geoid. A number of reference ellipsoids are defined for use in the field of geodesy. To specify which reference ellipsoid is being used, a grid_mapping variable should be attached to the data variable as described in Chapter 5.6 of the CF Convention. @@ -3331,39 +3964,95 @@ "anomaly" means difference from climatology. Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. Geopotential height is the geopotential divided by the standard acceleration due to gravity. It is numerically similar to the altitude (or geometric height) and not to the quantity with standard name height, which is relative to the surface. + + m + + + Cloud_top refers to the top of the highest cloud. Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. Geopotential height is the geopotential divided by the standard acceleration due to gravity. It is numerically similar to the altitude (or geometric height) and not to the quantity with standard name "height", which is relative to the surface. + + + + m + + + Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. Geopotential height is the geopotential divided by the standard acceleration due to gravity. It is numerically similar to the altitude (or geometric height) and not to the quantity with standard name "height", which is relative to the surface. "Volcanic_ash" means the fine-grained products of explosive volcanic eruptions, such as minerals or crystals, older fragmented rock (e.g. andesite), and glass. Particles within a volcanic ash cloud have diameters less than 2 mm. "Volcanic_ash" does not include non-volcanic dust. + + + + m s-1 + + + A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Geostrophic" indicates that geostrophic balance is assumed, i.e. that the pressure gradient force and the Coriolis force are balanced and the large scale fluid flow is parallel to the isobars. + + m s-1 - "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) "Geostrophic" indicates that geostrophic balance is assumed, i.e. that the pressure gradient force and the Coriolis force are balanced and the large scale fluid flow is parallel to the isobars. + + + + m s-1 + + + A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). "Geostrophic" indicates that geostrophic balance is assumed, i.e. that the pressure gradient force and the Coriolis force are balanced and the large scale fluid flow is parallel to the isobars. m s-1 - "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) "Geostrophic" indicates that geostrophic balance is assumed, i.e. that the pressure gradient force and the Coriolis force are balanced and the large scale fluid flow is parallel to the isobars. m - Global average sea level change is due to change in volume of the water in the ocean, caused by mass and/or density change, or to change in the volume of the ocean basins, caused by tectonics etc. It is sometimes called "eustatic", which is a term that also has other definitions. It differs from the change in the global average sea surface height relative to the centre of the Earth by the global average vertical movement of the ocean floor. Zero sea level change is an arbitrary level. + Global average sea level change is due to change in volume of the water in the ocean, caused by mass and/or density change, or to change in the volume of the ocean basins, caused by tectonics etc. It is sometimes called "eustatic", which is a term that also has other definitions. It differs from the change in the global average sea surface height relative to the centre of the Earth by the global average vertical movement of the ocean floor. Zero sea level change is an arbitrary level. Because global average sea level change quantifies the change in volume of the world ocean, it is not calculated necessarily by considering local changes in mean sea level. m - Global average steric sea level change is caused by changes in sea water density due to changes in temperature (thermosteric) and salinity (halosteric). Zero sea level change is an arbitrary level. + Global average steric sea level change is caused by changes in sea water density due to changes in temperature (thermosteric) and salinity (halosteric). This in turn results in a change in volume of the world ocean. Zero sea level change is an arbitrary level. Because global average sea level change quantifies the change in volume of the world ocean, it is not calculated necessarily by considering local changes in mean sea level. m - Global average thermosteric sea level change is the part caused by change in density due to change in temperature i.e. thermal expansion. Zero sea level change is an arbitrary level. + Global average thermosteric sea level change is the part caused by change in density due to change in temperature i.e. thermal expansion. This in turn results in a change in volume of the world ocean. Zero sea level change is an arbitrary level. Because global average sea level change quantifies the change in volume of the world ocean, it is not calculated necessarily by considering local changes in mean sea level. + + + + kg m-2 + + + "Amount" means mass per unit area. Graupel consists of heavily rimed snow particles, often called snow pellets; often indistinguishable from very small soft hail except when the size convention that hail must have a diameter greater than 5 mm is adopted. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Graupel. Hail is precipitation in the form of balls or irregular lumps of ice, often restricted by a size convention to diameters of 5 mm or more. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Hail. Standard names for "graupel_and_hail" should be used to describe data produced by models that do not distinguish between hail and graupel. For models that do distinguish between them, separate standard names for hail and graupel are available. + + + + kg m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Graupel consists of heavily rimed snow particles, often called snow pellets; often indistinguishable from very small soft hail except when the size convention that hail must have a diameter greater than 5 mm is adopted. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Graupel. Hail is precipitation in the form of balls or irregular lumps of ice, often restricted by a size convention to diameters of 5 mm or more. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Hail. Standard names for "graupel_and_hail" should be used to describe data produced by models that do not distinguish between hail and graupel. For models that do distinguish between them, separate standard names for hail and graupel are available. + + + + kg m-2 + + + "Amount" means mass per unit area. Graupel consists of heavily rimed snow particles, often called snow pellets; often indistinguishable from very small soft hail except for the size convention that hail must have a diameter greater than 5 mm. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Graupel. + + + + kg m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Graupel consists of heavily rimed snow particles, often called snow pellets; often indistinguishable from very small soft hail except when the size convention that hail must have a diameter greater than 5 mm is adopted. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Graupel. There are also separate standard names for hail. Standard names for "graupel_and_hail" should be used to describe data produced by models that do not distinguish between hail and graupel. @@ -3380,11 +4069,130 @@ Longitude is positive eastward; its units of degree_east (or equivalent) indicate this explicitly. In a latitude-longitude system defined with respect to a rotated North Pole, the standard name of grid_longitude should be used instead of longitude. Grid longitude is positive in the grid-eastward direction, but its units should be plain degree. - + + kg m-2 s-1 + + + "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Gross primary production is the rate of synthesis of biomass from inorganic precursors by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton. The producers also respire some of this biomass and the difference is "net_primary_production". "Productivity" means production per unit area. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "C" means the element carbon and "13C" is the stable isotope "carbon-13", having six protons and seven neutrons. + + + + kg m-2 s-1 + + + "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Gross primary production is the rate of synthesis of biomass from inorganic precursors by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton. The producers also respire some of this biomass and the difference is "net_primary_production". "Productivity" means production per unit area. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "C" means the element carbon and "14C" is the radioactive isotope "carbon-14", having six protons and eight neutrons and used in radiocarbon dating. + + + + kg m-2 s-1 + + + "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Gross primary production is the rate of synthesis of biomass from inorganic precursors by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton. The producers also respire some of this biomass and the difference is "net_primary_production". "Productivity" means production per unit area. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + + + + s-1 + + + The "gross rate of decrease in area fraction" is the fraction of a grid cell that transitions from a given area type per unit time, for example, as a result of land use changes. The quantity described by this standard name is a gross decrease because it includes only land where the use transitions away from the given area type and excludes land that transitions to that area type during the same period. The area type should be specified using a coordinate of scalar coordinate variable with standard name area_type. There is also a standard name for gross_rate_of_increase_in_area_fraction. + + + + s-1 + + + The "rate of increase in area fraction" is the fraction of a grid cell that transitions to a given area type per unit time, for example, as a result of land use changes. The quantity described by this standard name is a gross increase because it includes only land where the use transitions to the given area type and excludes land that transitions away from that area type during the same period. The area type should be specified using a coordinate or scalar coordinate variable with standard name area_type. There is also a standard name for gross_rate_of_decrease_in_area_fraction. + + + + m2 + + + "X_area" means the horizontal area occupied by X within the grid cell. The extent of an individual grid cell is defined by the horizontal coordinates and any associated coordinate bounds or by a string valued auxiliary coordinate variable with a standard name of "region". "Grounded ice sheet" indicates where the ice sheet rests over bedrock and is thus grounded. It excludes ice-caps, glaciers and floating ice shelves. + + + + 1 + + + "X_area_fraction" means the fraction of horizontal area occupied by X. "Grounded ice sheet" indicates where the ice sheet rests over bedrock and is thus grounded. It excludes ice-caps, glaciers and floating ice shelves. + + + + m + + + The ground_level_altitude is the geometric height of the upper boundary of the solid Earth above the geoid, which is the reference geopotential surface. The geoid is similar to mean sea level. + + + + 1 + + + "Calcareous phytoplankton" are phytoplankton that produce calcite. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Phytoplankton are algae that grow where there is sufficient light to support photosynthesis. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Irradiance" means the power per unit area (called radiative flux in other standard names), the area being normal to the direction of flow of the radiant energy. Solar irradiance is essential to the photosynthesis reaction and its presence promotes the growth of phytoplankton populations. "Growth limitation due to solar irradiance" means the ratio of the growth rate of a species population in the environment (where the amount of sunlight reaching a location may be limited) to the theoretical growth rate if there were no such limit on solar irradiance. + + + + 1 + + + Diatoms are phytoplankton with an external skeleton made of silica. Phytoplankton are algae that grow where there is sufficient light to support photosynthesis. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Irradiance" means the power per unit area (called radiative flux in other standard names), the area being normal to the direction of flow of the radiant energy. Solar irradiance is essential to the photosynthesis reaction and its presence promotes the growth of phytoplankton populations. "Growth limitation due to solar irradiance" means the ratio of the growth rate of a species population in the environment (where the amount of sunlight reaching a location may be limited) to the theoretical growth rate if there were no such limit on solar irradiance. + + + + 1 + + + In ocean modelling, diazotrophs are phytoplankton of the phylum cyanobacteria distinct from other phytoplankton groups in their ability to fix nitrogen gas in addition to nitrate and ammonium. Phytoplankton are algae that grow where there is sufficient light to support photosynthesis. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Irradiance" means the power per unit area (called radiative flux in other standard names), the area being normal to the direction of flow of the radiant energy. Solar irradiance is essential to the photosynthesis reaction and its presence promotes the growth of phytoplankton populations. "Growth limitation due to solar irradiance" means the ratio of the growth rate of a species population in the environment (where the amount of sunlight reaching a location may be limited) to the theoretical growth rate if there were no such limit on solar irradiance. + + + + 1 + + + Phytoplankton are algae that grow where there is sufficient light to support photosynthesis. "Miscellaneous phytoplankton" are all those phytoplankton that are not diatoms, diazotrophs, calcareous phytoplankton, picophytoplankton or other separately named components of the phytoplankton population. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Irradiance" means the power per unit area (called radiative flux in other standard names), the area being normal to the direction of flow of the radiant energy. Solar irradiance is essential to the photosynthesis reaction and its presence promotes the growth of phytoplankton populations. "Growth limitation due to solar irradiance" means the ratio of the growth rate of a species population in the environment (where the amount of sunlight reaching a location may be limited) to the theoretical growth rate if there were no such limit on solar irradiance. + + + + 1 + + + Picophytoplankton are phytoplankton of less than 2 micrometers in size. Phytoplankton are algae that grow where there is sufficient light to support photosynthesis. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Irradiance" means the power per unit area (called radiative flux in other standard names), the area being normal to the direction of flow of the radiant energy. Solar irradiance is essential to the photosynthesis reaction and its presence promotes the growth of phytoplankton populations. "Growth limitation due to solar irradiance" means the ratio of the growth rate of a species population in the environment (where the amount of sunlight reaching a location may be limited) to the theoretical growth rate if there were no such limit on solar irradiance. + + + + kg m-2 + + + "Amount" means mass per unit area. Hail is precipitation in the form of balls or irregular lumps of ice, often restricted by a size convention to diameters of 5 mm or more. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Hail. For diameters of less than 5 mm standard names for "graupel" should be used. Standard names for "graupel_and_hail" should be used to describe data produced by models that do not distinguish between hail and graupel. + + + kg m-2 s-1 - Gross primary productivity is the rate of synthesis of biomass per unit area from inorganic precursors by autotrophs, especially by photosynthesising plants using sunlight for energy. The producers also respire some of this biomass and the difference is net_primary_producivity. "Productivity of carbon" refers to the production of biomass expressed as the mass of carbon which it contains. "Productivity" means production per unit area. + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Hail is precipitation in the form of balls or irregular lumps of ice, often restricted by a size convention to diameters of 5 mm or more. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Hail. For diameters of less than 5 mm standard names for "graupel" should be used. Standard names for "graupel_and_hail" should be used to describe data produced by models that do not distinguish between hail and graupel. + + + + m + + + Halosteric sea level change is the part caused by change in sea water density due to change in salinity. "Mean sea level" means the time mean of sea surface elevation at a given location over an arbitrary period sufficient to eliminate the tidal signals. Zero mean sea level change is an arbitrary level. The sum of the quantities with standard names thermosteric_change_in_mean_sea_level and halosteric_change_in_mean_sea_level has the standard name steric_change_in_mean_sea_level. + + + + m + + + "Sea surface height" is a time-varying quantity. The halosteric change in sea surface height is the change in height that a water column of standard practical salinity S=35.0 would undergo when its salinity is changed to the observed value. The sum of the quantities with standard names thermosteric_change_in_sea_surface_height and halosteric_change_in_sea_surface_height is the total steric change in the water column height, which has the standard name of steric_change_in_sea_surface_height. + + + + s + + + A period is an interval of time, or the time-period of an oscillation. @@ -3395,10 +4203,10 @@ - Wm-2 + W m-2 - In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Frazil" consists of needle like crystals of ice, typically between three and four millimeters in diameter, which form as sea water begins to freeze. Salt is expelled during the freezing process and frazil ice consists of nearly pure fresh water. + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Frazil" consists of needle like crystals of ice, typically between three and four millimeters in diameter, which form as sea water begins to freeze. Salt is expelled during the freezing process and frazil ice consists of nearly pure fresh water. @@ -3419,7 +4227,7 @@ W m-2 - In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sea ice thermodynamics" refers to the addition or subtraction of mass due to surface and basal fluxes, i.e., due to melting, sublimation and fusion. + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sea ice thermodynamics" refers to the addition or subtraction of mass due to surface and basal fluxes, i.e., due to melting, sublimation and fusion. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. @@ -3436,11 +4244,32 @@ Height is the vertical distance above the surface. + + m + + + "Height_above_X" means the vertical distance above the named surface X. The "geopotential datum" is any estimated surface of constant geopotential used as a datum i.e. a reference level; for the geoid as a datum, specific standard names are available. To specify which geoid or geopotential datum is being used as a reference level, a grid_mapping variable should be attached to the data variable as described in Chapter 5.6 of the CF Convention. + + + + m + + + "Height_above_X" means the vertical distance above the named surface X. The "geopotential datum" is any estimated surface of constant geopotential used as a datum i.e. a reference level; for the geoid as a datum, specific standard names are available. To specify which geoid or geopotential datum is being used as a reference level, a grid_mapping variable should be attached to the data variable as described in Chapter 5.6 of the CF Convention. "Top of atmosphere model" means the upper boundary of the top layer of an atmosphere model. + + + + m + + + "Height_above_X" means the vertical distance above the named surface X. "Mean sea level" means the time mean of sea surface elevation at a given location over an arbitrary period sufficient to eliminate the tidal signals. + + m - Height is the vertical distance above a surface. A reference ellipsoid is a mathematical figure that approximates the geoid. The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. The ellipsoid is an approximation because the geoid is an irregular shape. A number of reference ellipsoids are defined for use in the field of geodesy. + "Height_above_X" means the vertical distance above the named surface X. A reference ellipsoid is a mathematical figure that approximates the geoid. The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. The ellipsoid is an approximation because the geoid is an irregular shape. A number of reference ellipsoids are defined for use in the field of geodesy. To specify which reference ellipsoid is being used, a grid_mapping variable should be attached to the data variable as described in Chapter 5.6 of the CF Convention. @@ -3457,32 +4286,32 @@ cloud_top refers to the top of the highest cloud. Height is the vertical distance above the surface. - - kg m-2 s-1 + + m - "Respiration carbon" refers to the rate at which biomass is respired expressed as the mass of carbon which it contains. Heterotrophic respiration is respiration by heterotrophs ("consumers"), which are organisms (including animals and decomposers) that consume other organisms or dead organic material, rather than synthesising organic material from inorganic precursors using energy from the environment (especially sunlight) as autotrophs ("producers") do. Heterotrophic respiration goes on both above and within the soil. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The "effective cloud top defined by infrared radiation" is (approximately) the geometric height above the surface that is one optical depth at infrared wavelengths (in the region of 11 micrometers) below the cloud top that would be detected by visible and lidar techniques. Reference: Minnis, P. et al 2011 CERES Edition-2 Cloud Property Retrievals Using TRMM VIRS and Terra and Aqua MODIS Data x2014; Part I: Algorithms IEEE Transactions on Geoscience and Remote Sensing, 49(11), 4374-4400. doi: http://dx.doi.org/10.1109/TGRS.2011.2144601. 1 - High type clouds are: Cirrus, Cirrostratus, Cirrocumulus. "X_area_fraction" means the fraction of horizontal area occupied by X. Cloud area fraction is also called "cloud amount" and "cloud cover". X_type_cloud_area_fraction is determined on the basis of cloud type and not on the vertical location of the cloud. + High type clouds are: Cirrus, Cirrostratus, Cirrocumulus. "X_area_fraction" means the fraction of horizontal area occupied by X. Cloud area fraction is also called "cloud amount" and "cloud cover". X_type_cloud_area_fraction is generally determined on the basis of cloud type, though Numerical Weather Prediction (NWP) models often calculate them based on the vertical location of the cloud. 1 - Scattering of radiation is its deflection from its incident path without loss of energy. Backwards scattering refers to the sum of scattering into all backward angles i.e. scattering_angle exceeding pi/2 radians. A scattering_angle should not be specified with this quantity. "Backscattering ratio" is the ratio of the quantity with standard name volume_attenuated_backwards_scattering_function_in_air to the quantity with standard name volume_attenuated_backwards_scattering_function_in_air_assuming_no_aerosol_or_cloud. "histogram_of_X[_over_Z]" means histogram (i.e. number of counts for each range of X) of variations (over Z) of X. The data variable should have an axis for X. + Scattering of radiation is its deflection from its incident path without loss of energy. Backwards scattering refers to the sum of scattering into all backward angles i.e. scattering_angle exceeding pi/2 radians. A scattering_angle should not be specified with this quantity. "Backscattering ratio" is the ratio of the quantity with standard name volume_attenuated_backwards_scattering_function_in_air to the quantity with standard name volume_attenuated_backwards_scattering_function_in_air_assuming_no_aerosol_or_cloud. "histogram_of_X[_over_Z]" means histogram (i.e. number of counts for each range of X) of variations (over Z) of X. The data variable should have an axis for X. A reference ellipsoid is a regular mathematical figure that approximates the irregular shape of the geoid. A number of reference ellipsoids are defined for use in the field of geodesy. The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. To specify which reference ellipsoid is being used, a grid_mapping variable should be attached to the data variable as described in Chapter 5.6 of the CF Convention. 1 - "Equivalent reflectivity factor" is the radar reflectivity factor that is calculated from the measured radar return power assuming the target is composed of liquid water droplets whose diameter is less than one tenth of the radar wavelength, i.e., treating the droplets as Rayleigh scatterers. The actual radar reflectivity factor would depend on the size distribution and composition of the particles within the target volume and these are often unknown. "histogram_of_X[_over_Z]" means histogram (i.e. number of counts for each range of X) of variations (over Z) of X. The data variable should have an axis for X. A reference ellipsoid is a regular mathematical figure that approximates the irregular shape of the geoid. A number of reference ellipsoids are defined for use in the field of geodesy. + "Equivalent reflectivity factor" is the radar reflectivity factor that is calculated from the measured radar return power assuming the target is composed of liquid water droplets whose diameter is less than one tenth of the radar wavelength, i.e., treating the droplets as Rayleigh scatterers. The actual radar reflectivity factor would depend on the size distribution and composition of the particles within the target volume and these are often unknown. "histogram_of_X[_over_Z]" means histogram (i.e. number of counts for each range of X) of variations (over Z) of X. The data variable should have an axis for X. A reference ellipsoid is a regular mathematical figure that approximates the irregular shape of the geoid. A number of reference ellipsoids are defined for use in the field of geodesy. The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. To specify which reference ellipsoid is being used, a grid_mapping variable should be attached to the data variable as described in Chapter 5.6 of the CF Convention. @@ -3506,13778 +4335,26838 @@ Humidity mixing ratio of a parcel of moist air is the ratio of the mass of water vapor to the mass of dry air. - - K s + + 1 - "integral_of_Y_wrt_X" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. The air temperature deficit is the air temperature threshold minus the air temperature. Its integral with respect to time is often called after its units of "degree-days". + "X_area_fraction" means the fraction of horizontal area occupied by X. Cloud area fraction is also called "cloud amount" and "cloud cover". The cloud area fraction is for the whole atmosphere column, as seen from the surface or the top of the atmosphere. The cloud area fraction in a layer of the atmosphere has the standard name cloud_area_fraction_in_atmosphere_layer. - - K s + + 1 - "integral_of_Y_wrt_X" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. The air temperature excess is the air temperature minus the air temperature threshold. Its integral with respect to time is often called after its units of "degree-days". + "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be "model_level_number", but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. "X_area_fraction" means the fraction of horizontal area occupied by X. Cloud area fraction is also called "cloud amount" and "cloud cover". - - J m-2 + + m3 s-1 - "Content" indicates a quantity per unit area. Depth is the vertical distance below the surface. The quantity with standard name integral_of_sea_ice_temperature_wrt_depth_expressed_as_heat_content is calculated relative to the heat content of ice at zero degrees Celsius, which is assumed to have a heat content of zero Joules. "integral_of_Y_wrt_X" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. + "Water" means water in all phases. "River" refers to water in the fluvial system (stream and floodplain). - - J m-2 + + - "integral_of_Y_wrt_X" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. "expressed_as_heat_content" means that this quantity is calculated as the (assumed constant) specific heat capacity times density of sea water multiplied by the integral, over the specified layer of the ocean, of the sea water potential temperature wrt depth. + An auxiliary coordinate variable with a standard name of institution contains string values which specify where the original data, with which the coordinate variable is associated, were produced. The use of institution as the standard name for an auxiliary coordinate variable permits the aggregation of data from multiple institutions within a single data file. - - K m + + kg degree_C m-2 - "integral_of_Y_wrt_X" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Depth is the vertical distance below the surface. Sea water temperature is the in situ temperature of the sea water. For observed data, depending on the period during which the observation was made, the measured in situ temperature was recorded against standard "scales". These historical scales include the International Practical Temperature Scale of 1948 (IPTS-48; 1948-1967), the International Practical Temperature Scale of 1968 (IPTS-68, Barber, 1969; 1968-1989) and the International Temperature Scale of 1990 (ITS-90, Saunders 1990; 1990 onwards). Conversion of data between these scales follows t68 = t48 - (4.4 x 10e-6) * t48(100 - t - 48); t90 = 0.99976 * t68. Observations made prior to 1948 (IPTS-48) have not been documented and therefore a conversion cannot be certain. Differences between t90 and t68 can be up to 0.01 at temperatures of 40 C and above; differences of 0.002-0.007 occur across the standard range of ocean temperatures (-10 - 30 C). The International Equation of State of Seawater 1980 (EOS-80, UNESCO, 1981) and the Practical Salinity Scale (PSS-78) were both based on IPTS-68, while the Thermodynamic Equation of Seawater 2010 (TEOS-10) is based on ITS-90. References: Barber, 1969, doi: 10.1088/0026-1394/5/2/001; UNESCO, 1981; Saunders, 1990, WOCE Newsletter, 10, September 1990. + The phrase "integral_wrt_X_of_Y" means int Y dX. To specify the limits of the integral the data variable should have an axis for X and associated coordinate bounds. If no axis for X is associated with the data variable, or no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is air the integral is assumed to be calculated over the full depth of the atmosphere. The phrase "wrt" means "with respect to". Depth is the vertical distance below the surface. The phrase "product_of_X_and_Y" means X*Y. Sea water density is the in-situ density (not the potential density). For Boussinesq models, density is the constant Boussinesq reference density, a quantity which has the standard name reference_sea_water_density_for_boussinesq_approximation. Conservative Temperature is defined as part of the Thermodynamic Equation of Seawater 2010 (TEOS-10) which was adopted in 2010 by the International Oceanographic Commission (IOC). Conservative Temperature is specific potential enthalpy (which has the standard name sea_water_specific_potential_enthalpy) divided by a fixed value of the specific heat capacity of sea water, namely cp_0 = 3991.86795711963 J kg-1 K-1. Conservative Temperature is a more accurate measure of the "heat content" of sea water, by a factor of one hundred, than is potential temperature. Because of this, it can be regarded as being proportional to the heat content of sea water per unit mass. Reference: www.teos-10.org; McDougall, 2003 doi: 10.1175/1520-0485(2003)033<0945:PEACOV>2.0.CO;2. - - Pa s + + kg degree_C m-2 - "integral_of_Y_wrt_X" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. The surface called "surface" means the lower boundary of the atmosphere. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Downward" indicates a vector component which is positive when directed downward (negative upward). "Downward eastward" indicates the ZX component of a tensor. A downward eastward stress is a downward flux of eastward momentum, which accelerates the lower medium eastward and the upper medium westward. The surface downward stress is the windstress on the surface. + The phrase "integral_wrt_X_of_Y" means int Y dX. To specify the limits of the integral the data variable should have an axis for X and associated coordinate bounds. If no axis for X is associated with the data variable, or no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is air the integral is assumed to be calculated over the full depth of the atmosphere. The phrase "wrt" means "with respect to". The phrase "product_of_X_and_Y" means X*Y. Depth is the vertical distance below the surface. Sea water density is the in-situ density (not the potential density). For Boussinesq models, density is the constant Boussinesq reference density, a quantity which has the standard name reference_sea_water_density_for_boussinesq_approximation. Potential temperature is the temperature a parcel of air or sea water would have if moved adiabatically to sea level pressure. - - W s m-2 + + 1e-3 kg m-2 - "integral_of_Y_wrt_X" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). The surface latent heat flux is the exchange of heat between the surface and the air on account of evaporation (including sublimation). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The phrase "integral_wrt_X_of_Y" means int Y dX. To specify the limits of the integral the data variable should have an axis for X and associated coordinate bounds. If no axis for X is associated with the data variable, or no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is air the integral is assumed to be calculated over the full depth of the atmosphere. The phrase "wrt" means "with respect to". The phrase "product_of_X_and_Y" means X*Y. Depth is the vertical distance below the surface. Sea water density is the in-situ density (not the potential density). For Boussinesq models, density is the constant Boussinesq reference density, a quantity which has the standard name reference_sea_water_density_for_boussinesq_approximation. Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and the units attribute should normally be given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. Practical salinity units are dimensionless. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. - - Pa s + + m - "integral_of_Y_wrt_X" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. The surface called "surface" means the lower boundary of the atmosphere. "Northward" indicates a vector component which is positive when directed northward (negative southward). "Downward" indicates a vector component which is positive when directed downward (negative upward). "Downward northward" indicates the ZY component of a tensor. A downward northward stress is a downward flux of northward momentum, which accelerates the lower medium northward and the upper medium southward. The surface downward stress is the windstress on the surface. + The phrase "integral_wrt_X_of_Y" means int Y dX. To specify the limits of the integral the data variable should have an axis for X and associated coordinate bounds. If no axis for X is associated with the data variable, or no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is air the integral is assumed to be calculated over the full depth of the atmosphere. "wrt" means with respect to. Depth is the vertical distance below the surface. Practical Salinity, S_P, is a determination of the salinity of sea water, based on its electrical conductance. The measured conductance, corrected for temperature and pressure, is compared to the conductance of a standard potassium chloride solution, producing a value on the Practical Salinity Scale of 1978 (PSS-78). This name should not be used to describe salinity observations made before 1978, or ones not based on conductance measurements. Conversion of Practical Salinity to other precisely defined salinity measures should use the appropriate formulas specified by TEOS-10. Other standard names for precisely defined salinity quantities are sea_water_absolute_salinity (S_A); sea_water_preformed_salinity (S_*), sea_water_reference_salinity (S_R); sea_water_cox_salinity (S_C), used for salinity observations between 1967 and 1977; and sea_water_knudsen_salinity (S_K), used for salinity observations between 1901 and 1966. Salinity quantities that do not match any of the precise definitions should be given the more general standard name of sea_water_salinity. Reference: www.teos-10.org; Lewis, 1980 doi:10.1109/JOE.1980.1145448. - - W s m-2 + + K m - "integral_of_Y_wrt_X" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). The surface sensible heat flux, also called "turbulent" heat flux, is the exchange of heat between the surface and the air by motion of air. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The phrase "integral_wrt_X_of_Y" means int Y dX. To specify the limits of the integral the data variable should have an axis for X and associated coordinate bounds. If no axis for X is associated with the data variable, or no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is air the integral is assumed to be calculated over the full depth of the atmosphere. "wrt" means with respect to. Depth is the vertical distance below the surface. Sea water temperature is the in situ temperature of the sea water. For observed data, depending on the period during which the observation was made, the measured in situ temperature was recorded against standard "scales". These historical scales include the International Practical Temperature Scale of 1948 (IPTS-48; 1948-1967), the International Practical Temperature Scale of 1968 (IPTS-68, Barber, 1969; 1968-1989) and the International Temperature Scale of 1990 (ITS-90, Saunders 1990; 1990 onwards). Conversion of data between these scales follows t68 = t48 - (4.4 x 10e-6) * t48(100 - t - 48); t90 = 0.99976 * t68. Observations made prior to 1948 (IPTS-48) have not been documented and therefore a conversion cannot be certain. Differences between t90 and t68 can be up to 0.01 at temperatures of 40 C and above; differences of 0.002-0.007 occur across the standard range of ocean temperatures (-10 - 30 C). The International Equation of State of Seawater 1980 (EOS-80, UNESCO, 1981) and the Practical Salinity Scale (PSS-78) were both based on IPTS-68, while the Thermodynamic Equation of Seawater 2010 (TEOS-10) is based on ITS-90. References: Barber, 1969, doi: 10.1088/0026-1394/5/2/001; UNESCO, 1981; Saunders, 1990, WOCE Newsletter, 10, September 1990. - - W s m-2 + + mol m-2 s-1 - "integral_of_Y_wrt_X" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. The surface called "surface" means the lower boundary of the atmosphere. "longwave" means longwave radiation. Downwelling radiation is radiation from above. It does not mean "net downward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The phrase "integral_wrt_X_of_Y" means int Y dX. To specify the limits of the integral the data variable should have an axis for X and associated coordinate bounds. If no axis for X is associated with the data variable, or no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is air the integral is assumed to be calculated over the full depth of the atmosphere. "wrt" means with respect to. Depth is the vertical distance below the surface."tendency_of_X" means derivative of X with respect to time. 'sea_water_alkalinity_expressed_as_mole_equivalent' is the total alkalinity equivalent concentration (including carbonate, nitrogen, silicate, and borate components). - - W s m-2 + + mol m-2 s-1 - "integral_of_Y_wrt_X" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. The surface called "surface" means the lower boundary of the atmosphere. "shortwave" means shortwave radiation. Downwelling radiation is radiation from above. It does not mean "net downward". Surface downwelling shortwave is the sum of direct and diffuse solar radiation incident on the surface, and is sometimes called "global radiation". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The phrase "integral_wrt_X_of_Y" means int Y dX. To specify the limits of the integral the data variable should have an axis for X and associated coordinate bounds. If no axis for X is associated with the data variable, or no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is air the integral is assumed to be calculated over the full depth of the atmosphere. "wrt" means with respect to. "tendency_of_X" means derivative of X with respect to time. Depth is the vertical distance below the surface. 'sea_water_alkalinity_expressed_as_mole_equivalent' is the total alkalinity equivalent concentration (including carbonate, nitrogen, silicate, and borate components). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - W s m-2 + + m2 s-1 - "integral_of_Y_wrt_X" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). "Longwave" means longwave radiation. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The phrase "integral_wrt_X_of_Y" means int Y dX. To specify the limits of the integral the data variable should have an axis for X and associated coordinate bounds. If no axis for X is associated with the data variable, or no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is air the integral is assumed to be calculated over the full depth of the atmosphere. The phrase "wrt" means "with respect to". Height is the vertical distance above the surface. The phrase "product_of_X_and_Y" means X*Y. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name "upward_air_velocity".) "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Specific humidity is the mass fraction of water vapor in (moist) air. - - W s m-2 + + m2 s-1 - "integral_of_Y_wrt_X" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). "Shortwave" means shortwave radiation. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The phrase "integral_wrt_X_of_Y" means int Y dX. To specify the limits of the integral the data variable should have an axis for X and associated coordinate bounds. If no axis for X is associated with the data variable, or no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is air the integral is assumed to be calculated over the full depth of the atmosphere. The phrase "wrt" means "with respect to". Height is the vertical distance above the surface. The phrase "product_of_X_and_Y" means X*Y. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name "upward_air_velocity".) "Northward" indicates a vector component which is positive when directed northward (negative southward). Specific humidity is the mass fraction of water vapor in (moist) air. - - W s m-2 + + K s - "integral_of_Y_wrt_X" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. "toa" means top of atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). "Shortwave" means shortwave radiation. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. The air temperature deficit is the air temperature threshold minus the air temperature, where only positive values are included in the integral. Its integral with respect to time is often called after its units of "degree-days". The air_temperature variable, which is the data variable of the integral should have a scalar coordinate variable or a size-one coordinate variable with the standard name of air_temperature_threshold, to indicate the threshold. - - W s m-2 + + K s - "integral_of_Y_wrt_X" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. "toa" means top of atmosphere. "Longwave" means longwave radiation. The TOA outgoing longwave flux is the upwelling thermal radiative flux, often called the "outgoing longwave radiation" or "OLR". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. The air temperature excess is the air temperature minus the air temperature threshold, where only positive values are included in the integral. Its integral with respect to time is often called after its units of "degree-days". The air_temperature variable, which is the data variable of the integral should have a scalar coordinate variable or a size-one coordinate variable with the standard name of air_temperature_threshold, to indicate the threshold. - - mol m-2 s-1 + + mol m-2 - Depth is the vertical distance below the surface. 'sea_water_alkalinity_expressed_as_mole_equivalent' is the total alkalinity equivalent concentration (including carbonate, nitrogen, silicate, and borate components). "tendency_of_X" means derivative of X with respect to time. "wrt" means with respect to. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". The stomatal ozone uptake is the net amount of ozone transferred into the plant during the time period over which the integral is calculated. This parameter is often called the "phytotoxic ozone dose (POD)". The chemical formula for ozone is O3. The IUPAC name for ozone is trioxygen. - - mol m-2 s-1 + + Bq s m-3 - Depth is the vertical distance below the surface. 'sea_water_alkalinity_expressed_as_mole_equivalent' is the total alkalinity equivalent concentration (including carbonate, nitrogen, silicate, and borate components). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "wrt" means with respect to. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. - - 1 + + Bq s m-3 - clisccp - "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. Cloud area fraction is also called "cloud amount" and "cloud cover". The cloud area fraction is for the whole atmosphere column, as seen from the surface or the top of the atmosphere. The cloud area fraction in a layer of the atmosphere has the standard name cloud_area_fraction_in_atmosphere_layer. The ISCCP cloud area fraction is diagnosed from atmosphere model output by the ISCCP simulator software in such a way as to be comparable with the observational diagnostics of ISCCP (the International Satellite Cloud Climatology Project). + + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Mo" means the element "molybdenum" and "101Mo" is the isotope "molybdenum-101" with a half-life of 1.01e-02 days. - - W m-2 sr-1 + + Bq s m-3 - "longwave" means longwave radiation. Radiance is the radiative flux in a particular direction, per unit of solid angle. If radiation is isotropic, the radiance is independent of direction, so the direction should not be specified. If the radiation is directionally dependent, a standard name of upwelling or downwelling radiance should be chosen instead. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tc" means the element "technetium" and "101Tc" is the isotope "technetium-101" with a half-life of 9.86e-03 days. - - W m-2 sr-1 + + Bq s m-3 - "shortwave" means shortwave radiation. Radiance is the radiative flux in a particular direction, per unit of solid angle. If radiation is isotropic, the radiance is independent of direction, so the direction should not be specified. If the radiation is directionally dependent, a standard name of upwelling or downwelling radiance should be chosen instead. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Mo" means the element "molybdenum" and "102Mo" is the isotope "molybdenum-102" with a half-life of 7.71e-03 days. - - W m-2 m-1 sr-1 + + Bq s m-3 - "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. Radiance is the radiative flux in a particular direction, per unit of solid angle. If radiation is isotropic, the radiance is independent of direction, so the direction should not be specified. If the radiation is directionally dependent, a standard name of upwelling or downwelling radiance should be chosen instead. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tc" means the element "technetium" and "102mTc" is the metastable state of the isotope "technetium-102" with a half-life of 2.98e-03 days. - - J m-2 + + Bq s m-3 - "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tc" means the element "technetium" and "102Tc" is the isotope "technetium-102" with a half-life of 6.12e-05 days. - - W m-2 - E145 + + Bq s m-3 + - + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rh" means the element "rhodium" and "103mRh" is the metastable state of the isotope "rhodium-103" with a half-life of 3.89e-02 days. - - Pa s-1 - 39 E135 - wap - "tendency_of_X" means derivative of X with respect to time. The Lagrangian tendency of a quantity is its rate of change following the motion of the fluid, also called the "material derivative" or "convective derivative". The Lagrangian tendency of air pressure, often called "omega", plays the role of the upward component of air velocity when air pressure is being used as the vertical coordinate. If the vertical air velocity is upwards, it is negative when expressed as a tendency of air pressure; downwards is positive. + + Bq s m-3 + + + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ru" means the element "ruthenium" and "103Ru" is the isotope "ruthenium-103" with a half-life of 3.95e+01 days. - - s-1 - 38 + + Bq s m-3 + - "tendency_of_X" means derivative of X with respect to time. The Lagrangian tendency of a quantity is its rate of change following the motion of the fluid, also called the "material derivative" or "convective derivative". The Lagrangian tendency of sigma plays the role of the upward component of air velocity when the atmosphere sigma coordinate (a dimensionless atmosphere vertical coordinate) is being used as the vertical coordinate. If the vertical air velocity is upwards, it is negative when expressed as a tendency of sigma; downwards is positive. See Appendix D of the CF convention for information about dimensionless vertical coordinates. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tc" means the element "technetium" and "104Tc" is the isotope "technetium-104" with a half-life of 1.25e-02 days. - - 1 - 81 - sftlf - "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. + + Bq s m-3 + + + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rh" means the element "rhodium" and "105mRh" is the metastable state of the isotope "rhodium-105" with a half-life of 4.41e-04 days. - - 1 - E172 + + Bq s m-3 + - X_binary_mask has 1 where condition X is met, 0 elsewhere. 1 = land, 0 = sea. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rh" means the element "rhodium" and "105Rh" is the isotope "rhodium-105" with a half-life of 1.48e+00 days. - - + + Bq s m-3 - A variable with the standard name of land_cover_sccs contains strings which indicate the nature of the surface, e.g. cropland_..., tree_... . These strings are standardised. Values must be combinations of classifiers from the Land Cover Classification System (LCCS; Di Gregorio A., 2005, UN Land Cover Classification System (LCCS) - Classification concepts and user manual for Software version 2; available at www.fao.org/DOCREP/003/X0596E/X0596e00.htm). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ru" means the element "ruthenium" and "105Ru" is the isotope "ruthenium-105" with a half-life of 1.85e-01 days. - - 1 + + Bq s m-3 - sftgif - "X_area_fraction" means the fraction of horizontal area occupied by X. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. + + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rh" means the element "rhodium" and "106mRh" is the metastable state of the isotope "rhodium-106" with a half-life of 9.09e-02 days. - - m s-1 + + Bq s m-3 - "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. The land ice basal melt rate is the rate at which ice is lost per unit area at the base of the ice. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rh" means the element "rhodium" and "106Rh" is the isotope "rhodium-106" with a half-life of 3.46e-04 days. - - m s-1 + + Bq s m-3 - A velocity is a vector quantity. "x" indicates a vector component along the grid x-axis, positive with increasing x. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ru" means the element "ruthenium" and "106Ru" is the isotope "ruthenium-106" with a half-life of 3.66e+02 days. - - m s-1 + + Bq s m-3 - A velocity is a vector quantity. "y" indicates a vector component along the grid y-axis, positive with increasing y. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pd" means the element "palladium" and "107mPd" is the metastable state of the isotope "palladium-107" with a half-life of 2.47e-04 days. - - m s-1 + + Bq s m-3 - "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. The land ice calving rate is the rate at which ice is lost per unit area through calving into the ocean. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pd" means the element "palladium" and "107Pd" is the isotope "palladium-107" with a half-life of 2.37e+09 days. - - m s-1 + + Bq s m-3 - "lwe" means liquid water equivalent. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. The land ice basal melt rate is the rate at which ice is lost per unit area at the base of the ice. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rh" means the element "rhodium" and "107Rh" is the isotope "rhodium-107" with a half-life of 1.51e-02 days. - - m s-1 + + Bq s m-3 - "lwe" means liquid water equivalent. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. The land ice calving rate is the rate at which ice is lost per unit area through calving into the ocean. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ag" means the element "silver" and "109mAg" is the metastable state of the isotope "silver-109" with a half-life of 4.58e-04 days. - - m s-1 + + Bq s m-3 - "lwe" means liquid water equivalent. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. Specific mass balance means the net rate at which ice is added per unit area at the land ice surface. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pd" means the element "palladium" and "109Pd" is the isotope "palladium-109" with a half-life of 5.61e-01 days. - - 1 + + Bq s m-3 - "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ag" means the element "silver" and "110mAg" is the metastable state of the isotope "silver-110" with a half-life of 2.70e+02 days. - - m s-1 + + Bq s m-3 - "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. Specific mass balance means the net rate at which ice is added per unit area at the land ice surface. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ag" means the element "silver" and "111Ag" is the isotope "silver-111" with a half-life of 7.50e+00 days. - - K + + Bq s m-3 - "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ag" means the element "silver" and "111mAg" is the metastable state of the isotope "silver-111" with a half-life of 8.56e-04 days. - - m + + Bq s m-3 - "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. "Thickness" means the vertical extent of a layer. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cd" means the element "cadmium" and "111mCd" is the metastable state of the isotope "cadmium-111" with a half-life of 3.39e-02 days. - - m s-1 + + Bq s m-3 - A velocity is a vector quantity. "x" indicates a vector component along the grid x-axis, positive with increasing x. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. The vertical mean land ice velocity is the average from the bedrock to the surface of the ice. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pd" means the element "palladium" and "111mPd" is the metastable state of the isotope "palladium-111" with a half-life of 2.29e-01 days. - - m s-1 + + Bq s m-3 - A velocity is a vector quantity. "y" indicates a vector component along the grid y-axis, positive with increasing y. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. The vertical mean land ice velocity is the average from the bedrock to the surface of the ice. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pd" means the element "palladium" and "111Pd" is the isotope "palladium-111" with a half-life of 1.53e-02 days. - - m s-1 + + Bq s m-3 - A velocity is a vector quantity. "x" indicates a vector component along the grid x-axis, positive with increasing x. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ag" means the element "silver" and "112Ag" is the isotope "silver-112" with a half-life of 1.30e-01 days. - - m s-1 + + Bq s m-3 - A velocity is a vector quantity. "y" indicates a vector component along the grid y-axis, positive with increasing y. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pd" means the element "palladium" and "112Pd" is the isotope "palladium-112" with a half-life of 8.37e-01 days. - - degree_north + + Bq s m-3 - latitude - Latitude is positive northward; its units of degree_north (or equivalent) indicate this explicitly. In a latitude-longitude system defined with respect to a rotated North Pole, the standard name of grid_latitude should be used instead of latitude. Grid latitude is positive in the grid-northward direction, but its units should be plain degree. + + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ag" means the element "silver" and "113Ag" is the isotope "silver-113" with a half-life of 2.21e-01 days. - - 1 + + Bq s m-3 - "X_area" means the horizontal area occupied by X within the grid cell. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cd" means the element "cadmium" and "113Cd" is the isotope "cadmium-113" with a half-life of 3.29e+18 days. - - kg m-2 + + Bq s m-3 - "Content" indicates a quantity per unit area. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ag" means the element "silver" and "113mAg" is the metastable state of the isotope "silver-113" with a half-life of 7.64e-04 days. - - kg m-2 + + Bq s m-3 - "Content" indicates a quantity per unit area. Permafrost is soil or rock that has remained at a temperature at or below zero degrees Celsius throughout the seasonal cycle for two or more years. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cd" means the element "cadmium" and "113mCd" is the metastable state of the isotope "cadmium-113" with a half-life of 5.31e+03 days. - - kg m-2 + + Bq s m-3 - "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Quantities defined for a soil layer must have a vertical coordinate variable with boundaries indicating the extent of the layer(s). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "113mIn" is the metastable state of the isotope "indium-113" with a half-life of 6.92e-02 days. - - kg m-2 + + Bq s m-3 - "Content" indicates a quantity per unit area. The surface called "surface" means the lower boundary of the atmosphere. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ag" means the element "silver" and "115Ag" is the isotope "silver-115" with a half-life of 1.46e-02 days. - - kg m-2 + + Bq s m-3 - "Content" indicates a quantity per unit area. "Litter carbon" is dead inorganic material in or above the soil quantified as the mass of carbon which it contains. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cd" means the element "cadmium" and "115Cd" is the isotope "cadmium-115" with a half-life of 2.23e+00 days. - - kg m-2 s-1 + + Bq s m-3 - "Litter carbon" is dead inorganic material in or above the soil quantified as the mass of carbon which it contains. The litter carbon flux is the rate of production of litter. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "115In" is the isotope "indium-115" with a half-life of 1.86e+18 days. - - degree_east + + Bq s m-3 - longitude - Longitude is positive eastward; its units of degree_east (or equivalent) indicate this explicitly. In a latitude-longitude system defined with respect to a rotated North Pole, the standard name of grid_longitude should be used instead of longitude. Grid longitude is positive in the grid-eastward direction, but its units should be plain degree. + + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ag" means the element "silver" and "115mAg" is the metastable state of the isotope "silver-115" with a half-life of 1.97e-04 days. - - 1 + + Bq s m-3 - Low type clouds are: Stratus, Stratocumulus, Cumulus, Cumulonimbus. "X_area_fraction" means the fraction of horizontal area occupied by X. Cloud area fraction is also called "cloud amount" and "cloud cover". X_type_cloud_area_fraction is determined on the basis of cloud type and not on the vertical location of the cloud. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cd" means the element "cadmium" and "115mCd" is the metastable state of the isotope "cadmium-115" with a half-life of 4.46e+01 days. - - m s-1 + + Bq s m-3 - "lwe" means liquid water equivalent. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "115mIn" is the metastable state of the isotope "indium-115" with a half-life of 1.87e-01 days. - - m s-1 + + Bq s m-3 - "lwe" means liquid water equivalent. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "116In" is the isotope "indium-116" with a half-life of 1.64e-04 days. - - m s-1 + + Bq s m-3 - "lwe" means liquid water equivalent. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "116mIn" is the metastable state of the isotope "indium-116" with a half-life of 3.77e-02 days. - - m s-1 + + Bq s m-3 - "lwe" means liquid water equivalent. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cd" means the element "cadmium" and "117Cd" is the isotope "cadmium-117" with a half-life of 1.08e-01 days. - - m s-1 + + Bq s m-3 - Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. "lwe" means liquid water equivalent. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "117In" is the isotope "indium-117" with a half-life of 3.05e-02 days. - - m s-1 + + Bq s m-3 - Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. "lwe" means liquid water equivalent. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cd" means the element "cadmium" and "117mCd" is the metastable state of the isotope "cadmium-117" with a half-life of 1.42e-01 days. - - m - E137 + + Bq s m-3 + - "lwe" means liquid water equivalent. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Atmosphere water vapor content is sometimes referred to as "precipitable water", although this term does not imply the water could all be precipitated. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "117mIn" is the metastable state of the isotope "indium-117" with a half-life of 8.08e-02 days. - - m + + Bq s m-3 - "lwe" means liquid water equivalent. "Amount" means mass per unit area. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. "Water" means water in all phases, including frozen i.e. ice and snow. "Canopy" means the plant or vegetation canopy. The canopy water is the water on the canopy. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "117mSn" is the metastable state of the isotope "tin-117" with a half-life of 1.40e+01 days. - - m - E143 + + Bq s m-3 + - "lwe" means liquid water equivalent. "Amount" means mass per unit area. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cd" means the element "cadmium" and "118Cd" is the isotope "cadmium-118" with a half-life of 3.49e-02 days. - - m + + Bq s m-3 - "lwe" means liquid water equivalent. "Amount" means mass per unit area. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "118In" is the isotope "indium-118" with a half-life of 5.77e-05 days. - - m + + Bq s m-3 - "frozen_water" means ice. "lwe" means liquid water equivalent. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Quantities defined for a soil layer must have a vertical coordinate variable with boundaries indicating the extent of the layer(s). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "118mIn" is the metastable state of the isotope "indium-118" with a half-life of 3.05e-03 days. - - m + + Bq s m-3 - "lwe" means liquid water equivalent. "moisture" means water in all phases contained in soil. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Quantities defined for a soil layer must have a vertical coordinate variable with boundaries indicating the extent of the layer(s). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "119In" is the isotope "indium-119" with a half-life of 1.74e-03 days. - - m + + Bq s m-3 - "lwe" means liquid water equivalent. "Amount" means mass per unit area. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "119mIn" is the metastable state of the isotope "indium-119" with a half-life of 1.25e-02 days. - - m - E144 + + Bq s m-3 + - "lwe" means liquid water equivalent. "Amount" means mass per unit area. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "119mSn" is the metastable state of the isotope "tin-119" with a half-life of 2.45e+02 days. - - m - E140 + + Bq s m-3 + - "lwe" means liquid water equivalent. "moisture" means water in all phases contained in soil. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including content_of_soil_layer are used. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "C" means the element "carbon" and "11C" is the isotope "carbon-11" with a half-life of 1.41e-02 days. - - m - E142 + + Bq s m-3 + - "Amount" means mass per unit area. "lwe" means liquid water equivalent. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "121mSn" is the metastable state of the isotope "tin-121" with a half-life of 1.82e+04 days. - - m + + Bq s m-3 - "Amount" means mass per unit area. "lwe" means liquid water equivalent. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "121Sn" is the isotope "tin-121" with a half-life of 1.12e+00 days. - - m - E141 + + Bq s m-3 + - The surface called "surface" means the lower boundary of the atmosphere. "lwe" means liquid water equivalent. "Amount" means mass per unit area. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. Surface amount refers to the amount on the ground, excluding that on the plant or vegetation canopy. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "123mSn" is the metastable state of the isotope "tin-123" with a half-life of 2.78e-02 days. - - m - E182 + + Bq s m-3 + - "lwe" means liquid water equivalent. "Amount" means mass per unit area. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. "Water" means water in all phases. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "123Sn" is the isotope "tin-123" with a half-life of 1.29e+02 days. - - m s-1 + + Bq s m-3 - "lwe" means liquid water equivalent. "Water" means water in all phases. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "124mSb" is the metastable state of the isotope "antimony-124" with a half-life of 1.41e-02 days. - - m + + Bq s m-3 - The quantity with standard name magnitude_of_derivative_of_position_wrt_model_level_number (known in differential geometry as a "scale factor") is | (dr/dk)ij|, where r(i,j,k) is the vector 3D position of the point with coordinate indices (i,j,k). It is a measure of the gridblock spacing in the z-direction. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "124Sb" is the isotope "antimony-124" with a half-life of 6.03e+01 days. - - m + + Bq s m-3 - The quantity with standard name magnitude_of_derivative_of_position_wrt_x_coordinate_index (known in differential geometry as a "scale factor") is | (dr/di)jk|, where r(i,j,k) is the vector 3D position of the point with coordinate indices (i,j,k). It is a measure of the gridblock spacing in the x-direction. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "125mTe" is the metastable state of the isotope "tellurium-125" with a half-life of 5.81e+01 days. - - m + + Bq s m-3 - The quantity with standard name magnitude_of_derivative_of_position_wrt_y_coordinate_index (known in differential geometry as a "scale factor") is | (dr/dj)ik|, where r(i,j,k) is the vector 3D position of the point with coordinate indices (i,j,k). It is a measure of the gridblock spacing in the y-direction. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "125Sb" is the isotope "antimony-125" with a half-life of 9.97e+02 days. - - m + + Bq s m-3 - "magnitude_of_X" means magnitude of a vector X. 'Displacement' means the change in geospatial position of an object that has moved over time. If possible, the time interval over which the motion took place should be specified using a bounds variable for the time coordinate variable. A displacement can be represented as a vector. Such a vector should however not be interpreted as describing a rectilinear, constant speed motion but merely as an indication that the start point of the vector is found at the tip of the vector after the time interval associated with the displacement variable. A displacement does not prescribe a trajectory. Sea ice displacement can be defined as a two-dimensional vector, with no vertical component. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "125Sn" is the isotope "tin-125" with a half-life of 9.65e+00 days. - - Pa + + Bq s m-3 - The surface called "surface" means the lower boundary of the atmosphere. "magnitude_of_X" means magnitude of a vector X. "Downward" indicates a vector component which is positive when directed downward (negative upward). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "126mSb" is the metastable state of the isotope "antimony-126" with a half-life of 1.32e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for acetic_acid is CH3COOH. The IUPAC name for acetic acid is ethanoic acid. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "126Sb" is the isotope "antimony-126" with a half-life of 1.24e+01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for aceto-nitrile is CH3CN. The IUPAC name for aceto-nitrile is ethanenitrile. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "126Sn" is the isotope "tin-126" with a half-life of 3.65e+07 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Alkanes are saturated hydrocarbons, i.e. they do not contain any chemical double bonds. Alkanes contain only hydrogen and carbon combined in the general proportions C(n)H(2n+2); "alkanes" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual alkane species, e.g., methane and ethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "127mTe" is the metastable state of the isotope "tellurium-127" with a half-life of 1.09e+02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Alkenes are unsaturated hydrocarbons as they contain chemical double bonds between adjacent carbon atoms. Alkenes contain only hydrogen and carbon combined in the general proportions C(n)H(2n); "alkenes" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual alkene species, e.g., ethene and propene. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "127Sb" is the isotope "antimony-127" with a half-life of 3.80e+00 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for alpha_hexachlorocyclohexane is C6H6Cl6. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "127Sn" is the isotope "tin-127" with a half-life of 8.84e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for alpha_pinene is C10H16. The IUPAC name for alpha-pinene is (1S,5S)-2,6,6-trimethylbicyclo[3.1.1]hept-2-ene. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "127Te" is the isotope "tellurium-127" with a half-life of 3.91e-01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ammonia is NH3. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "128mSb" is the metastable state of the isotope "antimony-128" with a half-life of 7.23e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The chemical formula for ammonium is NH4. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "128Sb" is the isotope "antimony-128" with a half-life of 3.75e-01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "nmvoc" means non methane volatile organic compounds. "Anthropogenic" means influenced, caused, or created by human activity. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "128Sn" is the isotope "tin-128" with a half-life of 4.09e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Aromatic compounds in organic chemistry are compounds that contain at least one benzene ring of six carbon atoms joined by alternating single and double covalent bonds. The simplest aromatic compound is benzene itself. In standard names "aromatic_compounds" is the term used to describe the group of aromatic chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual aromatic species, e.g. benzene and xylene. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "129I" is the isotope "iodine-129" with a half-life of 5.81e+09 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for atomic bromine is Br. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "129mTe" is the metastable state of the isotope "tellurium-129" with a half-life of 3.34e+01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for atomic chlorine is Cl. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Xe" means the element "xenon" and "129mXe" is the metastable state of the isotope "xenon-129" with a half-life of 8.02e+00 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for atomic nitrogen is N. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "129Sb" is the isotope "antimony-129" with a half-life of 1.81e-01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "129Te" is the isotope "tellurium-129" with a half-life of 4.86e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for beta_pinene is C10H16. The IUPAC name for beta-pinene is (1S,5S)-6,6-dimethyl-2-methylenebicyclo[3.1.1]heptane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "130I" is the isotope "iodine-130" with a half-life of 5.18e-01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "nmvoc" means non methane volatile organic compounds. "Biogenic" means influenced, caused, or created by natural processes. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "130mI" is the metastable state of the isotope "iodine-130" with a half-life of 6.17e-03 days. - - kg m-3 + + Bq s m-3 - 'Mass concentration' means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "130mSb" is the metastable state of the isotope "antimony-130" with a half-life of 4.58e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "130Sb" is the isotope "antimony-130" with a half-life of 2.57e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for bromine chloride is BrCl. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "130Sn" is the isotope "tin-130" with a half-life of 2.57e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for bromine monoxide is BrO. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "131I" is the isotope "iodine-131" with a half-life of 8.07e+00 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for bromine nitrate is BrONO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "131mTe" is the metastable state of the isotope "tellurium-131" with a half-life of 1.25e+00 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Brox" describes a family of chemical species consisting of inorganic bromine compounds with the exception of hydrogen bromide (HBr) and bromine nitrate (BrONO2). "Brox" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of source gases containing bromine (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. Standard names that use the term "inorganic_bromine" are used for quantities that contain all inorganic bromine species including HCl and ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Xe" means the element "xenon" and "131mXe" is the metastable state of the isotope "xenon-131" with a half-life of 1.18e+01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "131Sb" is the isotope "antimony-131" with a half-life of 1.60e-02 days. - - kg m-3 + + Bq s m-3 - 'Mass concentration' means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B containedin A, neglecting all other chemical constituents of A. Chlorophyll is the green pigment found in most plants, algae and cyanobacteria. The presence of chlorophyll is essential for photosynthesis to take place. There are five different forms of chlorophyll that occur naturally. All contain a chlorin ring (chemical formula C20H16N4) which gives the green pigment and a side chain whose structure varies. The naturally occurring forms of chlorophyll contain between 35 and 55 carbon atoms. 'Calcareous phytoplankton' are phytoplankton that produce calcite. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "131Te" is the isotope "tellurium-131" with a half-life of 1.74e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for carbon dioxide is CO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "132I" is the isotope "iodine-132" with a half-life of 9.60e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of carbon monoxide is CO. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "132Te" is the isotope "tellurium-132" with a half-life of 3.25e+00 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of carbon tetrachloride is CCl4. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "133I" is the isotope "iodine-133" with a half-life of 8.71e-01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC113a CCl3CF3. The IUPAC name for CFC113a is 1,1,1-trichloro-2,2,2-trifluoro-ethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "133mI" is the metastable state of the isotope "iodine-133" with a half-life of 1.04e-04 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC113 is CCl2FCClF2. The IUPAC name for CFC113 is 1,1,2-trichloro-1,2,2-trifluoro-ethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "133mTe" is the metastable state of the isotope "tellurium-133" with a half-life of 3.84e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC114 is CClF2CClF2. The IUPAC name for CFC114 is 1,2-dichloro-1,1,2,2-tetrafluoro-ethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Xe" means the element "xenon" and "133mXe" is the metastable state of the isotope "xenon-133" with a half-life of 2.26e+00 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC115 is CClF2CF3. The IUPAC name for CFC115 is 1-chloro-1,1,2,2,2-pentafluoro-ethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "133Te" is the isotope "tellurium-133" with a half-life of 8.68e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC11 is CFCl3. The IUPAC name fof CFC11 is trichloro-fluoro-methane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Xe" means the element "xenon" and "133Xe" is the isotope "xenon-133" with a half-life of 5.28e+00 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for CFC12 is CF2Cl2. The IUPAC name for CFC12 is dichloro-difluoro-methane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cs" means the element "cesium" and "134Cs" is the isotope "cesium-134" with a half-life of 7.50e+02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for chlorine dioxide is OClO. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "134I" is the isotope "iodine-134" with a half-life of 3.61e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for chlorine monoxide is ClO. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cs" means the element "cesium" and "134mCs" is the metastable state of the isotope "cesium-134" with a half-life of 1.21e-01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for chlorine nitrate is ClONO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "134mI" is the metastable state of the isotope "iodine-134" with a half-life of 2.50e-03 days. - - kg m-3 + + Bq s m-3 - 'Mass concentration' means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Chlorophyll is the green pigment found inmost plants, algae and cyanobacteria. The presence of chlorophyll is essential for photosynthesis to take place. There are five different forms of chlorophyll that occur naturally. All contain a chlorin ring (chemical formula C20H16N4) which gives the green pigment and a side chain whose structure varies. The naturally occurring forms of chlorophyll contain between 35 and 55 carbon atoms. Chlorophyll-a is the most commonly occurring form of natural chlorophyll. The chemical formula of chlorophyll-a is C55H72O5N4Mg. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Xe" means the element "xenon" and "134mXe" is the metastable state of the isotope "xenon-134" with a half-life of 3.36e-06 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Chlorophyll is the green pigment found in most plants, algae and cyanobacteria. The presence of chlorophyll is essential for photosynthesis to take place. There are five different forms of chlorophyll that occur naturally. All contain a chlorin ring (chemical formula C20H16N4) which gives the green pigment and a side chain whose structure varies. The naturally occurring forms of chlorophyll contain between 35 and 55 carbon atoms. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "134Te" is the isotope "tellurium-134" with a half-life of 2.92e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction "mass_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". Cloud droplets are spherical and typically a few micrometers to a few tens of micrometers in diameter. An upper limit of 0.2 mm diameter is sometimes used to distinguish between cloud droplets and drizzle drops, but in active cumulus clouds strong updrafts can maintain much larger cloud droplets. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cs" means the element "cesium" and "135Cs" is the isotope "cesium-135" with a half-life of 8.39e+08 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Clox" describes a family of chemical species consisting of inorganic chlorine compounds with the exception of hydrogen chloride (HCl) and chlorine nitrate (ClONO2). "Clox" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Inorganic chlorine", sometimes referred to as Cly, describes a family of chemical species which result from the degradation of source gases containing chlorine (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as seasalt and other aerosols. Standard names that use the term "inorganic_chlorine" are used for quantities that contain all inorganic chlorine species including HCl and ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "135I" is the isotope "iodine-135" with a half-life of 2.79e-01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. Coarse mode aerosol is aerosol having a diameter of more than 1 micrometer. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ba" means the element "barium" and "135mBa" is the metastable state of the isotope "barium-135" with a half-life of 1.20e+00 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. Condensed water means liquid and ice. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cs" means the element "cesium" and "135mCs" is the metastable state of the isotope "cesium-135" with a half-life of 3.68e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Diatoms are single-celled phytoplankton with an external skeleton made of silica. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Xe" means the element "xenon" and "135mXe" is the metastable state of the isotope "xenon-135" with a half-life of 1.08e-02 days. - - kg m-3 + + Bq s m-3 - 'Mass concentration' means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B containedin A, neglecting all other chemical constituents of A. Chlorophyll is the green pigment found in most plants, algae and cyanobacteria. The presence of chlorophyll is essential for photosynthesis to take place. There are five different forms of chlorophyll that occur naturally. All contain a chlorin ring (chemical formula C20H16N4) which gives the green pigment and a side chain whose structure varies. The naturally occurring forms of chlorophyll contain between 35 and 55 carbon atoms. Diatoms are single-celled phytoplankton with an external skeleton made of silica. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Xe" means the element "xenon" and "135Xe" is the isotope "xenon-135" with a half-life of 3.82e-01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Diatoms are single-celled phytoplankton with an external skeleton made of silica. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cs" means the element "cesium" and "136Cs" is the isotope "cesium-136" with a half-life of 1.30e+01 days. - - kg m-3 + + Bq s m-3 - 'Mass concentration' means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B containedin A, neglecting all other chemical constituents of A. Chlorophyll is the green pigment found in most plants, algae and cyanobacteria. The presence of chlorophyll is essential for photosynthesis to take place. There are five different forms of chlorophyll that occur naturally. All contain a chlorin ring (chemical formula C20H16N4) which gives the green pigment and a side chain whose structure varies. The naturally occurring forms of chlorophyll contain between 35 and 55 carbon atoms. In ocean modelling, diazotrophs are phytoplankton of the phylum cyanobacteria distinct from other phytoplankton groups in their ability to fix nitrogen gas in addition to nitrate and ammonium. Phytoplankton are autotrophic prokaryotic or eukaryotic organisms that live near the water surface where there is sufficient light to support photosynthesis. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cs" means the element "cesium" and "137Cs" is the isotope "cesium-137" with a half-life of 1.10e+04 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for dichlorine peroxide is Cl2O2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ba" means the element "barium" and "137mBa" is the metastable state of the isotope "barium-137" with a half-life of 1.77e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for dimethyl sulfide is (CH3)2S. Dimethyl sulfide is sometimes referred to as DMS. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Xe" means the element "xenon" and "137Xe" is the isotope "xenon-137" with a half-life of 2.71e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for dinitrogen pentoxide is N2O5. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cs" means the element "cesium" and "138Cs" is the isotope "cesium-138" with a half-life of 2.23e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction "mass_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Drizzle" means drops of water falling through the atmosphere that have a diameter typically in the range 0.2-0.5 mm. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Xe" means the element "xenon" and "138Xe" is the isotope "xenon-138" with a half-life of 9.84e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ba" means the element "barium" and "139Ba" is the isotope "barium-139" with a half-life of 5.77e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "N" means the element "nitrogen" and "13N" is the isotope "nitrogen-13" with a half-life of 6.92e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethanol is C2H5OH. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ba" means the element "barium" and "140Ba" is the isotope "barium-140" with a half-life of 1.28e+01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "La" means the element "lanthanum" and "140La" is the isotope "lanthanum-140" with a half-life of 1.76e+00 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ce" means the element "cerium" and "141Ce" is the isotope "cerium-141" with a half-life of 3.30e+01 days. - - kg m-3 + + Bq s m-3 - 'Mass concentration' means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. 'Flagellates' are a class of single celled organisms that use a flagellum (whip-like structure) for feeding and locomotion. Some flagellates can photosynthesize and others feed on bacteria, with a few flagellatescapable of both. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "La" means the element "lanthanum" and "141La" is the isotope "lanthanum-141" with a half-life of 1.61e-01 days. - - kg m-3 + + Bq s m-3 - 'Mass concentration' means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. 'Flagellates' are a class of single celled organisms that use a flagellum (whip-like structure) for feeding and locomotion. Some flagellates can photosynthesize and others feed on bacteria, with a few flagellatescapable of both. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ce" means the element "cerium" and "142Ce" is the isotope "cerium-142" with a half-life of 1.82e+19 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "La" means the element "lanthanum" and "142La" is the isotope "lanthanum-142" with a half-life of 6.42e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for formic acid is HCOOH. The IUPAC name for formic acid is methanoic acid. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pr" means the element "praseodymium" and "142mPr" is the metastable state of the isotope "praseodymium-142" with a half-life of 1.01e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Divalent mercury" means all compounds in which the mercury has two binding sites to other ion(s) in a salt or to other atom(s) in a molecule. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pr" means the element "praseodymium" and "142Pr" is the isotope "praseodymium-142" with a half-life of 7.94e-01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for mercury is Hg. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ce" means the element "cerium" and "143Ce" is the isotope "cerium-143" with a half-life of 1.37e+00 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halon1202 is CBr2F2. The IUPAC name for halon1202 is dibromo-difluoro-methane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "La" means the element "lanthanum" and "143La" is the isotope "lanthanum-143" with a half-life of 9.72e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halon1211 is CBrClF2. The IUPAC name for halon1211 is bromo-chloro-difluoro-methane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pr" means the element "praseodymium" and "143Pr" is the isotope "praseodymium-143" with a half-life of 1.36e+01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halon1301 is CBrF3. The IUPAC name for halon1301 is bromo-trifluoro-methane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ce" means the element "cerium" and "144Ce" is the isotope "cerium-144" with a half-life of 2.84e+02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halo2402 is C2Br2F4. The IUPAC name for halon2402 is 1,2-dibromo-1,1,2,2-tetrafluoro-ethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pr" means the element "praseodymium" and "144mPr" is the metastable state of the isotope "praseodymium-144" with a half-life of 4.98e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hcc140a is CH3CCl3. The IUPAC name for hcc140a is 1,1,1-trichloro-ethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nd" means the element "neodymium" and "144Nd" is the isotope "neodymium-144" with a half-life of 7.64e+17 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for HCFC141b is CH3CCl2F. The IUPAC name for HCFC141b is 1,1-dichloro-1-fluoroethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pr" means the element "praseodymium" and "144Pr" is the isotope "praseodymium-144" with a half-life of 1.20e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for HCFC142b is CH3CClF2. The IUPAC name for HCFC142b is 1-chloro-1,1-difluoroethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pr" means the element "praseodymium" and "145Pr" is the isotope "praseodymium-145" with a half-life of 2.49e-01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for HCFC22 is CHClF2. The IUPAC name for HCFC22 is chloro-difluoro-methane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ce" means the element "cerium" and "146Ce" is the isotope "cerium-146" with a half-life of 9.86e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hexachlorobiphenyl is C12H4Cl6. This structure of this species consists of two linked benzene rings, each of which is additionally bonded to three chlorine atoms. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pr" means the element "praseodymium" and "146Pr" is the isotope "praseodymium-146" with a half-life of 1.68e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "HOx" means a combination of two radical species containing hydrogen and oxygen: OH and HO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nd" means the element "neodymium" and "147Nd" is the isotope "neodymium-147" with a half-life of 1.10e+01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen bromide is HBr. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pm" means the element "promethium" and "147Pm" is the isotope "promethium-147" with a half-life of 9.57e+02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen chloride is HCl. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pr" means the element "praseodymium" and "147Pr" is the isotope "praseodymium-147" with a half-life of 8.33e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen cyanide is HCN. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sm" means the element "samarium" and "147Sm" is the isotope "samarium-147" with a half-life of 3.91e+13 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen peroxide is H2O2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pm" means the element "promethium" and "148mPm" is the metastable state of the isotope "promethium-148" with a half-life of 4.14e+01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for the hydroperoxyl radical is HO2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pm" means the element "promethium" and "148Pm" is the isotope "promethium-148" with a half-life of 5.38e+00 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for the hydroxyl radical is OH. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sm" means the element "samarium" and "148Sm" is the isotope "samarium-148" with a half-life of 2.92e+18 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hypobromous acid is HOBr. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nd" means the element "neodymium" and "149Nd" is the isotope "neodymium-149" with a half-life of 7.23e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hypochlorous acid is HOCl. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pm" means the element "promethium" and "149Pm" is the isotope "promethium-149" with a half-life of 2.21e+00 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of source gases containing bromine (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. "Inorganic bromine" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names that use the term "brox" are used for quantities that contain all inorganic bromine species except HBr and BrONO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sm" means the element "samarium" and "149Sm" is the isotope "samarium-149" with a half-life of 3.65e+18 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Inorganic chlorine", sometimes referred to as Cly, describes a family of chemical species which result from the degradation of source gases containing chlorine (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as seasalt and other aerosols. "Inorganic chlorine" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names that use the term "clox" are used for quantities that contain all inorganic chlorine species except HCl and ClONO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pm" means the element "promethium" and "150Pm" is the isotope "promethium-150" with a half-life of 1.12e-01 days. - - kg m-3 + + Bq s m-3 - 'Mass concentration' means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. 'Inorganic nitrogen' describes a family of chemical species which, in an ocean model, usually includes nitrite, nitrate and ammonium which act as nitrogen nutrients. 'Inorganic nitrogen' is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nd" means the element "neodymium" and "151Nd" is the isotope "neodymium-151" with a half-life of 8.61e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for isoprene is CH2=C(CH3)CH=CH2. The IUPAC name for isoprene is 2-methyl-buta-1,3-diene. Isoprene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pm" means the element "promethium" and "151Pm" is the isotope "promethium-151" with a half-life of 1.18e+00 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for limonene is C10H16. The IUPAC name for limonene is 1-methyl-4-prop-1-en-2-yl-cyclohexene. Limonene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sm" means the element "samarium" and "151Sm" is the isotope "samarium-151" with a half-life of 3.40e+04 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction "mass_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The mass concentration of liquid water takes into account all cloud droplets and liquid precipitation regardless of drop size or fall speed. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pm" means the element "promethium" and "152mPm" is the metastable state of the isotope "promethium-152" with a half-life of 1.25e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nd" means the element "neodymium" and "152Nd" is the isotope "neodymium-152" with a half-life of 7.94e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pm" means the element "promethium" and "152Pm" is the isotope "promethium-152" with a half-life of 2.84e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methanol is CH3OH. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sm" means the element "samarium" and "153Sm" is the isotope "samarium-153" with a half-life of 1.94e+00 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl bromide is CH3Br. The IUPAC name for methyl bromide is bromomethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Eu" means the element "europium" and "154Eu" is the isotope "europium-154" with a half-life of 3.13e+03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl chloride is CH3Cl. The IUPAC name for methyl chloride is chloromethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Eu" means the element "europium" and "155Eu" is the isotope "europium-155" with a half-life of 1.75e+03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl hydroperoxide is CH3OOH. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sm" means the element "samarium" and "155Sm" is the isotope "samarium-155" with a half-life of 1.54e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl_peroxy_radical is CH3O2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Eu" means the element "europium" and "156Eu" is the isotope "europium-156" with a half-life of 1.52e+01 days. - - kg m-3 + + Bq s m-3 - 'Mass concentration' means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B containedin A, neglecting all other chemical constituents of A. Chlorophyll is the green pigment found in most plants, algae and cyanobacteria. The presence of chlorophyll is essential for photosynthesis to take place. There are five different forms of chlorophyll that occur naturally. All contain a chlorin ring (chemical formula C20H16N4) which gives the green pigment and a side chain whose structure varies. The naturally occurring forms of chlorophyll contain between 35 and 55 carbon atoms. 'Miscellaneous phytoplankton' are all those phytoplankton that are not diatoms, diazotrophs, calcareous phytoplankton, picophytoplankton or other seperately named components of the phytoplankton population. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sm" means the element "samarium" and "156Sm" is the isotope "samarium-156" with a half-life of 3.91e-01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for molecular hydrogen is H2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Eu" means the element "europium" and "157Eu" is the isotope "europium-157" with a half-life of 6.32e-01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The chemical formula for the nitrate anion is NO3-. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Eu" means the element "europium" and "158Eu" is the isotope "europium-158" with a half-life of 3.18e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Eu" means the element "europium" and "159Eu" is the isotope "europium-159" with a half-life of 1.26e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitric acid is HNO3. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Gd" means the element "gadolinium" and "159Gd" is the isotope "gadolinium-159" with a half-life of 7.71e-01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. The chemical formula for nitric acid is HNO3. Nitric acid trihydrate, sometimes referred to as NAT, is a stable crystalline substance consisting of three molecules of water to one molecule of nitric acid. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "O" means the element "oxygen" and "15O" is the isotope "oxygen-15" with a half-life of 1.41e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrogen dioxide is NO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tb" means the element "terbium" and "160Tb" is the isotope "terbium-160" with a half-life of 7.23e+01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrogen monoxide is NO. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tb" means the element "terbium" and "161Tb" is the isotope "terbium-161" with a half-life of 6.92e+00 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrous acid is HNO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Gd" means the element "gadolinium" and "162Gd" is the isotope "gadolinium-162" with a half-life of 6.92e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrous oxide is N2O. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tb" means the element "terbium" and "162mTb" is the metastable state of the isotope "terbium-162" with a half-life of 9.30e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "nmvoc" means non methane volatile organic compounds. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tb" means the element "terbium" and "162Tb" is the isotope "terbium-162" with a half-life of 5.18e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tb" means the element "terbium" and "163Tb" is the isotope "terbium-163" with a half-life of 1.36e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Noy" describes a family of chemical species. The family usually includes atomic nitrogen (N), nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), peroxynitric acid (HNO4), bromine nitrate (BrONO2) , chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)). The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Dy" means the element "dysprosium" and "165Dy" is the isotope "dysprosium-165" with a half-life of 9.80e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Organic detritus are particles of debris from decaying plants and animals. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "F" means the element "fluorine" and "18F" is the isotope "fluorine-18" with a half-life of 6.98e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Organic detritus are particles of debris from decaying plants and animals. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Hg" means the element "mercury" and "206Hg" is the isotope "mercury-206" with a half-life of 5.57e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Oxygenated" means containing oxygen. "Hydrocarbon" means a compound containing hydrogen and carbon. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tl" means the element "thallium" and "206Tl" is the isotope "thallium-206" with a half-life of 2.91e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pb" means the element "lead" and "207mPb" is the metastable state of the isotope "lead-207" with a half-life of 9.26e-06 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ozone is O3. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tl" means the element "thallium" and "207Tl" is the isotope "thallium-207" with a half-life of 3.33e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except black carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tl" means the element "thallium" and "208Tl" is the isotope "thallium-208" with a half-life of 2.15e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for peroxyacetyl nitrate, sometimes referred to as PAN, is CH3COO2NO2. The IUPAC name for peroxyacetyl_nitrate is nitroethaneperoxoate. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Bi" means the element "bismuth" and "209Bi" is the isotope "bismuth-209" with a half-life of 7.29e+20 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for peroxynitric acid, sometimes referred to as PNA, is HO2NO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pb" means the element "lead" and "209Pb" is the isotope "lead-209" with a half-life of 1.38e-01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The term "peroxy_radicals" means all organic and inorganic peroxy radicals. This includes HO2 and all organic peroxy radicals, sometimes referred to as RO2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tl" means the element "thallium" and "209Tl" is the isotope "thallium-209" with a half-life of 1.53e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Bi" means the element "bismuth" and "210Bi" is the isotope "bismuth-210" with a half-life of 5.01e+00 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. Chlorophyll is the green pigment found in most plants, algae andcyanobacteria. The presence of chlorophyll is essential for photosynthesis to take place.There are five different forms of chlorophyll that occur naturally. All contain a chlorinring (chemical formula C20H16N4) which gives the green pigment and a side chain whose structure varies. The naturally occurring forms of chlorophyll contain between 35 and 55 carbon atoms. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pb" means the element "lead" and "210Pb" is the isotope "lead-210" with a half-life of 7.64e+03 days. - - kg m-3 + + Bq s m-3 - 'Mass concentration' means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B containedin A, neglecting all other chemical constituents of A. Chlorophyll is the green pigment found in most plants, algae and cyanobacteria. The presence of chlorophyll is essential for photosynthesis to take place. There are five different forms of chlorophyll that occur naturally. All contain a chlorin ring (chemical formula C20H16N4) which gives the green pigment and a side chain whose structure varies. The naturally occurring forms of chlorophyll contain between 35 and 55 carbon atoms. Picophytoplankton are phytoplankton of less than 2 micrometers in size. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Po" means the element "polonium" and "210Po" is the isotope "polonium-210" with a half-life of 1.38e+02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. "Pm10 aerosol" is an air pollutant with an aerodynamic diameter of less than or equal to 10 micrometers. To specify the relative humidity and temperature at which the particle size applies, provide scalar coordinate variables with the standard names of, respectively, "relative_humidity" and "air_temperature." + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tl" means the element "thallium" and "210Tl" is the isotope "thallium-210" with a half-life of 9.02e-04 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. "Pm1 aerosol" is an air pollutant with an aerodynamic diameter of less than or equal to 1 micrometer. To specify the relative humidity and temperature at which the particle size applies, provide scalar coordinate variables with the standard names of, respectively, "relative_humidity" and "air_temperature". + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Bi" means the element "bismuth" and "211Bi" is the isotope "bismuth-211" with a half-life of 1.49e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. "Pm2p5 aerosol" is an air pollutant with an aerodynamic diameter of less than or equal to 2.5 micrometers. To specify the relative humidity and temperature at which the particle size applies, provide scalar coordinate variables with the standard names of, respectively, "relative_humidity" and "air_temperature." + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pb" means the element "lead" and "211Pb" is the isotope "lead-211" with a half-life of 2.51e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "Primary particulate organic matter " means all organic matter emitted directly to the atmosphere as particles except black carbon. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Po" means the element "polonium" and "211Po" is the isotope "polonium-211" with a half-life of 6.03e-06 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Bi" means the element "bismuth" and "212Bi" is the isotope "bismuth-212" with a half-life of 4.20e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pb" means the element "lead" and "212Pb" is the isotope "lead-212" with a half-life of 4.43e-01 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for radon is Rn. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Po" means the element "polonium" and "212Po" is the isotope "polonium-212" with a half-life of 3.52e-12 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction "mass_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Rain" means drops of water falling through the atmosphere that have a diameter greater than 0.5 mm. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Bi" means the element "bismuth" and "213Bi" is the isotope "bismuth-213" with a half-life of 3.26e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pb" means the element "lead" and "213Pb" is the isotope "lead-213" with a half-life of 6.92e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "Secondary particulate organic matter " means particulate organic matter formed within the atmosphere from gaseous precursors. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Po" means the element "polonium" and "213Po" is the isotope "polonium-213" with a half-life of 4.86e-11 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Bi" means the element "bismuth" and "214Bi" is the isotope "bismuth-214" with a half-life of 1.37e-02 days. - - kg m-3 + + Bq s m-3 - trsul - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. + + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pb" means the element "lead" and "214Pb" is the isotope "lead-214" with a half-life of 1.86e-02 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The chemical formula for the sulfate anion is SO4(2-). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Po" means the element "polonium" and "214Po" is the isotope "polonium-214" with a half-life of 1.90e-09 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for sulfur dioxide is SO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "At" means the element "astatine" and "215At" is the isotope "astatine-215" with a half-life of 1.16e-09 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Bi" means the element "bismuth" and "215Bi" is the isotope "bismuth-215" with a half-life of 4.86e-03 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Terpenes are hydrocarbons, that is, they contain only hydrogen and carbon combined in the general proportions (C5H8)n where n is an integer greater than on equal to one. The term "terpenes" is used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual terpene species, e.g., isoprene and limonene. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Po" means the element "polonium" and "215Po" is the isotope "polonium-215" with a half-life of 2.06e-08 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "At" means the element "astatine" and "216At" is the isotope "astatine-216" with a half-life of 3.47e-09 days. - - kg m-3 + + Bq s m-3 - "Water" means water in all phases. Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Po" means the element "polonium" and "216Po" is the isotope "polonium-216" with a half-life of 1.74e-06 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "At" means the element "astatine" and "217At" is the isotope "astatine-217" with a half-life of 3.70e-07 days. - - kg m-3 + + Bq s m-3 - Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Po" means the element "polonium" and "217Po" is the isotope "polonium-217" with a half-life of 1.16e-04 days. - - kg m-2 + + Bq s m-3 - "condensed_water" means liquid and ice. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "At" means the element "astatine" and "218At" is the isotope "astatine-218" with a half-life of 2.31e-05 days. - - kg m-2 + + Bq s m-3 - "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Po" means the element "polonium" and "218Po" is the isotope "polonium-218" with a half-life of 2.12e-03 days. - - kg m-2 + + Bq s m-3 - "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rn" means the element "radon" and "218Rn" is the isotope "radon-218" with a half-life of 4.05e-07 days. - - kg m-2 + + Bq s m-3 - "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. "Water" means water in all phases. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "At" means the element "astatine" and "219At" is the isotope "astatine-219" with a half-life of 6.27e-04 days. - - kg m-2 + + Bq s m-3 - "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rn" means the element "radon" and "219Rn" is the isotope "radon-219" with a half-life of 4.64e-05 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for acetic_acid is CH3COOH. The IUPAC name for acetic acid is ethanoic acid. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rn" means the element "radon" and "220Rn" is the isotope "radon-220" with a half-life of 6.37e-04 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for aceto-nitrile is CH3CN. The IUPAC name for aceto-nitrile is ethanenitrile. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Fr" means the element "francium" and "221Fr" is the isotope "francium-221" with a half-life of 3.33e-03 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Alkanes are saturated hydrocarbons, i.e. they do not contain any chemical double bonds. Alkanes contain only hydrogen and carbon combined in the general proportions C(n)H(2n+2); "alkanes" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual alkane species, e.g., methane and ethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rn" means the element "radon" and "221Rn" is the isotope "radon-221" with a half-life of 1.74e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Alkenes are unsaturated hydrocarbons as they contain chemical double bonds between adjacent carbon atoms. Alkenes contain only hydrogen and carbon combined in the general proportions C(n)H(2n); "alkenes" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual alkene species, e.g., ethene and propene. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Fr" means the element "francium" and "222Fr" is the isotope "francium-222" with a half-life of 1.03e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for alpha_hexachlorocyclohexane is C6H6Cl6. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ra" means the element "radium" and "222Ra" is the isotope "radium-222" with a half-life of 4.41e-04 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for alpha_pinene is C10H16. The IUPAC name for alpha-pinene is (1S,5S)-2,6,6-trimethylbicyclo[3.1.1]hept-2-ene. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rn" means the element "radon" and "222Rn" is the isotope "radon-222" with a half-life of 3.82e+00 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ammonia is NH3. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Fr" means the element "francium" and "223Fr" is the isotope "francium-223" with a half-life of 1.53e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Mass_fraction_of_ammonium" means that the mass is expressed as mass of NH4. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ra" means the element "radium" and "223Ra" is the isotope "radium-223" with a half-life of 1.14e+01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "nmvoc" means non methane volatile organic compounds. "Anthropogenic" means influenced, caused, or created by human activity. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rn" means the element "radon" and "223Rn" is the isotope "radon-223" with a half-life of 2.98e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Aromatic compounds in organic chemistry are compounds that contain at least one benzene ring of six carbon atoms joined by alternating single and double covalent bonds. The simplest aromatic compound is benzene itself. In standard names "aromatic_compounds" is the term used to describe the group of aromatic chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual aromatic species, e.g. benzene and xylene. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ra" means the element "radium" and "224Ra" is the isotope "radium-224" with a half-life of 3.65e+00 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for atomic bromine is Br. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ac" means the element "actinium" and "225Ac" is the isotope "actinium-225" with a half-life of 1.00e+01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for atomic chlorine is Cl. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ra" means the element "radium" and "225Ra" is the isotope "radium-225" with a half-life of 1.48e+01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for atomic nitrogen is N. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ac" means the element "actinium" and "226Ac" is the isotope "actinium-226" with a half-life of 1.21e+00 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ra" means the element "radium" and "226Ra" is the isotope "radium-226" with a half-life of 5.86e+05 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for beta_pinene is C10H16. The IUPAC name for beta-pinene is (1S,5S)-6,6-dimethyl-2-methylenebicyclo[3.1.1]heptane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Th" means the element "thorium" and "226Th" is the isotope "thorium-226" with a half-life of 2.15e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "nmvoc" means non methane volatile organic compounds. "Biogenic" means influenced, caused, or created by natural processes. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ac" means the element "actinium" and "227Ac" is the isotope "actinium-227" with a half-life of 7.87e+03 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. Black carbon aerosol is composed of elemental carbon. It is strongly light absorbing. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ra" means the element "radium" and "227Ra" is the isotope "radium-227" with a half-life of 2.87e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for bromine chloride is BrCl. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Th" means the element "thorium" and "227Th" is the isotope "thorium-227" with a half-life of 1.82e+01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for bromine monoxide is BrO. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ac" means the element "actinium" and "228Ac" is the isotope "actinium-228" with a half-life of 2.55e-01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for bromine nitrate is BrONO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ra" means the element "radium" and "228Ra" is the isotope "radium-228" with a half-life of 2.45e+03 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Brox" describes a family of chemical species consisting of inorganic bromine compounds with the exception of hydrogen bromide (HBr) and bromine nitrate (BrONO2). "Brox" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompaniedby a complete description of the species represented, for example, by using a comment attribute. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of source gases containing bromine (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. Standard names that use the term "inorganic_bromine" are usedfor quantities that contain all inorganic bromine species including HCl and ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Th" means the element "thorium" and "228Th" is the isotope "thorium-228" with a half-life of 6.98e+02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ac" means the element "actinium" and "229Ac" is the isotope "actinium-229" with a half-life of 4.58e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for carbon dioxide is CO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ra" means the element "radium" and "229Ra" is the isotope "radium-229" with a half-life of 1.16e-17 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of carbon monoxide is CO. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Th" means the element "thorium" and "229Th" is the isotope "thorium-229" with a half-life of 2.68e+06 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of carbon tetrachloride is CCl4. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pa" means the element "protactinium" and "230Pa" is the isotope "protactinium-230" with a half-life of 1.77e+01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC113a CCl3CF3. The IUPAC name for CFC113a is 1,1,1-trichloro-2,2,2-trifluoro-ethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Th" means the element "thorium" and "230Th" is the isotope "thorium-230" with a half-life of 2.92e+07 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC113 is CCl2FCClF2. The IUPAC name for CFC113 is 1,1,2-trichloro-1,2,2-trifluoro-ethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "230U" is the isotope "uranium-230" with a half-life of 2.08e+01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC114 is CClF2CClF2. The IUPAC name for CFC114 is 1,2-dichloro-1,1,2,2-tetrafluoro-ethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pa" means the element "protactinium" and "231Pa" is the isotope "protactinium-231" with a half-life of 1.19e+07 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC115 is CClF2CF3. The IUPAC name for CFC115 is 1-chloro-1,1,2,2,2-pentafluoro-ethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Th" means the element "thorium" and "231Th" is the isotope "thorium-231" with a half-life of 1.06e+00 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC11 is CFCl3. The IUPAC name fof CFC11 is trichloro-fluoro-methane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "231U" is the isotope "uranium-231" with a half-life of 4.29e+00 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for CFC12 is CF2Cl2. The IUPAC name for CFC12 is dichloro-difluoro-methane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pa" means the element "protactinium" and "232Pa" is the isotope "protactinium-232" with a half-life of 1.31e+00 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for chlorine dioxide is OClO. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Th" means the element "thorium" and "232Th" is the isotope "thorium-232" with a half-life of 5.14e+12 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for chlorine monoxide is ClO. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "232U" is the isotope "uranium-232" with a half-life of 2.63e+04 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for chlorine nitrate is ClONO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pa" means the element "protactinium" and "233Pa" is the isotope "protactinium-233" with a half-life of 2.70e+01 days. - - 1 + + Bq s m-3 - "condensed_water" means liquid and ice. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Th" means the element "thorium" and "233Th" is the isotope "thorium-233" with a half-life of 1.54e-02 days. - - 1 + + Bq s m-3 - cli - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "233U" is the isotope "uranium-233" with a half-life of 5.90e+07 days. - - 1 + + Bq s m-3 - clw - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pa" means the element "protactinium" and "234mPa" is the metastable state of the isotope "protactinium-234" with a half-life of 8.13e-04 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Clox" describes a familyof chemical species consisting of inorganic chlorine compounds with the exception of hydrogen chloride (HCl) and chlorine nitrate (ClONO2). "Clox" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Inorganic chlorine", sometimes referred to as Cly, describes a family of chemical species which result from the degradation of source gases containing chlorine (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as seasalt and other aerosols. Standard names that use the term "inorganic_chlorine" are used for quantitiesthat contain all inorganic chlorine species including HCl and ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A.It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pa" means the element "protactinium" and "234Pa" is the isotope "protactinium-234" with a half-life of 2.81e-01 days. - - 1 + + Bq s m-3 - "condensed_water" means liquid and ice. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Th" means the element "thorium" and "234Th" is the isotope "thorium-234" with a half-life of 2.41e+01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). Convective cloud is that produced by the convection schemes in an atmosphere model. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "234U" is the isotope "uranium-234" with a half-life of 9.02e+07 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). Convective cloud is that produced by the convection schemes in an atmosphere model. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Np" means the element "neptunium" and "235Np" is the isotope "neptunium-235" with a half-life of 4.09e+02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for dichlorineperoxide is Cl2O2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "235Pu" is the isotope "plutonium-235" with a half-life of 1.81e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "235U" is the isotope "uranium-235" with a half-life of 2.60e+11 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for dinitrogenpentoxide is N2O5. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Np" means the element "neptunium" and "236mNp" is the metastable state of the isotope "neptunium-236" with a half-life of 4.72e+10 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Np" means the element "neptunium" and "236Np" is the isotope "neptunium-236" with a half-life of 9.17e-01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standardnames for the alkane group as well as for some of the individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "236Pu" is the isotope "plutonium-236" with a half-life of 1.04e+03 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethanol isC2H5OH. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "236U" is the isotope "uranium-236" with a half-life of 8.73e+09 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standardnames for the alkene group as well as for some of the individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Np" means the element "neptunium" and "237Np" is the isotope "neptunium-237" with a half-life of 7.79e+08 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "237Pu" is the isotope "plutonium-237" with a half-life of 4.56e+01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "237U" is the isotope "uranium-237" with a half-life of 6.74e+00 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for formic acid is HCOOH. The IUPAC name for formic acid is methanoic acid. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Np" means the element "neptunium" and "238Np" is the isotope "neptunium-238" with a half-life of 2.10e+00 days. - - 1 + + Bq s m-3 - "frozen_water" means ice. "moisture" means water in all phases contained in soil. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "238Pu" is the isotope "plutonium-238" with a half-life of 3.15e+04 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Divalent mercury" means all compounds in which the mercury has two binding sites to other ion(s) in a salt or to other atom(s) in a molecule. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "238U" is the isotope "uranium-238" with a half-life of 1.65e+12 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for mercury is Hg. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Np" means the element "neptunium" and "239Np" is the isotope "neptunium-239" with a half-life of 2.35e+00 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "239Pu" is the isotope "plutonium-239" with a half-life of 8.91e+06 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halon1202 is CBr2F2. The IUPAC name for halon1202 is dibromo-difluoro-methane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "239U" is the isotope "uranium-239" with a half-life of 1.63e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halon1211 is CBrClF2. The IUPAC name for halon1211 is bromo-chloro-difluoro-methane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Am" means the element "americium" and "240Am" is the isotope "americium-240" with a half-life of 2.12e+00 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halon1301 is CBrF3. The IUPAC name for halon1301 is bromo-trifluoro-methane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Np" means the element "neptunium" and "240mNp" is the metastable state of the isotope "neptunium-240" with a half-life of 5.08e-03 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halo2402 is C2Br2F4. The IUPAC name for halon2402 is 1,2-dibromo-1,1,2,2-tetrafluoro-ethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Np" means the element "neptunium" and "240Np" is the isotope "neptunium-240" with a half-life of 4.38e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hcc140a isCH3CCl3. The IUPAC name for hcc140a is 1,1,1-trichloro-ethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "240Pu" is the isotope "plutonium-240" with a half-life of 2.40e+06 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for HCFC141b is CH3CCl2F. The IUPAC name for HCFC141b is 1,1-dichloro-1-fluoroethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "240U" is the isotope "uranium-240" with a half-life of 5.99e-01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for HCFC142b is CH3CClF2. The IUPAC name for HCFC142b is 1-chloro-1,1-difluoroethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Am" means the element "americium" and "241Am" is the isotope "americium-241" with a half-life of 1.67e+05 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for HCFC22 is CHClF2. The IUPAC name for HCFC22 is chloro-difluoro-methane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "241Cm" is the isotope "curium-241" with a half-life of 3.50e+01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hexachlorobiphenyl is C12H4Cl6. This structure of this species consists of two linked benzene rings,each of which is additionally bonded to three chlorine atoms. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "241Pu" is the isotope "plutonium-241" with a half-life of 4.83e+03 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "HOx" means a combination of two radical species containing hydrogen and oxygen: OH and HO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Am" means the element "americium" and "242Am" is the isotope "americium-242" with a half-life of 6.69e-01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen bromide is HBr. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "242Cm" is the isotope "curium-242" with a half-life of 1.63e+02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen chloride is HCl. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Am" means the element "americium" and "242m1Am" is the metastable state of the isotope "americium-242" with a half-life of 5.53e+04 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen cyanide is HCN. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Am" means the element "americium" and "242m2Am" is the metastable state of the isotope "americium-242" with a half-life of 1.62e-07 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen peroxide is H2O2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "242Pu" is the isotope "plutonium-242" with a half-life of 1.38e+08 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for the hydroperoxyl radical is HO2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Am" means the element "americium" and "243Am" is the isotope "americium-243" with a half-life of 2.91e+06 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for the hydroxyl radical is OH. In chemistry, a 'radical' is a highly reactive, and therefore shortlived,species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "243Cm" is the isotope "curium-243" with a half-life of 1.17e+04 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hypobromous acid is HOBr. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "243Pu" is the isotope "plutonium-243" with a half-life of 2.07e-01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hypochlorous acid is HOCl. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Am" means the element "americium" and "244Am" is the isotope "americium-244" with a half-life of 4.20e-01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of source gases containing bromine (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. "Inorganic bromine" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names that use the term "brox" are used for quantities that contain all inorganic bromine species except HBr and BrONO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "244Cm" is the isotope "curium-244" with a half-life of 6.42e+03 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Inorganic chlorine", sometimes referred to as Cly, describes a family of chemical species which result from the degradation of source gases containing chlorine (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as seasalt and other aerosols. "Inorganic chlorine" is the termused in standard names for all species belonging to the family that are represented withina given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names that use the term "clox" are used for quantities that contain all inorganic chlorine species except HCl and ClONO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Am" means the element "americium" and "244mAm" is the metastable state of the isotope "americium-244" with a half-life of 1.81e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for isoprene is CH2=C(CH3)CH=CH2. The IUPAC name for isoprene is 2-methyl-buta-1,3-diene. Isoprene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "244Pu" is the isotope "plutonium-244" with a half-life of 2.92e+10 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for limonene is C10H16. The IUPAC name for limonene is 1-methyl-4-prop-1-en-2-yl-cyclohexene. Limonene is a member of the group of hydrocarbons known as terpenes. There are standard names for theterpene group as well as for some of the individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Am" means the element "americium" and "245Am" is the isotope "americium-245" with a half-life of 8.75e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "245Cm" is the isotope "curium-245" with a half-life of 3.40e+06 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methane isCH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "245Pu" is the isotope "plutonium-245" with a half-life of 4.16e-01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethanol isC2H5OH. The chemical formula for methanol is CH3OH. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "246Cm" is the isotope "curium-246" with a half-life of 2.01e+06 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl bromide is CH3Br. The IUPAC name for methyl bromide is bromomethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "247Cm" is the isotope "curium-247" with a half-life of 5.86e+09 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl chloride is CH3Cl. The IUPAC name for methyl chloride is chloromethane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "248Cm" is the isotope "curium-248" with a half-life of 1.72e+08 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl hydroperoxide is CH3OOH. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Bk" means the element "berkelium" and "249Bk" is the isotope "berkelium-249" with a half-life of 3.15e+02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl_peroxy_radical is CH3O2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cf" means the element "californium" and "249Cf" is the isotope "californium-249" with a half-life of 1.32e+05 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for molecular hydrogen is H2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "249Cm" is the isotope "curium-249" with a half-life of 4.43e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Mass_fraction_of_nitrate" means that the mass is expressed as mass of NO3. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Na" means the element "sodium" and "24Na" is the isotope "sodium-24" with a half-life of 6.27e-01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Bk" means the element "berkelium" and "250Bk" is the isotope "berkelium-250" with a half-life of 1.34e-01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitric acid is HNO3. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cf" means the element "californium" and "250Cf" is the isotope "californium-250" with a half-life of 4.75e+03 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol"is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. The chemical formula for nitric acid is HNO3. Nitric acid trihydrate, sometimes referred to as NAT,is a stable crystalline substance consisting of three molecules of water to one molecule of nitric acid. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "250Cm" is the isotope "curium-250" with a half-life of 2.52e+06 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrogen dioxide is NO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cf" means the element "californium" and "251Cf" is the isotope "californium-251" with a half-life of 2.92e+05 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrogen monoxide is NO. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cf" means the element "californium" and "252Cf" is the isotope "californium-252" with a half-life of 9.68e+02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrous acid is HNO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cf" means the element "californium" and "253Cf" is the isotope "californium-253" with a half-life of 1.76e+01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrous oxide is N2O. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Es" means the element "einsteinium" and "253Es" is the isotope "einsteinium-253" with a half-life of 2.05e+01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "nmvoc" means non methanevolatile organic compounds. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cf" means the element "californium" and "254Cf" is the isotope "californium-254" with a half-life of 6.03e+01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The term "peroxy_radicals" means all organic and inorganic peroxy radicals. This includes HO2 and all organic peroxyradicals, sometimes referred to as RO2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Es" means the element "einsteinium" and "254Es" is the isotope "einsteinium-254" with a half-life of 2.76e+02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Noy" describes a family of chemical species. The family usually includes atomic nitrogen (N), nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), peroxynitric acid (HNO4), bromine nitrate (BrONO2) , chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)). The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Es" means the element "einsteinium" and "254mEs" is the metastable state of the isotope "einsteinium-254" with a half-life of 1.63e+00 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Oxygenated" means containing oxygen. "Hydrocarbon" means a compound containing hydrogen and carbon. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Es" means the element "einsteinium" and "255Es" is the isotope "einsteinium-255" with a half-life of 3.84e+01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "H" means the element "hydrogen" and "3H" is the isotope "hydrogen-3" with a half-life of 4.51e+03 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except black carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ar" means the element "argon" and "41Ar" is the isotope "argon-41" with a half-life of 7.64e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for peroxyacetyl nitrate, sometimes referred to as PAN, is CH3COO2NO2. The IUPAC name for peroxyacetyl_nitrate is nitroethaneperoxoate. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Mn" means the element "manganese" and "54Mn" is the isotope "manganese-54" with a half-life of 3.12e+02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for peroxynitric acid, sometimes referred to as PNA, is HO2NO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Co" means the element "cobalt" and "58Co" is the isotope "cobalt-58" with a half-life of 7.10e+01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The term "peroxy_radicals" means all organic and inorganic peroxy radicals. This includes HO2 and all organic peroxyradicals, sometimes referred to as RO2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Co" means the element "cobalt" and "60Co" is the isotope "cobalt-60" with a half-life of 1.93e+03 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. "Pm10 aerosol" is an air pollutant with an aerodynamic diameter of less than or equal to 10 micrometers. To specify the relative humidity and temperature at which the particle size applies, provide scalar coordinate variables with the standard names of, respectively, "relative_humidity" and "air_temperature." + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ga" means the element "gallium" and "72Ga" is the isotope "gallium-72" with a half-life of 5.86e-01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquidor solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth dependson the relative humidity and the composition of the aerosol. "Pm1 aerosol" is an air pollutant with an aerodynamic diameter of less than or equal to 1 micrometer. To specify the relative humidity and temperature at which the particle size applies, provide scalar coordinate variables with the standard names of, respectively, "relative_humidity" and "air_temperature". + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Zn" means the element "zinc" and "72Zn" is the isotope "zinc-72" with a half-life of 1.94e+00 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. "Pm2p5 aerosol" is an air pollutant with an aerodynamic diameter of less than or equal to 2.5 micrometers. To specify the relative humidity and temperature at which the particle size applies, provide scalar coordinate variables with the standard names of, respectively, "relative_humidity" and "air_temperature". + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ga" means the element "gallium" and "73Ga" is the isotope "gallium-73" with a half-life of 2.03e-01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ge" means the element "germanium" and "75Ge" is the isotope "germanium-75" with a half-life of 5.73e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "Primary particulate organic matter " means all organic matter emitted directly to the atmosphere as particles except black carbon. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "As" means the element "arsenic" and "77As" is the isotope "arsenic-77" with a half-life of 1.62e+00 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for propane isC3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ge" means the element "germanium" and "77Ge" is the isotope "germanium-77" with a half-life of 4.72e-01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for propene isC3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ge" means the element "germanium" and "77mGe" is the metastable state of the isotope "germanium-77" with a half-life of 6.27e-04 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for radon is Rn. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "As" means the element "arsenic" and "78As" is the isotope "arsenic-78" with a half-life of 6.32e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ge" means the element "germanium" and "78Ge" is the isotope "germanium-78" with a half-life of 6.03e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Se" means the element "selenium" and "79Se" is the isotope "selenium-79" with a half-life of 2.37e+07 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "Secondary particulate organic matter " means particulate organic matter formed within the atmosphere from gaseous precursors. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Se" means the element "selenium" and "81mSe" is the metastable state of the isotope "selenium-81" with a half-life of 3.97e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Se" means the element "selenium" and "81Se" is the isotope "selenium-81" with a half-life of 1.28e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Br" means the element "bromine" and "82Br" is the isotope "bromine-82" with a half-life of 1.47e+00 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Br" means the element "bromine" and "82mBr" is the metastable state of the isotope "bromine-82" with a half-life of 4.24e-03 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Mass_fraction_of_sulfate" means that the mass is expressed as mass of SO4. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Br" means the element "bromine" and "83Br" is the isotope "bromine-83" with a half-life of 1.00e-01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Kr" means the element "krypton" and "83mKr" is the metastable state of the isotope "krypton-83" with a half-life of 7.71e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Se" means the element "selenium" and "83mSe" is the metastable state of the isotope "selenium-83" with a half-life of 8.10e-04 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Terpenes are hydrocarbons, that is,they contain only hydrogen and carbon combined in the general proportions (C5H8)n where n is an integer greater than on equal to one. The term "terpenes" is used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual terpene species, e.g., isoprene and limonene. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Se" means the element "selenium" and "83Se" is the isotope "selenium-83" with a half-life of 1.56e-02 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for toluene isC6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atomsis replaced by a methyl group. The systematic name for toluene is methylbenzene. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Br" means the element "bromine" and "84Br" is the isotope "bromine-84" with a half-life of 2.21e-02 days. - - 1 + + Bq s m-3 - "moisture" means water in all phases contained in soil. "unfrozen_water" means liquid and vapour. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Br" means the element "bromine" and "84mBr" is the metastable state of the isotope "bromine-84" with a half-life of 4.16e-03 days. - - 1 + + Bq s m-3 - "Water" means water in all phases. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Kr" means the element "krypton" and "85Kr" is the isotope "krypton-85" with a half-life of 3.95e+03 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Kr" means the element "krypton" and "85mKr" is the metastable state of the isotope "krypton-85" with a half-life of 1.83e-01 days. - - 1 + + Bq s m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer toaromatic_compounds as a group, as well as those for individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rb" means the element "rubidium" and "86mRb" is the metastable state of the isotope "rubidium-86" with a half-life of 7.04e-04 days. - - kg m-2 + + Bq s m-3 - "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including content_of_soil_layer are used. "Soil carbon" is the organic matter present in soil quantified by the mass of carbon it contains. Soil carbon is returned to the atmosphere as the organic matter decays. The decay process takes varying amounts of time depending on the composition of the organic matter, the temperature and the availability of moisture. A carbon "soil pool" means the carbon contained in organic matter which has a characteristic period over which it decays and releases carbon into the atmosphere. "Medium soil pool" refers to the decay of organic matter in soil with a characteristic period of between ten and one hundred years under reference climate conditions of a temperature of 20 degrees Celsius and no water limitations. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rb" means the element "rubidium" and "86Rb" is the isotope "rubidium-86" with a half-life of 1.87e+01 days. - - 1 + + Bq s m-3 - Middle type clouds are: Altostratus, Altocumulus, Nimbostratus. "X_area_fraction" means the fraction of horizontal area occupied by X. Cloud area fraction is also called "cloud amount" and "cloud cover". X_type_cloud_area_fraction is determined on the basis of cloud type and not on the vertical location of the cloud. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Kr" means the element "krypton" and "87Kr" is the isotope "krypton-87" with a half-life of 5.28e-02 days. - - m + + Bq s m-3 - Depth is the vertical distance below the surface. 'Undersaturation' means that a solution is unsaturated with respect to a solute. Aragonite is a mineral that is a polymorph of calcium carbonate. The chemical formula of aragonite is CaCO3. Standard names also exist for calcite, another polymorph of calcium carbonate. The "minimum depth of undersaturation", sometimes called the "saturation horizon", is the shallowest depth at which a body of water is an undersaturated solution of a named solute. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rb" means the element "rubidium" and "87Rb" is the isotope "rubidium-87" with a half-life of 1.71e+13 days. - - m + + Bq s m-3 - Depth is the vertical distance below the surface. 'Undersaturation' means that a solution is unsaturated with respect to a solute. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Standard names also exist for aragonite, another polymorph of calcium carbonate. The "minimum depth of undersaturation", sometimes called the "saturation horizon", is the shallowest depth at which a body of water is an undersaturated solution of a named solute. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Kr" means the element "krypton" and "88Kr" is the isotope "krypton-88" with a half-life of 1.17e-01 days. - - W m-2 + + Bq s m-3 - "Minus one times" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. The surface called "surface" means the lower boundary of the atmosphere. "longwave" means longwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rb" means the element "rubidium" and "88Rb" is the isotope "rubidium-88" with a half-life of 1.25e-02 days. - - W m-2 + + Bq s m-3 - "Minus one times" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. The surface called "surface" means the lower boundary of the atmosphere. "shortwave" means shortwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Kr" means the element "krypton" and "89Kr" is the isotope "krypton-89" with a half-life of 2.20e-03 days. - - W m-2 + + Bq s m-3 - "Minus one times" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Shortwave means shortwave radiation. "toa" means top of atmosphere. The TOA outgoing shortwave flux is the reflected and scattered solar radiative flux i.e. the "upwelling" TOA shortwave flux, sometimes called the "outgoing shortwave radiation" or "OSR". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rb" means the element "rubidium" and "89Rb" is the isotope "rubidium-89" with a half-life of 1.06e-02 days. - - kg m-2 s-1 + + Bq s m-3 - The quantity minus_one_times_water_flux_into_sea_water_from_rivers is the quantity with standard name water_flux_into_sea_water_from_rivers multiplied by -1. "Water" means water in all phases. The water flux or volume transport into sea water from rivers is the inflow to the ocean, often applied to the surface in ocean models. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sr" means the element "strontium" and "89Sr" is the isotope "strontium-89" with a half-life of 5.21e+01 days. - - kg m-2 + + Bq s m-3 - "Content" indicates a quantity per unit area. "Miscellaneous living matter" means all those parts of living vegetation that are not leaf, wood, root or other separately named components. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Y" means the element "yttrium" and "90mY" is the metastable state of the isotope "yttrium-90" with a half-life of 1.33e-01 days. - - 1 + + Bq s m-3 - lev - Model level number should be understood as equivalent to layer number. + + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sr" means the element "strontium" and "90Sr" is the isotope "strontium-90" with a half-life of 1.02e+04 days. - - 1 + + Bq s m-3 - The ocean mixed layer is the upper part of the ocean, regarded as being well-mixed. The base of the mixed layer defined by temperature, sigma, sigma_theta or vertical diffusivity is the level at which the quantity indicated differs from its surface value by a certain amount. The amount by which the quantity differs can be specified by a scalar coordinate variable. The quantity model_level_number_at_base_of_ocean_mixed_layer_defined_by_sigma_theta is sometimes referred to as the "bowl index". + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Y" means the element "yttrium" and "90Y" is the isotope "yttrium-90" with a half-life of 2.67e+00 days. - - 1 + + Bq s m-3 - cloud_base refers to the base of the lowest cloud. Model level number should be understood as equivalent to layer number. Convective cloud is that produced by the convection schemes in an atmosphere model. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Y" means the element "yttrium" and "91mY" is the metastable state of the isotope "yttrium-91" with a half-life of 3.46e-02 days. - - 1 + + Bq s m-3 - cloud_top refers to the top of the highest cloud. Model level number should be understood as equivalent to layer number. Convective cloud is that produced by the convection schemes in an atmosphere model. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sr" means the element "strontium" and "91Sr" is the isotope "strontium-91" with a half-life of 3.95e-01 days. - - 1 + + Bq s m-3 - The quantity with standard name model_level_number_at_sea_floor is the depth of the ocean expressed in model levels. This could be a non-integer value because some ocean models use partial cells close to the sea floor. For example, if this field were 23.4 at some location, it would mean the water column at that point comprised 23 full model levels plus 40% occupancy of the lowest (24th) gridcell. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Y" means the element "yttrium" and "91Y" is the isotope "yttrium-91" with a half-life of 5.86e+01 days. - - 1 + + Bq s m-3 - Model level number should be understood as equivalent to layer number. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sr" means the element "strontium" and "92Sr" is the isotope "strontium-92" with a half-life of 1.13e-01 days. - - kg m-2 + + Bq s m-3 - mrsos - "moisture" means water in all phases contained in soil. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Quantities defined for a soil layer must have a vertical coordinate variable with boundaries indicating the extent of the layer(s). + + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Y" means the element "yttrium" and "92Y" is the isotope "yttrium-92" with a half-life of 1.47e-01 days. - - kg m-2 + + Bq s m-3 - mrsofcs - "moisture" means water in all phases contained in soil. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Quantities defined for a soil layer must have a vertical coordinate variable with boundaries indicating the extent of the layer(s). The field capacity of soil is the maximum content of water it can retain against gravitational drainage. + + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Y" means the element "yttrium" and "93Y" is the isotope "yttrium-93" with a half-life of 4.24e-01 days. - - mol m-3 + + Bq s m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for acetic_acid is CH3COOH. The IUPAC name for acetic acid is ethanoic acid. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Zr" means the element "zirconium" and "93Zr" is the isotope "zirconium-93" with a half-life of 3.47e+08 days. - - mol m-3 + + Bq s m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for aceto-nitrile is CH3CN. The IUPAC name for aceto-nitrile is ethanenitrile. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nb" means the element "niobium" and "94mNb" is the metastable state of the isotope "niobium-94" with a half-life of 4.34e-03 days. - - mol m-3 + + Bq s m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for alpha_hexachlorocyclohexane is C6H6Cl6. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nb" means the element "niobium" and "94Nb" is the isotope "niobium-94" with a half-life of 7.29e+06 days. - - mol m-3 + + Bq s m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for alpha_pinene is C10H16. The IUPAC name for alpha-pinene is (1S,5S)-2,6,6-trimethylbicyclo[3.1.1]hept-2-ene. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Y" means the element "yttrium" and "94Y" is the isotope "yttrium-94" with a half-life of 1.32e-02 days. - - mol m-3 + + Bq s m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ammonia is NH3. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nb" means the element "niobium" and "95mNb" is the metastable state of the isotope "niobium-95" with a half-life of 3.61e+00 days. - - mol m-3 + + Bq s m-3 - Mole concentration means moles (amount of substance) per unit volume and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nb" means the element "niobium" and "95Nb" is the isotope "niobium-95" with a half-life of 3.52e+01 days. - - mol m-3 + + Bq s m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "nmvoc" means non methane volatile organic compounds. "Anthropogenic" means influenced,caused, or created by human activity. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituentsof A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Y" means the element "yttrium" and "95Y" is the isotope "yttrium-95" with a half-life of 7.29e-03 days. - - mol m-3 + + Bq s m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Aragonite is a mineral that is a polymorph of calcium carbonate. The chemical formula of aragonite is CaCO3. Standard names also exist for calcite, another polymorph of calcium carbonate. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Zr" means the element "zirconium" and "95Zr" is the isotope "zirconium-95" with a half-life of 6.52e+01 days. - - mol m-3 + + Bq s m-3 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Mole concentration at saturation means the mole concentration in a saturated solution.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Aragonite is a mineral that is a polymorph of calcium carbonate. The chemical formula of aragonite is CaCO3. Standard names also exist for calcite, another polymorph of calcium carbonate. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nb" means the element "niobium" and "96Nb" is the isotope "niobium-96" with a half-life of 9.75e-01 days. - - mol m-3 + + Bq s m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for atomic bromine is Br. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nb" means the element "niobium" and "97mNb" is the metastable state of the isotope "niobium-97" with a half-life of 6.27e-04 days. - - mol m-3 + + Bq s m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for atomic chlorine is Cl. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nb" means the element "niobium" and "97Nb" is the isotope "niobium-97" with a half-life of 5.11e-02 days. - - mol m-3 + + Bq s m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for atomic nitrogen is N. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Zr" means the element "zirconium" and "97Zr" is the isotope "zirconium-97" with a half-life of 6.98e-01 days. - - mol m-3 + + Bq s m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nb" means the element "niobium" and "98Nb" is the isotope "niobium-98" with a half-life of 3.53e-02 days. - - mol m-3 + + Bq s m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Mo" means the element "molybdenum" and "99Mo" is the isotope "molybdenum-99" with a half-life of 2.78e+00 days. - - mol m-3 + + Bq s m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for beta_pinene is C10H16. The IUPAC name for beta-pinene is (1S,5S)-6,6-dimethyl-2-methylenebicyclo[3.1.1]heptane. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tc" means the element "technetium" and "99mTc" is the metastable state of the isotope "technetium-99" with a half-life of 2.51e-01 days. - - mol m-3 + + Bq s m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "nmvoc" means non methane volatile organic compounds. "Biogenic" means influenced, caused, or created by natural processes. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituentsof A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means "with respect to". "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tc" means the element "technetium" and "99Tc" is the isotope "technetium-99" with a half-life of 7.79e+07 days. - - mol m-3 + + Pa s - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for bromine chloride is BrCl. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. The surface called "surface" means the lower boundary of the atmosphere. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Downward" indicates a vector component which is positive when directed downward (negative upward). "Downward eastward" indicates the ZX component of a tensor. A downward eastward stress is a downward flux of eastward momentum, which accelerates the lower medium eastward and the upper medium westward. The surface downward stress is the wind stress on the surface. - - mol m-3 + + W s m-2 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for bromine monoxide is BrO. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). The surface latent heat flux is the exchange of heat between the surface and the air on account of evaporation (including sublimation). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - mol m-3 + + Pa s - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for bromine nitrate is BrONO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. The surface called "surface" means the lower boundary of the atmosphere. "Northward" indicates a vector component which is positive when directed northward (negative southward). "Downward" indicates a vector component which is positive when directed downward (negative upward). "Downward northward" indicates the ZY component of a tensor. A downward northward stress is a downward flux of northward momentum, which accelerates the lower medium northward and the upper medium southward. The surface downward stress is the wind stress on the surface. - - mol m-3 + + W s m-2 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Brox" describes a family of chemical species consisting of inorganic bromine compounds with theexception of hydrogen bromide (HBr) and bromine nitrate (BrONO2). "Brox" is theterm used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of source gases containing bromine (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. Standard names that use the term "inorganic_bromine" are used for quantities that contain all inorganic bromine species including HCland ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard nameis calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). The surface sensible heat flux, also called "turbulent" heat flux, is the exchange of heat between the surface and the air by motion of air. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - mol m-3 + + W s m-2 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means with respect to. The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "longwave" means longwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - mol m-3 + + W s m-2 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. 'Calcareous phytoplankton' are phytoplankton that produce calcite. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. Calcite is a mineral that is a polymorphof calcium carbonate. The chemical formula of calcite is CaCO3. Standard names also existfor aragonite, another polymorph of calcium carbonate. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. The phrase "wrt" means with respect to. The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. Surface downwelling shortwave is the sum of direct and diffuse solar radiation incident on the surface, and is sometimes called "global radiation". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - mol m-3 + + W s m-2 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Standard names also exist for aragonite, another polymorph of calcium carbonate. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). "longwave" means longwave radiation. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - mol m-3 + + W s m-2 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Mole concentration at saturation means the mole concentration in a saturated solution.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Standard names also exist for aragonite, another polymorph of calcium carbonate. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). "Shortwave" means shortwave radiation. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - mol m-3 + + W s m-2 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula of the carbonate anion is CO3 with a charge of minus two. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. "toa" means top of atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). "Shortwave" means shortwave radiation. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - mol m-3 + + W s m-2 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for carbon dioxide is CO2. + The phrase "integral_wrt_X_of_Y" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. "toa" means top of atmosphere. "Longwave" means longwave radiation. The TOA outgoing longwave flux is the upwelling thermal radiative flux, often called the "outgoing longwave radiation" or "OLR". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - mol m-3 + + 1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of carbon monoxide is CO. + "Calcareous phytoplankton" are phytoplankton that produce calcite. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Phytoplankton are algae that grow where there is sufficient light to support photosynthesis. "Iron growth limitation" means the ratio of the growth rate of a species population in the environment (where there is a finite availability of iron) to the theoretical growth rate if there were no such limit on iron availability. - - mol m-3 + + 1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of carbon tetrachloride is CCl4. + Diatoms are phytoplankton with an external skeleton made of silica. Phytoplankton are algae that grow where there is sufficient light to support photosynthesis. "Iron growth limitation" means the ratio of the growth rate of a species population in the environment (where there is a finite availability of iron) to the theoretical growth rate if there were no such limit on iron availability. - - mol m-3 + + 1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC113a CCl3CF3. The IUPAC name for CFC113a is 1,1,1-trichloro-2,2,2-trifluoro-ethane. + In ocean modelling, diazotrophs are phytoplankton of the phylum cyanobacteria distinct from other phytoplankton groups in their ability to fix nitrogen gas in addition to nitrate and ammonium. Phytoplankton are algae that grow where there is sufficient light to support photosynthesis. "Iron growth limitation" means the ratio of the growth rate of a species population in the environment (where there is a finite availability of iron) to the theoretical growth rate if there were no such limit on iron availability. - - mol m-3 + + 1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC113 is CCl2FCClF2. The IUPAC name for CFC113 is 1,1,2-trichloro-1,2,2-trifluoro-ethane. + Phytoplankton are algae that grow where there is sufficient light to support photosynthesis. "Miscellaneous phytoplankton" are all those phytoplankton that are not diatoms, diazotrophs, calcareous phytoplankton, picophytoplankton or other separately named components of the phytoplankton population. "Iron growth limitation" means the ratio of the growth rate of a species population in the environment (where there is a finite availability of iron) to the theoretical growth rate if there were no such limit on iron availability. - - mol m-3 + + 1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC114 is CClF2CClF2. The IUPAC name for CFC114 is 1,2-dichloro-1,1,2,2-tetrafluoro-ethane. + Picophytoplankton are phytoplankton of less than 2 micrometers in size. Phytoplankton are algae that grow where there is sufficient light to support photosynthesis. "Iron growth limitation" means the ratio of the growth rate of a species population in the environment (where there is a finite availability of iron) to the theoretical growth rate if there were no such limit on iron availability. - - mol m-3 + + 1 - - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC115 is CClF2CF3. The IUPAC name for CFC115 is 1-chloro-1,1,2,2,2-pentafluoro-ethane. + clisccp + "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. Cloud area fraction is also called "cloud amount" and "cloud cover". The cloud area fraction is for the whole atmosphere column, as seen from the surface or the top of the atmosphere. The cloud area fraction in a layer of the atmosphere has the standard name cloud_area_fraction_in_atmosphere_layer. The ISCCP cloud area fraction is diagnosed from atmosphere model output by the ISCCP simulator software in such a way as to be comparable with the observational diagnostics of ISCCP (the International Satellite Cloud Climatology Project). - - mol m-3 + + 1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC11 is CFCl3. The IUPAC name fof CFC11 is trichloro-fluoro-methane. + The phrase "ratio_of_X_to_Y" means X/Y. The phrase "isotope_ratio" is used in the construction isotope_ratio_of_A_to_B where A and B are both named isotopes. It means the ratio of the number of atoms of A to the number of atoms of B present within a medium. "O" means the element "oxygen" and "17O" is the stable isotope "oxygen-17". "16O" is the stable isotope "oxygen-16". The phrase "in_sea_water_excluding_solutes_and_solids" means that the standard name refers only to the chemical compound water and does not include material that may be dissolved or suspended in the aqueous medium. - - mol m-3 + + 1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for CFC12 is CF2Cl2. The IUPAC name for CFC12 is dichloro-difluoro-methane. + The phrase "ratio_of_X_to_Y" means X/Y. The phrase "isotope_ratio" is used in the construction isotope_ratio_of_A_to_B where A and B are both named isotopes. It means the ratio of the number of atoms of A to the number of atoms of B present within a medium. "O" means the element "oxygen" and "18O" is the stable isotope "oxygen-18". "16O" is the stable isotope "oxygen-16". The phrase "in_sea_water_excluding_solutes_and_solids" means that the standard name refers only to the chemical compound water and does not include material that may be dissolved or suspended in the aqueous medium. - - mol m-3 + + W m-2 sr-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for chlorine dioxide is OClO. + "longwave" means longwave radiation. Radiance is the radiative flux in a particular direction, per unit of solid angle. If radiation is isotropic, the radiance is independent of direction, so the direction should not be specified. If the radiation is directionally dependent, a standard name of upwelling or downwelling radiance should be chosen instead. - - mol m-3 + + W m-2 m-1 sr-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for chlorine monoxide is ClO. + Radiance is the radiative flux in a particular direction, per unit of solid angle. If radiation is isotropic, the radiance is independent of direction, so the direction should not be specified. If the radiation is directionally dependent, a standard name of upwelling or downwelling radiance should be chosen instead. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. - - mol m-3 + + W m-2 sr-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for chlorine nitrate is ClONO2. + "shortwave" means shortwave radiation. Radiance is the radiative flux in a particular direction, per unit of solid angle. If radiation is isotropic, the radiance is independent of direction, so the direction should not be specified. If the radiation is directionally dependent, a standard name of upwelling or downwelling radiance should be chosen instead. - - mol m-3 + + J m-2 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Clox"describes a family of chemical species consisting of inorganic chlorine compounds with theexception of hydrogen chloride (HCl) and chlorine nitrate (ClONO2). "Clox" is the term used in standard names for all species belonging to the family that are representedwithin a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, byusing a comment attribute. "Inorganic chlorine", sometimes referred to as Cly, describes a family of chemical species which result from the degradation of source gases containing chlorine (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as seasaltand other aerosols. Standard names that use the term "inorganic_chlorine" are used for quantities that contain all inorganic chlorine species including HCl and ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculatedsolely with respect to the B contained in A, neglecting all other chemical constituents ofA. + "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. - - mol m-3 - + + W m-2 + E145 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Diatoms are single-celled phytoplankton with an external skeleton made of silica.Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. + - - mol m-3 - - - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated in terms of B alone, neglecting all other chemical constituents of A. + + Pa s-1 + 39 E135 + wap + "tendency_of_X" means derivative of X with respect to time. The Lagrangian tendency of a quantity is its rate of change following the motion of the fluid, also called the "material derivative" or "convective derivative". The Lagrangian tendency of air pressure, often called "omega", plays the role of the upward component of air velocity when air pressure is being used as the vertical coordinate. If the vertical air velocity is upwards, it is negative when expressed as a tendency of air pressure; downwards is positive. Air pressure is the force per unit area which would be exerted when the moving gas molecules of which the air is composed strike a theoretical surface of any orientation. - - mol m-3 - + + s-1 + 38 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. In ocean modelling, diazotrophs are phytoplankton of the phylum cyanobacteria distinct from other phytoplankton groups in their ability to fix nitrogen gas in addition to nitrate and ammonium. Phytoplankton are autotrophic prokaryotic or eukaryotic organisms that live near the water surface where there is sufficient light to support photosynthesis. + "tendency_of_X" means derivative of X with respect to time. The Lagrangian tendency of a quantity is its rate of change following the motion of the fluid, also called the "material derivative" or "convective derivative". The Lagrangian tendency of sigma plays the role of the upward component of air velocity when the atmosphere sigma coordinate (a dimensionless atmosphere vertical coordinate) is being used as the vertical coordinate. If the vertical air velocity is upwards, it is negative when expressed as a tendency of sigma; downwards is positive. See Appendix D of the CF convention for information about dimensionless vertical coordinates. - - mol m-3 - - - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for dichlorine peroxide is Cl2O2. + + 1 + 81 + sftlf + "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. - - mol m-3 - + + 1 + E172 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for dimethyl sulfide is (CH3)2S. Dimethyl sulfide is sometimes referred to as DMS. + X_binary_mask has 1 where condition X is met, 0 elsewhere. 1 = land, 0 = sea. - - mol m-3 + + - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for dimethyl sulfide is (CH3)2S. Dimethyl sulfide is sometimes referred to as DMS. + A variable with the standard name of land_cover_sccs contains strings which indicate the nature of the surface, e.g. cropland_..., tree_... . These strings are standardised. Values must be combinations of classifiers from the Land Cover Classification System (LCCS; Di Gregorio A., 2005, UN Land Cover Classification System (LCCS) - Classification concepts and user manual for Software version 2; available at www.fao.org/DOCREP/003/X0596E/X0596e00.htm). - - mol m-3 + + 1 - - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for dinitrogen pentoxide is N2O5. + sftgif + "X_area_fraction" means the fraction of horizontal area occupied by X. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. - - mol m-3 + + Pa - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Dissolved inorganic carbon" describes a family of chemical species in solution, including carbon dioxide, carbonic acid and the carbonate and bicarbonate anions. "Dissolved inorganic carbon" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the speciesrepresented, for example, by using a comment attribute. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. Basal drag is a resistive stress opposing ice flow at the ice bedrock boundary. - - mol m-3 + + m s-1 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. The land ice basal melt rate is the rate at which ice is lost per unit area at the base of the ice. - - mol m-3 + + kg m-2 s-1 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Specific mass balance" means the net rate at which ice is added per unit area. A negative value means loss of ice. For an area-average, the cell_methods attribute should be used to specify whether the average is over the area of the whole grid cell or the area of land ice only. "Basal specific mass balance" means the net rate at which ice is added per unit area at the land ice base. - - mol m-3 + + K - 'Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The concentration of any chemical species, whether particulate or dissolved, may vary with depth in the ocean. A depth profile may go through one or more local minima in concentration. The mole_concentration_of_molecular_oxygen_in_sea_water_at_shallowest_local_minimum_in_vertical_profile is the mole concentration of oxygen at the local minimum in the concentration profile that occurs closest to the sea surface. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. The standard name land_ice_basal_temperature means the temperature of the land ice at its lower boundary. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where Xis a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Organic carbon describes a family of chemical species and is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a completedescription of the species represented, for example, by using a comment attribute. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. A velocity is a vector quantity. "Upward" indicates a vector component which is positive when directed upward (negative downward). - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes.There are standard names for the alkane group as well as for some of the individual species. + A velocity is a vector quantity. "x" indicates a vector component along the grid x-axis, positive with increasing x. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethanol is C2H5OH. + A velocity is a vector quantity. "y" indicates a vector component along the grid y-axis, positive with increasing y. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes.There are standard names for the alkene group as well as for some of the individual species. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. The land ice calving rate is the rate at which ice is lost per unit area through calving into the ocean. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonlyknown as acetylene. + "lwe" means liquid water equivalent. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. The land ice basal melt rate is the rate at which ice is lost per unit area at the base of the ice. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. + "lwe" means liquid water equivalent. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. The land ice calving rate is the rate at which ice is lost per unit area through calving into the ocean. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for formic acid is HCOOH. The IUPAC name for formic acid is methanoic acid. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. "lwe" means liquid water equivalent. Specific mass balance means the net rate at which ice is added per unit area at the land ice surface due to all processes of surface accumulation and ablation. A negative value means loss of ice. - - mol m-3 + + kg - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Divalent mercury" means all compounds in which the mercury has two binding sites to other ion(s)in a salt or to other atom(s) in a molecule. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. The horizontal domain over which the quantity is calculated is described by the associated coordinate variables and coordinate bounds or by a coordinate variable or scalar coordinate variable with the standard name of "region" supplied according to section 6.1.1 of the CF conventions. - - mol m-3 + + kg - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for mercury is Hg. + "Land ice not displacing sea water" means land ice that would not alter sea level if the ice were converted to water and added to the ocean. It excludes ice shelves (and any other sort of floating ice) and it excludes a fraction of grounded ice-sheet mass equivalent to the mass of any sea water it displaces. It includes glaciers and a portion of grounded ice-sheet mass exceeding the mass of any sea water displaced. The quantity with standard name land_ice_mass_not_displacing_sea_water is the total mass integrated over an area of land ice. The geographical extent of the ice over which the mass was calculated should be described by providing bounds on the horizontal coordinate variable or scalar with the standard name of "region" supplied according to section 6.1.1 of the CF convention. - - mol m-3 + + kg m-2 s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halon1202 is CBr2F2. The IUPAC name for halon1202 is dibromo-difluoro-methane. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. Runoff flux over land ice is the difference between any available liquid water in the snowpack due to rainfall and melting minus any refreezing and liquid water retained in the snowpack. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - mol m-3 + + 1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halon1211 is CBrClF2. The IUPAC name for halon1211 is bromo-chloro-difluoro-methane. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. - - mol m-3 + + kg m-2 s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halon1301 is CBrF3. The IUPAC name for halon1301 is bromo-trifluoro-methane. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. "Specific mass flux due to calving" means the change in land ice mass per unit area resulting from iceberg calving. A negative value means loss of ice. For an area-average, the cell_methods attribute should be used to specify whether the average is over the area of the whole grid cell or the area of land ice only. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - mol m-3 + + kg m-2 s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halo2402 is C2Br2F4. The IUPAC name for halon2402 is 1,2-dibromo-1,1,2,2-tetrafluoro-ethane. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Specific mass flux due to calving and ice front melting" means the change in land ice mass per unit area resulting from iceberg calving and melting on the vertical ice front. A negative value means loss of ice. For an area-average, the cell_methods attribute should be used to specify whether the average is over the area of the whole grid cell or the area of land ice only. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - mol m-3 + + kg m-2 s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hcc140a is CH3CCl3. The IUPAC name for hcc140a is 1,1,1-trichloro-ethane. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. The land_ice_surface_melt_flux is the loss of ice mass resulting from surface melting. For an area-average, the cell_methods attribute should be used to specify whether the average is over the area of the whole grid cell or the area of land ice only. There is also a standard name for the quantity surface_snow_and_ice_melt_flux. - - mol m-3 + + kg m-2 s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for HCFC141b is CH3CCl2F. The IUPAC name for HCFC141b is 1,1-dichloro-1-fluoroethane. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Specific mass balance" means the net rate at which ice is added per unit area. A negative value means loss of ice. For an area-average, the cell_methods attribute should be used to specify whether the average is over the area of the whole grid cell or the area of land ice only. "Surface specific mass balance" means the net rate at which ice is added per unit area at the land ice surface due to all processes of surface accumulation and ablation. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for HCFC142b is CH3CClF2. The IUPAC name for HCFC142b is 1-chloro-1,1-difluoroethane. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. Specific mass balance means the net rate at which ice is added at the land ice surface due to all processes of surface accumulation and ablation. A negative value means loss of ice. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for HCFC22 is CHClF2. The IUPAC name for HCFC22 is chloro-difluoro-methane. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. A velocity is a vector quantity. "Upward" indicates a vector component which is positive when directed upward (negative downward). The surface called "surface" means the lower boundary of the atmosphere. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hexachlorobiphenyl is C12H4Cl6. This structure of this species consists of two linked benzene rings, each of which is additionally bonded to three chlorine atoms. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. A velocity is a vector quantity. "x" indicates a vector component along the grid x-axis, positive with increasing x. The surface called "surface" means the lower boundary of the atmosphere. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "HOx" means a combination of two radical species containing hydrogen and oxygen: OH and HO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. A velocity is a vector quantity. "y" indicates a vector component along the grid y-axis, positive with increasing y. The surface called "surface" means the lower boundary of the atmosphere. - - mol m-3 + + K - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen bromide is HBr. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. - - mol m-3 + + m - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen chloride is HCl. + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. "Thickness" means the vertical extent of a layer. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen cyanide is HCN. + A velocity is a vector quantity. "x" indicates a vector component along the grid x-axis, positive with increasing x. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. The vertical mean land ice velocity is the average from the bedrock to the surface of the ice. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen peroxide is H2O2. + A velocity is a vector quantity. "y" indicates a vector component along the grid y-axis, positive with increasing y. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. The vertical mean land ice velocity is the average from the bedrock to the surface of the ice. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for the hydroperoxyl radical is HO2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + A velocity is a vector quantity. "x" indicates a vector component along the grid x-axis, positive with increasing x. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for the hydroxyl radical is OH. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + A velocity is a vector quantity. "y" indicates a vector component along the grid y-axis, positive with increasing y. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. - - mol m-3 + + kg m-2 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hypobromous acid is HOBr. + The surface called "surface" means the lower boundary of the atmosphere. "Amount" means mass per unit area. The quantity with standard name land_surface_liquid_water_amount includes water in rivers, wetlands, lakes, reservoirs and liquid precipitation intercepted by the vegetation canopy. - - mol m-3 + + kg m-2 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hypochlorous acid is HOCl. + "Amount" means mass per unit area. "Water" means water in all phases. The phrase "land_water_amount", often known as "Terrestrial Water Storage", includes: surface liquid water (water in rivers, wetlands, lakes, reservoirs, rainfall intercepted by the canopy); surface ice and snow (glaciers, ice caps, grounded ice sheets not displacing sea water, river and lake ice, other surface ice such as frozen flood water, snow lying on the surface and intercepted by the canopy); subsurface water (liquid and frozen soil water, groundwater). - - mol m-3 + + degree_north - - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of source gases containing bromine (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. "Inorganic bromine" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names that use the term "brox" are used for quantities that contain all inorganic bromine species except HBr and BrONO2. + latitude + Latitude is positive northward; its units of degree_north (or equivalent) indicate this explicitly. In a latitude-longitude system defined with respect to a rotated North Pole, the standard name of grid_latitude should be used instead of latitude. Grid latitude is positive in the grid-northward direction, but its units should be plain degree. - - mol m-3 + + 1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Inorganic chlorine", sometimes referred to as Cly, describes a family of chemical species which result from the degradation of source gases containing chlorine (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as seasalt and other aerosols. "Inorganic chlorine" is the term used in standard names for all species belonging to the family that arerepresented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names that use the term "clox"are used for quantities that contain all inorganic chlorine species except HCl and ClONO2. + "X_area" means the horizontal area occupied by X within the grid cell. - - mol m-3 + + kg m-2 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for isoprene is CH2=C(CH3)CH=CH2. The IUPAC name for isoprene is 2-methyl-buta-1,3-diene. Isoprene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. + "Content" indicates a quantity per unit area. - - mol m-3 + + kg m-2 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl hydroperoxide is CH3OOH. + "Content" indicates a quantity per unit area. - - mol m-3 + + J - Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where Xis a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Mesozooplankton are zooplankton ranging between 20 micrometers and 200 micrometers in size. + The standard name "lightning radiant energy" means the energy emitted as electromagnetic radiation due to lightning. A coordinate variable of radiation_wavelength, radiation_frequency, or sensor_band_central_wavelength may be specified to indicate that the lightning_radiant_energy applies at specific wavelengths or frequencies. Bounds of the time and spatial coordinates may be specified to indicate the time interval and spatial extent over which the energy is emitted. - - mol m-3 + + 1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated in terms of B alone, neglecting all other chemical constituents of A. + "X_area_fraction" means the fraction of horizontal area occupied by X. Cloud area fraction is also called "cloud amount" and "cloud cover". The cloud area fraction is for the whole atmosphere column, as seen from the surface or the top of the atmosphere. The cloud area fraction in a layer of the atmosphere has the standard name cloud_area_fraction_in_atmosphere_layer. The chemical formula for water is H2O. - - mol m-3 + + 1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be "model_level_number", but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. "X_area_fraction" means the fraction of horizontal area occupied by X. Cloud area fraction is also called "cloud amount" and "cloud cover". The chemical formula for water is H2O. - - mol m-3 + + kg m-2 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methanol is CH3OH. + "Content" indicates a quantity per unit area. Permafrost is soil or rock that has remained at a temperature at or below zero degrees Celsius throughout the seasonal cycle for two or more years. - - mol m-3 + + kg m-2 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl bromide is CH3Br. The IUPAC name for methyl bromide is bromomethane. + "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Quantities defined for a soil layer must have a vertical coordinate variable with boundaries indicating the extent of the layer(s). - - mol m-3 + + kg m-2 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl chloride is CH3Cl. The IUPAC name for methyl chloride is chloromethane. + "Content" indicates a quantity per unit area. The surface called "surface" means the lower boundary of the atmosphere. - - mol m-3 + + kg m-2 s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl hydroperoxide is CH3OOH. + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "surface_snow" means snow lying on the surface. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - mol m-3 + + kg m-2 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl_peroxy_radical is CH3O2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + "Content" indicates a quantity per unit area. "Litter" is dead plant material in or above the soil. "C" means the element carbon and "13C" is the stable isotope "carbon-13", having six protons and seven neutrons. - - mol m-3 + + kg m-2 - Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where Xis a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Microzooplankton are zooplankton of less than 20 micrometers in size. + "Content" indicates a quantity per unit area. "Litter" is dead plant material in or above the soil. "C" means the element carbon and "14C" is the radioactive isotope "carbon-14", having six protons and eight neutrons and used in radiocarbon dating. - - mol m-3 + + kg m-2 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated in terms of B alone, neglecting all other chemical constituents of A. + "Litter" is dead plant material in or above the soil. It is distinct from coarse wood debris. The precise distinction between "fine" and "coarse" is model dependent. "Content" indicates a quantity per unit area. The sum of the quantities with standard names surface_litter_mass_content_of_carbon and subsurface_litter_mass_content_of_carbon has the standard name litter_mass_content_of_carbon. - - mol m-3 + + kg m-2 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. 'Miscellaneous phytoplankton' are all those phytoplankton that are not diatoms, diazotrophs, calcareous phytoplankton, picophytoplankton or other seperately named components of the phytoplankton population. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. + "Content" indicates a quantity per unit area. "Litter" is dead plant material in or above the soil. It is distinct from coarse wood debris. The precise distinction between "fine" and "coarse" is model dependent. The sum of the quantities with standard names surface_litter_mass_content_of_nitrogen and subsurface_litter_mass_content_of_nitrogen has the standard name litter_mass_content_of_nitrogen. - - mol m-3 + + m-3 - Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where Xis a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. 'Miscellaneous zooplankton' are all those zooplankton that are not mesozooplankton, microzooplankton or other seperately named components of the zooplankton population. + The cloud condensation nuclei number size distribution is the number concentration of aerosol particles, normalised to the decadal logarithmic size interval the concentration applies to, as a function of particle diameter, where the particle acts as condensation nucleus for liquid-phase clouds. A coordinate variable with the standard name of relative_humidity should be specified to indicate that the property refers to a specific supersaturation with respect to liquid water. A coordinate variable with the standard name of electrical_mobility_particle_diameter should be specified to indicate that the property applies at specific mobility particle sizes. To specify the relative humidity at which the particle sizes were selected, provide a scalar coordinate variable with the standard name of relative_humidity_for_aerosol_particle_size_selection. The ability of a particle to act as a condensation nucleus is determined by its size, chemical composition, and morphology. "log10_X" means common logarithm (i.e. base 10) of X. "stp" means standard temperature (0 degC) and pressure (101325 Pa). - - mol m-3 + + degree_east - - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for molecular hydrogen is H2. + longitude + Longitude is positive eastward; its units of degree_east (or equivalent) indicate this explicitly. In a latitude-longitude system defined with respect to a rotated North Pole, the standard name of grid_longitude should be used instead of longitude. Grid longitude is positive in the grid-eastward direction, but its units should be plain degree. - - mol m-3 + + 1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for the nitrate anion is NO3-. The chemical formula for the nitrite anion is NO2-. + Low type clouds are: Stratus, Stratocumulus, Cumulus, Cumulonimbus. "X_area_fraction" means the fraction of horizontal area occupied by X. Cloud area fraction is also called "cloud amount" and "cloud cover". X_type_cloud_area_fraction is generally determined on the basis of cloud type, though Numerical Weather Prediction (NWP) models often calculate them based on the vertical location of the cloud. - - mol m-3 + + m s-1 - Mole concentration means moles (amount of substance) per unit volume and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. + Convective precipitation is that produced by the convection schemes in an atmosphere model. "Precipitation" in the earth's atmosphere means precipitation of water in all phases. The abbreviation "lwe" means liquid water equivalent. "Precipitation rate" means the depth or thickness of the layer formed by precipitation per unit time. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + "lwe" means liquid water equivalent. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitric acid is HNO3. + "Precipitation" in the earth's atmosphere means precipitation of water in all phases. The abbreviation "lwe" means liquid water equivalent. "Precipitation rate" means the depth or thickness of the layer formed by precipitation per unit time. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. The chemical formula for nitric acid is HNO3. Nitric acid trihydrate, sometimes referred to as NAT, is a stable crystalline substance consisting of three molecules of water to one molecule of nitric acid. + "lwe" means liquid water equivalent. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for the nitrite anion is NO2-. + Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. "Precipitation" in the earth's atmosphere means precipitation of water in all phases. The abbreviation "lwe" means liquid water equivalent. "Precipitation rate" means the depth or thickness of the layer formed by precipitation per unit time. - - mol m-3 + + m s-1 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrogen dioxide is NO2. + Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. "lwe" means liquid water equivalent. - - mol m-3 - + + m + E137 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrogen monoxide is NO. + "lwe" means liquid water equivalent. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Atmosphere water vapor content is sometimes referred to as "precipitable water", although this term does not imply the water could all be precipitated. - - mol m-3 + + m - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrous acid is HNO2. + The abbreviation "lwe" means liquid water equivalent. "Amount" means mass per unit area. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. "Water" means water in all phases, including frozen i.e. ice and snow. The canopy water is the water on the canopy. "Canopy" means the vegetative covering over a surface. The canopy is often considered to be the outer surfaces of the vegetation. Plant height and the distribution, orientation and shape of plant leaves within a canopy influence the atmospheric environment and many plant processes within the canopy. Reference: AMS Glossary http://glossary.ametsoc.org/wiki/Canopy. - - mol m-3 - + + m + E143 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrous oxide is N2O. + The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. Convective precipitation is that produced by the convection schemes in an atmosphere model. "Precipitation" in the earth's atmosphere means precipitation of water in all phases. The abbreviation "lwe" means liquid water equivalent. - - mol m-3 + + m - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "nmvoc" means non methane volatile organic compounds. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained inA, neglecting all other chemical constituents of A. + "lwe" means liquid water equivalent. "Amount" means mass per unit area. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. - - mol m-3 + + m - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solelywith respect to the B contained in A, neglecting all other chemical constituents of A. + "frozen_water" means ice. "lwe" means liquid water equivalent. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Quantities defined for a soil layer must have a vertical coordinate variable with boundaries indicating the extent of the layer(s). - - mol m-3 + + m - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Noy" describes a family of chemical species. The family usually includes atomic nitrogen (N), nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), peroxynitric acid (HNO4), bromine nitrate (BrONO2) , chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)). The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name iscalculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + "lwe" means liquid water equivalent. "moisture" means water in all phases contained in soil. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Quantities defined for a soil layer must have a vertical coordinate variable with boundaries indicating the extent of the layer(s). - - mol m-3 + + m - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Organic detritus are particles of debris from decaying plants and animals. + The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. "Precipitation" in the earth's atmosphere means precipitation of water in all phases. The abbreviation "lwe" means liquid water equivalent. - - mol m-3 - + + m + E144 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Organic detritus are particles of debris from decaying plants and animals. + "lwe" means liquid water equivalent. "Amount" means mass per unit area. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. - - mol m-3 - + + m + E140 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Organic detritus are particles of debris from decaying plants and animals. + "lwe" means liquid water equivalent. "moisture" means water in all phases contained in soil. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including content_of_soil_layer are used. - - mol m-3 - + + m + E142 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ozone is O3. + The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. "Precipitation" in the earth's atmosphere means precipitation of water in all phases. The abbreviation "lwe" means liquid water equivalent. - - mol m-3 + + m - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + "Amount" means mass per unit area. "lwe" means liquid water equivalent. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. - - mol m-3 - + + m + E141 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The surface called "surface" means the lower boundary of the atmosphere. "lwe" means liquid water equivalent. "Amount" means mass per unit area. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. Surface amount refers to the amount on the ground, excluding that on the plant or vegetation canopy. - - mol m-3 - + + m + E182 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + "lwe" means liquid water equivalent. "Amount" means mass per unit area. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. "Water" means water in all phases. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) - - mol m-3 - + + m s-1 + - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + "lwe" means liquid water equivalent. "Water" means water in all phases. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) - - mol m-3 + + m - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for peroxyacetyl nitrate, sometimes referred to as PAN, is CH3COO2NO2. The IUPAC namefor peroxyacetyl_nitrate is nitroethaneperoxoate. + The quantity with standard name magnitude_of_derivative_of_position_wrt_model_level_number (known in differential geometry as a "scale factor") is | (dr/dk)ij|, where r(i,j,k) is the vector 3D position of the point with coordinate indices (i,j,k). It is a measure of the gridblock spacing in the z-direction. - - mol m-3 + + m - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for peroxynitric acid, sometimes referred to as PNA, is HO2NO2. + The quantity with standard name magnitude_of_derivative_of_position_wrt_x_coordinate_index (known in differential geometry as a "scale factor") is | (dr/di)jk|, where r(i,j,k) is the vector 3D position of the point with coordinate indices (i,j,k). It is a measure of the gridblock spacing in the x-direction. - - mol m-3 + + m - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. + The quantity with standard name magnitude_of_derivative_of_position_wrt_y_coordinate_index (known in differential geometry as a "scale factor") is | (dr/dj)ik|, where r(i,j,k) is the vector 3D position of the point with coordinate indices (i,j,k). It is a measure of the gridblock spacing in the y-direction. - - mol m-3 + + W m-2 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. Standard names also exist for the mole concentration of a number of components that make up the total phytoplankton population, such as diatoms, diazotrophs, calcareous phytoplankton, picophytoplankton and miscellaneous phytoplankton. + "magnitude_of_X" means magnitude of a vector X. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - mol m-3 + + m - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. + The phrase "magnitude_of_X" means magnitude of a vector X. "Displacement" means the change in geospatial position of an object that has moved over time. If possible, the time interval over which the motion took place should be specified using a bounds variable for the time coordinate variable. A displacement can be represented as a vector. Such a vector should however not be interpreted as describing a rectilinear, constant speed motion but merely as an indication that the start point of the vector is found at the tip of the vector after the time interval associated with the displacement variable. A displacement does not prescribe a trajectory. Sea ice displacement can be defined as a two-dimensional vector, with no vertical component. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - mol m-3 + + Pa - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + The surface called "surface" means the lower boundary of the atmosphere. "magnitude_of_X" means magnitude of a vector X. "Downward" indicates a vector component which is positive when directed downward (negative upward). - - mol m-3 + + kg m-3 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for acetic_acid is CH3COOH. The IUPAC name for acetic acid is ethanoic acid. - - mol m-3 + + kg m-3 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for aceto-nitrile is CH3CN. The IUPAC name for aceto-nitrile is ethanenitrile. - - mol m-3 + + kg m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Picophytoplankton are phytoplankton of less than 2 micrometers in size. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Alkanes are saturated hydrocarbons, i.e. they do not contain any chemical double bonds. Alkanes contain only hydrogen and carbon combined in the general proportions C(n)H(2n+2); "alkanes" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual alkane species, e.g., methane and ethane. - - mol m-3 + + kg m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Alkenes are unsaturated hydrocarbons as they contain chemical double bonds between adjacent carbon atoms. Alkenes contain only hydrogen and carbon combined in the general proportions C(n)H(2n); "alkenes" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual alkene species, e.g., ethene and propene. - - mol m-3 + + kg m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for alpha_hexachlorocyclohexane is C6H6Cl6. - - mol m-3 + + kg m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for radon is Rn. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for alpha_pinene is C10H16. The IUPAC name for alpha-pinene is (1S,5S)-2,6,6-trimethylbicyclo[3.1.1]hept-2-ene. - - mol m-3 + + kg m-3 - Mole concentration means moles (amount of substance) per unit volume and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ammonia is NH3. - - mol m-3 + + kg m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for sulfur dioxide is SO2. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The chemical formula for ammonium is NH4. - - mol m-3 + + kg m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one ofthe hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Anthropogenic" means influenced, caused, or created by human activity. - - mol m-3 + + kg m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Aromatic compounds in organic chemistry are compounds that contain at least one benzene ring of six carbon atoms joined by alternating single and double covalent bonds. The simplest aromatic compound is benzene itself. In standard names "aromatic_compounds" is the term used to describe the group of aromatic chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual aromatic species, e.g. benzene and xylene. - - mol m-3 + + kg m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for atomic bromine is Br. - - mol m-3 + + kg m-3 - Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Standard names also exist for the mole concentration of a number of components that make up the total zooplankton population, such as mesozooplankton, microzooplankton andmiscellaneous zooplankton. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for atomic chlorine is Cl. - - mol m-2 + + kg m-3 - "Content" indicates a quantity per unit area. The "content_of_X_in_atmosphere_layer" refers to the vertical integral between two specified levels in the atmosphere. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. For the mole content integrated from the surface to the top of the atmosphere, standard names including "atmosphere_mole_content_of_X" are used. The chemical formula for ozone is O3. "mole_content_of_ozone_in_atmosphere_layer" is usually measured in Dobson Units which are equivalent to 446.2 micromoles m-2. N.B. Data variables containing column content of ozone can be given the standard name of either equivalent_thickness_at_stp_of_atmosphere_ozone_content or atmosphere_mole_content_of_ozone. The latter name is recommended for consistency with mole content names for chemical species other than ozone. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for atomic nitrogen is N. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for acetic_acid is CH3COOH. The IUPAC name for acetic acid is ethanoic acid. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for aceto-nitrile is CH3CN. The IUPAC name for aceto-nitrile is ethanenitrile. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for beta_pinene is C10H16. The IUPAC name for beta-pinene is (1S,5S)-6,6-dimethyl-2-methylenebicyclo[3.1.1]heptane. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Aldehydes are organic compounds with a CHO group; "aldehydes" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for formaldehyde as the simplest member of the aldehydes group. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Biogenic" means influenced, caused, or created by natural processes. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Alkanes are saturated hydrocarbons, i.e. they do not contain any chemical double bonds. Alkanes contain only hydrogen and carbon combined in the general proportions C(n)H(2n+2); "alkanes" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual alkane species, e.g., methane and ethane. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for bromine chloride is BrCl. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for alpha_pinene is C10H16. The IUPAC name for alpha-pinene is (1S,5S)-2,6,6-trimethylbicyclo[3.1.1]hept-2-ene. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for bromine monoxide is BrO. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for ammonia is NH3. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for bromine nitrate is BrONO2. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "nmvoc" means non methane volatile organic compounds. "Anthropogenic" means influenced, caused, or created by human activity. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Brox" describes a family of chemical species consisting of inorganic bromine compounds with the exception of hydrogen bromide (HBr) and bromine nitrate (BrONO2). "Brox" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of source gases containing bromine (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. Standard names that use the term "inorganic_bromine" are used for quantities that contain all inorganic bromine species including HCl and ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical symbol of atomic bromine is Br. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical symbol of atomic chlorine is Cl. + 'Mass concentration' means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Chlorophylls are the green pigments found in most plants, algae and cyanobacteria; their presence is essential for photosynthesis to take place. There are several different forms of chlorophyll that occur naturally. All contain a chlorin ring (chemical formula C20H16N4) which gives the green pigment and a side chain whose structure varies. The naturally occurring forms of chlorophyll contain between 35 and 55 carbon atoms. 'Calcareous phytoplankton' are phytoplankton that produce calcite. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical symbol of atomic nitrogen is N. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for carbon dioxide is CO2. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of carbon monoxide is CO. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for beta_pinene is C10H16. The IUPAC name for beta-pinene is (1S,5S)-6,6-dimethyl-2-methylenebicyclo[3.1.1]heptane. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of carbon tetrachloride is CCl4. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "nmvoc" means non methane volatile organic compounds. "Biogenic" means influenced, caused, or created by natural processes. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC113a CCl3CF3. The IUPAC name for CFC113a is 1,1,1-trichloro-2,2,2-trifluoro-ethane. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of bromine chloride is BrCl. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC113 is CCl2FCClF2. The IUPAC name for CFC113 is 1,1,2-trichloro-1,2,2-trifluoro-ethane. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of bromine monoxide is BrO. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC114 is CClF2CClF2. The IUPAC name for CFC114 is 1,2-dichloro-1,1,2,2-tetrafluoro-ethane. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of bromine nitrate is BrONO2. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC115 is CClF2CF3. The IUPAC name for CFC115 is 1-chloro-1,1,2,2,2-pentafluoro-ethane. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Brox" describes a family of chemical species consisting of inorganic bromine compounds withthe exception of hydrogen bromide (HBr) and bromine nitrate (BrONO2). "Brox" isthe term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of source gases containing bromine (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. Standard names that use the term "inorganic_bromine" are used for quantities that contain all inorganic bromine species includingHCl and ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC11 is CFCl3. The IUPAC name fof CFC11 is trichloro-fluoro-methane. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for CFC12 is CF2Cl2. The IUPAC name for CFC12 is dichloro-difluoro-methane. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for chlorine dioxide is OClO. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for chlorine monoxide is ClO. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of carbon tetrachloride is CCl4. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for chlorine nitrate is ClONO2. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of CFC113a CCl3CF3. The IUPAC name for CFC113a is 1,1,1-trichloro-2,2,2-trifluoro-ethane. + 'Mass concentration' means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Chlorophylls are the green pigments found in most plants, algae and cyanobacteria; their presence is essential for photosynthesis to take place. There are several different forms of chlorophyll that occur naturally. All contain a chlorin ring (chemical formula C20H16N4) which gives the green pigment and a side chain whose structure varies. The naturally occurring forms of chlorophyll contain between 35 and 55 carbon atoms. Chlorophyll-a is the most commonly occurring form of natural chlorophyll. The chemical formula of chlorophyll-a is C55H72O5N4Mg. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of CFC113 is CCl2FCClF2. The IUPAC name for CFC113 is 1,1,2-trichloro-1,2,2-trifluoro-ethane. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Chlorophylls are the green pigments found in most plants, algae and cyanobacteria; their presence is essential for photosynthesis to take place. There are several different forms of chlorophyll that occur naturally. All contain a chlorin ring (chemical formula C20H16N4) which gives the green pigment and a side chain whose structure varies. The naturally occurring forms of chlorophyll contain between 35 and 55 carbon atoms. + - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of CFC114 is CClF2CClF2. The IUPAC name for CFC114 is 1,2-dichloro-1,1,2,2-tetrafluoro-ethane. + Mass concentration means mass per unit volume and is used in the construction "mass_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". Cloud droplets are spherical and typically a few micrometers to a few tens of micrometers in diameter. An upper limit of 0.2 mm diameter is sometimes used to distinguish between cloud droplets and drizzle drops, but in active cumulus clouds strong updrafts can maintain much larger cloud droplets. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of CFC115 is CClF2CF3. The IUPAC name for CFC115 is 1-chloro-1,1,2,2,2-pentafluoro-ethane. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Clox" describes a family of chemical species consisting of inorganic chlorine compounds with the exception of hydrogen chloride (HCl) and chlorine nitrate (ClONO2). "Clox" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Inorganic chlorine", sometimes referred to as Cly, describes a family of chemical species which result from the degradation of source gases containing chlorine (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as seasalt and other aerosols. Standard names that use the term "inorganic_chlorine" are used for quantities that contain all inorganic chlorine species including HCl and ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of CFC11 is CFCl3. The IUPAC name for CFC11 is trichloro-fluoro-methane. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. Coarse mode aerosol particles have a diameter of more than 1 micrometer. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of CFC12 is CF2Cl2. The IUPAC name for CFC12 is dichloro-difluoro-methane. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. Condensed water means liquid and ice. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of chlorine dioxide is OClO. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Diatoms are single-celled phytoplankton with an external skeleton made of silica. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of chlorine monoxide is ClO. + 'Mass concentration' means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B containedin A, neglecting all other chemical constituents of A. Chlorophylls are the green pigments found in most plants, algae and cyanobacteria; their presence is essential for photosynthesis to take place. There are several different forms of chlorophyll that occur naturally. All contain a chlorin ring (chemical formula C20H16N4) which gives the green pigment and a side chain whose structure varies. The naturally occurring forms of chlorophyll contain between 35 and 55 carbon atoms. Diatoms are single-celled phytoplankton with an external skeleton made of silica. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of chlorine nitrate is ClONO2. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Diatoms are single-celled phytoplankton with an external skeleton made of silica. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Clox" describes a family of chemical species consisting of inorganic chlorine compounds withthe exception of hydrogen chloride (HCl) and chlorine nitrate (ClONO2). "Clox" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Inorganic chlorine", sometimes referred to as Cly, describes a family of chemical species which result from the degradation of source gasescontaining chlorine (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as seasalt and other aerosols. Standard names that use the term "inorganic_chlorine" are used for quantities that contain all inorganic chlorine species including HCl and ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + 'Mass concentration' means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Chlorophylls are the green pigments found in most plants, algae and cyanobacteria; their presence is essential for photosynthesis to take place. There are several different forms of chlorophyll that occur naturally. All contain a chlorin ring (chemical formula C20H16N4) which gives the green pigment and a side chain whose structure varies. The naturally occurring forms of chlorophyll contain between 35 and 55 carbon atoms. In ocean modelling, diazotrophs are phytoplankton of the phylum cyanobacteria distinct from other phytoplankton groups in their ability to fix nitrogen gas in addition to nitrate and ammonium. Phytoplankton are autotrophic prokaryotic or eukaryotic organisms that live near the water surface where there is sufficient light to support photosynthesis. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Dichlorine is the molecular form of elemental chlorine with the chemical formula Cl2. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for dichlorine peroxide is Cl2O2. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of dichlorine peroxide is Cl2O2. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for dimethyl sulfide is (CH3)2S. Dimethyl sulfide is sometimes referred to as DMS. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for dinitrogen pentoxide is N2O5. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of dinitrogen pentoxide is N2O5. + Mass concentration means mass per unit volume and is used in the construction "mass_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Drizzle" means drops of water falling through the atmosphere that have a diameter typically in the range 0.2-0.5 mm. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for ethanol is C2H5OH. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethanol is C2H5OH. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for formic acid is HCOOH. The IUPAC name for formic acid is methanoic acid. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. "Divalent mercury" means all compounds in which the mercury has two binding sites to other ion(s) in a salt or to other atom(s) in a molecule. + 'Mass concentration' means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. 'Flagellates' are a class of single celled organisms that use a flagellum (whip-like structure) for feeding and locomotion. Some flagellates can photosynthesize and others feed on bacteria, with a few flagellatescapable of both. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + 'Mass concentration' means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. 'Flagellates' are a class of single celled organisms that use a flagellum (whip-like structure) for feeding and locomotion. Some flagellates can photosynthesize and others feed on bacteria, with a few flagellatescapable of both. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of halon1202 is CBr2F2. The IUPAC name for halon 1202 is dibromo-difluoro-methane. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of halon1211 is CBrClF2. The IUPAC name for halon 1211 is bromo-chloro-difluoro-methane. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for formic acid is HCOOH. The IUPAC name for formic acid is methanoic acid. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of halon1301 is CBrF3. The IUPAC name for halon 1301 is bromo-trifluoro-methane. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Divalent mercury" means all compounds in which the mercury has two binding sites to other ion(s) in a salt or to other atom(s) in a molecule. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of halon2402 is C2Br2F4. The IUPAC name for halon 2402 is 1,2-dibromo-1,1,2,2-tetrafluoro-ethane. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for mercury is Hg. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for hcc140a is CH3CCl3. The IUPAC name for hcc140a is 1,1,1-trichloro-ethane. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halon1202 is CBr2F2. The IUPAC name for halon1202 is dibromo-difluoro-methane. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for HCFC141b is CH3CCl2F. The IUPAC name for HCFC141b is 1,1-dichloro-1-fluoroethane. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halon1211 is CBrClF2. The IUPAC name for halon1211 is bromo-chloro-difluoro-methane. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for HCFC142b is CH3CClF2. The IUPAC name for HCFC142b is 1-chloro-1,1-difluoroethane. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halon1301 is CBrF3. The IUPAC name for halon1301 is bromo-trifluoro-methane. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for HCFC22 is CHClF2. The IUPAC name for HCFC22 is chloro-difluoro-methane. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halo2402 is C2Br2F4. The IUPAC name for halon2402 is 1,2-dibromo-1,1,2,2-tetrafluoro-ethane. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hcc140a is CH3CCl3. The IUPAC name for hcc140a is 1,1,1-trichloro-ethane. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "HOx" means a combination of two radical species containing hydrogen and oxygen: OH and HO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for HCFC141b is CH3CCl2F. The IUPAC name for HCFC141b is 1,1-dichloro-1-fluoroethane. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of hydrogen bromide is HBr. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for HCFC142b is CH3CClF2. The IUPAC name for HCFC142b is 1-chloro-1,1-difluoroethane. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of hydrogen chloride is HCl. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for HCFC22 is CHClF2. The IUPAC name for HCFC22 is chloro-difluoro-methane. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of hydrogen cyanide is HCN. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hexachlorobiphenyl is C12H4Cl6. This structure of this species consists of two linked benzene rings, each of which is additionally bonded to three chlorine atoms. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of hydrogen peroxide is H202. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "HOx" means a combination of two radical species containing hydrogen and oxygen: OH and HO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of hydrogen sulfide is H2S. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen bromide is HBr. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of hydroperoxyl radical is HO2. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen chloride is HCl. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen cyanide is HCN. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of hypobromous acid is HOBr. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen peroxide is H2O2. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of hypochlorous acid is HOCl. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for the hydroperoxyl radical is HO2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of bromine containing source gases (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. "Inorganic bromine" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names that use the term "brox" are used for quantities that contain all inorganic bromine species except HBr and BrONO2. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for the hydroxyl radical is OH. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. "Inorganic chlorine",sometimes referred to as Cly, describes a family of chemical species which result from the degradation of chlorine-containing source gases (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as sea-salt and other aerosols. mole_fraction_of_inorganic_chlorine is the sum of all species belonging to the family that are represented within a given model. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hypobromous acid is HOBr. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hypochlorous acid is HOCl. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for limonene is C10H16. The IUPAC name for limonene is 1-methyl-4-prop-1-en-2-yl-cyclohexene. Limonene is a member of the group of hydrocarbons known as terpenes. There arestandard names for the terpene group as well as for some of the individual species. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of source gases containing bromine (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. "Inorganic bromine" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names that use the term "brox" are used for quantities that contain all inorganic bromine species except HBr and BrONO2. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Inorganic chlorine", sometimes referred to as Cly, describes a family of chemical species which result from the degradation of source gases containing chlorine (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as seasalt and other aerosols. "Inorganic chlorine" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names that use the term "clox" are used for quantities that contain all inorganic chlorine species except HCl and ClONO2. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for methanol is CH3OH. + 'Mass concentration' means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. 'Inorganic nitrogen' describes a family of chemical species which, in an ocean model, usually includes nitrite, nitrate and ammonium which act as nitrogen nutrients. 'Inorganic nitrogen' is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Methylglyoxal is an organic molecule with the chemical formula CH3COCHO. It is also called pyruvaldehyde or 2-oxopropanal. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for isoprene is CH2=C(CH3)CH=CH2. The IUPAC name for isoprene is 2-methyl-buta-1,3-diene. Isoprene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of methyl bromide is CH3Br. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for limonene is C10H16. The IUPAC name for limonene is 1-methyl-4-prop-1-en-2-yl-cyclohexene. Limonene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of methyl chloride is CH3Cl. + Mass concentration means mass per unit volume and is used in the construction "mass_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The mass concentration of liquid water takes into account all cloud droplets and liquid precipitation regardless of drop size or fall speed. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of methyl hydroperoxide is CH3OOH. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for methyl_peroxy_radical is CH3O2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of molecular hydrogen is H2. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methanol is CH3OH. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl bromide is CH3Br. The IUPAC name for methyl bromide is bromomethane. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl chloride is CH3Cl. The IUPAC name for methyl chloride is chloromethane. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. The chemical formula for nitric acid is HNO3. Nitric acid trihydrate, sometimes referred to as NAT, is a stable crystalline substance consisting of three molecules of water to one molecule of nitric acid. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl hydroperoxide is CH3OOH. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl_peroxy_radical is CH3O2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Chlorophylls are the green pigments found in most plants, algae and cyanobacteria; their presence is essential for photosynthesis to take place. There are several different forms of chlorophyll that occur naturally. All contain a chlorin ring (chemical formula C20H16N4) which gives the green pigment and a side chain whose structure varies. The naturally occurring forms of chlorophyll contain between 35 and 55 carbon atoms. 'Miscellaneous phytoplankton' are all those phytoplankton that are not diatoms, diazotrophs, calcareous phytoplankton, picophytoplankton or other seperately named components of the phytoplankton population. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for nitrous acid is HNO2. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for molecular hydrogen is H2. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of nitrous oxide is N2O. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The chemical formula for the nitrate anion is NO3-. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "nmvoc" means non methane volatile organic compounds. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitric acid is HNO3. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Noy" describes a family of chemical species. The family usually includes atomic nitrogen (N), nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), peroxynitric acid (HNO4), bromine nitrate (BrONO2) , chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)). The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase 'expressed_as' is used in the construction A_expressed_as_B, whereB is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. The chemical formula for nitric acid is HNO3. Nitric acid trihydrate, sometimes referred to as NAT, is a stable crystalline substance consisting of three molecules of water to one molecule of nitric acid. - - 1 + + kg m-3 - tro3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrogen dioxide is NO2. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrogen monoxide is NO. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of peroxynitric acid is HNO4. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrous acid is HNO2. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrous oxide is N2O. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalsymbol for radon is Rn. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Noy" describes a family of chemical species. The family usually includes atomic nitrogen (N), nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), peroxynitric acid (HNO4), bromine nitrate (BrONO2) , chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)). The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Organic detritus are particles of debris from decaying plants and animals. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of water vapor is H2O. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Organic detritus are particles of debris from decaying plants and animals. - - 1 + + kg m-3 - Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Oxygenated" means containing oxygen. "Hydrocarbon" means a compound containing hydrogen and carbon. - - 1 + + kg m-3 - Mole ratio is used in the construction mole_ratio_of_X_to_Y_in_medium, where X and Y are both material constituents of the medium. "Medium" can take anyof the values given in the "Small scale medium" section of the standard name Guidelines document. "ratio_of_X_to_Y" means X/Y. The chemical formula for the nitrate anion is NO3-. The chemical formula of the phosphate anion is PO4 with a charge of minus three. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. - - mol kg-1 + + kg m-3 - moles_of_X_per_unit_mass_inY is also called "molality" of X in Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC11 is CFCl3. The IUPAC name fof CFC11 is trichloro-fluoro-methane. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ozone is O3. - - mol kg-1 + + kg m-3 - moles_of_X_per_unit_mass_inY is also called "molality" of X in Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. - - mol kg-1 + + kg m-3 - moles_of_X_per_unit_mass_inY is also called "molality" of X in Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for peroxyacetyl nitrate, sometimes referred to as PAN, is CH3COO2NO2. The IUPAC name for peroxyacetyl_nitrate is nitroethaneperoxoate. - - mol kg-1 + + kg m-3 - moles_of_X_per_unit_mass_inY is also called "molality" of X in Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for peroxynitric acid, sometimes referred to as PNA, is HO2NO2. - - mol kg-1 + + kg m-3 - moles_of_X_per_unit_mass_inY is also called "molality" of X in Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The term "peroxy_radicals" means all organic and inorganic peroxy radicals. This includes HO2 and all organic peroxy radicals, sometimes referred to as RO2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. - - mol kg-1 + + kg m-3 - moles_of_X_per_unit_mass_inY is also called "molality" of X in Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". Petroleum hydrocarbons are compounds containing just carbon and hydrogen originating from the fossil fuel crude oil. - - mol kg-1 + + kg m-3 - moles_of_X_per_unit_mass_inY is also called "molality" of X in Y, where X is a material constituent of Y. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. - - W m-2 + + kg m-3 - "longwave" means longwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mass concentration means mass per unit volume and is used in the construction "mass_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. Standard names also exist for the mass concentration of a number of components that make up the total phytoplankton population, such as diatoms, diazotrophs, calcareous phytoplankton, picophytoplankton and miscellaneous phytoplankton. Chlorophylls are the green pigments found in most plants, algae and cyanobacteria; their presence is essential for photosynthesis to take place. There are several different forms of chlorophyll that occur naturally. All contain a chlorin ring (chemical formula C20H16N4) which gives the green pigment and a side chain whose structure varies. The naturally occurring forms of chlorophyll contain between 35 and 55 carbon atoms. - - W m-2 + + kg m-3 - A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "longwave" means longwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Chlorophylls are the green pigments found in most plants, algae and cyanobacteria; their presence is essential for photosynthesis to take place. There are several different forms of chlorophyll that occur naturally. All contain a chlorin ring (chemical formula C20H16N4) which gives the green pigment and a side chain whose structure varies. The naturally occurring forms of chlorophyll contain between 35 and 55 carbon atoms. Picophytoplankton are phytoplankton of less than 2 micrometers in size. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. - - W m-2 + + kg m-3 - rtmt - Fluxes at the top_of_atmosphere_model differ from TOA fluxes only if the model TOA fluxes make some allowance for the atmosphere above the top of the model; if not, it is usual to give standard names with toa to the fluxes at the top of the model atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. To specify the relative humidity and temperature at which the particle size applies, provide scalar coordinate variables with the standard names of, respectively, "relative_humidity" and "air_temperature." - - W m-2 + + kg m-3 - "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. "shortwave" means shortwave radiation. + Mass concentration means mass per unit volume and is used in the construction "mass_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. The phrase "sea_salt_cation" is the term used in standard names to describe collectively the group of cationic species that occur in sea salt. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Sea salt cations are mainly sodium (Na+), but also include potassium (K+), magnesium (Mg2+), calcium (Ca2+) and rarer cations. Where possible, the data variable should be accompanied by a complete description of the ions represented, for example, by using a comment attribute. - - W m-2 + + kg m-3 - "shortwave" means shortwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mass concentration means mass per unit volume and is used in the construction "mass_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. - - W m-2 + + kg m-3 - rsntpcs - A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "shortwave" means shortwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. "Pm1 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 1 micrometer. To specify the relative humidity and temperature at which the particle size applies, provide scalar coordinate variables with the standard names of "relative_humidity" and "air_temperature". - - mol m-2 s-1 + + kg m-3 - "Productivity of carbon" refers to the production of biomass expressed as the mass of carbon which it contains. "Productivity" means production per unit area. Net primary productivity is the excess of gross primary productivity of organic carbon (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Standard names also exist for aragonite, another polymorph of calcium carbonate. 'Calcareous phytoplankton' are phytoplankton that produce calcite. Phytoplankton are autotrophic prokaryotic oreukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. To specify the relative humidity and temperature at which the particle size applies, provide scalar coordinate variables with the standard names of "relative_humidity" and "air_temperature." - - mol m-2 s-1 + + kg m-3 - "Productivity of carbon" refers to the production of biomass expressed as the mass of carbon which it contains. "Productivity" means production per unit area. Net primary productivity is the excess of gross primary productivity of organic carbon (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. Diatoms are single-celled phytoplankton with an external skeleton made of silica. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient lightto support photosynthesis. + Mass concentration means mass per unit volume and is used in the construction "mass_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. The phrase "sea_salt_cation" is the term used in standard names to describe collectively the group of cationic species that occur in sea salt. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Sea salt cations are mainly sodium (Na+), but also include potassium (K+), magnesium (Mg2+), calcium (Ca2+) and rarer cations. Where possible, the data variable should be accompanied by a complete description of the ions represented, for example, by using a comment attribute. - - mol m-2 s-1 + + kg m-3 - "Productivity of carbon" refers to the production of biomass expressed as the mass of carbon which it contains. "Productivity" means production per unit area. Net primary productivity is the excess of gross primary productivity of organic carbon (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. In ocean modelling, diazotrophs are phytoplankton of the phylum cyanobacteria distinct from other phytoplankton groupsin their ability to fix nitrogen gas in addition to nitrate and ammonium. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. + Mass concentration means mass per unit volume and is used in the construction "mass_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. - - mol m-2 s-1 + + kg m-3 - "Productivity of carbon" refers to the production of biomass expressed as the mass of carbon which it contains. "Productivity" means production per unit area. Net primary productivity is the excess of gross primary productivity of organic carbon (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. 'Miscellaneous phytoplankton' are all those phytoplankton that are not diatoms, diazotrophs, calcareous phytoplankton, picophytoplankton or other seperately named components of the phytoplankton population. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. "Primary particulate organic matter " means all organic matter emitted directly to the atmosphere as particles except elemental carbon. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. - - mol m-2 s-1 + + kg m-3 - "Productivity of carbon" refers to the production of biomass expressed as the mass of carbon which it contains. "Productivity" means production per unit area. Net primary productivity is the excess of gross primary productivity of organic carbon (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. - - mol m-2 s-1 + + kg m-3 - "Productivity of carbon" refers to the production of biomass expressed as the mass of carbon which it contains. "Productivity" means production per unit area. Net primary productivity is the excess of gross primary productivity of organic carbon (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. Picophytoplankton are phytoplankton of less than 2 micrometers in size. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. - - mol m-2 s-1 + + kg m-3 - "Productivity of carbon" refers to the production of biomass expressed as the mass of carbon which it contains. "Productivity" means production per unit area. Net primary productivity is the excess of gross primary productivity of organic carbon (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. "Nitrate utilization" means net primary production by phytoplankton based on nitrate alone. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The chemical formula for the nitrate anion is NO3-. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for radon is Rn. - - kg m-2 s-1 + + kg m-3 - Net primary productivity is the excess of gross_primary_producivity (rate of synthesis of biomass per unit area from inorganic precursors by autotrophs, or "producers", especially by photosynthesising plants using sunlight for energy) over the rate at which they themselves respire some of this biomass (plant_respiration, assuming all producers to be plants). "Productivity of carbon" refers to the production of biomass expressed as the mass of carbon which it contains. "Productivity" means production per unit area. + Mass concentration means mass per unit volume and is used in the construction "mass_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Rain" means drops of water falling through the atmosphere that have a diameter greater than 0.5 mm. - - kg m-2 s-1 + + kg m-3 - Net primary productivity is the excess of gross_primary_producivity (rate of synthesis of biomass per unit area from inorganic precursors by autotrophs, or "producers", especially by photosynthesising plants using sunlight for energy) over the rate at which they themselves respire some of this biomass (plant_respiration, assuming all producers to be plants). "Productivity of carbon" refers to the production of biomass expressed as the mass of carbon which it contains. "Productivity" means production per unit area. + Mass concentration means mass per unit volume and is used in the construction "mass_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The phrase "sea_salt_cation" is the term used in standard names to describe collectively the group of cationic species that occur in sea salt. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Sea salt cations are mainly sodium (Na+), but also include potassium (K+), magnesium (Mg2+), calcium (Ca2+) and rarer cations. Where possible, the data variable should be accompanied by a complete description of the ions represented, for example, by using a comment attribute. - - kg m-2 s-1 + + kg m-3 - Net primary productivity is the excess of gross_primary_producivity (rate of synthesis of biomass per unit area from inorganic precursors by autotrophs, or "producers", especially by photosynthesising plants using sunlight for energy) over the rate at which they themselves respire some of this biomass (plant_respiration, assuming all producers to be plants). "Productivity of carbon" refers to the production of biomass expressed as the mass of carbon which it contains. "Productivity" means production per unit area. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. - - kg m-2 s-1 + + kg m-3 - Net primary productivity is the excess of gross_primary_producivity (rate of synthesis of biomass per unit area from inorganic precursors by autotrophs, or "producers", especially by photosynthesising plants using sunlight for energy) over the rate at which they themselves respire some of this biomass (plant_respiration, assumingall producers to be plants). "Productivity of carbon" refers to the productionof biomass expressed as the mass of carbon which it contains. "Productivity" means production per unit area. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Secondary particulate organic matter" means particulate organic matter formed within the atmosphere from gaseous precursors. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. - - W m-2 + + kg m-3 - "longwave" means longwave radiation. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Net absorbed radiation is the difference between absorbed and emitted radiation. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. - - W m-2 + + kg m-3 - - "shortwave" means shortwave radiation. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Net absorbed radiation is the difference between absorbed and emitted radiation. + trsul + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". - - W m-2 - 115 + + kg m-3 + - "longwave" means longwave radiation. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The chemical formula for the sulfate anion is SO4(2-). - - W m-2 + + kg m-3 - rlntpcs - A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "longwave" means longwave radiation. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for sulfur dioxide is SO2. - - W m-2 - 116 + + kg m-3 + - "shortwave" means shortwave radiation. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. - - W m-2 + + kg m-3 - A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "shortwave" means shortwave radiation. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Terpenes are hydrocarbons, that is, they contain only hydrogen and carbon combined in the general proportions (C5H8)n where n is an integer greater than on equal to one. The term "terpenes" is used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual terpene species, e.g., isoprene and limonene. - - 1 + + kg m-3 - "Normalized_difference_vegetation_index", usually abbreviated to NDVI, is an index calculated from reflectances measured in the visible and near infrared channels. It is calculated as NDVI = (NIR - R) / (NIR + R) where NIR is the reflectance in the near-infrared band and R is the reflectance in the red visible band. Reflectance is the ratio of the reflected over the incoming radiation in each spectral band. The calculated value of NDVI depends on the precise definitions of the spectral bands and these definitions may vary between different models and remote sensing instruments. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. - - W m-1 + + kg m-3 - "Northward" indicates a vector component which is positive when directed northward (negative southward). Transport across_unit_distance means expressed per unit distance normal to the direction of transport. Dry static energy is the sum of enthalpy and potential energy (itself the sum of gravitational and centripetal potential energy). Enthalpy can be written either as (1) CpT, where Cp is heat capacity at constant pressure, T is absolute temperature, or (2) U+pV, where U is internal energy, p is pressure and V is volume. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. "Volcanic ash" means the fine-grained products of explosive volcanic eruptions, such as minerals or crystals, older fragmented rock (e.g. andesite) and glass. Particles within a volcanic ash cloud have diameters less than 2 mm. "Volcanic ash" does not include non-volcanic dust. - - W + + kg m-3 - "Northward" indicates a vector component which is positive when directed northward (negative southward). "Atmosphere heat transport" means total heat transport by the atmosphere by all processes. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. - - kg s-1 m-1 + + kg m-3 - "Water" means water in all phases. "Northward" indicates a vector component which is positive when directed northward (negative southward). Transport across_unit_distance means expressed per unit distance normal to the direction of transport. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. - - kg m-1 s-1 + + kg m-3 - "Northward" indicates a vector component which is positive when directed northward (negative southward). Transport across_unit_distance means expressed per unit distance normal to the direction of transport. + Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. - - s-1 + + kg m-2 - A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Northward" indicates a vector component which is positive when directed northward (negative southward). Sea ice velocity is defined as a two-dimensional vector, with no vertical component. "component_derivative_of_X" means derivative of X with respect to distance in the component direction, which may be northward, southward, eastward, westward, x or y. The last two indicate derivatives along the axes of the grid, in the case where they are not true longitude and latitude. The named quantity is a component of the strain rate tensor for sea ice. + "Content" indicates a quantity per unit area. "Vegetation" means any living plants e.g. trees, shrubs, grass. "Litter" is dead plant material in or above the soil. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. Examples of "forestry and agricultural products" are paper, cardboard, furniture, timber for construction, biofuels and food for both humans and livestock. Models that simulate land use changes have one or more pools of carbon that represent these products in order to conserve carbon and allow its eventual release into the atmosphere, for example, when the products decompose in landfill sites. "C" means the element carbon and "13C" is the stable isotope "carbon-13", having six protons and seven neutrons. - - m3 s-2 + + kg m-2 - "Eliassen Palm flux" is a widely used vector in the meridional plane, and the divergence of this flux appears as a forcing in the Transformed Eulerian mean formulation of the zonal mean zonal wind equation. "Northward" indicates a vector component which is positive when directed northward (negative southward). + "Content" indicates a quantity per unit area. "Vegetation" means any living plants e.g. trees, shrubs, grass. "Litter" is dead plant material in or above the soil. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. Examples of "forestry and agricultural products" are paper, cardboard, furniture, timber for construction, biofuels and food for both humans and livestock. Models that simulate land use changes have one or more pools of carbon that represent these products in order to conserve carbon and allow its eventual release into the atmosphere, for example, when the products decompose in landfill sites. "C" means the element carbon and "14C" is the radioactive isotope "carbon-14", having six protons and eight neutrons and used in radiocarbon dating. - - W m-2 + + kg m-2 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Northward" indicates a vector component which is positive when directed northward (negative southward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + "Content" indicates a quantity per unit area. "Vegetation" means any living plants e.g. trees, shrubs, grass. "Litter" is dead plant material in or above the soil. It is distinct from coarse wood debris. The precise distinction between "fine" and "coarse" is model dependent. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including "content_of_soil_layer" are used. Examples of "forestry and agricultural products" are paper, cardboard, furniture, timber for construction, biofuels and food for both humans and livestock. Models that simulate land use changes have one or more pools of carbon that represent these products in order to conserve carbon and allow its eventual release into the atmosphere, for example, when the products decompose in landfill sites. - - kg m-2 s-1 + + kg m-2 - "Northward" indicates a vector component which is positive when directed northward (negative southward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + "condensed_water" means liquid and ice. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. - - Pa + + kg m-2 - tauvcorr - "Northward" indicates a vector component which is positive when directed northward (negative southward). Momentum flux is dimensionally equivalent to stress and pressure. It is a tensor quantity. Flux correction is also called "flux adjustment". A positive flux correction is downward i.e. added to the ocean. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. - - kg s-1 + + kg m-2 - "Northward" indicates a vector component which is positive when directed northward (negative southward). Ocean transport means transport by all processes, both sea water and sea ice. + "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. - - kg s-1 + + kg m-2 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Northward" indicates a vector component which is positive when directed northward (negative southward). Northward transport by bolus advection in an ocean model means the part due to a scheme representing eddy-induced effects not included in the velocity field. + "Content" indicates a quantity per unit area. "Vegetation" means any living plants e.g. trees, shrubs, grass. "Litter" is dead plant material in or above the soil. It is distinct from coarse wood debris. The precise distinction between "fine" and "coarse" is model dependent. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including "content_of_soil_layer" are used. Examples of "forestry and agricultural products" are paper, cardboard, furniture, timber for construction, biofuels and food for both humans and livestock. Models that simulate land use changes have one or more pools of carbon that represent these products in order to conserve carbon and allow its eventual release into the atmosphere, for example, when the products decompose in landfill sites. - - kg s-1 + + kg m-2 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Northward" indicates a vector component which is positive when directed northward (negative southward). Northward transport by diffusion means the part due to horizontal or isopyncal diffusion schemes in an ocean model, but not including the "bolus" or Gent-McWilliams velocity. + "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. "Water" means water in all phases. - - kg s-1 + + kg m-2 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Northward" indicates a vector component which is positive when directed northward (negative southward). Northward transport by the ocean gyre is geometrically defined as being the part due to the vertical integral of the product of deviations of velocity and tracer from their zonal means. The velocity does not include "bolus" or Gent-McWilliams velocity. + "Water" means water in all phases. "Content" indicates a quantity per unit area. The mass content of water in soil refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including "content_of_soil_layer" are used. - - kg s-1 + + kg m-2 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Northward" indicates a vector component which is positive when directed northward (negative southward). Northward transport by (meridional) overturning is geometrically defined as being the part due to the vertical integral of the product of zonal means of velocity and tracer. The velocity does not include "bolus" or Gent-McWilliams velocity. + "Content" indicates a quantity per unit area. "Water" means water in all phases. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be "model_level_number", but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Quantities defined for a soil layer must have a vertical coordinate variable with boundaries indicating the extent of the layer(s). - - W + + kg m-2 - "Northward" indicates a vector component which is positive when directed northward (negative southward). Ocean transport means transport by all processes, both sea water and sea ice. + "Content" indicates a quantity per unit area. The content of a soil layer is the vertical integral of the specified quantity within the layer. The quantity with standard name mass_content_of_water_in_soil_layer_defined_by_root_depth is the vertical integral between the surface and the depth to which plant roots penetrate. A coordinate variable or scalar coordinate variable with standard name root_depth can be used to specify the extent of the layer. "Water" means water in all phases. - - W + + kg m-2 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Northward" indicates a vector component which is positive when directed northward (negative southward). Northward transport by bolus advection in an ocean model means the part due to a scheme representing eddy-induced effects not included in the velocity field. + "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be "model_level_number", but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. The "content_of_X_in_atmosphere_layer" refers to the vertical integral between two specified levels in the atmosphere. The chemical formula for water is H2O. "O" means the element "oxygen" and "17O" is the stable isotope "oxygen-17". - - W + + kg m-2 - htovdiff - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Northward" indicates a vector component which is positive when directed northward (negative southward). Northward transport by diffusion means the part due to horizontal or isopyncal diffusion schemes in an ocean model, but not including the "bolus" or Gent-McWilliams velocity. + + "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be "model_level_number", but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. The "content_of_X_in_atmosphere_layer" refers to the vertical integral between two specified levels in the atmosphere. The chemical formula for water is H2O. "O" means the element "oxygen" and "18O" is the stable isotope "oxygen-18". - - W + + kg m-2 - htovgyre - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Northward" indicates a vector component which is positive when directed northward (negative southward). Northward transport by the ocean gyre is geometrically defined as being the part due to the vertical integral of the product of deviations of velocity and tracer from their zonal means. The velocity does not include "bolus" or Gent-McWilliams velocity. + + "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be "model_level_number", but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. The "content_of_X_in_atmosphere_layer" refers to the vertical integral between two specified levels in the atmosphere. The chemical formula for water is H2O. "H" means the element "hydrogen" and "2H" is the stable isotope "hydrogen-2", usually called "deuterium". The construction "X_containing_single_Y" means the standard name refers to only that part of X composed of molecules containing a single atom of isotope Y. - - W + + kg m-2 - htovovrt - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Northward" indicates a vector component which is positive when directed northward (negative southward). Northward transport by (meridional) overturning is geometrically defined as being the part due to the vertical integral of the product of zonal means of velocity and tracer. The velocity does not include "bolus" or Gent-McWilliams velocity. + + "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. - - kg s-1 + + kg m-2 s-1 - "Northward" indicates a vector component which is positive when directed northward (negative southward). Ocean transport means transport by all processes, both sea water and sea ice. + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Examples of "forestry and agricultural products" are paper, cardboard, furniture, timber for construction, biofuels and food for both humans and livestock. Models that simulate land use changes have one or more pools of carbon that represent these products in order to conserve carbon and allow its eventual release into the atmosphere, for example, when the products decompose in landfill sites. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The definition of "crop" is model dependent, for example, some models may include fruit trees, trees grown for timber or other types of agricultural and forestry planting as crops. Crop harvesting means the human activity of collecting plant materials for the purpose of turning them into forestry or agricultural products. - - kg s-1 + + kg m-2 s-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Northward" indicates a vector component which is positive when directed northward (negative southward). Northward transport by bolus advection in an ocean model means the part due to a scheme representing eddy-induced effects not included in the velocity field. + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Vegetation" means any living plants e.g. trees, shrubs, grass. "Litter" is dead plant material in or above the soil. It is distinct from coarse wood debris. The precise distinction between "fine" and "coarse" is model dependent. The sum of the quantities with standard names mass_flux_of_carbon_into_litter_from_vegetation_due_to_mortality and mass_flux_of_carbon_into_litter_from_vegetation_due_to_senescence is mass_flux_of_carbon_into_litter_from_vegetation. - - kg s-1 + + kg m-2 s-1 - sltovdiff - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Northward" indicates a vector component which is positive when directed northward (negative southward). Northward transport by diffusion means the part due to horizontal or isopyncal diffusion schemes in an ocean model, but not including the "bolus" or Gent-McWilliams velocity. + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Vegetation" means any living plants e.g. trees, shrubs, grass. "Litter" is dead plant material in or above the soil. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The term "mortality" means the loss of living biomass due to plant death. It refers to the death of the whole plant, not only the leaves. - - kg s-1 + + kg m-2 s-1 - sltovgyre - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Northward" indicates a vector component which is positive when directed northward (negative southward). Northward transport by the ocean gyre is geometrically defined as being the part due to the vertical integral of the product of deviations of velocity and tracer from their zonal means. The velocity does not include "bolus" or Gent-McWilliams velocity. + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Vegetation" means any living plants e.g. trees, shrubs, grass. "Litter" is dead plant material in or above the soil. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The term "senescence" means loss of living biomass excluding plant death, e.g. leaf drop and other seasonal effects. The term refers to changes in the whole plant and is not confined only to leaf drop. - - kg s-1 + + kg m-2 s-1 - sltovovrt - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Northward" indicates a vector component which is positive when directed northward (negative southward). Northward transport by (meridional) overturning is geometrically defined as being the part due to the vertical integral of the product of zonal means of velocity and tracer. The velocity does not include "bolus" or Gent-McWilliams velocity. + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "River" refers to water in the fluvial system (stream and floodplain). - - m + + kg m-2 s-1 - "Northward" indicates a vector component which is positive when directed northward (negative southward). "Displacement" means the change in geospatial position of an object that has moved over time. If possible, the time interval over which the motion took place should be specified using a bounds variable for the time coordinate variable. A displacement can be represented as a vector. Such a vector should however not be interpreted as describing a rectilinear, constant speed motion but merely as an indication that the start point of the vector is found at the tip of the vector after the time interval associated with the displacement variable. A displacement does not prescribe a trajectory. Sea ice displacement can be defined as a two-dimensional vector, with no vertical component. A northward displacement is the distance calculated from the change in a moving object's latitude between the start and end of the time interval associated with the displacement variable. + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Vegetation" means any living plants e.g. trees, shrubs, grass. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The term "mortality" means the loss of living biomass due to plant death. It refers to the death of the whole plant, not only the leaves. - - m s-1 - 96 + + kg m-2 s-1 + - A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). Sea ice velocity is defined as a two-dimensional vector, with no vertical component. + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Vegetation" means any living plants e.g. trees, shrubs, grass. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The term "senescence" means loss of living biomass excluding plant death, e.g. leaf drop and other seasonal effects. The term refers to changes in the whole plant and is not confined only to leaf drop. - - m s-1 - 50 + + kg m-2 s-1 + - A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Leaching" means the loss of water soluble chemical species from soil. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. - - m s-1 + + kg m-2 s-1 - A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Nitrogen compounds" summarizes all chemical species containing nitrogen atoms. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "River" refers to water in the fluvial system (stream and floodplain). - - m s-1 + + kg m-2 s-1 - "Northward" indicates a vector component which is positive when directed northward (negative southward). + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Nitrogen compounds" summarizes all chemical species containing nitrogen atoms. "Litter" is dead plant material in or above the soil. It is distinct from coarse wood debris. The precise distinction between "fine" and "coarse" is model dependent. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Remineralization is the degradation of organic matter into inorganic forms of carbon, nitrogen, phosphorus and other micronutrients, which consumes oxygen and releases energy. Immobilisation of nitrogen refers to retention of nitrogen by micro-organisms under certain conditions, making it unavailable for plants. - + kg m-2 s-1 - "Northward" indicates a vector component which is positive when directed northward (negative southward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Nitrogen compounds" summarizes all chemical species containing nitrogen atoms. "Vegetation" means any living plants e.g. trees, shrubs, grass. The term "plants" refers to the kingdom of plants in the modern classification which excludes fungi. Plants are autotrophs i.e. "producers" of biomass using carbon obtained from carbon dioxide. "Litter" is dead plant material in or above the soil. It is distinct from coarse wood debris. The precise distinction between "fine" and "coarse" is model dependent. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Leaching" means the loss of water soluble chemical species from soil. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. - - kg m-1 s-1 + + 1 - "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. "Northward" indicates a vector component which is positive when directed northward (negative southward). Transport across_unit_distance means expressed per unit distance normal to the direction of transport. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for acetic_acid is CH3COOH. The IUPAC name for acetic acid is ethanoic acid. - - m s-1 - 34 E132 - va - "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + 1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for aceto-nitrile is CH3CN. The IUPAC name for aceto-nitrile is ethanenitrile. - - s-1 - 46 + + 1 + - "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) Wind shear is the derivative of wind with respect to height. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Alkanes are saturated hydrocarbons, i.e. they do not contain any chemical double bonds. Alkanes contain only hydrogen and carbon combined in the general proportions C(n)H(2n+2); "alkanes" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual alkane species, e.g., methane and ethane. - - m-3 + + 1 - "Number concentration" means the number of particles or other specified objects per unit volume. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Alkenes are unsaturated hydrocarbons as they contain chemical double bonds between adjacent carbon atoms. Alkenes contain only hydrogen and carbon combined in the general proportions C(n)H(2n); "alkenes" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual alkene species, e.g., ethene and propene. - - m-3 + + 1 - "Number concentration" means the number of particles or other specified objects per unit volume. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for alpha_hexachlorocyclohexane is C6H6Cl6. - - m-3 + + 1 - "Number concentration" means the number of particles or other specified objects per unit volume. cloud_top refers to the top of the highest cloud. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for alpha_pinene is C10H16. The IUPAC name for alpha-pinene is (1S,5S)-2,6,6-trimethylbicyclo[3.1.1]hept-2-ene. - - m-3 + + 1 - "Number concentration" means the number of particles or other specified objects per unit volume. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. Coarse mode aerosol is aerosol having a diameter of more than 1 micrometer. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ammonia is NH3. - - m-3 + + 1 - "Number concentration" means the number of particles or other specified objects per unit volume. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Mass_fraction_of_ammonium" means that the mass is expressed as mass of NH4. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. - - m-3 + + 1 - "Number concentration" means the number of particles or other specified objects per unit volume. cloud_top refers to the top of the highest cloud. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Anthropogenic" means influenced, caused, or created by human activity. - - m-3 + + 1 - "Number concentration" means the number of particles or other specified objects per unit volume. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. Nucleation mode aerosol is aerosol having a diameter of less than 3 nanometers. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Aromatic compounds in organic chemistry are compounds that contain at least one benzene ring of six carbon atoms joined by alternating single and double covalent bonds. The simplest aromatic compound is benzene itself. In standard names "aromatic_compounds" is the term used to describe the group of aromatic chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual aromatic species, e.g. benzene and xylene. - + 1 - Air temperature is the bulk temperature of the air, not the surface (skin) temperature. A variable whose standard name has the form number_of_days_with_X_below|above_threshold is a count of the number of days on which the condition X_below|above_threshold is satisfied. It must have a coordinate variable or scalar coordinate variable with the a standard name of X to supply the threshold(s). It must have a climatological time variable, and a cell_methods entry for within days which describes the processing of quantity X before the threshold is applied. A number_of_days is an extensive quantity in time, and the cell_methods entry for over days should be "sum". + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for atomic bromine is Br. - + 1 - Air temperature is the bulk temperature of the air, not the surface (skin) temperature. A variable whose standard name has the form number_of_days_with_X_below|above_threshold is a count of the number of days on which the condition X_below|above_threshold is satisfied. It must have a coordinate variable or scalar coordinate variable with the a standard name of X to supply the threshold(s). It must have a climatological time variable, and a cell_methods entry for within days which describes the processing of quantity X before the threshold is applied. A number_of_days is an extensive quantity in time, and the cell_methods entry for over days should be "sum". + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for atomic chlorine is Cl. - + 1 - "Amount" means mass per unit area. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. "lwe" means liquid water equivalent. A variable whose standard name has the form number_of_days_with_X_below|above_threshold is a count of the number of days on which the condition X_below|above_threshold is satisfied. It must have a coordinate variable or scalar coordinate variable with the a standard name of X to supply the threshold(s). It must have a climatological time variable, and a cell_methods entry for within days which describes the processing of quantity X before the threshold is applied. A number_of_days is an extensive quantity in time, and the cell_methods entry for over days should be "sum". + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for atomic nitrogen is N. - + 1 - Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) The wind speed is the magnitude of the wind velocity. A variable whose standard name has the form number_of_days_with_X_below|above_threshold is a count of the number of days on which the condition X_below|above_threshold is satisfied. It must have a coordinate variable or scalar coordinate variable with the a standard name of X to supply the threshold(s). It must have a climatological time variable, and a cell_methods entry for within days which describes the processing of quantity X before the threshold is applied. A number_of_days is an extensive quantity in time, and the cell_methods entry for over days should be "sum". + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. - - m-2 + + 1 - + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for beta_pinene is C10H16. The IUPAC name for beta-pinene is (1S,5S)-6,6-dimethyl-2-methylenebicyclo[3.1.1]heptane. - - kg s-1 + + 1 - The barotropic stream function with the dimensions of volume transport has the standard name ocean_barotropic_streamfunction. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Biogenic" means influenced, caused, or created by natural processes. - - m3 s-1 + + 1 - stfbaro - + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for bromine chloride is BrCl. - - W + + 1 - "x" indicates a vector component along the grid x-axis, positive with increasing x. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for bromine monoxide is BrO. - - W + + 1 - "x" indicates a vector component along the grid x-axis, positive with increasing x. Transport by bolus advection in an ocean model means the part due to a scheme representing eddy-induced effects not included in the velocity field. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for bromine nitrate is BrONO2. - - W + + 1 - "x" indicates a vector component along the grid x-axis, positive with increasing x. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Brox" describes a family of chemical species consisting of inorganic bromine compounds with the exception of hydrogen bromide (HBr) and bromine nitrate (BrONO2). "Brox" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompaniedby a complete description of the species represented, for example, by using a comment attribute. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of source gases containing bromine (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. Standard names that use the term "inorganic_bromine" are usedfor quantities that contain all inorganic bromine species including HCl and ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - W + + 1 - "y" indicates a vector component along the grid y-axis, positive with increasing y. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. - - W + + 1 - "y" indicates a vector component along the grid y-axis, positive with increasing y. Transport by bolus advection in an ocean model means the part due to a scheme representing eddy-induced effects not included in the velocity field. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for carbon dioxide is CO2. - - W + + 1 - "y" indicates a vector component along the grid y-axis, positive with increasing y. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + The chemical formula for carbon dioxide is CO2. Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". A "tracer" is a quantity advected by a model to facilitate analysis of flow patterns. - - K m + + 1 - "integral_of_Y_wrt_X" means int Y dX. The data variable should have an axis for X specifying the limits of the integral as bounds. "wrt" means with respect to. Depth is the vertical distance below the surface. Sea water temperature is the in situ temperature of the sea water. For observed data, depending on the period during which the observation was made, the measured in situ temperature was recorded against standard "scales". These historical scales include the International Practical Temperature Scale of 1948 (IPTS-48; 1948-1967), the International Practical Temperature Scale of 1968 (IPTS-68, Barber, 1969; 1968-1989) and the International Temperature Scale of 1990 (ITS-90, Saunders 1990; 1990 onwards). Conversion of data between these scales follows t68 = t48 - (4.4 x 10e-6) * t48(100 - t - 48); t90 = 0.99976 * t68. Observations made prior to 1948 (IPTS-48) have not been documented and therefore a conversion cannot be certain. Differences between t90 and t68 can be up to 0.01 at temperatures of 40 C and above; differences of 0.002-0.007 occur across the standard range of ocean temperatures (-10 - 30 C). The International Equation of State of Seawater 1980 (EOS-80, UNESCO, 1981) and the Practical Salinity Scale (PSS-78) were both based on IPTS-68, while the Thermodynamic Equation of Seawater 2010 (TEOS-10) is based on ITS-90. References: Barber, 1969, doi: 10.1088/0026-1394/5/2/001; UNESCO, 1981; Saunders, 1990, WOCE Newsletter, 10, September 1990. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of carbon monoxide is CO. - - m2 s-1 + + 1 - + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of carbon tetrachloride is CCl4. - - W m-2 + + 1 - Friction, leading to the dissipation of kinetic energy, arises in ocean models as a result of the viscosity of sea water. Generally, the lateral (xy) viscosity is given a large value to maintain the numerical stability of the model. In contrast, the vertical viscosity is usually much smaller. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC113a CCl3CF3. The IUPAC name for CFC113a is 1,1,1-trichloro-2,2,2-trifluoro-ethane. - - W m-2 + + 1 - Friction, leading to the dissipation of kinetic energy, arises in ocean models as a result of the viscosity of sea water. Generally, the lateral (xy) viscosity is given a large value to maintain the numerical stability of the model. In contrast, the vertical viscosity is usually much smaller. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC113 is CCl2FCClF2. The IUPAC name for CFC113 is 1,1,2-trichloro-1,2,2-trifluoro-ethane. - - kg m-2 + + 1 - "Content" indicates a quantity per unit area. "Dissolvedinorganic carbon" describes a family of chemical species in solution, including carbon dioxide, carbonic acid and the carbonate and bicarbonate anions. "Dissolved inorganic carbon" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC114 is CClF2CClF2. The IUPAC name for CFC114 is 1,2-dichloro-1,1,2,2-tetrafluoro-ethane. - - kg s-1 + + 1 - "x" indicates a vector component along the grid x-axis, positive with increasing x. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC115 is CClF2CF3. The IUPAC name for CFC115 is 1-chloro-1,1,2,2,2-pentafluoro-ethane. - - kg s-1 + + 1 - "x" indicates a vector component along the grid x-axis, positive with increasing x. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC11 is CFCl3. The IUPAC name fof CFC11 is trichloro-fluoro-methane. - - kg s-1 + + 1 - "x" indicates a vector component along the grid x-axis, positive with increasing x. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Transport by bolus advection in an ocean model means the part due to a scheme representing eddy-induced effects not included in the velocity field. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for CFC12 is CF2Cl2. The IUPAC name for CFC12 is dichloro-difluoro-methane. - - kg s-1 + + 1 - "y" indicates a vector component along the grid y-axis, positive with increasing y. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for chlorine dioxide is OClO. - - kg s-1 + + 1 - "y" indicates a vector component along the grid y-axis, positive with increasing y. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for chlorine monoxide is ClO. - - kg s-1 + + 1 - "y" indicates a vector component along the grid y-axis, positive with increasing y. Transport by bolus advection in an ocean model means the part due to a scheme representing eddy-induced effects not included in the velocity field. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for chlorine nitrate is ClONO2. - - kg s-1 + + 1 - In contrast to the quantity with standard name ocean_meridional_overturning_streamfunction, this quantity includes all physical processes, resolved or parameterized, that impact mass/volume transport. Thus it includes contributions from the bolus and Gent-McWilliams velocity. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Chlorophylls are the green pigments found in most plants, algae and cyanobacteria; their presence is essential for photosynthesis to take place. There are several different forms of chlorophyll that occur naturally; all contain a chlorin ring which gives the green pigment and a side chain whose structure varies. Chlorophyll-a is the most commonly occurring form of natural chlorophyll. - - kg s-1 + + 1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + "condensed_water" means liquid and ice. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). - - m3 s-1 + + 1 - stfmmcgo - The ocean meridional overturning streamfunction should not include not include "bolus" or Gent-McWilliams velocity. + cli + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). - - m - 67 - - The ocean mixed layer is the upper part of the ocean, regarded as being well-mixed. Various criteria are used to define the mixed layer; this can be specified by using a standard name of ocean_mixed_layer_defined_byX. + + 1 + + clw + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). - - m + + 1 - The ocean mixed layer is the upper part of the ocean, regarded as being well-mixed. The base of the mixed layer defined by the mixing scheme is a diagnostic of ocean models. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Clox" describes a familyof chemical species consisting of inorganic chlorine compounds with the exception of hydrogen chloride (HCl) and chlorine nitrate (ClONO2). "Clox" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Inorganic chlorine", sometimes referred to as Cly, describes a family of chemical species which result from the degradation of source gases containing chlorine (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as seasalt and other aerosols. Standard names that use the term "inorganic_chlorine" are used for quantitiesthat contain all inorganic chlorine species including HCl and ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A.It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - m + + 1 - The ocean mixed layer is the upper part of the ocean, regarded as being well-mixed. The base of the mixed layer defined by temperature, sigma or sigma_theta is the level at which the quantity indicated differs from its surface value by a certain amount. + "condensed_water" means liquid and ice. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). - - m + + 1 - The ocean mixed layer is the upper part of the ocean, regarded as being well-mixed. The base of the mixed layer defined by temperature, sigma or sigma_theta is the level at which the quantity indicated differs from its surface value by a certain amount. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). Convective cloud is that produced by the convection schemes in an atmosphere model. - - m + + 1 - The ocean mixed layer is the upper part of the ocean, regarded as being well-mixed. The base of the mixed layer defined by temperature, sigma or sigma_theta is the level at which the quantity indicated differs from its surface value by a certain amount. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). Convective cloud is that produced by the convection schemes in an atmosphere model. - - m + + 1 - The ocean mixed layer is the upper part of the ocean, regarded as being well-mixed. The base of the mixed layer defined by temperature, sigma, sigma_theta, or vertical diffusivity is the level at which the quantity indicated differs from its surface value by a certain amount. The amount by which the quantity differs can be specified by a scalar coordinate variable. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for dichlorineperoxide is Cl2O2. - - m4 s-1 + + 1 - Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. "xy diffusivity" means the lateral along_coordinate component of diffusivity due to motion which is not resolved on the grid scale of the model. xy diffusivities are used in some ocean models to counteract the numerical instabilities inherent in certain implementations of rotated neutral diffusion. "biharmonic diffusivity" means diffusivity for use with a biharmonic diffusion operator. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). - - m2 s-1 + + 1 - Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. "xy diffusivity" means the lateral along_coordinate component of diffusivity due to motion which is not resolved on the grid scale of the model. xy diffusivities are used in some ocean models to counteract the numerical instabilities inherent in certain implementations of rotated neutral diffusion. "laplacian diffusivity" means diffusivity for use with a Laplacian diffusion operator. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for dinitrogenpentoxide is N2O5. - - m2 s-2 + + 1 - Mongomery potential is defined as M = ap + gz, where a = specific volume, p = pressure, g = gravity, and z=depth. It represents an exact streamfunction on specificvolume anomaly surfaces. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. - - Pa + + 1 - "Ocean rigid lid pressure" means the pressure at the surface of an ocean model assuming that it is bounded above by a rigid lid. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). - - m + + 1 - "Ocean rigid lid pressure" means the pressure at the surface of an ocean model assuming that it is bounded above by a rigid lid. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standardnames for the alkane group as well as for some of the individual species. - - 1e-3 kg s-1 + + 1 - "x" indicates a vector component along the grid x-axis, positive with increasing x. Salt transport refers to the mass of salt being transported. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethanol isC2H5OH. - - 1e-3 kg s-1 + + 1 - "y" indicates a vector component along the grid y-axis, positive with increasing y. Salt transport refers to the mass of salt being transported. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standardnames for the alkene group as well as for some of the individual species. - + 1 - See Appendix D of the CF convention for information about dimensionless vertical coordinates. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. - + 1 - See Appendix D of the CF convention for information about dimensionless vertical coordinates. Note that the ocean sigma coordinate is not the same quantity as sea water sigma (excess of density over 1000 kg m-3), for which there are various other standard names. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. - - m4 s-1 + + 1 - Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. "Bolus diffusivity" means a lateral diffusivity. "biharmonicdiffusivity" means diffusivity for use with a biharmonic diffusion operator. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for formic acid is HCOOH. The IUPAC name for formic acid is methanoic acid. - - m2 s-1 + + 1 - Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. "Bolus diffusivity" means a lateral diffusivity. "laplacian diffusivity" means diffusivity for use with a Laplacian diffusion operator. + "frozen_water" means ice. "moisture" means water in all phases contained in soil. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). - - m4 s-1 + + 1 - Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. "epineutral diffusivity" means a lateral diffusivity along a either a neutral or isopycnal density surface due to motion which is not resolved on the grid scale of an ocean model. The type of density surface is dependent on the model formulation. "biharmonic diffusivity" means diffusivity for use with a biharmonic diffusion operator. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Divalent mercury" means all compounds in which the mercury has two binding sites to other ion(s) in a salt or to other atom(s) in a molecule. - - m2 s-1 + + 1 - Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. "epineutral diffusivity" means a lateral diffusivity along a either a neutral or isopycnal density surface due to motion which is not resolved on the grid scale of an ocean model. The type of density surface is dependent on the model formulation. "laplacian diffusivity" means diffusivity for use with a Laplacian diffusion operator. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for mercury is Hg. - - m4 s-1 + + 1 - Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. "xy diffusivity" means the lateral along_coordinate component of diffusivity due to motion which is not resolved on the grid scale of the model. xy diffusivities are used in some ocean models to counteract the numerical instabilities inherent in certain implementations of rotated neutral diffusion. "biharmonic diffusivity" means diffusivity for use with a biharmonic diffusion operator. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). Graupel consists of heavily rimed snow particles, often called snow pellets; often indistinguishable from very small soft hail except when the size convention that hail must have a diameter greater than 5 mm is adopted. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Graupel. Hail is precipitation in the form of balls or irregular lumps of ice, often restricted by a size convention to diameters of 5 mm or more. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Hail. Standard names for "graupel_and_hail" should be used to describe data produced by models that do not distinguish between hail and graupel. For models that do distinguish between them, separate standard names for hail and graupel are available. - - m2 s-1 + + 1 - Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. "xy diffusivity" means the lateral along_coordinate component of diffusivity due to motion which is not resolved on the grid scale of the model. xy diffusivities are used in some ocean models to counteract the numerical instabilities inherent in certain implementations of rotated neutral diffusion. "laplacian diffusivity" means diffusivity for use with a Laplacian diffusion operator. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). Graupel consists of heavily rimed snow particles, often called snow pellets; often indistinguishable from very small soft hail except when the size convention that hail must have a diameter greater than 5 mm is adopted. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Graupel. There are also separate standard names for hail. Standard names for "graupel_and_hail" should be used to describe data produced by models that do not distinguish between hail and graupel. - - m2 s-1 + + 1 - "Vertical diffusivity" means the vertical component of diffusivity due to motion which is not resolved on the grid scale of the model. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). Hail is precipitation in the form of balls or irregular lumps of ice, often restricted by a size convention to diameters of 5 mm or more. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Hail. For diameters of less than 5 mm standard names for "graupel" should be used. Standard names for "graupel_and_hail" should be used to describe data produced by models that do not distinguish between hail and graupel. - - m2 s-1 + + 1 - "Vertical heat diffusivity" means the vertical component of the diffusivity of heat due to motion which is not resolved on the grid scale of the model. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halon1202 is CBr2F2. The IUPAC name for halon1202 is dibromo-difluoro-methane. - - m2 s-1 + + 1 - "Vertical momentum diffusivity" means the vertical component of the diffusivity of momentum due to motion which is not resolved on the grid scale of the model. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halon1211 is CBrClF2. The IUPAC name for halon1211 is bromo-chloro-difluoro-methane. - - m2 s-1 + + 1 - Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. The construction vertical_X_diffusivity means the vertical component of thediffusivity of X due to motion which is not resolved on the grid scale of the model. "Due to background" means caused by a time invariant imposed field which may be eitherconstant over the globe or spatially varying, depending on the ocean model used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halon1301 is CBrF3. The IUPAC name for halon1301 is bromo-trifluoro-methane. - - m2 s-1 + + 1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Vertical momentum diffusivity" means the vertical component of the diffusivity of momentum due to motion which is not resolved on the grid scale of the model. Convective mixing in the ocean is somtimes modelled as an enhanced diffusivity. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halo2402 is C2Br2F4. The IUPAC name for halon2402 is 1,2-dibromo-1,1,2,2-tetrafluoro-ethane. - - m2 s-1 + + 1 - Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. The construction vertical_X_diffusivity means the vertical component of thediffusivity of X due to motion which is not resolved on the grid scale of the model. "Due to form drag" refers to a vertical diffusivity resulting from a model scheme representing mesoscale eddy-induced form drag. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hcc140a isCH3CCl3. The IUPAC name for hcc140a is 1,1,1-trichloro-ethane. - - m2 s-1 - + + 1 + - Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. The construction vertical_X_diffusivity means the vertical component of thediffusivity of X due to motion which is not resolved on the grid scale of the model. "Due to tides" means due to all astronomical gravity changes which manifest as tides.No distinction is made between different tidal components. The specification of a physicalprocess by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for HCFC141b is CH3CCl2F. The IUPAC name for HCFC141b is 1,1-dichloro-1-fluoroethane. - - m2 s-1 + + 1 - "Vertical salt diffusivity" means the vertical component of the diffusivity of salt due to motion which is not resolved on the grid scale of the model. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for HCFC142b is CH3CClF2. The IUPAC name for HCFC142b is 1-chloro-1,1-difluoroethane. - - m2 s-1 + + 1 - "Vertical tracer diffusivity" means the vertical component of the diffusivity of tracers, i.e. heat and salinity, due to motion which is not resolved on the grid scale of the model. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for HCFC22 is CHClF2. The IUPAC name for HCFC22 is chloro-difluoro-methane. - - m2 s-1 + + 1 - Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. The construction vertical_X_diffusivity means the vertical component of thediffusivity of X due to motion which is not resolved on the grid scale of the model. "Due to background" means caused by a time invariant imposed field which may be eitherconstant over the globe or spatially varying, depending on the ocean model used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hexachlorobiphenyl is C12H4Cl6. This structure of this species consists of two linked benzene rings,each of which is additionally bonded to three chlorine atoms. - - m2 s-1 + + 1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Vertical tracer diffusivity" means the vertical component of the diffusivity of tracers, i.e. heat and salinity, due to motion which is not resolved on the grid scale of the model. Convective mixing in the ocean is sometimes modelled as an enhanced diffusivity. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "HOx" means a combination of two radical species containing hydrogen and oxygen: OH and HO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - m2 s-1 + + 1 - Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. The construction vertical_X_diffusivity means the vertical component of thediffusivity of X due to motion which is not resolved on the grid scale of the model. "Due to tides" means due to all astronomical gravity changes which manifest as tides.No distinction is made between different tidal components. The specification of a physicalprocess by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen bromide is HBr. - - m2 s-1 + + 1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Vertical tracer diffusivity" means the vertical component of the diffusivity of tracers, i.e. heat and salinity, due to motion which is not resolved on the grid scale of the model. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen chloride is HCl. - - m3 + + 1 - + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen cyanide is HCN. - + 1 - "X_volume_fraction" means the fraction of volume occupied by X. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen peroxide is H2O2. - - m3 s-1 + + 1 - Transport "across_line" means that which crosses a particular line on the Earth's surface; formally this means the integral along the line of the normal component of the transport. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for the hydroperoxyl radical is HO2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. - - m3 s-1 + + 1 - "x" indicates a vector component along the grid x-axis, positive with increasing x. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for the hydroxyl radical is OH. In chemistry, a 'radical' is a highly reactive, and therefore shortlived,species. - - m3 s-1 + + 1 - "y" indicates a vector component along the grid y-axis, positive with increasing y. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hypobromous acid is HOBr. - - kg s-1 + + 1 - "y" indicates a vector component along the grid y-axis, positive with increasing y. In contrast to the quantity with standard name ocean_meridional_overturning_streamfunction, this quantity includes all physical processes, resolved or parameterized, that impact mass/volume transport. Thus it includes contributions from the bolus and Gent-McWilliams velocity. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hypochlorous acid is HOCl. - - kg s-1 + + 1 - "y" indicates a vector component along the grid y-axis, positive with increasing y. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of source gases containing bromine (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. "Inorganic bromine" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names that use the term "brox" are used for quantities that contain all inorganic bromine species except HBr and BrONO2. - - W m-2 + + 1 - "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 300-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. Omnidirectional spherical irradiance is the radiation incident on unit area of a spherical (or "4-pi") collector. It is sometimes called "scalar irradiance". Radiation incident on a 2-pi collector has standard names of "spherical irradiance" which specify up/downwelling. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Inorganic chlorine", sometimes referred to as Cly, describes a family of chemical species which result from the degradation of source gases containing chlorine (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as seasalt and other aerosols. "Inorganic chlorine" is the termused in standard names for all species belonging to the family that are represented withina given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names that use the term "clox" are used for quantities that contain all inorganic chlorine species except HCl and ClONO2. - - W m-3 + + 1 - "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. Omnidirectional spherical irradiance is the radiation incident on unit area of a spherical (or "4-pi") collector. It is sometimes called "scalar irradiance". Radiation incident on a 2-pi collector has standard names of "spherical irradiance" which specify up/downwelling. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for isoprene is CH2=C(CH3)CH=CH2. The IUPAC name for isoprene is 2-methyl-buta-1,3-diene. Isoprene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. - + 1 - "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for limonene is C10H16. The IUPAC name for limonene is 1-methyl-4-prop-1-en-2-yl-cyclohexene. Limonene is a member of the group of hydrocarbons known as terpenes. There are standard names for theterpene group as well as for some of the individual species. - - m + + 1 - Permafrost is soil or rock that has remained at a temperature at or below zero degrees Celsius throughout the seasonal cycle for two or more years. "Thickness" means the vertical extent of a layer. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. - + 1 - + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methane isCH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. - - kg m-2 s-1 + + 1 - "Respiration carbon" refers to the rate at which biomass is respired expressed as the mass of carbon which it contains. Plant respiration is the sum of respiration by parts of plants both above and below the soil. Plants which photosynthesise are autotrophs i.e. "producers" of the biomass which they respire from inorganic precursors using sunlight for energy. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The chemical formula for methanesulfonic acid is CH3SO3H. - - degree + + 1 - Standard names for platform describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane or ship. The platform course is the direction in which the platform is travelling (not necessarily the same as the direction in which it is pointing, called platform_orientation). + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethanol isC2H5OH. The chemical formula for methanol is CH3OH. - - degree + + 1 - Standard names for platform describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane or ship. The platform orientation is the direction in which the "front" or longitudinal axis of the platform is pointing (not necessarily the same as the direction in which it is travelling, called platform_course). + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl bromide is CH3Br. The IUPAC name for methyl bromide is bromomethane. - - degree + + 1 - Standard names for platform describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane or ship. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl chloride is CH3Cl. The IUPAC name for methyl chloride is chloromethane. - - degree s-1 + + 1 - Standard names for platform describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane or ship. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl hydroperoxide is CH3OOH. - - degree + + 1 - Standard names for platform describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane or ship. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl_peroxy_radical is CH3O2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. - - degree s-1 + + 1 - Standard names for platform describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane or ship. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for molecular hydrogen is H2. - - m s-1 + + 1 - "wrt" means with respect to. Speed is the magnitude of velocity. Standard names for platform describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane or ship. The platform speed with respect to air is often called the "air speed" of the platform. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Mass_fraction_of_nitrate" means that the mass is expressed as mass of NO3. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. - - m s-1 + + 1 - "wrt" means with respect to. Speed is the magnitude of velocity. Standard names for platform describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane or ship. The platform speed with respect to ground is relative to the solid Earth beneath it i.e. the sea floor for a ship. It is often called the "ground speed" of the platform. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. - - m s-1 + + 1 - "wrt" means with respect to. Speed is the magnitude of velocity. Standard names for platform describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane or ship. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitric acid is HNO3. - - degree + + 1 - Standard names for platform describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane or ship. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. The chemical formula for nitric acid is HNO3. Nitric acid trihydrate, sometimes referred to as NAT, is a stable crystalline substance consisting of three molecules of water to one molecule of nitric acid. - - degree s-1 + + 1 - Standard names for platform describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane or ship. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrogen dioxide is NO2. - - degree + + 1 - Standard names for "platform" describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane or ship. Platform zenith angle is the the angle between the line of sight to the platform and the local vertical. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrogen monoxide is NO. - - J m-2 + + 1 - "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrous acid is HNO2. - - Pa-1 s-1 + + 1 - "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Atmosphere potential vorticity is the vertically averaged absolute vorticity of a layer of the atmosphere divided by the pressure difference from the bottom to the top of the layer. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrous oxide is N2O. - - m-1 s-1 + + 1 - "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Ocean potential vorticity is the vertically averaged absolute vorticity of a layer of the ocean divided by the thickness of the layer. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. - - kg m-2 - 61 + + 1 + - "Amount" means mass per unit area. - - - - kg m-2 s-1 - 59 - pr - In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The term "peroxy_radicals" means all organic and inorganic peroxy radicals. This includes HO2 and all organic peroxyradicals, sometimes referred to as RO2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. - - kg m-2 s-1 + + 1 - prveg - "Canopy" means the plant or vegetation canopy. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. Previously, the qualifier where_type was used to specify that the quantity applies only to the part of the grid box of the named type. Names containing the where_type qualifier are deprecated and newly created data should use the cell_methods attribute to indicate the horizontal area to which the quantity applies. + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Noy" describes a family of chemical species. The family usually includes atomic nitrogen (N), nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), peroxynitric acid (HNO4), bromine nitrate (BrONO2) , chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)). The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - K Pa s-1 + + 1 - "product_of_X_and_Y" means X*Y. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. "omegaX" is used for brevity to mean "lagrangian_tendency_of_air_pressure in standard names constructed as a combination of omega with some other quantity. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Oxygenated" means containing oxygen. "Hydrocarbon" means a compound containing hydrogen and carbon. - - K + + 1 - "product_of_X_and_Y" means X*Y. "specific" means per unit mass. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. Specific humidity is the mass fraction of water vapor in (moist) air. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). - - m s-1 + + 1 - "product_of_X_and_Y" means X*Y. A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and normally given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. - - K m s-1 + + 1 - "product_of_X_and_Y" means X*Y. A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. - - K m s-1 + + 1 - "product_of_X_and_Y" means X*Y. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for peroxyacetyl nitrate, sometimes referred to as PAN, is CH3COO2NO2. The IUPAC name for peroxyacetyl_nitrate is nitroethaneperoxoate. - - m2 s-1 + + 1 - mpuzga - "product_of_X_and_Y" means X*Y. Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. Geopotential height is the geopotential divided by the standard acceleration due to gravity. It is numerically similar to the altitude (or geometric height) and not to the quantity with standard name height, which is relative to the surface. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for peroxynitric acid, sometimes referred to as PNA, is HO2NO2. - - m2 s-2 + + 1 - mpuva - "product_of_X_and_Y" means X*Y. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The term "peroxy_radicals" means all organic and inorganic peroxy radicals. This includes HO2 and all organic peroxyradicals, sometimes referred to as RO2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. - - Pa m s-2 + + 1 - "product_of_X_and_Y" means X*Y. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) "omegaX" is used for brevity to mean "lagrangian_tendency_of_air_pressure in standard names constructed as a combination of omega with some other quantity. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. To specify the relative humidity and temperature at which the particle size applies, provide scalar coordinate variables with the standard names of "relative_humidity" and "air_temperature." - - m s-1 + + 1 - "product_of_X_and_Y" means X*Y. "specific" means per unit mass. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Specific humidity is the mass fraction of water vapor in (moist) air. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. The chemical formula for ammonium is NH4. - - m2 s-2 + + 1 - "product_of_X_and_Y" means X*Y. A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Upward" indicates a vector component which is positive when directed upward (negative downward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) Upward air velocity is the vertical component of the 3D air velocity vector. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. - - Pa m s-1 + + 1 - "product_of_X_and_Y" means X*Y. Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. Geopotential height is the geopotential divided by the standard acceleration due to gravity. It is numerically similar to the altitude (or geometric height) and not to the quantity with standard name height, which is relative to the surface. "omegaX" is used for brevity to mean "lagrangian_tendency_of_air_pressure in standard names constructed as a combination of omega with some other quantity. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. - - m s-1 + + 1 - "product_of_X_and_Y" means X*Y. A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and normally given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). - - K m s-1 + + 1 - "product_of_X_and_Y" means X*Y. A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). - - - - K m s-1 - - mpvta - "product_of_X_and_Y" means X*Y. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. The chemical formula for the nitrate anion is NO3-. - - m2 s-1 + + 1 - mpvzga - "product_of_X_and_Y" means X*Y. Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. Geopotential height is the geopotential divided by the standard acceleration due to gravity. It is numerically similar to the altitude (or geometric height) and not to the quantity with standard name height, which is relative to the surface. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. - - Pa m s-2 + + 1 - "product_of_X_and_Y" means X*Y. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) "omegaX" is used for brevity to mean "lagrangian_tendency_of_air_pressure in standard names constructed as a combination of omega with some other quantity. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. - - m s-1 + + 1 - mpvhusa - "product_of_X_and_Y" means X*Y. "specific" means per unit mass. "Northward" indicates a vector component which is positive when directed northward (negative southward). Specific humidity is the mass fraction of water vapor in (moist) air. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. "Primary particulate organic matter" means all organic matter emitted directly to the atmosphere as particles except elemental carbon. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. - - m2 s-2 + + 1 - "product_of_X_and_Y" means X*Y. A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). "Upward" indicates a vector component which is positive when directed upward (negative downward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) Upward air velocity is the vertical component of the 3D air velocity vector. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. The phrase "sea_salt_cation" is the term used in standard names to describe collectively the group of cationic species that occur in sea salt. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Sea salt cations are mainly sodium (Na+), but also include potassium (K+), magnesium (Mg2+), calcium (Ca2+) and rarer cations. Where possible, the data variable should be accompanied by a complete description of the ions represented, for example, by using a comment attribute. - - K Pa s-1 + + 1 - mpwapta - "product_of_X_and_Y" means X*Y. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. "omegaX" is used for brevity to mean "lagrangian_tendency_of_air_pressure in standard names constructed as a combination of omega with some other quantity. + + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. - - Pa s-1 + + 1 - mpwhusa - "product_of_X_and_Y" means X*Y. "specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. "omegaX" is used for brevity to mean "lagrangian_tendency_of_air_pressure in standard names constructed as a combination of omega with some other quantity. + + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. The chemical formula for the sulfate anion is SO4(2-). - - Pa s-1 + + 1 - "product_of_X_and_Y" means X*Y. "specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. "omegaX" is used for brevity to mean "lagrangian_tendency_of_air_pressure in standard names constructed as a combination of omega with some other quantity. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. "Pm1 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 1 micrometer. To specify the relative humidity and temperature at which the particle size applies, provide scalar coordinate variables with the standard names of "relative_humidity" and "air_temperature". - - K m s-1 + + 1 - "product_of_X_and_Y" means X*Y. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. A velocity is a vector quantity. "Upward" indicates a vector component which is positive when directed upward (negative downward). Upward air velocity is the vertical component of the 3D air velocity vector. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm1 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 1 micrometer. - - m s-1 + + 1 - "product_of_X_and_Y" means X*Y. "specific" means per unit mass. A velocity is a vector quantity. "Upward" indicates a vector component which is positive when directed upward (negative downward). Specific humidity is the mass fraction of water vapor in (moist) air. Upward air velocity is the vertical component of the 3D air velocity vector. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. To specify the relative humidity and temperature at which the particle size applies, provide scalar coordinate variables with the standard names of "relative_humidity" and "air_temperature". - - m + + 1 - "x" indicates a vector component along the grid x-axis, when this is not true longitude, positive with increasing x. Projection coordinates are distances in the x- and y-directions on a plane onto which the surface of the Earth has been projected according to a map projection. The relationship between the projection coordinates and latitude and longitude is described by the grid_mapping. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. The chemical formula for ammonium is NH4. - - m + + 1 - "y" indicates a vector component along the grid y-axis, when this is not true latitude, positive with increasing y. Projection coordinates are distances in the x- and y-directions on a plane onto which the surface of the Earth has been projected according to a map projection. The relationship between the projection coordinates and latitude and longitude is described by the grid_mapping. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. - - K - 14 + + 1 + - Potential temperature is the temperature a parcel of air or sea water would have if moved adiabatically to sea level pressure. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. - - K + + 1 - + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). - - m s-1 + + 1 - A velocity is a vector quantity. Radial velocity away from instrument means the component of the velocity along the line of sight of the instrument where positive implies movement away from the instrument (i.e. outward). The "instrument" (examples are radar and lidar) is the device used to make an observation. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. The chemical formula for the nitrate anion is NO3-. - - m s-1 + + 1 - A velocity is a vector quantity. "Radial velocity away from instrument" means the component of the velocity of the scatterers along the line of sight of the instrument where positive implies movement away from the instrument (i.e. outward). The "instrument" (examples are radar and lidar) is the device used to make the observation, and the "scatterers" are what causes the transmitted signal to be returned to the instrument (examples are aerosols, hydrometeors and refractive index irregularities), of whatever kind the instrument detects. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. - - s-1 + + 1 - Frequency is the number of oscillations of a wave per unit time. The radiation frequency can refer to any electromagnetic wave, such as light, heat radiation and radio waves. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. - - m + + 1 - The radiation wavelength can refer to any electromagnetic wave, such as light, heat radiation and radio waves. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. "Primary particulate organic matter" means all organic matter emitted directly to the atmosphere as particles except elemental carbon. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. - - kg m-2 + + 1 - "Amount" means mass per unit area. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. The phrase "sea_salt_cation" is the term used in standard names to describe collectively the group of cationic species that occur in sea salt. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Sea salt cations are mainly sodium (Na+), but also include potassium (K+), magnesium (Mg2+), calcium (Ca2+) and rarer cations. Where possible, the data variable should be accompanied by a complete description of the ions represented, for example, by using a comment attribute. - - kg m-2 s-1 + + 1 - In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. - - m s-1 + + 1 - + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. The chemical formula for the sulfate anion is SO4(2-). - - m s-2 + + 1 - Sea surface density is the density of sea water near the surface (including the part under sea-ice, if any). "component_derivative_of_X" means derivative of X with respect to distance in the component direction, which may be northward, southward, eastward, westward, x or y. The last two indicate derivatives along the axes of the grid, whether or not they are true longitude and latitude. "ratio_of_X_to_Y" means X/Y. "Ocean rigid lid pressure" means the pressure at the surface of an ocean model assuming that it is bounded above by a rigid lid. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Precipitation" in the earth's atmosphere means precipitation of water in all phases. - - m s-2 + + 1 - Sea surface density is the density of sea water near the surface (including the part under sea-ice, if any). "component_derivative_of_X" means derivative of X with respect to distance in the component direction, which may be northward, southward, eastward, westward, x or y. The last two indicate derivatives along the axes of the grid, whether or not they are true longitude and latitude. "ratio_of_X_to_Y" means X/Y. "Ocean rigid lid pressure" means the pressure at the surface of an ocean model assuming that it is bounded above by a rigid lid. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. "Primary particulate organic matter " means all organic matter emitted directly to the atmosphere as particles except elemental carbon. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. - + 1 - Realization is used to label a dimension that can be thought of asa statistical sample, e.g., labelling members of a model ensemble. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for propane isC3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. - - kg m-3 + + 1 - Sea water density is the in-situ density (not the potential density). For a rigid lid Boussinesq geopotential ocean model the density of the sea water is maintained at a constant reference density. In a model using the rigid lid Boussinesq approximation , the vertical grid coordinates (and hence the grid cell volumes) are time invariant. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for propene isC3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. - - string + + 1 - A variable with the standard name of region contains strings which indicate geographical regions. These strings must be chosen from the standard region list. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for radon is Rn. - + 1 - 52 E157 - hur - + + + The quantity with standard name mass_fraction_of_rainfall_falling_onto_surface_snow is the mass of rainfall falling onto snow as a fraction of the mass of rainfall falling within the area of interest. The phrase "surface_snow" means snow lying on the surface. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. - + 1 - Richardson number is a measure of dynamic stability and can be used to diagnose the existence of turbulent flow. It is defined as the ratio of the buoyant suppression of turbulence (i.e. how statically stable or unstable the conditions are) to the kinetic energy available to generate turbulence in a shear flow. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). - - kg m-2 + + 1 - "Content" indicates a quantity per unit area. + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The phrase "sea_salt_cation" is the term used in standard names to describe collectively the group of cationic species that occur in sea salt. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Sea salt cations are mainly sodium (Na+), but also include potassium (K+), magnesium (Mg2+), calcium (Ca2+) and rarer cations. Where possible, the data variable should be accompanied by a complete description of the ions represented, for example, by using a comment attribute. - - m + + 1 - Depth is the vertical distance below the surface. The root depth is maximum depth of soil reached by plant roots, from which they can extract moisture. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. - - kg m-2 + + 1 - "Amount" means mass per unit area. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Secondary particulate organic matter" means particulate organic matter formed within the atmosphere from gaseous precursors. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. - - kg m-2 + + 1 - Runoff is the liquid water which drains from land. "Runoff_excluding_baseflow" is the sum of surface runoff and subsurface runoff excluding baseflow. Baseflow is subsurface runoff which takes place below the level of the water table. "Amount" means mass per unit area. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). - - kg m-2 s-1 + + 1 - mrro - The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. (The volume enclosed between the geoid and the sea floor equals the mean volume of water in the ocean.) In an ocean GCM the geoid is the surface of zero depth, or the rigid lid if the model uses that approximation. "Sea surface height" is a time-varying quantity. By definition of the geoid, the global average of the time-mean sea surface height (i.e. mean sea level) above the geoid must be zero. The standard name for the height of the sea surface above mean sea level is sea_surface_height_above_sea_level. The standard name for the height of the sea surface above the reference ellipsoid is sea_surface_height_above_reference_ellipsoid. + + Solid precipitation refers to the precipitation of water in the solid phase. Water in the atmosphere exists in one of three phases: solid, liquid or vapor. The solid phase can exist as snow, hail, graupel, cloud ice, or as a component of aerosol. The quantity with standard name mass_fraction_of_solid_precipitation_falling_onto_surface_snow is the mass of solid precipitation falling onto snow as a fraction of the mass of solid precipitation falling within the area of interest. The phrase "surface_snow" means snow lying on the surface. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. - - kg m-2 s-1 + + 1 - In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). - - rad + + 1 - The scattering angle is that between the direction of the beam of incident radiation and the direction into which it is scattered. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). - - m2 + + 1 - "X_area" means the horizontal area occupied by X within the grid cell. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Mass_fraction_of_sulfate" means that the mass is expressed as mass of SO4. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. - + 1 - "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). - - m + + 1 - zobt - The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. (The volume enclosed between the geoid and the sea floor equals the mean volume of water in the ocean.) In an ocean GCM the geoid is the surface of zero depth, or the rigid lid if the model uses that approximation. + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. - - m + + 1 - sea_level means mean sea level, which is close to the geoid in sea areas. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Terpenes are hydrocarbons, that is,they contain only hydrogen and carbon combined in the general proportions (C5H8)n where n is an integer greater than on equal to one. The term "terpenes" is used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual terpene species, e.g., isoprene and limonene. - - m + + 1 - The sea_floor_depth_below_sea_surface is the vertical distance between the sea surface and the seabed as measured at a given point in space including the variance caused by tides and possibly waves. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for toluene isC6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atomsis replaced by a methyl group. The systematic name for toluene is methylbenzene. - + 1 - The albedo of sea ice. + "moisture" means water in all phases contained in soil. "unfrozen_water" means liquid and vapour. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). - - kg m-2 + + 1 - "Amount" means mass per unit area. + "Water" means water in all phases. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). - - kg m-2 + + 1 - "Amount" means mass per unit area. Surface amount refers to the amount on the ground, excluding that on the plant or vegetation canopy. The surface called "surface" means the lower boundary of the atmosphere. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. - - m2 + + 1 - "X_area" means the horizontal area occupied by X within the grid cell. + "Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". - + 1 - 91 - sic - "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. Sea ice area fraction is area of the sea surface occupied by sea ice. It is also called "sea ice concentration". + + + Mass fraction is used in the construction "mass_fraction_of_X_in_Y", where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". - + 1 - A variable with the standard name of sea_ice_classification contains strings which indicate the character of the ice surface e.g. open_ice, or first_year_ice. These strings have not yet been standardised. However, and whenever possible, they should follow the terminology defined in the WMO Standard Nomenclature for Sea Ice Classification. Alternatively, the data variable may contain integers which can be translated to strings using flag_values and flag_meanings attributes. + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer toaromatic_compounds as a group, as well as those for individual species. - - m + + s-1 - Sea ice draft is the depth of the sea-ice lower surface below the water surface. + "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. Axial strain is the symmetric component of the tensor representing the gradient of internal forces (e.g. in ice). Strain rate refers to off-diagonal element(s) of the strain tensor (a single element for horizontal shear strain). "Horizontal" refers to the local horizontal in the location of the sea ice, i.e., perpendicular to the local gravity vector. Each of the strain components is defined with respect to a frame of reference. "Coordinate rotation" refers to the range of all possible orientations of the frame of reference. The shear strain has a maximum value relative to one of these orientations. The second invariant of strain rate, often referred to as the maximum shear strain [rate], is the maximum over coordinate rotations of the shear strain rate. - - m2 + + N m-1 - + "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. Axial stress is the symmetric component of the tensor representing the gradient of internal forces (e.g. in ice). Shear stress refers to off-diagonal element(s) of the stress tensor (a single element for horizontal shear stress). "Horizontal" refers to the local horizontal in the location of the sea ice, i.e., perpendicular to the local gravity vector. Each of the stress components is defined with respect to a frame of reference. "Coordinate rotation" refers to the range of all possible orientations of the frame of reference. The shear stress has a maximum value relative to one of these orientations. The second invariant of stress, often referred to as the maximum shear stress, is the maximum over coordinate rotations of the shear stress. - - m + + kg m-2 - Sea ice freeboard is the height of the sea-ice upper surface above the water surface. + "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including content_of_soil_layer are used. Soil carbon is returned to the atmosphere as the organic matter decays. The decay process takes varying amounts of time depending on the composition of the organic matter, the temperature and the availability of moisture. A carbon "soil pool" means the carbon contained in organic matter which has a characteristic period over which it decays and releases carbon into the atmosphere. "Medium soil pool" refers to the decay of organic matter in soil with a characteristic period of between ten and one hundred years under reference climate conditions of a temperature of 20 degrees Celsius and no water limitations. - - kg + + 1 - + Middle type clouds are: Altostratus, Altocumulus, Nimbostratus. "X_area_fraction" means the fraction of horizontal area occupied by X. Cloud area fraction is also called "cloud amount" and "cloud cover". X_type_cloud_area_fraction is generally determined on the basis of cloud type, though Numerical Weather Prediction (NWP) models often calculate them based on the vertical location of the cloud. - - 1e-3 + + m - Sea ice salinity is the salt content of sea ice, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and normally given as 1e-3 or 0.001 i.e. parts per thousand. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. + Depth is the vertical distance below the surface. 'Undersaturation' means that a solution is unsaturated with respect to a solute. Aragonite is a mineral that is a polymorph of calcium carbonate. The chemical formula of aragonite is CaCO3. Standard names also exist for calcite, another polymorph of calcium carbonate. The "minimum depth of undersaturation", sometimes called the "saturation horizon", is the shallowest depth at which a body of water is an undersaturated solution of a named solute. - - m s-1 - 94 + + m + - Speed is the magnitude of velocity. + Depth is the vertical distance below the surface. 'Undersaturation' means that a solution is unsaturated with respect to a solute. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Standard names also exist for aragonite, another polymorph of calcium carbonate. The "minimum depth of undersaturation", sometimes called the "saturation horizon", is the shallowest depth at which a body of water is an undersaturated solution of a named solute. - - K + + W m-2 - The surface temperature is the (skin) temperature at the interface, not the bulk temperature of the medium above or below. "Sea ice surface temperature" is the temperature that exists at the interface of sea ice and an overlying medium which may be air or snow. In areas of snow covered sea ice, sea_ice_surface_temperature is not the same as the quantity with standard name surface_temperature. + The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. "Minus one times" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. The surface called "surface" means the lower boundary of the atmosphere. The term "longwave" means longwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - K + + W m-2 - + The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. "Minus one times" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. The surface called "surface" means the lower boundary of the atmosphere. The term "shortwave" means shortwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - m - 92 - sit - + + W m-2 + + + "Minus one times" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Shortwave means shortwave radiation. "toa" means top of atmosphere. The TOA outgoing shortwave flux is the reflected and scattered solar radiative flux i.e. the "upwelling" TOA shortwave flux, sometimes called the "outgoing shortwave radiation" or "OSR". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - kg s-1 + + kg m-2 s-1 - Transport across_line means that which crosses a particular line on the Earth's surface; formally this means the integral along the line of the normal component of the transport. + The quantity minus_one_times_water_flux_into_sea_water_from_rivers is the quantity with standard name water_flux_into_sea_water_from_rivers multiplied by -1. "Water" means water in all phases. The water flux or volume transport into sea water from rivers is the inflow to the ocean, often applied to the surface in ocean models. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "River" refers to water in the fluvial system (stream and floodplain). - - m3 + + kg m-2 s-1 - + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The chemical formula for ammonia is NH3. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. - - m + + kg m-2 s-1 - "x" indicates a vector component along the grid x-axis, positive with increasing x. "Displacement" means the change in geospatial position of an object that has moved over time. If possible, the time interval over which the motion took place should be specified using a bounds variable for the time coordinate variable. A displacement can be represented as a vector. Such a vector should however not be interpreted as describing a rectilinear, constant speed motion but merely as an indication that the start point of the vector is found at the tip of the vector after the time interval associated with the displacement variable. A displacement does not prescribe a trajectory. Sea ice displacement can be defined as a two-dimensional vector, with no vertical component. An x displacement is calculated from the difference in the moving object's grid x coordinate between the start and end of the time interval associated with the displacement variable. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The chemical formula for ammonia is NH3. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. - - kg s-1 + + kg m-2 s-1 - "x" indicates a vector component along the grid x-axis, positive with increasing x. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The chemical formula for ammonium is NH4. The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. - - m s-1 + + kg m-2 s-1 - A velocity is a vector quantity. "x" indicates a vector component along the grid x-axis, positive with increasing x. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The chemical formula for ammonium is NH4. The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. - - m + + kg m-2 s-1 - "y" indicates a vector component along the grid y-axis, positive with increasing y. "Displacement" means the change in geospatial position of an object that has moved over time. If possible, the time interval over which the motion took place should be specified using a bounds variable for the time coordinate variable. A displacement can be represented as a vector. Such a vector should however not be interpreted as describing a rectilinear, constant speed motion but merely as an indication that the start point of the vector is found at the tip of the vector after the time interval associated with the displacement variable. A displacement does not prescribe a trajectory. Sea ice displacement can be defined as a two-dimensional vector, with no vertical component. A y displacement is calculated from the difference in the moving object's grid y coordinate between the start and end of the time interval associated with the displacement variable. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Deposition" is the sum of wet and dry deposition. - - kg s-1 + + kg m-2 s-1 - "y" indicates a vector component along the grid y-axis, positive with increasing y. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. - - m s-1 + + kg m-2 s-1 - A velocity is a vector quantity. "y" indicates a vector component along the grid y-axis, positive with increasing y. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. - - kg m-3 + + kg m-2 s-1 - Sea surface density is the density of sea water near the surface (including the part under sea-ice, if any). + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. - - K + + kg m-2 s-1 - The surface called "surface" means the lower boundary of the atmosphere. The sea surface foundation temperature is the water temperature that is not influenced by a thermally stratified layer of diurnal temperature variability (either by daytime warming or nocturnal cooling). The foundation temperature is named to indicate that it is the temperature from which the growth of the diurnal thermocline develops each day, noting that on some occasions with a deep mixed layer there is no clear foundation temperature in the surface layer. In general, sea surface foundation temperature will be similar to a night time minimum or pre-dawn value at depths of between approximately 1 and 5 meters. In the absence of any diurnal signal, the foundation temperature is considered equivalent to the quantity with standard name sea_surface_subskin_temperature. The sea surface foundation temperature defines a level in the upper water column that varies in depth, space, and time depending on the local balance between thermal stratification and turbulent energy and is expected to change slowly over the course of a day. If possible, a data variable with the standard name sea_surface_foundation_temperature should be used with a scalar vertical coordinate variable to specify the depth of the foundation level. Sea surface foundation temperature is measured at the base of the diurnal thermocline or as close to the water surface as possible in the absence of thermal stratification. Only in situ contact thermometry is able to measure the sea surface foundation temperature. Analysis procedures must be used to estimate sea surface foundation temperature value from radiometric satellite measurements of the quantities with standard names sea_surface_skin_temperature and sea_surface_subskin_temperature. Sea surface foundation temperature provides a connection with the historical concept of a "bulk" sea surface temperature considered representative of the oceanic mixed layer temperature that is typically represented by any sea temperature measurement within the upper ocean over a depth range of 1 to approximately 20 meters. The general term, "bulk" sea surface temperature, has the standard name sea_surface_temperature with no associated vertical coordinate axis. Sea surface foundation temperature provides a more precise, well-defined quantity than "bulk" sea surface temperature and, consequently, is more representative of the mixed layer temperature. The temperature of sea water at a particular depth (other than the foundation level) should be reported using the standard name sea_water_temperature and, wherever possible, supplying a vertical coordinate axis or scalar coordinate variable. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000 K and can only be gasified by oxidation starting at temperatures above 340 degrees Celsius. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. - - m + + kg m-2 s-1 - The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. (The volume enclosed between the geoid and the sea floor equals the mean volume of water in the ocean.) In an ocean GCM the geoid is the surface of zero depth, or the rigid lid if the model uses that approximation. "Sea surface height" is a time-varying quantity. By definition of the geoid, the global average of the time-mean sea surface height (i.e. mean sea level) above the geoid must be zero. The standard name for the height of the sea surface above mean sea level is sea_surface_height_above_sea_level. The standard name for the height of the sea surface above the reference ellipsoid is sea_surface_height_above_reference_ellipsoid. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The mass is the total mass of the particles. "Insoluble aerosol" means aerosol which is not soluble in water, such as mineral dusts. At low temperatures such particles can be efficient nuclei for ice clouds. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Deposition" is the sum of wet and dry deposition. - - m + + kg m-2 s-1 - "Sea surface height" is a time-varying quantity. A reference ellipsoid is a mathematical figure that approximates the geoid. The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. The ellipsoid is an approximation because the geoid is an irregular shape. A number of reference ellipsoids are defined for use in the field of geodesy. The standard name for the height of the sea surface above the geoid is sea_surface_height_above_geoid. The standard name for the height of the sea surface above mean sea level is sea_surface_height_above_sea_level. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Nitrogen compounds" summarizes all chemical species containing nitrogen atoms. Usually, particle bound and gaseous nitrogen compounds, such as atomic nitrogen (N), nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), nitrate (NO3-), peroxynitric acid (HNO4), ammonia (NH3), ammonium (NH4+), bromine nitrate (BrONO2), chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)) are included. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Deposition" is the sum of wet and dry deposition. - - m - 82 + + kg m-2 s-1 + - sea_level means mean sea level, which is close to the geoid in sea areas. "Sea surface height" is a time-varying quantity. The standard name for the height of the sea surface above the geoid is sea_surface_height_above_geoid. The standard name for the height of the sea surface above the reference ellipsoid is sea_surface_height_above_reference_ellipsoid. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Noy" describes a family of chemical species. The family usually includes atomic nitrogen (N), nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), peroxynitric acid (HNO4), bromine nitrate (BrONO2), chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)). The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. - - m + + kg m-2 s-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Tides are a significant contributor to the observed sea surface height; earth tide means the solid earth tide. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Noy" describes a family of chemical species. The family usually includes atomic nitrogen (N), nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), peroxynitric acid (HNO4), bromine nitrate (BrONO2), chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)). The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. - - m + + kg m-2 s-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Tides are a significant contributor to the observed sea surface height; equilibrium ocean tide refers to the long period ocean tide. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The chemical formula for ozone is O3. The IUPAC name for ozone is trioxygen. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. - - m + + kg m-2 s-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Tides are a significant contributor to the observed sea surface height; geocentric ocean tide means the sum total of ocean tide and load tide. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. - - m + + kg m-2 s-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Tides are a significant contributor to the observed sea surface height; non equilibrium ocean tide refers to the long period ocean tide. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. - - m + + kg m-2 s-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Tides are a significant contributor to the observed sea surface height; the pole tide occurs due to variations in the earth's rotation. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. - - m + + kg m-2 s-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Altimeter pulses tend to be more strongly refelected by the troughs of sea surface waves than by the crests leading to a bias in the measured sea surface height. This quantity is commonly known as "sea state bias". + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. - - m + + kg m-2 s-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Air pressure and wind at high frequency" means variations in air pressure with periods shorter than 20 days. These give rise to corresponding variations in sea surface topography. The quantity sea_surface_height_correction_due_to_air_pressure_and_wind_at_high_frequency should be applied by adding it to the quantity with standard name altimeter_range. Additional altimeter range corrections are given by the quantities with standard names altimeter_range_correction_due_to_wet_troposphere, altimeter_range_correction_due_to_dry_troposphere, altimeter_range_correction_due_to_ionosphere and sea_surface_height_correction_due_to_air_pressure_at_low_frequency. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The chemical formula for the sulfate anion is SO4(2-). The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. - - m + + kg m-2 s-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Air pressure at low frequency" means variations in air pressure with periods longer than 20 days. These give rise to corresponding variations in sea surface topography. The quantity sea_surface_height_correction_due_to_air_pressure_at_low_frequency is commonly called the "inverted barometer effect" and the correction should be applied by adding it to the quantity with standard name altimeter_range. Additional altimeter range corrections are given by the quantities with standard names altimeter_range_correction_due_to_wet_troposphere, altimeter_range_correction_due_to_dry_troposphere, altimeter_range_correction_due_to_ionosphere and sea_surface_height_correction_due_to_air_pressure_and_wind_at_high_frequency. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The chemical formula for the sulfate anion is SO4(2-). The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. - - 1e-3 + + kg m-2 s-1 - Sea surface salinity is the salt content of sea water close to the sea surface, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and the units attribute should normally be given as 1e-3 or 0.001 i.e. parts per thousand. Sea surface salinity is often abbreviated as "SSS". For the salinity of sea water at a particular depth or layer, a data variable of "sea_water_salinity" or one of the more precisely defined salinities should be used with a vertical coordinate axis. There are standard names for the precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The chemical formula for sulfur dioxide is SO2. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. - - K + + kg m-2 s-1 - The surface called "surface" means the lower boundary of the atmosphere. The sea surface skin temperature is the temperature measured by an infrared radiometer typically operating at wavelengths in the range 3.7 - 12 micrometers. It represents the temperature within the conductive diffusion-dominated sub-layer at a depth of approximately 10 - 20 micrometers below the air-sea interface. Measurements of this quantity are subject to a large potential diurnal cycle including cool skin layer effects (especially at night under clear skies and low wind speed conditions) and warm layer effects in the daytime. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The chemical formula for sulfur dioxide is SO2. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. - - K + + mol m-2 s-1 - The surface called "surface" means the lower boundary of the atmosphere. The sea surface subskin temperature is the temperature at the base of the conductive laminar sub-layer of the ocean surface, that is, at a depth of approximately 1 - 1.5 millimeters below the air-sea interface. For practical purposes, this quantity can be well approximated to the measurement of surface temperature by a microwave radiometer operating in the 6 - 11 gigahertz frequency range, but the relationship is neither direct nor invariant to changing physical conditions or to the specific geometry of the microwave measurements. Measurements of this quantity are subject to a large potential diurnal cycle due to thermal stratification of the upper ocean layer in low wind speed high solar irradiance conditions. + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "ocean content" of a quantity refers to the vertical integral from the surface to the bottom of the ocean. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Denitrification" is the conversion of nitrate into gaseous compounds such as nitric oxide, nitrous oxide and molecular nitrogen which are then emitted to the atmosphere. "Sedimentation" is the sinking of particulate matter to the floor of a body of water. - - s + + mol m-2 s-1 - The swell wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S can be integrated over direction to give S1= integral(S dtheta). Frequency moments, M(n) of S1 can then be calculated as follows: M(n) = integral(S1 f^n df), where f^n is f to the power of n. The first wave period, T(m1), is calculated as the ratio M(0)/M(1). + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "ocean content" of a quantity refers to the vertical integral from the surface to the bottom of the ocean. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sedimentation" is the sinking of particulate matter to the floor of a body of water. "Inorganic carbon" describes a family of chemical species and is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. - - s + + mol m-2 s-1 - The swell wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S can be integrated over direction to give S1= integral(S dtheta). Frequency moments, M(n) of S1 can then be calculated as follows: M(n) = integral(S1 f^n df), where f^n is f to the power of n. The inverse wave period, T(m-1), is calculated as the ratio M(-1)/M(0). + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "ocean content" of a quantity refers to the vertical integral from the surface to the bottom of the ocean. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sedimentation" is the sinking of particulate matter to the floor of a body of water. - - s + + mol m-2 s-1 - The swell wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S can be integrated over direction to give S1= integral(S dtheta). Frequency moments, M(n) of S1 can then be calculated as follows: M(n) = integral(S1 f^n df), where f^n is f to the power of n. The second wave period, T(m2), is calculated as the square root of the ratio M(0)/M(2). + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "minus_tendency" means that the quantity described takes the opposite sign convention to that for the quantity which has the same standard name apart from this phrase, i.e. the two quantities differ from one another by a factor of -1. Thus a "minus_tendency" in the atmosphere means a positive deposition rate onto the underlying surface. "Content" indicates a quantity per unit area. The "ocean content" of a quantity refers to the vertical integral from the surface to the bottom of the ocean. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sedimentation" is the sinking of particulate matter to the floor of a body of water. "Organic carbon" describes a family of chemical species and is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. - - s - 106 + + kg m-2 + - A period is an interval of time, or the time-period of an oscillation. Swell waves are waves on the ocean surface. + "Content" indicates a quantity per unit area. "Miscellaneous living matter" means all those parts of plants that are not leaf, stem, root or other separately named components. The term "plants" refers to the kingdom of plants in the modern classification which excludes fungi. Plants are autotrophs i.e. "producers" of biomass using carbon obtained from carbon dioxide. - - m - 105 + + kg m-2 + - Height is the vertical distance above the surface. Swell waves are waves on the ocean surface. + "Content" indicates a quantity per unit area. "Miscellaneous living matter" means all those parts of plants that are not leaf, stem, root or other separately named components. The term "plants" refers to the kingdom of plants in the modern classification which excludes fungi. Plants are autotrophs i.e. "producers" of biomass using carbon obtained from carbon dioxide. - - degree - 104 - - Swell waves are waves on the ocean surface. "to_direction" is used in the construction X_to_direction and indicates the direction towards which the velocity vector of X is headed. + + 1 + + lev + Model level number should be understood as equivalent to layer number. - - s + + 1 - A period is an interval of time, or the time-period of an oscillation. The zero upcrossing period is defined as the time interval between consecutive occasions on which the surface height passes upward above the mean level. Swell waves are waves on the ocean surface. + The ocean mixed layer is the upper part of the ocean, regarded as being well-mixed. The base of the mixed layer defined by "temperature", "sigma", "sigma_theta", "sigma_t" or vertical diffusivity is the level at which the quantity indicated differs from its surface value by a certain amount. A coordinate variable or scalar coordinate variable with standard name sea_water_sigma_theta_difference can be used to specify the sigma_theta criterion that determines the layer thickness. Sigma-theta of sea water is the potential density (i.e. the density when moved adiabatically to a reference pressure) of water having the same temperature and salinity, minus 1000 kg m-3. The quantity model_level_number_at_base_of_ocean_mixed_layer_defined_by_sigma_theta is sometimes referred to as the "bowl index". - - K + + 1 - Sea surface temperature is usually abbreviated as "SST". It is the temperature of sea water near the surface (including the part under sea-ice, if any), and not the skin temperature, whose standard name is surface_temperature. For the temperature of sea water at a particular depth or layer, a data variable of sea_water_temperature with a vertical coordinate axis should be used. + cloud_base refers to the base of the lowest cloud. Model level number should be understood as equivalent to layer number. Convective cloud is that produced by the convection schemes in an atmosphere model. - - m2 s rad-1 + + 1 - Sea surface wave directional variance spectral density is the variance of the amplitude of the waves within given ranges of direction and wave frequency. + cloud_top refers to the top of the highest cloud. Model level number should be understood as equivalent to layer number. Convective cloud is that produced by the convection schemes in an atmosphere model. - - degree + + 1 - "from_direction" is used in the construction X_from_direction and indicates the direction from which the velocity vector of X is coming. + The quantity with standard name model_level_number_at_sea_floor is the depth of the ocean expressed in model levels. This could be a non-integer value because some ocean models use partial cells close to the sea floor. For example, if this field were 23.4 at some location, it would mean the water column at that point comprised 23 full model levels plus 40% occupancy of the lowest (24th) gridcell. - - s + + 1 - The wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S has the standard name sea_surface_wave_directional_variance_spectral_density. S can be integrated over direction to give S1= integral(S dtheta) and this quantity has the standard name sea_surface_wave_variance_spectral_density. Frequency moments, M(n) of S1 can then be calculated as follows: M(n) = integral(S1 f^n df), where f^n is f to the power of n. The first wave period, T(m1) is calculated as the ratio M(0)/M(1). + Model level number should be understood as equivalent to layer number. - - s + + kg m-2 - - The wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S has the standard name sea_surface_wave_directional_variance_spectral_density. S can be integrated over direction to give S1= integral(S dtheta) and this quantity has the standard name sea_surface_wave_variance_spectral_density. Frequency moments, M(n) of S1 can then be calculated as follows: M(n) = integral(S1 f^n df), where f^n is f to the power of n. The inverse wave period, T(m-1), is calculated as the ratio M(-1)/M(0). + mrsofcs + "moisture" means water in all phases contained in soil. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Quantities defined for a soil layer must have a vertical coordinate variable with boundaries indicating the extent of the layer(s). The field capacity of soil is the maximum content of water it can retain against gravitational drainage. - - s + + mol m-3 - The wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S has the standard name sea_surface_wave_directional_variance_spectral_density. S can be integrated over direction to give S1= integral(S dtheta) and this quantity has the standard name sea_surface_wave_variance_spectral_density. Frequency moments, M(n) of S1 can then be calculated as follows: M(n) = integral(S1 f^n df), where f^n is f to the power of n. The second wave period, T(m2) is calculated as the square root of the ratio M(0)/M(2). + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for acetic_acid is CH3COOH. The IUPAC name for acetic acid is ethanoic acid. - - s + + mol m-3 - A period is an interval of time, or the time-period of an oscillation. The sea_surface_wave_period_at_variance_spectral_density_maximum, sometimes called peak wave period, is the period of the most energetic waves in the total wave spectrum at a specific location. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for aceto-nitrile is CH3CN. The IUPAC name for aceto-nitrile is ethanenitrile. - - m - 100 + + mol m-3 + - Height is the vertical distance above the surface. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for alpha_hexachlorocyclohexane is C6H6Cl6. - - degree + + mol m-3 - "to_direction" is used in the construction X_to_direction and indicates the direction towards which the velocity vector of X is headed. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for alpha_pinene is C10H16. The IUPAC name for alpha-pinene is (1S,5S)-2,6,6-trimethylbicyclo[3.1.1]hept-2-ene. - - m2 s + + mol m-3 - Sea surface wave variance spectral density is the variance of wave amplitude within a range of wave frequency. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ammonia is NH3. - - s + + mol m-3 - A period is an interval of time, or the time-period of an oscillation. The zero upcrossing period is defined as the time interval between consecutive occasions on which the surface height passes upward above the mean level. + Mole concentration means moles (amount of substance) per unit volume and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. - - s + + mol m-3 - The wind wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S can be integrated over direction to give S1= integral(S dtheta) . Frequency moments, M(n) of S1 can then be calculated as follows: M(n) = integral(S1 f^n df), where f^n is f to the power of n. The first wave period, T(m1) is calculated as the ratio M(0)/M(1). + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituentsof A. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Anthropogenic" means influenced,caused, or created by human activity. - - s + + mol m-3 - The wind wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S can be integrated over direction to give S1= integral(S dtheta). Frequency moments, M(n) of S1 can then be calculated as follows: M(n) = integral(S1 f^n df), where f^n is f to the power of n. The inverse wave period, T(m-1), is calculated as the ratio M(-1)/M(0). + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Aragonite is a mineral that is a polymorph of calcium carbonate. The chemical formula of aragonite is CaCO3. Standard names also exist for calcite, another polymorph of calcium carbonate. - - s + + mol m-3 - The wind wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S can be integrated over direction, thus S1= integral(S dtheta). Frequency moments, M(n) of S1 can then be calculated as follows: M(n) = integral(S1 f^n df), where f^n is f to the power of n. The second wave period, T(m2), is calculated as the square root of the ratio M(0)/M(2). + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Mole concentration at saturation means the mole concentration in a saturated solution.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Aragonite is a mineral that is a polymorph of calcium carbonate. The chemical formula of aragonite is CaCO3. Standard names also exist for calcite, another polymorph of calcium carbonate. - - s - 103 + + mol m-3 + - A period is an interval of time, or the time-period of an oscillation. Wind waves are waves on the ocean surface. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for atomic bromine is Br. - - m - 102 + + mol m-3 + - Height is the vertical distance above the surface. Wind waves are waves on the ocean surface. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for atomic chlorine is Cl. - - degree - 101 + + mol m-3 + - Wind waves are waves on the ocean surface. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) "to_direction" is used in the construction X_to_direction and indicates the direction towards which the velocity vector of X is headed. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for atomic nitrogen is N. - - s + + mol m-3 - A period is an interval of time, or the time-period of an oscillation. The zero upcrossing period is defined as the time interval between consecutive occasions on which the surface height passes upward above the mean level. Wind waves are waves on the ocean surface. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - g kg-1 + + mol m-3 - Absolute Salinity, S_A, is defined as part of the Thermodynamic Equation of Seawater 2010 (TEOS-10) which was adopted in 2010 by the Intergovernmental Oceanographic Commission (IOC). It is the mass fraction of dissolved material in sea water. Absolute Salinity incorporates the spatial variations in the composition of sea water. This type of Absolute Salinity is also called "Density Salinity". TEOS-10 estimates Absolute Salinity as the salinity variable that, when used with the TEOS-10 expression for density, yields the correct density of a sea water sample even when the sample is not of Reference Composition. In practice, Absolute Salinity is often calculated from Practical Salinity using a spatial lookup table of pre-defined values of the Absolute Salinity Anomaly. It is recommended that the version of (TEOS-10) software and the associated Absolute Salinity Anomaly climatology be specified within metadata by attaching a comment attribute to the data variable. Reference: www.teos-10.org; Millero et al., 2008 doi: 10.1016/j.dsr.2007.10.001. There are also standard names for the precisely defined salinity quantities sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 onwards), sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Salinity quantities that do not match any of the precise definitions should be given the more general standard name of sea_water_salinity. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. - - year + + mol m-3 - "Sea water age since surface contact" means the length of time elapsed since the sea water in a grid cell was last in the surface level of an ocean model. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for beta_pinene is C10H16. The IUPAC name for beta-pinene is (1S,5S)-6,6-dimethyl-2-methylenebicyclo[3.1.1]heptane. - + mol m-3 - 'sea_water_alkalinity_expressed_as_mole_equivalent' is the total alkalinity equivalent concentration (including carbonate, nitrogen, silicate, and borate components). + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Biogenic" means influenced, caused, or created by natural processes. - - K + + mol m-3 - Conservative Temperature is defined as part of the Thermodynamic Equation of Seawater 2010 (TEOS-10) which was adopted in 2010 by the International Oceanographic Commission (IOC). Conservative Temperature is specific potential enthalpy (which has the standard name sea_water_specific_potential_enthalpy) divided by a fixed value divided by a fixed value of the specific heat capacity of sea water, namely cp_0 = 3991.86795711963 J kg-1 K-1. Conservative Temperature is a more accurate measure of the "heat content" of sea water, by a factor of one hundred, than is potential temperature. Because of this, it can be regarded as being proportional to the heat content of sea water per unit mass. Reference: www.teos-10.org; McDougall, 2003 doi: 10.1175/1520-0485(2003)033<0945:PEACOV>2.0.CO;2. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for bromine chloride is BrCl. - - 1e-3 + + mol m-3 - Cox Salinity, S_C, is defined unitless as a mass fraction per mil (0/00) or "parts per thousand". S_C was the standard salinity measure from 1967 until Practical Salinity, S_P, was established with PSS-78 (1978). Chlorinity, Cl, is calculated from the conductivity of a sea water sample and since the work of the Joint Panel for Oceanographic Tables and Standards (JPOTS; 1966) is converted into Cox Salinity using S_C = 1.80655Cl. This type of salinity was called simply "salinity" from 1967 to 1978. Cox Salinity was replaced by Practical Salinity in 1978. Cox Salinity is converted to Practical Salinity following S_P = S_C, however the accuracy of this is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of the Practical Salinity Scale 1978 (PSS-78). Reference: Cox et al., 1967 doi: 10.1016/0011-7471(67)90006-X; Lyman, 1969 doi: 10.4319/lo.1969.14.6.0928; Wooster et al., 1969 doi: 10.4319/lo.1969.14.3.0437. There are standard names for the precisely defined salinity quantities sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_practical_salinity, S_P, sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_* and sea_water_reference_salinity. Salinity quantities that do not match any of the precise definitions should be given the more general standard name of sea_water_salinity. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for bromine monoxide is BrO. - - kg m-3 + + mol m-3 - Sea water density is the in-situ density (not the potential density). If 1000 kg m-3 is subtracted, the standard name sea_water_sigma_t should be chosen instead. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for bromine nitrate is BrONO2. - - S m-1 + + mol m-3 - + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Brox" describes a family of chemical species consisting of inorganic bromine compounds with theexception of hydrogen bromide (HBr) and bromine nitrate (BrONO2). "Brox" is theterm used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of source gases containing bromine (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. Standard names that use the term "inorganic_bromine" are used for quantities that contain all inorganic bromine species including HCland ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard nameis calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - 1e-3 + + mol m-3 - Knudsen Salinity, S_K, is defined unitless as a mass fraction per mil (0/00) or "parts per thousand", and was calculated from the titration of inorganic salts from a sample of sea water after a commission to study the problem of determining salinity and density was initiated by the International Council for the Exploration of the Sea (ICES) in 1899. S_K was the standard salinity measure until S_C (Cox Salinity) was established in 1967. Since the work of Knudsen (1901), chlorinity is converted into Knudsen Salinity using S_K = 0.030 + 1.805 Cl. This type of salinity was called simply "salinity" from 1901 to 1966. From the 1960s on, electrical conductivity began to be used to estimate the Knudsen Salinity, rather than chemical titration. Knudsen Salinity was replaced by Cox Salinity in 1967 which was in turn replaced by Practical Salinity, S_P, in 1978. Conversion of Knudsen Salinity to Practical Salinity follows S_P = (S_K - 0.03) * (1.80655 / 1.805). Reference: Knudsen, 1901; Thomas et al., 1934 doi: 10.1093/icesjms/9.1.28; Lyman, 1969 doi: 10.4319/lo.1969.14.6.0928; Wooster et al., 1969 doi: 10.4319/lo.1969.14.3.0437; Lewis, 1980 doi: 10.1109/JOE.1980.1145448; Millero et al., 2008 doi: 10.1016/j.dsr.2007.10.001. There are standard names for the precisely defined salinity quantities sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P, sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_* and sea_water_reference_salinity. Salinity quantities that do not match any of the precise definitions should be given the more general standard name of sea_water_salinity. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. - - kg + + mol m-3 - The quantity with standard name "sea_water_mass" is the total mass of liquid seawater in the global oceans, including enclosed seas. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. 'Calcareous phytoplankton' are phytoplankton that produce calcite. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. Calcite is a mineral that is a polymorphof calcium carbonate. The chemical formula of calcite is CaCO3. Standard names also existfor aragonite, another polymorph of calcium carbonate. - - kg m-2 + + mol m-3 - Sea_water_mass_per_unit_area is the mass per unit area of the sea water contained within each grid cell. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Standard names also exist for aragonite, another polymorph of calcium carbonate. - - kg m-3 + + mol m-3 - "Neutral density" is a variable designed so that a surface of constant neutral density everywhere has a local slope that is close to the local slope of the neutral tangent plane. At the sea surface in the equatorial Pacific neutral density is very close to the potential density anomaly. At other locations, this is not the case. For example, along a neutral density surface there is a difference of up to 0.14 kg/m^3 in the potential density anomaly at the outcrops in the Southern and Northern hemispheres. Refer to Jackett & McDougall (1997; Journal of Physical Oceanography, Vol 27, doi: 10.1175/1520-0485(1997)027<0237:ANDVFT>2.0.CO;2) for more information. + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Mole concentration at saturation means the mole concentration in a saturated solution.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Standard names also exist for aragonite, another polymorph of calcium carbonate. - - 1 + + mol m-3 - 'sea_water_pH_reported_on_total_scale' is the measure of acidity of seawater, defined as the negative logarithm of the activity of dissolved hydrogen ions plus bisulfate ions in a sea water medium; it can be measured or calculated; when measured the scale is defined according to a series of buffers prepared in artificial seawater containing bisulfate. The quantity may be written as pH(total) = -log([H+](free) + [HSO4-]). + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". In ocean biogeochemistry models, an "abiotic analogue" is used to simulate the effect on a modelled variable when biological effects on ocean carbon concentration and alkalinity are ignored. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula of the carbonate anion is CO3 with an electrical charge of minus two. - - kg m-3 + + mol m-3 - Potential density is the density a parcel of air or sea water would have if moved adiabatically to a reference pressure, by default assumed to be sea level pressure. For sea water potential density, if 1000 kg m-3 is subtracted, the standard name sea_water_sigma_theta should be chosen instead. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula of the carbonate anion is CO3 with an electrical charge of minus two. Aragonite is a mineral that is a polymorph of calcium carbonate. The chemical formula of aragonite is CaCO3. At a given salinity, the thermodynamic equilibrium is that between dissolved carbonate ion and solid aragonite. Standard names also exist for calcite, another polymorph of calcium carbonate. - - K + + mol m-3 - Potential temperature is the temperature a parcel of air or sea water would have if moved adiabatically to sea level pressure. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula of the carbonate anion is CO3 with an electrical charge of minus two. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. At a given salinity, the thermodynamic equilibrium is that between dissolved carbonate ion and solid calcite. Standard names also exist for aragonite, another polymorph of calcium carbonate. - - 1e-3 + + mol m-3 - Practical Salinity, S_P, is defined on the Practical Salinity Scale of 1978 (PSS-78) and is calculated from the electrical conductivity of sea water (as well as temperature and pressure). Officially S_P is dimensionless so that, while convenient, and while it is common practice, it is not officially sanctioned to say S_P = 35 psu. Often authors use PSS-78, as in S_P = 35 PSS-78. If salinity was measured using remote sensing techniques and not conductivity, then it is recommended that additional metadata (calibration/validation information) be described in the variable comment attribute. This name should be used to describe salinity observations made from 1978 onwards (Practical Salinity is the salinity quantity stored by national data centres for post-1978 observations). The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. There are also standard names for the precisely defined salinity quantities sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Salinity quantities that do not match any of the precise definitions should be given the more general standard name of sea_water_salinity. Reference: www.teos-10.org; Lewis, 1980 doi:10.1109/JOE.1980.1145448 + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula of the carbonate anion is CO3 with a charge of minus two. - - g kg-1 + + mol m-3 - Preformed Salinity, S*, is defined as part of the Thermodynamic Equation of Seawater 2010 (TEOS-10) which was adopted in 2010 by the Intergovernmental Oceanographic Commission (IOC). Preformed Salinity is a salinity variable that is designed to be as conservative as possible, by removing the estimated biogeochemical influences on the sea water composition. Preformed Salinity is Absolute Salinity, S_A (which has the standard name sea_water_absolute_salinity), minus all contributions to sea water composition from biogeochemical processes. Preformed Salinity is the mass fraction of dissolved material in sea water. Reference: www.teos-10.org; Pawlowicz et al., 2011 doi: 10.5194/os-7-363-2011; Wright et al., 2011 doi: 10.5194/os-7-1-2011. There are also standard names for the precisely defined salinity quantities sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 onwards), and sea_water_reference_salinity. Salinity quantities that do not match any of the precise definitions should be given the more general standard name of sea_water_salinity. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". In ocean biogeochemistry models, a "natural analogue" is used to simulate the effect on a modelled variable of imposing preindustrial atmospheric carbon dioxide concentrations, even when the model as a whole may be subjected to varying forcings. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula of the carbonate anion is CO3 with an electrical charge of minus two. - - dbar + + mol m-3 - "Sea water pressure" is the pressure that exists in the medium of sea water. It includes the pressure due to overlying sea water, sea ice, air and any other medium that may be present. For sea water pressure excluding the pressure due to overlying media other than sea water, the standard name sea_water_pressure_due_to_sea_water should be used. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for carbon dioxide is CO2. - - dbar + + mol m-3 - "Sea water pressure" is the pressure that exists in the medium of sea water. It includes the pressure due to overlying sea water, sea ice, air and any other medium that may be present. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of carbon monoxide is CO. - - dbar + + mol m-3 - The surface called "surface" means the lower boundary of the atmosphere. "Sea water pressure" is the pressure that exists in the medium of sea water. It includes the pressure due to overlying sea water, sea ice, air and any other medium that may be present. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of carbon tetrachloride is CCl4. - - dbar + + mol m-3 - The pressure that exists in the medium of sea water due to overlying sea water. Excludes the pressure due to sea ice, air and any other medium that may be present. For sea water pressure including the pressure due to overlying media other than sea water, the standard name sea_water_pressure should be used. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC113a CCl3CF3. The IUPAC name for CFC113a is 1,1,1-trichloro-2,2,2-trifluoro-ethane. - - g kg-1 + + mol m-3 - If a sea water sample has the Reference Composition (defined in Millero et al., 2008), then its Reference Salinity is the best available estimate of its Absolute Salinity. For general purposes, Reference Salinity is (35.16504 g kg-1)/35 times Practical Salinity. Reference: www.teos-10.org; Millero et al., 2008 doi: 10.1016/j.dsr.2007.10.001. There are also standard names for the precisely defined salinity quantities sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity (used for salinity observations from 1978 onwards), sea_water_absolute_salinity, S_A, and sea_water_preformed_salinity, S_*. Salinity quantities that do not match any of the precise definitions should be given the more general standard name of sea_water_salinity. - - - - 1e-3 - 88 - so - Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and the units attribute should normally be given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC113 is CCl2FCClF2. The IUPAC name for CFC113 is 1,1,2-trichloro-1,2,2-trifluoro-ethane. - - kg m-3 + + mol m-3 - Sigma-t of sea water is the density of water at atmospheric pressure (i.e. the surface) having the same temperature and salinity, minus 1000 kg m-3. Note that sea water sigma is not the same quantity as the dimensionless ocean sigma coordinate (see Appendix D of the CF convention), for which there is another standard name. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC114 is CClF2CClF2. The IUPAC name for CFC114 is 1,2-dichloro-1,1,2,2-tetrafluoro-ethane. - - kg m-3 + + mol m-3 - Sigma-theta of sea water is the potential density (i.e. the density when moved adiabatically to a reference pressure) of water having the same temperature and salinity, minus 1000 kg m-3. Note that sea water sigma is not the same quantity as the dimensionless ocean sigma coordinate (see Appendix D of the CF convention), for which there is another standard name. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC115 is CClF2CF3. The IUPAC name for CFC115 is 1-chloro-1,1,2,2,2-pentafluoro-ethane. - - J kg-1 + + mol m-3 - The potential enthalpy of a sea water parcel is the specific enthalpy after an adiabatic and isohaline change in pressure from its in situ pressure to the sea pressure p = 0 dbar. "specific" means per unit mass. Reference: www.teos-10.org; McDougall, 2003 doi: 10.1175/1520-0485(2003)033<0945:PEACOV>2.0.CO;2. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC11 is CFCl3. The IUPAC name fof CFC11 is trichloro-fluoro-methane. - - m s-1 - 48 + + mol m-3 + - Speed is the magnitude of velocity. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The chemical formula of CFC11 is CFCl3. The IUPAC name fof CFC11 is trichloro-fluoro-methane. - - K - 80 - to - Sea water temperature is the in situ temperature of the sea water. To specify the depth at which the temperature applies use a vertical coordinate variable or scalar coordinate variable. There are standard names for sea_surface_temperature, sea_surface_skin_temperature, sea_surface_subskin_temperature and sea_surface_foundation_temperature which can be used to describe data located at the specified surfaces. For observed data, depending on the period during which the observation was made, the measured in situ temperature was recorded against standard "scales". These historical scales include the International Practical Temperature Scale of 1948 (IPTS-48; 1948-1967), the International Practical Temperature Scale of 1968 (IPTS-68, Barber, 1969; 1968-1989) and the International Temperature Scale of 1990 (ITS-90, Saunders 1990; 1990 onwards). Conversion of data between these scales follows t68 = t48 - (4.4 x 10e-6) * t48(100 - t - 48); t90 = 0.99976 * t68. Observations made prior to 1948 (IPTS-48) have not been documented and therefore a conversion cannot be certain. Differences between t90 and t68 can be up to 0.01 at temperatures of 40 C and above; differences of 0.002-0.007 occur across the standard range of ocean temperatures (-10 - 30 C). The International Equation of State of Seawater 1980 (EOS-80, UNESCO, 1981) and the Practical Salinity Scale (PSS-78) were both based on IPTS-68, while the Thermodynamic Equation of Seawater 2010 (TEOS-10) is based on ITS-90. References: Barber, 1969, doi: 10.1088/0026-1394/5/2/001; UNESCO, 1981; Saunders, 1990, WOCE Newsletter, 10, September 1990. + + mol m-3 + + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for CFC12 is CF2Cl2. The IUPAC name for CFC12 is dichloro-difluoro-methane. - - kg s-1 + + mol m-3 - Transport across_line means that which crosses a particular line on the Earth's surface; formally this means the integral along the line of the normal component of the transport. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The chemical formula for CFC12 is CF2Cl2. The IUPAC name for CFC12 is dichloro-difluoro-methane. - - 1 + + mol m-3 - Turbidity is a dimensionless quantity which is expressed in NTU (Nephelometric Turbidity Units). Turbidity expressed in NTU is the proportion of white light scattered back to a transceiver by the particulate load in a body of water, represented on an arbitrary scale referenced against measurements made in the laboratory on aqueous suspensions of formazine beads. Sea water turbidity may also be measured by the quantity with standard name secchi_depth_of_sea_water. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for chlorine dioxide is OClO. - - m3 + + mol m-3 - The quantity with standard name "sea_water_volume" is the total volume of liquid seawater in the global oceans, including enclosed seas. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for chlorine monoxide is ClO. - - m s-1 + + mol m-3 - A velocity is a vector quantity. "x" indicates a vector component along the grid x-axis, positive with increasing x. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for chlorine nitrate is ClONO2. - - m s-1 + + mol m-3 - A velocity is a vector quantity. "y" indicates a vector component along the grid y-axis, positive with increasing y. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Clox"describes a family of chemical species consisting of inorganic chlorine compounds with theexception of hydrogen chloride (HCl) and chlorine nitrate (ClONO2). "Clox" is the term used in standard names for all species belonging to the family that are representedwithin a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, byusing a comment attribute. "Inorganic chlorine", sometimes referred to as Cly, describes a family of chemical species which result from the degradation of source gases containing chlorine (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as seasaltand other aerosols. Standard names that use the term "inorganic_chlorine" are used for quantities that contain all inorganic chlorine species including HCl and ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculatedsolely with respect to the B contained in A, neglecting all other chemical constituents ofA. - - m + + mol m-3 - Depth is the vertical distance below the surface. A Secchi disk is a patterned disk that is used to measure water transparency, also called turbidity, in oceans and lakes. The disk is lowered into the water and the depth at which the pattern is no longer visible is the called the secchi depth. Sea water turbidity may also be measured by the quantity with standard name sea_water_turbidity. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Diatoms are single-celled phytoplankton with an external skeleton made of silica.Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. - - 1 + + mol m-3 - "Time fraction" means a fraction of a time interval. The interval in question must be specified by the values or bounds of the time coordinate variable associated with the data. "X_time_fraction" means the fraction of the time interval during which X occurs. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated in terms of B alone, neglecting all other chemical constituents of A. - - mol m-2 s-1 + + mol m-3 - The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. 'Sinking' is the gravitational settling of particulate matter suspended in a liquid. A sinking flux is positive downwards and is calculated relative to the movement of the surrounding fluid. Aragonite is a mineral that is a polymorph of calcium carbonate. The chemical formula of aragonite is CaCO3. Standard names also exist for calcite, another polymorph of calcium carbonate. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. In ocean modelling, diazotrophs are phytoplankton of the phylum cyanobacteria distinct from other phytoplankton groups in their ability to fix nitrogen gas in addition to nitrate and ammonium. Phytoplankton are autotrophic prokaryotic or eukaryotic organisms that live near the water surface where there is sufficient light to support photosynthesis. - - mol m-2 s-1 + + mol m-3 - The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. 'Sinking' is the gravitational settling of particulate matter suspended in a liquid. A sinking flux is positive downwards and is calculated relative to the movement of the surrounding fluid. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Standard names also exist for aragonite, another polymorph of calcium carbonate. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for dichlorine peroxide is Cl2O2. - - mol m-2 s-1 + + mol m-3 - In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. 'Sinking' is the gravitational settling of particulate matter suspended in a liquid. A sinking flux is positive downwards and is calculated relative to the movement of the surrounding fluid. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for dimethyl sulfide is (CH3)2S. Dimethyl sulfide is sometimes referred to as DMS. - - mol m-2 s-1 + + mol m-3 - The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. 'Sinking' is the gravitational settling of particulate matter suspended in a liquid. A sinking flux is positive downwards and is calculated relative to the movement of the surrounding fluid. + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for dimethyl sulfide is (CH3)2S. Dimethyl sulfide is sometimes referred to as DMS. - - mol m-2 s-1 + + mol m-3 - In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. 'Sinking' is the gravitational settling of particulate matter suspended in a liquid. A sinking flux is positive downwards and is calculated relative to the movement of the surrounding fluid. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for dinitrogen pentoxide is N2O5. - - mol m-2 s-1 + + mol m-3 - In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. 'Sinking' is the gravitational settling of particulate matter suspended in a liquid. A sinking flux is positive downwards and is calculated relative to the movement of the surrounding fluid. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Dissolved inorganic carbon" describes a family of chemical species in solution, including carbon dioxide, carbonic acid and the carbonate and bicarbonate anions. "Dissolved inorganic carbon" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "C" means the element carbon and "13C" is the stable isotope "carbon-13", having six protons and seven neutrons. - - mol m-2 s-1 + + mol m-3 - In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. 'Sinking' is the gravitational settling of particulate matter suspended in a liquid. A sinking flux is positive downwards and is calculated relative to the movement of the surrounding fluid. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Dissolved inorganic carbon" describes a family of chemical species in solution, including carbon dioxide, carbonic acid and the carbonate and bicarbonate anions. "Dissolved inorganic carbon" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "C" means the element carbon and "14C" is the radioactive isotope "carbon-14", having six protons and eight neutrons and used in radiocarbon dating. - - kg m-2 + + mol m-3 - "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including content_of_soil_layer are used. "Soil carbon" is the organic matter present in soil quantified by the mass of carbon it contains. Soil carbon is returned to the atmosphere as the organic matter decays. The decay process takes varying amounts of time depending on the composition of the organic matter, the temperature and the availability of moisture. A carbon "soil pool" means the carbon contained in organic matter which has a characteristic period over which it decays and releases carbon into the atmosphere. "Slow soil pool" refers to the decay of organic matter in soil with a characteristic period of more than a hundred years under reference climate conditions of a temperature of 20 degrees Celsius and no water limitations. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". In ocean biogeochemistry models, an "abiotic analogue" is used to simulate the effect on a modelled variable when biological effects on ocean carbon concentration and alkalinity are ignored. "Dissolved inorganic carbon" describes a family of chemical species in solution, including carbon dioxide, carbonic acid and the carbonate and bicarbonate anions. "Dissolved inorganic carbon" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. - - kg m-3 + + mol m-3 - + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Dissolved inorganic carbon" describes a family of chemical species in solution, including carbon dioxide, carbonic acid and the carbonate and bicarbonate anions. "Dissolved inorganic carbon" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the speciesrepresented, for example, by using a comment attribute. - - kg m-2 + + mol m-3 - "Amount" means mass per unit area. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". In ocean biogeochemistry models, a "natural analogue" is used to simulate the effect on a modelled variable of imposing preindustrial atmospheric carbon dioxide concentrations, even when the model as a whole may be subjected to varying forcings. "Dissolved inorganic carbon" describes a family of chemical species in solution, including carbon dioxide, carbonic acid and the carbonate and bicarbonate anions. "Dissolved inorganic carbon" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. - - kg m-2 s-1 - 64 - prsn - In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + mol m-3 + + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Dissolved inorganic phosphorus" means the sum of all inorganic phosphorus in solution (including phosphate, hydrogen phosphate, dihydrogen phosphate, and phosphoric acid). - - m + + mol m-3 - + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Dissolved inorganic silicon" means the sum of all inorganic silicon in solution (including silicic acid and its first dissociated anion SiO(OH)3-). - - 1 + + mol m-3 - Soil albedo is the albedo of the soil surface assuming no snow. + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. - - kg m-2 + + mol m-3 - "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including content_of_soil_layer are used. + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. - - kg m-2 + + mol m-3 - mrfso - "frozen_water" means ice. "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including content_of_soil_layer are used. + + "Mole concentration at saturation" means the mole concentration in a saturated solution. Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". - - m s-1 + + mol m-3 - Hydraulic conductivity is the constant k in Darcy's Law q=-k grad h for fluid flow q (volume transport per unit area i.e. velocity) through a porous medium, where h is the hydraulic head (pressure expressed as an equivalent depth of water). - - - - kg m-2 - 86 - mrso - "moisture" means water in all phases contained in soil. "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including content_of_soil_layer are used. + 'Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The concentration of any chemical species, whether particulate or dissolved, may vary with depth in the ocean. A depth profile may go through one or more local minima in concentration. The mole_concentration_of_molecular_oxygen_in_sea_water_at_shallowest_local_minimum_in_vertical_profile is the mole concentration of oxygen at the local minimum in the concentration profile that occurs closest to the sea surface. - - kg m-2 + + mol m-3 - mrsofc - "moisture" means water in all phases contained in soil. "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including content_of_soil_layer are used. The field capacity of soil is the maximum content of water it can retain against gravitational drainage. + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where Xis a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Organic carbon describes a family of chemical species and is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a completedescription of the species represented, for example, by using a comment attribute. - - 1 + + mol m-3 - The soil porosity is the proportion of its total volume not occupied by soil solids. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes.There are standard names for the alkane group as well as for some of the individual species. - - kg m-2 s-1 + + mol m-3 - "Respiration carbon" refers to the rate at which biomass is respired expressed as the mass of carbon which it contains. Soil respiration is the sum of respiration in the soil by animals and decomposers of litter (heterotrophs or "consumers"), which have not produced the biomass they respire, and respiration by the roots of plants (autotrophs or "producers"), which have themselves produced the biomass they respire. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethanol is C2H5OH. - - Pa + + mol m-3 - Soil suction is the tensile stress on water in soil due to molecular forces acting at the water-soil particle boundary. The forces may cause water to be drawn into the spaces within the soil matrix or cause it to be held in the soil without draining. Soil suction occurs in soil above the water table. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes.There are standard names for the alkene group as well as for some of the individual species. - - K - 85 + + mol m-3 + - Soil temperature is the bulk temperature of the soil, not the surface (skin) temperature. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonlyknown as acetylene. - - J kg-1 K-1 + + mol m-3 - Thermal capacity, or heat capacity, is the amount of heat energy required to increase the temperature of 1 kg of material by 1 K. It is a property of the material. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. - - W m-1 K-1 + + mol m-3 - Thermal conductivity is the constant k in the formula q = -k grad T where q is the heat transfer per unit time per unit area of a surface normal to the direction of transfer and grad T is the temperature gradient. Thermal conductivity is a property of the material. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for formic acid is HCOOH. The IUPAC name for formic acid is methanoic acid. - - 1 + + mol m-3 - A variable with the standard name of soil_type contains strings which indicate the character of the soil e.g. clay. These strings have not yet been standardised. Alternatively, the data variable may contain integers which can be translated to strings using flag_values and flag_meanings attributes. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Divalent mercury" means all compounds in which the mercury has two binding sites to other ion(s)in a salt or to other atom(s) in a molecule. - - degree + + mol m-3 - Solar azimuth angle is the horizontal angle between the line of sight to the sun and a reference direction which is often due north. The angle is measured clockwise. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for mercury is Hg. - - degree + + mol m-3 - Solar elevation angle is the angle between the line of sight to the sun and the local horizontal. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halon1202 is CBr2F2. The IUPAC name for halon1202 is dibromo-difluoro-methane. - - degree + + mol m-3 - Solar zenith angle is the the angle between the line of sight to the sun and the local vertical. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halon1211 is CBrClF2. The IUPAC name for halon1211 is bromo-chloro-difluoro-methane. - - kg m-2 + + mol m-3 - "Content" indicates a quantity per unit area. The surface called "surface" means the lower boundary of the atmosphere. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halon1301 is CBrF3. The IUPAC name for halon1301 is bromo-trifluoro-methane. - - s-1 + + mol m-3 - Frequency is the number of oscillations of a wave per unit time. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for halo2402 is C2Br2F4. The IUPAC name for halon2402 is 1,2-dibromo-1,1,2,2-tetrafluoro-ethane. - - W m-2 + + mol m-3 - Sound intensity is the sound energy per unit time per unit area. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hcc140a is CH3CCl3. The IUPAC name for hcc140a is 1,1,1-trichloro-ethane. - - W m-2 + + mol m-3 - Sound intensity is the sound energy per unit time per unit area. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for HCFC141b is CH3CCl2F. The IUPAC name for HCFC141b is 1,1-dichloro-1-fluoroethane. - - dB + + mol m-3 - Sound intensity is the sound energy per unit time per unit area. Sound intensity level in air is expressed on a logarithmic scale with reference to a sound intensity of 1e-12 W m-2. LI = 10 log10(I/I0) where LI is sound intensity level, I is sound intensity and I0 is the reference sound intensity. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for HCFC142b is CH3CClF2. The IUPAC name for HCFC142b is 1-chloro-1,1-difluoroethane. - - dB + + mol m-3 - Sound intensity is the sound energy per unit time per unit area. Sound intensity level in water is expressed on a logarithmic scale with reference to a sound intensity of 6.7e-19 W m-2. LI = 10 log10(I/I0) where LI is sound intensity level, I is sound intensity and I0 is the reference sound intensity. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for HCFC22 is CHClF2. The IUPAC name for HCFC22 is chloro-difluoro-methane. - - Pa + + mol m-3 - Sound pressure is the difference from the local ambient pressure caused by a sound wave at a particular location and time. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hexachlorobiphenyl is C12H4Cl6. This structure of this species consists of two linked benzene rings, each of which is additionally bonded to three chlorine atoms. - - Pa + + mol m-3 - Sound pressure is the difference from the local ambient pressure caused by a sound wave at a particular location and time. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "HOx" means a combination of two radical species containing hydrogen and oxygen: OH and HO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - dB + + mol m-3 - Sound pressure is the difference from the local ambient pressure caused by a sound wave at a particular location and time. Sound pressure level in air is expressed on a logarithmic scale with reference to a sound pressure of 2e-5 Pa. Lp = 20 log10(p/p0) where Lp is the sound pressure level, p is the rms sound pressure and p0 is the reference sound pressure. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen bromide is HBr. - - dB + + mol m-3 - Sound pressure is the difference from the local ambient pressure caused by a sound wave at a particular location and time. Sound pressure level in water is expressed on a logarithmic scale with reference to a sound pressure of 1e-6 Pa. Lp = 20 log10(p/p0) where Lp is the sound pressure level, p is the rms sound pressure and p0 is the reference sound pressure. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen chloride is HCl. - - m2 s-2 + + mol m-3 - "specific" means per unit mass. Dry energy is the sum of dry static energy and kinetic energy. Dry static energy is the sum of enthalpy and potential energy (itself the sum of gravitational and centripetal potential energy). Enthalpy can be written either as (1) CpT, where Cp is heat capacity at constant pressure, T is absolute temperature, or (2) U+pV, where U is internal energy, p is pressure and V is volume. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen cyanide is HCN. - - J kg-1 + + mol m-3 - "specific" means per unit mass. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) - - - - 1 - 51 E133 - hus - "specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hydrogen peroxide is H2O2. - - m2 s-2 + + mol m-3 - "specific" means per unit mass. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for the hydroperoxyl radical is HO2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. - - m2 s-2 + + mol m-3 - "specific" means per unit mass. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for the hydroxyl radical is OH. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. - - m s-1 + + mol m-3 - Speed is the magnitude of velocity. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hypobromous acid is HOBr. - - m s-1 + + mol m-3 - Speed is the magnitude of velocity. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for hypochlorous acid is HOCl. - - day + + mol m-3 - Air temperature is the bulk temperature of the air, not the surface (skin) temperature. A spell is the number of consecutive days on which the condition X_below|above_threshold is satisified. A variable whose standard name has the form spell_length_of_days_with_X_below|above_threshold must have a coordinate variable or scalar coordinate variable with the a standard name of X to supply the threshold(s). It must have a climatological time variable, and a cell_method entry for within days which describes the processing of quantity X before the threshold is applied. A spell_length_of_days is an intensive quantity in time, and the cell_methods entry for over days can be any of the methods listed in Appendix E appropriate for intensive quantities e.g. "maximum", "minimum" or "mean". + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of source gases containing bromine (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. "Inorganic bromine" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names that use the term "brox" are used for quantities that contain all inorganic bromine species except HBr and BrONO2. - - day + + mol m-3 - Air temperature is the bulk temperature of the air, not the surface (skin) temperature. A spell is the number of consecutive days on which the condition X_below|above_threshold is satisified. A variable whose standard name has the form spell_length_of_days_with_X_below|above_threshold must have a coordinate variable or scalar coordinate variable with the a standard name of X to supply the threshold(s). It must have a climatological time variable, and a cell_method entry for within days which describes the processing of quantity X before the threshold is applied. A spell_length_of_days is an intensive quantity in time, and the cell_methods entry for over days can be any of the methods listed in Appendix E appropriate for intensive quantities e.g. "maximum", "minimum" or "mean". + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Inorganic chlorine", sometimes referred to as Cly, describes a family of chemical species which result from the degradation of source gases containing chlorine (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as seasalt and other aerosols. "Inorganic chlorine" is the term used in standard names for all species belonging to the family that arerepresented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names that use the term "clox"are used for quantities that contain all inorganic chlorine species except HCl and ClONO2. - - day + + mol m-3 - "Amount" means mass per unit area. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. "lwe" means liquid water equivalent. A spell is the number of consecutive days on which the condition X_below|above_threshold is satisified. A variable whose standard name has the form spell_length_of_days_with_X_below|above_threshold must have a coordinate variable or scalar coordinate variable with the a standard name of X to supply the threshold(s). It must have a climatological time variable, and a cell_method entry for within days which describes the processing of quantity X before the threshold is applied. A spell_length_of_days is an intensive quantity in time, and the cell_methods entry for over days can be any of the methods listed in Appendix E appropriate for intensive quantities e.g. "maximum", "minimum" or "mean". + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for isoprene is CH2=C(CH3)CH=CH2. The IUPAC name for isoprene is 2-methyl-buta-1,3-diene. Isoprene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. - - day + + mol m-3 - "Amount" means mass per unit area. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. "lwe" means liquid water equivalent. A spell is the number of consecutive days on which the condition X_below|above_threshold is satisified. A variable whose standard name has the form spell_length_of_days_with_X_below|above_threshold must have a coordinate variable or scalar coordinate variable with the a standard name of X to supply the threshold(s). It must have a climatological time variable, and a cell_method entry for within days which describes the processing of quantity X before the threshold is applied. A spell_length_of_days is an intensive quantity in time, and the cell_methods entry for over days can be any of the methods listed in Appendix E appropriate for intensive quantities e.g. "maximum", "minimum" or "mean". + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl hydroperoxide is CH3OOH. - - K2 + + mol m-3 - mptta - "square_of_X" means X*X. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. - - - - s-2 - N138 - "square_of_X" means X*X. Frequency is the number of oscillations of a wave per unit time. + Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where Xis a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Mesozooplankton are zooplankton ranging between 20 micrometers and 200 micrometers in size. - - m2 s-2 + + mol m-3 - mpuua - "square_of_X" means X*X. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated in terms of B alone, neglecting all other chemical constituents of A. - - m2 + + mol m-3 - "square_of_X" means X*X. Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. Geopotential height is the geopotential divided by the standard acceleration due to gravity. It is numerically similar to the altitude (or geometric height) and not to the quantity with standard name height, which is relative to the surface. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. - - Pa2 s-2 + + mol m-3 - "square_of_X" means X*X. "tendency_of_X" means derivative of X with respect to time. The Lagrangian tendency of a quantity is its rate of change following the motion of the fluid, also called the "material derivative" or "convective derivative". The Lagrangian tendency of air pressure, often called "omega", plays the role of the upward component of air velocity when air pressure is being used as the vertical coordinate. If the vertical air velocity is upwards, it is negative when expressed as a tendency of air pressure; downwards is positive. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methanol is CH3OH. - - m2 s-2 + + mol m-3 - mpvva - "square_of_X" means X*X. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl bromide is CH3Br. The IUPAC name for methyl bromide is bromomethane. - - m2 + + mol m-3 - The ocean mixed layer is the upper part of the ocean, regarded as being well-mixed. The base of the mixed layer defined by temperature, sigma, sigma_theta or sigma_t is the level at which the quantity indicated differs from its surface value by a certain amount. "Thickness" means the vertical extent of a layer. "square_of_X" means X*X. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl chloride is CH3Cl. The IUPAC name for methyl chloride is chloromethane. - - m2 + + mol m-3 - The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. (The volume enclosed between the geoid and the sea floor equals the mean volume of water in the ocean.) In an ocean GCM the geoid is the surface of zero depth, or the rigid lid if the model uses that approximation. "Sea surface height" is a time-varying quantity. "square_of_X" means X*X. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl hydroperoxide is CH3OOH. - - K2 + + mol m-3 - Sea surface temperature is usually abbreviated as "SST". It is the temperature of sea water near the surface (including the part under sea-ice, if any), and not the skin temperature, whose standard name is surface_temperature. For the temperature of sea water at a particular depth or layer, a data variable of sea_water_temperature with a vertical coordinate axis should be used. "square_of_X" means X*X. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for methyl_peroxy_radical is CH3O2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. - - m2 s-2 + + mol m-3 - "square_of_X" means X*X. A velocity is a vector quantity. "Upward" indicates a vector component which is positive when directed upward (negative downward). Upward air velocity is the vertical component of the 3D air velocity vector. + Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where Xis a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Microzooplankton are zooplankton of less than 20 micrometers in size. - - kg2 s-2 + + mol m-3 - "Upward" indicates a vector component which is positive when directed upward (negative downward). Ocean transport means transport by all processes, both sea water and sea ice. "square_of_X" means X*X. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated in terms of B alone, neglecting all other chemical constituents of A. - - 1 + + mol m-3 - "X_area_fraction" means the fraction of horizontal area occupied by X. Cloud area fraction is also called "cloud amount" and "cloud cover". The cloud area fraction is for the whole atmosphere column, as seen from the surface or the top of the atmosphere. The cloud area fraction in a layer of the atmosphere has the standard name cloud_area_fraction_in_atmosphere_layer. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. 'Miscellaneous phytoplankton' are all those phytoplankton that are not diatoms, diazotrophs, calcareous phytoplankton, picophytoplankton or other seperately named components of the phytoplankton population. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. - - 1 + + mol m-3 - "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. Cloud area fraction is also called "cloud amount" and "cloud cover". In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). + Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where Xis a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. 'Miscellaneous zooplankton' are all those zooplankton that are not mesozooplankton, microzooplankton or other seperately named components of the zooplankton population. - - 1 + + mol m-3 - Emissivity is the ratio of the power emitted by an object to the power that would be emitted by a perfect black body having the same temperature as the object. The emissivity is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength or radiation_frequency is included to specify either the wavelength or frequency. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). "longwave" means longwave radiation. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for molecular hydrogen is H2. - - kg m-2 s-1 + + mol m-3 - In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for the nitrate anion is NO3-. The chemical formula for the nitrite anion is NO2-. - - kg m-2 - 62 + + mol m-3 + - Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. "Amount" means mass per unit area. + Mole concentration means moles (amount of substance) per unit volume and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. - - kg m-2 s-1 + + mol m-3 - In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. - - kg m-2 + + mol m-3 - Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. "Amount" means mass per unit area. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitric acid is HNO3. - - kg m-2 s-1 + + mol m-3 - In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. The chemical formula for nitric acid is HNO3. Nitric acid trihydrate, sometimes referred to as NAT, is a stable crystalline substance consisting of three molecules of water to one molecule of nitric acid. - - m s-1 + + mol m-3 - Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for the nitrite anion is NO2-. - - kg m-2 - 79 + + mol m-3 + - Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. "Amount" means mass per unit area. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrogen dioxide is NO2. - - kg m-2 s-1 + + mol m-3 - In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrogen monoxide is NO. - - mol m-2 + + mol m-3 - "Content" indicates a quantity per unit area. The "stratosphere content" of a quantity refers to the vertical integral from the tropopause to the stratopause. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for nitrogen_dioxide is NO2. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrous acid is HNO2. - - kg m-2 + + mol m-3 - "Content" indicates a quantity per unit area. "Litter carbon" is dead plant material in or above the soil quantified as the mass of carbon which it contains. The surface called "surface" means the lower boundary of the atmosphere. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for nitrous oxide is N2O. - - kg m-2 + + mol m-3 - "Amount" means mass per unit area. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained inA, neglecting all other chemical constituents of A. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. - - kg m-2 s-1 + + mol m-3 - Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solelywith respect to the B contained in A, neglecting all other chemical constituents of A. - - 1 + + mol m-3 - X_binary_mask has 1 where condition X is met, 0 elsewhere. - - - - Pa - E134 - ps - The surface called "surface" means the lower boundary of the atmosphere. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Noy" describes a family of chemical species. The family usually includes atomic nitrogen (N), nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), peroxynitric acid (HNO4), bromine nitrate (BrONO2) , chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)). The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name iscalculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - 1 - 84 E174 + + mol m-3 + - The surface called "surface" means the lower boundary of the atmosphere. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Organic detritus are particles of debris from decaying plants and animals. - - 1 + + mol m-3 - The surface called "surface" means the lower boundary of the atmosphere. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Organic detritus are particles of debris from decaying plants and animals. - - 1 + + mol m-3 - The surface called "surface" means the lower boundary of the atmosphere. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Organic detritus are particles of debris from decaying plants and animals. - - m + + mol m-3 - orog - The surface called "surface" means the lower boundary of the atmosphere. Altitude is the (geometric) height above the geoid, which is the reference geopotential surface. The geoid is similar to mean sea level. + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for ozone is O3. - - 1 + + mol m-3 - The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength is included to specify the wavelength. Scattering of radiation is its deflection from its incident path without loss of energy. Backwards scattering refers to the sum of scattering into all backward angles i.e. scattering_angle exceeding pi/2 radians. A scattering_angle should not be specified with this quantity. + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - 1 + + mol m-3 - The surface called "surface" means the lower boundary of the atmosphere. "Bidirectional_reflectance" depends on the angles of incident and measured radiation. Reflectance is the ratio of the energy of the reflected to the incident radiation. A coordinate variable of radiation_wavelength or radiation_frequency can be used to specify the wavelength or frequency, respectively, of the radiation. + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - K + + mol m-3 - The surface called "surface" means the lower boundary of the atmosphere.The brightness temperature of a body is the temperature of a black body which radiates the same power per unit solid angle per unit area. + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - Pa + + mol m-3 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. The partial pressure of a gaseous constituent of air is the pressure which it alone would exert with unchanged temperature and number of moles per unit volume. + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - Pa + + mol m-3 - The partial pressure of a dissolved gas in sea water is the partial pressure in air with which it would be in equilibrium. The partial pressure of a gaseous constituent of air is the pressure which it alone would exert with unchanged temperature and number of moles per unit volume. The surface called "surface" means the lower boundary of the atmosphere. The chemical formula for carbon dioxide is CO2. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - W m-2 + + mol m-3 - The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". Radiative flux is the sum of shortwave and longwave radiative fluxes. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 300-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for peroxyacetyl nitrate, sometimes referred to as PAN, is CH3COO2NO2. The IUPAC namefor peroxyacetyl_nitrate is nitroethaneperoxoate. - - W m-2 + + mol m-3 - Downwelling radiation is radiation from above. It does not mean "net downward". "Diffuse" radiation is radiation that has been scattered by particles in the atmosphere such as cloud droplets and aerosols. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. "shortwave" means shortwave radiation. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for peroxynitric acid, sometimes referred to as PNA, is HO2NO2. - - W m-2 + + mol m-3 - Downwelling radiation is radiation from above. It does not mean "net downward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". "Diffuse" radiation is radiation that has been scattered by particles in the atmosphere such as cloud droplets and aerosols. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. A phrase "assuming_condition" indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "shortwave" means shortwave radiation. - - - - Pa - E180 - tauu - The surface called "surface" means the lower boundary of the atmosphere. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Downward" indicates a vector component which is positive when directed downward (negative upward). "Downward eastward" indicates the ZX component of a tensor. A downward eastward stress is a downward flux of eastward momentum, which accelerates the lower medium eastward and the upper medium westward. The surface downward stress is the windstress on the surface. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. - - W m-2 + + mol m-3 - hfns - The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). The vertical heat flux in air is the sum of all heat fluxes i.e. radiative, latent and sensible. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. Standard names also exist for the mole concentration of a number of components that make up the total phytoplankton population, such as diatoms, diazotrophs, calcareous phytoplankton, picophytoplankton and miscellaneous phytoplankton. - - W m-2 + + mol m-3 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. - - Wm-2 + + mol m-3 - "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - W m-2 + + mol m-3 - The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). The surface latent heat flux is the exchange of heat between the surface and the air on account of evaporation (including sublimation). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. - - kg m-2 s-1 + + mol m-3 - "Downward" indicates a vector component which is positive when directed downward (negative upward). The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. The chemical formula for carbon dioxide is CO2. + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. - - mol m-2 s-1 + + mol m-3 - "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. The chemical formula for carbon dioxide is CO2. The standard name surface_upward_mole_flux_of_carbon_dioxide should be used to label data in which the flux is positive when directed upward. The standard name "surface_carbon_dioxide_mole_flux" is deprecated because it does not specify in which direction the flux is positive. Any data having the standard name "surface_carbon_dioxide_mole_flux" should be examined carefully to determine which sign convention was used. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Picophytoplankton are phytoplankton of less than 2 micrometers in size. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. - - mol m-2 s-1 + + mol m-3 - "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. - - - - Pa - E181 - tauv - The surface called "surface" means the lower boundary of the atmosphere. "Northward" indicates a vector component which is positive when directed northward (negative southward). "Downward" indicates a vector component which is positive when directed downward (negative upward). "Downward northward" indicates the ZY component of a tensor. A downward northward stress is a downward flux of northward momentum, which accelerates the lower medium northward and the upper medium southward. The surface downward stress is the windstress on the surface. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. - - W m-2 + + mol m-3 - The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). The surface sensible heat flux, also called "turbulent" heat flux, is the exchange of heat between the surface and the air by motion of air. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. - - kg m-2 s-1 + + mol m-3 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. "Downward" indicates a vector component which is positive when directed downward (negative upward). The surface water flux is the result of precipitation and evaporation. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical symbol for radon is Rn. - - Pa + + mol m-3 - The surface called "surface" means the lower boundary of the atmosphere. "x" indicates a vector component along the grid x-axis, positive with increasing x. "Downward" indicates a vector component which is positive when directed downward (negative upward). + Mole concentration means moles (amount of substance) per unit volume and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. - - Pa + + mol m-3 - "x" indicates a vector component along the grid x-axis, positive with increasing x. "Downward" indicates a vector component which is positive when directed downward (negative upward). The surface called "surface" means the lower boundary of the atmosphere. A downward x stress is a downward flux of momentum towards the positive direction of the model's x-axis. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for sulfur dioxide is SO2. - - Pa + + mol m-3 - The surface called "surface" means the lower boundary of the atmosphere. "y" indicates a vector component along the grid y-axis, positive with increasing y. "Downward" indicates a vector component which is positive when directed downward (negative upward). + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The chemical formula of sulfur hexafluoride is SF6. - - Pa + + mol m-3 - "y" indicates a vector component along the grid y-axis, positive with increasing y. "Downward" indicates a vector component which is positive when directed downward (negative upward). The surface called "surface" means the lower boundary of the atmosphere. A downward y stress is a downward flux of momentum towards the positive direction of the model's y-axis. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one ofthe hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. - - W m-2 + + mol m-3 - rlds - The surface called "surface" means the lower boundary of the atmosphere. "longwave" means longwave radiation. Downwelling radiation is radiation from above. It does not mean "net downward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. - - W m-2 + + mol m-3 - rldscs - The surface called "surface" means the lower boundary of the atmosphere. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "longwave" means longwave radiation. Downwelling radiation is radiation from above. It does not mean "net downward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. - - mol m-2 s-1 + + mol m-3 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Downwelling radiation is radiation from above. It does not mean "net downward". A photon flux is specified in terms of numbers of photons expressed in moles. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'.The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Standard names also exist for the mole concentration of a number of components that make up the total zooplankton population, such as mesozooplankton, microzooplankton andmiscellaneous zooplankton. - - mol m-2 s-1 sr-1 + + mol m-3 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Downwelling radiation is radiation from above. It does not mean "net downward". Photon radiance is the photon flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. A photon flux is specified in terms of numbers of photons expressed in moles. + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated in terms of B alone, neglecting all other chemical constituents of A. Standard names also exist for the mole concentration of a number of components that make up the total zooplankton population, such as mesozooplankton, and microzooplankton. - - mol m-2 s-1 + + mol m-2 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Downwelling radiation is radiation from above. It does not mean "net downward". Photon spherical irradiance is the photon flux incident on unit area of a hemispherical (or "2-pi") collector. A photon flux is specified in terms of numbers of photons expressed in moles. + "Content" indicates a quantity per unit area. The "content_of_X_in_atmosphere_layer" refers to the vertical integral between two specified levels in the atmosphere. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. For the mole content integrated from the surface to the top of the atmosphere, standard names including "atmosphere_mole_content_of_X" are used. The chemical formula for carbon monoxide is CO. - - mol m-2 s-1 + + mol m-2 - The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 300-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. A photon flux is specified in terms of numbers of photons expressed in moles. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + "Content" indicates a quantity per unit area. The "content_of_X_in_atmosphere_layer" refers to the vertical integral between two specified levels in the atmosphere. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. For the mole content integrated from the surface to the top of the atmosphere, standard names including "atmosphere_mole_content_of_X" are used. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. - - mol m-2 s-1 + + mol m-2 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Downwelling radiation is radiation from above. It does not mean "net downward". "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 300-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. A photon flux is specified in terms of numbers of photons expressed in moles. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + "Content" indicates a quantity per unit area. The "content_of_X_in_atmosphere_layer" refers to the vertical integral between two specified levels in the atmosphere. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. For the mole content integrated from the surface to the top of the atmosphere, standard names including "atmosphere_mole_content_of_X" are used. The chemical formula for nitrogen dioxide is NO2. - - mol m-2 s-1 sr-1 + + mol m-2 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Downwelling radiation is radiation from above. It does not mean "net downward". Photon radiance is the photon flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 300-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. A photon flux is specified in terms of numbers of photons expressed in moles. + "Content" indicates a quantity per unit area. The "content_of_X_in_atmosphere_layer" refers to the vertical integral between two specified levels in the atmosphere. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. For the mole content integrated from the surface to the top of the atmosphere, standard names including "atmosphere_mole_content_of_X" are used. The chemical formula for ozone is O3. "mole_content_of_ozone_in_atmosphere_layer" is usually measured in Dobson Units which are equivalent to 446.2 micromoles m-2. N.B. Data variables containing column content of ozone can be given the standard name of either equivalent_thickness_at_stp_of_atmosphere_ozone_content or atmosphere_mole_content_of_ozone. The latter name is recommended for consistency with mole content names for chemical species other than ozone. - - mol m-2 s-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Downwelling radiation is radiation from above. It does not mean "net downward". "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 300-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. Photon spherical irradiance is the photon flux incident on unit area of a hemispherical (or "2-pi") collector. A photon flux is specified in terms of numbers of photons expressed in moles. + Mole fraction is used in the construction "mole_fraction_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The chemical formula for acetaldehyde is CH3CHO. The IUPAC name for acetaldehyde is ethanal. - - W m-2 sr-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Downwelling radiation is radiation from above. It does not mean "net downward". Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 300-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for acetic_acid is CH3COOH. The IUPAC name for acetic acid is ethanoic acid. - - W m-2 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". Radiative flux is the sum of shortwave and longwave radiative fluxes. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 300-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction "mole_fraction_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". Acetone is an organic molecule with the chemical formula CH3CH3CO. The IUPAC name for acetone is propan-2-one. Acetone is a member of the group of organic compounds known as ketones. There are standard names for the ketone group as well as for some of the individual species. - - W m-2 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Downwelling radiation is radiation from above. It does not mean "net downward". Radiative flux is the sum of shortwave and longwave radiative fluxes. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 300-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for aceto-nitrile is CH3CN. The IUPAC name for aceto-nitrile is ethanenitrile. - - W m-2 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Downwelling radiation is radiation from above. It does not mean "net downward". "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 300-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. Spherical irradiance is the radiation incident on unit area of a hemispherical (or "2-pi") collector. It is sometimes called "scalar irradiance". The direction (up/downwelling) is specified. Radiation incident on a 4-pi collector has standard names of "omnidirectional spherical irradiance". + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Aldehydes are organic compounds with a CHO group; "aldehydes" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for formaldehyde as the simplest member of the aldehydes group. - - W m-2 sr-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Downwelling radiation is radiation from above. It does not mean "net downward". Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Alkanes are saturated hydrocarbons, i.e. they do not contain any chemical double bonds. Alkanes contain only hydrogen and carbon combined in the general proportions C(n)H(2n+2); "alkanes" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual alkane species, e.g., methane and ethane. - - W m-2 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Downwelling radiation is radiation from above. It does not mean "net downward". Radiative flux is the sum of shortwave and longwave radiative fluxes. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction "mole_fraction_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". Alkenes are unsaturated hydrocarbons as they contain chemical double bonds between adjacent carbon atoms. "Hydrocarbon" means a compound containing hydrogen and carbon. Alkenes contain only hydrogen and carbon combined in the general proportions C(n)H(2n); "alkenes" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual alkene species, e.g., ethene and propene. - - W m-2 - 117 E169 - rsds - The surface called "surface" means the lower boundary of the atmosphere. "shortwave" means shortwave radiation. Downwelling radiation is radiation from above. It does not mean "net downward". Surface downwelling shortwave is the sum of direct and diffuse solar radiation incident on the surface, and is sometimes called "global radiation". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + 1 + + + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - W m-2 + + 1 - rsdscs - The surface called "surface" means the lower boundary of the atmosphere. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "shortwave" means shortwave radiation. Downwelling radiation is radiation from above. It does not mean "net downward". Surface downwelling shortwave is the sum of direct and diffuse solar radiation incident on the surface, and is sometimes called "global radiation". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for alpha_pinene is C10H16. The IUPAC name for alpha-pinene is (1S,5S)-2,6,6-trimethylbicyclo[3.1.1]hept-2-ene. - - mol m-2 s-1 m-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Downwelling radiation is radiation from above. It does not mean "net downward". A photon flux is specified in terms of numbers of photons expressed in moles. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for ammonia is NH3. - - mol m-2 s-1 m-1 sr-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Downwelling radiation is radiation from above. It does not mean "net downward". Photon radiance is the photon flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. A photon flux is specified in terms of numbers of photons expressed in moles. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Anthropogenic" means influenced, caused, or created by human activity. - - mol m-2 s-1 m-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Downwelling radiation is radiation from above. It does not mean "net downward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. Photon spherical irradiance is the photon flux incident on unit area of a hemispherical (or "2-pi") collector. A photon flux is specified in terms of numbers of photons expressed in moles. + Mole fraction is used in the construction "mole_fraction_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Artificial tracer" means a passive atmospheric tracer that is used to study atmospheric transport and deposition. To specify the length of the tracer lifetime in the atmosphere, a scalar coordinate variable with the standard name of tracer_lifetime should be used. - - W m-2 m-1 sr-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Downwelling radiation is radiation from above. It does not mean "net downward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical symbol of atomic bromine is Br. - - W m-2 m-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical symbol of atomic chlorine is Cl. - - W m-2 m-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Downwelling radiation is radiation from above. It does not mean "net downward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical symbol of atomic nitrogen is N. - - W m-2 m-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Downwelling radiation is radiation from above. It does not mean "net downward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. Spherical irradiance is the radiation incident on unit area of a hemispherical (or "2-pi") collector. It is sometimes called "scalar irradiance". The direction (up/downwelling) is specified. Radiation incident on a 4-pi collector has standard names of "omnidirectional spherical irradiance". + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - W m-2 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Downwelling radiation is radiation from above. It does not mean "net downward". Spherical irradiance is the radiation incident on unit area of a hemispherical (or "2-pi") collector. It is sometimes called "scalar irradiance". The direction (up/downwelling) is specified. Radiation incident on a 4-pi collector has standard names of "omnidirectional spherical irradiance". + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for beta_pinene is C10H16. The IUPAC name for beta-pinene is (1S,5S)-6,6-dimethyl-2-methylenebicyclo[3.1.1]heptane. - + 1 - The surface called "surface" means the lower boundary of the atmosphere. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Biogenic" means influenced, caused, or created by natural processes. - + 1 - The surface called "surface" means the lower boundary of the atmosphere. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of bromine chloride is BrCl. - + 1 - The surface called "surface" means the lower boundary of the atmosphere. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of bromine monoxide is BrO. - - m s-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of bromine nitrate is BrONO2. - - kg m-2 + + 1 - "Amount" means mass per unit area. The surface called "surface" means the lower boundary of the atmosphere. The chemical formula for carbon dioxide is CO2. Frozen carbon dioxide is found on the surface of Mars. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Brox" describes a family of chemical species consisting of inorganic bromine compounds withthe exception of hydrogen bromide (HBr) and bromine nitrate (BrONO2). "Brox" isthe term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of source gases containing bromine (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. Standard names that use the term "inorganic_bromine" are used for quantities that contain all inorganic bromine species includingHCl and ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - m2 s-2 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. - - m s-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Geostrophic" indicates that geostrophic balance is assumed. "Water" means water in all phases. surface_geostrophic_eastward_sea_water_velocity is the sum of a variable part, surface_geostrophic_eastward_sea_water_velocity_assuming_sea_level_for_geoid, and a constant part due to the stationary component of ocean circulation. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - m s-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Geostrophic" indicates that geostrophic balance is assumed. "Water" means water in all phases. "sea_level" means mean sea level. The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. surface_geostrophic_eastward_sea_water_velocity_assuming_sea_level_for_geoid is the variable part of surface_geostrophic_eastward_sea_water_velocity. The assumption that sea level is equal to the geoid means that the stationary component of ocean circulation is equal to zero. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - m s-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). "Geostrophic" indicates that geostrophic balance is assumed. "Water" means water in all phases. surface_geostrophic_northward_sea_water_velocity is the sum of a variable part, surface_geostrophic_northward_sea_water_velocity_assuming_sea_level_for_geoid, and a constant part due to the stationary component of ocean circulation. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of carbon tetrachloride is CCl4. - - m s-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). "Geostrophic" indicates that geostrophic balance is assumed. "Water" means water in all phases. "sea_level" means mean sea level. The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. surface_geostrophic_northward_sea_water_velocity_assuming_sea_level_for_geoid is the variable part of surface_geostrophic_northward_sea_water_velocity. The assumption that sea level is equal to the geoid means that the stationary component of ocean circulation is equal to zero. + Mole fraction is used in the construction "mole_fraction_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The chemical formula for carbon tetrafluoride is CF4. The IUPAC name for carbon tetrafluoride is tetrafluoromethane. - - m s-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. A velocity is a vector quantity. "x" indicates a vector component along the grid x-axis, positive with increasing x. "Geostrophic" indicates that geostrophic balance is assumed. surface_geostrophic_sea_water_x_velocity is the sum of a variable part, surface_geostrophic_sea_water_x_velocity_assuming_sea_level_for_geoid, and a constant part due to the stationary component of ocean circulation. + Mole fraction is used in the construction "mole_fraction_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The chemical formula of carbonyl fluoride is COF2. The IUPAC name for carbonyl fluoride is carbonyl difluoride. - - m s-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. A velocity is a vector quantity. "x" indicates a vector component along the grid x-axis, positive with increasing x. "Geostrophic" indicates that geostrophic balance is assumed. "sea_level" means mean sea level. The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. surface_geostrophic_sea_water_x_velocity_assuming_sea_level_for_geoid is the variable part of surface_geostrophic_sea_water_x_velocity. The assumption that sea level is equal to the geoid means that the stationary component of ocean circulation is equal to zero. + Mole fraction is used in the construction "mole_fraction_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The chemical formula for carbonyl sulfide is COS. The IUPAC name for carbonyl sulfide is carbon oxide sulfide. - - m s-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. A velocity is a vector quantity. "y" indicates a vector component along the grid y-axis, positive with increasing y. "Geostrophic" indicates that geostrophic balance is assumed. surface_geostrophic_sea_water_y_velocity is the sum of a variable part, surface_geostrophic_sea_water_y_velocity_assuming_sea_level_for_geoid, and a constant part due to the stationary component of ocean circulation. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of CFC113a CCl3CF3. The IUPAC name for CFC113a is 1,1,1-trichloro-2,2,2-trifluoro-ethane. - - m s-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. A velocity is a vector quantity. "y" indicates a vector component along the grid y-axis, positive with increasing y. "Geostrophic" indicates that geostrophic balance is assumed. "sea_level" means mean sea level. The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. surface_geostrophic_sea_water_y_velocity_assuming_sea_level_for_geoid is the variable part of surface_geostrophic_sea_water_y_velocity. The assumption that sea level is equal to the geoid means that the stationary component of ocean circulation is equal to zero. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of CFC113 is CCl2FCClF2. The IUPAC name for CFC113 is 1,1,2-trichloro-1,2,2-trifluoro-ethane. - - kg m-2 + + 1 - "Content" indicates a quantity per unit area. "Litter carbon" is dead plant material in or above the soil quantified as the mass of carbon which it contains. The surface called "surface" means the lower boundary of the atmosphere. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of CFC114 is CClF2CClF2. The IUPAC name for CFC114 is 1,2-dichloro-1,1,2,2-tetrafluoro-ethane. - + 1 - Emissivity is the ratio of the power emitted by an object to the power that would be emitted by a perfect black body having the same temperature as the object. The emissivity is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength or radiation_frequency is included to specify either the wavelength or frequency. The surface called "surface" means the lower boundary of the atmosphere. "longwave" means longwave radiation. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of CFC115 is CClF2CF3. The IUPAC name for CFC115 is 1-chloro-1,1,2,2,2-pentafluoro-ethane. - + 1 - Emissivity is the ratio of the power emitted by an object to the power that would be emitted by a perfect black body having the same temperature as the object. The emissivity is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength or radiation_frequency is included to specify either the wavelength or frequency. The surface called "surface" means the lower boundary of the atmosphere. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of CFC11 is CFCl3. The IUPAC name for CFC11 is trichloro-fluoro-methane. - - Pa + + 1 - The partial pressure of a dissolved gas in sea water is the partial pressure in air with which it would be in equilibrium. The partial pressure of a gaseous constituent of air is the pressure which it alone would exert with unchanged temperature and number of moles per unit volume. The surface called "surface" means the lower boundary of the atmosphere. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of CFC12 is CF2Cl2. The IUPAC name for CFC12 is dichloro-difluoro-methane. - - W m-2 + + 1 - rls - The surface called "surface" means the lower boundary of the atmosphere. "longwave" means longwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of chlorine dioxide is OClO. - - W m-2 - E211 + + 1 + - The surface called "surface" means the lower boundary of the atmosphere. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "longwave" means longwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of chlorine monoxide is ClO. - - kg m-2 s-1 + + 1 - "Downward" indicates a vector component which is positive when directed downward (negative upward). The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "All land processes" means plant and soil respiration, photosynthesis, animal grazing, crop harvesting, natural fires and anthropogenic land use change. "Anthropogenic land use change" means human changes to land, excluding forest regrowth. It includes fires ignited by humans for the purpose of land use change and the processes of eventual disposal and decomposition of wood products such as paper, cardboard, furniture and timber for construction. The quantity with standard name surface_net_downward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_all_land_processes is equal to the difference between the quantities with standard names surface_net_downward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_all_land_processes_excluding_anthropogenic_land_use_change and surface_net_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_emission_from_anthropogenic_land_use_change. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The chemical formula for carbon dioxide is CO2. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of chlorine nitrate is ClONO2. - - kg m-2 s-1 + + 1 - "Downward" indicates a vector component which is positive when directed downward (negative upward). The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "All land processes" means plant and soil respiration, photosynthesis, animal grazing, crop harvesting, natural fires and anthropogenic land use change. "Anthropogenic land use change" means human changes to land, excluding forest regrowth. It includes fires ignited by humans for the purpose of land use change and the processes of eventual disposal and decomposition of wood products such as paper, cardboard, furniture and timber for construction. The quantity with standard name surface_net_downward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_all_land_processes is equal to the difference between the quantities with standard names surface_net_downward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_all_land_processes_excluding_anthropogenic_land_use_change and surface_net_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_emission_from_anthropogenic_land_use_change. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The chemical formula for carbon dioxide is CO2. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Clox" describes a family of chemical species consisting of inorganic chlorine compounds withthe exception of hydrogen chloride (HCl) and chlorine nitrate (ClONO2). "Clox" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Inorganic chlorine", sometimes referred to as Cly, describes a family of chemical species which result from the degradation of source gasescontaining chlorine (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as seasalt and other aerosols. Standard names that use the term "inorganic_chlorine" are used for quantities that contain all inorganic chlorine species including HCl and ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - W m-2 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. Previously, the qualifier where_type was used to specify that the quantity applies only to the part of the grid box of the named type. Names containing the where_type qualifier are deprecated and newly created data should use the cell_methods attribute to indicate the horizontal area to which the quantity applies. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Dichlorine is the molecular form of elemental chlorine with the chemical formula Cl2. - - W m-2 + + 1 - rss - The surface called "surface" means the lower boundary of the atmosphere. "shortwave" means shortwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of dichlorine peroxide is Cl2O2. - - W m-2 - E210 + + 1 + - The surface called "surface" means the lower boundary of the atmosphere. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "shortwave" means shortwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - W m-2 - 112 E176 + + 1 + - The surface called "surface" means the lower boundary of the atmosphere. "longwave" means longwave radiation. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of dinitrogen pentoxide is N2O5. - - kg m-2 s-1 + + 1 - "Upward" indicates a vector component which is positive when directed upward (negative downward). The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Anthropogenic land use change" means human changes to land, excluding forest regrowth. It includes fires ignited by humans for the purpose of land use change and the processes of eventual disposal and decomposition of wood products such as paper, cardboard, furniture and timber for construction. The quantity with standard name surface_net_downward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_all_land_processes is equal to the difference between the quantities with standard names surface_net_downward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_all_land_processes_excluding_anthropogenic_land_use_change and surface_net_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_emission_from_anthropogenic_land_use_change. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon dioxide is CO2. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - W m-2 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for ethanol is C2H5OH. - - W m-2 - 111 E177 + + 1 + - The surface called "surface" means the lower boundary of the atmosphere. "shortwave" means shortwave radiation. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - m s-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - Pa + + 1 - The surface called "surface" means the lower boundary of the atmosphere. The partial pressure of a gaseous constituent of air is the pressure which it alone would exert with unchanged temperature and number of moles per unit volume. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - Pa + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. The partial pressure of a dissolved gas in sea water is the partial pressure in air with which it would be in equilibrium. The partial pressure of a gaseous constituent of air is the pressure which it alone would exert with unchanged temperature and number of moles per unit volume. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for formic acid is HCOOH. The IUPAC name for formic acid is methanoic acid. - - sr^-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "ratio_of_X_to_Y" means X/Y. Upwelling radiation is radiation from below. It does not mean "net upward". Downwelling radiation is radiation from above. It does not mean "net downward". Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of angle_of_emergence. Radiative flux is the sum of shortwave and longwave radiative fluxes. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In relation to satellite ocean color products the quantity named surface_ratio_of_upwelling_radiance_emerging_from_sea_water_to_downwelling_radiative_flux_in_air is sometimes called "remote sensing reflectance" and has a bidirectional dependence. The direction of the downwelling flux can be specified using a coordinate with the standard name angle_of_incidence. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. "Divalent mercury" means all compounds in which the mercury has two binding sites to other ion(s) in a salt or to other atom(s) in a molecule. - - m - 83 E173 + + 1 + - The surface called "surface" means the lower boundary of the atmosphere. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - m + + 1 - The surface called "surface" means the lower boundary of the atmosphere. + Mole fraction is used in the construction "mole_fraction_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The chemical formula for glyoxal is CHOCHO. The IUPAC name for glyoxal is ethanedial. - - m + + 1 - The surface called "surface" means the lower boundary of the atmosphere. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of halon1202 is CBr2F2. The IUPAC name for halon 1202 is dibromo-difluoro-methane. - - kg m-2 - 90 + + 1 + - The surface called "surface" means the lower boundary of the atmosphere. "Amount" means mass per unit area. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of halon1211 is CBrClF2. The IUPAC name for halon 1211 is bromo-chloro-difluoro-methane. - - kg m-2 s-1 + + 1 - mrros - The surface called "surface" means the lower boundary of the atmosphere. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of halon1301 is CBrF3. The IUPAC name for halon 1301 is bromo-trifluoro-methane. - - kg m-2 - 65 - snw - The surface called "surface" means the lower boundary of the atmosphere. "Amount" means mass per unit area. Surface amount refers to the amount on the ground, excluding that on the plant or vegetation canopy. + + 1 + + + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of halon2402 is C2Br2F4. The IUPAC name for halon 2402 is 1,2-dibromo-1,1,2,2-tetrafluoro-ethane. - - kg m-2 s-1 + + 1 - In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. "Surface snow and ice melt flux" means the mass flux of all melting at the surface. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for hcc140a is CH3CCl3. The IUPAC name for hcc140a is 1,1,1-trichloro-ethane. - - W m-2 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. The snow and ice melt heat flux is the supply of latent heat which is melting snow and ice at freezing point. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for HCFC141b is CH3CCl2F. The IUPAC name for HCFC141b is 1,1-dichloro-1-fluoroethane. - - kg m-2 s-1 + + 1 - In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. "Surface snow and ice refreezing flux" means the mass flux of surface meltwater which refreezes within the snow or firn. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for HCFC142b is CH3CClF2. The IUPAC name for HCFC142b is 1-chloro-1,1-difluoroethane. - - kg m-2 s-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. Sublimation is the conversion of solid into vapor. The snow and ice sublimation flux is the loss of snow and ice mass resulting from their conversion to water vapor. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for HCFC22 is CHClF2. The IUPAC name for HCFC22 is chloro-difluoro-methane. - + 1 - snc - The surface called "surface" means the lower boundary of the atmosphere. "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. + + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - + 1 - X"_binary_mask" has 1 where condition X is met, 0 elsewhere. The value is 1 where the snow cover area fraction is greater than a threshold, and 0 elsewhere. The threshold must be specified by associating a coordinate variable or scalar coordinate variable with the data variable and giving the coordinate variable a standard name of surface_snow_area_fraction. The values of the coordinate variable are the threshold values for the corresponding subarrays of the data variable. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "HOx" means a combination of two radical species containing hydrogen and oxygen: OH and HO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - kg m-2 - 99 + + 1 + - The surface called "surface" means the lower boundary of the atmosphere. "Amount" means mass per unit area. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of hydrogen bromide is HBr. - - W m-2 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. Sublimation is the conversion of solid into vapor. The snow melt and sublimation heat flux is the supply of latent heat which converting snow to liquid water (melting) and water vapor (sublimation). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of hydrogen chloride is HCl. - - kg m-2 s-1 + + 1 - snm - The surface called "surface" means the lower boundary of the atmosphere. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of hydrogen cyanide is HCN. - - W m-2 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. The snow melt heat flux is the supply of latent heat which is melting snow at freezing point. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of hydrogen peroxide is H202. - - kg m-2 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Amount" means mass per unit area. Sublimation is the conversion of solid into vapor. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of hydrogen sulfide is H2S. - - W m-2 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. Sublimation is the conversion of solid into vapor. The snow sublimation heat flux is the supply of latent heat which is causing evaporation of snow to water vapor. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of hydroperoxyl radical is HO2. - - m - 66 - snd - The surface called "surface" means the lower boundary of the atmosphere. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. Previously, the qualifier where_type was used to specify that the quantity applies only to the part of the grid box of the named type. Names containing the where_type qualifier are deprecated and newly created data should use the cell_methods attribute to indicate the horizontal area to which the quantity applies. + + 1 + + + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - + 1 - The surface called "surface" means the lower boundary of the atmosphere. "specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of hypobromous acid is HOBr. - - K - E139 - ts - The surface called "surface" means the lower boundary of the atmosphere. The surface temperature is the temperature at the interface, not the bulk temperature of the medium above or below. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. Previously, the qualifier where_type was used to specify that the quantity applies only to the part of the grid box of the named type. Names containing the where_type qualifier are deprecated and newly created data should use the cell_methods attribute to indicate the horizontal area to which the quantity applies. + + 1 + + + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of hypochlorous acid is HOCl. - - K + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "anomaly" means difference from climatology. The surface temperature is the (skin) temperature at the interface, not the bulk temperature of the medium above or below. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of bromine containing source gases (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. "Inorganic bromine" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names that use the term "brox" are used for quantities that contain all inorganic bromine species except HBr and BrONO2. - - kg m-2 s-1 + + 1 - "Upward" indicates a vector component which is positive when directed upward (negative downward). Plant respiration is the sum of respiration by parts of plants both above and below the soil. Plants which photosynthesise are autotrophs i.e."producers" of the biomass which they respire from inorganic precursors using sunlight for energy. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. "Inorganic chlorine",sometimes referred to as Cly, describes a family of chemical species which result from the degradation of chlorine-containing source gases (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as sea-salt and other aerosols. mole_fraction_of_inorganic_chlorine is the sum of all species belonging to the family that are represented within a given model. - - kg m-2 s-1 + + 1 - "Upward" indicates a vector component which is positive when directed upward (negative downward). Plant respiration is the sum of respiration by parts of plants both above and below the soil. Plants which photosynthesise are autotrophs i.e."producers" of the biomass which they respire from inorganic precursors using sunlight for energy. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - W m-2 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). The vertical heat flux in air is the sum of all heat fluxes i.e. radiative, latent and sensible. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for limonene is C10H16. The IUPAC name for limonene is 1-methyl-4-prop-1-en-2-yl-cyclohexene. Limonene is a member of the group of hydrocarbons known as terpenes. There arestandard names for the terpene group as well as for some of the individual species. - - W m-2 - 121 E147 - hfls - The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). The surface latent heat flux is the exchange of heat between the surface and the air on account of evaporation (including sublimation). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + 1 + + + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - kg m-2 s-1 + + 1 - "Upward" indicates a vector component which is positive when directed upward (negative downward). The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon dioxide is CO2. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for methanol is CH3OH. - - kg m-2 s-1 + + 1 - "Upward" indicates a vector component which is positive when directed upward (negative downward). The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Fires excluding anthropogenic land use change" means all natural fires and human ignited fires that are not associated with change of land use. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon dioxide is CO2. "Anthropogenic" means influenced, caused, or created by human activity. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Methylglyoxal is an organic molecule with the chemical formula CH3COCHO. It is also called pyruvaldehyde or 2-oxopropanal. - - kg m-2 s-1 + + 1 - "Upward" indicates a vector component which is positive when directed upward (negative downward). The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon dioxide is CO2. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of methyl bromide is CH3Br. - - kg m-2 s-1 + + 1 - "Upward" indicates a vector component which is positive when directed upward (negative downward). The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon dioxide is CO2. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of methyl chloride is CH3Cl. - - mol m-2 s-1 + + 1 - "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. The chemical formula for carbon dioxide is CO2. The standard name surface_downward_mole_flux_of_carbon_dioxide should be used to label data in which the flux is positive when directed downward. The standard name "surface_carbon_dioxide_mole_flux" is deprecated because it does not specify in which direction the flux is positive. Any data having the standard name "surface_carbon_dioxide_mole_flux" should be examined carefully to determine which sign convention was used. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of methyl hydroperoxide is CH3OOH. - - mol m-2 s-1 + + 1 - "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. Thechemical formula for dimethyl sulfide is (CH3)2S. Dimethyl sulfide is sometimes referredto as DMS. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for methyl_peroxy_radical is CH3O2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. - - W m-2 - 122 E146 - hfss - The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). The surface sensible heat flux, also called "turbulent" heat flux, is the exchange of heat between the surface and the air by motion of air. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. Previously, the qualifier where_type was used to specify that the quantity applies only to the part of the grid box of the named type. Names containing the where_type qualifier are deprecated and newly created data should use the cell_methods attribute to indicate the horizontal area to which the quantity applies. + + 1 + + + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of molecular hydrogen is H2. - - kg m-2 s-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. "Upward" indicates a vector component which is positive when directed upward (negative downward). The surface water flux is the result of precipitation and evaporation. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. - - kg m-2 s-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - W m-2 + + 1 - rlus - The surface called "surface" means the lower boundary of the atmosphere. "longwave" means longwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. The chemical formula for nitric acid is HNO3. Nitric acid trihydrate, sometimes referred to as NAT, is a stable crystalline substance consisting of three molecules of water to one molecule of nitric acid. - - W m-2 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "longwave" means longwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - mol m-2 s-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. Upwelling radiation is radiation from below. It does not mean "net upward". "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 300-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. A photon flux is specified in terms of numbers of photons expressed in moles. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - W m-2 sr-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. Upwelling radiation is radiation from below. It does not mean "net upward". Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalformula for nitrous acid is HNO2. - - W m-2 sr-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Upwelling radiation is radiation from below. It does not mean "net upward". Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of nitrous oxide is N2O. - - W m-2 sr-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Upwelling radiation is radiation from below. It does not mean "net upward". Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. - - W m-2 sr-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Upwelling radiation is radiation from below. It does not mean "net upward". Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - W m-2 + + 1 - rsus - The surface called "surface" means the lower boundary of the atmosphere. "shortwave" means shortwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. "Noy" describes a family of chemical species. The family usually includes atomic nitrogen (N), nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), peroxynitric acid (HNO4), bromine nitrate (BrONO2) , chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)). The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase 'expressed_as' is used in the construction A_expressed_as_B, whereB is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - W m-2 + + 1 - rsuscs - The surface called "surface" means the lower boundary of the atmosphere. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "shortwave" means shortwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + Mole fraction is used in the construction "mole_fraction_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". Organic nitrates are nitrogen-containing compounds having the general formula RONO2, where R is an alkyl (or organic) group; "organic_nitrates" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. - - W m-2 m-1 sr-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. Upwelling radiation is radiation from below. It does not mean "net upward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + Mole fraction is used in the construction "mole_fraction_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The term "ox" means a combination of three radical species containing 1 or 3 oxygen atoms: O + O1d + O3. - - W m-2 m-1 sr-1 + + 1 - - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Upwelling radiation is radiation from below. It does not mean "net upward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + tro3 + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - W m-2 m-1 sr-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Upwelling radiation is radiation from below. It does not mean "net upward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - W m-2 m-1 sr-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Upwelling radiation is radiation from below. It does not mean "net upward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of peroxynitric acid is HNO4. - - W m-2 m-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. Upwelling radiation is radiation from below. It does not mean "net upward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - W m-2 m-1 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Upwelling radiation is radiation from below. It does not mean "net upward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - kg m-2 + + 1 - The surface called "surface" means the lower boundary of the atmosphere. "Amount" means mass per unit area. "Water" means water in all phases, including frozen i.e. ice and snow. Surface amount refers to the amount on the ground, excluding that on the plant or vegetation canopy. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, whereX is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemicalsymbol for radon is Rn. - - W m-2 + + 1 - Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) The quantity with standard name temperature_flux_due_to_evaporation_expressed_as_heat_flux_out_of_sea_water is the heat energy carried by the transfer of water away from the liquid ocean through the process of evaporation. It is distinct from the transfer of latent heat and is calculated relative to the heat that would be transported by water evaporating at zero degrees Celsius. It is calculated as the product QevapCpTevap, where Qevap is the mass flux of evaporating water (kg m-2 s-1), Cp is the specific heat capacity of water and Tevap is the temperature in degrees Celsius of the evaporating water. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - W m-2 + + 1 - The quantity with standard name temperature_flux_due_to_rainfall_expressed_as_heat_flux_into_sea_water is the heat energy carried by rainfall entering the sea at the sea surface. It is calculated relative to the heat that would be carried by rainfall entering the sea at zero degrees Celsius. It is calculated as the product QrainCpTrain, where Qrain is the mass flux of rainfall entering the sea (kg m-2 s-1), Cp is the specific heat capacity of water and Train is the temperature in degrees Celsius of the rain water entering the sea surface. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mole fraction is used in the construction "mole_fraction_of_X_in_Y", where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The chemical formula of sulfur hexafluoride is SF6. - - W m-2 + + 1 - Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. The quantity with standard name temperature_flux_due_to_runoff_expressed_as_heat_flux_into_sea_water is the heat carried by the transfer of water into the liquid ocean by the process of runoff. This quantity additonally includes melt water from sea ice and icebergs. It is calculated relative to the heat that would be transported by runoff water entering the sea at zero degrees Celsius. It is calculated as the product QrunoffCpTrunoff, where Q runoff is the mass flux of liquid runoff entering the sea water (kg m-2 s-1), Cp is the specific heat capacity of water, and Trunoff is the temperature in degrees Celsius of the runoff water. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - K - E238 + + 1 + - "Temperature in surface snow" is the bulk temperature of the snow, not the surface (skin) temperature. The surface called "surface" means the lower boundary of the atmosphere. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. The chemical formula of water vapor is H2O. - - K + + 1 - Temperature_of_sensor_for_oxygen_in_sea_water is the instrument temperature used in calculating the concentration of oxygen in sea water; it is not a measurement of the ambient water temperature. + Mole fraction is used in the construction mole_fraction_of_X_in_Y, where X is a material constituent of Y. - - kg m-3 s-1 + + 1 - "tendency_of_X" means derivative of X with respect to time. + Mole ratio is used in the construction mole_ratio_of_X_to_Y_in_medium, where X and Y are both material constituents of the medium. "Medium" can take anyof the values given in the "Small scale medium" section of the standard name Guidelines document. "ratio_of_X_to_Y" means X/Y. The chemical formula for the nitrate anion is NO3-. The chemical formula of the phosphate anion is PO4 with a charge of minus three. - - Pa s-1 - 3 + + mol kg-1 + - "tendency_of_X" means derivative of X with respect to time. + moles_of_X_per_unit_mass_inY is also called "molality" of X in Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The chemical formula of CFC11 is CFCl3. The IUPAC name fof CFC11 is trichloro-fluoro-methane. - - K s-1 + + mol kg-1 - "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + moles_of_X_per_unit_mass_inY is also called "molality" of X in Y, where X is a material constituent of Y. - - K s-1 + + mol kg-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + moles_of_X_per_unit_mass_inY is also called "molality" of X in Y, where X is a material constituent of Y. - - K s-1 + + mol kg-1 - Air temperature is the bulk temperature of the air, not the surface (skin) temperature. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + moles_of_X_per_unit_mass_inY is also called "molality" of X in Y, where X is a material constituent of Y. - - K s-1 + + mol kg-1 - tnt - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + moles_of_X_per_unit_mass_inY is also called "molality" of X in Y, where X is a material constituent of Y. - - K s-1 + + mol kg-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + moles_of_X_per_unit_mass_inY is also called "molality" of X in Y, where X is a material constituent of Y. - - K s-1 + + mol kg-1 - tntdc - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + moles_of_X_per_unit_mass_inY is also called "molality" of X in Y, where X is a material constituent of Y. - - K s-1 + + W m-2 - tntlw - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "longwave" means longwave radiation. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + "longwave" means longwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - K s-1 + + W m-2 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "tendency_of_X" means derivative of X with respect to time. "longwave" means longwave radiation. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "longwave" means longwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - K s-1 + + W m-2 - - Air temperature is the bulk temperature of the air, not the surface (skin) temperature. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + rtmt + Fluxes at the top_of_atmosphere_model differ from TOA fluxes only if the model TOA fluxes make some allowance for the atmosphere above the top of the model; if not, it is usual to give standard names with toa to the fluxes at the top of the model atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - K s-1 + + W m-2 - tntmc - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. "shortwave" means shortwave radiation. - - + + W m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Wet deposition" means deposition by precipitation. The chemical formula for acetic_acid is CH3COOH. The IUPAC name for acetic acid is ethanoic acid. + "shortwave" means shortwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - K s-1 + + W m-2 - tntsw - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "shortwave" means shortwave radiation. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + rsntpcs + A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "shortwave" means shortwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - K s-1 + + mol m-2 s-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "tendency_of_X" means derivative of X with respect to time. "shortwave" means shortwave radiation. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. "Productivity" means production per unit area. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. "Calcareous phytoplankton" are phytoplankton that produce calcite. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Standard names also exist for aragonite, another polymorph of calcium carbonate. - - K s-1 + + mol m-2 s-1 - Air temperature is the bulk temperature of the air, not the surface (skin) temperature. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. "Productivity" means production per unit area. Diatoms are single-celled phytoplankton with an external skeleton made of silica. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - K s-1 + + mol m-2 s-1 - tntlsp - Air temperature is the bulk temperature of the air, not the surface (skin) temperature. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. "Productivity" means production per unit area. In ocean modelling, diazotrophs are phytoplankton of the phylum cyanobacteria distinct from other phytoplankton groups in their ability to fix nitrogen gas in addition to nitrate and ammonium. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - K s-1 + + mol m-2 s-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. "Productivity" means production per unit area. "Miscellaneous phytoplankton" are all those phytoplankton that are not diatoms, diazotrophs, calcareous phytoplankton, picophytoplankton or other seperately named components of the phytoplankton population. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - W m-2 + + mol m-2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Dry energy is the sum of dry static energy and kinetic energy. Dry static energy is the sum of enthalpy and potential energy (itself the sum of gravitational and centripetal potential energy). Enthalpy can be written either as (1) CpT, where Cp is heat capacity at constant pressure, T is absolute temperature, or (2) U+pV, where U is internal energy, p is pressure and V is volume. + "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. "Productivity" means production per unit area. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - W m-2 + + mol m-2 s-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Enthalpy can be written either as (1) CpT, where Cp is heat capacity at constant pressure, T is absolute temperature, or (2) U+pV, where U is internal energy, p is pressure and V is volume. + "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. "Productivity" means production per unit area. Picophytoplankton are phytoplankton of less than 2 micrometers in size. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - W m-2 + + mol m-2 s-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. + "Production of carbon" refers to the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. "Productivity" means production per unit area. "Nitrate utilization" means net primary production by phytoplankton based on nitrate alone. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. The chemical formula for the nitrate anion is NO3-. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - kg m-2 s-1 + + kg m-3 s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for acetic_acid is CH3COOH. The IUPAC name for acetic acid is ethanoic acid. + Net primary production is the excess of gross primary production (rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. In the oceans, carbon production per unit volume is often found at a number of depths at a given horizontal location. That quantity can then be integrated to calculate production per unit area at the location. Standard names for production per unit area use the term "productivity". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constiuents of A. - + kg m-2 s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Wet deposition" means deposition by precipitation. The chemical formula for acetic_acid is CH3COOH. The IUPAC name for acetic acid is ethanoic acid. + "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. "Productivity" means production per unit area. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - + kg m-2 s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for aceto-nitrile is CH3CN. The IUPAC name for aceto-nitrile is ethanenitrile. + "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. "Productivity" means production per unit area. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - + kg m-2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Alcohols include all organic compounds with an alcoholic (OH) group. In standard names "alcohols" is the term used to describe the group of chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Miscellaneous living matter" means all those parts of plants that are not leaf, stem, root or other separately named components. The term "plants" refers to the kingdom of plants in the modern classification which excludes fungi. Plants are autotrophs i.e. "producers" of biomass using carbon obtained from carbon dioxide. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. "Productivity" means production per unit area. - + kg m-2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Alcohols include all organic compounds with an alcoholic (OH) group. In standard names "alcohols" is the term used to describe the group of chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. "Productivity" means production per unit area. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - + kg m-2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Alcohols include all organic compounds with an alcoholic (OH) group. In standard names "alcohols" is the term used to describe the group of chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. "Productivity" means production per unit area. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The stem of a plant is the axis that bears buds and shoots with leaves and, at its basal end, roots. Its function is to carry water and nutrients. Examples include the stalk of a plant or the main trunk of a tree. - + kg m-2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Alcohols include all organic compounds with an alcoholic (OH) group. In standard names "alcohols" is the term used to describe the group of chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. "Productivity" means production per unit area. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - kg m-2 s-1 + + W m-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Alcohols include all organic compounds with an alcoholic (OH) group. In standard names "alcohols" is the term used to describe the group of chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "longwave" means longwave radiation. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Net absorbed radiation is the difference between absorbed and emitted radiation. - - kg m-2 s-1 + + W m-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Alcohols include all organic compounds with an alcoholic (OH) group. In standard names "alcohols" is the term used to describe the group of chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "shortwave" means shortwave radiation. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Net absorbed radiation is the difference between absorbed and emitted radiation. - - kg m-2 s-1 + + W m-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Alcohols include all organic compounds with an alcoholic (OH) group. In standard names "alcohols" is the term used to describe the group of chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "shortwave" means shortwave radiation. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Net absorbed radiation is the difference between absorbed and emitted radiation. - - kg m-2 s-1 - + + W m-2 + 115 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Alcohols include all organic compounds with an alcoholic (OH) group. In standard names "alcohols" is the term used to describe the group of chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "solvent production and use" sector comprises industrial processes related to the consumption of halocarbons, SF6, solvent and other product use. "Solvent production and use" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 2F and 3 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "longwave" means longwave radiation. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - kg m-2 s-1 + + W m-2 - - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Alcohols include all organic compounds with an alcoholic (OH) group. In standard names "alcohols" is the term used to describe the group of chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + rlntpcs + A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "longwave" means longwave radiation. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - kg m-2 s-1 - + + W m-2 + 116 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + "shortwave" means shortwave radiation. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - kg m-2 s-1 + + W m-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "shortwave" means shortwave radiation. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - kg m-2 s-1 + + 1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Re-emission" refers to emission that is not from a primary source; it refers to emission of a species that has previously been deposited and accumulated in soils or water. "Re-emission" is a process entirely distinct from "emission" which is used in some standard names. + "Calcareous phytoplankton" are phytoplankton that produce calcite. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Phytoplankton are algae that grow where there is sufficient light to support photosynthesis. "Nitrogen growth limitation" means the ratio of the growth rate of a species population in the environment (where there is a finite availability of nitrogen) to the theoretical growth rate if there were no such limit on nitrogen availability. - - kg m-2 s-1 + + 1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Wet deposition" means deposition by precipitation. + Diatoms are phytoplankton with an external skeleton made of silica. Phytoplankton are algae that grow where there is sufficient light to support photosynthesis. "Nitrogen growth limitation" means the ratio of the growth rate of a species population in the environment (where there is a finite availability of nitrogen) to the theoretical growth rate if there were no such limit on nitrogen availability. - - kg m-2 s-1 + + 1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for alpha_pinene is C10H16. The IUPAC name for alpha-pinene is (1S,5S)-2,6,6-trimethylbicyclo[3.1.1]hept-2-ene. + In ocean modelling, diazotrophs are phytoplankton of the phylum cyanobacteria distinct from other phytoplankton groups in their ability to fix nitrogen gas in addition to nitrate and ammonium. Phytoplankton are algae that grow where there is sufficient light to support photosynthesis. "Nitrogen growth limitation" means the ratio of the growth rate of a species population in the environment (where there is a finite availability of nitrogen) to the theoretical growth rate if there were no such limit on nitrogen availability. - - kg m-2 s-1 + + 1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + Phytoplankton are algae that grow where there is sufficient light to support photosynthesis. "Miscellaneous phytoplankton" are all those phytoplankton that are not diatoms, diazotrophs, calcareous phytoplankton, picophytoplankton or other separately named components of the phytoplankton population. "Nitrogen growth limitation" means the ratio of the growth rate of a species population in the environment (where there is a finite availability of nitrogen) to the theoretical growth rate if there were no such limit on nitrogen availability. - - kg m-2 s-1 + + 1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + Picophytoplankton are phytoplankton of less than 2 micrometers in size. Phytoplankton are algae that grow where there is sufficient light to support photosynthesis. "Nitrogen growth limitation" means the ratio of the growth rate of a species population in the environment (where there is a finite availability of nitrogen) to the theoretical growth rate if there were no such limit on nitrogen availability. - - kg m-2 s-1 + + kg m-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ammonia is NH3. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Content" indicates a quantity per unit area. Examples of "forestry and agricultural products" are paper, cardboard, furniture, timber for construction, biofuels and food for both humans and livestock. Models that simulate land use changes have one or more pools of carbon that represent these products in order to conserve carbon and allow its eventual release into the atmosphere, for example, when the products decompose in landfill sites. - + kg m-2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ammonia is NH3. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Examples of "forestry and agricultural products" are paper, cardboard, furniture, timber for construction, biofuels and food for both humans and livestock. Models that simulate land use changes have one or more pools of nitrogen that represent these products in order to conserve nitrogen and allow its eventual release into the atmosphere, for example, when the products decompose in landfill sites. "Anthropogenic" means influenced, caused, or created by human activity. "Anthropogenic land use change" means human changes to land, excluding forest regrowth. It includes fires ignited by humans for the purpose of land use change and the processes of eventual disposal and decomposition of wood products such as paper, cardboard, furniture and timber for construction. - + kg m-2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ammonia is NH3. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Litter" is dead plant material in or above the soil. "Vegetation" means any living plants e.g. trees, shrubs, grass. - + kg m-2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. he chemical formula for ammonia is NH3. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Litter" is dead plant material in or above the soil. - + kg m-2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ammonia is NH3. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Vegetation" means any living plants e.g. trees, shrubs, grass. "Litter" is dead plant material in or above the soil. - - kg m-2 s-1 + + m - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ammonia is NH3. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Sea surface height" is a time-varying quantity. The phrase "non_tidal_elevation" describes the contribution to sea surface height variability made by processes other than astronomic forcing of the ocean and shallow water resonance of tidal components. These processes include storm surge (due to a combination of meteorological forcing of the ocean and interaction between the generated surge and tides), effects of surface ocean waves, and seasonal and climatic variation in ocean density and circulation. The contribution made by each process varies according to the averaging time of the variable as described by the bounds and cell_methods attributes of the data variable. - - kg m-2 s-1 + + 1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ammonia is NH3. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Normalized_difference_vegetation_index", usually abbreviated to NDVI, is an index calculated from reflectances measured in the visible and near infrared channels. It is calculated as NDVI = (NIR - R) / (NIR + R) where NIR is the reflectance in the near-infrared band and R is the reflectance in the red visible band. Reflectance is the ratio of the reflected over the incoming radiation in each spectral band. The calculated value of NDVI depends on the precise definitions of the spectral bands and these definitions may vary between different models and remote sensing instruments. - - kg m-2 s-1 + + W m-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ammonia is NH3. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Northward" indicates a vector component which is positive when directed northward (negative southward). Transport across_unit_distance means expressed per unit distance normal to the direction of transport. Dry static energy is the sum of enthalpy and potential energy (itself the sum of gravitational and centripetal potential energy). Enthalpy can be written either as (1) CpT, where Cp is heat capacity at constant pressure, T is absolute temperature, or (2) U+pV, where U is internal energy, p is pressure and V is volume. - - kg m-2 s-1 + + W - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Wet deposition" means deposition by precipitation. + "Northward" indicates a vector component which is positive when directed northward (negative southward). "Atmosphere heat transport" means total heat transport by the atmosphere by all processes. - - kg m-2 s-1 + + kg s-1 m-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for ammonium is NH4. + "Water" means water in all phases. "Northward" indicates a vector component which is positive when directed northward (negative southward). Transport across_unit_distance means expressed per unit distance normal to the direction of transport. - - kg m-2 s-1 + + kg m-1 s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Wet deposition" means deposition by precipitation. The chemical formula for ammonium is NH4. + "Northward" indicates a vector component which is positive when directed northward (negative southward). Transport across_unit_distance means expressed per unit distance normal to the direction of transport. - - kg m-2 s-1 + + s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. + A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Northward" indicates a vector component which is positive when directed northward (negative southward). Sea ice velocity is defined as a two-dimensional vector, with no vertical component. The phrase "component_derivative_of_X" means derivative of X with respect to distance in the component direction, which may be northward, southward, eastward, westward, x or y. The last two indicate derivatives along the axes of the grid, in the case where they are not true longitude and latitude. The named quantity is a component of the strain rate tensor for sea ice. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - kg m-2 s-1 + + m3 s-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Eliassen Palm flux" is a widely used vector in the meridional plane, and the divergence of this flux appears as a forcing in the Transformed Eulerian mean formulation of the zonal mean zonal wind equation. "Northward" indicates a vector component which is positive when directed northward (negative southward). - - kg m-2 s-1 + + m s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). Flood water is water that covers land which is normally not covered by water. - - kg m-2 s-1 + + W m-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Northward" indicates a vector component which is positive when directed northward (negative southward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - kg m-2 s-1 + + m s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). Land ice velocity is defined as a two-dimensional vector, with no vertical component. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. - + kg m-2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Northward" indicates a vector component which is positive when directed northward (negative southward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - kg m-2 s-1 + + Pa - - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + tauvcorr + "Northward" indicates a vector component which is positive when directed northward (negative southward). Momentum flux is dimensionally equivalent to stress and pressure. It is a tensor quantity. Flux correction is also called "flux adjustment". A positive flux correction is downward i.e. added to the ocean. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - kg m-2 s-1 + + s-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + A quantity with standard name Xward_Yward_derivative_of_geopotential is a second spatial derivative of geopotential, P, in the direction specified by X and Y, i.e., d2P/dXdY. Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. "Northward" indicates a vector component which is positive when directed northward (negative southward). "component_derivative_of_X" means derivative of X with respect to distance in the component direction, which may be "northward", "southward", "eastward", "westward", "x" or "y". The last two indicate derivatives along the axes of the grid, in the case where they are not true longitude and latitude. - - kg m-2 s-1 + + kg s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Northward" indicates a vector component which is positive when directed northward (negative southward). Ocean transport means transport by all processes, both sea water and sea ice. - - kg m-2 s-1 + + kg s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Northward" indicates a vector component which is positive when directed northward (negative southward). Northward transport by diffusion means the part due to horizontal or isopyncal diffusion schemes in an ocean model, but not including the parameterized eddy velocity. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + kg s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for beta_pinene is C10H16. The IUPAC name for beta-pinene is (1S,5S)-6,6-dimethyl-2-methylenebicyclo[3.1.1]heptane. + "Northward" indicates a vector component which is positive when directed northward (negative southward). Northward transport by the ocean gyre is geometrically defined as being the part due to the vertical integral of the product of deviations of velocity and tracer from their zonal means. The velocity does not include the parameterized eddy velocity. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + kg s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term ina sum of terms which together compose the general quantity named by omitting the phrase."tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. + "Northward" indicates a vector component which is positive when directed northward (negative southward). Northward transport by (meridional) overturning is geometrically defined as being the part due to the vertical integral of the product of zonal means of velocity and tracer. The velocity does not include the parameterized eddy velocity. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + kg s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. Black carbon aerosol is composed of elemental carbon. It is strongly light absorbing. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + "Northward" indicates a vector component which is positive when directed northward (negative southward). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized eddy advection can be represented on various spatial scales and there are standard names for parameterized_mesoscale_eddy_advection and parameterized_submesoscale_eddy_advection which both contribute to the total parameterized eddy advection. - - kg m-2 s-1 + + W - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. Black carbon aerosol is composed of elemental carbon. It is strongly light absorbing. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Northward" indicates a vector component which is positive when directed northward (negative southward). Ocean transport means transport by all processes, both sea water and sea ice. - - kg m-2 s-1 + + W - - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. Black carbon aerosol is composed of elemental carbon. It is strongly light absorbing. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + htovdiff + "Northward" indicates a vector component which is positive when directed northward (negative southward). Northward transport by diffusion means the part due to horizontal or isopyncal diffusion schemes in an ocean model, but not including the parameterized eddy velocity. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + W - - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. Black carbon aerosol is composed of elemental carbon. It is strongly light absorbing. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + htovgyre + "Northward" indicates a vector component which is positive when directed northward (negative southward). Northward transport by the ocean gyre is geometrically defined as being the part due to the vertical integral of the product of deviations of velocity and tracer from their zonal means. The velocity does not include the parameterized eddy velocity. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + W - - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. Black carbon aerosol is composed of elemental carbon. It is strongly light absorbing. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + htovovrt + "Northward" indicates a vector component which is positive when directed northward (negative southward). Northward transport by (meridional) overturning is geometrically defined as being the part due to the vertical integral of the product of zonal means of velocity and tracer. The velocity does not include the parameterized eddy velocity. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + W - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. Black carbon aerosol is composed of elemental carbon. It is strongly light absorbing. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Northward" indicates a vector component which is positive when directed northward (negative southward). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized eddy advection can be represented on various spatial scales and there are standard names for parameterized_mesoscale_eddy_advection and parameterized_submesoscale_eddy_advection which both contribute to the total parameterized eddy advection. - - kg m-2 s-1 + + W - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. Black carbon aerosol is composed of elemental carbon. It is strongly light absorbing. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Northward" indicates a vector component which is positive when directed northward (negative southward). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized mesoscale eddy advection occurs on a spatial scale of many tens of kilometres and an evolutionary time of weeks. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. Parameterized mesoscale eddy advection is represented in ocean models using schemes such as the Gent-McWilliams scheme. There are also standard names for parameterized_submesoscale_eddy_advection which, along with parameterized_mesoscale_eddy_advection, contributes to the total parameterized eddy advection. - - kg m-2 s-1 + + W - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. Black carbon aerosol is composed of elemental carbon. It is strongly light absorbing. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Northward" indicates a vector component which is positive when directed northward (negative southward). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized mesoscale eddy diffusive processes include diffusion along neutral directions in the interior of the ocean and horizontal diffusion in the surface boundary layer. The processes occur on a spatial scale of many tens of kilometres and an evolutionary time of weeks. - - kg m-2 s-1 + + W - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. Black carbon aerosol is composed of elemental carbon. It is strongly light absorbing. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Northward" indicates a vector component which is positive when directed northward (negative southward). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized submesoscale eddy advection occurs on a spatial scale of the order of 1 km horizontally. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. There are also standard names for parameterized_mesoscale_eddy_advection which, along with parameterized_submesoscale_eddy_advection, contributes to the total parameterized eddy advection. - - kg m-2 s-1 + + kg s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. Black carbon aerosol is composed of elemental carbon. It is strongly light absorbing. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Northward" indicates a vector component which is positive when directed northward (negative southward). Ocean transport means transport by all processes, both sea water and sea ice. - - kg m-2 s-1 + + kg s-1 - - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. The sum of turbulent deposition and gravitational settling is dry deposition. + sltovdiff + "Northward" indicates a vector component which is positive when directed northward (negative southward). "Salt transport" means the mass of salt being transported. Northward transport by diffusion means the part due to horizontal or isopyncal diffusion schemes in an ocean model, but not including the parameterized eddy velocity. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + kg s-1 - - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. The sum of turbulent deposition and gravitational settling is dry deposition. + sltovgyre + "Northward" indicates a vector component which is positive when directed northward (negative southward). "Salt transport" means the mass of salt being transported. Northward transport by the ocean gyre is geometrically defined as being the part due to the vertical integral of the product of deviations of velocity and tracer from their zonal means. The velocity does not include the parameterized eddy velocity. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + kg s-1 - - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. Black carbon aerosol is composed of elemental carbon. It is strongly light absorbing. "Wet deposition" means deposition by precipitation. + sltovovrt + "Northward" indicates a vector component which is positive when directed northward (negative southward). "Salt transport" means the mass of salt being transported. Northward transport by (meridional) overturning is geometrically defined as being the part due to the vertical integral of the product of zonal means of velocity and tracer. The velocity does not include the parameterized eddy velocity. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + kg s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + "Northward" indicates a vector component which is positive when directed northward (negative southward). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized eddy advection can be represented on various spatial scales and there are standard names for parameterized_mesoscale_eddy_advection and parameterized_submesoscale_eddy_advection which both contribute to the total parameterized eddy advection. - - kg m-2 s-1 + + m - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Northward" indicates a vector component which is positive when directed northward (negative southward). "Displacement" means the change in geospatial position of an object that has moved over time. If possible, the time interval over which the motion took place should be specified using a bounds variable for the time coordinate variable. A displacement can be represented as a vector. Such a vector should however not be interpreted as describing a rectilinear, constant speed motion but merely as an indication that the start point of the vector is found at the tip of the vector after the time interval associated with the displacement variable. A displacement does not prescribe a trajectory. Sea ice displacement can be defined as a two-dimensional vector, with no vertical component. A northward displacement is the distance calculated from the change in a moving object's latitude between the start and end of the time interval associated with the displacement variable. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - kg m-2 s-1 - + + m s-1 + 96 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). Sea ice velocity is defined as a two-dimensional vector, with no vertical component. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - kg m-2 s-1 - + + m s-1 + 50 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). - - kg m-2 s-1 + + m s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. - - kg m-2 s-1 + + m s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Northward" indicates a vector component which is positive when directed northward (negative southward). The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized mesoscale eddies occur on a spatial scale of many tens of kilometres and an evolutionary time of weeks. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. Parameterized mesoscale eddies are represented in ocean models using schemes such as the Gent-McWilliams scheme. - - kg m-2 s-1 + + m s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Northward" indicates a vector component which is positive when directed northward (negative southward). The "Transformed Eulerian Mean" refers to a formulation of the mean equations which incorporates some eddy terms into the definition of the mean, described in Andrews et al (1987): Middle Atmospheric Dynamics. Academic Press. - - kg m-2 s-1 + + s-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + A quantity with standard name Xward_Yward_derivative_of_geopotential is a second spatial derivative of geopotential, P, in the direction specified by X and Y, i.e., d2P/dXdY. Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. "Northward" indicates a vector component which is positive when directed northward (negative southward). "Upward" indicates a vector component which is positive when directed upward (negative downward). "component_derivative_of_X" means derivative of X with respect to distance in the component direction, which may be "northward", "southward", "eastward", "westward", "x" or "y". The last two indicate derivatives along the axes of the grid, in the case where they are not true longitude and latitude. - + kg m-2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Northward" indicates a vector component which is positive when directed northward (negative southward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - kg m-2 s-1 + + kg m-1 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. "Northward" indicates a vector component which is positive when directed northward (negative southward). Transport across_unit_distance means expressed per unit distance normal to the direction of transport. - - kg m-2 s-1 + + s-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + A quantity with standard name Xward_Yward_derivative_of_geopotential is a second spatial derivative of geopotential in the direction specified by X and Y, i.e., d2P/dXdY. Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. "Westward" indicates a vector component which is positive when directed westward (negative eastward). "Northward" indicates a vector component which is positive when directed northward (negative southward). "component_derivative_of_X" means derivative of X with respect to distance in the component direction, which may be "northward", "southward", "eastward", "westward", "x" or "y". The last two indicate derivatives along the axes of the grid, in the case where they are not true longitude and latitude. - - kg m-2 s-1 - - - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon dioxide is CO2. + + m s-1 + 34 E132 + va + "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) - - kg m-2 s-1 - + + s-1 + 46 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon dioxide is CO2. "Anthropogenic" means influenced, caused, or created by human activity. Anthropogenic emission of carbon dioxide includes fossil fuel use, cement production, agricultural burning and sources associated with anthropogenic land use change, except forest regrowth. + "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) Wind shear is the derivative of wind with respect to height. - - kg m-2 s-1 + + kg m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon dioxide is CO2. Fossil fuel combustion includes cement production and flaring of natural gas. + A "nudging increment" refers to an amount added to parts of a model system. The phrase "nudging_increment_in_X" refers to an increment in quantity X over a time period which should be defined in the bounds of the time coordinate. "Content" indicates a quantity per unit area. "Water" means water in all phases. The mass content of water in soil refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including "content_of_soil_layer" are used. - - kg m-2 s-1 + + kg m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula of carbon monoxide is CO. + A "nudging increment" refers to an amount added to parts of a model system. The phrase "nudging_increment_in_X" refers to an increment in quantity X over a time period which should be defined in the bounds of the time coordinate. "Amount" means mass per unit area. "Snow and ice on land" means ice in glaciers, ice caps, ice sheets & shelves, river and lake ice, any other ice on a land surface, such as frozen flood water, and snow lying on such ice or on the land surface. - - kg m-2 s-1 + + m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + "Number concentration" means the number of particles or other specified objects per unit volume. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "stp" means standard temperature (0 degC) and pressure (101325 Pa). The surface called "surface" means the lower boundary of the atmosphere. - - kg m-2 s-1 + + m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon monoxide is CO. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Number concentration" means the number of particles or other specified objects per unit volume. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. - - kg m-2 s-1 + + m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon monoxide is CO. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + The cloud condensation nuclei number concentration is the total number of aerosol particles per unit volume independent of and integrated over particle size that act as condensation nuclei for liquid-phase clouds. A coordinate variable with the standard name of relative_humidity should be specified to indicate that the property refers to a specific supersaturation with respect to liquid water. The ability of a particle to act as a condensation nucleus is determined by its size, chemical composition, and morphology. "stp" means standard temperature (0 degC) and pressure (101325 Pa). - - kg m-2 s-1 + + m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon monoxide is CO. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Number concentration" means the number of particles or other specified objects per unit volume. - - kg m-2 s-1 + + m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon monoxide is CO. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Number concentration" means the number of particles or other specified objects per unit volume. cloud_top refers to the top of the highest cloud. - - kg m-2 s-1 + + m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon monoxide is CO. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Number concentration" means the number of particles or other specified objects per unit volume. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. Coarse mode aerosol particles have a diameter of more than 1 micrometer. - - kg m-2 s-1 + + m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon monoxide is CO. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Number concentration" means the number of particles or other specified objects per unit volume.The phrase "convective_liquid_water_cloud_top" refers to the top of the highest convective liquid water cloud. Convective cloud is that produced by the convection schemes in an atmosphere model. - - kg m-2 s-1 + + m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon monoxide is CO. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Number concentration" means the number of particles or other specified objects per unit volume. - - kg m-2 s-1 + + m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon monoxide is CO. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Number concentration" means the number of particles or other specified objects per unit volume. cloud_top refers to the top of the highest cloud. - - kg m-2 s-1 + + m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon monoxide is CO. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Number concentration" means the number of particles or other specified objects per unit volume. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. Nucleation mode aerosol particles have a diameter of less than 3 nanometers. - - kg m-2 s-1 + + m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon monoxide is CO. The "solvent production and use" sector comprises industrial processes related to the consumption of halocarbons, SF6, solvent and other product use. "Solvent production and use" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 2F and 3 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Number concentration" means the number of particles or other specified objects per unit volume. The chemical formula for ozone is O3. The IUPAC name for ozone is trioxygen. - - kg m-2 s-1 + + m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon monoxide is CO. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Number concentration" means the number of particles or other specified objects per unit volume. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. To specify the relative humidity and temperature at which the particle size applies, provide scalar coordinate variables with the standard names of, respectively, "relative_humidity" and "air_temperature". - - kg m-2 s-1 + + m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon tetrachloride is CCl4. + "Number concentration" means the number of particles or other specified objects per unit volume. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. To specify the relative humidity and temperature at which the particle size applies, provide scalar coordinate variables with the standard names of, respectively, "relative_humidity" and "air_temperature". - - kg m-2 s-1 + + m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of CFC113a CCl3CF3. The IUPAC name for CFC113a is 1,1,1-trichloro-2,2,2-trifluoro-ethane. + "Number concentration" means the number of particles or other specified objects per unit volume. The phrase "stratiform_liquid_water_cloud_top" refers to the top of the highest stratiform liquid water cloud. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). - - kg m-2 s-1 + + 1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of CFC113 is CCl2FCClF2. The IUPAC name for CFC113 is 1,1,2-trichloro-1,2,2-trifluoro-ethane. + Air temperature is the bulk temperature of the air, not the surface (skin) temperature. A variable whose standard name has the form number_of_days_with_X_below|above_threshold is a count of the number of days on which the condition X_below|above_threshold is satisfied. It must have a coordinate variable or scalar coordinate variable with the a standard name of X to supply the threshold(s). It must have a climatological time variable, and a cell_methods entry for within days which describes the processing of quantity X before the threshold is applied. A number_of_days is an extensive quantity in time, and the cell_methods entry for over days should be "sum". - - kg m-2 s-1 + + 1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of CFC114 is CClF2CClF2. The IUPAC name for CFC114 is 1,2-dichloro-1,1,2,2-tetrafluoro-ethane. + Air temperature is the bulk temperature of the air, not the surface (skin) temperature. A variable whose standard name has the form number_of_days_with_X_below|above_threshold is a count of the number of days on which the condition X_below|above_threshold is satisfied. It must have a coordinate variable or scalar coordinate variable with the a standard name of X to supply the threshold(s). It must have a climatological time variable, and a cell_methods entry for within days which describes the processing of quantity X before the threshold is applied. A number_of_days is an extensive quantity in time, and the cell_methods entry for over days should be "sum". - - kg m-2 s-1 + + 1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of CFC115 is CClF2CF3. The IUPAC name for CFC115 is 1-chloro-1,1,2,2,2-pentafluoro-ethane. + The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. "Precipitation" in the earth's atmosphere means precipitation of water in all phases. The abbreviation "lwe" means liquid water equivalent. A variable whose standard name has the form number_of_days_with_X_below|above_threshold is a count of the number of days on which the condition X_below|above_threshold is satisfied. It must have a coordinate variable or scalar coordinate variable with the a standard name of X to supply the threshold(s). It must have a climatological time variable, and a cell_methods entry for within days which describes the processing of quantity X before the threshold is applied. A number_of_days is an extensive quantity in time, and the cell_methods entry for over days should be "sum". - - kg m-2 s-1 + + 1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of CFC11 is CFCl3. The IUPAC name fof CFC11 is trichloro-fluoro-methane. + The surface temperature is the temperature at the interface, not the bulk temperature of the medium above or below. The surface called "surface" means the lower boundary of the atmosphere. A variable whose standard name has the form number_of_days_with_X_below|above_threshold is a count of the number of days on which the condition X_below|above_threshold is satisfied. It must have a coordinate variable or scalar coordinate variable with the a standard name of X to supply the threshold(s). It must have a climatological time variable, and a cell_methods entry for within days which describes the processing of quantity X before the threshold is applied. A number_of_days is an extensive quantity in time, and the cell_methods entry for over days should be "sum". - - kg m-2 s-1 + + 1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for CFC12 is CF2Cl2. The IUPAC name for CFC12 is dichloro-difluoro-methane. + Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) The wind speed is the magnitude of the wind velocity. A variable whose standard name has the form number_of_days_with_X_below|above_threshold is a count of the number of days on which the condition X_below|above_threshold is satisfied. It must have a coordinate variable or scalar coordinate variable with the a standard name of X to supply the threshold(s). It must have a climatological time variable, and a cell_methods entry for within days which describes the processing of quantity X before the threshold is applied. A number_of_days is an extensive quantity in time, and the cell_methods entry for over days should be "sum". - - kg m-2 s-1 + + m-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Chlorinated hydrocarbons are a group of chemicals composed of carbon, chlorine and hydrogen. As pesticides, they are also referred to by several other names, including chlorinated organics, chlorinated insecticides and chlorinated synthetics. In standard names "chlorinated_hydrocarbons" is the term used to describe the group of chlorinated hydrocarbon species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + The number of icebergs per unit area. - - kg m-2 s-1 + + 1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Chlorinated hydrocarbons are a group of chemicals composed of carbon, chlorine and hydrogen. As pesticides, they are also referred to by several other names, including chlorinated organics, chlorinated insecticides and chlorinated synthetics. In standard names "chlorinated_hydrocarbons" is the term used to describe the group of chlorinated hydrocarbon species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + A variable with the standard name of number_of_observations contains the number of discrete observations or measurements from which the values of another data variable have been derived. The linkage between the data variable and the variable with a standard_name of number_of_observations is achieved using the ancillary_variables attribute. - - kg m-2 s-1 + + kg s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Chlorinated hydrocarbons are a group of chemicals composed of carbon, chlorine and hydrogen. As pesticides, they are also referred to by several other names, including chlorinated organics, chlorinated insecticides and chlorinated synthetics. In standard names "chlorinated_hydrocarbons" is the term used to describe the group of chlorinated hydrocarbon species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + The barotropic stream function with the dimensions of volume transport has the standard name ocean_barotropic_streamfunction. - - kg m-2 s-1 + + m3 s-1 - - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Chlorinated hydrocarbons are a group of chemicals composed of carbon, chlorine and hydrogen. As pesticides, they are also referred to by several other names, including chlorinated organics, chlorinated insecticides and chlorinated synthetics. In standard names "chlorinated_hydrocarbons" is the term used to describe the group of chlorinated hydrocarbon species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "solvent production and use" sector comprises industrial processes related to the consumption of halocarbons, SF6, solvent and other product use. "Solvent production and use" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 2F and 3 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + stfbaro + - - kg m-2 s-1 + + W - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Chlorinated hydrocarbons are a group of chemicals composed of carbon, chlorine and hydrogen. As pesticides, they are also referred to by several other names, including chlorinated organics, chlorinated insecticides and chlorinated synthetics. In standard names "chlorinated_hydrocarbons" is the term used to describe the group of chlorinated hydrocarbon species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "x" indicates a vector component along the grid x-axis, positive with increasing x. - - kg m-2 s-1 + + W - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + "x" indicates a vector component along the grid x-axis, positive with increasing x. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + W - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + "x" indicates a vector component along the grid x-axis, positive with increasing x. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized eddy advection can be represented on various spatial scales and there are standard names for parameterized_mesoscale_eddy_advection and parameterized_submesoscale_eddy_advection which both contribute to the total parameterized eddy advection. - - kg m-2 s-1 + + W - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for dimethyl sulfide is (CH3)2S. Dimethyl sulfide is sometimes referred to as DMS. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "y" indicates a vector component along the grid y-axis, positive with increasing y. - - kg m-2 s-1 + + W - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for dimethyl sulfide is (CH3)2S. Dimethyl sulfide is sometimes referred to as DMS. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "y" indicates a vector component along the grid y-axis, positive with increasing y. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + W - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Wet deposition" means deposition by precipitation. + "y" indicates a vector component along the grid y-axis, positive with increasing y. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized eddy advection can be represented on various spatial scales and there are standard names for parameterized_mesoscale_eddy_advection and parameterized_submesoscale_eddy_advection which both contribute to the total parameterized eddy advection. - - kg m-2 s-1 + + m2 s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term ina sum of terms which together compose the general quantity named by omitting the phrase."tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. + - - kg m-2 s-1 + + W m-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + Friction, leading to the dissipation of kinetic energy, arises in ocean models as a result of the viscosity of sea water. Generally, the lateral (xy) viscosity is given a large value to maintain the numerical stability of the model. In contrast, the vertical viscosity is usually much smaller. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + W m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. The sum of turbulent deposition and gravitational settling is dry deposition. + Friction, leading to the dissipation of kinetic energy, arises in ocean models as a result of the viscosity of sea water. Generally, the lateral (xy) viscosity is given a large value to maintain the numerical stability of the model. In contrast, the vertical viscosity is usually much smaller. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + kg m-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. The sum of turbulent deposition and gravitational settling is dry deposition. + "Content" indicates a quantity per unit area. "Dissolvedinorganic carbon" describes a family of chemical species in solution, including carbon dioxide, carbonic acid and the carbonate and bicarbonate anions. "Dissolved inorganic carbon" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. - - kg m-2 s-1 + + kg m-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "Wet deposition" means deposition by precipitation. + "Content" indicates a quantity per unit area. Organic carbon describes a family of chemical species and is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. - - kg m-2 s-1 + + kg m-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Esters in organic chemistry are chemical compounds derived by reacting an oxoacid with a hydroxyl compound such as an alcohol or phenol. Esters are usually derived from an inorganic acid or organic acid in which at least one -OH (hydroxyl) group is replaced by an -O-alkyl (alkoxy) group, and most commonly from carboxylic acids and alcohols. That is, esters are formed by condensing an acid with an alcohol. In standard names "esters" is the term used to describe the group of ester species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Content" indicates a quantity per unit area. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. - - kg m-2 s-1 + + kg s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Esters in organic chemistry are chemical compounds derived by reacting an oxoacid with a hydroxyl compound such as an alcohol or phenol. Esters are usually derived from an inorganic acid or organic acid in which at least one -OH (hydroxyl) group is replaced by an -O-alkyl (alkoxy) group, and most commonly from carboxylic acids and alcohols. That is, esters are formed by condensing an acid with an alcohol. In standard names "esters" is the term used to describe the group of ester species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "solvent production and use" sector comprises industrial processes related to the consumption of halocarbons, SF6, solvent and other product use. "Solvent production and use" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 2F and 3 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "x" indicates a vector component along the grid x-axis, positive with increasing x. - - kg m-2 s-1 + + kg s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Esters in organic chemistry are chemical compounds derived by reacting an oxoacid with a hydroxyl compound such as an alcohol or phenol. Esters are usually derived from an inorganic acid or organic acid in which at least one -OH (hydroxyl) group is replaced by an -O-alkyl (alkoxy) group, and most commonly from carboxylic acids and alcohols. That is, esters are formed by condensing an acid with an alcohol. In standard names "esters" is the term used to describe the group of ester species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "x" indicates a vector component along the grid x-axis, positive with increasing x. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + kg s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + "x" indicates a vector component along the grid x-axis, positive with increasing x. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized eddy advection can be represented on various spatial scales and there are standard names for parameterized_mesoscale_eddy_advection and parameterized_submesoscale_eddy_advection which both contribute to the total parameterized eddy advection. - - kg m-2 s-1 + + kg s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "y" indicates a vector component along the grid y-axis, positive with increasing y. - - kg m-2 s-1 + + kg s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "y" indicates a vector component along the grid y-axis, positive with increasing y. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + kg s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "y" indicates a vector component along the grid y-axis, positive with increasing y. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized eddy advection can be represented on various spatial scales and there are standard names for parameterized_mesoscale_eddy_advection and parameterized_submesoscale_eddy_advection which both contribute to the total parameterized eddy advection. - - kg m-2 s-1 + + kg s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + In contrast to the quantity with standard name ocean_meridional_overturning_streamfunction, this quantity includes all physical processes, resolved or parameterized, that impact mass/volume transport. Thus it includes contributions from the parameterized eddy velocity. - - kg m-2 s-1 + + kg s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized eddy advection can be represented on various spatial scales and there are standard names for parameterized_mesoscale_eddy_advection and parameterized_submesoscale_eddy_advection which both contribute to the total parameterized eddy advection. - - kg m-2 s-1 + + kg s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized mesoscale eddy advection occurs on a spatial scale of many tens of kilometres and an evolutionary time of weeks. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. Parameterized mesoscale eddy advection is represented in ocean models using schemes such as the Gent-McWilliams scheme. There are also standard names for parameterized_submesoscale_eddy_advection which, along with parameterized_mesoscale_eddy_advection, contributes to the total parameterized eddy advection. - - kg m-2 s-1 + + kg s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized submesoscale eddy advection occurs on a spatial scale of the order of 1 km horizontally. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. There are also standard names for parameterized_mesoscale_eddy_advection which, along with parameterized_submesoscale_eddy_advection, contributes to the total parameterized eddy advection. - - kg m-2 s-1 + + m3 s-1 - - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + stfmmcgo + The ocean meridional overturning streamfunction should not include not include the parameterized eddy advection velocity. - - kg m-2 s-1 - + + m + 67 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + The ocean mixed layer is the upper part of the ocean, regarded as being well-mixed. Various criteria are used to define the mixed layer; this can be specified by using a standard name of ocean_mixed_layer_defined_by_X. "Thickness" means the vertical extent of a layer. - - kg m-2 s-1 + + m - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + The ocean mixed layer is the upper part of the ocean, regarded as being well-mixed. The base of the mixed layer defined by the mixing scheme is a diagnostic of ocean models. "Thickness" means the vertical extent of a layer. - - kg m-2 s-1 + + m - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethanol is C2H5OH. + The ocean mixed layer is the upper part of the ocean, regarded as being well-mixed. The base of the mixed layer defined by "temperature", "sigma", "sigma_theta", "sigma_t" or vertical diffusivity is the level at which the quantity indicated differs from its surface value by a certain amount. A coordinate variable or scalar coordinate variable with standard name sea_water_sigma_t_difference can be used to specify the sigma_t criterion that determines the layer thickness. Sigma-t of sea water is the density of water at atmospheric pressure (i.e. the surface) having the same temperature and salinity, minus 1000 kg m-3. "Thickness" means the vertical extent of a layer. - - kg m-2 s-1 + + m - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. + The ocean mixed layer is the upper part of the ocean, regarded as being well-mixed. The base of the mixed layer defined by "temperature", "sigma", "sigma_theta", "sigma_t" or vertical diffusivity is the level at which the quantity indicated differs from its surface value by a certain amount. A coordinate variable or scalar coordinate variable with standard name sea_water_sigma_theta_difference can be used to specify the sigma_theta criterion that determines the layer thickness. Sigma-theta of sea water is the potential density (i.e. the density when moved adiabatically to a reference pressure) of water having the same temperature and salinity, minus 1000 kg m-3. "Thickness" means the vertical extent of a layer. - - kg m-2 s-1 + + m - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + The ocean mixed layer is the upper part of the ocean, regarded as being well-mixed. The base of the mixed layer defined by "temperature", "sigma", "sigma_theta", "sigma_t" or vertical diffusivity is the level at which the quantity indicated differs from its surface value by a certain amount. A coordinate variable or scalar coordinate variable with standard name sea_water_temperature_difference can be used to specify the temperature criterion that determines the layer thickness. Sea water temperature is the in situ temperature of the sea water. "Thickness" means the vertical extent of a layer. - - kg m-2 s-1 + + m - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Thickness" means the vertical extent of a layer. The ocean mixed layer is the upper part of the ocean, regarded as being well-mixed. The base of the mixed layer defined by temperature, sigma, sigma_theta, or vertical diffusivity is the level at which the quantity indicated differs from its surface value by a certain amount. The amount by which the quantity differs can be specified by a scalar coordinate variable. - - kg m-2 s-1 + + m - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Thickness" means the vertical extent of a layer. The ocean mixed layer is the upper part of the ocean, regarded as being well-mixed. Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. The diffusivity threshold should be specified by associating a coordinate variable or scalar coordinate variable with the data variable and giving the coordinate variable a standard name of ocean_vertical_tracer_diffusivity. - - kg m-2 s-1 + + m4 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. "xy diffusivity" means the lateral along_coordinate component of diffusivity due to motion which is not resolved on the grid scale of the model. xy diffusivities are used in some ocean models to counteract the numerical instabilities inherent in certain implementations of rotated neutral diffusion. "biharmonic diffusivity" means diffusivity for use with a biharmonic diffusion operator. - - kg m-2 s-1 + + m2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. "xy diffusivity" means the lateral along_coordinate component of diffusivity due to motion which is not resolved on the grid scale of the model. xy diffusivities are used in some ocean models to counteract the numerical instabilities inherent in certain implementations of rotated neutral diffusion. "laplacian diffusivity" means diffusivity for use with a Laplacian diffusion operator. - - kg m-2 s-1 + + m2 s-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Mongomery potential is defined as M = ap + gz, where a = specific volume, p = pressure, g = gravity, and z=depth. It represents an exact streamfunction on specificvolume anomaly surfaces. - - kg m-2 s-1 + + s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + Relative vorticity is the upward component of the relative vorticity vector i.e. the component which arises from horizontal velocity. - - kg m-2 s-1 + + Pa - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Ocean rigid lid pressure" means the pressure at the surface of an ocean model assuming that it is bounded above by a rigid lid. - - kg m-2 s-1 + + m - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Ocean rigid lid pressure" means the pressure at the surface of an ocean model assuming that it is bounded above by a rigid lid. "Sea surface height" is a time-varying quantity. The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. (The volume enclosed between the geoid and the sea floor equals the mean volume of water in the ocean). In an ocean GCM the geoid is the surface of zero depth, or the rigid lid if the model uses that approximation. To specify which geoid or geopotential datum is being used as a reference level, a grid_mapping variable should be attached to the data variable as described in Chapter 5.6 of the CF Convention. - - kg m-2 s-1 + + 1e-3 kg s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "x" indicates a vector component along the grid x-axis, positive with increasing x. Salt transport refers to the mass of salt being transported. - - kg m-2 s-1 + + 1e-3 kg s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Ethers are a class of organic compounds that contain an ether group - an oxygen atom connected to two alkyl or aryl groups - of general formula R-O-R. In standard names "ethers" is the term used to describe the group of ether species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "y" indicates a vector component along the grid y-axis, positive with increasing y. Salt transport refers to the mass of salt being transported. - - kg m-2 s-1 + + 1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Ethers are a class of organic compounds that contain an ether group - an oxygen atom connected to two alkyl or aryl groups - of general formula R-O-R. In standard names "ethers" is the term used to describe the group of ether species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + See Appendix D of the CF convention for information about dimensionless vertical coordinates. - - kg m-2 s-1 + + 1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Ethers are a class of organic compounds that contain an ether group - an oxygen atom connected to two alkyl or aryl groups - of general formula R-O-R. In standard names "ethers" is the term used to describe the group of ether species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + See Appendix D of the CF convention for information about dimensionless vertical coordinates. - - kg m-2 s-1 + + 1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Ethers are a class of organic compounds that contain an ether group - an oxygen atom connected to two alkyl or aryl groups - of general formula R-O-R. In standard names "ethers" is the term used to describe the group of ether species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + See Appendix D of the CF convention for information about dimensionless vertical coordinates. - - kg m-2 s-1 + + 1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Ethers are a class of organic compounds that contain an ether group - an oxygen atom connected to two alkyl or aryl groups - of general formula R-O-R. In standard names "ethers" is the term used to describe the group of ether species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + See Appendix D of the CF convention for information about dimensionless vertical coordinates. Note that the ocean sigma coordinate is not the same quantity as sea water sigma (excess of density over 1000 kg m-3), for which there are various other standard names. - - kg m-2 s-1 + + 1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Ethers are a class of organic compounds that contain an ether group - an oxygen atom connected to two alkyl or aryl groups - of general formula R-O-R. In standard names "ethers" is the term used to describe the group of ether species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "solvent production and use" sector comprises industrial processes related to the consumption of halocarbons, SF6, solvent and other product use. "Solvent production and use" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 2F and 3 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + See Appendix D of the CF convention for information about dimensionless vertical coordinates. - - kg m-2 s-1 + + m4 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Ethers are a class of organic compounds that contain an ether group - an oxygen atom connected to two alkyl or aryl groups - of general formula R-O-R. In standard names "ethers" is the term used to describe the group of ether species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. "biharmonicdiffusivity" means diffusivity for use with a biharmonic diffusion operator. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized mesoscale eddy advection occurs on a spatial scale of many tens of kilometres and an evolutionary time of weeks. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. Parameterized mesoscale eddy advection is represented in ocean models using schemes such as the Gent-McWilliams scheme. There are also standard names for parameterized_submesoscale_eddy_advection which, along with parameterized_mesoscale_eddy_advection, contributes to the total parameterized eddy advection. - - kg m-2 s-1 + + m2 s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. + Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized mesoscale eddy advection occurs on a spatial scale of many tens of kilometres and an evolutionary time of weeks. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. Parameterized mesoscale eddy advection is represented in ocean models using schemes such as the Gent-McWilliams scheme. There are also standard names for parameterized_submesoscale_eddy_advection which, along with parameterized_mesoscale_eddy_advection, contributes to the total parameterized eddy advection. - - kg m-2 s-1 + + m4 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. "epineutral diffusivity" means a lateral diffusivity along a either a neutral or isopycnal density surface due to motion which is not resolved on the grid scale of an ocean model. The type of density surface is dependent on the model formulation. "biharmonic diffusivity" means diffusivity for use with a biharmonic diffusion operator. - - kg m-2 s-1 + + m2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. "epineutral diffusivity" means a lateral diffusivity along a either a neutral or isopycnal density surface due to motion which is not resolved on the grid scale of an ocean model. The type of density surface is dependent on the model formulation. "laplacian diffusivity" means diffusivity for use with a Laplacian diffusion operator. - - kg m-2 s-1 + + m2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. "laplacian diffusivity" means diffusivity for use with a Laplacian diffusion operator. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized mesoscale eddy advection occurs on a spatial scale of many tens of kilometres and an evolutionary time of weeks. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. Parameterized mesoscale eddy advection is represented in ocean models using schemes such as the Gent-McWilliams scheme. There are also standard names for parameterized_submesoscale_eddy_advection which, along with parameterized_mesoscale_eddy_advection, contributes to the total parameterized eddy advection. - - kg m-2 s-1 + + m4 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. "xy diffusivity" means the lateral along_coordinate component of diffusivity due to motion which is not resolved on the grid scale of the model. xy diffusivities are used in some ocean models to counteract the numerical instabilities inherent in certain implementations of rotated neutral diffusion. "biharmonic diffusivity" means diffusivity for use with a biharmonic diffusion operator. - - kg m-2 s-1 + + m2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. "xy diffusivity" means the lateral along_coordinate component of diffusivity due to motion which is not resolved on the grid scale of the model. xy diffusivities are used in some ocean models to counteract the numerical instabilities inherent in certain implementations of rotated neutral diffusion. "laplacian diffusivity" means diffusivity for use with a Laplacian diffusion operator. - - kg m-2 s-1 + + m2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Vertical diffusivity" means the vertical component of diffusivity due to motion which is not resolved on the grid scale of the model. - - kg m-2 s-1 + + m2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Vertical heat diffusivity" means the vertical component of the diffusivity of heat due to motion which is not resolved on the grid scale of the model. - - kg m-2 s-1 + + m2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Vertical momentum diffusivity" means the vertical component of the diffusivity of momentum due to motion which is not resolved on the grid scale of the model. - - kg m-2 s-1 + + m2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. The construction vertical_X_diffusivity means the vertical component of thediffusivity of X due to motion which is not resolved on the grid scale of the model. "Due to background" means caused by a time invariant imposed field which may be eitherconstant over the globe or spatially varying, depending on the ocean model used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + m2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Vertical momentum diffusivity" means the vertical component of the diffusivity of momentum due to motion which is not resolved on the grid scale of the model. Convective mixing in the ocean is somtimes modelled as an enhanced diffusivity. - - kg m-2 s-1 + + m2 s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. + Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. The construction vertical_X_diffusivity means the vertical component of thediffusivity of X due to motion which is not resolved on the grid scale of the model. "Due to form drag" refers to a vertical diffusivity resulting from a model scheme representing mesoscale eddy-induced form drag. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + m2 s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. + Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. The construction vertical_X_diffusivity means the vertical component of thediffusivity of X due to motion which is not resolved on the grid scale of the model. "Due to tides" means due to all astronomical gravity changes which manifest as tides.No distinction is made between different tidal components. The specification of a physicalprocess by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + m2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Vertical salt diffusivity" means the vertical component of the diffusivity of salt due to motion which is not resolved on the grid scale of the model. - - kg m-2 s-1 + + m2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Vertical tracer diffusivity" means the vertical component of the diffusivity of tracers, i.e. heat and salinity, due to motion which is not resolved on the grid scale of the model. - - kg m-2 s-1 + + m2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. The construction vertical_X_diffusivity means the vertical component of thediffusivity of X due to motion which is not resolved on the grid scale of the model. "Due to background" means caused by a time invariant imposed field which may be eitherconstant over the globe or spatially varying, depending on the ocean model used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + m2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Vertical tracer diffusivity" means the vertical component of the diffusivity of tracers, i.e. heat and salinity, due to motion which is not resolved on the grid scale of the model. Convective mixing in the ocean is sometimes modelled as an enhanced diffusivity. - - kg m-2 s-1 + + m2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Diffusivity is also sometimes known as the coefficient of diffusion. Diffusion occurs as a result of a gradient in the spatial distribution of mass concentration, temperature or momentum. The diffusivity may be very different in the vertical and horizontal directions. The construction vertical_X_diffusivity means the vertical component of thediffusivity of X due to motion which is not resolved on the grid scale of the model. "Due to tides" means due to all astronomical gravity changes which manifest as tides.No distinction is made between different tidal components. The specification of a physicalprocess by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + m2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Vertical tracer diffusivity" means the vertical component of the diffusivity of tracers, i.e. heat and salinity, due to motion which is not resolved on the grid scale of the model. - - kg m-2 s-1 + + m3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + - - kg m-2 s-1 + + 1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "X_volume_fraction" means the fraction of volume occupied by X. - - kg m-2 s-1 + + m3 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Transport "across_line" means that which crosses a particular line on the Earth's surface; formally this means the integral along the line of the normal component of the transport. - - kg m-2 s-1 + + m3 s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for formic acid is HCOOH. The IUPAC name for formic acid is methanoic acid. + "x" indicates a vector component along the grid x-axis, positive with increasing x. - - kg m-2 s-1 + + m3 s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Wet deposition" means deposition by precipitation. The chemical formula for formic acid is HCOOH. The IUPAC name for formic acid is methanoic acid. + "y" indicates a vector component along the grid y-axis, positive with increasing y. - - kg m-2 s-1 + + kg s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Divalent mercury" means all compounds in which the mercury has two binding sites to other ion(s) in a salt or to other atom(s) in a molecule. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + "y" indicates a vector component along the grid y-axis, positive with increasing y. In contrast to the quantity with standard name ocean_meridional_overturning_streamfunction, this quantity includes all physical processes, resolved or parameterized, that impact mass/volume transport. Thus it includes contributions from the parameterized eddy velocity. - - kg m-2 s-1 + + kg s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Divalent mercury" means all compounds in which the mercury has two binding sites to other ion(s) in a salt or to other atom(s) in a molecule. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + "y" indicates a vector component along the grid y-axis, positive with increasing y. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized eddy advection can be represented on various spatial scales and there are standard names for parameterized_mesoscale_eddy_advection and parameterized_submesoscale_eddy_advection which both contribute to the total parameterized eddy advection. - - kg m-2 s-1 + + kg s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Divalent mercury" means all compounds in which the mercury has two binding sites to other ion(s) in a salt or to other atom(s) in a molecule. "Wet deposition" means deposition by precipitation. + "y" indicates a vector component along the grid y-axis, positive with increasing y. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized mesoscale eddy advection occurs on a spatial scale of many tens of kilometres and an evolutionary time of weeks. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. Parameterized mesoscale eddy advection is represented in ocean models using schemes such as the Gent-McWilliams scheme. There are also standard names for parameterized_submesoscale_eddy_advection which, along with parameterized_mesoscale_eddy_advection, contributes to the total parameterized eddy advection. - - kg m-2 s-1 + + kg s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + "y" indicates a vector component along the grid y-axis, positive with increasing y. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized submesoscale eddy advection occurs on a spatial scale of the order of 1 km horizontally. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. There are also standard names for parameterized_mesoscale_eddy_advection which, along with parameterized_submesoscale_eddy_advection, contributes to the total parameterized eddy advection. - - kg m-2 s-1 + + W m-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 400-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. Omnidirectional spherical irradiance is the radiation incident on unit area of a spherical (or "4-pi") collector. It is sometimes called "scalar irradiance". Radiation incident on a 2-pi collector has standard names of "spherical irradiance" which specify up/downwelling. - - kg m-2 s-1 + + W m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Wet deposition" means deposition by precipitation. + Omnidirectional spherical irradiance is the radiation incident on unit area of a spherical (or "4-pi") collector. It is sometimes called "scalar irradiance". Radiation incident on a 2-pi collector has standard names of "spherical irradiance" which specify up/downwelling. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. - - kg m-2 s-1 + + 1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for halon1202 is CBr2F2. The IUPAC name for halon1202 is dibromo-difluoro-methane. + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-optical_thickness) on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. - - kg m-2 s-1 + + Pa - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for halon1211 is CBrClF2. The IUPAC name for halon1211 is bromo-chloro-difluoro-methane. + Various stability and convective potential indices are calculated by "lifting" a parcel of air: moving it dry adiabatically from a starting height (often the surface) to the Lifting Condensation Level, and then wet adiabatically from there to an ending height (often the top of the data/model/atmosphere). The quantities with standard names original_air_pressure_of_lifted_parcel and final_air_pressure_of_lifted_parcel are the ambient air pressure at the start and end of lifting, respectively. Air pressure is the force per unit area which would be exerted when the moving gas molecules of which the air is composed strike a theoretical surface of any orientation. - - kg m-2 s-1 + + m3 s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for halon1301 is CBrF3. The IUPAC name for halon1301 is bromo-trifluoro-methane. + "Water" means water in all phases. "River" refers to water in the fluvial system (stream and floodplain). - - kg m-2 s-1 + + Pa - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for halo2402 is C2Br2F4. The IUPAC name for halon2402 is 1,2-dibromo-1,1,2,2-tetrafluoro-ethane. + The partial pressure of a dissolved gas in sea water is the partial pressure in air with which it would be in equilibrium. The partial pressure of a gaseous constituent of air is the pressure which it alone would exert with unchanged temperature and number of moles per unit volume. The chemical formula for carbon dioxide is CO2. - - kg m-2 s-1 + + Pa - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for hcc140a is CH3CCl3. The IUPAC name for hcc140a is 1,1,1-trichloro-ethane. + The partial pressure of a dissolved gas in sea water is the partial pressure in air with which it would be in equilibrium. The partial pressure of a gaseous constituent of air is the pressure which it alone would exert with unchanged temperature and number of moles per unit volume. The chemical formula for methane is CH4. - - kg m-2 s-1 + + m - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for HCFC141b is CH3CCl2F. The IUPAC name for HCFC141b is 1,1-dichloro-1-fluoroethane. + Permafrost is soil or rock that has remained at a temperature at or below zero degrees Celsius throughout the seasonal cycle for two or more years. "Thickness" means the vertical extent of a layer. - - kg m-2 s-1 + + degree - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for HCFC142b is CH3CClF2. The IUPAC name for HCFC142b is 1-chloro-1,1-difluoroethane. + Global average sea level change is due to change in volume of the water in the ocean, caused by mass and/or density change, or to change in the volume of the ocean basins, caused by tectonics etc. It is sometimes called "eustatic", which is a term that also has other definitions. It differs from the change in the global average sea surface height relative to the centre of the Earth by the global average vertical movement of the ocean floor. Zero sea level change is an arbitrary level. Phase is the initial angle of a wave modelled by a sinusoidal function. A coordinate variable of harmonic_period should be used to specify the period of the sinusoidal wave. Because global average sea level change quantifies the change in volume of the world ocean, it is not calculated necessarily by considering local changes in mean sea level. - - kg m-2 s-1 + + s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for HCFC22 is CHClF2. The IUPAC name for HCFC22 is chloro-difluoro-methane. + "Photolysis" is a chemical reaction in which a chemical compound is broken down by photons. The "reaction rate" is the rate at which the reactants of a chemical reaction form the products. The chemical formula for molecular oxygen is O2. - - kg m-2 s-1 + + s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + "Photolysis" is a chemical reaction in which a chemical compound is broken down by photons. The "reaction rate" is the rate at which the reactants of a chemical reaction form the products. The chemical formula for nitrogen dioxide is NO2. - - kg m-2 s-1 + + s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + "Photolysis" is a chemical reaction in which a chemical compound is broken down by photons. The "reaction rate" is the rate at which the reactants of a chemical reaction form the products. The chemical formula for ozone is O3. The IUPAC name for ozone is trioxygen. The quantity with standard name photolysis_rate_of_ozone is the rate of photolytic loss of ozone, including all possible photolysis channels to form ground state atomic oxygen (O3P ) and excited (singlet D) atomic oxygen (O1D). Photolysis to the excited state only has the standard name photolysis_rate_of_ozone_to_1D_oxygen_atom. - - kg m-2 s-1 + + s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Re-emission" refers to emission that is not from a primary source; it refers to emission of a species that has previously been deposited and accumulated in soils or water. "Re-emission" is a process entirely distinct from "emission" which is used in some standard names. + "Photolysis" is a chemical reaction in which a chemical compound is broken down by photons. The "reaction rate" is the rate at which the reactants of a chemical reaction form the products. The chemical formula for ozone is O3. The IUPAC name for ozone is trioxygen. "1D oxygen atom" means the singlet D state, an excited state, of the oxygen atom. The combined photolysis rate of ozone to both excited and ground state oxygen atoms has the standard name photolysis_rate_of_ozone. - - kg m-2 s-1 + + 1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Wet deposition" means deposition by precipitation. + Albedo is the ratio of outgoing to incoming shortwave irradiance, where 'shortwave irradiance' means that both the incoming and outgoing radiation are integrated across the solar spectrum. - - kg m-2 s-1 + + degree - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for hydrogen cyanide is HCN. + Standard names for "platform" describe the motion and orientation of the vehicle from which observations are made. Platforms include, but are not limited to, satellites, aeroplanes, ships, instruments and buoys. Platform azimuth angle is the horizontal angle between the line of sight from the observation point to the platform and a reference direction at the observation point, which is often due north. The angle is measured clockwise positive, starting from the reference direction. A comment attribute should be added to a data variable with the standard name platform_azimuth_angle to specify the reference direction. A standard name also exists for sensor_azimuth_angle. For some viewing geometries the sensor and the platform cannot be assumed to be close enough to neglect the difference in calculated azimuth angle. - - kg m-2 s-1 + + degree - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for hydrogen cyanide is HCN. + Standard names for "platform" describe the motion and orientation of the vehicle from which observations are made. Platforms include, but are not limited to, satellites, aeroplanes, ships, instruments and buoys. The platform course is the direction in which the platform is travelling (not necessarily the same as the direction in which it is pointing, called platform_orientation). - - kg m-2 s-1 + + m - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for hydrogen peroxide is H2O2. + Standard names for "platform" describe the motion and orientation of the vehicle from which observations are made. Platforms include, but are not limited to, satellites, aeroplanes, ships, instruments and buoys. "Heave" means the vertical displacement of a platform (positive upwards) over a measurement time interval. - - kg m-2 s-1 + + m s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for isoprene is CH2=C(CH3)CH=CH2. The IUPAC name for isoprene is 2-methyl-buta-1,3-diene. Isoprene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. + Standard names for "platform" describe the motion and orientation of the vehicle from which observations are made. Platforms include, but are not limited to, satellites, aeroplanes, ships, instruments and buoys. "Heave" means the vertical displacement of a platform (positive upwards) over a measurement time interval. "Heave rate" means the rate of change of vertical displacement of the platform over a measurement time interval. - - kg m-2 s-1 + + - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for isoprene is CH2=C(CH3)CH=CH2. The IUPAC name for isoprene is 2-methyl-buta-1,3-diene. Isoprene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Standard names for "platform" describe the motion and orientation of the vehicle from which observations are made. Platforms include, but are not limited to, satellites, aeroplanes, ships, instruments and buoys. A variable with the standard name of platform_id contains strings which help to identify the platform from which an observation was made. For example, this may be a WMO station identification number. - - kg m-2 s-1 + + - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for isoprene is CH2=C(CH3)CH=CH2. The IUPAC name for isoprene is 2-methyl-buta-1,3-diene. Isoprene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Standard names for "platform" describe the motion and orientation of the vehicle from which observations are made. Platforms include, but are not limited to, satellites, aeroplanes, ships, instruments and buoys. A variable with the standard name of platform_name contains strings which help to identify the platform from which an observation was made. For example, this may be a geographical place name such as "South Pole" or the name of a meteorological observing station. - - kg m-2 s-1 + + degree - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Standard names for platform describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane, ship or satellite. The platform orientation is the direction in which the "front" or longitudinal axis of the platform is pointing (not necessarily the same as the direction in which it is travelling, called platform_course). - - kg m-2 s-1 + + degree - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Standard names for platform describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane, ship or satellite. - - kg m-2 s-1 + + degree s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Standard names for platform describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane, ship or satellite. - - kg m-2 s-1 + + degree - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + Standard names for platform describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane, ship or satellite. - - kg m-2 s-1 + + degree s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Standard names for platform describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane, ship or satellite. - - kg m-2 s-1 + + m s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Standard names for "platform" describe the motion and orientation of the vehicle from which observations are made. Platforms include, but are not limited to, satellites, aeroplanes, ships, instruments and buoys. The phrase "wrt" means "with respect to". The abbreviation "wrt" means with respect to. Speed is the magnitude of velocity. The platform speed with respect to air is often called the "air speed" of the platform. - - kg m-2 s-1 + + m s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Standard names for "platform" describe the motion and orientation of the vehicle from which observations are made. Platforms include, but are not limited to, satellites, aeroplanes, ships, instruments and buoys. The abbreviation "wrt" means with respect to. Speed is the magnitude of velocity. The platform speed with respect to ground is relative to the solid Earth beneath it, i.e. the sea floor for a ship. It is often called the "ground speed" of the platform. - - kg m-2 s-1 + + m s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + Standard names for "platform" describe the motion and orientation of the vehicle from which observations are made. Platforms include, but are not limited to, satellites, aeroplanes, ships, instruments and buoys. The abbreviation "wrt" means with respect to. Speed is the magnitude of velocity. - - kg m-2 s-1 + + degree - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "solvent production and use" sector comprises industrial processes related to the consumption of halocarbons, SF6, solvent and other product use. "Solvent production and use" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 2F and 3 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Standard names for "platform" describe the motion and orientation of the vehicle from which observations are made. Platforms include, but are not limited to, satellites, aeroplanes, ships, instruments and buoys. Platform view angle is the angle between the line of sight from the platform and the direction straight vertically down. Zero view angle means looking directly beneath the platform. There is no standardized sign convention for platform_view_angle. A standard name also exists for sensor_view_angle. For some viewing geometries the sensor and the platform cannot be assumed to be close enough to neglect the difference in calculated view angle. - - kg m-2 s-1 + + degree - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Standard names for platform describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane, ship or satellite. - - kg m-2 s-1 + + degree s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for limonene is C10H16. The IUPAC name for limonene is 1-methyl-4-prop-1-en-2-yl-cyclohexene. Limonene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. + Standard names for platform describe the motion and orientation of the vehicle from which observations are made e.g. aeroplane, ship or satellite. - - kg m-2 s-1 + + degree - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term ina sum of terms which together compose the general quantity named by omitting the phrase."tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. + Standard names for "platform" describe the motion and orientation of the vehicle from which observations are made. Platforms include, but are not limited to, satellites, aeroplanes, ships, instruments and buoys. Platform zenith angle is the the angle between the line of sight to the platform and the local zenith at the observation target. This angle is measured starting from directly overhead and its range is from zero (directly overhead the observation target) to 180 degrees (directly below the observation target). Local zenith is a line perpendicular to the Earth's surface at a given location. "Observation target" means a location on the Earth defined by the sensor performing the observations. A standard name also exists for sensor_zenith_angle. For some viewing geometries the sensor and the platform cannot be assumed to be close enough to neglect the difference in calculated zenith angle. - - kg m-2 s-1 + + J m-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) - - kg m-2 s-1 + + Pa-1 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "Wet deposition" means deposition by precipitation. + "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Atmosphere potential vorticity is the vertically averaged absolute vorticity of a layer of the atmosphere divided by the pressure difference from the bottom to the top of the layer. - - kg m-2 s-1 + + m-1 s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Ocean potential vorticity is the vertically averaged absolute vorticity of a layer of the ocean divided by the thickness of the layer. - - kg m-2 s-1 - + + kg m-2 + 61 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Amount" means mass per unit area. "Precipitation" in the earth's atmosphere means precipitation of water in all phases. - + kg m-2 s-1 - - - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + 59 + pr + "Precipitation" in the earth's atmosphere means precipitation of water in all phases. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - + kg m-2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Precipitation" in the earth's atmosphere means precipitation of water in all phases. The chemical formula for water is H2O. "O" means the element "oxygen" and "17O" is the stable isotope "oxygen-17". - + kg m-2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Precipitation" in the earth's atmosphere means precipitation of water in all phases. The chemical formula for water is H2O. "O" means the element "oxygen" and "18O" is the stable isotope "oxygen-18". - + kg m-2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Precipitation" in the earth's atmosphere means precipitation of water in all phases. The chemical formula for water is H2O. "H" means the element "hydrogen" and "2H" is the stable isotope "hydrogen-2", usually called "deuterium". The construction "X_containing_single_Y" means the standard name refers to only that part of X composed of molecules containing a single atom of isotope Y. - + kg m-2 s-1 - - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. he chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + prveg + "Precipitation" in the earth's atmosphere means precipitation of water in all phases. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. Previously, the qualifier where_type was used to specify that the quantity applies only to the part of the grid box of the named type. Names containing the where_type qualifier are deprecated and newly created data should use the cell_methods attribute to indicate the horizontal area to which the quantity applies. "Canopy" means the vegetative covering over a surface. The canopy is often considered to be the outer surfaces of the vegetation. Plant height and the distribution, orientation and shape of plant leaves within a canopy influence the atmospheric environment and many plant processes within the canopy. Reference: AMS Glossary http://glossary.ametsoc.org/wiki/Canopy. - - kg m-2 s-1 + + Pa - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + The "effective cloud top defined by infrared radiation" is (approximately) the geometric height above the surface that is one optical depth at infrared wavelengths (in the region of 11 micrometers) below the cloud top that would be detected by visible and lidar techniques. Reference: Minnis, P. et al 2011 CERES Edition-2 Cloud Property Retrievals Using TRMM VIRS and Terra and Aqua MODIS Data x2014; Part I: Algorithms IEEE Transactions on Geoscience and Remote Sensing, 49(11), 4374-4400. doi: http://dx.doi.org/10.1109/TGRS.2011.2144601. - - kg m-2 s-1 + + K Pa s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "product_of_X_and_Y" means X*Y. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. "omegaX" is used for brevity to mean "lagrangian_tendency_of_air_pressure in standard names constructed as a combination of omega with some other quantity. - - kg m-2 s-1 + + K - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "product_of_X_and_Y" means X*Y. "specific" means per unit mass. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. Specific humidity is the mass fraction of water vapor in (moist) air. - - kg m-2 s-1 + + m s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "product_of_X_and_Y" means X*Y. A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and normally given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. - - kg m-2 s-1 + + K m s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methanol is CH3OH. + "product_of_X_and_Y" means X*Y. A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). - - kg m-2 s-1 + + K m s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methyl bromide is CH3Br. The IUPAC name for methyl bromide is bromomethane. + "product_of_X_and_Y" means X*Y. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) - - kg m-2 s-1 + + m2 s-1 - - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methyl chloride is CH3Cl. The IUPAC name for methyl chloride is chloromethane. + mpuzga + "product_of_X_and_Y" means X*Y. Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. Geopotential height is the geopotential divided by the standard acceleration due to gravity. It is numerically similar to the altitude (or geometric height) and not to the quantity with standard name height, which is relative to the surface. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) - - kg m-2 s-1 + + m2 s-2 - - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for molecular hydrogen is H2. + mpuva + "product_of_X_and_Y" means X*Y. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) - - kg m-2 s-1 + + Pa m s-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for molecular hydrogen is H2. + "product_of_X_and_Y" means X*Y. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) "omegaX" is used for brevity to mean "lagrangian_tendency_of_air_pressure in standard names constructed as a combination of omega with some other quantity. - - kg m-2 s-1 + + m s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for molecular hydrogen is H2. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "product_of_X_and_Y" means X*Y. "specific" means per unit mass. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Specific humidity is the mass fraction of water vapor in (moist) air. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) - - kg m-2 s-1 + + m2 s-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for molecular hydrogen is H2. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "product_of_X_and_Y" means X*Y. A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Upward" indicates a vector component which is positive when directed upward (negative downward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) Upward air velocity is the vertical component of the 3D air velocity vector. - - kg m-2 s-1 + + Pa m s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for the nitrate anion is NO3-. + "product_of_X_and_Y" means X*Y. Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. Geopotential height is the geopotential divided by the standard acceleration due to gravity. It is numerically similar to the altitude (or geometric height) and not to the quantity with standard name height, which is relative to the surface. "omegaX" is used for brevity to mean "lagrangian_tendency_of_air_pressure in standard names constructed as a combination of omega with some other quantity. - - kg m-2 s-1 + + m s-1 - quot;Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + "product_of_X_and_Y" means X*Y. A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and normally given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. - - kg m-2 s-1 + + K m s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Wet deposition" means deposition by precipitation. + "product_of_X_and_Y" means X*Y. A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). - - kg m-2 s-1 + + K m s-1 - - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + mpvta + "product_of_X_and_Y" means X*Y. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) - - kg m-2 s-1 + + m2 s-1 - - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen dioxide is NO2. + mpvzga + "product_of_X_and_Y" means X*Y. Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. Geopotential height is the geopotential divided by the standard acceleration due to gravity. It is numerically similar to the altitude (or geometric height) and not to the quantity with standard name height, which is relative to the surface. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) - - kg m-2 s-1 + + Pa m s-2 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen dioxide is NO2. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "product_of_X_and_Y" means X*Y. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) "omegaX" is used for brevity to mean "lagrangian_tendency_of_air_pressure in standard names constructed as a combination of omega with some other quantity. - - kg m-2 s-1 + + m s-1 - - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen dioxide is NO2. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + mpvhusa + "product_of_X_and_Y" means X*Y. "specific" means per unit mass. "Northward" indicates a vector component which is positive when directed northward (negative southward). Specific humidity is the mass fraction of water vapor in (moist) air. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) - - kg m-2 s-1 + + m2 s-2 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. + "product_of_X_and_Y" means X*Y. A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). "Upward" indicates a vector component which is positive when directed upward (negative downward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) Upward air velocity is the vertical component of the 3D air velocity vector. - - kg m-2 s-1 + + K Pa s-1 - - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + mpwapta + "product_of_X_and_Y" means X*Y. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. "omegaX" is used for brevity to mean "lagrangian_tendency_of_air_pressure in standard names constructed as a combination of omega with some other quantity. - - kg m-2 s-1 + + Pa s-1 - - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + mpwhusa + "product_of_X_and_Y" means X*Y. "specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. "omegaX" is used for brevity to mean "lagrangian_tendency_of_air_pressure in standard names constructed as a combination of omega with some other quantity. - - kg m-2 s-1 + + Pa s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "product_of_X_and_Y" means X*Y. "specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. "omegaX" is used for brevity to mean "lagrangian_tendency_of_air_pressure in standard names constructed as a combination of omega with some other quantity. - - kg m-2 s-1 + + K m s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "product_of_X_and_Y" means X*Y. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. A velocity is a vector quantity. "Upward" indicates a vector component which is positive when directed upward (negative downward). Upward air velocity is the vertical component of the 3D air velocity vector. - - kg m-2 s-1 + + m s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "product_of_X_and_Y" means X*Y. "specific" means per unit mass. A velocity is a vector quantity. "Upward" indicates a vector component which is positive when directed upward (negative downward). Specific humidity is the mass fraction of water vapor in (moist) air. Upward air velocity is the vertical component of the 3D air velocity vector. - - kg m-2 s-1 + + m - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "x" indicates a vector component along the grid x-axis, when this is not true longitude, positive with increasing x. Projection coordinates are distances in the x- and y-directions on a plane onto which the surface of the Earth has been projected according to a map projection. The relationship between the projection coordinates and latitude and longitude is described by the grid_mapping. - - kg m-2 s-1 + + m - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "y" indicates a vector component along the grid y-axis, when this is not true latitude, positive with increasing y. Projection coordinates are distances in the x- and y-directions on a plane onto which the surface of the Earth has been projected according to a map projection. The relationship between the projection coordinates and latitude and longitude is described by the grid_mapping. - - kg m-2 s-1 - + + K + 14 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + Potential temperature is the temperature a parcel of air or sea water would have if moved adiabatically to sea level pressure. - - kg m-2 s-1 + + K - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + - - kg m-2 s-1 + + m s-1 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + A velocity is a vector quantity. Radial velocity away from instrument means the component of the velocity along the line of sight of the instrument where positive implies movement away from the instrument (i.e. outward). The "instrument" (examples are radar and lidar) is the device used to make an observation. - - kg m-2 s-1 + + m s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for nitrous acid is HNO2. + A velocity is a vector quantity. "Radial velocity away from instrument" means the component of the velocity of the scatterers along the line of sight of the instrument where positive implies movement away from the instrument (i.e. outward). The "instrument" (examples are radar and lidar) is the device used to make the observation, and the "scatterers" are what causes the transmitted signal to be returned to the instrument (examples are aerosols, hydrometeors and refractive index irregularities), of whatever kind the instrument detects. - - kg m-2 s-1 + + s-1 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrous acid is HNO2. + Frequency is the number of oscillations of a wave per unit time. The radiation frequency can refer to any electromagnetic wave, such as light, heat radiation and radio waves. - - kg m-2 s-1 + + m - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for nitrous oxide is N2O. + The radiation wavelength can refer to any electromagnetic wave, such as light, heat radiation and radio waves. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrous oxide is N2O. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Mo" means the element "molybdenum" and "101Mo" is the isotope "molybdenum-101" with a half-life of 1.01e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tc" means the element "technetium" and "101Tc" is the isotope "technetium-101" with a half-life of 9.86e-03 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Mo" means the element "molybdenum" and "102Mo" is the isotope "molybdenum-102" with a half-life of 7.71e-03 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tc" means the element "technetium" and "102mTc" is the metastable state of the isotope "technetium-102" with a half-life of 2.98e-03 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tc" means the element "technetium" and "102Tc" is the isotope "technetium-102" with a half-life of 6.12e-05 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rh" means the element "rhodium" and "103mRh" is the metastable state of the isotope "rhodium-103" with a half-life of 3.89e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ru" means the element "ruthenium" and "103Ru" is the isotope "ruthenium-103" with a half-life of 3.95e+01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tc" means the element "technetium" and "104Tc" is the isotope "technetium-104" with a half-life of 1.25e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rh" means the element "rhodium" and "105mRh" is the metastable state of the isotope "rhodium-105" with a half-life of 4.41e-04 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds. The "solvent production and use" sector comprises industrial processes related to the consumption of halocarbons, SF6, solvent and other product use. "Solvent production and use" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 2F and 3 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rh" means the element "rhodium" and "105Rh" is the isotope "rhodium-105" with a half-life of 1.48e+00 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ru" means the element "ruthenium" and "105Ru" is the isotope "ruthenium-105" with a half-life of 1.85e-01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Nox" means nitric oxide (NO) and nitrogen dioxide (NO2). "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rh" means the element "rhodium" and "106mRh" is the metastable state of the isotope "rhodium-106" with a half-life of 9.09e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rh" means the element "rhodium" and "106Rh" is the isotope "rhodium-106" with a half-life of 3.46e-04 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ru" means the element "ruthenium" and "106Ru" is the isotope "ruthenium-106" with a half-life of 3.66e+02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pd" means the element "palladium" and "107mPd" is the metastable state of the isotope "palladium-107" with a half-life of 2.47e-04 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pd" means the element "palladium" and "107Pd" is the isotope "palladium-107" with a half-life of 2.37e+09 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rh" means the element "rhodium" and "107Rh" is the isotope "rhodium-107" with a half-life of 1.51e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ag" means the element "silver" and "109mAg" is the metastable state of the isotope "silver-109" with a half-life of 4.58e-04 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pd" means the element "palladium" and "109Pd" is the isotope "palladium-109" with a half-life of 5.61e-01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ag" means the element "silver" and "110mAg" is the metastable state of the isotope "silver-110" with a half-life of 2.70e+02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ag" means the element "silver" and "111Ag" is the isotope "silver-111" with a half-life of 7.50e+00 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ag" means the element "silver" and "111mAg" is the metastable state of the isotope "silver-111" with a half-life of 8.56e-04 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. An organic acid is an organic compound with acidic properties. The most common organic acids are the carboxylic acids, whose acidity is associated with their carboxyl group -COOH. In standard names "organic_acids" is the term used to describe the group of organic acid species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cd" means the element "cadmium" and "111mCd" is the metastable state of the isotope "cadmium-111" with a half-life of 3.39e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. An organic acid is an organic compound with acidic properties. The most common organic acids are the carboxylic acids, whose acidity is associated with their carboxyl group -COOH. In standard names "organic_acids" is the term used to describe the group of organic acid species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pd" means the element "palladium" and "111mPd" is the metastable state of the isotope "palladium-111" with a half-life of 2.29e-01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. An organic acid is an organic compound with acidic properties. The most common organic acids are the carboxylic acids, whose acidity is associated with their carboxyl group -COOH. In standard names "organic_acids" is the term used to describe the group of organic acid species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pd" means the element "palladium" and "111Pd" is the isotope "palladium-111" with a half-life of 1.53e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. An organic acid is an organic compound with acidic properties. The most common organic acids are the carboxylic acids, whose acidity is associated with their carboxyl group -COOH. In standard names "organic_acids" is the term used to describe the group of organic acid species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ag" means the element "silver" and "112Ag" is the isotope "silver-112" with a half-life of 1.30e-01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. An organic acid is an organic compound with acidic properties. The most common organic acids are the carboxylic acids, whose acidity is associated with their carboxyl group -COOH. In standard names "organic_acids" is the term used to describe the group of organic acid species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pd" means the element "palladium" and "112Pd" is the isotope "palladium-112" with a half-life of 8.37e-01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. An organic acid is an organic compound with acidic properties. The most common organic acids are the carboxylic acids, whose acidity is associated with their carboxyl group -COOH. In standard names "organic_acids" is the term used to describe the group of organic acid species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ag" means the element "silver" and "113Ag" is the isotope "silver-113" with a half-life of 2.21e-01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. An organic acid is an organic compound with acidic properties. The most common organic acids are the carboxylic acids, whose acidity is associated with their carboxyl group -COOH. In standard names "organic_acids" is the term used to describe the group of organic acid species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cd" means the element "cadmium" and "113Cd" is the isotope "cadmium-113" with a half-life of 3.29e+18 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. An organic acid is an organic compound with acidic properties. The most common organic acids are the carboxylic acids, whose acidity is associated with their carboxyl group -COOH. In standard names "organic_acids" is the term used to describe the group of organic acid species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ag" means the element "silver" and "113mAg" is the metastable state of the isotope "silver-113" with a half-life of 7.64e-04 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cd" means the element "cadmium" and "113mCd" is the metastable state of the isotope "cadmium-113" with a half-life of 5.31e+03 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "113mIn" is the metastable state of the isotope "indium-113" with a half-life of 6.92e-02 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term ina sum of terms which together compose the general quantity named by omitting the phrase."tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ag" means the element "silver" and "115Ag" is the isotope "silver-115" with a half-life of 1.46e-02 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. The sum of turbulent deposition and gravitational settling is dry deposition. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except black carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cd" means the element "cadmium" and "115Cd" is the isotope "cadmium-115" with a half-life of 2.23e+00 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except black carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Net chemical production" means the net result of all chemical reactions within the atmosphere that produce or destroy a particular species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "115In" is the isotope "indium-115" with a half-life of 1.86e+18 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. The sum of turbulent deposition and gravitational settling is dry deposition. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except black carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ag" means the element "silver" and "115mAg" is the metastable state of the isotope "silver-115" with a half-life of 1.97e-04 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except black carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. "Wet deposition" means deposition by precipitation. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cd" means the element "cadmium" and "115mCd" is the metastable state of the isotope "cadmium-115" with a half-life of 4.46e+01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except black carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "115mIn" is the metastable state of the isotope "indium-115" with a half-life of 1.87e-01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except black carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "116In" is the isotope "indium-116" with a half-life of 1.64e-04 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except black carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "116mIn" is the metastable state of the isotope "indium-116" with a half-life of 3.77e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except black carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cd" means the element "cadmium" and "117Cd" is the isotope "cadmium-117" with a half-life of 1.08e-01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except black carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "117In" is the isotope "indium-117" with a half-life of 3.05e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer are used. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except black carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cd" means the element "cadmium" and "117mCd" is the metastable state of the isotope "cadmium-117" with a half-life of 1.42e-01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except black carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "117mIn" is the metastable state of the isotope "indium-117" with a half-life of 8.08e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "Primary particulate organic matter " means all organic matter emitted directly to the atmosphere as particles except black carbon. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "117mSn" is the metastable state of the isotope "tin-117" with a half-life of 1.40e+01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except black carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cd" means the element "cadmium" and "118Cd" is the isotope "cadmium-118" with a half-life of 3.49e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for pentane is C5H12. Pentane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "118In" is the isotope "indium-118" with a half-life of 5.77e-05 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for pentane is C5H12. Pentane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "118mIn" is the metastable state of the isotope "indium-118" with a half-life of 3.05e-03 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for pentane is C5H12. Pentane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "119In" is the isotope "indium-119" with a half-life of 1.74e-03 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for pentane is C5H12. Pentane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "In" means the element "indium" and "119mIn" is the metastable state of the isotope "indium-119" with a half-life of 1.25e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for pentane is C5H12. Pentane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "119mSn" is the metastable state of the isotope "tin-119" with a half-life of 2.45e+02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for pentane is C5H12. Pentane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "C" means the element "carbon" and "11C" is the isotope "carbon-11" with a half-life of 1.41e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for pentane is C5H12. Pentane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "121mSn" is the metastable state of the isotope "tin-121" with a half-life of 1.82e+04 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for pentane is C5H12. Pentane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "121Sn" is the isotope "tin-121" with a half-life of 1.12e+00 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "123mSn" is the metastable state of the isotope "tin-123" with a half-life of 2.78e-02 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for peroxyacetyl nitrate, sometimes referred to as PAN, is CH3COO2NO2. The IUPAC name for peroxyacetyl_nitrate is nitroethaneperoxoate. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "123Sn" is the isotope "tin-123" with a half-life of 1.29e+02 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for peroxynitric acid, sometimes referred to as PNA, is HO2NO2. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "124mSb" is the metastable state of the isotope "antimony-124" with a half-life of 1.41e-02 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term ina sum of terms which together compose the general quantity named by omitting the phrase."tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "124Sb" is the isotope "antimony-124" with a half-life of 6.03e+01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "Primary particulate organic matter " means all organic matter emitted directly to the atmosphere as particles except black carbon. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "125mTe" is the metastable state of the isotope "tellurium-125" with a half-life of 5.81e+01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "Primary particulate organic matter " means all organic matter emitted directly to the atmosphere as particles except black carbon. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. "Wet deposition" means deposition by precipitation. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "125Sb" is the isotope "antimony-125" with a half-life of 9.97e+02 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "125Sn" is the isotope "tin-125" with a half-life of 9.65e+00 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "126mSb" is the metastable state of the isotope "antimony-126" with a half-life of 1.32e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "126Sb" is the isotope "antimony-126" with a half-life of 1.24e+01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "126Sn" is the isotope "tin-126" with a half-life of 3.65e+07 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "127mTe" is the metastable state of the isotope "tellurium-127" with a half-life of 1.09e+02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "127Sb" is the isotope "antimony-127" with a half-life of 3.80e+00 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "127Sn" is the isotope "tin-127" with a half-life of 8.84e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "127Te" is the isotope "tellurium-127" with a half-life of 3.91e-01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "128mSb" is the metastable state of the isotope "antimony-128" with a half-life of 7.23e-03 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "128Sb" is the isotope "antimony-128" with a half-life of 3.75e-01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "128Sn" is the isotope "tin-128" with a half-life of 4.09e-02 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "129I" is the isotope "iodine-129" with a half-life of 5.81e+09 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "129mTe" is the metastable state of the isotope "tellurium-129" with a half-life of 3.34e+01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Xe" means the element "xenon" and "129mXe" is the metastable state of the isotope "xenon-129" with a half-life of 8.02e+00 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "129Sb" is the isotope "antimony-129" with a half-life of 1.81e-01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "129Te" is the isotope "tellurium-129" with a half-life of 4.86e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "130I" is the isotope "iodine-130" with a half-life of 5.18e-01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "130mI" is the metastable state of the isotope "iodine-130" with a half-life of 6.17e-03 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "130mSb" is the metastable state of the isotope "antimony-130" with a half-life of 4.58e-03 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "130Sb" is the isotope "antimony-130" with a half-life of 2.57e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sn" means the element "tin" and "130Sn" is the isotope "tin-130" with a half-life of 2.57e-03 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "131I" is the isotope "iodine-131" with a half-life of 8.07e+00 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical symbol for radon is Rn. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "131mTe" is the metastable state of the isotope "tellurium-131" with a half-life of 1.25e+00 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term ina sum of terms which together compose the general quantity named by omitting the phrase."tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Xe" means the element "xenon" and "131mXe" is the metastable state of the isotope "xenon-131" with a half-life of 1.18e+01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sb" means the element "antimony" and "131Sb" is the isotope "antimony-131" with a half-life of 1.60e-02 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. The sum of turbulent deposition and gravitational settling is dry deposition. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "131Te" is the isotope "tellurium-131" with a half-life of 1.74e-02 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. The sum of turbulent deposition and gravitational settling is dry deposition. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "132I" is the isotope "iodine-132" with a half-life of 9.60e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "Wet deposition" means deposition by precipitation. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "132Te" is the isotope "tellurium-132" with a half-life of 3.25e+00 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term ina sum of terms which together compose the general quantity named by omitting the phrase."tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "133I" is the isotope "iodine-133" with a half-life of 8.71e-01 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "Secondary particulate organic matter" means particulate organic matter formed within the atmosphere from gaseous precursors. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. "Net chemical production" means the net result of all chemical reactions within the atmosphere that produce or destroy a particular species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "133mI" is the metastable state of the isotope "iodine-133" with a half-life of 1.04e-04 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "Secondary particulate organic matter" means particulate organic matter formed within the atmosphere from gaseous precursors. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. "Wet deposition" means deposition by precipitation. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "133mTe" is the metastable state of the isotope "tellurium-133" with a half-life of 3.84e-02 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for the sulfate anion is SO4(2-). + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Xe" means the element "xenon" and "133mXe" is the metastable state of the isotope "xenon-133" with a half-life of 2.26e+00 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. The chemical formula for the sulfate anion is SO4(2-). "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "133Te" is the isotope "tellurium-133" with a half-life of 8.68e-03 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. The chemical formula for the sulfate anion is SO4(2-). + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Xe" means the element "xenon" and "133Xe" is the isotope "xenon-133" with a half-life of 5.28e+00 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The sum of turbulent deposition and gravitational settling is dry deposition. "tendency_of_X" means derivative of X with respect to time. The chemical formula for the sulfate anion is SO4(2-). + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cs" means the element "cesium" and "134Cs" is the isotope "cesium-134" with a half-life of 7.50e+02 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The sum of turbulent deposition and gravitational settling is dry deposition. "tendency_of_X" means derivative of X with respect to time. The chemical formula for the sulfate anion is SO4(2-). + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "134I" is the isotope "iodine-134" with a half-life of 3.61e-02 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. The chemical formula for the sulfate anion is SO4(2-). + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cs" means the element "cesium" and "134mCs" is the metastable state of the isotope "cesium-134" with a half-life of 1.21e-01 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for sulfur dioxide is SO2. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "134mI" is the metastable state of the isotope "iodine-134" with a half-life of 2.50e-03 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Xe" means the element "xenon" and "134mXe" is the metastable state of the isotope "xenon-134" with a half-life of 3.36e-06 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for sulfur dioxide is SO2. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Te" means the element "tellurium" and "134Te" is the isotope "tellurium-134" with a half-life of 2.92e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for sulfur dioxide is SO2. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cs" means the element "cesium" and "135Cs" is the isotope "cesium-135" with a half-life of 8.39e+08 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for sulfur dioxide is SO2. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "I" means the element "iodine" and "135I" is the isotope "iodine-135" with a half-life of 2.79e-01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for sulfur dioxide is SO2. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ba" means the element "barium" and "135mBa" is the metastable state of the isotope "barium-135" with a half-life of 1.20e+00 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for sulfur dioxide is SO2. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cs" means the element "cesium" and "135mCs" is the metastable state of the isotope "cesium-135" with a half-life of 3.68e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for sulfur dioxide is SO2. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Xe" means the element "xenon" and "135mXe" is the metastable state of the isotope "xenon-135" with a half-life of 1.08e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for sulfur dioxide is SO2. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Xe" means the element "xenon" and "135Xe" is the isotope "xenon-135" with a half-life of 3.82e-01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for sulfur dioxide is SO2. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cs" means the element "cesium" and "136Cs" is the isotope "cesium-136" with a half-life of 1.30e+01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for sulfur dioxide is SO2. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cs" means the element "cesium" and "137Cs" is the isotope "cesium-137" with a half-life of 1.10e+04 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Wet deposition" means deposition by precipitation. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ba" means the element "barium" and "137mBa" is the metastable state of the isotope "barium-137" with a half-life of 1.77e-03 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Terpenes are hydrocarbons, that is, they contain only hydrogen and carbon combined in the general proportions (C5H8)n where n is an integer greater than on equal to one. The term "terpenes" is used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual terpene species, e.g., isoprene and limonene. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Xe" means the element "xenon" and "137Xe" is the isotope "xenon-137" with a half-life of 2.71e-03 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Terpenes are hydrocarbons, that is, they contain only hydrogen and carbon combined in the general proportions (C5H8)n where n is an integer greater than on equal to one. The term "terpenes" is used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual terpene species, e.g., isoprene and limonene. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cs" means the element "cesium" and "138Cs" is the isotope "cesium-138" with a half-life of 2.23e-02 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Xe" means the element "xenon" and "138Xe" is the isotope "xenon-138" with a half-life of 9.84e-03 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ba" means the element "barium" and "139Ba" is the isotope "barium-139" with a half-life of 5.77e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "N" means the element "nitrogen" and "13N" is the isotope "nitrogen-13" with a half-life of 6.92e-03 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ba" means the element "barium" and "140Ba" is the isotope "barium-140" with a half-life of 1.28e+01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "La" means the element "lanthanum" and "140La" is the isotope "lanthanum-140" with a half-life of 1.76e+00 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ce" means the element "cerium" and "141Ce" is the isotope "cerium-141" with a half-life of 3.30e+01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "La" means the element "lanthanum" and "141La" is the isotope "lanthanum-141" with a half-life of 1.61e-01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ce" means the element "cerium" and "142Ce" is the isotope "cerium-142" with a half-life of 1.82e+19 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "La" means the element "lanthanum" and "142La" is the isotope "lanthanum-142" with a half-life of 6.42e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pr" means the element "praseodymium" and "142mPr" is the metastable state of the isotope "praseodymium-142" with a half-life of 1.01e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "solvent production and use" sector comprises industrial processes related to the consumption of halocarbons, SF6, solvent and other product use. "Solvent production and use" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 2F and 3 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pr" means the element "praseodymium" and "142Pr" is the isotope "praseodymium-142" with a half-life of 7.94e-01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ce" means the element "cerium" and "143Ce" is the isotope "cerium-143" with a half-life of 1.37e+00 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for trimethylbenzene is C9H12. The IUPAC names for trimethylbenzene is 1,3,5-trimethylbenzene. Trimethylbenzene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "La" means the element "lanthanum" and "143La" is the isotope "lanthanum-143" with a half-life of 9.72e-03 days. - - kg m-2 s-1 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Water" means water in all phases. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pr" means the element "praseodymium" and "143Pr" is the isotope "praseodymium-143" with a half-life of 1.36e+01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Atmosphere water vapor content is sometimes referred to as "precipitable water", although this term does not imply the water could all be precipitated. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ce" means the element "cerium" and "144Ce" is the isotope "cerium-144" with a half-life of 2.84e+02 days. - - kg m-2 s-1 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Atmosphere water vapor content is sometimes referred to as "precipitable water", although this term does not imply the water could all be precipitated. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pr" means the element "praseodymium" and "144mPr" is the metastable state of the isotope "praseodymium-144" with a half-life of 4.98e-03 days. - - kg m-2 s-1 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Atmosphere water vapor content is sometimes referred to as "precipitable water", although this term does not imply the water could all be precipitated. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nd" means the element "neodymium" and "144Nd" is the isotope "neodymium-144" with a half-life of 7.64e+17 days. - - kg m-2 s-1 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Atmosphere water vapor content is sometimes referred to as "precipitable water", although this term does not imply the water could all be precipitated. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pr" means the element "praseodymium" and "144Pr" is the isotope "praseodymium-144" with a half-life of 1.20e-02 days. - - kg m-2 s-1 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Atmosphere water vapor content is sometimes referred to as "precipitable water", although this term does not imply the water could all be precipitated. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pr" means the element "praseodymium" and "145Pr" is the isotope "praseodymium-145" with a half-life of 2.49e-01 days. - - kg m-2 s-1 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Atmosphere water vapor content is sometimes referred to as "precipitable water", although this term does not imply the water could all be precipitated. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ce" means the element "cerium" and "146Ce" is the isotope "cerium-146" with a half-life of 9.86e-03 days. - - kg m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pr" means the element "praseodymium" and "146Pr" is the isotope "praseodymium-146" with a half-life of 1.68e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nd" means the element "neodymium" and "147Nd" is the isotope "neodymium-147" with a half-life of 1.10e+01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pm" means the element "promethium" and "147Pm" is the isotope "promethium-147" with a half-life of 9.57e+02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pr" means the element "praseodymium" and "147Pr" is the isotope "praseodymium-147" with a half-life of 8.33e-03 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sm" means the element "samarium" and "147Sm" is the isotope "samarium-147" with a half-life of 3.91e+13 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pm" means the element "promethium" and "148mPm" is the metastable state of the isotope "promethium-148" with a half-life of 4.14e+01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pm" means the element "promethium" and "148Pm" is the isotope "promethium-148" with a half-life of 5.38e+00 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sm" means the element "samarium" and "148Sm" is the isotope "samarium-148" with a half-life of 2.92e+18 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nd" means the element "neodymium" and "149Nd" is the isotope "neodymium-149" with a half-life of 7.23e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pm" means the element "promethium" and "149Pm" is the isotope "promethium-149" with a half-life of 2.21e+00 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "solvent production and use" sector comprises industrial processes related to the consumption of halocarbons, SF6, solvent and other product use. "Solvent production and use" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 2F and 3 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sm" means the element "samarium" and "149Sm" is the isotope "samarium-149" with a half-life of 3.65e+18 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pm" means the element "promethium" and "150Pm" is the isotope "promethium-150" with a half-life of 1.12e-01 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "X_area" means the horizontal area occupied by X within the grid cell. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nd" means the element "neodymium" and "151Nd" is the isotope "neodymium-151" with a half-life of 8.61e-03 days. - - kg m-2 s-1 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "X_area" means the horizontal area occupied by X within the grid cell. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pm" means the element "promethium" and "151Pm" is the isotope "promethium-151" with a half-life of 1.18e+00 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for acetic_acid is CH3COOH. The IUPAC name for acetic acid is ethanoic acid. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sm" means the element "samarium" and "151Sm" is the isotope "samarium-151" with a half-life of 3.40e+04 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for aceto-nitrile is CH3CN. The IUPAC name for aceto-nitrile is ethanenitrile. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pm" means the element "promethium" and "152mPm" is the metastable state of the isotope "promethium-152" with a half-life of 1.25e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for alpha_hexachlorocyclohexane is C6H6Cl6. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nd" means the element "neodymium" and "152Nd" is the isotope "neodymium-152" with a half-life of 7.94e-03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for alpha_pinene is C10H16. The IUPAC name for alpha-pinene is (1S,5S)-2,6,6-trimethylbicyclo[3.1.1]hept-2-ene. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pm" means the element "promethium" and "152Pm" is the isotope "promethium-152" with a half-life of 2.84e-03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for ammonia is NH3. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sm" means the element "samarium" and "153Sm" is the isotope "samarium-153" with a half-life of 1.94e+00 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "nmvoc" means non methane volatile organic compounds. "Anthropogenic" means influenced, caused, or created by human activity. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Eu" means the element "europium" and "154Eu" is the isotope "europium-154" with a half-life of 3.13e+03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical symbol for atomic bromine is Br. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Eu" means the element "europium" and "155Eu" is the isotope "europium-155" with a half-life of 1.75e+03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical symbol for atomic chlorine is Cl. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sm" means the element "samarium" and "155Sm" is the isotope "samarium-155" with a half-life of 1.54e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical symbol for atomic nitrogen is N. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Eu" means the element "europium" and "156Eu" is the isotope "europium-156" with a half-life of 1.52e+01 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sm" means the element "samarium" and "156Sm" is the isotope "samarium-156" with a half-life of 3.91e-01 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for beta_pinene is C10H16. The IUPAC name for beta-pinene is (1S,5S)-6,6-dimethyl-2-methylenebicyclo[3.1.1]heptane. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Eu" means the element "europium" and "157Eu" is the isotope "europium-157" with a half-life of 6.32e-01 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "nmvoc" means non methane volatile organic compounds. "Biogenic" means influenced, caused, or created by natural processes. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Eu" means the element "europium" and "158Eu" is the isotope "europium-158" with a half-life of 3.18e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for bromine chloride is BrCl. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Eu" means the element "europium" and "159Eu" is the isotope "europium-159" with a half-life of 1.26e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for bromine monoxide is BrO. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Gd" means the element "gadolinium" and "159Gd" is the isotope "gadolinium-159" with a half-life of 7.71e-01 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for bromine nitrate is BrONO2. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "O" means the element "oxygen" and "15O" is the isotope "oxygen-15" with a half-life of 1.41e-03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "Brox" describes a family of chemical species consisting of inorganic bromine compounds with the exception of hydrogen bromide (HBr) and bromine nitrate (BrONO2). "Brox" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of source gases containing bromine (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. Standard names that use the term "inorganic_bromine" are used for quantities that contain all inorganic bromine species including HCl and ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tb" means the element "terbium" and "160Tb" is the isotope "terbium-160" with a half-life of 7.23e+01 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tb" means the element "terbium" and "161Tb" is the isotope "terbium-161" with a half-life of 6.92e+00 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for carbon dioxide is CO2. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Gd" means the element "gadolinium" and "162Gd" is the isotope "gadolinium-162" with a half-life of 6.92e-03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere,i.e. summed over the atmospheric column and over the entire globe. The chemical formula ofcarbon monoxide is CO. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tb" means the element "terbium" and "162mTb" is the metastable state of the isotope "terbium-162" with a half-life of 9.30e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere,i.e. summed over the atmospheric column and over the entire globe. The chemical formula ofcarbon tetrachloride is CCl4. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tb" means the element "terbium" and "162Tb" is the isotope "terbium-162" with a half-life of 5.18e-03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere,i.e. summed over the atmospheric column and over the entire globe. The chemical formula ofCFC11 is CFCl3. The IUPAC name fof CFC11 is trichloro-fluoro-methane. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tb" means the element "terbium" and "163Tb" is the isotope "terbium-163" with a half-life of 1.36e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. Thechemical formula of CFC113 is CCl2FCClF2. The IUPAC name for CFC113 is 1,1,2-trichloro-1,2,2-trifluoro-ethane. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Dy" means the element "dysprosium" and "165Dy" is the isotope "dysprosium-165" with a half-life of 9.80e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula of CFC113a CCl3CF3. The IUPAC name for CFC113a is 1,1,1-trichloro-2,2,2-trifluoro-ethane. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "F" means the element "fluorine" and "18F" is the isotope "fluorine-18" with a half-life of 6.98e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere,i.e. summed over the atmospheric column and over the entire globe. The chemical formula ofCFC114 is CClF2CClF2. The IUPAC name for CFC114 is 1,2-dichloro-1,1,2,2-tetrafluoro-ethane. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Hg" means the element "mercury" and "206Hg" is the isotope "mercury-206" with a half-life of 5.57e-03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. Thechemical formula of CFC115 is CClF2CF3. The IUPAC name for CFC115 is 1-chloro-1,1,2,2,2-pentafluoro-ethane. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tl" means the element "thallium" and "206Tl" is the isotope "thallium-206" with a half-life of 2.91e-03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. Thechemical formula for CFC12 is CF2Cl2. The IUPAC name for CFC12 is dichloro-difluoro-methane. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pb" means the element "lead" and "207mPb" is the metastable state of the isotope "lead-207" with a half-life of 9.26e-06 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for chlorine dioxide is OClO. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tl" means the element "thallium" and "207Tl" is the isotope "thallium-207" with a half-life of 3.33e-03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for chlorine monoxide is ClO. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tl" means the element "thallium" and "208Tl" is the isotope "thallium-208" with a half-life of 2.15e-03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for chlorine nitrate is ClONO2. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Bi" means the element "bismuth" and "209Bi" is the isotope "bismuth-209" with a half-life of 7.29e+20 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "Clox" describes a family of chemical species consisting of inorganic chlorine compounds with the exception of hydrogen chloride (HCl) and chlorine nitrate (ClONO2). "Clox" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Inorganic chlorine", sometimes referred to as Cly, describes a family of chemical species which result from the degradation of source gases containing chlorine (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as seasalt and other aerosols. Standard names that use the term "inorganic_chlorine" are used for quantities that contain all inorganic chlorine species including HCl and ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pb" means the element "lead" and "209Pb" is the isotope "lead-209" with a half-life of 1.38e-01 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for dichlorine peroxide is Cl2O2. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tl" means the element "thallium" and "209Tl" is the isotope "thallium-209" with a half-life of 1.53e-03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for dimethyl sulfide is (CH3)2S. Dimethyl sulfide is sometimes referred to as DMS. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Bi" means the element "bismuth" and "210Bi" is the isotope "bismuth-210" with a half-life of 5.01e+00 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for dinitrogen pentoxide is N2O5. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pb" means the element "lead" and "210Pb" is the isotope "lead-210" with a half-life of 7.64e+03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Po" means the element "polonium" and "210Po" is the isotope "polonium-210" with a half-life of 1.38e+02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for ethanol is C2H5OH. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tl" means the element "thallium" and "210Tl" is the isotope "thallium-210" with a half-life of 9.02e-04 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Bi" means the element "bismuth" and "211Bi" is the isotope "bismuth-211" with a half-life of 1.49e-03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pb" means the element "lead" and "211Pb" is the isotope "lead-211" with a half-life of 2.51e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Po" means the element "polonium" and "211Po" is the isotope "polonium-211" with a half-life of 6.03e-06 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for formic acid is HCOOH. The IUPAC name for formic acid is methanoic acid. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Bi" means the element "bismuth" and "212Bi" is the isotope "bismuth-212" with a half-life of 4.20e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "Divalent mercury" means all compounds in which the mercury has two binding sites to other ion(s) in a salt or to other atom(s) in a molecule. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pb" means the element "lead" and "212Pb" is the isotope "lead-212" with a half-life of 4.43e-01 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical symbol for mercury is Hg. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Po" means the element "polonium" and "212Po" is the isotope "polonium-212" with a half-life of 3.52e-12 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for halon1202 is CBr2F2. The IUPAC name for halon1202 is dibromo-difluoro-methane. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Bi" means the element "bismuth" and "213Bi" is the isotope "bismuth-213" with a half-life of 3.26e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for halon1211 is CBrClF2. The IUPAC name for halon1211 is bromo-chloro-difluoro-methane. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pb" means the element "lead" and "213Pb" is the isotope "lead-213" with a half-life of 6.92e-03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for halon1301 is CBrF3. The IUPAC name for halon1301 is bromo-trifluoro-methane. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Po" means the element "polonium" and "213Po" is the isotope "polonium-213" with a half-life of 4.86e-11 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for halo2402 is C2Br2F4. The IUPAC name for halon2402 is 1,2-dibromo-1,1,2,2-tetrafluoro-ethane. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Bi" means the element "bismuth" and "214Bi" is the isotope "bismuth-214" with a half-life of 1.37e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for hcc140a is CH3CCl3. The IUPAC name for hcc140a is 1,1,1-trichloro-ethane. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pb" means the element "lead" and "214Pb" is the isotope "lead-214" with a half-life of 1.86e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for HCFC141b is CH3CCl2F. The IUPAC name for HCFC141b is 1,1-dichloro-1-fluoroethane. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Po" means the element "polonium" and "214Po" is the isotope "polonium-214" with a half-life of 1.90e-09 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for HCFC142b is CH3CClF2. The IUPAC name for HCFC142b is 1-chloro-1,1-difluoroethane. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "At" means the element "astatine" and "215At" is the isotope "astatine-215" with a half-life of 1.16e-09 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for HCFC22 is CHClF2. The IUPAC name for HCFC22 is chloro-difluoro-methane. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Bi" means the element "bismuth" and "215Bi" is the isotope "bismuth-215" with a half-life of 4.86e-03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for hexachlorobiphenyl is C12H4Cl6. This structure of this species consists of two linked benzene rings, each of which is additionally bonded to three chlorine atoms. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Po" means the element "polonium" and "215Po" is the isotope "polonium-215" with a half-life of 2.06e-08 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "HOx" means a combination of two radical species containing hydrogen and oxygen: OH and HO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "At" means the element "astatine" and "216At" is the isotope "astatine-216" with a half-life of 3.47e-09 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for hydrogen bromide is HBr. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Po" means the element "polonium" and "216Po" is the isotope "polonium-216" with a half-life of 1.74e-06 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for hydrogen chloride is HCl. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "At" means the element "astatine" and "217At" is the isotope "astatine-217" with a half-life of 3.70e-07 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for hydrogen cyanide is HCN. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Po" means the element "polonium" and "217Po" is the isotope "polonium-217" with a half-life of 1.16e-04 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for hydrogen peroxide is H2O2. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "At" means the element "astatine" and "218At" is the isotope "astatine-218" with a half-life of 2.31e-05 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for the hydroperoxyl radical is HO2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Po" means the element "polonium" and "218Po" is the isotope "polonium-218" with a half-life of 2.12e-03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for the hydroxyl radical is OH. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rn" means the element "radon" and "218Rn" is the isotope "radon-218" with a half-life of 4.05e-07 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for hypobromous acid is HOBr. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "At" means the element "astatine" and "219At" is the isotope "astatine-219" with a half-life of 6.27e-04 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for hypochlorous acid is HOCl. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rn" means the element "radon" and "219Rn" is the isotope "radon-219" with a half-life of 4.64e-05 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of source gases containing bromine (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. "Inorganic bromine" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names that use the term "brox" are used for quantities that contain all inorganic bromine species except HBr and BrONO2. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rn" means the element "radon" and "220Rn" is the isotope "radon-220" with a half-life of 6.37e-04 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "Inorganic chlorine", sometimes referred to as Cly, describes a family of chemical species which result from the degradation of source gases containing chlorine (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as seasalt and other aerosols. "Inorganic chlorine" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names that use the term "clox" are used for quantities that contain all inorganic chlorine species except HCl and ClONO2. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Fr" means the element "francium" and "221Fr" is the isotope "francium-221" with a half-life of 3.33e-03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for isoprene is CH2=C(CH3)CH=CH2. The IUPAC name for isoprene is 2-methyl-buta-1,3-diene. Isoprene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rn" means the element "radon" and "221Rn" is the isotope "radon-221" with a half-life of 1.74e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for limonene is C10H16. The IUPAC name for limonene is 1-methyl-4-prop-1-en-2-yl-cyclohexene. Limonene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Fr" means the element "francium" and "222Fr" is the isotope "francium-222" with a half-life of 1.03e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere,i.e. summed over the atmospheric column and over the entire globe. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. Thereare standard names for the alkane group as well as for some of the individual species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ra" means the element "radium" and "222Ra" is the isotope "radium-222" with a half-life of 4.41e-04 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for methanol is CH3OH. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rn" means the element "radon" and "222Rn" is the isotope "radon-222" with a half-life of 3.82e+00 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere,i.e. summed over the atmospheric column and over the entire globe. The chemical formula for methyl bromide is CH3Br. The IUPAC name for methyl bromide is bromomethane. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Fr" means the element "francium" and "223Fr" is the isotope "francium-223" with a half-life of 1.53e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X contained in the entire atmosphere, i.e, summed over the atmospheric column and over the entire globe. The chemical formula of methyl chloride is CH3Cl. The IUPAC name for methyl chloride is chloromethane. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ra" means the element "radium" and "223Ra" is the isotope "radium-223" with a half-life of 1.14e+01 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for methyl hydroperoxide is CH3OOH. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rn" means the element "radon" and "223Rn" is the isotope "radon-223" with a half-life of 2.98e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for methyl_peroxy_radical is CH3O2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ra" means the element "radium" and "224Ra" is the isotope "radium-224" with a half-life of 3.65e+00 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X contained in the entire atmosphere, i.e, summed over the atmospheric column and over the entire globe. The chemical formula of molecular hydrogen is H2. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ac" means the element "actinium" and "225Ac" is the isotope "actinium-225" with a half-life of 1.00e+01 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for nitrate is NO3. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ra" means the element "radium" and "225Ra" is the isotope "radium-225" with a half-life of 1.48e+01 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for nitric acid is HNO3. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ac" means the element "actinium" and "226Ac" is the isotope "actinium-226" with a half-life of 1.21e+00 days. - - mol s-1 + + Bq m-3 - "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for nitric acid is HNO3. Nitric acid trihydrate, sometimes referred to as NAT, is a stable crystalline substance consisting of three molecules of water to one molecule of nitric acid. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ra" means the element "radium" and "226Ra" is the isotope "radium-226" with a half-life of 5.86e+05 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for nitrogen dioxide is NO2. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Th" means the element "thorium" and "226Th" is the isotope "thorium-226" with a half-life of 2.15e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for nitrogen monoxide is NO. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ac" means the element "actinium" and "227Ac" is the isotope "actinium-227" with a half-life of 7.87e+03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for nitrous acid is HNO2. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ra" means the element "radium" and "227Ra" is the isotope "radium-227" with a half-life of 2.87e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X contained in the entire atmosphere, i.e, summed over the atmospheric column and over the entire globe. The chemical formula of nitrous oxide is N2O. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Th" means the element "thorium" and "227Th" is the isotope "thorium-227" with a half-life of 1.82e+01 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "nmvoc" means non methane volatile organic compounds. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ac" means the element "actinium" and "228Ac" is the isotope "actinium-228" with a half-life of 2.55e-01 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ra" means the element "radium" and "228Ra" is the isotope "radium-228" with a half-life of 2.45e+03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "Noy" describes a family of chemical species. The family usually includes atomic nitrogen (N), nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), peroxynitric acid (HNO4), bromine nitrate (BrONO2) , chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)). The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Th" means the element "thorium" and "228Th" is the isotope "thorium-228" with a half-life of 6.98e+02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for ozone is O3. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ac" means the element "actinium" and "229Ac" is the isotope "actinium-229" with a half-life of 4.58e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for peroxyacetyl nitrate, sometimes referred to as PAN, is CH3COO2NO2. The IUPAC name for peroxyacetyl_nitrate is nitroethaneperoxoate. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ra" means the element "radium" and "229Ra" is the isotope "radium-229" with a half-life of 1.16e-17 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for peroxynitric acid, sometimes referred to as PNA, is HO2NO2. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Th" means the element "thorium" and "229Th" is the isotope "thorium-229" with a half-life of 2.68e+06 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pa" means the element "protactinium" and "230Pa" is the isotope "protactinium-230" with a half-life of 1.77e+01 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Th" means the element "thorium" and "230Th" is the isotope "thorium-230" with a half-life of 2.92e+07 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical symbol for radon is Rn. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "230U" is the isotope "uranium-230" with a half-life of 2.08e+01 days. - - mol s-1 + + Bq m-3 - "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for the sulfate anion is SO4(2-). + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pa" means the element "protactinium" and "231Pa" is the isotope "protactinium-231" with a half-life of 1.19e+07 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for sulfur dioxide is SO2. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Th" means the element "thorium" and "231Th" is the isotope "thorium-231" with a half-life of 1.06e+00 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "231U" is the isotope "uranium-231" with a half-life of 4.29e+00 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pa" means the element "protactinium" and "232Pa" is the isotope "protactinium-232" with a half-life of 1.31e+00 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Th" means the element "thorium" and "232Th" is the isotope "thorium-232" with a half-life of 5.14e+12 days. - - m-2 s-2 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "232U" is the isotope "uranium-232" with a half-life of 2.63e+04 days. - - m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. The sum of turbulent deposition and gravitational settling is dry deposition. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pa" means the element "protactinium" and "233Pa" is the isotope "protactinium-233" with a half-life of 2.70e+01 days. - - m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. The sum of turbulent deposition and gravitational settling is dry deposition. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Th" means the element "thorium" and "233Th" is the isotope "thorium-233" with a half-life of 1.54e-02 days. - - m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Wet deposition" means deposition by precipitation. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "233U" is the isotope "uranium-233" with a half-life of 5.90e+07 days. - - W m-2 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pa" means the element "protactinium" and "234mPa" is the metastable state of the isotope "protactinium-234" with a half-life of 8.13e-04 days. - - m s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. Altitude is the (geometric) height above the geoid, which is the reference geopotential surface. The geoid is similar to mean sea level. "Bedrock" is the solid Earth surface beneath land ice or ocean water. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pa" means the element "protactinium" and "234Pa" is the isotope "protactinium-234" with a half-life of 2.81e-01 days. - - W m-2 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Dry energy is the sum of dry static energy and kinetic energy. Dry static energy is the sum of enthalpy and potential energy (itself the sum of gravitational and centripetal potential energy). Enthalpy can be written either as (1) CpT, where Cp is heat capacity at constant pressure, T is absolute temperature, or (2) U+pV, where U is internal energy, p is pressure and V is volume. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Th" means the element "thorium" and "234Th" is the isotope "thorium-234" with a half-life of 2.41e+01 days. - - W m-2 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Dry static energy is the sum of enthalpy and potential energy (itself the sum of gravitational and centripetal potential energy). Enthalpy can be written either as (1) CpT, where Cp is heat capacity at constant pressure, T is absolute temperature, or (2) U+pV, where U is internal energy, p is pressure and V is volume. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "234U" is the isotope "uranium-234" with a half-life of 9.02e+07 days. - - m s-2 + + Bq m-3 - tnmmutot - "tendency_of_X" means derivative of X with respect to time. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Np" means the element "neptunium" and "235Np" is the isotope "neptunium-235" with a half-life of 4.09e+02 days. - - m s-2 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "235Pu" is the isotope "plutonium-235" with a half-life of 1.81e-02 days. - - m s-2 + + Bq m-3 - tnmmuc - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "235U" is the isotope "uranium-235" with a half-life of 2.60e+11 days. - - m s-2 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Np" means the element "neptunium" and "236mNp" is the metastable state of the isotope "neptunium-236" with a half-life of 4.72e+10 days. - - m s-2 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Eliassen Palm flux" is a widely used vector in the meridional plane, and the divergence of this flux appears as a forcing in the Transformed Eulerian mean formulation of the zonal mean zonal wind equation. Thus, "eastward_wind" here will generally be the zonally averaged eastward wind. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Np" means the element "neptunium" and "236Np" is the isotope "neptunium-236" with a half-life of 9.17e-01 days. - - m s-2 + + Bq m-3 - tnmmugwd - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) The quantity named tendency_of_eastward_wind_due_to_gravity_wave_drag is the sum of the tendencies due to orographic and nonorographic gravity waves which have standard names of tendency_of_eastward_wind_due_to_orographic_gravity_wave_drag and tendency_of_eastward_wind_due_to_nonorographic_gravity_wave_drag, respectively. + + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "236Pu" is the isotope "plutonium-236" with a half-life of 1.04e+03 days. - - m s-2 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). The total tendency of the eastward wind due to gravity waves has the standard name tendency_of_eastward_wind_due_to_gravity_wave_drag. It is the sum of the tendencies due to orographic gravity waves and nonorographic waves. The tendency of eastward wind due to orographic gravity waves has the standard name tendency_of_eastward_wind_due_to_orographic_gravity_wave_drag. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "236U" is the isotope "uranium-236" with a half-life of 8.73e+09 days. - - m s-2 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). The total tendency of the eastward wind will include a variety of numerical and diffusive effects: a variable with this standard name is sometimes needed to allow the momentum budget to be closed. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Np" means the element "neptunium" and "237Np" is the isotope "neptunium-237" with a half-life of 7.79e+08 days. - - m s-2 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). The total tendency of the eastward wind due to gravity waves has the standard name tendency_of_eastward_wind_due_to_gravity_wave_drag. It is the sum of the tendencies due to orographic gravity waves and nonorographic waves. The tendency of eastward wind due to nonorographic gravity waves has the standard name tendency_of_eastward_wind_due_to_nonorographic_gravity_wave_drag. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "237Pu" is the isotope "plutonium-237" with a half-life of 4.56e+01 days. - - W m-2 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Enthalpy can be written either as (1) CpT, where Cp is heat capacity at constant pressure, T is absolute temperature, or (2) U+pV, where U is internal energy, p is pressure and V is volume. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "237U" is the isotope "uranium-237" with a half-life of 6.74e+00 days. - - W m-2 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Np" means the element "neptunium" and "238Np" is the isotope "neptunium-238" with a half-life of 2.10e+00 days. - - m s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. "Thickness" means the vertical extent of a layer.. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "238Pu" is the isotope "plutonium-238" with a half-life of 3.15e+04 days. - - kg m-3 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol" means aerosol without water. Black carbon aerosol is composed of elemental carbon. It is strongly light absorbing. The "aviation" sector includes fuel combustion activities related to civil aviation. "Aviation" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3a as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "238U" is the isotope "uranium-238" with a half-life of 1.65e+12 days. - - kg m-3 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen dioxide is NO2. The "aviation" sector includes fuel combustion activities related to civil aviation. "Aviation" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3a as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Np" means the element "neptunium" and "239Np" is the isotope "neptunium-239" with a half-life of 2.35e+00 days. - - kg m-3 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "aviation" sector includes fuel combustion activities related to civil aviation. "Aviation" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3a as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "239Pu" is the isotope "plutonium-239" with a half-life of 8.91e+06 days. - - kg m-3 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "aviation" sector includes fuel combustion activities related to civil aviation. "Aviation" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3a as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "239U" is the isotope "uranium-239" with a half-life of 1.63e-02 days. - - kg m-2 s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Am" means the element "americium" and "240Am" is the isotope "americium-240" with a half-life of 2.12e+00 days. - - kg m-2 s-1 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Np" means the element "neptunium" and "240mNp" is the metastable state of the isotope "neptunium-240" with a half-life of 5.08e-03 days. - - kg m-2 s-1 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Np" means the element "neptunium" and "240Np" is the isotope "neptunium-240" with a half-life of 4.38e-02 days. - - kg m-2 s-1 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "240Pu" is the isotope "plutonium-240" with a half-life of 2.40e+06 days. - - kg m-2 s-1 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary variable) as well. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "U" means the element "uranium" and "240U" is the isotope "uranium-240" with a half-life of 5.99e-01 days. - - s-1 + + Bq m-3 - "Tendency_of_X" means derivative of X with respect to time. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Condensed_water" means liquid and ice. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Am" means the element "americium" and "241Am" is the isotope "americium-241" with a half-life of 1.67e+05 days. - - s-1 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "condensed_water" means liquid and ice. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "241Cm" is the isotope "curium-241" with a half-life of 3.50e+01 days. - - s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "241Pu" is the isotope "plutonium-241" with a half-life of 4.83e+03 days. - - s-1 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Am" means the element "americium" and "242Am" is the isotope "americium-242" with a half-life of 6.69e-01 days. - - s-1 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "242Cm" is the isotope "curium-242" with a half-life of 1.63e+02 days. - - s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Am" means the element "americium" and "242m1Am" is the metastable state of the isotope "americium-242" with a half-life of 5.53e+04 days. - - s-1 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Am" means the element "americium" and "242m2Am" is the metastable state of the isotope "americium-242" with a half-life of 1.62e-07 days. - - s-1 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "242Pu" is the isotope "plutonium-242" with a half-life of 1.38e+08 days. - - s-1 + + Bq m-3 - 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convectionschemes). "tendency_of_X" means derivative of X with respect to time. "condensed_water" means liquid and ice. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Am" means the element "americium" and "243Am" is the isotope "americium-243" with a half-life of 2.91e+06 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "condensed_water" means liquid and ice. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "243Cm" is the isotope "curium-243" with a half-life of 1.17e+04 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Autoconversion is the process of collision and coalescence which results in the formation of precipitation particles from cloud water droplets or ice crystals. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "condensed_water" means liquid and ice. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "243Pu" is the isotope "plutonium-243" with a half-life of 2.07e-01 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Autoconversion is the process of collision and coalescence which results in the formation of precipitation particles from cloud water droplets or ice crystals. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "condensed_water" means liquid and ice. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Am" means the element "americium" and "244Am" is the isotope "americium-244" with a half-life of 4.20e-01 days. - - s-1 + + Bq m-3 - 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convectionschemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "condensed_water" means liquid and ice. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "244Cm" is the isotope "curium-244" with a half-life of 6.42e+03 days. - - s-1 + + Bq m-3 - 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. 'cloud_microphysics' is the sum of many cloud processes such as condensation, evaporation, homogeneous nucleation, heterogeneous nucleation, deposition, sublimation, the Bergeron-Findeisen process, riming, accretion, aggregationand icefall. The precise list of processes that are included in 'cloud_microphysics' canvary between models. Where possible, the data variable should be accompanied by a complete description of the processes included, for example, by using a comment attribute. Standard names also exist to describe the tendencies due to the separate processes. "tendency_of_X" means derivative of X with respect to time. "condensed_water" means liquid and ice. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Am" means the element "americium" and "244mAm" is the metastable state of the isotope "americium-244" with a half-life of 1.81e-02 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) Condensation is the conversion of vapor into liquid. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "condensed_water" means liquid and ice. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "244Pu" is the isotope "plutonium-244" with a half-life of 2.92e+10 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "condensed_water" means liquid and ice. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Am" means the element "americium" and "245Am" is the isotope "americium-245" with a half-life of 8.75e-02 days. - - s-1 + + Bq m-3 - 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convectionschemes). "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "245Cm" is the isotope "curium-245" with a half-life of 3.40e+06 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Accretion is the growth of a hydrometeor by collision with cloud droplets or ice crystals. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Pu" means the element "plutonium" and "245Pu" is the isotope "plutonium-245" with a half-life of 4.16e-01 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "246Cm" is the isotope "curium-246" with a half-life of 2.01e+06 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Aggregation is the clumping together of frozen cloud particles to produce snowflakes. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "247Cm" is the isotope "curium-247" with a half-life of 5.86e+09 days. - - s-1 + + Bq m-3 - 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convectionschemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The Bergeron-Findeisen process is the conversion of cloud liquid water to cloud ice arising from the fact that water vapor has a lower equilibrium vapor pressure with respect to ice than it has with respect to liquid water at the same subfreezing temperature. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "248Cm" is the isotope "curium-248" with a half-life of 1.72e+08 days. - - s-1 + + Bq m-3 - 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convectionschemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Bk" means the element "berkelium" and "249Bk" is the isotope "berkelium-249" with a half-life of 3.15e+02 days. - - s-1 + + Bq m-3 - 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. 'cloud_microphysics' is the sum of many cloud processes such as condensation, evaporation, homogeneous nucleation, heterogeneous nucleation, deposition, sublimation, the Bergeron-Findeisen process, riming, accretion, aggregationand icefall. The precise list of processes that are included in 'cloud_microphysics' canvary between models. Where possible, the data variable should be accompanied by a complete description of the processes included, for example, by using a comment attribute. Standard names also exist to describe the tendencies due to the separate processes. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cf" means the element "californium" and "249Cf" is the isotope "californium-249" with a half-life of 1.32e+05 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "249Cm" is the isotope "curium-249" with a half-life of 4.43e-02 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Sublimation is the conversion of solid into vapor. Deposition is the opposite of sublimation, i.e. it is the conversion of vapor into solid. Deposition is distinct from the processes of dry deposition and wet deposition of atmospheric aerosol particles, which are referred to in some standard names. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Na" means the element "sodium" and "24Na" is the isotope "sodium-24" with a half-life of 6.27e-01 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Bk" means the element "berkelium" and "250Bk" is the isotope "berkelium-250" with a half-life of 1.34e-01 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Heterogeneous nucleation occurs when a small particle of a substance other than water acts as a freezing or condensation nucleus. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cf" means the element "californium" and "250Cf" is the isotope "californium-250" with a half-life of 4.75e+03 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Heterogeneous nucleation occurs when a small particle of a substance other than water acts as a freezing or condensation nucleus. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cm" means the element "curium" and "250Cm" is the isotope "curium-250" with a half-life of 2.52e+06 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Homogeneous nucleation occurs when a small number of water molecules combine to form a freezing or condensation nucleus. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cf" means the element "californium" and "251Cf" is the isotope "californium-251" with a half-life of 2.92e+05 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cf" means the element "californium" and "252Cf" is the isotope "californium-252" with a half-life of 9.68e+02 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cf" means the element "californium" and "253Cf" is the isotope "californium-253" with a half-life of 1.76e+01 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Es" means the element "einsteinium" and "253Es" is the isotope "einsteinium-253" with a half-life of 2.05e+01 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Riming is the rapid freezing of supercooled water onto a surface. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Cf" means the element "californium" and "254Cf" is the isotope "californium-254" with a half-life of 6.03e+01 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Riming is the rapid freezing of supercooled water onto a surface. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Es" means the element "einsteinium" and "254Es" is the isotope "einsteinium-254" with a half-life of 2.76e+02 days. - - s-1 + + Bq m-3 - 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convectionschemes). "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Es" means the element "einsteinium" and "254mEs" is the metastable state of the isotope "einsteinium-254" with a half-life of 1.63e+00 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Accretion is the growth of a hydrometeor by collision with cloud droplets or ice crystals. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Es" means the element "einsteinium" and "255Es" is the isotope "einsteinium-255" with a half-life of 3.84e+01 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Accretion is the growth of a hydrometeor by collision with cloud droplets or ice crystals. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "H" means the element "hydrogen" and "3H" is the isotope "hydrogen-3" with a half-life of 4.51e+03 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ar" means the element "argon" and "41Ar" is the isotope "argon-41" with a half-life of 7.64e-02 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Autoconversion is the process of collision and coalescence which results in the formation of precipitation particles from cloud water droplets or ice crystals. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Mn" means the element "manganese" and "54Mn" is the isotope "manganese-54" with a half-life of 3.12e+02 days. - - s-1 + + Bq m-3 - 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The Bergeron-Findeisen process is the conversion of cloud liquid water to cloud ice arising from the fact that water vapor has a lower equilibrium vapor pressure with respect to ice than it has with respect to liquid water at the same subfreezing temperature. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Co" means the element "cobalt" and "58Co" is the isotope "cobalt-58" with a half-life of 7.10e+01 days. - - s-1 + + Bq m-3 - 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convectionschemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Co" means the element "cobalt" and "60Co" is the isotope "cobalt-60" with a half-life of 1.93e+03 days. - - s-1 + + Bq m-3 - 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convectionschemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. 'cloud_microphysics' is the sum of many cloud processes such as condensation, evaporation, homogeneous nucleation, heterogeneous nucleation, deposition, sublimation, the Bergeron-Findeisen process, riming, accretion, aggregationand icefall. The precise list of processes that are included in 'cloud_microphysics' canvary between models. Where possible, the data variable should be accompanied by a complete description of the processes included, for example, by using a comment attribute. Standard names also exist to describe the tendencies due to the separate processes. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ga" means the element "gallium" and "72Ga" is the isotope "gallium-72" with a half-life of 5.86e-01 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Evaporation is the conversion of liquid or solid into vapor. Condensation is the conversion of vapor into liquid. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Zn" means the element "zinc" and "72Zn" is the isotope "zinc-72" with a half-life of 1.94e+00 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Evaporation is the conversion of liquid or solid into vapor. Condensation is the conversion of vapor into liquid. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ga" means the element "gallium" and "73Ga" is the isotope "gallium-73" with a half-life of 2.03e-01 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Evaporation is the conversion of liquid or solid into vapor. Condensation is the conversion of vapor into liquid. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ge" means the element "germanium" and "75Ge" is the isotope "germanium-75" with a half-life of 5.73e-02 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Evaporation is the conversion of liquid or solid into vapor. Condensation is the conversion of vapor into liquid. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "longwave" means longwave radiation. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "As" means the element "arsenic" and "77As" is the isotope "arsenic-77" with a half-life of 1.62e+00 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Evaporation is the conversion of liquid or solid into vapor. Condensation is the conversion of vapor into liquid. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ge" means the element "germanium" and "77Ge" is the isotope "germanium-77" with a half-life of 4.72e-01 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Evaporation is the conversion of liquid or solid into vapor. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "shortwave" means shortwave radiation. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ge" means the element "germanium" and "77mGe" is the metastable state of the isotope "germanium-77" with a half-life of 6.27e-04 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Evaporation is the conversion of liquid or solid into vapor. Condensation is the conversion of vapor into liquid. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "As" means the element "arsenic" and "78As" is the isotope "arsenic-78" with a half-life of 6.32e-02 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Ge" means the element "germanium" and "78Ge" is the isotope "germanium-78" with a half-life of 6.03e-02 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Heterogeneous nucleation occurs when a small particle of a substance other than water acts asa freezing or condensation nucleus. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Se" means the element "selenium" and "79Se" is the isotope "selenium-79" with a half-life of 2.37e+07 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Homogeneous nucleation occurs when a small number of water molecules combine to form a freezing or condensation nucleus. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Se" means the element "selenium" and "81mSe" is the metastable state of the isotope "selenium-81" with a half-life of 3.97e-02 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Se" means the element "selenium" and "81Se" is the isotope "selenium-81" with a half-life of 1.28e-02 days. - - s-1 + + Bq m-3 - Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Riming is the rapid freezing of supercooled water onto a surface. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Br" means the element "bromine" and "82Br" is the isotope "bromine-82" with a half-life of 1.47e+00 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "middle_atmosphere_moles_of_X" means the total number of moles of X contained in the troposphere and stratosphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of carbon monoxide is CO. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Br" means the element "bromine" and "82mBr" is the metastable state of the isotope "bromine-82" with a half-life of 4.24e-03 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "middle_atmosphere_moles_of_X" means the total number of moles of X contained in the troposphere and stratosphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of HCC140a is CH3CCl3. The IUPAC name for HCC 140a is 1,1,1-trichloroethane. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Br" means the element "bromine" and "83Br" is the isotope "bromine-83" with a half-life of 1.00e-01 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "middle_atmosphere_moles_of_X" means the total number of moles of X contained in the troposphere and stratosphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of methane is CH4. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Kr" means the element "krypton" and "83mKr" is the metastable state of the isotope "krypton-83" with a half-life of 7.71e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "middle_atmosphere_moles_of_X" means the total number of moles of X contained in the troposphere and stratosphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of methyl bromide is CH3Br. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Se" means the element "selenium" and "83mSe" is the metastable state of the isotope "selenium-83" with a half-life of 8.10e-04 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "middle_atmosphere_moles_of_X" means the total number of moles of X contained in the troposphere and stratosphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of methyl chloride is CH3Cl. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Se" means the element "selenium" and "83Se" is the isotope "selenium-83" with a half-life of 1.56e-02 days. - - mol s-1 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. "middle_atmosphere_moles_of_X" means the total number of moles of X contained in the troposphere and stratosphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of molecular hydrogen is H2. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Br" means the element "bromine" and "84Br" is the isotope "bromine-84" with a half-life of 2.21e-02 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Aragonite is a mineral that is a polymorph of calcium carbonate. The chemical formula of aragonite is CaCO3. Standard names also exist for calcite, another polymorph of calcium carbonate. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Br" means the element "bromine" and "84mBr" is the metastable state of the isotope "bromine-84" with a half-life of 4.16e-03 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Aragonite is a mineral that is a polymorph of calcium carbonate. The chemical formula of aragonite is CaCO3. Standard names also exist for calcite, another polymorph of calcium carbonate. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Kr" means the element "krypton" and "85Kr" is the isotope "krypton-85" with a half-life of 3.95e+03 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Calcite is a mineral that is a polymorph of calcium carbonate. Thechemical formula of calcite is CaCO3. Standard names also exist for aragonite, another polymorph of calcium carbonate. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Kr" means the element "krypton" and "85mKr" is the metastable state of the isotope "krypton-85" with a half-life of 1.83e-01 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Calcite is a mineral that is a polymorph of calcium carbonate. Thechemical formula of calcite is CaCO3. Standard names also exist for aragonite, another polymorph of calcium carbonate. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rb" means the element "rubidium" and "86mRb" is the metastable state of the isotope "rubidium-86" with a half-life of 7.04e-04 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic carbon" describes a family of chemical species in solution, including carbon dioxide, carbonic acid and the carbonate and bicarbonate anions. "Dissolved inorganic carbon" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rb" means the element "rubidium" and "86Rb" is the isotope "rubidium-86" with a half-life of 1.87e+01 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic iron" means iron ions, in oxidation states of both Fe2+ and Fe3+, in solution. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Kr" means the element "krypton" and "87Kr" is the isotope "krypton-87" with a half-life of 5.28e-02 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Inorganic nitrogen" describes a family of chemical species which, in an ocean model, usually includes nitrite, nitrate and ammonium which act as nitrogennutrients. "Inorganic nitrogen" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rb" means the element "rubidium" and "87Rb" is the isotope "rubidium-87" with a half-life of 1.71e+13 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Dissolved inorganic phosphorus/phosphate means phosphate ions in solution. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Kr" means the element "krypton" and "88Kr" is the isotope "krypton-88" with a half-life of 1.17e-01 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Dissolved inorganic silicon/silicate means silicate ions in solution. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rb" means the element "rubidium" and "88Rb" is the isotope "rubidium-88" with a half-life of 1.25e-02 days. - - mol m-3 s-1 + + Bq m-3 - Dissolution, remineralization and desorption of iron back to the dissolved phase 'Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity namedby omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Kr" means the element "krypton" and "89Kr" is the isotope "krypton-89" with a half-life of 2.20e-03 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. 'Grazing of phytoplankton' means the grazing of phytoplankton by zooplankton. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Rb" means the element "rubidium" and "89Rb" is the isotope "rubidium-89" with a half-life of 1.06e-02 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sr" means the element "strontium" and "89Sr" is the isotope "strontium-89" with a half-life of 5.21e+01 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Y" means the element "yttrium" and "90mY" is the metastable state of the isotope "yttrium-90" with a half-life of 1.33e-01 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Net primary production" is the excess of gross primary production of organic carbon (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sr" means the element "strontium" and "90Sr" is the isotope "strontium-90" with a half-life of 1.02e+04 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Net primary production" is the excess of gross primary production of organic carbon (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. 'Calcareous phytoplankton' are phytoplankton that produce calcite. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there issufficient light to support photosynthesis. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Standard names also exist for aragonite, another polymorph of calcium carbonate. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Y" means the element "yttrium" and "90Y" is the isotope "yttrium-90" with a half-life of 2.67e+00 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Net primary production" is the excess of gross primary production of organic carbon (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. Diatoms are single-celled phytoplankton with an external skeleton made of silica. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surfacewhere there is sufficient light to support photosynthesis. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Y" means the element "yttrium" and "91mY" is the metastable state of the isotope "yttrium-91" with a half-life of 3.46e-02 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Net primary production" is the excess of gross primary production of organic carbon (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. In ocean modelling, diazotrophs are phytoplankton of the phylum cyanobacteria distinct from other phytoplankton groups in their ability to fix nitrogen gas in addition to nitrate and ammonium. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sr" means the element "strontium" and "91Sr" is the isotope "strontium-91" with a half-life of 3.95e-01 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Net primary production" is the excess of gross primary production of organic carbon (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. 'Miscellaneous phytoplankton' are all those phytoplankton that are not diatoms, diazotrophs, calcareous phytoplankton, picophytoplankton or other seperately named components of the phytoplankton population. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Y" means the element "yttrium" and "91Y" is the isotope "yttrium-91" with a half-life of 5.86e+01 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Net primary production" is the excess of gross primary production of organic carbon (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. Picophytoplankton are phytoplankton of less than 2 micrometers in size. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Sr" means the element "strontium" and "92Sr" is the isotope "strontium-92" with a half-life of 1.13e-01 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Nitrate utilization" means net primary production by phytoplankton based on nitrate alone. "Net primary production" is the excess of gross primary production of organic carbon (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. "tendency_of_X" means derivative of X with respect to time. Thechemical formula for the nitrate anion is NO3-. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Y" means the element "yttrium" and "92Y" is the isotope "yttrium-92" with a half-life of 1.47e-01 days. - - mol m-3 s-1 + + Bq m-3 - 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Y" means the element "yttrium" and "93Y" is the isotope "yttrium-93" with a half-life of 4.24e-01 days. - - m s-2 + + Bq m-3 - tnmmvtot - "tendency_of_X" means derivative of X with respect to time. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Zr" means the element "zirconium" and "93Zr" is the isotope "zirconium-93" with a half-life of 3.47e+08 days. - - m s-2 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nb" means the element "niobium" and "94mNb" is the metastable state of the isotope "niobium-94" with a half-life of 4.34e-03 days. - - m s-2 + + Bq m-3 - tnmmvc - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nb" means the element "niobium" and "94Nb" is the isotope "niobium-94" with a half-life of 7.29e+06 days. - - m s-2 + + Bq m-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Y" means the element "yttrium" and "94Y" is the isotope "yttrium-94" with a half-life of 1.32e-02 days. - - m s-2 + + Bq m-3 - tnmmvgwd - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nb" means the element "niobium" and "95mNb" is the metastable state of the isotope "niobium-95" with a half-life of 3.61e+00 days. - - m3 s-2 + + Bq m-3 - "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nb" means the element "niobium" and "95Nb" is the isotope "niobium-95" with a half-life of 3.52e+01 days. - - W m-2 + + Bq m-3 - "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Bolus transport in an ocean model means the part due to a scheme representing eddy-induced effects not included in the velocity field. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Y" means the element "yttrium" and "95Y" is the isotope "yttrium-95" with a half-life of 7.29e-03 days. - - mol m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Aragonite is a mineral that is a polymorph of calcium carbonate. The chemical formula of aragonite is CaCO3. Standard names also exist for calcite, another polymorph of calcium carbonate. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Zr" means the element "zirconium" and "95Zr" is the isotope "zirconium-95" with a half-life of 6.52e+01 days. - - mol m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Standard names also exist for aragonite, another polymorph of calcium carbonate. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nb" means the element "niobium" and "96Nb" is the isotope "niobium-96" with a half-life of 9.75e-01 days. - - mol m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of termswhich together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nb" means the element "niobium" and "97mNb" is the metastable state of the isotope "niobium-97" with a half-life of 6.27e-04 days. - - mol m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is asingle term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nb" means the element "niobium" and "97Nb" is the isotope "niobium-97" with a half-life of 5.11e-02 days. - - mol m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic carbon" describes a family of chemical species in solution, including carbon dioxide, carbonic acid and the carbonate and bicarbonate anions. "Dissolved inorganic carbon" isthe term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Zr" means the element "zirconium" and "97Zr" is the isotope "zirconium-97" with a half-life of 6.98e-01 days. - - mol m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is asingle term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic carbon" describes a family of chemical species in solution, including carbon dioxide, carbonic acid and the carbonate and bicarbonate anions. "Dissolved inorganic carbon" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Nb" means the element "niobium" and "98Nb" is the isotope "niobium-98" with a half-life of 3.53e-02 days. - - mol m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic iron" means iron ions, in oxidation states of both Fe2+ and Fe3+, in solution. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Mo" means the element "molybdenum" and "99Mo" is the isotope "molybdenum-99" with a half-life of 2.78e+00 days. - - mol m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is asingle term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic iron" means iron ions, in oxidation states of both Fe2+ and Fe3+, in solution. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tc" means the element "technetium" and "99mTc" is the metastable state of the isotope "technetium-99" with a half-life of 2.51e-01 days. - - mol m-2 s-1 + + Bq m-3 - "Content" indicates a quantity per unit area. "tendency_of_X" means derivative of X with respect to time. "Inorganic nitrogen" describes a family of chemical species which, in an ocean model, usually includes nitrite, nitrate and ammonium which act as nitrogen nutrients. "Inorganic nitrogen" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variableshould be accompanied by a complete description of the species represented, for example, by using a comment attribute. + "Radioactivity" means the number of radioactive decays of a material per second. "Radioactivity concentration" means radioactivity per unit volume of the medium. "Tc" means the element "technetium" and "99Tc" is the isotope "technetium-99" with a half-life of 7.79e+07 days. - - mol m-2 s-1 + + m - "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Inorganic nitrogen" describes a family of chemical species which, in an ocean model, usually includes nitrite, nitrate and ammonium which act as nitrogen nutrients. "Inorganic nitrogen" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + The average radius of a central region of clouds in tropical cyclones lacking well-defined eye features, which is computed by averaging the great circle distance in four cardinal directions. The radius in each direction is measured from the estimated storm center position to a warm point that exceeds a threshold brightness temperature at top of atmosphere limit. The threshold applied should be recorded in a coordinate variable having the standard_name of toa_brightness_temperature. A coordinate variable of radiation_wavelength, sensor_band_central_radiation_wavelength, or radiation_frequency may be specified to indicate that the brightness temperature applies at specific wavelengths or frequencies. - - mol m-2 s-1 + + m - "Content" indicates a quantity per unit area. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic phosphorus/phosphate" means phosphate ions in solution. The chemical formula of the phosphate anion is PO4 with a charge of minus three. + The radius of a tropical cyclone eye is defined to be the great circle distance measured from the cyclone center to the eye wall. - - mol m-2 s-1 + + m - "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is asingle term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic phosphorus/phosphate" means phosphate ions in solution. The chemical formula of the phosphate anion is PO4 with a charge of minus three. + The great circle distance measured from the tropical cyclone center to the region of sustained 1-minute duration maximum wind speed, as defined by the standard name, tropical_cyclone_maximum_sustained_wind_speed. - - mol m-2 s-1 + + kg m-2 - "Content" indicates a quantity per unit area. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic silicon/silicate" means silicate ions in solution. + "Amount" means mass per unit area. - - mol m-2 s-1 + + kg m-2 s-1 - "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is asingle term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic silicon/silicate" means silicate ions in solution. + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - mol m-2 s-1 + + m s-1 - "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is asingle term in a sum of terms which together compose the general quantity named by omitting the phrase. 'Denitrification' is the conversion of nitrate into gasesous compounds such as nitric oxide, nitrous oxide and molecular nitrogen which are then emitted to the atmosphere. 'Sedimentation' is the sinking of particulate matter to the floor of a body of water. "tendency_of_X" means derivative of X with respect to time. + - - mol m-2 s-1 + + s-1 - "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is asingle term in a sum of terms which together compose the general quantity named by omitting the phrase. Deposition of nitrogen into the ocean is the sum of dry and wet depositionof nitrogen species onto the ocean surface from the atmosphere. 'Nitrogen fixation' means the production of ammonia from nitrogen gas. Organisms that fix nitrogen are termed 'diazotrophs'. Diazotrophic phytoplankton can fix atmospheric nitrogen, thus increasing the content of nitrogen in the ocean. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage."tendency_of_X" means derivative of X with respect to time. + The "reaction rate" is the rate at which the reactants of a chemical reaction form the products. The rate of "hydroxyl radical destruction due to reaction with nmvoc" is the nmvoc reactivity with regard to reactions with OH. It is the weighted sum of the reactivity of all individual nmvoc species with OH. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The chemical formula for the hydroxyl radical is OH. In chemistry, a "radical" is a highly reactive, and therefore shortlived, species. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. - - mol m-2 s-1 + + K s-1 - "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is asingle term in a sum of terms which together compose the general quantity named by omitting the phrase. 'Nitrogen fixation' means the production of ammonia from nitrogen gas. Organisms that fix nitrogen are termed 'diazotrophs'. Diazotrophic phytoplankton can fix atmospheric nitrogen, thus increasing the content of nitrogen in the ocean. "tendency_of_X" means derivative of X with respect to time. + The quantity with standard name ratio_of_sea_water_potential_temperature_anomaly_to_relaxation_timescale is a correction term applied to modelled sea water potential temperature. The term is estimated as the deviation of model local sea water potential temperature from an observation-based climatology (e.g. World Ocean Database) weighted by a user-specified relaxation coefficient in s-1 (1/(relaxation timescale)). Potential temperature is the temperature a parcel of air or sea water would have if moved adiabatically to sea level pressure. The phrase "ratio_of_X_to_Y" means X/Y. The term "anomaly" means difference from climatology. - - mol m-2 s-1 + + s-1 - "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + The quantity with standard name ratio_of_sea_water_practical_salinity_anomaly_to_relaxation_timescale is a correction term applied to modelled sea water practical salinity. The term is estimated as the deviation of model local sea water practical salinity from an observation-based climatology (e.g. World Ocean Database) weighted by a user-specified relaxation coefficient in s-1 (1/(relaxation timescale)). The phrase "ratio_of_X_to_Y" means X/Y. The term "anomaly" means difference from climatology. Practical Salinity, S_P, is a determination of the salinity of sea water, based on its electrical conductance. The measured conductance, corrected for temperature and pressure, is compared to the conductance of a standard potassium chloride solution, producing a value on the Practical Salinity Scale of 1978 (PSS-78). This name should not be used to describe salinity observations made before 1978, or ones not based on conductance measurements. Conversion of Practical Salinity to other precisely defined salinity measures should use the appropriate formulas specified by TEOS-10. Other standard names for precisely defined salinity quantities are sea_water_absolute_salinity (S_A); sea_water_preformed_salinity (S_*), sea_water_reference_salinity (S_R); sea_water_cox_salinity (S_C), used for salinity observations between 1967 and 1977; and sea_water_knudsen_salinity (S_K), used for salinity observations between 1901 and 1966. Salinity quantities that do not match any of the precise definitions shoul d be given the more general standard name of sea_water_salinity. Reference: www.teos-10.org; Lewis, 1980 doi:10.1109/JOE.1980.1145448. - - mol m-2 s-1 + + m s-2 - "Content" indicates a quantity per unit area. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of termswhich together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + Sea surface density is the density of sea water near the surface (including the part under sea-ice, if any). "component_derivative_of_X" means derivative of X with respect to distance in the component direction, which may be northward, southward, eastward, westward, x or y. The last two indicate derivatives along the axes of the grid, whether or not they are true longitude and latitude. "ratio_of_X_to_Y" means X/Y. "Ocean rigid lid pressure" means the pressure at the surface of an ocean model assuming that it is bounded above by a rigid lid. - - mol m-2 s-1 + + m s-2 - "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + Sea surface density is the density of sea water near the surface (including the part under sea-ice, if any). "component_derivative_of_X" means derivative of X with respect to distance in the component direction, which may be northward, southward, eastward, westward, x or y. The last two indicate derivatives along the axes of the grid, whether or not they are true longitude and latitude. "ratio_of_X_to_Y" means X/Y. "Ocean rigid lid pressure" means the pressure at the surface of an ocean model assuming that it is bounded above by a rigid lid. - - mol m-2 s-1 + + 1 - "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is asingle term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + Realization is used to label a dimension that can be thought of asa statistical sample, e.g., labelling members of a model ensemble. - - W m-2 + + Pa - "Content" indicates a quantity per unit area. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) "tendency_of_X" means derivative of X with respect to time. + For models using a dimensionless vertical coordinate, for example, sigma, hybrid sigma-pressure or eta, the values of the vertical coordinate at the model levels are calculated relative to a reference level. "Reference air pressure" is the air pressure at the model reference level. It is a model-dependent constant. - - W m-2 + + kg m-3 - "Content" indicates a quantity per unit area. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) "Due to background" means caused by a time invariant imposed field which may be either constant over the globe or spatially varying, depending on the ocean model used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + Sea water density is the in-situ density (not the potential density). For a rigid lid Boussinesq geopotential ocean model the density of the sea water is maintained at a constant reference density. In a model using the rigid lid Boussinesq approximation , the vertical grid coordinates (and hence the grid cell volumes) are time invariant. - - W m-2 + + - "Content" indicates a quantity per unit area. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) "Due to tides" means due to all astronomical gravity changes which manifest as tides. No distinction is made between different tidal components. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + A variable with the standard name of region contains strings which indicate geographical regions. These strings must be chosen from the standard region list. - - W m-2 - - - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) + + 1 + 52 E157 + hur + - - W m-2 + + 1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) + Relative humidity at which the size of a sampled aerosol particle was selected. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. - - W m-2 + + degree - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) + Standard names for "platform" describe the motion and orientation of the vehicle from which observations are made. Platforms include, but are not limited to, satellites, aeroplanes, ships, instruments and buoys. The quantity with standard name relative_platform_azimuth_angle is the difference between the viewing geometries from two different platforms over the same observation target. It is the difference between the values of two quantities with standard name platform_azimuth_angle. There is no standardized sign convention for relative_platform_azimuth_angle. "Observation target" means a location on the Earth defined by the sensor performing the observations. A standard name also exists for relative_sensor_azimuth_angle. For some viewing geometries the sensor and the platform cannot be assumed to be close enough to neglect the difference in calculated azimuth angle. - - kg m-2 s-1 + + degree - "Amount" means mass per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + relative_sensor_azimuth_angle is the difference between the viewing geometries from two different sensors over the same observation target. It is the difference between the values of two quantities with standard name sensor_azimuth_angle. There is no standardized sign convention for relative_sensor_azimuth_angle. "Observation target" means a location on the Earth defined by the sensor performing the observations. A standard name also exists for relative_platform_azimuth_angle, where "platform" refers to the vehicle from which observations are made e.g. aeroplane, ship, or satellite. For some viewing geometries the sensor and the platform cannot be assumed to be close enough to neglect the difference in calculated azimuth angle. - - kg m-2 s-1 + + 1 - "Amount" means mass per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Congelation ice" means the freezing of sea water onto the underside of thin, new sea ice that has been formed by small areas of frazil ice crystals joining together into a continuous layer at the sea surface. Congelation ice forms under calm water conditions; it thickens and stabilizes the layer of sea ice and produces a smooth bottom surface. + Richardson number is a measure of dynamic stability and can be used to diagnose the existence of turbulent flow. It is defined as the ratio of the buoyant suppression of turbulence (i.e. how statically stable or unstable the conditions are) to the kinetic energy available to generate turbulence in a shear flow. - - kg m-2 s-1 + + m - "Amount" means mass per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Frazil" consists of needle like crystals of ice, typically between three and four millimeters in diameter, which form as sea water begins to freeze. Salt is expelled during the freezing process and frazil ice consists of nearly pure fresh water. Leads are stretches of open water within wider areas of sea ice. + Depth is the vertical distance below the surface. The root depth is maximum depth of soil reached by plant roots, from which they can extract moisture. - - kg m-2 s-1 + + kg m-2 - "Amount" means mass per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. An ice floe is a flat expanse of sea ice, generally taken to be less than 10 km across. "Lateral growth of ice floe" means the accumulation of ice at the extreme edges of the ice area. + "Content" indicates a quantity per unit area. - - kg m-2 s-1 + + kg m-2 - "Amount" means mass per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Snow to sea ice conversion" occurs when the mass of snow accumulated on an area of sea ice is sufficient to cause the ice to become mostly submerged. Waves can then wash over the ice and snow surface and freeze into a layer that becomes "snow ice". + "Content" indicates a quantity per unit area. - - kg m-2 s-1 + + kg m-2 - "Amount" means mass per unit area. The surface called "surface" means the lower boundary of the atmosphere. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + "Amount" means mass per unit area. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. - - s-1 + + kg m-2 - "tendency_of_X" means derivative of X with respect to time. "X_area_fraction" means the fraction of horizontal area occupied by X. Sea ice area fraction is area of the sea surface occupied by sea ice. It is also called "sea ice concentration". "Sea ice dynamics" refers to the motion of sea ice. + Runoff is the liquid water which drains from land. "Runoff_excluding_baseflow" is the sum of surface runoff and subsurface runoff excluding baseflow. Baseflow is subsurface runoff which takes place below the level of the water table. "Amount" means mass per unit area. - - s-1 + + kg m-2 s-1 - - "X_area_fraction" means the fraction of horizontal area occupied by X. Sea ice area fraction is area of the sea surface occupied by sea ice. It is also called "sea ice concentration". The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Sea ice "ridging" occurs in rough sea conditions. The motion of the sea surface can cause areas of sea ice to deform and fold resulting in ridged upper and lower surfaces. The ridges can be as much as twenty metres thick if thick ice is deformed. + mrro + Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - s-1 + + kg m-2 s-1 - "tendency_of_X" means derivative of X with respect to time. "X_area_fraction" means the fraction of horizontal area occupied by X. Sea ice area fraction is area of the sea surface occupied by sea ice. It is also called "sea ice concentration". "Sea ice thermodynamics" refers to the addition or subtraction of mass due to surface and basal fluxes. + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sea ice thermodynamics" refers to the addition or subtraction of ice mass due to surface and basal fluxes, i.e., due to melting, sublimation and fusion. The quantity with standard name salt_flux_into_sea_water_due_to_sea_ice_thermodynamics is negative during ice growth when salt becomes embedded into the ice and positive during ice melting when salt is released into the ocean. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - m s-1 + + kg m-2 s-1 - "tendency_of_X" means derivative of X with respect to time. "Sea ice dynamics" refers to the motion of sea ice. + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "River" refers to water in the fluvial system (stream and floodplain). - - m s-1 - 97 + + rad + - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + The scattering angle is that between the direction of the beam of incident radiation and the direction into which it is scattered. - - mol m-3 s-1 + + 1 - 'sea_water_alkalinity_expressed_as_mole_equivalent' is the total alkalinity equivalent concentration (including carbonate, nitrogen, silicate, and borate components). The specification of a physical process by the phrase due_to_process means that thequantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X withrespect to time. + A variable with the standard name of scene_type_of_dvorak_tropical_cyclone_cloud_region contains integers which can be translated to strings using flag_values and flag_meanings attributes. It indicates the Advanced Dvorak Technique tropical cyclone cloud region scene type chosen from the following list: uniform_central_dense_overcast; embedded_center; irregular_central_dense_overcast; curved_band; shear. Alternatively, the data variable may contain strings chosen from the same standardised list to indicate the scene type. Reference: Olander, T. L., & Velden, C. S., The Advanced Dvorak Technique: Continued Development of an Objective Scheme to Estimate Tropical Cyclone Intensity Using Geostationary Infrared Satellite Imagery (2007). American Meterorological Society Weather and Forecasting, 22, 287-298. - - 1e-3 s-1 + + 1 - "tendency_of_X" means derivative of X with respect to time. Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and normally given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. + A variable with the standard name of scene_type_of_dvorak_tropical_cyclone_eye_region contains integers which can be translated to strings using flag_values and flag_meanings attributes. It indicates the Advanced Dvorak Technique tropical cyclone eye region scene type chosen from the following list: clear_ragged_or_obscured_eye; pinhole_eye; large_eye; no_eye. Alternatively, the data variable may contain strings chosen from the same standardised list to indicate the scene type. Reference: Olander, T. L., & Velden, C. S., The Advanced Dvorak Technique: Continued Development of an Objective Scheme to Estimate Tropical Cyclone Intensity Using Geostationary Infrared Satellite Imagery (2007). American Meterorological Society Weather and Forecasting, 22, 287-298. - - 1e-3 s-1 + + m2 - "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and normally given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. + "X_area" means the horizontal area occupied by X within the grid cell. The extent of an individual grid cell is defined by the horizontal coordinates and any associated coordinate bounds or by a string valued auxiliary coordinate variable with a standard name of "region". - - 1e-3 s-1 + + 1 - "tendency_of_X" means derivative of X with respect to time. Bolus advection in an ocean model means the part due to a scheme representing eddy-induced effects not included in the velocity field. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and normally given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. + "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. - - 1e-3 s-1 + + 1 - "tendency_of_X" means derivative of X with respect to time. "Horizontal mixing" means any horizontal transport other than by advection and bolus advection, usually represented as horizontal diffusion in ocean models. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and normally given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. + X"_binary_mask" has 1 where condition X is met, 0 elsewhere. 1 = sea, 0 = land. - - 1e-3 s-1 + + m - - "tendency_of_X" means derivative of X with respect to time. "Sea ice thermodynamics" refers to the addition or subtraction of sea ice mass due to surface and basal fluxes. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and normally given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. + zobt + "Depth_below_X" means the vertical distance below the named surface X. The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. (The volume enclosed between the geoid and the sea floor equals the mean volume of water in the ocean). In an ocean GCM the geoid is the surface of zero depth, or the rigid lid if the model uses that approximation. To specify which geoid or geopotential datum is being used as a reference level, a grid_mapping variable should be attached to the data variable as described in Chapter 5.6 of the CF Convention. - - 1e-3 s-1 + + m - "tendency_of_X" means derivative of X with respect to time. "Vertical mixing" means any vertical transport other than by advection and bolus advection, represented by a combination of vertical diffusion, turbulent mixing and convection in ocean models. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and normally given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. + "Depth_below_X" means the vertical distance below the named surface X. The "geopotential datum" is any estimated surface of constant geopotential used as a datum i.e. a reference level; for the geoid as a datum, specific standard names are available. To specify which geoid or geopotential datum is being used as a reference level, a grid_mapping variable should be attached to the data variable as described in Chapter 5.6 of the CF Convention. - - K s-1 + + m - "tendency_of_X" means derivative of X with respect to time. Sea water temperature is the in situ temperature of the sea water. For observed data, depending on the period during which the observation was made, the measured in situ temperature was recorded against standard "scales". These historical scales include the International Practical Temperature Scale of 1948 (IPTS-48; 1948-1967), the International Practical Temperature Scale of 1968 (IPTS-68, Barber, 1969; 1968-1989) and the International Temperature Scale of 1990 (ITS-90, Saunders 1990; 1990 onwards). Conversion of data between these scales follows t68 = t48 - (4.4 x 10e-6) * t48(100 - t - 48); t90 = 0.99976 * t68. Observations made prior to 1948 (IPTS-48) have not been documented and therefore a conversion cannot be certain. Differences between t90 and t68 can be up to 0.01 at temperatures of 40 C and above; differences of 0.002-0.007 occur across the standard range of ocean temperatures (-10 - 30 C). The International Equation of State of Seawater 1980 (EOS-80, UNESCO, 1981) and the Practical Salinity Scale (PSS-78) were both based on IPTS-68, while the Thermodynamic Equation of Seawater 2010 (TEOS-10) is based on ITS-90. References: Barber, 1969, doi: 10.1088/0026-1394/5/2/001; UNESCO, 1981; Saunders, 1990, WOCE Newsletter, 10, September 1990. + "Depth_below_X" means the vertical distance below the named surface X. "Mean sea level" means the time mean of sea surface elevation at a given location over an arbitrary period sufficient to eliminate the tidal signals. - - K s-1 + + m - "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Sea water temperature is the in situ temperature of the sea water. For observed data, depending on the period during which the observation was made, the measured in situ temperature was recorded against standard "scales". These historical scales include the International Practical Temperature Scale of 1948 (IPTS-48; 1948-1967), the International Practical Temperature Scale of 1968 (IPTS-68, Barber, 1969; 1968-1989) and the International Temperature Scale of 1990 (ITS-90, Saunders 1990; 1990 onwards). Conversion of data between these scales follows t68 = t48 - (4.4 x 10e-6) * t48(100 - t - 48); t90 = 0.99976 * t68. Observations made prior to 1948 (IPTS-48) have not been documented and therefore a conversion cannot be certain. Differences between t90 and t68 can be up to 0.01 at temperatures of 40 C and above; differences of 0.002-0.007 occur across the standard range of ocean temperatures (-10 - 30 C). The International Equation of State of Seawater 1980 (EOS-80, UNESCO, 1981) and the Practical Salinity Scale (PSS-78) were both based on IPTS-68, while the Thermodynamic Equation of Seawater 2010 (TEOS-10) is based on ITS-90. References: Barber, 1969, doi: 10.1088/0026-1394/5/2/001; UNESCO, 1981; Saunders, 1990, WOCE Newsletter, 10, September 1990. + "Depth_below_X" means the vertical distance below the named surface X. A reference ellipsoid is a regular mathematical figure that approximates the irregular shape of the geoid. A number of reference ellipsoids are defined for use in the field of geodesy. To specify which reference ellipsoid is being used, a grid_mapping variable should be attached to the data variable as described in Chapter 5.6 of the CF Convention. - - K s-1 + + m - "tendency_of_X" means derivative of X with respect to time. Bolus advection in an ocean model means the part due to a scheme representing eddy-induced effects not included in the velocity field. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Sea water temperature is the in situ temperature of the sea water. For observed data, depending on the period during which the observation was made, the measured in situ temperature was recorded against standard "scales". These historical scales include the International Practical Temperature Scale of 1948 (IPTS-48; 1948-1967), the International Practical Temperature Scale of 1968 (IPTS-68, Barber, 1969; 1968-1989) and the International Temperature Scale of 1990 (ITS-90, Saunders 1990; 1990 onwards). Conversion of data between these scales follows t68 = t48 - (4.4 x 10e-6) * t48(100 - t - 48); t90 = 0.99976 * t68. Observations made prior to 1948 (IPTS-48) have not been documented and therefore a conversion cannot be certain. Differences between t90 and t68 can be up to 0.01 at temperatures of 40 C and above; differences of 0.002-0.007 occur across the standard range of ocean temperatures (-10 - 30 C). The International Equation of State of Seawater 1980 (EOS-80, UNESCO, 1981) and the Practical Salinity Scale (PSS-78) were both based on IPTS-68, while the Thermodynamic Equation of Seawater 2010 (TEOS-10) is based on ITS-90. References: Barber, 1969, doi: 10.1088/0026-1394/5/2/001; UNESCO, 1981; Saunders, 1990, WOCE Newsletter, 10, September 1990. + The sea_floor_depth_below_sea_surface is the vertical distance between the sea surface and the seabed as measured at a given point in space including the variance caused by tides and possibly waves. - - K s-1 + + 1 - "tendency_of_X" means derivative of X with respect to time. "Horizontal mixing" means any horizontal transport other than by advection and bolus advection, usually represented as horizontal diffusion in ocean models. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Sea water temperature is the in situ temperature of the sea water. For observed data, depending on the period during which the observation was made, the measured in situ temperature was recorded against standard "scales". These historical scales include the International Practical Temperature Scale of 1948 (IPTS-48; 1948-1967), the International Practical Temperature Scale of 1968 (IPTS-68, Barber, 1969; 1968-1989) and the International Temperature Scale of 1990 (ITS-90, Saunders 1990; 1990 onwards). Conversion of data between these scales follows t68 = t48 - (4.4 x 10e-6) * t48(100 - t - 48); t90 = 0.99976 * t68. Observations made prior to 1948 (IPTS-48) have not been documented and therefore a conversion cannot be certain. Differences between t90 and t68 can be up to 0.01 at temperatures of 40 C and above; differences of 0.002-0.007 occur across the standard range of ocean temperatures (-10 - 30 C). The International Equation of State of Seawater 1980 (EOS-80, UNESCO, 1981) and the Practical Salinity Scale (PSS-78) were both based on IPTS-68, while the Thermodynamic Equation of Seawater 2010 (TEOS-10) is based on ITS-90. References: Barber, 1969, doi: 10.1088/0026-1394/5/2/001; UNESCO, 1981; Saunders, 1990, WOCE Newsletter, 10, September 1990. + The albedo of sea ice. Albedo is the ratio of outgoing to incoming shortwave irradiance, where 'shortwave irradiance' means that both the incoming and outgoing radiation are integrated across the solar spectrum. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - K s-1 + + kg m-2 - "tendency_of_X" means derivative of X with respect to time. "Vertical mixing" means any vertical transport other than by advection and bolus advection, represented by a combination of vertical diffusion, turbulent mixing and convection in ocean models. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Sea water temperature is the in situ temperature of the sea water. For observed data, depending on the period during which the observation was made, the measured in situ temperature was recorded against standard "scales". These historical scales include the International Practical Temperature Scale of 1948 (IPTS-48; 1948-1967), the International Practical Temperature Scale of 1968 (IPTS-68, Barber, 1969; 1968-1989) and the International Temperature Scale of 1990 (ITS-90, Saunders 1990; 1990 onwards). Conversion of data between these scales follows t68 = t48 - (4.4 x 10e-6) * t48(100 - t - 48); t90 = 0.99976 * t68. Observations made prior to 1948 (IPTS-48) have not been documented and therefore a conversion cannot be certain. Differences between t90 and t68 can be up to 0.01 at temperatures of 40 C and above; differences of 0.002-0.007 occur across the standard range of ocean temperatures (-10 - 30 C). The International Equation of State of Seawater 1980 (EOS-80, UNESCO, 1981) and the Practical Salinity Scale (PSS-78) were both based on IPTS-68, while the Thermodynamic Equation of Seawater 2010 (TEOS-10) is based on ITS-90. References: Barber, 1969, doi: 10.1088/0026-1394/5/2/001; UNESCO, 1981; Saunders, 1990, WOCE Newsletter, 10, September 1990. + "Amount" means mass per unit area. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - s-1 + + kg m-2 - "tendency_of_X" means derivative of X with respect to time. "specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. + "Amount" means mass per unit area. Surface amount refers to the amount on the ground, excluding that on the plant or vegetation canopy. The phrase "surface_snow" means snow lying on the surface. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - s-1 + + m2 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. + "X_area" means the horizontal area occupied by X within the grid cell. The extent of an individual grid cell is defined by the horizontal coordinates and any associated coordinate bounds or by a string valued auxiliary coordinate variable with a standard name of "region". "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - s-1 - - tnmrc - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. + + 1 + 91 + sic + "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. Sea ice area fraction is area of the sea surface occupied by sea ice. It is also called "sea ice concentration". "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - s-1 + + m2 s-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. + Transport "across_line" means that which crosses a particular line on the Earth's surface; formally this means the integral along the line of the normal component of the transport. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - s-1 + + N m-1 - tnmrd - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. + + "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. Axial stress is the symmetric component of the tensor representing the gradient of internal forces (e.g. in ice). Horizontal stress refers to the stress in the horizontal plane. "Horizontal" refers to the local horizontal in the location of the sea ice, i.e., perpendicular to the local gravity vector. Average normal stress refers to the average of the diagonal elements of the stress tensor and represents the first invariant of stress. - - K s-1 + + 1 - Specific humidity is the mass fraction of water vapor in (moist) air. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "specific" means per unit mass. + The quantity with standard name sea_ice_basal_drag_coefficient_for_momentum_in_sea_water is used to calculate the oceanic momentum drag on sea ice movement. Basal drag is a resistive stress opposing ice flow at the boundary between sea ice and sea water. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - s-1 + + K - Specific humidity is the mass fraction of water vapor in (moist) air. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Tendency_of_X" means derivative of X with respect to time. "Specific" means per unit mass. + "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. The standard name sea_ice_basal_temperature means the temperature of the sea ice at its lower boundary. - - Pa s-1 - E158 + + 1 + - The surface called "surface" means the lower boundary of the atmosphere. "tendency_of_X" means derivative of X with respect to time. + A variable with the standard name of sea_ice_classification contains strings which indicate the character of the ice surface e.g. open_ice, or first_year_ice. These strings have not yet been standardised. However, and whenever possible, they should follow the terminology defined in the WMO Standard Nomenclature for Sea Ice Classification. Alternatively, the data variable may contain integers which can be translated to strings using flag_values and flag_meanings attributes. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - kg m-2 s-1 + + m - The surface called "surface" means the lower boundary of the atmosphere. "tendency_of_X" means derivative of X with respect to time. "Amount" means mass per unit area. Surface amount refers to the amount on the ground, excluding that on the plant or vegetation canopy. + Sea ice draft is the depth of the sea-ice lower surface below the water surface. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - mol s-1 + + m2 - "tendency_of_X" means derivative of X with respect to time. "troposphere_moles_of_X" means the total number of moles of X contained in the troposphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of carbon monoxide is CO. + The term sea_ice_extent means the total area of all grid cells in which the sea ice area fraction equals or exceeds a threshold, often chosen to be 15 per cent. The threshold must be specified by supplying a coordinate variable or scalar coordinate variable with the standard name of sea_ice_area_fraction. The horizontal domain over which sea ice extent is calculated is described by the associated coordinate variables and coordinate bounds or by a coordinate variable or scalar coordinate variable with the standard name of "region" supplied according to section 6.1.1 of the CF conventions. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - mol s-1 + + m - "tendency_of_X" means derivative of X with respect to time. "troposphere_moles_of_X" means the total number of moles of X contained in the troposphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of HCC140a is CH3CCl3. The IUPAC name for HCC140a is 1,1,1-trichloroethane. + Sea ice freeboard is the height of the sea-ice upper surface above the water surface. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - mol s-1 + + kg - "tendency_of_X" means derivative of X with respect to time. "troposphere_moles_of_X" means the total number of moles of X contained in the troposphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of HCFC22 is CHClF2. The IUPAC name for HCFC 22 is chloro-difluoro-methane. + The horizontal domain over which sea ice mass is calculated is described by the associated coordinate variables and coordinate bounds or by a coordinate variable or scalar coordinate variable with the standard name of "region" supplied according to section 6.1.1 of the CF conventions."Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - mol s-1 + + kg m-2 - "tendency_of_X" means derivative of X with respect to time. "troposphere_moles_of_X" means the total number of moles of X contained in the troposphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. "Content" indicates a quantity per unit area. The "sea_ice content" of a quantity refers to the vertical integral from the surface down to the bottom of the sea ice. - - mol s-1 + + m - "tendency_of_X" means derivative of X with respect to time. "troposphere_moles_of_X" means the total number of moles of X contained in the troposphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of methyl bromide is CH3Br. The IUPAC name for methyl bromide is bromomethane. + "Thickness" means the vertical extent of a layer. Melt ponds occur on top of the existing sea ice. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - mol s-1 + + 1e-3 - "tendency_of_X" means derivative of X with respect to time. "troposphere_moles_of_X" means the total number of moles of X contained in the troposphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of methyl chloride is CH3Cl. The IUPAC name for methyl chloride is chloromethane. + Sea ice salinity is the salt content of sea ice, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and normally given as 1e-3 or 0.001 i.e. parts per thousand. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - mol s-1 - + + m s-1 + 94 - "tendency_of_X" means derivative of X with respect to time. "troposphere_moles_of_X" means the total number of moles of X contained in the troposphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of molecular hydrogen is H2. + Speed is the magnitude of velocity. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - m s-2 + + K - "tendency_of_X" means derivative of X with respect to time. A velocity is a vector quantity. "Upward" indicates a vector component which is positive when directed upward (negative downward). Upward air velocity is the vertical component of the 3D air velocity vector. + The surface temperature is the (skin) temperature at the interface, not the bulk temperature of the medium above or below. "Sea ice surface temperature" is the temperature that exists at the interface of sea ice and an overlying medium which may be air or snow. In areas of snow covered sea ice, sea_ice_surface_temperature is not the same as the quantity with standard name surface_temperature. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - m s-2 + + K - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. A velocity is a vector quantity. "Upward" indicates a vector component which is positive when directed upward (negative downward). Upward air velocity is the vertical component of the 3D air velocity vector. + Sea ice temperature is the bulk temperature of the sea ice, not the surface (skin) temperature. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - m s-2 + + J m-2 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Speed is the magnitude of velocity. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) The wind speed is the magnitude of the wind velocity. + The quantity with standard name sea_ice_temperature_expressed_as_heat_content is calculated relative to the heat content of ice at zero degrees Celsius, which is assumed to have a heat content of zero Joules. The phrase "expressed_as_heat_content" means that this quantity is calculated as the specific heat capacity times density of sea ice multiplied by the temperature of the sea ice in the grid cell and integrated over depth. If used for a layer heat content, coordinate bounds should be used to define the extent of the layers. If no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is sea ice the integral is assumed to be calculated over the full depth of the ice. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - m s-2 + + m + 92 + sit + "Thickness" means the vertical extent of a layer. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. + + + + kg s-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Speed is the magnitude of velocity. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) The wind speed is the magnitude of the wind velocity. + Transport across_line means that which crosses a particular line on the Earth's surface; formally this means the integral along the line of the normal component of the transport. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - J m-2 + + m3 - "Content" indicates a quantity per unit area. Thermal energy is the total vibrational energy, kinetic and potential, of all the molecules and atoms in a substance. The surface called "surface" means the lower boundary of the atmosphere. + "X_volume" means the volume occupied by X within the grid cell. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - + m - "Amount" means mass per unit area. The construction thickness_of_[X_]rainfall_amount means the accumulated "depth" of rainfall i.e. the thickness of a layer of liquid water having the same mass per unit area as the rainfall amount. + "x" indicates a vector component along the grid x-axis, positive with increasing x. "Displacement" means the change in geospatial position of an object that has moved over time. If possible, the time interval over which the motion took place should be specified using a bounds variable for the time coordinate variable. A displacement can be represented as a vector. Such a vector should however not be interpreted as describing a rectilinear, constant speed motion but merely as an indication that the start point of the vector is found at the tip of the vector after the time interval associated with the displacement variable. A displacement does not prescribe a trajectory. Sea ice displacement can be defined as a two-dimensional vector, with no vertical component. An x displacement is calculated from the difference in the moving object's grid x coordinate between the start and end of the time interval associated with the displacement variable. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - m + + N m-2 - "Amount" means mass per unit area. The construction thickness_of_[X_]snowfall_amount means the accumulated "depth" of snow which fell i.e. the thickness of the layer of snow at its own density. There are corresponding standard names for liquid water equivalent (lwe) thickness. + "x" indicates a vector component along the grid x-axis, positive with increasing x. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. In meteorology and oceanography, the Coriolis effect per unit mass arises solely from the earth's rotation and acts as a deflecting force, normal to the velocity, to the right of the motion in the Northern Hemisphere and to the left in the Southern Hemisphere. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Coriolis_force. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - m + + N m-2 - "Thickness" means the vertical extent of a layer. + "x" indicates a vector component along the grid x-axis, positive with increasing x. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Several factors contribute to differences in the ocean surface level, including uneven heating, salinity variations, and currents, especially near coastal regions or ice shelves. Differences in surface level result in sea-surface tilt, a force that influences the ice motion. Reference: National Snow and Ice Data Center https://nsidc.org/cryosphere/seaice/processes/dynamics.html. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - m + + N m-2 - "Amount" means mass per unit area. The construction thickness_of_[X_]rainfall_amount means the accumulated "depth" of rainfall i.e. the thickness of a layer of liquid water having the same mass per unit area as the rainfall amount. + "x" indicates a vector component along the grid x-axis, positive with increasing x. Internal ice stress is a measure of the compactness, or strength, of the ice. Internal ice stress usually acts as a resistance to the motion caused by the wind force. Reference: National Snow and Ice Data Center https://nsidc.org/cryosphere/seaice/processes/dynamics.html. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - m + + kg s-1 - "Amount" means mass per unit area. The construction thickness_of_[X_]snowfall_amount means the accumulated "depth" of snow which fell i.e. the thickness of the layer of snow at its own density. There are corresponding standard names for liquid water equivalent (lwe) thickness. + "x" indicates a vector component along the grid x-axis, positive with increasing x. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - m + + m s-1 - "Amount" means mass per unit area. The construction thickness_of_[X_]rainfall_amount means the accumulated "depth" of rainfall i.e. the thickness of a layer of liquid water having the same mass per unit area as the rainfall amount. Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. + A velocity is a vector quantity. "x" indicates a vector component along the grid x-axis, positive with increasing x. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - + m - "Amount" means mass per unit area. The construction thickness_of_[X_]snowfall_amount means the accumulated "depth" of snow which fell i.e. the thickness of the layer of snow at its own density. There are corresponding standard names for liquid water equivalent (lwe) thickness. Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. + "y" indicates a vector component along the grid y-axis, positive with increasing y. "Displacement" means the change in geospatial position of an object that has moved over time. If possible, the time interval over which the motion took place should be specified using a bounds variable for the time coordinate variable. A displacement can be represented as a vector. Such a vector should however not be interpreted as describing a rectilinear, constant speed motion but merely as an indication that the start point of the vector is found at the tip of the vector after the time interval associated with the displacement variable. A displacement does not prescribe a trajectory. Sea ice displacement can be defined as a two-dimensional vector, with no vertical component. A y displacement is calculated from the difference in the moving object's grid y coordinate between the start and end of the time interval associated with the displacement variable. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - 1 - 60 + + N m-2 + - "probability_of_X" means the chance that X is true or of at least one occurrence of X. Space and time coordinates must be used to indicate the area and time-interval to which a probability applies. + "y" indicates a vector component along the grid y-axis, positive with increasing y. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. In meteorology and oceanography, the Coriolis effect per unit mass arises solely from the earth's rotation and acts as a deflecting force, normal to the velocity, to the right of the motion in the Northern Hemisphere and to the left in the Southern Hemisphere. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Coriolis_force. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - s + + N m-2 - time - + + "y" indicates a vector component along the grid y-axis, positive with increasing y. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Several factors contribute to differences in the ocean surface level, including uneven heating, salinity variations, and currents, especially near coastal regions or ice shelves. Differences in surface level result in sea-surface tilt, a force that influences the ice motion. Reference: National Snow and Ice Data Center https://nsidc.org/cryosphere/seaice/processes/dynamics.html. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - W m-2 + + N m-2 - "longwave" means longwave radiation. "toa" means top of atmosphere. Adjusted forcing is the radiative flux change caused by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.) after allowance for stratospheric temperature adjustment. + "y" indicates a vector component along the grid y-axis, positive with increasing y. Internal ice stress is a measure of the compactness, or strength, of the ice. Internal ice stress usually acts as a resistance to the motion caused by the wind force. Reference: National Snow and Ice Data Center https://nsidc.org/cryosphere/seaice/processes/dynamics.html. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - W m-2 + + kg s-1 - "toa" means top of atmosphere. Adjusted forcing is the radiative flux change caused by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.) after allowance for stratospheric temperature adjustment. + "y" indicates a vector component along the grid y-axis, positive with increasing y. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - W m-2 + + m s-1 - "shortwave" means shortwave radiation. "toa" means top of atmosphere. Adjusted forcing is the radiative flux change caused by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.) after allowance for stratospheric temperature adjustment. + A velocity is a vector quantity. "y" indicates a vector component along the grid y-axis, positive with increasing y. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - - 1 + + kg m-3 - "Bidirectional_reflectance" depends on the angles of incident and measured radiation. Reflectance is the ratio of the energy of the reflected to the incident radiation. A coordinate variable of radiation_wavelength or radiation_frequency can be used to specify the wavelength or frequency, respectively, of the radiation. "toa" means top of atmosphere. toa_bidirectional_reflectance includes a factor to account for the cosine of the solar zenith angle but does not include any integration over solid angle. + Sea surface density is the density of sea water near the surface (including the part under sea-ice, if any). - + K - The brightness temperature of a body is the temperature of a black body which radiates the same power per unit solid angle per unit area. "toa" means top of atmosphere. + The sea surface foundation temperature is the water temperature that is not influenced by a thermally stratified layer of diurnal temperature variability (either by daytime warming or nocturnal cooling). The foundation temperature is named to indicate that it is the temperature from which the growth of the diurnal thermocline develops each day, noting that on some occasions with a deep mixed layer there is no clear foundation temperature in the surface layer. In general, sea surface foundation temperature will be similar to a night time minimum or pre-dawn value at depths of between approximately 1 and 5 meters. In the absence of any diurnal signal, the foundation temperature is considered equivalent to the quantity with standard name sea_surface_subskin_temperature. The sea surface foundation temperature defines a level in the upper water column that varies in depth, space, and time depending on the local balance between thermal stratification and turbulent energy and is expected to change slowly over the course of a day. If possible, a data variable with the standard name sea_surface_foundation_temperature should be used with a scalar vertical coordinate variable to specify the depth of the foundation level. Sea surface foundation temperature is measured at the base of the diurnal thermocline or as close to the water surface as possible in the absence of thermal stratification. Only in situ contact thermometry is able to measure the sea surface foundation temperature. Analysis procedures must be used to estimate sea surface foundation temperature value from radiometric satellite measurements of the quantities with standard names sea_surface_skin_temperature and sea_surface_subskin_temperature. Sea surface foundation temperature provides a connection with the historical concept of a "bulk" sea surface temperature considered representative of the oceanic mixed layer temperature that is typically represented by any sea temperature measurement within the upper ocean over a depth range of 1 to approximately 20 meters. The general term, "bulk" sea surface temperature, has the standard name sea_surface_temperature with no associated vertical coordinate axis. Sea surface foundation temperature provides a more precise, well defined quantity than "bulk" sea surface temperature and, consequently, is more representative of the mixed layer temperature. The temperature of sea water at a particular depth (other than the foundation level) should be reported using the standard name sea_water_temperature and, wherever possible, supplying a vertical coordinate axis or scalar coordinate variable. - - K + + m - The brightness temperature of a body is the temperature of a black body which radiates the same power per unit solid angle per unit area. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "toa" means top of atmosphere. + "Height_above_X" means the vertical distance above the named surface X. "Sea surface height" is a time-varying quantity. The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. (The volume enclosed between the geoid and the sea floor equals the mean volume of water in the ocean). In an ocean GCM the geoid is the surface of zero depth, or the rigid lid if the model uses that approximation. To specify which geoid or geopotential datum is being used as a reference level, a grid_mapping variable should be attached to the data variable as described in Chapter 5.6 of the CF Convention. By definition of the geoid, the global average of the time-mean sea surface height (i.e. mean sea level) above the geoid must be zero. The standard name for the height of the sea surface above mean sea level is sea_surface_height_above_mean_sea_level. The standard name for the height of the sea surface above the reference ellipsoid is sea_surface_height_above_reference_ellipsoid. - - W m-2 + + m - "toa" means top of atmosphere. Cloud radiative effect is also commonly known as "cloud radiative forcing". It is the sum of the quantities with standard names toa_shortwave_cloud_radiative_effect and toa_longwave_cloud_radiative_effect. + "Height_above_X" means the vertical distance above the named surface X. "Sea surface height" is a time-varying quantity. The "geopotential datum" is any estimated surface of constant geopotential used as a datum i.e. a reference level; for the geoid as a datum, specific standard names are available. To specify which geoid or geopotential datum is being used as a reference level, a grid_mapping variable should be attached to the data variable as described in Chapter 5.6 of the CF Convention. - - W m-2 - - rsdt - "shortwave" means shortwave radiation. "toa" means top of atmosphere. The TOA incoming shortwave flux is the radiative flux from the sun i.e. the "downwelling" TOA shortwave flux. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + m + 82 + + "Sea surface height" is a time-varying quantity. "Height_above_X" means the vertical distance above the named surface X. "Mean sea level" means the time mean of sea surface elevation at a given location over an arbitrary period sufficient to eliminate the tidal signals. The standard name for the height of the sea surface above the geoid is sea_surface_height_above_geoid. The standard name for the height of the sea surface above the reference ellipsoid is sea_surface_height_above_reference_ellipsoid. - - W m-2 + + m - "longwave" means longwave radiation. "toa" means top of atmosphere. Instantaneous forcing is the radiative flux change caused instantaneously by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.). + "Height_above_X" means the vertical distance above the named surface X. "Sea surface height" is a time-varying quantity. A reference ellipsoid is a regular mathematical figure that approximates the irregular shape of the geoid. A number of reference ellipsoids are defined for use in the field of geodesy. The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. To specify which reference ellipsoid is being used, a grid_mapping variable should be attached to the data variable as described in Chapter 5.6 of the CF Convention. The standard name for the height of the sea surface above the geoid is sea_surface_height_above_geoid. The standard name for the height of the sea surface above mean sea level is sea_surface_height_above_mean_sea_level. - - W m-2 + + m - "toa" means top of atmosphere. Instantaneous forcing is the radiative flux change caused instantaneously by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.). + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Tides are a significant contributor to the observed sea surface height; earth tide means the solid earth tide. - - W m-2 + + m - "shortwave" means shortwave radiation. "toa" means top of atmosphere. Instantaneous forcing is the radiative flux change caused instantaneously by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.). + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Tides are a significant contributor to the observed sea surface height; equilibrium ocean tide refers to the long period ocean tide. - - W m-2 + + m - "toa" means top of atmosphere. "Longwave" means longwave radiation. Cloud radiative effect is also commonly known as "cloud radiative forcing". It is the difference in radiative flux resulting from the presence of clouds, i.e. it is the difference between toa_outgoing_longwave_flux_assuming_clear_sky and toa_outgoing_longwave_flux. + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Tides are a significant contributor to the observed sea surface height; geocentric ocean tide means the sum total of ocean tide and load tide. - - W m-2 + + m - "longwave" means longwave radiation. "toa" means top of atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Tides are a significant contributor to the observed sea surface height; non equilibrium ocean tide refers to the long period ocean tide. - - W m-2 + + m - A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "longwave" means longwave radiation. "toa" means top of atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Tides are a significant contributor to the observed sea surface height; the pole tide occurs due to variations in the earth's rotation. - - W m-2 + + m - "toa" means top of atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Altimeter pulses tend to be more strongly refelected by the troughs of sea surface waves than by the crests leading to a bias in the measured sea surface height. This quantity is commonly known as "sea state bias". - - W m-2 + + m - rst - "shortwave" means shortwave radiation. "toa" means top of atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Air pressure and wind at high frequency" means variations in air pressure with periods shorter than 20 days. These give rise to corresponding variations in sea surface topography. The quantity sea_surface_height_correction_due_to_air_pressure_and_wind_at_high_frequency should be applied by adding it to the quantity with standard name altimeter_range. Additional altimeter range corrections are given by the quantities with standard names altimeter_range_correction_due_to_wet_troposphere, altimeter_range_correction_due_to_dry_troposphere, altimeter_range_correction_due_to_ionosphere and sea_surface_height_correction_due_to_air_pressure_at_low_frequency. - - W m-2 - + + m + - A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "shortwave" means shortwave radiation. "toa" means top of atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Air pressure at low frequency" means variations in air pressure with periods longer than 20 days. These give rise to corresponding variations in sea surface topography. The quantity sea_surface_height_correction_due_to_air_pressure_at_low_frequency is commonly called the "inverted barometer effect" and the correction should be applied by adding it to the quantity with standard name altimeter_range. Additional altimeter range corrections are given by the quantities with standard names altimeter_range_correction_due_to_wet_troposphere, altimeter_range_correction_due_to_dry_troposphere, altimeter_range_correction_due_to_ionosphere and sea_surface_height_correction_due_to_air_pressure_and_wind_at_high_frequency. - - W m-2 + + degree - "longwave" means longwave radiation. "toa" means top of atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The quantity with standard name sea_surface_primary_swell_wave_directional_spread is the directional width of the primary swell wave component of a sea. Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The primary swell wave is the most energetic swell wave. Directional spread is the (one-sided) directional width within a given sub-domain of the wave directional spectrum, S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. For a given mean wave (beam) direction the quantity approximates half the root mean square width about the beam axis, as derived either directly from circular moments or via the Fourier components of the wave directional spectrum. - - W m-2 + + m2 s - A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "longwave" means longwave radiation. "toa" means top of atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The quantity with standard name sea_surface_primary_swell_wave_energy_at_variance_spectral_density_maximum is the energy of the most energetic waves within the primary swell wave component of a sea. Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The primary swell wave is the most energetic swell wave. The phrase "wave_energy_at_variance_spectral_density_maximum", sometimes called peak wave energy, describes the maximum value of the wave_variance_spectral_density within a given sub-domain of the wave spectrum. - - W m-2 - 113 E178 + + degree + - "shortwave" means shortwave radiation. "toa" means top of atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The quantity with standard name sea_surface_primary_swell_wave_from_direction is the direction from which the most energetic swell waves are coming. Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The primary swell wave is the most energetic swell wave. The phrase "from_direction" is used in the construction X_from_direction and indicates the direction from which the velocity vector of X is coming. The direction is a bearing in the usual geographical sense, measured positive clockwise from due north. - - W m-2 - 114 E179 - rlut - "longwave" means longwave radiation. "toa" means top of atmosphere. The TOA outgoing longwave flux is the upwelling thermal radiative flux, often called the "outgoing longwave radiation" or "OLR". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + s + + + The quantity with standard name sea_surface_primary_swell_wave_mean_period is the mean period of the most energetic swell waves. Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The primary swell wave is the most energetic swell wave. A period is an interval of time, or the time-period of an oscillation. Wave period is the interval of time between repeated features on the waveform such as crests, troughs or upward passes through the mean level. Wave mean period is the mean period measured over the observation duration. - - W m-2 + + s - rlutcs - A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "longwave" means longwave radiation. "toa" means top of atmosphere. The TOA outgoing longwave flux is the upwelling thermal radiative flux, often called the "outgoing longwave radiation" or "OLR". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + The quantity with standard name sea_surface_primary_swell_wave_period_at_variance_spectral_density_maximum is the period of the most energetic waves within the primary swell wave component of a sea. Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The primary swell wave is the most energetic swell wave. A period is an interval of time, or the time-period of an oscillation. Wave period is the interval of time between repeated features on the waveform such as crests, troughs or upward passes through the mean level. The phrase "wave_period_at_variance_spectral_density_maximum", sometimes called peak wave period, describes the period of the most energetic waves within a given sub-domain of the wave spectrum. - - W m-2 + + m - rsut - "shortwave" means shortwave radiation. "toa" means top of atmosphere. The TOA outgoing shortwave flux is the reflected and scattered solar radiative flux i.e. the "upwelling" TOA shortwave flux, sometimes called the "outgoing shortwave radiation" or "OSR". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The primary swell wave is the most energetic swell wave. Significant wave height is a statistic computed from wave measurements and corresponds to the average height of the highest one third of the waves, where the height is defined as the vertical distance from a wave trough to the following wave crest. - - W m-2 + + 1e-3 - rsutcs - A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "shortwave" means shortwave radiation. "toa" means top of atmosphere. The TOA outgoing shortwave flux is the reflected and scattered solar radiative flux i.e. the "upwelling" TOA shortwave flux, sometimes called the "outgoing shortwave radiation" or "OSR". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + Sea surface salinity is the salt content of sea water close to the sea surface, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and the units attribute should normally be given as 1e-3 or 0.001 i.e. parts per thousand. Sea surface salinity is often abbreviated as "SSS". For the salinity of sea water at a particular depth or layer, a data variable of "sea_water_salinity" or one of the more precisely defined salinities should be used with a vertical coordinate axis. There are standard names for the precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. - - W m-2 + + degree - "toa" means top of atmosphere. "Shortwave" means shortwave radiation. Cloud radiative effect is also commonly known as "cloud radiative forcing". It is the difference in radiative flux resulting from the presence of clouds, i.e. the difference between toa_net_downward_shortwave_flux and toa_net_downward_shortwave_flux_assuming_clear_sky. + The quantity with standard name sea_surface_secondary_swell_wave_directional_spread is the directional width of the secondary swell wave component of a sea. Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The secondary swell wave is the second most energetic wave in the low frequency portion of a bimodal wave frequency spectrum. Directional spread is the (one-sided) directional width within a given sub-domain of the wave directional spectrum, S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. For a given mean wave (beam) direction the quantity approximates half the root mean square width about the beam axis, as derived either directly from circular moments or via the Fourier components of the wave directional spectrum. - - kg m-2 + + m2 s - "Amount" means mass per unit area. + The quantity with standard name sea_surface_secondary_swell_wave_energy_at_variance_spectral_density_maximum is the energy of the most energetic waves within the secondary swell wave component of a sea. Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The secondary swell wave is the second most energetic wave in the low frequency portion of a bimodal wave frequency spectrum. The phrase "wave_energy_at_variance_spectral_density_maximum", sometimes called peak wave energy, describes the maximum value of the wave_variance_spectral_density within a given sub-domain of the wave spectrum. - - kg m-2 s-1 + + degree - In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The quantity with standard name sea_surface_secondary_swell_wave_from_direction is the direction from which the second most energetic swell waves are coming. Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The secondary swell wave is the second most energetic wave in the low frequency portion of a bimodal wave frequency spectrum. The phrase "from_direction" is used in the construction X_from_direction and indicates the direction from which the velocity vector of X is coming. The direction is a bearing in the usual geographical sense, measured positive clockwise from due north. - - W m-2 + + s - "longwave" means longwave radiation. Adjusted forcing is the radiative flux change caused by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.) after allowance for stratospheric temperature adjustment. + The quantity with standard name sea_surface_secondary_swell_wave_mean_period is the mean period of the second most energetic swell waves. Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The secondary swell wave is the second most energetic wave in the low frequency portion of a bimodal wave frequency spectrum. A period is an interval of time, or the time-period of an oscillation. Wave period is the interval of time between repeated features on the waveform such as crests, troughs or upward passes through the mean level. Wave mean period is the mean period measured over the observation duration. - - W m-2 + + s - Adjusted forcing is the radiative flux change caused by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.) after allowance for stratospheric temperature adjustment. + The quantity with standard name sea_surface_secondary_swell_wave_period_at_variance_spectral_density_maximum is the period of the most energetic waves within the secondary swell wave component of a sea. Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The secondary swell wave is the second most energetic wave in the low frequency portion of a bimodal wave frequency spectrum. A period is an interval of time, or the time-period of an oscillation. Wave period is the interval of time between repeated features on the waveform such as crests, troughs or upward passes through the mean level. The phrase "wave_period_at_variance_spectral_density_maximum", sometimes called peak wave period, describes the period of the most energetic waves within a given sub-domain of the wave spectrum. - - W m-2 + + m - "shortwave" means shortwave radiation. Adjusted forcing is the radiative flux change caused by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.) after allowance for stratospheric temperature adjustment. + Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The secondary swell wave is the second most energetic wave in the low frequency portion of a bimodal wave frequency spectrum. Significant wave height is a statistic computed from wave measurements and corresponds to the average height of the highest one third of the waves, where the height is defined as the vertical distance from a wave trough to the following wave crest. - - Pa + + K - + The sea surface skin temperature is the temperature measured by an infrared radiometer typically operating at wavelengths in the range 3.7 - 12 micrometers. It represents the temperature within the conductive diffusion-dominated sub-layer at a depth of approximately 10 - 20 micrometers below the air-sea interface. Measurements of this quantity are subject to a large potential diurnal cycle including cool skin layer effects (especially at night under clear skies and low wind speed conditions) and warm layer effects in the daytime. - + K - Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + The sea surface subskin temperature is the temperature at the base of the conductive laminar sub-layer of the ocean surface, that is, at a depth of approximately 1 - 1.5 millimeters below the air-sea interface. For practical purposes, this quantity can be well approximated to the measurement of surface temperature by a microwave radiometer operating in the 6 - 11 gigahertz frequency range, but the relationship is neither direct nor invariant to changing physical conditions or to the specific geometry of the microwave measurements. Measurements of this quantity are subject to a large potential diurnal cycle due to thermal stratification of the upper ocean layer in low wind speed high solar irradiance conditions. - - m + + degree - Altitude is the (geometric) height above the geoid, which is the reference geopotential surface. The geoid is similar to mean sea level. + Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The phrase "from_direction" is used in the construction X_from_direction and indicates the direction from which the velocity vector of X is coming. The direction is a bearing in the usual geographical sense, measured positive clockwise from due north. - - W m-2 + + s - "longwave" means longwave radiation. Downwelling radiation is radiation from above. It does not mean "net downward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + A period is an interval of time, or the time-period of an oscillation. Wave period is the interval of time between repeated features on the waveform such as crests, troughs or upward passes through the mean level. Wave mean period is the mean period measured over the observation duration. Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. - - W m-2 + + s - "longwave" means longwave radiation. Instantaneous forcing is the radiative flux change caused instantaneously by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.). + The swell wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S can be integrated over direction to give S1= integral(S dtheta). Frequency moments, M(n) of S1 can then be calculated as follows: M(n) = integral(S1 f^n df), where f^n is f to the power of n. The first wave period, T(m1), is calculated as the ratio M(0)/M(1). - - W m-2 + + s - Instantaneous forcing is the radiative flux change caused instantaneously by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.). + The swell wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S can be integrated over direction to give S1= integral(S dtheta). Frequency moments, M(n) of S1 can then be calculated as follows: M(n) = integral(S1 f^n df), where f^n is f to the power of n. The inverse wave period, T(m-1), is calculated as the ratio M(-1)/M(0). - - W m-2 + + s - "shortwave" means shortwave radiation. Instantaneous forcing is the radiative flux change caused instantaneously by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.). + The swell wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S can be integrated over direction to give S1= integral(S dtheta). Frequency moments, M(n) of S1 can then be calculated as follows: M(n) = integral(S1 f^n df), where f^n is f to the power of n. The second wave period, T(m2), is calculated as the square root of the ratio M(0)/M(2). - - W m-2 - + + s + 106 - "longwave" means longwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + A period is an interval of time, or the time-period of an oscillation. Swell waves are waves on the ocean surface. - - W m-2 - + + m + 105 - "shortwave" means shortwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. Significant wave height is a statistic computed from wave measurements and corresponds to the average height of the highest one third of the waves, where the height is defined as the vertical distance from a wave trough to the following wave crest. - - W m-2 - + + degree + 104 - "shortwave" means shortwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The phrase "to_direction" is used in the construction X_to_direction and indicates the direction towards which the velocity vector of X is headed. The direction is a bearing in the usual geographical sense, measured positive clockwise from due north. - - mol m-2 + + K - "Content" indicates a quantity per unit area. The "troposphere content" of a quantity refers to the vertical integral from the surface to the tropopause. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for bromine_monoxide is BrO. + Sea surface temperature is usually abbreviated as "SST". It is the temperature of sea water near the surface (including the part under sea-ice, if any). More specific terms, namely sea_surface_skin_temperature, sea_surface_subskin_temperature, and surface_termperature are available for the skin, subskin, and interface temperature. respectively. For the temperature of sea water at a particular depth or layer, a data variable of sea_water_temperature with a vertical coordinate axis should be used.’ - - mol m-2 + + degree - "Content" indicates a quantity per unit area. The "troposphere content" of a quantity refers to the vertical integral from the surface to the tropopause. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. + The quantity with standard name sea_surface_tertiary_swell_wave_directional_spread is the directional width of the tertiary swell wave component of a sea. Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The tertiary swell wave is the third most energetic swell wave. Directional spread is the (one-sided) directional width within a given sub-domain of the wave directional spectrum, S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. For a given mean wave (beam) direction the quantity approximates half the root mean square width about the beam axis, as derived either directly from circular moments or via the Fourier components of the wave directional spectrum. - - mol m-2 + + m2 s - "Content" indicates a quantity per unit area. The "troposphere content" of a quantity refers to the vertical integral from the surface to the tropopause. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for glyoxal is CHOCHO. The IUPAC name for glyoxal is ethanedial. + The quantity with standard name sea_surface_tertiary_swell_wave_energy_at_variance_spectral_density_maximum is the energy of the most energetic waves within the tertiary swell wave component of a sea. Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The tertiary swell wave is the third most energetic swell wave. The phrase "wave_energy_at_variance_spectral_density_maximum", sometimes called peak wave energy, describes the maximum value of the wave_variance_spectral_density within a given sub-domain of the wave spectrum. - - mol m-2 + + degree - "Content" indicates a quantity per unit area. The "troposphere content" of a quantity refers to the vertical integral from the surface to the tropopause. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for iodine_monoxide is IO. + The quantity with standard name sea_surface_tertiary_swell_wave_from_direction is the direction from which the third most energetic swell waves are coming. Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The tertiary swell wave is the third most energetic swell wave. The phrase "from_direction" is used in the construction X_from_direction and indicates the direction from which the velocity vector of X is coming. The direction is a bearing in the usual geographical sense, measured positive clockwise from due north. - - mol m-2 + + s - "Content" indicates a quantity per unit area. The "troposphere content" of a quantity refers to the vertical integral from the surface to the tropopause. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for nitrogen_dioxide is NO2. + The quantity with standard name sea_surface_tertiary_swell_wave_mean_period is the mean period of the third most energetic swell waves. Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The tertiary swell wave is the third most energetic swell wave. A period is an interval of time, or the time-period of an oscillation. Wave period is the interval of time between repeated features on the waveform such as crests, troughs or upward passes through the mean level. Wave mean period is the mean period measured over the observation duration. - - mol m-2 + + s - "Content" indicates a quantity per unit area. The "troposphere content" of a quantity refers to the vertical integral from the surface to the tropopause. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for ozone is O3. The IUPAC name for ozone is trioxygen. + The quantity with standard name sea_surface_tertiary_swell_wave_period_at_variance_spectral_density_maximum is the period of the most energetic waves within the tertiary swell wave component of a sea. Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The tertiary swell wave is the third most energetic swell wave. A period is an interval of time, or the time-period of an oscillation. Wave period is the interval of time between repeated features on the waveform such as crests, troughs or upward passes through the mean level. The phrase "wave_period_at_variance_spectral_density_maximum", sometimes called peak wave period, describes the period of the most energetic waves within a given sub-domain of the wave spectrum. - - mol m-2 + + m - "Content" indicates a quantity per unit area. The "troposphere content" of a quantity refers to the vertical integral from the surface to the tropopause. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for suflur_dioxide is SO2. + Swell waves are waves on the ocean surface and are the low frequency portion of a bimodal wave frequency spectrum. The tertiary swell wave is the third most energetic swell wave. Significant wave height is a statistic computed from wave measurements and corresponds to the mean height of the highest one third of the waves, where the height is defined as the vertical distance from a wave trough to the following wave crest. - - m s-1 - 40 + + degree + - A velocity is a vector quantity. "Upward" indicates a vector component which is positive when directed upward (negative downward). Upward air velocity is the vertical component of the 3D air velocity vector. + Directional spread is the (one-sided) directional width within a given sub-domain of the wave directional spectrum, S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. For a given mean wave (beam) direction the quantity approximates half the root mean square width about the beam axis, as derived either directly from circular moments or via the Fourier components of the wave directional spectrum. - - W m-2 + + m2 s rad-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Upward" indicates a vector component which is positive when directed upward (negative downward). Dry static energy is the sum of enthalpy and potential energy (itself the sum of gravitational and centripetal potential energy). Enthalpy can be written either as (1) CpT, where Cp is heat capacity at constant pressure, T is absolute temperature, or (2) U+pV, where U is internal energy, p is pressure and V is volume. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Sea surface wave directional variance spectral density is the variance of the amplitude of the waves within given ranges of direction and wave frequency. - - Pa + + m2 s - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Upward" indicates a vector component which is positive when directed upward (negative downward). "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Upward eastward" indicates the ZX component of a tensor. An upward eastward momentum flux is an upward flux of eastward momentum, which accelerates the upper medium eastward and the lower medium westward. Momentum flux is dimensionally equivalent to stress and pressure. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The total upward eastward momentum flux due to gravity waves is the sum of the fluxes due to orographic gravity waves and nonorographic waves. The upward eastward momentum flux due to orographic gravity waves has the standard name upward_eastward_momentum_flux_in_air_due_to_orographic_gravity_waves. The total upward eastward momentum flux due to nonorographic gravity waves is the sum of the fluxes due to eastward and westward propagating waves. The latter has the standard name upward_eastward_momentum_flux_in_air_due_to_nonorographic_westward_gravity_waves. + The wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S has the standard name sea_surface_wave_directional_variance_spectral_density. S can be integrated over direction to give S1= integral(S dtheta) and this quantity has the standard name sea_surface_wave_variance_spectral_density. The quantity with standard name sea_surface_wave_energy_at_variance_spectral_density_maximum, sometimes called peak wave energy, is the maximum value of the variance spectral density (max(S1)). - - Pa + + degree - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Upward" indicates a vector component which is positive when directed upward (negative downward). "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Upward eastward" indicates the ZX component of a tensor. An upward eastward momentum flux is an upward flux of eastward momentum, which accelerates the upper medium eastward and the lower medium westward. Momentum flux is dimensionally equivalent to stress and pressure. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The total upward eastward momentum flux due to gravity waves is the sum of the fluxes due to orographic gravity waves and nonorographic waves. The upward eastward momentum flux due to orographic gravity waves has the standard name upward_eastward_momentum_flux_in_air_due_to_orographic_gravity_waves. The total upward eastward momentum flux due to nonorographic gravity waves is the sum of the fluxes due to eastward and westward propagating waves. The former has the standard name upward_eastward_momentum_flux_in_air_due_to_nonorographic_eastward _gravity_waves. + The phrase "from_direction" is used in the construction X_from_direction and indicates the direction from which the velocity vector of X is coming. The direction is a bearing in the usual geographical sense, measured positive clockwise from due north. - - Pa + + degree - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Upward" indicates a vector component which is positive when directed upward (negative downward). "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Upward eastward" indicates the ZX component of a tensor. An upward eastward momentum flux is an upward flux of eastward momentum, which accelerates the upper medium eastward and the lower medium westward. Momentum flux is dimensionally equivalent to stress and pressure. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The total upward eastward momentum flux due to gravity waves is the sum of the fluxes due to orographic gravity waves and nonorographic waves. The total upward eastward momentum flux due to nonorographic gravity waves is the sum of the fluxes due to eastward and westward propagating waves. These quantities have the standard names upward_eastward_momentum_flux_in_air_due_to_nonorographic_eastward_gravity_waves and upward_eastward_momentum_flux_in_air_due_to_nonorographic_westward_gravity_waves, respectively. + The quantity with standard name sea_surface_wave_from_direction_at_variance_spectral_density_maximum is the direction from which the most energetic waves are coming. The spectral peak is the most energetic wave in the total wave spectrum. The phrase "from_direction" is used in the construction X_from_direction and indicates the direction from which the velocity vector of X is coming. The direction is a bearing in the usual geographical sense, measured positive clockwise from due north. The wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S has the standard name sea_surface_wave_directional_variance_spectral_density. S can be integrated over direction to give S1= integral(S dtheta) and this quantity has the standard name sea_surface_wave_variance_spectral_density. - - Pa + + m - "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Upward" indicates a vector component which is positive when directed upward (negative downward). "Upward eastward" indicates the ZX component of a tensor. An upward eastward stress is an upward flux of eastward momentum, which accelerates the upper medium eastward and the lower medium westward. + The crest is the highest point of a wave. Crest height is the vertical distance between the crest and the calm sea surface. Maximum crest height is the maximum value measured during the observation period. - - m3 s-2 + + m - "Eliassen Palm flux" is a widely used vector in the meridional plane, and the divergence of this flux appears as a forcing in the Transformed Eulerian mean formulation of the zonal mean zonal wind equation. "Upward" indicates a vector component which is positive when directed upward (negative downward). + Wave height is defined as the vertical distance from a wave trough to the following wave crest. The maximum wave height is the greatest trough to crest distance measured during the observation period. - - W m-2 + + s - "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The maximum wave period is the longest wave period measured during the observation period. A period is an interval of time, or the time-period of an oscillation. Wave period is the interval of time between repeated features on the waveform such as crests, troughs or upward passes through the mean level. - - W m-2 + + 1 - ground_level means the land surface (beneath the snow and surface water, if any). "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Wave steepness is defined as the ratio of the wave height divided by the wavelength. Maximum wave steepness is the maximum value measured during the observation period. Wave height is defined as the vertical distance from a wave trough to the following wave crest. The wavelength is the horizontal distance between repeated features on the waveform such as crests, troughs or upward passes through the mean level. - - W m-2 + + m - ground_level means the land surface (beneath the snow and surface water, if any). "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The trough is the lowest point of a wave. Trough depth is the vertical distance between the trough and the calm sea surface. Maximum trough depth is the maximum value measured during the observation period. - - W m-2 + + m - "Upward" indicates a vector component which is positive when directed upward (negative downward). The vertical heat flux in air is the sum of all heat fluxes i.e. radiative, latent and sensible. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Wave height is defined as the vertical distance from a wave trough to the following wave crest. The mean wave height is the mean trough to crest distance measured during the observation period. - - W m-2 + + m - "Upward" indicates a vector component which is positive when directed upward (negative downward). The latent heat flux is the exchange of heat across a surface on account of evaporation and condensation (including sublimation and deposition). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Wave height is defined as the vertical distance from a wave trough to the following wave crest. The height of the highest tenth is defined as the mean of the highest ten per cent of trough to crest distances measured during the observation period. - - kg m-2 s-1 + + s - "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + A period is an interval of time, or the time-period of an oscillation. Wave period is the interval of time between repeated features on the waveform such as crests, troughs or upward passes through the mean level. Wave mean period is the mean period measured over the observation duration. - - Pa + + s - "Northward" indicates a vector component which is positive when directed northward (negative southward). "Upward" indicates a vector component which is positive when directed upward (negative downward). "Upward northward" indicates the ZY component of a tensor. An upward northward stress is an upward flux of northward momentum, which accelerates the upper medium northward and the lower medium southward. + The wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S has the standard name sea_surface_wave_directional_variance_spectral_density. S can be integrated over direction to give S1= integral(S dtheta) and this quantity has the standard name sea_surface_wave_variance_spectral_density. Frequency moments, M(n) of S1 can then be calculated as follows: M(n) = integral(S1 f^n df), where f^n is f to the power of n. The first wave period, T(m1) is calculated as the ratio M(0)/M(1). - - kg s-1 + + s - "Upward" indicates a vector component which is positive when directed upward (negative downward). + The wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S has the standard name sea_surface_wave_directional_variance_spectral_density. S can be integrated over direction to give S1= integral(S dtheta) and this quantity has the standard name sea_surface_wave_variance_spectral_density. Frequency moments, M(n) of S1 can then be calculated as follows: M(n) = integral(S1 f^n df), where f^n is f to the power of n. The inverse wave period, T(m-1), is calculated as the ratio M(-1)/M(0). - - W m-2 + + s - "Upward" indicates a vector component which is positive when directed upward (negative downward). The sea ice basal heat flux is the vertical heat flux (apart from radiation i.e. "diffusive") in sea water at the base of the sea ice. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S has the standard name sea_surface_wave_directional_variance_spectral_density. S can be integrated over direction to give S1= integral(S dtheta) and this quantity has the standard name sea_surface_wave_variance_spectral_density. Frequency moments, M(n) of S1 can then be calculated as follows: M(n) = integral(S1 f^n df), where f^n is f to the power of n. The second wave period, T(m2) is calculated as the square root of the ratio M(0)/M(2). - - m s-1 + + s - A velocity is a vector quantity. "Upward" indicates a vector component which is positive when directed upward (negative downward). + Wave mean period is the mean period measured over the observation duration. The quantity with standard name sea_surface_wave_mean_period_of_highest_tenth is the mean period of the highest one-tenth of waves during the observation duration. A period is an interval of time, or the time-period of an oscillation. Wave period is the interval of time between repeated features on the waveform such as crests, troughs or upward passes through the mean level. - - W m-2 + + s - "Upward" indicates a vector component which is positive when directed upward (negative downward). The sensible heat flux, also called "turbulent" heat flux, is the exchange of heat caused by the motion of air. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + A period is an interval of time, or the time-period of an oscillation. The sea_surface_wave_period_at_variance_spectral_density_maximum, sometimes called peak wave period, is the period of the most energetic waves in the total wave spectrum at a specific location. - - kg m-2 s-1 + + s - "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Wave period of the highest wave is the period determined from wave crests corresponding to the greatest vertical distance above mean level during the observation period. A period is an interval of time, or the time-period of an oscillation. Wave period is the interval of time between repeated features on the waveform such as crests, troughs or upward passes through the mean level. - - kg m-2 s-1 - + + m + 100 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Significant wave height is a statistic computed from wave measurements and corresponds to the average height of the highest one third of the waves, where the height is defined as the vertical distance from a wave trough to the following wave crest. - - Pa + + s - "x" indicates a vector component along the grid x-axis, positive with increasing x. "Upward" indicates a vector component which is positive when directed upward (negative downward). + Significant wave period is a statistic computed from wave measurements and corresponds to the mean wave period of the highest one third of the waves. A period is an interval of time, or the time-period of an oscillation. Wave period is the interval of time between repeated features on the waveform such as crests, troughs or upward passes through the mean level. - - Pa + + m s-1 - "y" indicates a vector component along the grid y-axis, positive with increasing y. "Upward" indicates a vector component which is positive when directed upward (negative downward). + A velocity is a vector quantity. "x" indicates a vector component along the grid x-axis, positive with increasing x. The Stokes drift velocity is the average velocity when following a specific fluid parcel as it travels with the fluid flow. For instance, a particle floating at the free surface of water waves, experiences a net Stokes drift velocity in the direction of wave propagation. - - W m-2 + + m s-1 - "longwave" means longwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + A velocity is a vector quantity. "y" indicates a vector component along the grid x-axis, positive with increasing y. The Stokes drift velocity is the average velocity when following a specific fluid parcel as it travels with the fluid flow. For instance, a particle floating at the free surface of water waves, experiences a net Stokes drift velocity in the direction of wave propagation. - - W m-2 + + degree - Upwelling radiation is radiation from below. It does not mean "net upward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "longwave" means longwave radiation. + The phrase "to_direction" is used in the construction X_to_direction and indicates the direction towards which the velocity vector of X is headed. The direction is a bearing in the usual geographical sense, measured positive clockwise from due north. - - W m-2 sr-1 + + m2 s - "longwave" means longwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + Sea surface wave variance spectral density is the variance of wave amplitude within a range of wave frequency. - - W m-2 + + degree - "shortwave" means shortwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The quantity with standard name sea_surface_wind_wave_directional_spread is the directional width of the wind wave component of a sea. Wind waves are waves on the ocean surface and are the high frequency portion of a bimodal wave frequency spectrum. Directional spread is the (one-sided) directional width within a given sub-domain of the wave directional spectrum, S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. For a given mean wave (beam) direction the quantity approximates half the root mean square width about the beam axis, as derived either directly from circular moments or via the Fourier components of the wave directional spectrum. - - W m-2 + + m2 s - Upwelling radiation is radiation from below. It does not mean "net upward". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "shortwave" means shortwave radiation. + The quantity with standard name sea_surface_wind_wave_energy_at_variance_spectral_density_maximum is the energy of the most energetic waves within the wind wave component of a sea. Wind waves are waves on the ocean surface and are the high frequency portion of a bimodal wave frequency spectrum. The phrase "wave_energy_at_variance_spectral_density_maximum", sometimes called peak wave energy, describes the maximum value of the wave_variance_spectral_density within a given sub-domain of the wave spectrum. - - W m-2 sr-1 + + degree - "shortwave" means shortwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + Wind waves are waves on the ocean surface and are the high frequency portion of a bimodal wave frequency spectrum. The phrase "from_direction" is used in the construction X_from_direction and indicates the direction from which the velocity vector of X is coming. The direction is a bearing in the usual geographical sense, measured positive clockwise from due north. - - W m-2 m-1 sr-1 + + s - Upwelling radiation is radiation from below. It does not mean "net upward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + A period is an interval of time, or the time-period of an oscillation. Wave period is the interval of time between repeated features on the waveform such as crests, troughs or upward passes through the mean level. Wave mean period is the mean period measured over the observation duration. Wind waves are waves on the ocean surface and are the high frequency portion of a bimodal wave frequency spectrum. - - W m-2 m-1 + + s - Upwelling radiation is radiation from below. It does not mean "net upward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The wind wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S can be integrated over direction to give S1= integral(S dtheta) . Frequency moments, M(n) of S1 can then be calculated as follows: M(n) = integral(S1 f^n df), where f^n is f to the power of n. The first wave period, T(m1) is calculated as the ratio M(0)/M(1). - - W m-2 m-1 + + s - Upwelling radiation is radiation from below. It does not mean "net upward". "spectral" means per unit wavelength or as a function of wavelength; spectral quantities are sometimes called "monochromatic". Radiation wavelength has standard name radiation_wavelength. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. - - - - 1 - 87 - - "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. "Vegetation" means any plants e.g. trees, shrubs, grass. + The wind wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S can be integrated over direction to give S1= integral(S dtheta). Frequency moments, M(n) of S1 can then be calculated as follows: M(n) = integral(S1 f^n df), where f^n is f to the power of n. The inverse wave period, T(m-1), is calculated as the ratio M(-1)/M(0). - - kg m-2 + + s - "Content" indicates a quantity per unit area. "Vegetation" means any plants e.g. trees, shrubs, grass. + The wind wave directional spectrum can be written as a five dimensional function S(t,x,y,f,theta) where t is time, x and y are horizontal coordinates (such as longitude and latitude), f is frequency and theta is direction. S can be integrated over direction, thus S1= integral(S dtheta). Frequency moments, M(n) of S1 can then be calculated as follows: M(n) = integral(S1 f^n df), where f^n is f to the power of n. The second wave period, T(m2), is calculated as the square root of the ratio M(0)/M(2). - - m2 s-1 - + + s + 103 - The vertical_component_of_ocean_xy_tracer_diffusivity means the vertical component of the diffusivity of tracers in the ocean due to lateral mixing. This quantity could appear in formulations of lateral diffusivity in which "lateral" does not mean "iso-level", e.g. it would not be used for isopycnal diffusivity. "Tracer diffusivity" means the diffusivity of heat and salinity due to motion which is not resolved on the grid scale of the model. + A period is an interval of time, or the time-period of an oscillation. Wind waves are waves on the ocean surface. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) - - kg m-2 s-1 + + s - The virtual_salt_flux_into_sea_water_due_to_process is the salt flux that would have the same effect on the sea surface salinity as water_flux_out_of_sea_water_due_to_process. Flux correction is also called "flux adjustment". A positive flux correction is downward i.e. added to the ocean. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The quantity with standard name sea_surface_wind_wave_period_at_variance_spectral_density_maximum is the period of the most energetic waves within the wind wave component of a sea. Wind waves are waves on the ocean surface and are the high frequency portion of a bimodal wave frequency spectrum. A period is an interval of time, or the time-period of an oscillation. Wave period is the interval of time between repeated features on the waveform such as crests, troughs or upward passes through the mean level. The phrase "wave_period_at_variance_spectral_density_maximum", sometimes called peak wave period, describes the period of the most energetic waves within a given sub-domain of the wave spectrum. - - kg m-2 s-1 - + + m + 102 - The virtual_salt_flux_into_sea_water is the salt flux that would have the same effect on the sea surface salinity as the water_flux_out_of_sea_water. It includes the effects of precipitation, evaporation, river outflow, sea-ice and any water flux relaxation(s) and correction(s) that may have been applied. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Wind waves are waves on the ocean surface and are the high frequency portion of a bimodal wave frequency spectrum. Significant wave height is a statistic computed from wave measurements and corresponds to the average height of the highest one third of the waves, where the height is defined as the vertical distance from a wave trough to the following wave crest. - - kg m-2 s-1 - + + degree + 101 - The virtual_salt_flux_into_sea_water_due_to_process is the salt flux that would have the same effect on the sea surface salinity as water_flux_out_of_sea_water_due_to_process. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Wind waves are waves on the ocean surface and are the high frequency portion of a bimodal wave frequency spectrum. The phrase "to_direction" is used in the construction X_to_direction and indicates the direction towards which the velocity vector of X is headed. The direction is a bearing in the usual geographical sense, measured positive clockwise from due north. - - kg m-2 s-1 + + g kg-1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The virtual_salt_flux_into_sea_water_due_to_newtonian_relaxation is the salt flux that would have the same effect on the sea surface salinity as water_flux_out_of_sea_water_due_to_newtonian_relaxation. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Absolute Salinity, S_A, is defined as part of the Thermodynamic Equation of Seawater 2010 (TEOS-10) which was adopted in 2010 by the Intergovernmental Oceanographic Commission (IOC). It is the mass fraction of dissolved material in sea water. Absolute Salinity incorporates the spatial variations in the composition of sea water. This type of Absolute Salinity is also called "Density Salinity". TEOS-10 estimates Absolute Salinity as the salinity variable that, when used with the TEOS-10 expression for density, yields the correct density of a sea water sample even when the sample is not of Reference Composition. In practice, Absolute Salinity is often calculated from Practical Salinity using a spatial lookup table of pre-defined values of the Absolute Salinity Anomaly. It is recommended that the version of (TEOS-10) software and the associated Absolute Salinity Anomaly climatology be specified within metadata by attaching a comment attribute to the data variable. Reference: www.teos-10.org; Millero et al., 2008 doi: 10.1016/j.dsr.2007.10.001. There are also standard names for the precisely defined salinity quantities sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 onwards), sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Salinity quantities that do not match any of the precise definitions should be given the more general standard name of sea_water_salinity. - - kg m-2 s-1 + + degree_C - The virtual_salt_flux_into_sea_water_due_to_process is the salt flux that would have the same effect on the sea surface salinity as water_flux_out_of_sea_water_due_to_process. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + The quantity with standard name sea_water_added_conservative_temperature is a passive tracer in an ocean model whose surface flux does not come from the atmosphere but is imposed externally upon the simulated climate system. The surface flux is expressed as a heat flux and converted to a passive tracer increment as if it were a heat flux being added to conservative temperature. The passive tracer is transported within the ocean as if it were conservative temperature. The passive tracer is zero in the control climate of the model. The passive tracer records added heat, as described for the CMIP6 FAFMIP experiment (doi:10.5194/gmd-9-3993-2016), following earlier ideas. Conservative Temperature is defined as part of the Thermodynamic Equation of Seawater 2010 (TEOS-10) which was adopted in 2010 by the International Oceanographic Commission (IOC). Conservative Temperature is specific potential enthalpy (which has the standard name sea_water_specific_potential_enthalpy) divided by a fixed value of the specific heat capacity of sea water, namely cp_0 = 3991.86795711963 J kg-1 K-1. Conservative Temperature is a more accurate measure of the "heat content" of sea water, by a factor of one hundred, than is potential temperature. Because of this, it can be regarded as being proportional to the heat content of sea water per unit mass. Reference: www.teos-10.org; McDougall, 2003 doi: 10.1175/1520-0485(2003)033<0945:PEACOV>2.0.CO;2. - - kg m-2 s-1 + + degree_C - The virtual_salt_flux_into_sea_water_due_to_process is the salt flux that would have the same effect on the sea surface salinity as water_flux_out_of_sea_water_due_to_process. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sea ice thermodynamics" refers to the addition or subtraction of mass due to surface and basal fluxes, i.e., due to melting, sublimation and fusion. + The quantity with standard name sea_water_added_potential_temperature is a passive tracer in an ocean model whose surface flux does not come from the atmosphere but is imposed externally upon the simulated climate system. The surface flux is expressed as a heat flux and converted to a passive tracer increment as if it were a heat flux being added to potential temperature. The passive tracer is transported within the ocean as if it were potential temperature. The passive tracer is zero in the control climate of the model. The passive tracer records added heat, as described for the CMIP6 FAFMIP experiment (doi:10.5194/gmd-9-3993-2016), following earlier ideas. Potential temperature is the temperature a parcel of air or sea water would have if moved adiabatically to sea level pressure. - - kg m-2 s-1 + + year - The virtual_salt_flux_into_sea_water_due_to_process is the salt flux that would have the same effect on the sea surface salinity as water_flux_out_of_sea_water_due_to_process. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + "Sea water age since surface contact" means the length of time elapsed since the sea water in a grid cell was last in the surface level of an ocean model. - - K - 12 + + mol m-3 + - The virtual temperature of air is the temperature at which the dry air constituent of a parcel of moist air would have the same density as the moist air at the same pressure. + 'sea_water_alkalinity_expressed_as_mole_equivalent' is the total alkalinity equivalent concentration (including carbonate, nitrogen, silicate, and borate components). - - m - 20 + + mol m-3 + - The visibility is the distance at which something can be seen. + sea_water_alkalinity_expressed_as_mole_equivalent is the total alkalinity equivalent concentration (including carbonate, nitrogen, silicate, and borate components). In ocean biogeochemistry models, a "natural analogue" is used to simulate the effect on a modelled variable of imposing preindustrial atmospheric carbon dioxide concentrations, even when the model as a whole may be subjected to varying forcings. - - m-1 + + K - Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The volume scattering/absorption/attenuation coefficient is the fractional change of radiative flux per unit path length due to the stated process. Coefficients with canonical units of m2 s-1 i.e. multiplied by density have standard names with specific_ instead of volume_. The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength is included to specify the wavelength. + Conservative Temperature is defined as part of the Thermodynamic Equation of Seawater 2010 (TEOS-10) which was adopted in 2010 by the International Oceanographic Commission (IOC). Conservative Temperature is specific potential enthalpy (which has the standard name sea_water_specific_potential_enthalpy) divided by a fixed value of the specific heat capacity of sea water, namely cp_0 = 3991.86795711963 J kg-1 K-1. Conservative Temperature is a more accurate measure of the "heat content" of sea water, by a factor of one hundred, than is potential temperature. Because of this, it can be regarded as being proportional to the heat content of sea water per unit mass. Reference: www.teos-10.org; McDougall, 2003 doi: 10.1175/1520-0485(2003)033<0945:PEACOV>2.0.CO;2. - - m-1 + + 1e-3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The volume scattering/absorption/attenuation coefficient is the fractional change of radiative flux per unit path length due to the stated process. Coefficients with canonical units of m2 s-1 i.e. multiplied by density have standard names with specific_ instead of volume_. The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength is included to specify the wavelength. + Cox Salinity, S_C, is defined unitless as a mass fraction per mil (0/00) or "parts per thousand". S_C was the standard salinity measure from 1967 until Practical Salinity, S_P, was established with PSS-78 (1978). Chlorinity, Cl, is calculated from the conductivity of a sea water sample and since the work of the Joint Panel for Oceanographic Tables and Standards (JPOTS; 1966) is converted into Cox Salinity using S_C = 1.80655Cl. This type of salinity was called simply "salinity" from 1967 to 1978. Cox Salinity was replaced by Practical Salinity in 1978. Cox Salinity is converted to Practical Salinity following S_P = S_C, however the accuracy of this is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of the Practical Salinity Scale 1978 (PSS-78). Reference: Cox et al., 1967 doi: 10.1016/0011-7471(67)90006-X; Lyman, 1969 doi: 10.4319/lo.1969.14.6.0928; Wooster et al., 1969 doi: 10.4319/lo.1969.14.3.0437. There are standard names for the precisely defined salinity quantities sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_practical_salinity, S_P, sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_* and sea_water_reference_salinity. Salinity quantities that do not match any of the precise definitions should be given the more general standard name of sea_water_salinity. - - m-1 sr-1 + + kg m-3 - Attenuation is the sum of absorption and scattering. Attenuation is sometimes called "extinction". The attenuated backwards scattering function includes the effects of two-way attenuation by the medium between a radar source and receiver. The volume scattering function is the fraction of incident radiative flux scattered into unit solid angle per unit path length. Backwards scattering refers to the sum of scattering into all backward angles i.e. scattering_angle exceeding pi/2 radians. A scattering_angle should not be specified with this quantity. + Sea water density is the in-situ density (not the potential density). If 1000 kg m-3 is subtracted, the standard name sea_water_sigma_t should be chosen instead. - - m-1 sr-1 + + S m-1 - Attenuation is the sum of absorption and scattering. Attenuation is sometimes called "extinction". The attenuated backwards scattering function includes the effects of two-way attenuation by the medium between a radar source and receiver. The volume scattering function is the fraction of incident radiative flux scattered into unit solid angle per unit path length. Backwards scattering refers to the sum of scattering into all backward angles i.e. scattering_angle exceeding pi/2 radians. A scattering_angle should not be specified with this quantity. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. + - - m-1 + + degree - Downwelling radiation is radiation from above. It does not mean "net downward". Radiative flux is the sum of shortwave and longwave radiative fluxes. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The volume scattering/absorption/attenuation coefficient is the fractional change of radiative flux per unit path length due to the stated process. Coefficients with canonical units of m2 s-1 i.e. multiplied by density have standard names with specific_ instead of volume_. The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength is included to specify the wavelength. Attenuation is the sum of absorption and scattering. Attenuation is sometimes called "extinction". Also called "diffuse" attenuation, the attenuation of downwelling radiative flux refers to the decrease with decreasing height or increasing depth of the downwelling component of radiative flux, regardless of incident direction. + The phrase "from_direction" is used in the construction X_from_direction and indicates the direction from which the velocity vector of X is coming. The direction is a bearing in the usual geographical sense, measured positive clockwise from due north. - - m-1 + + 1e-3 - Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The volume scattering/absorption/attenuation coefficient is the fractional change of radiative flux per unit path length due to the stated process. Coefficients with canonical units of m2 s-1 i.e. multiplied by density have standard names with specific_ instead of volume_. The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength is included to specify the wavelength. Scattering of radiation is its deflection from its incident path without loss of energy. Backwards scattering refers to the sum of scattering into all backward angles i.e. scattering_angle exceeding pi/2 radians. A scattering_angle should not be specified with this quantity. + Knudsen Salinity, S_K, is defined unitless as a mass fraction per mil (0/00) or "parts per thousand", and was calculated from the titration of inorganic salts from a sample of sea water after a commission to study the problem of determining salinity and density was initiated by the International Council for the Exploration of the Sea (ICES) in 1899. S_K was the standard salinity measure until S_C (Cox Salinity) was established in 1967. Since the work of Knudsen (1901), chlorinity is converted into Knudsen Salinity using S_K = 0.030 + 1.805 Cl. This type of salinity was called simply "salinity" from 1901 to 1966. From the 1960s on, electrical conductivity began to be used to estimate the Knudsen Salinity, rather than chemical titration. Knudsen Salinity was replaced by Cox Salinity in 1967 which was in turn replaced by Practical Salinity, S_P, in 1978. Conversion of Knudsen Salinity to Practical Salinity follows S_P = (S_K - 0.03) * (1.80655 / 1.805). Reference: Knudsen, 1901; Thomas et al., 1934 doi: 10.1093/icesjms/9.1.28; Lyman, 1969 doi: 10.4319/lo.1969.14.6.0928; Wooster et al., 1969 doi: 10.4319/lo.1969.14.3.0437; Lewis, 1980 doi: 10.1109/JOE.1980.1145448; Millero et al., 2008 doi: 10.1016/j.dsr.2007.10.001. There are standard names for the precisely defined salinity quantities sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P, sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_* and sea_water_reference_salinity. Salinity quantities that do not match any of the precise definitions should be given the more general standard name of sea_water_salinity. - - m-1 + + kg - Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The volume scattering/absorption/attenuation coefficient is the fractional change of radiative flux per unit path length due to the stated process. Coefficients with canonical units of m2 s-1 i.e. multiplied by density have standard names with specific_ instead of volume_. The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength is included to specify the wavelength. Attenuation is the sum of absorption and scattering. Attenuation is sometimes called "extinction". Beam attenuation refers to the decrease of radiative flux along the direction of the incident path. It is distinguished from attenuation of the downwelling component of radiative flux from any incident direction, also called "diffuse" attenuation. + The quantity with standard name "sea_water_mass" is the total mass of liquid seawater in the global oceans, including enclosed seas. - - m -1 + + kg m-2 - The volume extinction coefficient is the fractional change of radiative flux per unit path length. Extinction is the sum of absorption and scattering, sometimes called "attenuation". "Extinction" is the term most commonly used at optical wavelengths whereas "attenuation" is more often used at radio and radar wavelengths. "Aerosol" means the suspended liquid or solid particles in air (except cloud droplets). "Ambient aerosol" is aerosol that has taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the aerosol. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + Sea_water_mass_per_unit_area is the mass per unit area of the sea water contained within each grid cell. - - 1 + + m - "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. + "Thickness" means the vertical extent of a layer. The quantity with standard name sea_water_mass_per_unit_area_expressed_as_thickness is the thickness of the water column from sea floor to surface, minus any contribution to column thickness from steric changes. The sea water density used to convert mass to thickness is assumed to be the density of water of standard temperature zero degrees Celsius and practical salinity S=35.0 unless an auxiliary scalar coordinate variable with standard name sea_water_density is used to specify an alternative value. The sum of the quantities with standard names sea_water_mass_per_unit_area_expressed_as_thickness and steric_change_in_sea_surface_height is the total thickness of the sea water column. Sea_water_mass_per_unit_area is the mass per unit area of the sea water contained within each grid cell. The extent of an individual grid cell is defined by the horizontal coordinates and any associated coordinate bounds or by a string valued auxiliary coordinate variable with a standard name of "region". - - 1 + + kg m-3 - "Condensed water" means liquid and ice. "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. + "Neutral density" is a variable designed so that a surface of constant neutral density everywhere has a local slope that is close to the local slope of the neutral tangent plane. At the sea surface in the equatorial Pacific neutral density is very close to the potential density anomaly. At other locations, this is not the case. For example, along a neutral density surface there is a difference of up to 0.14 kg/m^3 in the potential density anomaly at the outcrops in the Southern and Northern hemispheres. Refer to Jackett & McDougall (1997; Journal of Physical Oceanography, Vol 27, doi: 10.1175/1520-0485(1997)027<0237:ANDVFT>2.0.CO;2) for more information. - + 1 - "Condensed water" means liquid and ice. "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. When soil moisture equals or exceeds the critical point evapotranspiration takes place at the potential rate and is controlled by the ambient meteorological conditions (temperature, wind, relative humidity). Evapotranspiration is the sum of evaporation and plant transpiration. Potential evapotranspiration is the rate at which evapotranspiration would occur under ambient conditions from a uniformly vegetated area when the water supply is not limiting. + sea_water_pH_reported_on_total_scale is the measure of acidity of sea water, defined as the negative logarithm of the concentration of dissolved hydrogen ions plus bisulfate ions in a sea water medium; it can be measured or calculated; when measured the scale is defined according to a series of buffers prepared in artificial seawater containing bisulfate. The quantity may be written as pH(total) = -log([H+](free) + [HSO4-]). In ocean biogeochemistry models, an "abiotic analogue" is used to simulate the effect on a modelled variable when biological effects on ocean carbon concentration and alkalinity are ignored. - + 1 - "Condensed water" means liquid and ice. "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. The field capacity of soil is the maximum content of water it can retain against gravitational drainage. + sea_water_pH_reported_on_total_scale is the measure of acidity of sea water, defined as the negative logarithm of the concentration of dissolved hydrogen ions plus bisulfate ions in a sea water medium; it can be measured or calculated; when measured the scale is defined according to a series of buffers prepared in artificial seawater containing bisulfate. The quantity may be written as pH(total) = -log([H+](free) + [HSO4-]). In ocean biogeochemistry models, a "natural analogue" is used to simulate the effect on a modelled variable of imposing preindustrial atmospheric carbon dioxide concentrations, even when the model as a whole may be subjected to varying forcings. - + 1 - "Condensed water" means liquid and ice. "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. The wilting point of soil is the water content below which plants cannot extract sufficient water to balance their loss through transpiration. + 'sea_water_pH_reported_on_total_scale' is the measure of acidity of seawater, defined as the negative logarithm of the concentration of dissolved hydrogen ions plus bisulfate ions in a sea water medium; it can be measured or calculated; when measured the scale is defined according to a series of buffers prepared in artificial seawater containing bisulfate. The quantity may be written as pH(total) = -log([H+](free) + [HSO4-]). - - 1 + + kg m-3 - "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. "Condensed water" means liquid and ice. "Volume_fraction_of_condensed_water_in_soil_pores" is the ratio of the volume of condensed water in soil pores to the volume of the pores themselves. + Potential density is the density a parcel of air or sea water would have if moved adiabatically to a reference pressure, by default assumed to be sea level pressure. For sea water potential density, if 1000 kg m-3 is subtracted, the standard name sea_water_sigma_theta should be chosen instead. - - 1 + + K - "frozen_water" means ice. "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. + Potential temperature is the temperature a parcel of air or sea water would have if moved adiabatically to sea level pressure. - - 1 + + K - "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. + Potential temperature is the temperature a parcel of air or sea water would have if moved adiabatically to sea level pressure. The potential temperature at the sea floor is that adjacent to the ocean bottom, which would be the deepest grid cell in an ocean model. - - 1 + + J m-2 - "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. + The phrase "expressed_as_heat_content" means that this quantity is calculated as the specific heat capacity times density of sea water multiplied by the potential temperature of the sea water in the grid cell and integrated over depth. If used for a layer heat content, coordinate bounds should be used to define the extent of the layers. If no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is sea water the integral is assumed to be calculated over the full depth of the ocean. Potential temperature is the temperature a parcel of air or sea water would have if moved adiabatically to sea level pressure. - + 1 - "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. + Practical Salinity, S_P, is a determination of the salinity of sea water, based on its electrical conductance. The measured conductance, corrected for temperature and pressure, is compared to the conductance of a standard potassium chloride solution, producing a value on the Practical Salinity Scale of 1978 (PSS-78). This name should not be used to describe salinity observations made before 1978, or ones not based on conductance measurements. Conversion of Practical Salinity to other precisely defined salinity measures should use the appropriate formulas specified by TEOS-10. Other standard names for precisely defined salinity quantities are sea_water_absolute_salinity (S_A); sea_water_preformed_salinity (S_*), sea_water_reference_salinity (S_R); sea_water_cox_salinity (S_C), used for salinity observations between 1967 and 1977; and sea_water_knudsen_salinity (S_K), used for salinity observations between 1901 and 1966. Salinity quantities that do not match any of the precise definitions shoul + d be given the more general standard name of sea_water_salinity. Reference: www.teos-10.org; Lewis, 1980 doi:10.1109/JOE.1980.1145448. - - 1 + + g kg-1 - "ratio_of_X_to_Y" means X/Y. "stp" means standard temperature (0 degC) and pressure (101325 Pa). + Preformed Salinity, S*, is defined as part of the Thermodynamic Equation of Seawater 2010 (TEOS-10) which was adopted in 2010 by the Intergovernmental Oceanographic Commission (IOC). Preformed Salinity is a salinity variable that is designed to be as conservative as possible, by removing the estimated biogeochemical influences on the sea water composition. Preformed Salinity is Absolute Salinity, S_A (which has the standard name sea_water_absolute_salinity), minus all contributions to sea water composition from biogeochemical processes. Preformed Salinity is the mass fraction of dissolved material in sea water. Reference: www.teos-10.org; Pawlowicz et al., 2011 doi: 10.5194/os-7-363-2011; Wright et al., 2011 doi: 10.5194/os-7-1-2011. There are also standard names for the precisely defined salinity quantities sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 onwards), and sea_water_reference_salinity. Salinity quantities that do not match any of the precise definitions should be given the more general standard name of sea_water_salinity. - - m-1 + + dbar - Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The volume scattering/absorption/attenuation coefficient is the fractional change of radiative flux per unit path length due to the stated process. Coefficients with canonical units of m2 s-1 i.e. multiplied by density have standard names with specific_ instead of volume_. The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength is included to specify the wavelength. Scattering of radiation is its deflection from its incident path without loss of energy. The (range of) direction(s) of scattering can be specified by a coordinate of scattering_angle. + "Sea water pressure" is the pressure that exists in the medium of sea water. It includes the pressure due to overlying sea water, sea ice, air and any other medium that may be present. For sea water pressure excluding the pressure due to overlying media other than sea water, the standard name sea_water_pressure_due_to_sea_water should be used. - - m-1 sr-1 + + dbar - Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Scattering of radiation is its deflection from its incident path without loss of energy. The volume scattering function is the fraction of incident radiative flux scattered into unit solid angle per unit path length. The (range of) direction(s) of scattering can be specified by a coordinate of scattering_angle. + "Sea water pressure" is the pressure that exists in the medium of sea water. It includes the pressure due to overlying sea water, sea ice, air and any other medium that may be present. - - kg m-2 - 57 + + dbar + - "Amount" means mass per unit area. "Water" means water in all phases. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) + The surface called "surface" means the lower boundary of the atmosphere. "Sea water pressure" is the pressure that exists in the medium of sea water. It includes the pressure due to overlying sea water, sea ice, air and any other medium that may be present. - - kg m-2 + + dbar - "Amount" means mass per unit area. "Water" means water in all phases. "Canopy" means the plant or vegetation canopy. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) + The pressure that exists in the medium of sea water due to overlying sea water. Excludes the pressure due to sea ice, air and any other medium that may be present. For sea water pressure including the pressure due to overlying media other than sea water, the standard name sea_water_pressure should be used. - - kg m-2 s-1 + + degree_C - evspsbl - Water means water in all phases. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. Previously, the qualifier where_type was used to specify that the quantity applies only to the part of the grid box of the named type. Names containing the where_type qualifier are deprecated and newly created data should use the cell_methods attribute to indicate the horizontal area to which the quantity applies. + + The quantity with standard name sea_water_redistributed_conservative_temperature is a passive tracer in an ocean model which is subject to an externally imposed perturbative surface heat flux. The passive tracer is initialised to the conservative temperature in the control climate before the perturbation is imposed. Its surface flux is the heat flux from the atmosphere, not including the imposed perturbation, and is converted to a passive tracer increment as if it were being added to conservative temperature. The passive tracer is transported within the ocean as if it were conservative temperature. The passive tracer records redistributed heat, as described for the CMIP6 FAFMIP experiment (doi:10.5194/gmd-9-3993-2016), following earlier ideas. Conservative Temperature is defined as part of the Thermodynamic Equation of Seawater 2010 (TEOS-10) which was adopted in 2010 by the International Oceanographic Commission (IOC). Conservative Temperature is specific potential enthalpy (which has the standard name sea_water_specific_potential_enthalpy) divided by a fixed value of the specific heat capacity of sea water, namely cp_0 = 3991.86795711963 J kg-1 K-1. Conservative Temperature is a more accurate measure of the "heat content" of sea water, by a factor of one hundred, than is potential temperature. Because of this, it can be regarded as being proportional to the heat content of sea water per unit mass. Reference: www.teos-10.org; McDougall, 2003 doi: 10.1175/1520-0485(2003)033<0945:PEACOV>2.0.CO;2. - - kg m-2 s-1 + + degree_C - "Water" means water in all phases. "Canopy" means the plant or vegetation canopy. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. Previously, the qualifier where_type was used to specify that the quantity applies only to the part of the grid box of the named type. Names containing the where_type qualifier are deprecated and newly created data should use the cell_methods attribute to indicate the horizontal area to which the quantity applies. + The quantity with standard name sea_water_redistributed_potential_temperature is a passive tracer in an ocean model which is subject to an externally imposed perturbative surface heat flux. The passive tracer is initialised to the potential temperature in the control climate before the perturbation is imposed. Its surface flux is the heat flux from the atmosphere, not including the imposed perturbation, and is converted to a passive tracer increment as if it were being added to potential temperature. The passive tracer is transported within the ocean as if it were potential temperature. The passive tracer records redistributed heat, as described for the CMIP6 FAFMIP experiment (doi:10.5194/gmd-9-3993-2016), following earlier ideas. Potential temperature is the temperature a parcel of air or sea water would have if moved adiabatically to sea level pressure. - - kg m-2 s-1 + + g kg-1 - "Water" means water in all phases. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + If a sea water sample has the Reference Composition (defined in Millero et al., 2008), then its Reference Salinity is the best available estimate of its Absolute Salinity. For general purposes, Reference Salinity is (35.16504 g kg-1)/35 times Practical Salinity. Reference: www.teos-10.org; Millero et al., 2008 doi: 10.1016/j.dsr.2007.10.001. There are also standard names for the precisely defined salinity quantities sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity (used for salinity observations from 1978 onwards), sea_water_absolute_salinity, S_A, and sea_water_preformed_salinity, S_*. Salinity quantities that do not match any of the precise definitions should be given the more general standard name of sea_water_salinity. - - kg m-2 s-1 - - - "Water" means water in all phases. Flux correction is also called "flux adjustment". A positive flux correction is downward i.e. added to the ocean. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + 1e-3 + 88 + so + Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and the units attribute should normally be given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. - - kg m-2 s-1 + + 1e-3 - wfo - "Water" means water in all phases. The water flux into sea water is the freshwater entering as a result of precipitation, evaporation, river inflow, sea ice effects and water flux relaxation and correction (if applied). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + The salinity at the sea floor is that adjacent to the ocean bottom, which would be the deepest grid cell in an ocean model. Sea water salinity is the salt concentration of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and the units attribute should normally be given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. Practical salinity units are dimensionless. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. - - kg m-2 s-1 + + kg m-3 - The water flux into sea water is the freshwater entering as a result of precipitation, evaporation, river inflow, sea ice effects and water flux correction (if applied). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sea ice thermodynamics" refers to the addition or subtraction of mass due to surface and basal fluxes, i.e., due to melting, sublimation and fusion. + Sigma-t of sea water is the density of water at atmospheric pressure (i.e. the surface) having the same temperature and salinity, minus 1000 kg m-3. Note that sea water sigma is not the same quantity as the dimensionless ocean sigma coordinate (see Appendix D of the CF convention), for which there is another standard name. - - kg m-2 s-1 + + kg m-3 - The water flux into sea water is the freshwater entering as a result of precipitation, evaporation, river inflow, sea ice effects and water flux correction (if applied). The water flux into sea water from icebergs is due to the melting of the iceberg. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Sigma-t of sea water is the density of water at atmospheric pressure (i.e. the surface) having the same temperature and salinity, minus 1000 kg m-3. - - kg m-2 s-1 + + kg m-3 - "Water" means water in all phases. The water flux or volume transport into sea water from rivers is the inflow to the ocean, often applied to the surface in ocean models. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Sigma-theta of sea water is the potential density (i.e. the density when moved adiabatically to a reference pressure) of water having the same temperature and salinity, minus 1000 kg m-3. Note that sea water sigma is not the same quantity as the dimensionless ocean sigma coordinate (see Appendix D of the CF convention), for which there is another standard name. - - kg m-2 s-1 + + kg m-3 - "Water" means water in all phases, including frozen i.e. ice and snow. "Downward" indicates a vector component which is positive when directed downward (negative upward). The surface water flux is the result of precipitation and evaporation. The water flux into sea water is the freshwater entering as a result of precipitation, evaporation, river inflow, sea ice effects and water flux correction (if applied). The water flux or volume transport into sea water from rivers is the inflow to the ocean, often applied to the surface in ocean models. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. + Sigma-theta of sea water is the potential density (i.e. the density when moved adiabatically to a reference pressure) of water having the same temperature and salinity, minus 1000 kg m-3. - - kg m-2 s-1 + + J kg-1 - Water means water in all phases. The water_flux_into_sea_water_without_flux_correction is the freshwater entering as a result of precipitation, evaporation, river inflow and sea ice effects. The total water flux including any flux relaxation(s) or correction(s) is described by the standard name water_flux_into_sea_water. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The potential enthalpy of a sea water parcel is the specific enthalpy after an adiabatic and isohaline change in pressure from its in situ pressure to the sea pressure p = 0 dbar. "specific" means per unit mass. Reference: www.teos-10.org; McDougall, 2003 doi: 10.1175/1520-0485(2003)033<0945:PEACOV>2.0.CO;2. - - kg m-2 s-1 + + m s-1 + 48 + + Speed is the magnitude of velocity. + + + + K + 80 + to + Sea water temperature is the in situ temperature of the sea water. To specify the depth at which the temperature applies use a vertical coordinate variable or scalar coordinate variable. There are standard names for sea_surface_temperature, sea_surface_skin_temperature, sea_surface_subskin_temperature and sea_surface_foundation_temperature which can be used to describe data located at the specified surfaces. For observed data, depending on the period during which the observation was made, the measured in situ temperature was recorded against standard "scales". These historical scales include the International Practical Temperature Scale of 1948 (IPTS-48; 1948-1967), the International Practical Temperature Scale of 1968 (IPTS-68, Barber, 1969; 1968-1989) and the International Temperature Scale of 1990 (ITS-90, Saunders 1990; 1990 onwards). Conversion of data between these scales follows t68 = t48 - (4.4 x 10e-6) * t48(100 - t - 48); t90 = 0.99976 * t68. Observations made prior to 1948 (IPTS-48) have not been documented and therefore a conversion cannot be certain. Differences between t90 and t68 can be up to 0.01 at temperatures of 40 C and above; differences of 0.002-0.007 occur across the standard range of ocean temperatures (-10 - 30 C). The International Equation of State of Seawater 1980 (EOS-80, UNESCO, 1981) and the Practical Salinity Scale (PSS-78) were both based on IPTS-68, while the Thermodynamic Equation of Seawater 2010 (TEOS-10) is based on ITS-90. References: Barber, 1969, doi: 10.1088/0026-1394/5/2/001; UNESCO, 1981; Saunders, 1990, WOCE Newsletter, 10, September 1990. + + + + K - "Water" means water in all phases. The water_flux_out_of_sea_ice_and_sea_water is the freshwater leaving the ocean as a result of precipitation, evaporation, river outflow and any water flux relaxation(s) and correction(s) that may have been applied. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Sea water temperature is the in situ temperature of the sea water. - - kg m-2 s-1 + + degree + 47 + + The phrase "to_direction" is used in the construction X_to_direction and indicates the direction towards which the velocity vector of X is headed. The direction is a bearing in the usual geographical sense, measured positive clockwise from due north. + + + + kg s-1 - The quantity water_flux_out_of_sea_water is the quantity with standard name water_flux_into_sea_water multiplied by -1. "Water" means water in all phases. The water flux out of sea water is the freshwater leaving as a result of precipitation, evaporation, river outflow, sea-ice and any water flux relaxation(s) and correction(s) that may have been applied. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Transport across_line means that which crosses a particular line on the Earth's surface; formally this means the integral along the line of the normal component of the transport. - - kg m-2 s-1 + + 1 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The water_flux_out_of_sea_water_due_to_newtonian_relaxation is the freshwater leaving as a result of the Newtonian relaxation of the sea surface salinity. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + Turbidity is a dimensionless quantity which is expressed in NTU (Nephelometric Turbidity Units). Turbidity expressed in NTU is the proportion of white light scattered back to a transceiver by the particulate load in a body of water, represented on an arbitrary scale referenced against measurements made in the laboratory on aqueous suspensions of formazine beads. Sea water turbidity may also be measured by the quantity with standard name secchi_depth_of_sea_water. - - kg m-2 s-1 + + m3 - The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Water" means water in all phases. The water flux out of sea water is the freshwater leaving the sea water. "Sea ice thermodynamics" refers to the addition or subtraction of sea ice mass due to surface and basal fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + The quantity with standard name "sea_water_volume" is the total volume of liquid seawater in the global oceans, including enclosed seas. - - kg m-2 + + m s-1 - "Amount" means mass per unit area. "Water" means water in all phases. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) Potential evaporation is the rate at which evaporation would take place under unaltered ambient conditions (temperature, relative humidity, wind, etc.) if the supply of water were unlimited, as if from an open water surface. + A velocity is a vector quantity. "x" indicates a vector component along the grid x-axis, positive with increasing x. - - kg m-2 s-1 + + m s-1 - "Water" means water in all phases. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) Potential evaporation is the rate at which evaporation would take place under unaltered ambient conditions (temperature, relative humidity, wind, etc.) if the supply of water were unlimited, as if from an open water surface. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + A velocity is a vector quantity. "x" indicates a vector component along the grid x-axis, positive with increasing x. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized mesoscale eddies occur on a spatial scale of many tens of kilometres and an evolutionary time of weeks. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. Parameterized mesoscale eddies are represented in ocean models using schemes such as the Gent-McWilliams scheme. sea_water_x_velocity_due_to_parameterized_mesoscale_eddies is used in some parameterisations of lateral diffusion in the ocean. - - kg m-2 s-1 + + m s-1 - "Water" means water in all phases. Sublimation is the conversion of solid into vapor. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + A velocity is a vector quantity. "y" indicates a vector component along the grid y-axis, positive with increasing y. - + + m s-1 + + + A velocity is a vector quantity. "y" indicates a vector component along the grid y-axis, positive with increasing y. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized mesoscale eddies occur on a spatial scale of many tens of kilometres and an evolutionary time of weeks. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. Parameterized mesoscale eddies are represented in ocean models using schemes such as the Gent-McWilliams scheme. sea_water_y_velocity_due_to_parameterized_mesoscale_eddies is used in some parameterisations of lateral diffusion in the ocean. + + + m - 'Water surface height above reference datum' means the height of the upper surface of a body of liquid water, such as sea, lake or river, above an arbitrary reference datum. The altitude of the datum should be provided in a variable with standard name water_surface_reference_datum_altitude. The surface called "surface" means the lower boundary of the atmosphere. + Depth is the vertical distance below the surface. A Secchi disk is a patterned disk that is used to measure water transparency, also called turbidity, in oceans and lakes. The disk is lowered into the water and the depth at which the pattern is no longer visible is the called the secchi depth. Sea water turbidity may also be measured by the quantity with standard name sea_water_turbidity. - + + degree + + + sensor_azimuth_angle is the horizontal angle between the line of sight from the observation point to the sensor and a reference direction at the observation point, which is often due north. The angle is measured clockwise positive, starting from the reference direction. A comment attribute should be added to a data variable with this standard name to specify the reference direction. A standard name also exists for platform_azimuth_angle, where "platform" refers to the vehicle from which observations are made e.g. aeroplane, ship, or satellite. For some viewing geometries the sensor and the platform cannot be assumed to be close enough to neglect the difference in calculated azimuth angle. + + + + s-1 + + + sensor_band_central_radiation_frequency is the central frequency of a sensor's band, calculated as the first moment of the band's normalized spectral response function. + + + m - Altitude is the (geometric) height above the geoid, which is the reference geopotential surface. The geoid is similar to mean sea level. 'Water surface reference datum altitude' means the altitude of the arbitrary datum referred to by a quantity with standard name 'water_surface_height_above_reference_datum'. The surface called "surface" means the lower boundary of the atmosphere. + sensor_band_central_radiation_wavelength is the central wavelength of a sensor's band, calculated as the first moment of the band's normalized spectral response function. - - Pa - 55 + + m-1 + - The partial pressure of a gaseous constituent of air is the pressure which it alone would exert with unchanged temperature and number of moles per unit volume. + sensor_band_central_radiation_wavenumber is the central wavenumber of a sensor's band, calculated as the first moment of the band's normalized spectral response function. - - Pa - 56 + + + - Water vapor saturation deficit is the difference between the saturationwater vapor partial pressure and the actual water vapor partial pressure in air. + A variable with the standard name of sensor_band_identifier contains strings which give the alphanumeric identifier of a sensor band. These strings have not yet been standardised. + - - m3 s-1 + + degree - "Water" means water in all phases. The water flux or volume transport into sea water from rivers is the inflow to the ocean, often applied to the surface in ocean models. + Sensor view angle is the angle between the line of sight from the sensor and the direction straight vertically down. Zero view angle means looking directly beneath the sensor. There is no standardized sign convention for sensor_view_angle. A standard name also exists for platform_view_angle, where "platform" refers to the vehicle from which observations are made e.g. aeroplane, ship, or satellite. For some viewing geometries the sensor and the platform cannot be assumed to be close enough to neglect the difference in calculated view angle. - - s-1 + + degree - Frequency is the number of oscillations of a wave per unit time. + sensor_zenith_angle is the angle between the line of sight to the sensor and the local zenith at the observation target. This angle is measured starting from directly overhead and its range is from zero (directly overhead the observation target) to 180 degrees (directly below the observation target). Local zenith is a line perpendicular to the Earth's surface at a given location. "Observation target" means a location on the Earth defined by the sensor performing the observations. A standard name also exists for platform_zenith_angle, where "platform" refers to the vehicle from which observations are made e.g. aeroplane, ship, or satellite. For some viewing geometries the sensor and the platform cannot be assumed to be close enough to neglect the difference in calculated zenith angle. - - K + + 1 + + + "Time fraction" means a fraction of a time interval. The interval in question must be specified by the values or bounds of the time coordinate variable associated with the data. "X_time_fraction" means the fraction of the time interval during which X occurs. + + + + kg m-2 s-1 + + + Convective precipitation is that produced by the convection schemes in an atmosphere model. Some atmosphere models differentiate between shallow and deep convection. "Precipitation" in the earth's atmosphere means precipitation of water in all phases. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + 1 + + + "Single scattering albedo" is the fraction of radiation in an incident light beam scattered by the particles of an aerosol reference volume for a given wavelength. It is the ratio of the scattering and the extinction coefficients of the aerosol particles in the reference volume. A coordinate variable with a standard name of radiation_wavelength or radiation_frequency should be included to specify either the wavelength or frequency. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + + mol m-2 s-1 + + + The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. 'Sinking' is the gravitational settling of particulate matter suspended in a liquid. A sinking flux is positive downwards and is calculated relative to the movement of the surrounding fluid. Aragonite is a mineral that is a polymorph of calcium carbonate. The chemical formula of aragonite is CaCO3. Standard names also exist for calcite, another polymorph of calcium carbonate. + + + + mol m-2 s-1 + + + The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. 'Sinking' is the gravitational settling of particulate matter suspended in a liquid. A sinking flux is positive downwards and is calculated relative to the movement of the surrounding fluid. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Standard names also exist for aragonite, another polymorph of calcium carbonate. + + + + mol m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. 'Sinking' is the gravitational settling of particulate matter suspended in a liquid. A sinking flux is positive downwards and is calculated relative to the movement of the surrounding fluid. + + + + mol m-2 s-1 + + + The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. 'Sinking' is the gravitational settling of particulate matter suspended in a liquid. A sinking flux is positive downwards and is calculated relative to the movement of the surrounding fluid. + + + + mol m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. 'Sinking' is the gravitational settling of particulate matter suspended in a liquid. A sinking flux is positive downwards and is calculated relative to the movement of the surrounding fluid. + + + + mol m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. 'Sinking' is the gravitational settling of particulate matter suspended in a liquid. A sinking flux is positive downwards and is calculated relative to the movement of the surrounding fluid. + + + + mol m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. 'Sinking' is the gravitational settling of particulate matter suspended in a liquid. A sinking flux is positive downwards and is calculated relative to the movement of the surrounding fluid. + + + + kg m-2 + + + "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including content_of_soil_layer are used. Soil carbon is returned to the atmosphere as the organic matter decays. The decay process takes varying amounts of time depending on the composition of the organic matter, the temperature and the availability of moisture. A carbon "soil pool" means the carbon contained in organic matter which has a characteristic period over which it decays and releases carbon into the atmosphere. "Slow soil pool" refers to the decay of organic matter in soil with a characteristic period of more than a hundred years under reference climate conditions of a temperature of 20 degrees Celsius and no water limitations. + + + + kg m-3 - - degree - 31 + + kg m-2 + - Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) In meteorological reports, the direction of the wind vector is usually (but not always) given as the direction from which it is blowing (wind_from_direction) (westerly, northerly, etc.). In other contexts, such as atmospheric modelling, it is often natural to give the direction in the usual manner of vectors as the heading or the direction to which it is blowing (wind_to_direction) (eastward, southward, etc.) "from_direction" is used in the construction X_from_direction and indicates the direction from which the velocity vector of X is coming. + "Amount" means mass per unit area. - - W m-2 - 126 + + kg m-2 s-1 + 64 + prsn + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + m + - Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + - - m s-1 - 32 + + kg s-1 + - Speed is the magnitude of velocity. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) The wind speed is the magnitude of the wind velocity. + Transport "across_line" means that which crosses a particular line on the Earth's surface; formally this means the integral along the line of the normal component of the transport. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sea ice dynamics" refers to advection of sea ice. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. - + + 1 + + + Soil albedo is the albedo of the soil surface assuming no snow. Albedo is the ratio of outgoing to incoming shortwave irradiance, where 'shortwave irradiance' means that both the incoming and outgoing radiation are integrated across the solar spectrum. + + + + kg m-2 + + mrfso + "frozen_water" means ice. "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including content_of_soil_layer are used. + + + m s-1 - Speed is the magnitude of velocity. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) The wind speed is the magnitude of the wind velocity. A gust is a sudden brief period of high wind speed. In an observed timeseries of wind speed, the gust wind speed can be indicated by a cell_methods of maximum for the time-interval. In an atmospheric model which has a parametrised calculation of gustiness, the gust wind speed may be separately diagnosed from the wind speed. + Hydraulic conductivity is the constant k in Darcy's Law q=-k grad h for fluid flow q (volume transport per unit area i.e. velocity) through a porous medium, where h is the hydraulic head (pressure expressed as an equivalent depth of water). - - s-1 - N136 + + kg m-2 + - Speed is the magnitude of velocity. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) The wind speed is the magnitude of the wind velocity. Wind speed shear is the derivative of wind speed with respect to height. + "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including "content_of_soil_layer" are used. "C" means the element carbon and "13C" is the stable isotope "carbon-13", having six protons and seven neutrons. - - degree + + kg m-2 - Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) In meteorological reports, the direction of the wind vector is usually (but not always) given as the direction from which it is blowing (wind_from_direction) (westerly, northerly, etc.). In other contexts, such as atmospheric modelling, it is often natural to give the direction in the usual manner of vectors as the heading or the direction to which it is blowing (wind_to_direction) (eastward, southward, etc.) "to_direction" is used in the construction X_to_direction and indicates the direction towards which the velocity vector of X is headed. + "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including "content_of_soil_layer" are used. "C" means the element carbon and "14C" is the radioactive isotope "carbon-14", having six protons and eight neutrons and used in radiocarbon dating. - + kg m-2 - "Content" indicates a quantity per unit area. + "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including content_of_soil_layer are used. - + kg m-2 - "Content" indicates a quantity per unit area. "Wood debris" means dead organic matter composed of coarse wood. It is distinct from litter. + "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including "content_of_soil_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula for the ammonium cation is NH4+. The quantity with standard name soil_mass_content_of_inorganic_nitrogen_expressed_as_nitrogen is the sum of the quantities with standard names soil_mass_content_of_inorganic_ammonium_expressed_as_nitrogen and soil_mass_content_of_inorganic_nitrate_expressed_as_nitrogen. - - Pa m-1 + + kg m-2 - "component_derivative_of_X" means the derivative of X with respect to distance in the component direction, which may be northward, southward, eastward, westward, x or y. The last two indicate derivatives along the axes of the grid, whether or not they are true longitude and latitude. x_derivative_of_ocean_rigid_lid_pressure means (d/dx) of the ocean surface pressure, as derived by a rigid lid approximation, keeping the other horizontal coordinate (y, presumably) constant. + "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including "content_of_soil_layer" are used. The chemical formula for the nitrate anion is NO3-. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The quantity with standard name soil_mass_content_of_inorganic_nitrogen_expressed_as_nitrogen is the sum of the quantities with standard names soil_mass_content_of_inorganic_ammonium_expressed_as_nitrogen and soil_mass_content_of_inorganic_nitrate_expressed_as_nitrogen. - - m s-1 + + kg m-2 - "x" indicates a vector component along the grid x-axis, positive with increasing x. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including "content_of_soil_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Inorganic nitrogen" describes a family of chemical species which, in soil, usually consists of nitrate and ammonium which act as nitrogen nutrients. The quantity with standard name soil_mass_content_of_inorganic_nitrogen_expressed_as_nitrogen is the sum of the quantities with standard names soil_mass_content_of_inorganic_ammonium_expressed_as_nitrogen and soil_mass_content_of_inorganic_nitrate_expressed_as_nitrogen. - - Pa m-1 + + kg m-2 - "component_derivative_of_X" means the derivative of X with respect to distance in the component direction, which may be northward, southward, eastward, westward, x or y. The last two indicate derivatives along the axes of the grid, whether or not they are true longitude and latitude. y_derivative_of_ocean_rigid_lid_pressure means (d/dy) of the ocean surface pressure, as derived by a rigid lid approximation, keeping the other horizontal coordinate (x, presumably) constant. + "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including "content_of_soil_layer" are used. - - m s-1 + + kg m-2 + + mrsofc + "moisture" means water in all phases contained in soil. "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including content_of_soil_layer are used. The field capacity of soil is the maximum content of water it can retain against gravitational drainage. + + + + - "y" indicates a vector component along the grid y-axis, positive with increasing y. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + A variable with the standard name of soil_pool contains strings which indicate the character of the soil pool classified according to the decay rate of the organic carbon material it contains. These strings have not yet been standardised. + + + + s-1 + + + "Soil carbon" is the organic matter present in soil quantified by the mass of carbon it contains. Soil carbon is returned to the atmosphere as the organic matter decays. Each modelled soil carbon pool has a characteristic turnover time, which is modified by environmental conditions such as temperature and moisture so that the turnover time varies in space and time. The quantity with standard name soil_pool_carbon_decay_rate is defined as 1/(turnover time). The data variable should be accompanied by a string valued coordinate variable or scalar coordinate variable with standard name soil_pool. - - degree - - - Zenith angle is the angle to the local vertical; a value of zero is directly overhead. - - + + 1 + + + The soil porosity is the proportion of its total volume not occupied by soil solids. + + + + Pa + + + Soil suction is the tensile stress on water in soil due to molecular forces acting at the water-soil particle boundary. The forces may cause water to be drawn into the spaces within the soil matrix or cause it to be held in the soil without draining. Soil suction occurs in soil above the water table. + + + + K + 85 + + Soil temperature is the bulk temperature of the soil, not the surface (skin) temperature. + + + + J kg-1 K-1 + + + Thermal capacity, or heat capacity, is the amount of heat energy required to increase the temperature of 1 kg of material by 1 K. It is a property of the material. + + + + W m-1 K-1 + + + Thermal conductivity is the constant k in the formula q = -k grad T where q is the heat transfer per unit time per unit area of a surface normal to the direction of transfer and grad T is the temperature gradient. Thermal conductivity is a property of the material. + + + + 1 + + + A variable with the standard name of soil_type contains strings which indicate the character of the soil e.g. clay. These strings have not yet been standardised. Alternatively, the data variable may contain integers which can be translated to strings using flag_values and flag_meanings attributes. + + + + degree + + + Solar azimuth angle is the horizontal angle between the line of sight to the sun and a reference direction which is often due north. The angle is measured clockwise. + + + + degree + + + Solar elevation angle is the angle between the line of sight to the sun and the local horizontal. + + + + W m-2 + + + The quantity with standard name solar_irradiance, often called Total Solar Irradiance (TSI), is the radiation from the sun integrated over the whole electromagnetic spectrum and over the entire solar disk. The quantity applies outside the atmosphere, by default at a distance of one astronomical unit from the sun, but a coordinate or scalar coordinate variable of distance_from_sun can be used to specify a value other than the default. "Irradiance" means the power per unit area (called radiative flux in other standard names), the area being normal to the direction of flow of the radiant energy. + + + + W m-2 m-1 + + + The quantity with standard name solar_irradiance_per_unit_wavelength, often called Solar Spectral Irradiance (SSI), is the radiation from the sun as a function of wavelength integrated over the entire solar disk. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. The quantity applies outside the atmosphere, by default at a distance of one astronomical unit from the sun, but a coordinate or scalar coordinate variable of distance_from_sun can be used to specify a value other than the default. "Irradiance" means the power per unit area (called radiative flux in other standard names), the area being normal to the direction of flow of the radiant energy. + + + + degree + + + Solar zenith angle is the the angle between the line of sight to the sun and the local vertical. + + + + kg m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Solid precipitation refers to the precipitation of water in the solid phase. Water in the atmosphere exists in one of three phases: solid, liquid or vapor. The solid phase can exist as snow, hail, graupel, cloud ice, or as a component of aerosol. + + + + kg m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Solid precipitation refers to the precipitation of water in the solid phase. Water in the atmosphere exists in one of three phases: solid, liquid or vapor. The solid phase can exist as snow, hail, graupel, cloud ice, or as a component of aerosol. "O" means the element "oxygen" and "17O" is the stable isotope "oxygen-17". + + + + kg m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Solid precipitation refers to the precipitation of water in the solid phase. Water in the atmosphere exists in one of three phases: solid, liquid or vapor. The solid phase can exist as snow, hail, graupel, cloud ice, or as a component of aerosol. The chemical formula for water is H2O. "O" means the element "oxygen" and "18O" is the stable isotope "oxygen-18". + + + + kg m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Solid precipitation refers to the precipitation of water in the solid phase. Water in the atmosphere exists in one of three phases: solid, liquid or vapor. The solid phase can exist as snow, hail, graupel, cloud ice, or as a component of aerosol. The chemical formula for water is H2O. "H" means the element "hydrogen" and "2H" is the stable isotope "hydrogen-2", usually called "deuterium". The construction "X_containing_single_Y" means the standard name refers to only that part of X composed of molecules containing a single atom of isotope Y. + + + + kg m-2 + + + "Content" indicates a quantity per unit area. The surface called "surface" means the lower boundary of the atmosphere. + + + + s-1 + + + Frequency is the number of oscillations of a wave per unit time. + + + + W m-2 + + + Sound intensity is the sound energy per unit time per unit area. + + + + W m-2 + + + Sound intensity is the sound energy per unit time per unit area. + + + + dB + + + Sound intensity is the sound energy per unit time per unit area. Sound intensity level in air is expressed on a logarithmic scale with reference to a sound intensity of 1e-12 W m-2. LI = 10 log10(I/I0) where LI is sound intensity level, I is sound intensity and I0 is the reference sound intensity. + + + + dB + + + Sound intensity is the sound energy per unit time per unit area. Sound intensity level in water is expressed on a logarithmic scale with reference to a sound intensity of 6.7e-19 W m-2. LI = 10 log10(I/I0) where LI is sound intensity level, I is sound intensity and I0 is the reference sound intensity. + + + + Pa + + + Sound pressure is the difference from the local ambient pressure caused by a sound wave at a particular location and time. + + + + Pa + + + Sound pressure is the difference from the local ambient pressure caused by a sound wave at a particular location and time. + + + + dB + + + Sound pressure is the difference from the local ambient pressure caused by a sound wave at a particular location and time. Sound pressure level in air is expressed on a logarithmic scale with reference to a sound pressure of 2e-5 Pa. Lp = 20 log10(p/p0) where Lp is the sound pressure level, p is the rms sound pressure and p0 is the reference sound pressure. + + + + dB + + + Sound pressure is the difference from the local ambient pressure caused by a sound wave at a particular location and time. Sound pressure level in water is expressed on a logarithmic scale with reference to a sound pressure of 1e-6 Pa. Lp = 20 log10(p/p0) where Lp is the sound pressure level, p is the rms sound pressure and p0 is the reference sound pressure. + + + + + + + An auxiliary coordinate variable with a standard name of source contains string values which describe the method of production of the original data with which the coordinate variable is associated. If the data were model-generated, source should name the model and its version, as specifically as could be useful. If the data are observational, source should characterize them (e.g., "surface observation", "radiosonde"). The use of source as the standard name for an auxiliary coordinate variable permits the aggregation of data from multiple sources within a single data file. + + + + m2 s-2 + + + "specific" means per unit mass. Dry energy is the sum of dry static energy and kinetic energy. Dry static energy is the sum of enthalpy and potential energy (itself the sum of gravitational and centripetal potential energy). Enthalpy can be written either as (1) CpT, where Cp is heat capacity at constant pressure, T is absolute temperature, or (2) U+pV, where U is internal energy, p is pressure and V is volume. + + + + J kg-1 + + + "specific" means per unit mass. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) + + + + J kg-1 K-1 + + + The specific heat capacity of sea water, Cp(ocean), is used in ocean models to convert between model prognostic temperature (potential or conservative temperature) and model heat content. + + + + 1 + 51 E133 + hus + "specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. + + + + m2 s-2 + + + "specific" means per unit mass. + + + + m2 s-2 + + + "specific" means per unit mass. + + + + W kg-1 + + + "Specific" means per unit mass. "Turbulent kinetic energy" is the kinetic energy of chaotic fluctuations of the fluid flow. The dissipation of kinetic energy arises in ocean models as a result of the viscosity of sea water. + + + + m2 s-2 + + + "Specific" means per unit mass. "Turbulent kinetic energy" is the kinetic energy of chaotic fluctuations of the fluid flow. + + + + m s-1 + + + Speed is the magnitude of velocity. + + + + m s-1 + + + Speed is the magnitude of velocity. + + + + day + + + Air temperature is the bulk temperature of the air, not the surface (skin) temperature. A spell is the number of consecutive days on which the condition X_below|above_threshold is satisfied. A variable whose standard name has the form spell_length_of_days_with_X_below|above_threshold must have a coordinate variable or scalar coordinate variable with the a standard name of X to supply the threshold(s). It must have a climatological time variable, and a cell_method entry for within days which describes the processing of quantity X before the threshold is applied. A spell_length_of_days is an intensive quantity in time, and the cell_methods entry for over days can be any of the methods listed in Appendix E appropriate for intensive quantities e.g. "maximum", "minimum" or "mean". + + + + day + + + Air temperature is the bulk temperature of the air, not the surface (skin) temperature. A spell is the number of consecutive days on which the condition X_below|above_threshold is satisfied. A variable whose standard name has the form spell_length_of_days_with_X_below|above_threshold must have a coordinate variable or scalar coordinate variable with the a standard name of X to supply the threshold(s). It must have a climatological time variable, and a cell_method entry for within days which describes the processing of quantity X before the threshold is applied. A spell_length_of_days is an intensive quantity in time, and the cell_methods entry for over days can be any of the methods listed in Appendix E appropriate for intensive quantities e.g. "maximum", "minimum" or "mean". + + + + day + + + "Amount" means mass per unit area. "Precipitation" in the earth's atmosphere means precipitation of water in all phases. The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. The abbreviation "lwe" means liquid water equivalent. A spell is the number of consecutive days on which the condition X_below|above_threshold is satisfied. A variable whose standard name has the form spell_length_of_days_with_X_below|above_threshold must have a coordinate variable or scalar coordinate variable with the a standard name of X to supply the threshold(s). It must have a climatological time variable, and a cell_method entry for within days which describes the processing of quantity X before the threshold is applied. A spell_length_of_days is an intensive quantity in time, and the cell_methods entry for over days can be any of the methods listed in Appendix E appropriate for intensive quantities e.g. "maximum", "minimum" or "mean". + + + + day + + + "Amount" means mass per unit area. "Precipitation" in the earth's atmosphere means precipitation of water in all phases.The construction lwe_thickness_of_X_amount or _content means the vertical extent of a layer of liquid water having the same mass per unit area. The abbreviation "lwe" means liquid water equivalent. A spell is the number of consecutive days on which the condition X_below|above_threshold is satisfied. A variable whose standard name has the form spell_length_of_days_with_X_below|above_threshold must have a coordinate variable or scalar coordinate variable with the a standard name of X to supply the threshold(s). It must have a climatological time variable, and a cell_method entry for within days which describes the processing of quantity X before the threshold is applied. A spell_length_of_days is an intensive quantity in time, and the cell_methods entry for over days can be any of the methods listed in Appendix E appropriate for intensive quantities e.g. "maximum", "minimum" or "mean". + + + + K2 + + mptta + "square_of_X" means X*X. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + + + s-2 + N138 + + The phrase "square_of_X" means X*X. Frequency is the number of oscillations of a wave per unit time. Brunt-Vaisala frequency is also sometimes called "buoyancy frequency" and is a measure of the vertical stratification of the medium. + + + + s-2 + + + The phrase "square_of_X" means X*X. Frequency is the number of oscillations of a wave per unit time. Brunt-Vaisala frequency is also sometimes called "buoyancy frequency" and is a measure of the vertical stratification of the medium. + + + + m2 s-2 + + mpuua + "square_of_X" means X*X. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + + + m2 + + + "square_of_X" means X*X. Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. Geopotential height is the geopotential divided by the standard acceleration due to gravity. It is numerically similar to the altitude (or geometric height) and not to the quantity with standard name height, which is relative to the surface. + + + + Pa2 s-2 + + + The phrase "square_of_X" means X*X. "tendency_of_X" means derivative of X with respect to time. The Lagrangian tendency of a quantity is its rate of change following the motion of the fluid, also called the "material derivative" or "convective derivative". The Lagrangian tendency of air pressure, often called "omega", plays the role of the upward component of air velocity when air pressure is being used as the vertical coordinate. If the vertical air velocity is upwards, it is negative when expressed as a tendency of air pressure; downwards is positive. Air pressure is the force per unit area which would be exerted when the moving gas molecules of which the air is composed strike a theoretical surface of any orientation. + + + + m2 s-2 + + mpvva + "square_of_X" means X*X. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + + + m2 + + + The phrase "square_of_X" means X*X. The ocean mixed layer is the upper part of the ocean, regarded as being well-mixed. The base of the mixed layer defined by "temperature", "sigma", "sigma_theta", "sigma_t" or vertical diffusivity is the level at which the quantity indicated differs from its surface value by a certain amount. A coordinate variable or scalar coordinate variable with standard name sea_water_sigma_t_difference can be used to specify the sigma_t criterion that determines the layer thickness. Sigma-t of sea water is the density of water at atmospheric pressure (i.e. the surface) having the same temperature and salinity, minus 1000 kg m-3. "Thickness" means the vertical extent of a layer. + + + + m2 + + + The phrase "square_of_X" means X*X. "Height_above_X" means the vertical distance above the named surface X. "Sea surface height" is a time-varying quantity. The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. (The volume enclosed between the geoid and the sea floor equals the mean volume of water in the ocean). In an ocean GCM the geoid is the surface of zero depth, or the rigid lid if the model uses that approximation. To specify which geoid or geopotential datum is being used as a reference level, a grid_mapping variable should be attached to the data variable as described in Chapter 5.6 of the CF Convention. By definition of the geoid, the global average of the time-mean sea surface height (i.e. mean sea level) above the geoid must be zero. + + + + 1e-6 + + + The phrase "square_of_X" means X*X. Sea surface salinity is the salt concentration of sea water close to the sea surface, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and the units attribute should normally be given as 1e-3 or 0.001 i.e. parts per thousand. Sea surface salinity is often abbreviated as "SSS". For the salinity of sea water at a particular depth or layer, a data variable of "sea_water_salinity" or one of the more precisely defined salinities should be used with a vertical coordinate axis. There are standard names for the precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. + + + + K2 + + + Sea surface temperature is usually abbreviated as "SST". It is the temperature of sea water near the surface (including the part under sea-ice, if any), and not the skin temperature, whose standard name is surface_temperature. For the temperature of sea water at a particular depth or layer, a data variable of sea_water_temperature with a vertical coordinate axis should be used. "square_of_X" means X*X. + + + + m2 s-2 + + + "square_of_X" means X*X. A velocity is a vector quantity. "Upward" indicates a vector component which is positive when directed upward (negative downward). Upward air velocity is the vertical component of the 3D air velocity vector. + + + + kg2 s-2 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). Ocean transport means transport by all processes, both sea water and sea ice. "square_of_X" means X*X. + + + + 1 + + + A variable with the standard name of status_flag contains an indication of quality or other status of another data variable. The linkage between the data variable and the variable with the standard_name of status_flag is achieved using the ancillary_variables attribute. + + + + kg m-2 + + + "Content" indicates a quantity per unit area. The stem of a plant is the axis that bears buds and shoots with leaves and, at its basal end, roots. Its function is to carry water and nutrients. Examples include the stalk of a plant or the main trunk of a tree. + + + + kg m-2 + + + "Content" indicates a quantity per unit area. The stem of a plant is the axis that bears buds and shoots with leaves and, at its basal end, roots. Its function is to carry water and nutrients. Examples include the stalk of a plant or the main trunk of a tree. + + + + m + + + Steric sea level change is caused by changes in sea water density due to changes in temperature (thermosteric) and salinity (halosteric). "Mean sea level" means the time mean of sea surface elevation at a given location over an arbitrary period sufficient to eliminate the tidal signals. Zero mean sea level change is an arbitrary level. The sum of the quantities with standard names thermosteric_change_in_mean_sea_level and halosteric_change_in_mean_sea_level has the standard name steric_change_in_mean_sea_level. + + + + m + + + "Sea surface height" is a time-varying quantity. The steric change in sea surface height is the change in height that a water column of standard temperature zero degrees Celsius and practical salinity S=35.0 would undergo when its temperature and salinity are changed to the observed values. The sum of the quantities with standard names thermosteric_change_in_sea_surface_height and halosteric_change_in_sea_surface_height is the total steric change in the water column height, which has the standard name of steric_change_in_sea_surface_height. The sum of the quantities with standard names sea_water_mass_per_unit_area_expressed_as_thickness and steric_change_in_sea_surface_height is the total thickness of the sea water column. + + + + 1 + + + "X_area_fraction" means the fraction of horizontal area occupied by X. Cloud area fraction is also called "cloud amount" and "cloud cover". The cloud area fraction is for the whole atmosphere column, as seen from the surface or the top of the atmosphere. The cloud area fraction in a layer of the atmosphere has the standard name cloud_area_fraction_in_atmosphere_layer. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). + + + + 1 + + + "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. Cloud area fraction is also called "cloud amount" and "cloud cover". In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). + + + + 1 + + + Emissivity is the ratio of the power emitted by an object to the power that would be emitted by a perfect black body having the same temperature as the object. The emissivity is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength or radiation_frequency is included to specify either the wavelength or frequency. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). "longwave" means longwave radiation. + + + + kg m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. Graupel consists of heavily rimed snow particles, often called snow pellets; often indistinguishable from very small soft hail except when the size convention that hail must have a diameter greater than 5 mm is adopted. Reference: American Meteorological Society Glossary http://glossary.ametsoc.org/wiki/Graupel. There are also separate standard names for hail. Standard names for "graupel_and_hail" should be used to describe data produced by models that do not distinguish between hail and graupel. + + + + kg m-2 + 62 + + "Precipitation" in the earth's atmosphere means precipitation of water in all phases. Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. "Amount" means mass per unit area. + + + + kg m-2 s-1 + + + Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. "Precipitation" in the earth's atmosphere means precipitation of water in all phases. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 + + + Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. "Amount" means mass per unit area. + + + + kg m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. + + + + m s-1 + + + Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. + + + + kg m-2 + 79 + + Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. "Amount" means mass per unit area. + + + + kg m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. + + + + mol m-2 + + + "Content" indicates a quantity per unit area. The "stratosphere content" of a quantity refers to the vertical integral from the tropopause to the stratopause. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for nitrogen_dioxide is NO2. + + + + 1 + + + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-"optical_thickness") on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. The stratosphere optical thickness applies to radiation passing through the atmosphere layer between the tropopause and stratopause. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". + + + + 1 + + + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-"optical_thickness") on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. The stratosphere optical thickness applies to radiation passing through the atmosphere layer between the tropopause and stratopause. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". + + + + 1 + + + The optical thickness is the integral along the path of radiation of a volume scattering/absorption/attenuation coefficient. The radiative flux is reduced by a factor exp(-"optical_thickness") on traversing the path. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the optical thickness applies at specific wavelengths or frequencies. The stratosphere optical thickness applies to radiation passing through the atmosphere layer between the tropopause and stratopause. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". Volcanic aerosols include both volcanic ash and secondary products such as sulphate aerosols formed from gaseous emissions of volcanic eruptions. + + + + kg m-2 + + + "Litter" is dead plant material in or above the soil. It is distinct from coarse wood debris. The precise distinction between "fine" and "coarse" is model dependent. "Subsurface litter" means the part of the litter mixed within the soil below the surface. "Content" indicates a quantity per unit area. The sum of the quantities with standard names surface_litter_mass_content_of_carbon and subsurface_litter_mass_content_of_carbon has the standard name litter_mass_content_of_carbon. + + + + kg m-2 + + + "Content" indicates a quantity per unit area. "Litter" is dead plant material in or above the soil. It is distinct from coarse wood debris. The precise distinction between "fine" and "coarse" is model dependent. "Subsurface litter" means the part of the litter mixed within the soil below the surface. The sum of the quantities with standard names wood_debris_mass_content_of_nitrogen, surface_litter_mass_content_of_nitrogen and subsurface_litter_mass_content_of_nitrogen is the total nitrogen mass content of dead plant material. + + + + kg m-2 + + + "Amount" means mass per unit area. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. + + + + kg m-2 s-1 + + + Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + rad + + + The angle between an incident beam of solar radiation and the outgoing beam specularly reflected at a sea surface. + + + + 1 + + + X_binary_mask has 1 where condition X is met, 0 elsewhere. + + + + Pa + E134 + ps + The surface called "surface" means the lower boundary of the atmosphere. Air pressure is the force per unit area which would be exerted when the moving gas molecules of which the air is composed strike a theoretical surface of any orientation. + + + + 1 + 84 E174 + + The surface called "surface" means the lower boundary of the atmosphere. Albedo is the ratio of outgoing to incoming shortwave irradiance, where 'shortwave irradiance' means that both the incoming and outgoing radiation are integrated across the solar spectrum. To specify the nature of the surface a cell_methods attribute should be supplied as described in Chapter 7.3.3 of the CF Conventions. + + + + 1 + + + The surface called "surface" means the lower boundary of the atmosphere. Albedo is the ratio of outgoing to incoming shortwave irradiance, where 'shortwave irradiance' means that both the incoming and outgoing radiation are integrated across the solar spectrum. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. + + + + 1 + + + The surface called "surface" means the lower boundary of the atmosphere. Albedo is the ratio of outgoing to incoming shortwave irradiance, where 'shortwave irradiance' means that both the incoming and outgoing radiation are integrated across the solar spectrum. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. + + + + m + + orog + The surface called "surface" means the lower boundary of the atmosphere. Altitude is the (geometric) height above the geoid, which is the reference geopotential surface. The geoid is similar to mean sea level. + + + + 1 + + + The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength is included to specify the wavelength. Scattering of radiation is its deflection from its incident path without loss of energy. Backwards scattering refers to the sum of scattering into all backward angles i.e. scattering_angle exceeding pi/2 radians. A scattering_angle should not be specified with this quantity. + + + + 1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Bidirectional_reflectance" depends on the angles of incident and measured radiation. Reflectance is the ratio of the energy of the reflected to the incident radiation. A coordinate variable of radiation_wavelength or radiation_frequency can be used to specify the wavelength or frequency, respectively, of the radiation. + + + + K + + + The surface called "surface" means the lower boundary of the atmosphere.The brightness temperature of a body is the temperature of a black body which radiates the same power per unit solid angle per unit area. + + + + Pa + + + The surface called "surface" means the lower boundary of the atmosphere. The chemical formula for carbon dioxide is CO2. In ocean biogeochemistry models, an "abiotic analogue" is used to simulate the effect on a modelled variable when biological effects on ocean carbon concentration and alkalinity are ignored. The partial pressure of a gaseous constituent of air is the pressure which it alone would exert with unchanged temperature and number of moles per unit volume. The partial pressure of a dissolved gas in sea water is the partial pressure in air with which it would be in equilibrium. The partial pressure difference between sea water and air is positive when the partial pressure of the dissolved gas in sea water is greater than the partial pressure in air. + + + + Pa + + + The surface called "surface" means the lower boundary of the atmosphere. The chemical formula for carbon dioxide is CO2. In ocean biogeochemistry models, a "natural analogue" is used to simulate the effect on a modelled variable of imposing preindustrial atmospheric carbon dioxide concentrations, even when the model as a whole may be subjected to varying forcings. The partial pressure of a gaseous constituent of air is the pressure which it alone would exert with unchanged temperature and number of moles per unit volume. The partial pressure of a dissolved gas in sea water is the partial pressure in air with which it would be in equilibrium. The partial pressure difference between sea water and air is positive when the partial pressure of the dissolved gas in sea water is greater than the partial pressure in air. + + + + Pa + + + The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. The partial pressure of a gaseous constituent of air is the pressure which it alone would exert with unchanged temperature and number of moles per unit volume. + + + + Pa + + + The partial pressure of a dissolved gas in sea water is the partial pressure in air with which it would be in equilibrium. The partial pressure of a gaseous constituent of air is the pressure which it alone would exert with unchanged temperature and number of moles per unit volume. The surface called "surface" means the lower boundary of the atmosphere. The chemical formula for carbon dioxide is CO2. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 400-700 nm. "Diffuse" radiation is radiation that has been scattered by gas molecules in the atmosphere and by particles such as cloud droplets and aerosols. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. The term "shortwave" means shortwave radiation. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. "Diffuse" radiation is radiation that has been scattered by gas molecules in the atmosphere and by particles such as cloud droplets and aerosols. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Diffuse" radiation is radiation that has been scattered by gas molecules in the atmosphere and by particles such as cloud droplets and aerosols. The term "shortwave" means shortwave radiation. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase "assuming_condition" indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Clear sky" means in the absence of clouds. + + + + 1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Diffuse" radiation is radiation that has been scattered by gas molecules in the atmosphere and by particles such as cloud droplets and aerosols. The term "shortwave" means shortwave radiation. Hemispherical reflectance is the ratio of the energy of the reflected to the incident radiation. This term gives the fraction of the surface_diffuse_downwelling_shortwave_flux_in_air which is reflected. If the diffuse radiation is isotropic, this term is equivalent to the integral of surface_bidirectional_reflectance over all incident angles and over all outgoing angles in the hemisphere above the surface. A coordinate variable of radiation_wavelength or radiation_frequency can be used to specify the wavelength or frequency, respectively, of the radiation. Shortwave hemispherical reflectance is related to albedo, but albedo is defined in terms of the fraction of the full spectrum of incident solar radiation which is reflected. It is related to the hemispherical reflectance averaged over all wavelengths using a weighting proportional to the incident radiative flux. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Direct" (also known as "beam") radiation is radiation that has followed a direct path from the sun and is alternatively known as "direct insolation". Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + 1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Direct" (also known as "beam") radiation is radiation that has followed a direct path from the sun and is alternatively known as "direct insolation". The term "shortwave" means shortwave radiation. Hemispherical reflectance is the ratio of the energy of the reflected to the incident radiation. This term gives the fraction of the surface_direct_downwelling_shortwave_flux_in_air which is reflected. It is equivalent to the surface_bidirectional_reflectance at the incident angle of the incoming solar radiation and integrated over all outgoing angles in the hemisphere above the surface. A coordinate variable of radiation_wavelength or radiation_frequency can be used to specify the wavelength or frequency, respectively, of the radiation. Shortwave hemispherical reflectance is related to albedo, but albedo is defined in terms of the fraction of the full spectrum of incident solar radiation which is reflected. It is related to the hemispherical reflectance averaged over all wavelengths using a weighting proportional to the incident radiation flux. + + + + Pa + E180 + tauu + The surface called "surface" means the lower boundary of the atmosphere. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Downward" indicates a vector component which is positive when directed downward (negative upward). "Downward eastward" indicates the ZX component of a tensor. A downward eastward stress is a downward flux of eastward momentum, which accelerates the lower medium eastward and the upper medium westward. The surface downward stress is the windstress on the surface. + + + + Pa + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Downward eastward" indicates the ZX component of a tensor. A downward eastward stress is a downward flux of eastward momentum, which accelerates the lower medium eastward and the upper medium westward. The surface downward stress is the wind stress on the surface. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Boundary layer mixing" means turbulent motions that transport heat, water, momentum and chemical constituents within the atmospheric boundary layer and affect exchanges between the surface and the atmosphere. The atmospheric boundary layer is typically characterised by a well-mixed sub-cloud layer of order 500 metres, and by a more extended conditionally unstable layer with boundary-layer clouds up to 2 km. (Reference: IPCC Third Assessment Report, Working Group 1: The Scientific Basis, 7.2.2.3, https://www.ipcc.ch/ipccreports/tar/wg1/273.htm). + + + + W m-2 + + hfns + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). The vertical heat flux in air is the sum of all heat fluxes i.e. radiative, latent and sensible. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). The surface latent heat flux is the exchange of heat between the surface and the air on account of evaporation (including sublimation). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. In ocean biogeochemistry models, an "abiotic analogue" is used to simulate the effect on a modelled variable when biological effects on ocean carbon concentration and alkalinity are ignored. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "C" means the element carbon and "13C" is the stable isotope "carbon-13", having six protons and seven neutrons. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. In ocean biogeochemistry models, an "abiotic analogue" is used to simulate the effect on a modelled variable when biological effects on ocean carbon concentration and alkalinity are ignored. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "C" means the element carbon and "14C" is the radioactive isotope "carbon-14", having six protons and eight neutrons and used in radiocarbon dating. + + + + kg m-2 s-1 + + + "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. The chemical formula for ammonia is NH3. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. In ocean biogeochemistry models, an "abiotic analogue" is used to simulate the effect on a modelled variable when biological effects on ocean carbon concentration and alkalinity are ignored. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula for carbon dioxide is CO2. + + + + kg m-2 s-1 + + + "Downward" indicates a vector component which is positive when directed downward (negative upward). The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. The chemical formula for carbon dioxide is CO2. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. In ocean biogeochemistry models, a "natural analogue" is used to simulate the effect on a modelled variable of imposing preindustrial atmospheric carbon dioxide concentrations, even when the model as a whole may be subjected to varying forcings. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula for carbon dioxide is CO2. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The chemical formula for methane is CH4. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Wetlands are areas where water covers the soil, or is present either at or near the surface of the soil all year or for varying periods of time during the year, including during the growing season. The precise conditions under which wetlands produce and consume methane can vary between models. + + + + kg m-2 s-1 + + + "Downward" indicates a vector component which is positive when directed downward (negative upward). The surface called "surface" means the lower boundary of the atmosphere. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Irrigation" includes water used to sustain crops, trees, pastures and urban lawns. + + + + mol m-2 s-1 + + + "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. The chemical formula for carbon dioxide is CO2. The standard name surface_upward_mole_flux_of_carbon_dioxide should be used to label data in which the flux is positive when directed upward. The standard name "surface_carbon_dioxide_mole_flux" is deprecated because it does not specify in which direction the flux is positive. Any data having the standard name "surface_carbon_dioxide_mole_flux" should be examined carefully to determine which sign convention was used. + + + + mol m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The chemical formula of CFC11 is CFCl3. The IUPAC name fof CFC11 is trichloro-fluoro-methane. + + + + mol m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The chemical formula for CFC12 is CF2Cl2. The IUPAC name for CFC12 is dichloro-difluoro-methane. + + + + mol m-2 s-1 + + + "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. + + + + mol m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The chemical formula of sulfur hexafluoride is SF6. + + + + Pa + E181 + tauv + The surface called "surface" means the lower boundary of the atmosphere. "Northward" indicates a vector component which is positive when directed northward (negative southward). "Downward" indicates a vector component which is positive when directed downward (negative upward). "Downward northward" indicates the ZY component of a tensor. A downward northward stress is a downward flux of northward momentum, which accelerates the lower medium northward and the upper medium southward. The surface downward stress is the windstress on the surface. + + + + Pa + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). "Northward" indicates a vector component which is positive when directed northward (negative southward). Downward northward" indicates the ZY component of a tensor. A downward northward stress is a downward flux of northward momentum, which accelerates the lower medium northward and the upper medium southward. The surface downward stress is the wind stress on the surface. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Boundary layer mixing" means turbulent motions that transport heat, water, momentum and chemical constituents within the atmospheric boundary layer and affect exchanges between the surface and the atmosphere. The atmospheric boundary layer is typically characterised by a well-mixed sub-cloud layer of order 500 metres, and by a more extended conditionally unstable layer with boundary-layer clouds up to 2 km. (Reference: IPCC Third Assessment Report, Working Group 1: The Scientific Basis, 7.2.2.3, https://www.ipcc.ch/ipccreports/tar/wg1/273.htm). + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). The surface sensible heat flux, also called "turbulent" heat flux, is the exchange of heat between the surface and the air by motion of air. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. "Downward" indicates a vector component which is positive when directed downward (negative upward). The surface water flux is the result of precipitation and evaporation. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + Pa + + + The surface called "surface" means the lower boundary of the atmosphere. "x" indicates a vector component along the grid x-axis, positive with increasing x. "Downward" indicates a vector component which is positive when directed downward (negative upward). + + + + Pa + + + "x" indicates a vector component along the grid x-axis, positive with increasing x. "Downward" indicates a vector component which is positive when directed downward (negative upward). The surface called "surface" means the lower boundary of the atmosphere. A downward x stress is a downward flux of momentum towards the positive direction of the model's x-axis. + + + + Pa + + + The surface called "surface" means the lower boundary of the atmosphere. "y" indicates a vector component along the grid y-axis, positive with increasing y. "Downward" indicates a vector component which is positive when directed downward (negative upward). + + + + Pa + + + "y" indicates a vector component along the grid y-axis, positive with increasing y. "Downward" indicates a vector component which is positive when directed downward (negative upward). The surface called "surface" means the lower boundary of the atmosphere. A downward y stress is a downward flux of momentum towards the positive direction of the model's y-axis. + + + + W m-2 + + rlds + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "longwave" means longwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + rldscs + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "longwave" means longwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Clear sky" means in the absence of clouds. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "longwave" means longwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". Volcanic aerosols include both volcanic ash and secondary products such as sulphate aerosols formed from gaseous emissions of volcanic eruptions. + + + + mol m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. A photon flux is specified in terms of numbers of photons expressed in moles. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + mol m-2 s-1 m-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. A photon flux is specified in terms of numbers of photons expressed in moles. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. + + + + mol m-2 s-1 sr-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Photon radiance is the photon flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. A photon flux is specified in terms of numbers of photons expressed in moles. + + + + mol m-2 s-1 m-1 sr-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Photon radiance is the photon flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. A photon flux is specified in terms of numbers of photons expressed in moles. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. + + + + mol m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Photon spherical irradiance is the photon flux incident on unit area of a hemispherical (or "2-pi") collector. The direction ("up/downwelling") is specified. Radiation incident on a 4-pi collector has a standard name referring to "omnidirectional spherical irradiance". A photon flux is specified in terms of numbers of photons expressed in moles. + + + + mol m-2 s-1 m-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. Photon spherical irradiance is the photon flux incident on unit area of a hemispherical (or "2-pi") collector. The direction ("up/downwelling") is specified. Radiation incident on a 4-pi collector has a standard name referring to "omnidirectional spherical irradiance". A photon flux is specified in terms of numbers of photons expressed in moles. + + + + mol m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 400-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. A photon flux is specified in terms of numbers of photons expressed in moles. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + mol m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 400-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. A photon flux is specified in terms of numbers of photons expressed in moles. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + mol m-2 s-1 sr-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Photon radiance is the photon flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 400-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. A photon flux is specified in terms of numbers of photons expressed in moles. + + + + mol m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 400-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. Photon spherical irradiance is the photon flux incident on unit area of a hemispherical (or "2-pi") collector. The direction ("up/downwelling") is specified. Radiation incident on a 4-pi collector has standard names of "omnidirectional spherical irradiance". A photon flux is specified in terms of numbers of photons expressed in moles. + + + + W m-2 sr-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 400-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 400-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 400-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 400-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. Spherical irradiance is the radiation incident on unit area of a hemispherical (or "2-pi") collector. It is sometimes called "scalar irradiance". The direction (up/downwelling) is specified. Radiation incident on a 4-pi collector has standard names of "omnidirectional spherical irradiance". + + + + W m-2 sr-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + + + + W m-2 m-1 sr-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction from which it is coming must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiative flux is the sum of shortwave and longwave radiative fluxes. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 m-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. + + + + W m-2 m-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. + + + + W m-2 + 117 E169 + rsds + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. Surface downwelling shortwave is the sum of direct and diffuse solar radiation incident on the surface, and is sometimes called "global radiation". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + rsdscs + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. Surface downwelling shortwave is the sum of direct and diffuse solar radiation incident on the surface, and is sometimes called "global radiation". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Clear sky" means in the absence of clouds. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. Surface downwelling shortwave is the sum of direct and diffuse solar radiation incident on the surface, and is sometimes called "global radiation". When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase "assuming_condition" indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Clear sky" means in the absence of clouds. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". Volcanic aerosols include both volcanic ash and secondary products such as sulphate aerosols formed from gaseous emissions of volcanic eruptions. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Spherical irradiance is the radiation incident on unit area of a hemispherical (or "2-pi") collector. It is sometimes called "scalar irradiance". The direction (up/downwelling) is specified. Radiation incident on a 4-pi collector has standard names of "omnidirectional spherical irradiance". + + + + W m-2 m-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Spherical irradiance is the radiation incident on unit area of a hemispherical (or "2-pi") collector. It is sometimes called "scalar irradiance". The direction (up/downwelling) is specified. Radiation incident on a 4-pi collector has standard names of "omnidirectional spherical irradiance". A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. + + + + 1 + + + The surface called "surface" means the lower boundary of the atmosphere. + + + + 1 + + + The surface called "surface" means the lower boundary of the atmosphere. + + + + 1 + + + The surface called "surface" means the lower boundary of the atmosphere. + + + + m s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). + + + + kg m-2 + + + "Amount" means mass per unit area. The surface called "surface" means the lower boundary of the atmosphere. The chemical formula for carbon dioxide is CO2. Frozen carbon dioxide is found on the surface of Mars. + + + + m2 s-2 + + + The surface called "surface" means the lower boundary of the atmosphere. Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. + + + + m s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Geostrophic" indicates that geostrophic balance is assumed, i.e. that the pressure gradient force and the Coriolis force are balanced and the large scale fluid flow is parallel to the isobars. The quantity with standard name surface_geostrophic_eastward_sea_water_velocity is the sum of a variable part, surface_geostrophic_eastward_sea_water_velocity_assuming_mean_sea_level_for_geoid, and a constant part due to the stationary component of ocean circulation. + + + + m s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. A velocity is a vector quantity. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Geostrophic" indicates that geostrophic balance is assumed, i.e. that the pressure gradient force and the Coriolis force are balanced and the large scale fluid flow is parallel to the isobars. "Mean sea level" means the time mean of sea surface elevation at a given location over an arbitrary period sufficient to eliminate the tidal signals. The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. (The volume enclosed between the geoid and the sea floor equals the mean volume of water in the ocean.) In an ocean GCM the geoid is the surface of zero depth, or the rigid lid if the model uses that approximation. The quantity with standard name surface_geostrophic_eastward_sea_water_velocity_assuming_mean_sea_level_for_geoid is the variable part of surface_geostrophic_eastward_sea_water_velocity. The assumption that sea level is equal to the geoid means that the stationary component of ocean circulation is equal to zero. + + + + m s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). "Geostrophic" indicates that geostrophic balance is assumed, i.e. that the pressure gradient force and the Coriolis force are balanced and the large scale fluid flow is parallel to the isobars. The quantity with standard name surface_geostrophic_northward_sea_water_velocity is the sum of a variable part, surface_geostrophic_northward_sea_water_velocity_assuming_mean_sea_level_for_geoid, and a constant part due to the stationary component of ocean circulation. + + + + m s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). "Geostrophic" indicates that geostrophic balance is assumed, i.e. that the pressure gradient force and the Coriolis force are balanced and the large scale fluid flow is parallel to the isobars. "Mean sea level" means the time mean of sea surface elevation at a given location over an arbitrary period sufficient to eliminate the tidal signals. The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. (The volume enclosed between the geoid and the sea floor equals the mean volume of water in the ocean.) In an ocean GCM the geoid is the surface of zero depth, or the rigid lid if the model uses that approximation. The quantity with standard name surface_geostrophic_northward_sea_water_velocity_assuming_mean_sea_level_for_geoid is the variable part of surface_geostrophic_northward_sea_water_velocity. The assumption that sea level is equal to the geoid means that the stationary component of ocean circulation is equal to zero. + + + + m s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. A velocity is a vector quantity. "x" indicates a vector component along the grid x-axis, positive with increasing x. "Geostrophic" indicates that geostrophic balance is assumed, i.e. that the pressure gradient force and the Coriolis force are balanced and the large scale fluid flow is parallel to the isobars. The quantity with standard name surface_geostrophic_sea_water_x_velocity is the sum of a variable part, surface_geostrophic_sea_water_x_velocity_assuming_mean_sea_level_for_geoid, and a constant part due to the stationary component of ocean circulation. + + + + m s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. A velocity is a vector quantity. "x" indicates a vector component along the grid x-axis, positive with increasing x. "Geostrophic" indicates that geostrophic balance is assumed, i.e. that the pressure gradient force and the Coriolis force are balanced and the large scale fluid flow is parallel to the isobars. "Mean sea level" means the time mean of sea surface elevation at a given location over an arbitrary period sufficient to eliminate the tidal signals. The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. (The volume enclosed between the geoid and the sea floor equals the mean volume of water in the ocean.) In an ocean GCM the geoid is the surface of zero depth, or the rigid lid if the model uses that approximation. The quantity with standard name surface_geostrophic_sea_water_x_velocity_assuming_mean_sea_level_for_geoid is the variable part of surface_geostrophic_sea_water_x_velocity. The assumption that sea level is equal to the geoid means that the stationary component of ocean circulation is equal to zero. + + + + m s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. A velocity is a vector quantity. "y" indicates a vector component along the grid y-axis, positive with increasing y. "Geostrophic" indicates that geostrophic balance is assumed, i.e. that the pressure gradient force and the Coriolis force are balanced and the large scale fluid flow is parallel to the isobars. The quantity with standard name surface_geostrophic_sea_water_y_velocity is the sum of a variable part, surface_geostrophic_sea_water_y_velocity_assuming_mean_sea_level_for_geoid, and a constant part due to the stationary component of ocean circulation. + + + + m s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. A velocity is a vector quantity. "y" indicates a vector component along the grid y-axis, positive with increasing y. "Geostrophic" indicates that geostrophic balance is assumed, i.e. that the pressure gradient force and the Coriolis force are balanced and the large scale fluid flow is parallel to the isobars. "Mean sea level" means the time mean of sea surface elevation at a given location over an arbitrary period sufficient to eliminate the tidal signals. The geoid is a surface of constant geopotential with which mean sea level would coincide if the ocean were at rest. (The volume enclosed between the geoid and the sea floor equals the mean volume of water in the ocean). In an ocean GCM the geoid is the surface of zero depth, or the rigid lid if the model uses that approximation. The quantity with standard name surface_geostrophic_sea_water_y_velocity_assuming_mean_sea_level_for_geoid is the variable part of surface_geostrophic_sea_water_y_velocity. The assumption that sea level is equal to the geoid means that the stationary component of ocean circulation is equal to zero. + + + + m + + + "Height_above_X" means the vertical distance above the named surface X. The surface called "surface" means the lower boundary of the atmosphere. The "geopotential datum" is any estimated surface of constant geopotential used as a datum i.e. a reference level; for the geoid as a datum, specific standard names are available. To specify which geoid or geopotential datum is being used as a reference level, a grid_mapping variable should be attached to the data variable as described in Chapter 5.6 of the CF Convention. + + + + kg m-2 + + + "Litter" is dead plant material in or above the soil. It is distinct from coarse wood debris. The precise distinction between "fine" and "coarse" is model dependent. "Surface litter" means the part of the litter resting above the soil surface. "Content" indicates a quantity per unit area. The sum of the quantities with standard names surface_litter_mass_content_of_carbon and subsurface_litter_mass_content_of_carbon has the standard name litter_mass_content_of_carbon. + + + + kg m-2 + + + "Content" indicates a quantity per unit area. "Litter" is dead plant material in or above the soil. It is distinct from coarse wood debris. The precise distinction between "fine" and "coarse" is model dependent. "Surface litter" means the part of the litter resting above the soil surface. The sum of the quantities with standard names wood_debris_mass_content_of_nitrogen, surface_litter_mass_content_of_nitrogen and subsurface_litter_mass_content_of_nitrogen is the total nitrogen mass content of dead plant material. + + + + 1 + + + Emissivity is the ratio of the power emitted by an object to the power that would be emitted by a perfect black body having the same temperature as the object. The emissivity is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength or radiation_frequency is included to specify either the wavelength or frequency. The surface called "surface" means the lower boundary of the atmosphere. "longwave" means longwave radiation. + + + + 1 + + + Emissivity is the ratio of the power emitted by an object to the power that would be emitted by a perfect black body having the same temperature as the object. The emissivity is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength or radiation_frequency is included to specify either the wavelength or frequency. The surface called "surface" means the lower boundary of the atmosphere. + + + + Pa + + + The partial pressure of a dissolved gas in sea water is the partial pressure in air with which it would be in equilibrium. The partial pressure of a gaseous constituent of air is the pressure which it alone would exert with unchanged temperature and number of moles per unit volume. The surface called "surface" means the lower boundary of the atmosphere. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). The term "longwave" means longwave radiation. "X_direct_radiative_effect" refers to the instantaneous radiative impact of X on the Earth's energy balance, excluding secondary effects such as changes in cloud cover which may be caused by X. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). The term "longwave" means longwave radiation. "X_direct_radiative_effect" refers to the instantaneous radiative impact of X on the Earth's energy balance, excluding secondary effects such as changes in cloud cover which may be caused by X. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". A phrase "assuming_condition" indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Clear sky" means in the absence of clouds. + + + + W m-2 + + rls + The surface called "surface" means the lower boundary of the atmosphere. "longwave" means longwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + E211 + + The surface called "surface" means the lower boundary of the atmosphere. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "longwave" means longwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + + "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward mass flux is the difference between downward_mass_flux and upward_mass_flux. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Bidirectional surface exchange" is the exchange of a chemical species between the atmosphere and biosphere as simulated by bidirectional surface flux models. It refers to exchange through stomata and soil surfaces and is the net result of emission and dry deposition. The surface called "surface" means the lower boundary of the atmosphere. The chemical formula for ammonia is NH3. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula for carbon dioxide is CO2. "C" means the element carbon and "13C" is the stable isotope "carbon-13", having six protons and seven neutrons. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "All land processes" means plant and soil respiration, photosynthesis, animal grazing, crop harvesting, natural fires and anthropogenic land use change. "Anthropogenic land use change" means human changes to land, excluding forest regrowth. It includes fires ignited by humans for the purpose of land use change and the processes of eventual disposal and decomposition of wood products such as paper, cardboard, furniture and timber for construction. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula for carbon dioxide is CO2. "C" means the element carbon and "14C" is the radioactive isotope "carbon-14", having six protons and eight neutrons and used in radiocarbon dating. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "All land processes" means plant and soil respiration, photosynthesis, animal grazing, crop harvesting, natural fires and anthropogenic land use change. "Anthropogenic land use change" means human changes to land, excluding forest regrowth. It includes fires ignited by humans for the purpose of land use change and the processes of eventual disposal and decomposition of wood products such as paper, cardboard, furniture and timber for construction. + + + + kg m-2 s-1 + + + "Downward" indicates a vector component which is positive when directed downward (negative upward). The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "All land processes" means plant and soil respiration, photosynthesis, animal grazing, crop harvesting, natural fires and anthropogenic land use change. "Anthropogenic land use change" means human changes to land, excluding forest regrowth. It includes fires ignited by humans for the purpose of land use change and the processes of eventual disposal and decomposition of wood products such as paper, cardboard, furniture and timber for construction. The quantity with standard name surface_net_downward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_all_land_processes is equal to the difference between the quantities with standard names surface_net_downward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_all_land_processes_excluding_anthropogenic_land_use_change and surface_net_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_emission_from_anthropogenic_land_use_change. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The chemical formula for carbon dioxide is CO2. + + + + kg m-2 s-1 + + + "Downward" indicates a vector component which is positive when directed downward (negative upward). The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "All land processes" means plant and soil respiration, photosynthesis, animal grazing, crop harvesting, natural fires and anthropogenic land use change. "Anthropogenic land use change" means human changes to land, excluding forest regrowth. It includes fires ignited by humans for the purpose of land use change and the processes of eventual disposal and decomposition of wood products such as paper, cardboard, furniture and timber for construction. The quantity with standard name surface_net_downward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_all_land_processes is equal to the difference between the quantities with standard names surface_net_downward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_all_land_processes_excluding_anthropogenic_land_use_change and surface_net_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_emission_from_anthropogenic_land_use_change. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The chemical formula for carbon dioxide is CO2. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. Previously, the qualifier where_type was used to specify that the quantity applies only to the part of the grid box of the named type. Names containing the where_type qualifier are deprecated and newly created data should use the cell_methods attribute to indicate the horizontal area to which the quantity applies. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). The term "shortwave" means shortwave radiation. "X_direct_radiative_effect" refers to the instantaneous radiative impact of X on the Earth's energy balance, excluding secondary effects such as changes in cloud cover which may be caused by X. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). The term "shortwave" means shortwave radiation. "X_direct_radiative_effect" refers to the instantaneous radiative impact of X on the Earth's energy balance, excluding secondary effects such as changes in cloud cover which may be caused by X. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". A phrase "assuming_condition" indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Clear sky" means in the absence of clouds. + + + + W m-2 + + rss + The surface called "surface" means the lower boundary of the atmosphere. "shortwave" means shortwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + E210 + + The surface called "surface" means the lower boundary of the atmosphere. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "shortwave" means shortwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + 112 E176 + + The surface called "surface" means the lower boundary of the atmosphere. "longwave" means longwave radiation. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Anthropogenic land use change" means human changes to land, excluding forest regrowth. It includes fires ignited by humans for the purpose of land use change and the processes of eventual disposal and decomposition of wood products such as paper, cardboard, furniture and timber for construction. The quantity with standard name surface_net_downward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_all_land_processes is equal to the difference between the quantities with standard names surface_net_downward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_all_land_processes_excluding_anthropogenic_land_use_change and surface_net_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_emission_from_anthropogenic_land_use_change. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon dioxide is CO2. + + + + kg m-2 s-1 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). A net upward flux is the difference between the flux from below (upward) and the flux from above (downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Wetlands are areas where water covers the soil, or is present either at or near the surface of the soil all year or for varying periods of time during the year, including during the growing season. The precise conditions under which wetlands produce and consume methane can vary between models. The quantity with standard name surface_net_upward_mass_flux_of_methane_due_to_emission_from_wetland_biological_processes is the difference between the upward and downward surface fluxes of methane which have standard names surface_upward_mass_flux_of_methane_due_to_emission_from_wetland_biological_production and surface_downward_mass_flux_of_methane_due_to_wetland_biological_consumption, respectively. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + 111 E177 + + The surface called "surface" means the lower boundary of the atmosphere. "shortwave" means shortwave radiation. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + m s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. A velocity is a vector quantity. "Northward" indicates a vector component which is positive when directed northward (negative southward). + + + + Pa + + + The surface called "surface" means the lower boundary of the atmosphere. The chemical formula for carbon dioxide is CO2. In ocean biogeochemistry models, an "abiotic analogue" is used to simulate the effect on a modelled variable when biological effects on ocean carbon concentration and alkalinity are ignored. The partial pressure of a dissolved gas in sea water is the partial pressure in air with which it would be in equilibrium. The partial pressure of a gaseous constituent of air is the pressure which it alone would exert with unchanged temperature and number of moles per unit volume. + + + + Pa + + + The surface called "surface" means the lower boundary of the atmosphere. The partial pressure of a gaseous constituent of air is the pressure which it alone would exert with unchanged temperature and number of moles per unit volume. + + + + Pa + + + The surface called "surface" means the lower boundary of the atmosphere. The partial pressure of a dissolved gas in sea water is the partial pressure in air with which it would be in equilibrium. The partial pressure of a gaseous constituent of air is the pressure which it alone would exert with unchanged temperature and number of moles per unit volume. The chemical formula for carbon dioxide is CO2. + + + + Pa + + + The surface called "surface" means the lower boundary of the atmosphere. The chemical formula for carbon dioxide is CO2. In ocean biogeochemistry models, a "natural analogue" is used to simulate the effect on a modelled variable of imposing preindustrial atmospheric carbon dioxide concentrations, even when the model as a whole may be subjected to varying forcings. The partial pressure of a dissolved gas in sea water is the partial pressure in air with which it would be in equilibrium. The partial pressure of a gaseous constituent of air is the pressure which it alone would exert with unchanged temperature and number of moles per unit volume. + + + + + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Mo" means the element "molybdenum" and "101Mo" is the isotope "molybdenum-101" with a half-life of 1.01e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Tc" means the element "technetium" and "101Tc" is the isotope "technetium-101" with a half-life of 9.86e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Mo" means the element "molybdenum" and "102Mo" is the isotope "molybdenum-102" with a half-life of 7.71e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Tc" means the element "technetium" and "102mTc" is the metastable state of the isotope "technetium-102" with a half-life of 2.98e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Tc" means the element "technetium" and "102Tc" is the isotope "technetium-102" with a half-life of 6.12e-05 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Rh" means the element "rhodium" and "103mRh" is the metastable state of the isotope "rhodium-103" with a half-life of 3.89e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ru" means the element "ruthenium" and "103Ru" is the isotope "ruthenium-103" with a half-life of 3.95e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Tc" means the element "technetium" and "104Tc" is the isotope "technetium-104" with a half-life of 1.25e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Rh" means the element "rhodium" and "105mRh" is the metastable state of the isotope "rhodium-105" with a half-life of 4.41e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Rh" means the element "rhodium" and "105Rh" is the isotope "rhodium-105" with a half-life of 1.48e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ru" means the element "ruthenium" and "105Ru" is the isotope "ruthenium-105" with a half-life of 1.85e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Rh" means the element "rhodium" and "106mRh" is the metastable state of the isotope "rhodium-106" with a half-life of 9.09e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Rh" means the element "rhodium" and "106Rh" is the isotope "rhodium-106" with a half-life of 3.46e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ru" means the element "ruthenium" and "106Ru" is the isotope "ruthenium-106" with a half-life of 3.66e+02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pd" means the element "palladium" and "107mPd" is the metastable state of the isotope "palladium-107" with a half-life of 2.47e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pd" means the element "palladium" and "107Pd" is the isotope "palladium-107" with a half-life of 2.37e+09 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Rh" means the element "rhodium" and "107Rh" is the isotope "rhodium-107" with a half-life of 1.51e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ag" means the element "silver" and "109mAg" is the metastable state of the isotope "silver-109" with a half-life of 4.58e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pd" means the element "palladium" and "109Pd" is the isotope "palladium-109" with a half-life of 5.61e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ag" means the element "silver" and "110mAg" is the metastable state of the isotope "silver-110" with a half-life of 2.70e+02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ag" means the element "silver" and "111Ag" is the isotope "silver-111" with a half-life of 7.50e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ag" means the element "silver" and "111mAg" is the metastable state of the isotope "silver-111" with a half-life of 8.56e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cd" means the element "cadmium" and "111mCd" is the metastable state of the isotope "cadmium-111" with a half-life of 3.39e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pd" means the element "palladium" and "111mPd" is the metastable state of the isotope "palladium-111" with a half-life of 2.29e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pd" means the element "palladium" and "111Pd" is the isotope "palladium-111" with a half-life of 1.53e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ag" means the element "silver" and "112Ag" is the isotope "silver-112" with a half-life of 1.30e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pd" means the element "palladium" and "112Pd" is the isotope "palladium-112" with a half-life of 8.37e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ag" means the element "silver" and "113Ag" is the isotope "silver-113" with a half-life of 2.21e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cd" means the element "cadmium" and "113Cd" is the isotope "cadmium-113" with a half-life of 3.29e+18 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ag" means the element "silver" and "113mAg" is the metastable state of the isotope "silver-113" with a half-life of 7.64e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cd" means the element "cadmium" and "113mCd" is the metastable state of the isotope "cadmium-113" with a half-life of 5.31e+03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "In" means the element "indium" and "113mIn" is the metastable state of the isotope "indium-113" with a half-life of 6.92e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ag" means the element "silver" and "115Ag" is the isotope "silver-115" with a half-life of 1.46e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cd" means the element "cadmium" and "115Cd" is the isotope "cadmium-115" with a half-life of 2.23e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "In" means the element "indium" and "115In" is the isotope "indium-115" with a half-life of 1.86e+18 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ag" means the element "silver" and "115mAg" is the metastable state of the isotope "silver-115" with a half-life of 1.97e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cd" means the element "cadmium" and "115mCd" is the metastable state of the isotope "cadmium-115" with a half-life of 4.46e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "In" means the element "indium" and "115mIn" is the metastable state of the isotope "indium-115" with a half-life of 1.87e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "In" means the element "indium" and "116In" is the isotope "indium-116" with a half-life of 1.64e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "In" means the element "indium" and "116mIn" is the metastable state of the isotope "indium-116" with a half-life of 3.77e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cd" means the element "cadmium" and "117Cd" is the isotope "cadmium-117" with a half-life of 1.08e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "In" means the element "indium" and "117In" is the isotope "indium-117" with a half-life of 3.05e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cd" means the element "cadmium" and "117mCd" is the metastable state of the isotope "cadmium-117" with a half-life of 1.42e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "In" means the element "indium" and "117mIn" is the metastable state of the isotope "indium-117" with a half-life of 8.08e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sn" means the element "tin" and "117mSn" is the metastable state of the isotope "tin-117" with a half-life of 1.40e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cd" means the element "cadmium" and "118Cd" is the isotope "cadmium-118" with a half-life of 3.49e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "In" means the element "indium" and "118In" is the isotope "indium-118" with a half-life of 5.77e-05 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "In" means the element "indium" and "118mIn" is the metastable state of the isotope "indium-118" with a half-life of 3.05e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "In" means the element "indium" and "119In" is the isotope "indium-119" with a half-life of 1.74e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "In" means the element "indium" and "119mIn" is the metastable state of the isotope "indium-119" with a half-life of 1.25e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sn" means the element "tin" and "119mSn" is the metastable state of the isotope "tin-119" with a half-life of 2.45e+02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "C" means the element "carbon" and "11C" is the isotope "carbon-11" with a half-life of 1.41e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sn" means the element "tin" and "121mSn" is the metastable state of the isotope "tin-121" with a half-life of 1.82e+04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sn" means the element "tin" and "121Sn" is the isotope "tin-121" with a half-life of 1.12e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sn" means the element "tin" and "123mSn" is the metastable state of the isotope "tin-123" with a half-life of 2.78e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sn" means the element "tin" and "123Sn" is the isotope "tin-123" with a half-life of 1.29e+02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sb" means the element "antimony" and "124mSb" is the metastable state of the isotope "antimony-124" with a half-life of 1.41e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sb" means the element "antimony" and "124Sb" is the isotope "antimony-124" with a half-life of 6.03e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Te" means the element "tellurium" and "125mTe" is the metastable state of the isotope "tellurium-125" with a half-life of 5.81e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sb" means the element "antimony" and "125Sb" is the isotope "antimony-125" with a half-life of 9.97e+02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sn" means the element "tin" and "125Sn" is the isotope "tin-125" with a half-life of 9.65e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sb" means the element "antimony" and "126mSb" is the metastable state of the isotope "antimony-126" with a half-life of 1.32e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sb" means the element "antimony" and "126Sb" is the isotope "antimony-126" with a half-life of 1.24e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sn" means the element "tin" and "126Sn" is the isotope "tin-126" with a half-life of 3.65e+07 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Te" means the element "tellurium" and "127mTe" is the metastable state of the isotope "tellurium-127" with a half-life of 1.09e+02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sb" means the element "antimony" and "127Sb" is the isotope "antimony-127" with a half-life of 3.80e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sn" means the element "tin" and "127Sn" is the isotope "tin-127" with a half-life of 8.84e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Te" means the element "tellurium" and "127Te" is the isotope "tellurium-127" with a half-life of 3.91e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sb" means the element "antimony" and "128mSb" is the metastable state of the isotope "antimony-128" with a half-life of 7.23e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sb" means the element "antimony" and "128Sb" is the isotope "antimony-128" with a half-life of 3.75e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sn" means the element "tin" and "128Sn" is the isotope "tin-128" with a half-life of 4.09e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "I" means the element "iodine" and "129I" is the isotope "iodine-129" with a half-life of 5.81e+09 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Te" means the element "tellurium" and "129mTe" is the metastable state of the isotope "tellurium-129" with a half-life of 3.34e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Xe" means the element "xenon" and "129mXe" is the metastable state of the isotope "xenon-129" with a half-life of 8.02e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sb" means the element "antimony" and "129Sb" is the isotope "antimony-129" with a half-life of 1.81e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Te" means the element "tellurium" and "129Te" is the isotope "tellurium-129" with a half-life of 4.86e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "I" means the element "iodine" and "130I" is the isotope "iodine-130" with a half-life of 5.18e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "I" means the element "iodine" and "130mI" is the metastable state of the isotope "iodine-130" with a half-life of 6.17e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sb" means the element "antimony" and "130mSb" is the metastable state of the isotope "antimony-130" with a half-life of 4.58e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sb" means the element "antimony" and "130Sb" is the isotope "antimony-130" with a half-life of 2.57e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sn" means the element "tin" and "130Sn" is the isotope "tin-130" with a half-life of 2.57e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "I" means the element "iodine" and "131I" is the isotope "iodine-131" with a half-life of 8.07e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Te" means the element "tellurium" and "131mTe" is the metastable state of the isotope "tellurium-131" with a half-life of 1.25e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Xe" means the element "xenon" and "131mXe" is the metastable state of the isotope "xenon-131" with a half-life of 1.18e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sb" means the element "antimony" and "131Sb" is the isotope "antimony-131" with a half-life of 1.60e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Te" means the element "tellurium" and "131Te" is the isotope "tellurium-131" with a half-life of 1.74e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "I" means the element "iodine" and "132I" is the isotope "iodine-132" with a half-life of 9.60e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Te" means the element "tellurium" and "132Te" is the isotope "tellurium-132" with a half-life of 3.25e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "I" means the element "iodine" and "133I" is the isotope "iodine-133" with a half-life of 8.71e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "I" means the element "iodine" and "133mI" is the metastable state of the isotope "iodine-133" with a half-life of 1.04e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Te" means the element "tellurium" and "133mTe" is the metastable state of the isotope "tellurium-133" with a half-life of 3.84e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Xe" means the element "xenon" and "133mXe" is the metastable state of the isotope "xenon-133" with a half-life of 2.26e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Te" means the element "tellurium" and "133Te" is the isotope "tellurium-133" with a half-life of 8.68e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Xe" means the element "xenon" and "133Xe" is the isotope "xenon-133" with a half-life of 5.28e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cs" means the element "cesium" and "134Cs" is the isotope "cesium-134" with a half-life of 7.50e+02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "I" means the element "iodine" and "134I" is the isotope "iodine-134" with a half-life of 3.61e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cs" means the element "cesium" and "134mCs" is the metastable state of the isotope "cesium-134" with a half-life of 1.21e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "I" means the element "iodine" and "134mI" is the metastable state of the isotope "iodine-134" with a half-life of 2.50e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Xe" means the element "xenon" and "134mXe" is the metastable state of the isotope "xenon-134" with a half-life of 3.36e-06 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Te" means the element "tellurium" and "134Te" is the isotope "tellurium-134" with a half-life of 2.92e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cs" means the element "cesium" and "135Cs" is the isotope "cesium-135" with a half-life of 8.39e+08 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "I" means the element "iodine" and "135I" is the isotope "iodine-135" with a half-life of 2.79e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ba" means the element "barium" and "135mBa" is the metastable state of the isotope "barium-135" with a half-life of 1.20e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cs" means the element "cesium" and "135mCs" is the metastable state of the isotope "cesium-135" with a half-life of 3.68e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Xe" means the element "xenon" and "135mXe" is the metastable state of the isotope "xenon-135" with a half-life of 1.08e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Xe" means the element "xenon" and "135Xe" is the isotope "xenon-135" with a half-life of 3.82e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cs" means the element "cesium" and "136Cs" is the isotope "cesium-136" with a half-life of 1.30e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cs" means the element "cesium" and "137Cs" is the isotope "cesium-137" with a half-life of 1.10e+04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ba" means the element "barium" and "137mBa" is the metastable state of the isotope "barium-137" with a half-life of 1.77e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Xe" means the element "xenon" and "137Xe" is the isotope "xenon-137" with a half-life of 2.71e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cs" means the element "cesium" and "138Cs" is the isotope "cesium-138" with a half-life of 2.23e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Xe" means the element "xenon" and "138Xe" is the isotope "xenon-138" with a half-life of 9.84e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ba" means the element "barium" and "139Ba" is the isotope "barium-139" with a half-life of 5.77e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "N" means the element "nitrogen" and "13N" is the isotope "nitrogen-13" with a half-life of 6.92e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ba" means the element "barium" and "140Ba" is the isotope "barium-140" with a half-life of 1.28e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "La" means the element "lanthanum" and "140La" is the isotope "lanthanum-140" with a half-life of 1.76e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ce" means the element "cerium" and "141Ce" is the isotope "cerium-141" with a half-life of 3.30e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "La" means the element "lanthanum" and "141La" is the isotope "lanthanum-141" with a half-life of 1.61e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ce" means the element "cerium" and "142Ce" is the isotope "cerium-142" with a half-life of 1.82e+19 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "La" means the element "lanthanum" and "142La" is the isotope "lanthanum-142" with a half-life of 6.42e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pr" means the element "praseodymium" and "142mPr" is the metastable state of the isotope "praseodymium-142" with a half-life of 1.01e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pr" means the element "praseodymium" and "142Pr" is the isotope "praseodymium-142" with a half-life of 7.94e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ce" means the element "cerium" and "143Ce" is the isotope "cerium-143" with a half-life of 1.37e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "La" means the element "lanthanum" and "143La" is the isotope "lanthanum-143" with a half-life of 9.72e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pr" means the element "praseodymium" and "143Pr" is the isotope "praseodymium-143" with a half-life of 1.36e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ce" means the element "cerium" and "144Ce" is the isotope "cerium-144" with a half-life of 2.84e+02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pr" means the element "praseodymium" and "144mPr" is the metastable state of the isotope "praseodymium-144" with a half-life of 4.98e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Nd" means the element "neodymium" and "144Nd" is the isotope "neodymium-144" with a half-life of 7.64e+17 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pr" means the element "praseodymium" and "144Pr" is the isotope "praseodymium-144" with a half-life of 1.20e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pr" means the element "praseodymium" and "145Pr" is the isotope "praseodymium-145" with a half-life of 2.49e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ce" means the element "cerium" and "146Ce" is the isotope "cerium-146" with a half-life of 9.86e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pr" means the element "praseodymium" and "146Pr" is the isotope "praseodymium-146" with a half-life of 1.68e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Nd" means the element "neodymium" and "147Nd" is the isotope "neodymium-147" with a half-life of 1.10e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pm" means the element "promethium" and "147Pm" is the isotope "promethium-147" with a half-life of 9.57e+02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pr" means the element "praseodymium" and "147Pr" is the isotope "praseodymium-147" with a half-life of 8.33e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sm" means the element "samarium" and "147Sm" is the isotope "samarium-147" with a half-life of 3.91e+13 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pm" means the element "promethium" and "148mPm" is the metastable state of the isotope "promethium-148" with a half-life of 4.14e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pm" means the element "promethium" and "148Pm" is the isotope "promethium-148" with a half-life of 5.38e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sm" means the element "samarium" and "148Sm" is the isotope "samarium-148" with a half-life of 2.92e+18 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Nd" means the element "neodymium" and "149Nd" is the isotope "neodymium-149" with a half-life of 7.23e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pm" means the element "promethium" and "149Pm" is the isotope "promethium-149" with a half-life of 2.21e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sm" means the element "samarium" and "149Sm" is the isotope "samarium-149" with a half-life of 3.65e+18 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pm" means the element "promethium" and "150Pm" is the isotope "promethium-150" with a half-life of 1.12e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Nd" means the element "neodymium" and "151Nd" is the isotope "neodymium-151" with a half-life of 8.61e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pm" means the element "promethium" and "151Pm" is the isotope "promethium-151" with a half-life of 1.18e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sm" means the element "samarium" and "151Sm" is the isotope "samarium-151" with a half-life of 3.40e+04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pm" means the element "promethium" and "152mPm" is the metastable state of the isotope "promethium-152" with a half-life of 1.25e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Nd" means the element "neodymium" and "152Nd" is the isotope "neodymium-152" with a half-life of 7.94e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pm" means the element "promethium" and "152Pm" is the isotope "promethium-152" with a half-life of 2.84e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sm" means the element "samarium" and "153Sm" is the isotope "samarium-153" with a half-life of 1.94e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Eu" means the element "europium" and "154Eu" is the isotope "europium-154" with a half-life of 3.13e+03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Eu" means the element "europium" and "155Eu" is the isotope "europium-155" with a half-life of 1.75e+03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sm" means the element "samarium" and "155Sm" is the isotope "samarium-155" with a half-life of 1.54e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Eu" means the element "europium" and "156Eu" is the isotope "europium-156" with a half-life of 1.52e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sm" means the element "samarium" and "156Sm" is the isotope "samarium-156" with a half-life of 3.91e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Eu" means the element "europium" and "157Eu" is the isotope "europium-157" with a half-life of 6.32e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Eu" means the element "europium" and "158Eu" is the isotope "europium-158" with a half-life of 3.18e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Eu" means the element "europium" and "159Eu" is the isotope "europium-159" with a half-life of 1.26e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Gd" means the element "gadolinium" and "159Gd" is the isotope "gadolinium-159" with a half-life of 7.71e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "O" means the element "oxygen" and "15O" is the isotope "oxygen-15" with a half-life of 1.41e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Tb" means the element "terbium" and "160Tb" is the isotope "terbium-160" with a half-life of 7.23e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Tb" means the element "terbium" and "161Tb" is the isotope "terbium-161" with a half-life of 6.92e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Gd" means the element "gadolinium" and "162Gd" is the isotope "gadolinium-162" with a half-life of 6.92e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Tb" means the element "terbium" and "162mTb" is the metastable state of the isotope "terbium-162" with a half-life of 9.30e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Tb" means the element "terbium" and "162Tb" is the isotope "terbium-162" with a half-life of 5.18e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Tb" means the element "terbium" and "163Tb" is the isotope "terbium-163" with a half-life of 1.36e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Dy" means the element "dysprosium" and "165Dy" is the isotope "dysprosium-165" with a half-life of 9.80e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "F" means the element "fluorine" and "18F" is the isotope "fluorine-18" with a half-life of 6.98e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Hg" means the element "mercury" and "206Hg" is the isotope "mercury-206" with a half-life of 5.57e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Tl" means the element "thallium" and "206Tl" is the isotope "thallium-206" with a half-life of 2.91e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pb" means the element "lead" and "207mPb" is the metastable state of the isotope "lead-207" with a half-life of 9.26e-06 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Tl" means the element "thallium" and "207Tl" is the isotope "thallium-207" with a half-life of 3.33e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Tl" means the element "thallium" and "208Tl" is the isotope "thallium-208" with a half-life of 2.15e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Bi" means the element "bismuth" and "209Bi" is the isotope "bismuth-209" with a half-life of 7.29e+20 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pb" means the element "lead" and "209Pb" is the isotope "lead-209" with a half-life of 1.38e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Tl" means the element "thallium" and "209Tl" is the isotope "thallium-209" with a half-life of 1.53e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Bi" means the element "bismuth" and "210Bi" is the isotope "bismuth-210" with a half-life of 5.01e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pb" means the element "lead" and "210Pb" is the isotope "lead-210" with a half-life of 7.64e+03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Po" means the element "polonium" and "210Po" is the isotope "polonium-210" with a half-life of 1.38e+02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Tl" means the element "thallium" and "210Tl" is the isotope "thallium-210" with a half-life of 9.02e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Bi" means the element "bismuth" and "211Bi" is the isotope "bismuth-211" with a half-life of 1.49e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pb" means the element "lead" and "211Pb" is the isotope "lead-211" with a half-life of 2.51e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Po" means the element "polonium" and "211Po" is the isotope "polonium-211" with a half-life of 6.03e-06 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Bi" means the element "bismuth" and "212Bi" is the isotope "bismuth-212" with a half-life of 4.20e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pb" means the element "lead" and "212Pb" is the isotope "lead-212" with a half-life of 4.43e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Po" means the element "polonium" and "212Po" is the isotope "polonium-212" with a half-life of 3.52e-12 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Bi" means the element "bismuth" and "213Bi" is the isotope "bismuth-213" with a half-life of 3.26e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pb" means the element "lead" and "213Pb" is the isotope "lead-213" with a half-life of 6.92e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Po" means the element "polonium" and "213Po" is the isotope "polonium-213" with a half-life of 4.86e-11 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Bi" means the element "bismuth" and "214Bi" is the isotope "bismuth-214" with a half-life of 1.37e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pb" means the element "lead" and "214Pb" is the isotope "lead-214" with a half-life of 1.86e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Po" means the element "polonium" and "214Po" is the isotope "polonium-214" with a half-life of 1.90e-09 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "At" means the element "astatine" and "215At" is the isotope "astatine-215" with a half-life of 1.16e-09 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Bi" means the element "bismuth" and "215Bi" is the isotope "bismuth-215" with a half-life of 4.86e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Po" means the element "polonium" and "215Po" is the isotope "polonium-215" with a half-life of 2.06e-08 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "At" means the element "astatine" and "216At" is the isotope "astatine-216" with a half-life of 3.47e-09 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Po" means the element "polonium" and "216Po" is the isotope "polonium-216" with a half-life of 1.74e-06 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "At" means the element "astatine" and "217At" is the isotope "astatine-217" with a half-life of 3.70e-07 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Po" means the element "polonium" and "217Po" is the isotope "polonium-217" with a half-life of 1.16e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "At" means the element "astatine" and "218At" is the isotope "astatine-218" with a half-life of 2.31e-05 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Po" means the element "polonium" and "218Po" is the isotope "polonium-218" with a half-life of 2.12e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Rn" means the element "radon" and "218Rn" is the isotope "radon-218" with a half-life of 4.05e-07 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "At" means the element "astatine" and "219At" is the isotope "astatine-219" with a half-life of 6.27e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Rn" means the element "radon" and "219Rn" is the isotope "radon-219" with a half-life of 4.64e-05 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Rn" means the element "radon" and "220Rn" is the isotope "radon-220" with a half-life of 6.37e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Fr" means the element "francium" and "221Fr" is the isotope "francium-221" with a half-life of 3.33e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Rn" means the element "radon" and "221Rn" is the isotope "radon-221" with a half-life of 1.74e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Fr" means the element "francium" and "222Fr" is the isotope "francium-222" with a half-life of 1.03e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ra" means the element "radium" and "222Ra" is the isotope "radium-222" with a half-life of 4.41e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Rn" means the element "radon" and "222Rn" is the isotope "radon-222" with a half-life of 3.82e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Fr" means the element "francium" and "223Fr" is the isotope "francium-223" with a half-life of 1.53e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ra" means the element "radium" and "223Ra" is the isotope "radium-223" with a half-life of 1.14e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Rn" means the element "radon" and "223Rn" is the isotope "radon-223" with a half-life of 2.98e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ra" means the element "radium" and "224Ra" is the isotope "radium-224" with a half-life of 3.65e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ac" means the element "actinium" and "225Ac" is the isotope "actinium-225" with a half-life of 1.00e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ra" means the element "radium" and "225Ra" is the isotope "radium-225" with a half-life of 1.48e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ac" means the element "actinium" and "226Ac" is the isotope "actinium-226" with a half-life of 1.21e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ra" means the element "radium" and "226Ra" is the isotope "radium-226" with a half-life of 5.86e+05 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Th" means the element "thorium" and "226Th" is the isotope "thorium-226" with a half-life of 2.15e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ac" means the element "actinium" and "227Ac" is the isotope "actinium-227" with a half-life of 7.87e+03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ra" means the element "radium" and "227Ra" is the isotope "radium-227" with a half-life of 2.87e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Th" means the element "thorium" and "227Th" is the isotope "thorium-227" with a half-life of 1.82e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ac" means the element "actinium" and "228Ac" is the isotope "actinium-228" with a half-life of 2.55e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ra" means the element "radium" and "228Ra" is the isotope "radium-228" with a half-life of 2.45e+03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Th" means the element "thorium" and "228Th" is the isotope "thorium-228" with a half-life of 6.98e+02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ac" means the element "actinium" and "229Ac" is the isotope "actinium-229" with a half-life of 4.58e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ra" means the element "radium" and "229Ra" is the isotope "radium-229" with a half-life of 1.16e-17 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Th" means the element "thorium" and "229Th" is the isotope "thorium-229" with a half-life of 2.68e+06 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pa" means the element "protactinium" and "230Pa" is the isotope "protactinium-230" with a half-life of 1.77e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Th" means the element "thorium" and "230Th" is the isotope "thorium-230" with a half-life of 2.92e+07 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "U" means the element "uranium" and "230U" is the isotope "uranium-230" with a half-life of 2.08e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pa" means the element "protactinium" and "231Pa" is the isotope "protactinium-231" with a half-life of 1.19e+07 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Th" means the element "thorium" and "231Th" is the isotope "thorium-231" with a half-life of 1.06e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "U" means the element "uranium" and "231U" is the isotope "uranium-231" with a half-life of 4.29e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pa" means the element "protactinium" and "232Pa" is the isotope "protactinium-232" with a half-life of 1.31e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Th" means the element "thorium" and "232Th" is the isotope "thorium-232" with a half-life of 5.14e+12 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "U" means the element "uranium" and "232U" is the isotope "uranium-232" with a half-life of 2.63e+04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pa" means the element "protactinium" and "233Pa" is the isotope "protactinium-233" with a half-life of 2.70e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Th" means the element "thorium" and "233Th" is the isotope "thorium-233" with a half-life of 1.54e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "U" means the element "uranium" and "233U" is the isotope "uranium-233" with a half-life of 5.90e+07 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pa" means the element "protactinium" and "234mPa" is the metastable state of the isotope "protactinium-234" with a half-life of 8.13e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pa" means the element "protactinium" and "234Pa" is the isotope "protactinium-234" with a half-life of 2.81e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Th" means the element "thorium" and "234Th" is the isotope "thorium-234" with a half-life of 2.41e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "U" means the element "uranium" and "234U" is the isotope "uranium-234" with a half-life of 9.02e+07 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Np" means the element "neptunium" and "235Np" is the isotope "neptunium-235" with a half-life of 4.09e+02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pu" means the element "plutonium" and "235Pu" is the isotope "plutonium-235" with a half-life of 1.81e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "U" means the element "uranium" and "235U" is the isotope "uranium-235" with a half-life of 2.60e+11 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Np" means the element "neptunium" and "236mNp" is the metastable state of the isotope "neptunium-236" with a half-life of 4.72e+10 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Np" means the element "neptunium" and "236Np" is the isotope "neptunium-236" with a half-life of 9.17e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pu" means the element "plutonium" and "236Pu" is the isotope "plutonium-236" with a half-life of 1.04e+03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "U" means the element "uranium" and "236U" is the isotope "uranium-236" with a half-life of 8.73e+09 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Np" means the element "neptunium" and "237Np" is the isotope "neptunium-237" with a half-life of 7.79e+08 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pu" means the element "plutonium" and "237Pu" is the isotope "plutonium-237" with a half-life of 4.56e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "U" means the element "uranium" and "237U" is the isotope "uranium-237" with a half-life of 6.74e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Np" means the element "neptunium" and "238Np" is the isotope "neptunium-238" with a half-life of 2.10e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pu" means the element "plutonium" and "238Pu" is the isotope "plutonium-238" with a half-life of 3.15e+04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "U" means the element "uranium" and "238U" is the isotope "uranium-238" with a half-life of 1.65e+12 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Np" means the element "neptunium" and "239Np" is the isotope "neptunium-239" with a half-life of 2.35e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pu" means the element "plutonium" and "239Pu" is the isotope "plutonium-239" with a half-life of 8.91e+06 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "U" means the element "uranium" and "239U" is the isotope "uranium-239" with a half-life of 1.63e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Am" means the element "americium" and "240Am" is the isotope "americium-240" with a half-life of 2.12e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Np" means the element "neptunium" and "240mNp" is the metastable state of the isotope "neptunium-240" with a half-life of 5.08e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Np" means the element "neptunium" and "240Np" is the isotope "neptunium-240" with a half-life of 4.38e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pu" means the element "plutonium" and "240Pu" is the isotope "plutonium-240" with a half-life of 2.40e+06 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "U" means the element "uranium" and "240U" is the isotope "uranium-240" with a half-life of 5.99e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Am" means the element "americium" and "241Am" is the isotope "americium-241" with a half-life of 1.67e+05 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cm" means the element "curium" and "241Cm" is the isotope "curium-241" with a half-life of 3.50e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pu" means the element "plutonium" and "241Pu" is the isotope "plutonium-241" with a half-life of 4.83e+03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Am" means the element "americium" and "242Am" is the isotope "americium-242" with a half-life of 6.69e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cm" means the element "curium" and "242Cm" is the isotope "curium-242" with a half-life of 1.63e+02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Am" means the element "americium" and "242m1Am" is the metastable state of the isotope "americium-242" with a half-life of 5.53e+04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Am" means the element "americium" and "242m2Am" is the metastable state of the isotope "americium-242" with a half-life of 1.62e-07 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pu" means the element "plutonium" and "242Pu" is the isotope "plutonium-242" with a half-life of 1.38e+08 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Am" means the element "americium" and "243Am" is the isotope "americium-243" with a half-life of 2.91e+06 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cm" means the element "curium" and "243Cm" is the isotope "curium-243" with a half-life of 1.17e+04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pu" means the element "plutonium" and "243Pu" is the isotope "plutonium-243" with a half-life of 2.07e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Am" means the element "americium" and "244Am" is the isotope "americium-244" with a half-life of 4.20e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cm" means the element "curium" and "244Cm" is the isotope "curium-244" with a half-life of 6.42e+03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Am" means the element "americium" and "244mAm" is the metastable state of the isotope "americium-244" with a half-life of 1.81e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pu" means the element "plutonium" and "244Pu" is the isotope "plutonium-244" with a half-life of 2.92e+10 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Am" means the element "americium" and "245Am" is the isotope "americium-245" with a half-life of 8.75e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cm" means the element "curium" and "245Cm" is the isotope "curium-245" with a half-life of 3.40e+06 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Pu" means the element "plutonium" and "245Pu" is the isotope "plutonium-245" with a half-life of 4.16e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cm" means the element "curium" and "246Cm" is the isotope "curium-246" with a half-life of 2.01e+06 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cm" means the element "curium" and "247Cm" is the isotope "curium-247" with a half-life of 5.86e+09 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cm" means the element "curium" and "248Cm" is the isotope "curium-248" with a half-life of 1.72e+08 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Bk" means the element "berkelium" and "249Bk" is the isotope "berkelium-249" with a half-life of 3.15e+02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cf" means the element "californium" and "249Cf" is the isotope "californium-249" with a half-life of 1.32e+05 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cm" means the element "curium" and "249Cm" is the isotope "curium-249" with a half-life of 4.43e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Na" means the element "sodium" and "24Na" is the isotope "sodium-24" with a half-life of 6.27e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Bk" means the element "berkelium" and "250Bk" is the isotope "berkelium-250" with a half-life of 1.34e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cf" means the element "californium" and "250Cf" is the isotope "californium-250" with a half-life of 4.75e+03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cm" means the element "curium" and "250Cm" is the isotope "curium-250" with a half-life of 2.52e+06 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cf" means the element "californium" and "251Cf" is the isotope "californium-251" with a half-life of 2.92e+05 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cf" means the element "californium" and "252Cf" is the isotope "californium-252" with a half-life of 9.68e+02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cf" means the element "californium" and "253Cf" is the isotope "californium-253" with a half-life of 1.76e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Es" means the element "einsteinium" and "253Es" is the isotope "einsteinium-253" with a half-life of 2.05e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Cf" means the element "californium" and "254Cf" is the isotope "californium-254" with a half-life of 6.03e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Es" means the element "einsteinium" and "254Es" is the isotope "einsteinium-254" with a half-life of 2.76e+02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Es" means the element "einsteinium" and "254mEs" is the metastable state of the isotope "einsteinium-254" with a half-life of 1.63e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Es" means the element "einsteinium" and "255Es" is the isotope "einsteinium-255" with a half-life of 3.84e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "H" means the element "hydrogen" and "3H" is the isotope "hydrogen-3" with a half-life of 4.51e+03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ar" means the element "argon" and "41Ar" is the isotope "argon-41" with a half-life of 7.64e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Mn" means the element "manganese" and "54Mn" is the isotope "manganese-54" with a half-life of 3.12e+02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Co" means the element "cobalt" and "58Co" is the isotope "cobalt-58" with a half-life of 7.10e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Co" means the element "cobalt" and "60Co" is the isotope "cobalt-60" with a half-life of 1.93e+03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ga" means the element "gallium" and "72Ga" is the isotope "gallium-72" with a half-life of 5.86e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Zn" means the element "zinc" and "72Zn" is the isotope "zinc-72" with a half-life of 1.94e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ga" means the element "gallium" and "73Ga" is the isotope "gallium-73" with a half-life of 2.03e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ge" means the element "germanium" and "75Ge" is the isotope "germanium-75" with a half-life of 5.73e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "As" means the element "arsenic" and "77As" is the isotope "arsenic-77" with a half-life of 1.62e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ge" means the element "germanium" and "77Ge" is the isotope "germanium-77" with a half-life of 4.72e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ge" means the element "germanium" and "77mGe" is the metastable state of the isotope "germanium-77" with a half-life of 6.27e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "As" means the element "arsenic" and "78As" is the isotope "arsenic-78" with a half-life of 6.32e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Ge" means the element "germanium" and "78Ge" is the isotope "germanium-78" with a half-life of 6.03e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Se" means the element "selenium" and "79Se" is the isotope "selenium-79" with a half-life of 2.37e+07 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Se" means the element "selenium" and "81mSe" is the metastable state of the isotope "selenium-81" with a half-life of 3.97e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Se" means the element "selenium" and "81Se" is the isotope "selenium-81" with a half-life of 1.28e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Br" means the element "bromine" and "82Br" is the isotope "bromine-82" with a half-life of 1.47e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Br" means the element "bromine" and "82mBr" is the metastable state of the isotope "bromine-82" with a half-life of 4.24e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Br" means the element "bromine" and "83Br" is the isotope "bromine-83" with a half-life of 1.00e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Kr" means the element "krypton" and "83mKr" is the metastable state of the isotope "krypton-83" with a half-life of 7.71e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Se" means the element "selenium" and "83mSe" is the metastable state of the isotope "selenium-83" with a half-life of 8.10e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Se" means the element "selenium" and "83Se" is the isotope "selenium-83" with a half-life of 1.56e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Br" means the element "bromine" and "84Br" is the isotope "bromine-84" with a half-life of 2.21e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Br" means the element "bromine" and "84mBr" is the metastable state of the isotope "bromine-84" with a half-life of 4.16e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Kr" means the element "krypton" and "85Kr" is the isotope "krypton-85" with a half-life of 3.95e+03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Kr" means the element "krypton" and "85mKr" is the metastable state of the isotope "krypton-85" with a half-life of 1.83e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Rb" means the element "rubidium" and "86mRb" is the metastable state of the isotope "rubidium-86" with a half-life of 7.04e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Rb" means the element "rubidium" and "86Rb" is the isotope "rubidium-86" with a half-life of 1.87e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Kr" means the element "krypton" and "87Kr" is the isotope "krypton-87" with a half-life of 5.28e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Rb" means the element "rubidium" and "87Rb" is the isotope "rubidium-87" with a half-life of 1.71e+13 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Kr" means the element "krypton" and "88Kr" is the isotope "krypton-88" with a half-life of 1.17e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Rb" means the element "rubidium" and "88Rb" is the isotope "rubidium-88" with a half-life of 1.25e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Kr" means the element "krypton" and "89Kr" is the isotope "krypton-89" with a half-life of 2.20e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Rb" means the element "rubidium" and "89Rb" is the isotope "rubidium-89" with a half-life of 1.06e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sr" means the element "strontium" and "89Sr" is the isotope "strontium-89" with a half-life of 5.21e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Y" means the element "yttrium" and "90mY" is the metastable state of the isotope "yttrium-90" with a half-life of 1.33e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sr" means the element "strontium" and "90Sr" is the isotope "strontium-90" with a half-life of 1.02e+04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Y" means the element "yttrium" and "90Y" is the isotope "yttrium-90" with a half-life of 2.67e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Y" means the element "yttrium" and "91mY" is the metastable state of the isotope "yttrium-91" with a half-life of 3.46e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sr" means the element "strontium" and "91Sr" is the isotope "strontium-91" with a half-life of 3.95e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Y" means the element "yttrium" and "91Y" is the isotope "yttrium-91" with a half-life of 5.86e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Sr" means the element "strontium" and "92Sr" is the isotope "strontium-92" with a half-life of 1.13e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Y" means the element "yttrium" and "92Y" is the isotope "yttrium-92" with a half-life of 1.47e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Y" means the element "yttrium" and "93Y" is the isotope "yttrium-93" with a half-life of 4.24e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Zr" means the element "zirconium" and "93Zr" is the isotope "zirconium-93" with a half-life of 3.47e+08 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Nb" means the element "niobium" and "94mNb" is the metastable state of the isotope "niobium-94" with a half-life of 4.34e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Nb" means the element "niobium" and "94Nb" is the isotope "niobium-94" with a half-life of 7.29e+06 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Y" means the element "yttrium" and "94Y" is the isotope "yttrium-94" with a half-life of 1.32e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Nb" means the element "niobium" and "95mNb" is the metastable state of the isotope "niobium-95" with a half-life of 3.61e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Nb" means the element "niobium" and "95Nb" is the isotope "niobium-95" with a half-life of 3.52e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Y" means the element "yttrium" and "95Y" is the isotope "yttrium-95" with a half-life of 7.29e-03 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Zr" means the element "zirconium" and "95Zr" is the isotope "zirconium-95" with a half-life of 6.52e+01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Nb" means the element "niobium" and "96Nb" is the isotope "niobium-96" with a half-life of 9.75e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Nb" means the element "niobium" and "97mNb" is the metastable state of the isotope "niobium-97" with a half-life of 6.27e-04 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Nb" means the element "niobium" and "97Nb" is the isotope "niobium-97" with a half-life of 5.11e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Zr" means the element "zirconium" and "97Zr" is the isotope "zirconium-97" with a half-life of 6.98e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Nb" means the element "niobium" and "98Nb" is the isotope "niobium-98" with a half-life of 3.53e-02 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Mo" means the element "molybdenum" and "99Mo" is the isotope "molybdenum-99" with a half-life of 2.78e+00 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Tc" means the element "technetium" and "99mTc" is the metastable state of the isotope "technetium-99" with a half-life of 2.51e-01 days. + + + + Bq m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Content" indicates a quantity per unit area. "Radioactivity" means the number of radioactive decays of a material per second. "Tc" means the element "technetium" and "99Tc" is the isotope "technetium-99" with a half-life of 7.79e+07 days. + + + + sr-1 + + + The surface called "surface" means the lower boundary of the atmosphere. The phrase "ratio_of_X_to_Y" means X/Y. Upwelling radiation is radiation from below. It does not mean "net upward". Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of angle_of_emergence. Radiative flux is the sum of shortwave and longwave radiative fluxes. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In relation to satellite ocean color products the quantity named surface_ratio_of_upwelling_radiance_emerging_from_sea_water_to_downwelling_radiative_flux_in_air is sometimes called "remote sensing reflectance" and has a bidirectional dependence. The direction of the downwelling flux can be specified using a coordinate with the standard name angle_of_incidence. + + + + m + 83 E173 + + The surface called "surface" means the lower boundary of the atmosphere. + + + + m + + + The surface called "surface" means the lower boundary of the atmosphere. + + + + m + + + The surface called "surface" means the lower boundary of the atmosphere. + + + + kg m-2 + 90 + + The surface called "surface" means the lower boundary of the atmosphere. "Amount" means mass per unit area. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. + + + + kg m-2 s-1 + + mrros + The surface called "surface" means the lower boundary of the atmosphere. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 + 65 + snw + The surface called "surface" means the lower boundary of the atmosphere. "Amount" means mass per unit area. Surface amount refers to the amount on the ground, excluding that on the plant or vegetation canopy. + + + + kg m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. "Surface snow and ice melt flux" means the mass flux of all melting at the surface. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. The snow and ice melt heat flux is the supply of latent heat which is melting snow and ice at freezing point. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. "Surface snow and ice refreezing flux" means the mass flux of surface meltwater which refreezes within the snow or firn. + + + + 1 + + snc + The surface called "surface" means the lower boundary of the atmosphere. "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. + + + + 1 + + + X"_binary_mask" has 1 where condition X is met, 0 elsewhere. The value is 1 where the snow cover area fraction is greater than a threshold, and 0 elsewhere. The threshold must be specified by associating a coordinate variable or scalar coordinate variable with the data variable and giving the coordinate variable a standard name of surface_snow_area_fraction. The values of the coordinate variable are the threshold values for the corresponding subarrays of the data variable. + + + + kg m-2 + 99 + + The surface called "surface" means the lower boundary of the atmosphere. "Amount" means mass per unit area. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. Sublimation is the conversion of solid into vapor. The snow melt and sublimation heat flux is the supply of latent heat which converting snow to liquid water (melting) and water vapor (sublimation). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + snm + The surface called "surface" means the lower boundary of the atmosphere. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. The snow melt heat flux is the supply of latent heat which is melting snow at freezing point. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 + + + The phrase "surface_snow" means snow lying on the surface. "Amount" means mass per unit area. Sublimation is the conversion of solid into vapor. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. Sublimation is the conversion of solid into vapor. The snow sublimation heat flux is the supply of latent heat which is causing evaporation of snow to water vapor. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + m + 66 + snd + The surface called "surface" means the lower boundary of the atmosphere. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. Previously, the qualifier where_type was used to specify that the quantity applies only to the part of the grid box of the named type. Names containing the where_type qualifier are deprecated and newly created data should use the cell_methods attribute to indicate the horizontal area to which the quantity applies. + + + + 1 + + + The surface called "surface" means the lower boundary of the atmosphere. "specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. + + + + K + E139 + ts + The surface called "surface" means the lower boundary of the atmosphere. The surface temperature is the temperature at the interface, not the bulk temperature of the medium above or below. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. Previously, the qualifier where_type was used to specify that the quantity applies only to the part of the grid box of the named type. Names containing the where_type qualifier are deprecated and newly created data should use the cell_methods attribute to indicate the horizontal area to which the quantity applies. + + + + K + + + The surface called "surface" means the lower boundary of the atmosphere. "anomaly" means difference from climatology. The surface temperature is the (skin) temperature at the interface, not the bulk temperature of the medium above or below. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). The vertical heat flux in air is the sum of all heat fluxes i.e. radiative, latent and sensible. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Anthropogenic" means influenced, caused, or created by human activity. The heat flux due to anthropogenic energy consumption results from non-renewable human primary energy consumption, including energy use by vehicles, commercial and residential buildings, industry, and power plants. Primary energy refers to energy in natural resources, fossil and non-fossil, before conversion into other forms, such as electricity. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). The vertical heat flux in air is the sum of all heat fluxes i.e. radiative, latent and sensible. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + 121 E147 + hfls + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). The surface latent heat flux is the exchange of heat between the surface and the air on account of evaporation (including sublimation). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). The surface latent heat flux is the exchange of heat between the surface and the air on account of evaporation (including sublimation). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Sublimation is the conversion of solid into vapor. + + + + kg m-2 s-1 + + + Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. The chemical formula for ammonia is NH3. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula for carbon dioxide is CO2. "C" means the element carbon and "13C" is the stable isotope "carbon-13", having six protons and seven neutrons. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Heterotrophic respiration is respiration by heterotrophs ("consumers"), which are organisms (including animals and decomposers) that consume other organisms or dead organic material, rather than synthesising organic material from inorganic precursors using energy from the environment (especially sunlight) as autotrophs ("producers") do. Heterotrophic respiration goes on within both the soil and litter pools. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula for carbon dioxide is CO2. "C" means the element carbon and "13C" is the stable isotope "carbon-13", having six protons and seven neutrons. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Plant respiration is the sum of respiration by parts of plants both above and below the soil. It is assumed that all the respired carbon dioxide is emitted to the atmosphere. The term "plants" refers to the kingdom of plants in the modern classification which excludes fungi. Plants are autotrophs i.e. "producers" of biomass using carbon obtained from carbon dioxide. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula for carbon dioxide is CO2. "C" means the element carbon and "14C" is the radioactive isotope "carbon-14", having six protons and eight neutrons and used in radiocarbon dating. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Heterotrophic respiration is respiration by heterotrophs ("consumers"), which are organisms (including animals and decomposers) that consume other organisms or dead organic material, rather than synthesising organic material from inorganic precursors using energy from the environment (especially sunlight) as autotrophs ("producers") do. Heterotrophic respiration goes on within both the soil and litter pools. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula for carbon dioxide is CO2. "C" means the element carbon and "14C" is the radioactive isotope "carbon-14", having six protons and eight neutrons and used in radiocarbon dating. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Plant respiration is the sum of respiration by parts of plants both above and below the soil. It is assumed that all the respired carbon dioxide is emitted to the atmosphere. The term "plants" refers to the kingdom of plants in the modern classification which excludes fungi. Plants are autotrophs i.e. "producers" of biomass using carbon obtained from carbon dioxide. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula for carbon dioxide is CO2. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Anthropogenic" means influenced, caused, or created by human activity. "Anthropogenic land use change" means human changes to land, excluding forest regrowth. It includes fires ignited by humans for the purpose of land use change and the processes of eventual disposal and decomposition of wood products such as paper, cardboard, furniture and timber for construction. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula for carbon dioxide is CO2. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Anthropogenic" means influenced, caused, or created by human activity. "Anthropogenic land use change" means human changes to land, excluding forest regrowth. It includes fires ignited by humans for the purpose of land use change. The quantity with standard name surface_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_anthropogenic_land_use_or_land_cover_change_excluding_forestry_and_agricultural_products excludes the carbon dioxide flux into the atmosphere due to the processes of eventual disposal and decomposition of wood products such as paper, cardboard, furniture and timber for construction. The standard name for the quantity that includes product decomposition is surface_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_anthropogenic_land_use_or_land_cover_change. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula for carbon dioxide is CO2. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The definition of "crop" is model dependent, for example, some models may include fruit trees, trees grown for timber or other types of agricultural and forestry planting as crops. Crop harvesting means the human activity of collecting plant materials for the purpose of turning them into forestry or agricultural products. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula for carbon dioxide is CO2. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The term "fires" means all biomass fires, whether naturally occurring or ignited by humans. The quantity with standard name surface_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_emission_from_fires is the sum of the quantities with standard names surface_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_emission_from_vegetation_in_fires and surface_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_emission_from_litter_in_fires. + + + + kg m-2 s-1 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Fires excluding anthropogenic land use change" means all natural fires and human ignited fires that are not associated with change of land use. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon dioxide is CO2. "Anthropogenic" means influenced, caused, or created by human activity. + + + + kg m-2 s-1 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon dioxide is CO2. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula for carbon dioxide is CO2. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Litter" is dead plant material in or above the soil. The quantity with standard name surface_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_emission_from_fires is the sum of the quantities with standard names surface_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_emission_from_vegetation_in_fires and surface_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_emission_from_litter_in_fires. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula for carbon dioxide is CO2. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Natural fires" means burning of biomass, whether living or dead, excluding fires ignited by humans, e.g. for agricultural purposes. + + + + kg m-2 s-1 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon dioxide is CO2. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula for carbon dioxide is CO2. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Vegetation" means any living plants e.g. trees, shrubs, grass. The quantity with standard name surface_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_emission_from_fires is the sum of the quantities with standard names surface_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_emission_from_vegetation_in_fires and surface_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_emission_from_litter_in_fires. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The chemical formula for carbon dioxide is CO2. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Heterotrophic respiration is respiration by heterotrophs ("consumers"), which are organisms (including animals and decomposers) that consume other organisms or dead organic material, rather than synthesising organic material from inorganic precursors using energy from the environment (especially sunlight) as autotrophs ("producers") do. Heterotrophic respiration goes on both above and within the soil. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The chemical formula for carbon dioxide is CO2. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Plant respiration is the sum of respiration by parts of plants both above and below the soil. It is assumed that all the respired carbon dioxide is emitted to the atmosphere. The term "plants" refers to the kingdom of plants in the modern classification which excludes fungi. Plants are autotrophs i.e. "producers" of biomass using carbon obtained from carbon dioxide. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The chemical formula for carbon dioxide is CO2. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Plant respiration is the sum of respiration by parts of plants both above and below the soil. It is assumed that all the respired carbon dioxide is emitted to the atmosphere. The term "plants" refers to the kingdom of plants in the modern classification which excludes fungi. Plants are autotrophs i.e. "producers" of biomass using carbon obtained from carbon dioxide. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The chemical formula for carbon dioxide is CO2. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Plant respiration is the sum of respiration by parts of plants both above and below the soil. It is assumed that all the respired carbon dioxide is emitted to the atmosphere. The term "plants" refers to the kingdom of plants in the modern classification which excludes fungi. Plants are autotrophs i.e. "producers" of biomass using carbon obtained from carbon dioxide. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The chemical formula for carbon dioxide is CO2. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Plant respiration is the sum of respiration by parts of plants both above and below the soil. Plants which photosynthesise are autotrophs i.e. "producers" of the biomass which they respire from inorganic precursors using sunlight for energy. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The chemical formula for carbon dioxide is CO2. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Plant respiration is the sum of respiration by parts of plants both above and below the soil. It is assumed that all the respired carbon dioxide is emitted to the atmosphere. The term "plants" refers to the kingdom of plants in the modern classification which excludes fungi. Plants are autotrophs i.e. "producers" of biomass using carbon obtained from carbon dioxide. "Miscellaneous living matter" means all those parts of plants that are not leaf, stem, root or other separately named components. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The chemical formula for carbon dioxide is CO2. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Plant respiration is the sum of respiration by parts of plants both above and below the soil. Plants which photosynthesise are autotrophs i.e. "producers" of the biomass which they respire from inorganic precursors using sunlight for energy. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The chemical formula for carbon dioxide is CO2. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Plant respiration is the sum of respiration by parts of plants both above and below the soil. Plants which photosynthesise are autotrophs i.e. "producers" of the biomass which they respire from inorganic precursors using sunlight for energy. The stem of a plant is the axis that bears buds and shoots with leaves and, at its basal end, roots. Its function is to carry water and nutrients. Examples include the stalk of a plant or the main trunk of a tree. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The chemical formula for carbon dioxide is CO2. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Soil respiration is the sum of respiration in the soil by animals and decomposers of litter (heterotrophs or "consumers"), which have not produced the biomass they respire, and respiration by the roots of plants (autotrophs or "producers"), which have themselves produced the biomass they respire. + + + + kg m-2 s-1 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Litter" is dead plant material in or above the soil. Heterotrophic respiration is respiration by heterotrophs ("consumers"), which are organisms (including animals and decomposers) that consume other organisms or dead organic material, rather than synthesising organic material from inorganic precursors using energy from the environment (especially sunlight) as autotrophs ("producers") do. Heterotrophic respiration goes on within both the soil and litter pools. + + + + kg m-2 s-1 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Heterotrophic respiration is respiration by heterotrophs ("consumers"), which are organisms (including animals and decomposers) that consume other organisms or dead organic material, rather than synthesising organic material from inorganic precursors using energy from the environment (especially sunlight) as autotrophs ("producers") do. Heterotrophic respiration goes on within both the soil and litter pools. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The chemical formula for methane is CH4. The mass is the total mass of the molecules. The phrase "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Wetlands are areas where water covers the soil, or is present either at or near the surface of the soil all year or for varying periods of time during the year, including during the growing season. The precise conditions under which wetlands produce and consume methane can vary between models. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. he phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Nitrogen compounds" summarizes all chemical species containing nitrogen atoms. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + kg m-2 s-1 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Nitrogen compounds" summarizes all chemical species containing nitrogen atoms. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "All land processes" means plant and soil respiration, photosynthesis, animal grazing, crop harvesting, natural fires and anthropogenic land use change. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Nitrogen compounds" summarizes all chemical species containing nitrogen atoms. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The term "fires" means all biomass fires, whether naturally occurring or ignited by humans. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Nitrogen compounds" summarizes all chemical species containing nitrogen atoms. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Vegetation" means any living plants e.g. trees, shrubs, grass. "Litter" is dead plant material in or above the soil. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula for nitrous oxide is N2O. "Vegetation" means any living plants e.g. trees, shrubs, grass. The term "plants" refers to the kingdom of plants in the modern classification which excludes fungi. Plants are autotrophs i.e. "producers" of biomass using carbon obtained from carbon dioxide. "Litter" is dead plant material in or above the soil. It is distinct from coarse wood debris. The precise distinction between "fine" and "coarse" is model dependent. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Nox" means a combination of two radical species containing nitrogen and oxygen NO+NO2. "Vegetation" means any living plants e.g. trees, shrubs, grass. "Litter" is dead plant material in or above the soil. + + + + mol m-2 s-1 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. The chemical formula for carbon dioxide is CO2. The standard name surface_downward_mole_flux_of_carbon_dioxide should be used to label data in which the flux is positive when directed downward. The standard name "surface_carbon_dioxide_mole_flux" is deprecated because it does not specify in which direction the flux is positive. Any data having the standard name "surface_carbon_dioxide_mole_flux" should be examined carefully to determine which sign convention was used. + + + + mol m-2 s-1 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The surface called "surface" means the lower boundary of the atmosphere. Thechemical formula for dimethyl sulfide is (CH3)2S. Dimethyl sulfide is sometimes referredto as DMS. + + + + W m-2 + 122 E146 + hfss + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). The surface sensible heat flux, also called "turbulent" heat flux, is the exchange of heat between the surface and the air by motion of air. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. Previously, the qualifier where_type was used to specify that the quantity applies only to the part of the grid box of the named type. Names containing the where_type qualifier are deprecated and newly created data should use the cell_methods attribute to indicate the horizontal area to which the quantity applies. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. "Upward" indicates a vector component which is positive when directed upward (negative downward). The surface water flux is the result of precipitation and evaporation. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + rlus + The surface called "surface" means the lower boundary of the atmosphere. The term "longwave" means longwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "longwave" means longwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Clear sky" means in the absence of clouds. + + + + mol m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. "Photosynthetic" radiation is the part of the spectrum which is used in photosynthesis e.g. 400-700 nm. The range of wavelengths could be specified precisely by the bounds of a coordinate of radiation_wavelength. A photon flux is specified in terms of numbers of photons expressed in moles. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 sr-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + + + + W m-2 sr-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + + + + W m-2 sr-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + + + + W m-2 sr-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + + + + W m-2 m-1 sr-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. + + + + W m-2 m-1 sr-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. + + + + W m-2 m-1 sr-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. + + + + W m-2 m-1 sr-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. + + + + W m-2 m-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. + + + + W m-2 m-1 + + + The surface called "surface" means the lower boundary of the atmosphere. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. + + + + W m-2 + + rsus + The surface called "surface" means the lower boundary of the atmosphere. The term "shortwave" means shortwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + rsuscs + The surface called "surface" means the lower boundary of the atmosphere. The term "shortwave" means shortwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Clear sky" means in the absence of clouds. + + + + W m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase "assuming_condition" indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Clear sky" means in the absence of clouds. + + + + kg m-2 + + + The surface called "surface" means the lower boundary of the atmosphere. "Amount" means mass per unit area. "Water" means water in all phases, including frozen i.e. ice and snow. Surface amount refers to the amount on the ground, excluding that on the plant or vegetation canopy. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "Water" means water in all phases, including frozen i.e. ice and snow. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation"). The quantity with standard name surface_water_evaporation_flux does not include transpiration from vegetation. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. Previously, the qualifier where_type was used to specify that the quantity applies only to the part of the grid box of the named type. Names containing the where_type qualifier are deprecated and newly created data should use the cell_methods attribute to indicate the horizontal area to which the quantity applies. + + + + K + + + The quantity with standard name temperature_at_base_of_ice_sheet_model is the lower boundary temperature that is used to force ice sheet models. Beneath ice shelves it is the temperature at the ice-ocean interface. Beneath grounded ice, it is the temperature at the ice-bedrock interface. In all instances the temperature is that of the interface itself and not that of the medium above or below the interface. + + + + K + + + The quantity with standard name temperature_at_top_of_ice_sheet_model is the upper boundary temperature that is used to force ice sheet models. It is the temperature at the interface between the ice sheet and the overlying medium which may be snow or the atmosphere. In all instances the temperature is that of the interface itself and not that of the medium above or below the interface. + + + + K + + + This quantity is defined as the temperature difference between a parcel of air lifted adiabatically from a starting air pressure to a finishing air pressure in the troposphere and the ambient air temperature at the finishing air pressure in the troposphere. It is +often called the lifted index (LI) and provides a measure of the instability of the atmosphere. The air parcel is "lifted" by moving the air parcel from the starting air pressure to the Lifting Condensation Level (dry adiabatically) and then from the Lifting Condensation Level to the finishing air pressure (wet adiabatically). Air temperature is +the bulk temperature of the air. Coordinate variables of original_air_pressure_of_lifted_parcel and +final_air_pressure_of_lifted_parcel should be specified to indicate the specific air pressures at which the parcel lifting starts (starting air pressure) and the temperature difference is calculated at (finishing air pressure), respectively. + + + + K + + + This quantity is defined as the temperature difference between a parcel of air lifted adiabatically from the surface to a finishing air pressure in the troposphere and the ambient air temperature at the finishing air pressure in the troposphere. It is often called the lifted index (LI) and provides a measure of the instability of the atmosphere. The air parcel is "lifted" by moving the air parcel from the surface to the Lifting Condensation Level (dry adiabatically) and then from the Lifting Condensation Level to the finishing air pressure (wet adiabatically). Air temperature is the bulk temperature of the air, not the surface (skin) temperature. The term "surface" means the lower boundary of the atmosphere. A coordinate variable of final_air_pressure_of_lifted_parcel should be specified to indicate the specific air pressure that the temperature difference is calculated at. + + + + W m-2 + + + Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) The quantity with standard name temperature_flux_due_to_evaporation_expressed_as_heat_flux_out_of_sea_water is the heat energy carried by the transfer of water away from the liquid ocean through the process of evaporation. It is distinct from the transfer of latent heat and is calculated relative to the heat that would be transported by water evaporating at zero degrees Celsius. It is calculated as the product QevapCpTevap, where Qevap is the mass flux of evaporating water (kg m-2 s-1), Cp is the specific heat capacity of water and Tevap is the temperature in degrees Celsius of the evaporating water. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + + W m-2 + + + The quantity with standard name temperature_flux_due_to_rainfall_expressed_as_heat_flux_into_sea_water is the heat energy carried by rainfall entering the sea at the sea surface. It is calculated relative to the heat that would be carried by rainfall entering the sea at zero degrees Celsius. It is calculated as the product QrainCpTrain, where Qrain is the mass flux of rainfall entering the sea (kg m-2 s-1), Cp is the specific heat capacity of water and Train is the temperature in degrees Celsius of the rain water entering the sea surface. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + + W m-2 + + + Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. The quantity with standard name temperature_flux_due_to_runoff_expressed_as_heat_flux_into_sea_water is the heat carried by the transfer of water into the liquid ocean by the process of runoff. This quantity additonally includes melt water from sea ice and icebergs. It is calculated relative to the heat that would be transported by runoff water entering the sea at zero degrees Celsius. It is calculated as the product QrunoffCpTrunoff, where Q runoff is the mass flux of liquid runoff entering the sea water (kg m-2 s-1), Cp is the specific heat capacity of water, and Trunoff is the temperature in degrees Celsius of the runoff water. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + + K + E238 + + "Temperature in surface snow" is the bulk temperature of the snow, not the surface (skin) temperature. The surface called "surface" means the lower boundary of the atmosphere. + + + + K + + + Temperature_of_sensor_for_oxygen_in_sea_water is the instrument temperature used in calculating the concentration of oxygen in sea water; it is not a measurement of the ambient water temperature. + + + + kg m-3 s-1 + + + "tendency_of_X" means derivative of X with respect to time. + + + + Pa s-1 + 3 + + "tendency_of_X" means derivative of X with respect to time. Air pressure is the force per unit area which would be exerted when the moving gas molecules of which the air is composed strike a theoretical surface of any orientation. + + + + K s-1 + + + "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + + + K s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + + + K s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Boundary layer mixing" means turbulent motions that transport heat, water, momentum and chemical constituents within the atmospheric boundary layer and affect exchanges between the surface and the atmosphere. The atmospheric boundary layer is typically characterised by a well-mixed sub-cloud layer of order 500 metres, and by a more extended conditionally unstable layer with boundary-layer clouds up to 2 km. (Reference: IPCC Third Assessment Report, Working Group 1: The Scientific Basis, 7.2.2.3, https://www.ipcc.ch/ipccreports/tar/wg1/273.htm). + + + + K s-1 + + + Air temperature is the bulk temperature of the air, not the surface (skin) temperature. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + K s-1 + + tnt + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + + + K s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + + + K s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Nonorographic" gravity waves refer to gravity waves which are not generated by flow over orography. The dissipation of gravity waves generates heating through an eddy heat flux convergence and through a viscous stress term. + + + + K s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Orographic gravity waves" refer to gravity waves which are generated by flow over orography. The dissipation of gravity waves generates heating through an eddy heat flux convergence and through a viscous stress term. + + + + K s-1 + + tntdc + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + + + K s-1 + + tntlw + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "longwave" means longwave radiation. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + + + K s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "tendency_of_X" means derivative of X with respect to time. "longwave" means longwave radiation. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + + + K s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The term "longwave" means longwave radiation. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". Volcanic aerosols include both volcanic ash and secondary products such as sulphate aerosols formed from gaseous emissions of volcanic eruptions. + + + + K s-1 + + + Air temperature is the bulk temperature of the air, not the surface (skin) temperature. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + K s-1 + + tntmc + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + + + K s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + + + K s-1 + + tntsw + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "shortwave" means shortwave radiation. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + + + K s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "tendency_of_X" means derivative of X with respect to time. "shortwave" means shortwave radiation. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + + + K s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The term "shortwave" means shortwave radiation. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". Volcanic aerosols include both volcanic ash and secondary products such as sulphate aerosols formed from gaseous emissions of volcanic eruptions. + + + + K s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). "Precipitation" in the earth's atmosphere means precipitation of water in all phases. A variable with the standard name tendency_of_air_temperature_due_to_stratiform_cloud_and_precipitation should contain net latent heating effects of all processes which convert stratiform clouds and precipitation between water vapor, liquid or ice phases. + + + + K s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). "Precipitation" in the earth's atmosphere means precipitation of water in all phases. "Boundary layer mixing" means turbulent motions that transport heat, water, momentum and chemical constituents within the atmospheric boundary layer and affect exchanges between the surface and the atmosphere. The atmospheric boundary layer is typically characterised by a well-mixed sub-cloud layer of order 500 metres, and by a more extended conditionally unstable layer with boundary-layer clouds up to 2 km. (Reference: IPCC Third Assessment Report, Working Group 1: The Scientific Basis, 7.2.2.3, https://www.ipcc.ch/ipccreports/tar/wg1/273.htm). + + + + K s-1 + + tntlsp + The phrase "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). "Precipitation" in the earth's atmosphere means precipitation of water in all phases. + + + + K s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + + + W m-2 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Dry energy is the sum of dry static energy and kinetic energy. Dry static energy is the sum of enthalpy and potential energy (itself the sum of gravitational and centripetal potential energy). Enthalpy can be written either as (1) CpT, where Cp is heat capacity at constant pressure, T is absolute temperature, or (2) U+pV, where U is internal energy, p is pressure and V is volume. + + + + W m-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Enthalpy can be written either as (1) CpT, where Cp is heat capacity at constant pressure, T is absolute temperature, or (2) U+pV, where U is internal energy, p is pressure and V is volume. + + + + W m-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. The chemical formula for acetaldehyde is CH3CHO. The IUPAC name for acetaldehyde is ethanal. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. The chemical formula for acetaldehyde is CH3CHO. The IUPAC name for acetaldehyde is ethanal. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. The chemical formula for acetaldehyde is CH3CHO. The IUPAC name for acetaldehyde is ethanal. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for acetic_acid is CH3COOH. The IUPAC name for acetic acid is ethanoic acid. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Wet deposition" means deposition by precipitation. The chemical formula for acetic_acid is CH3COOH. The IUPAC name for acetic acid is ethanoic acid. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. Acetone is an organic molecule with the chemical formula CH3CH3CO. The IUPAC name for acetone is propan-2-one. Acetone is a member of the group of organic compounds known as ketones. There are standard names for the ketone group as well as for some of the individual species. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for aceto-nitrile is CH3CN. The IUPAC name for aceto-nitrile is ethanenitrile. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Alcohols include all organic compounds with an alcoholic (OH) group. In standard names "alcohols" is the term used to describe the group of chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Alcohols include all organic compounds with an alcoholic (OH) group. In standard names "alcohols" is the term used to describe the group of chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Alcohols include all organic compounds with an alcoholic (OH) group. In standard names "alcohols" is the term used to describe the group of chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Alcohols include all organic compounds with an alcoholic (OH) group. In standard names "alcohols" is the term used to describe the group of chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Alcohols include all organic compounds with an alcoholic (OH) group. In standard names "alcohols" is the term used to describe the group of chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Alcohols include all organic compounds with an alcoholic (OH) group. In standard names "alcohols" is the term used to describe the group of chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Alcohols include all organic compounds with an alcoholic (OH) group. In standard names "alcohols" is the term used to describe the group of chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Alcohols include all organic compounds with an alcoholic (OH) group. In standard names "alcohols" is the term used to describe the group of chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "solvent production and use" sector comprises industrial processes related to the consumption of halocarbons, SF6, solvent and other product use. "Solvent production and use" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 2F and 3 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Alcohols include all organic compounds with an alcoholic (OH) group. In standard names "alcohols" is the term used to describe the group of chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. Aldehydes are organic compounds with a CHO group; "aldehydes" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual aldehyde species, e.g., formaldehyde and acetyladehyde. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. Aldehydes are organic compounds with a CHO group; "aldehydes" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual aldehyde species, e.g., formaldehyde and acetyladehyde. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. Alkanes are saturated hydrocarbons, i.e. they do not contain any chemical double bonds. "Hydrocarbon" means a compound containing hydrogen and carbon. Alkanes contain only hydrogen and carbon combined in the general proportions C(n)H(2n+2); "alkanes" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual alkane species, e.g., methane and ethane. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. Alkenes are unsaturated hydrocarbons as they contain chemical double bonds between adjacent carbon atoms. "Hydrocarbon" means a compound containing hydrogen and carbon. Alkenes contain only hydrogen and carbon combined in the general proportions C(n)H(2n); "alkenes" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual alkene species, e.g., ethene and propene. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Re-emission" refers to emission that is not from a primary source; it refers to emission of a species that has previously been deposited and accumulated in soils or water. "Re-emission" is a process entirely distinct from "emission" which is used in some standard names. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Wet deposition" means deposition by precipitation. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for alpha_pinene is C10H16. The IUPAC name for alpha-pinene is (1S,5S)-2,6,6-trimethylbicyclo[3.1.1]hept-2-ene. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ammonia is NH3. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ammonia is NH3. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ammonia is NH3. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. he chemical formula for ammonia is NH3. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ammonia is NH3. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ammonia is NH3. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ammonia is NH3. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ammonia is NH3. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Wet deposition" means deposition by precipitation. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. The chemical formula for ammonium is NH4. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. The chemical formula for ammonium is NH4. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. Aromatic compounds in organic chemistry are compounds that contain at least one benzene ring of six carbon atoms joined by alternating single and double covalent bonds. The simplest aromatic compound is benzene itself. In standard names "aromatic_compounds" is the term used to describe the group of aromatic chemical species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual aromatic species, e.g. benzene and xylene. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for beta_pinene is C10H16. The IUPAC name for beta-pinene is (1S,5S)-6,6-dimethyl-2-methylenebicyclo[3.1.1]heptane. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Biogenic" means influenced, caused, or created by natural processes. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon dioxide is CO2. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon dioxide is CO2. "Anthropogenic" means influenced, caused, or created by human activity. Anthropogenic emission of carbon dioxide includes fossil fuel use, cement production, agricultural burning and sources associated with anthropogenic land use change, except forest regrowth. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The chemical formula for carbon dioxide is CO2. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Examples of "forestry and agricultural products" are paper, cardboard, furniture, timber for construction, biofuels and food for both humans and livestock. Models that simulate land use changes have one or more pools of carbon that represent these products in order to conserve carbon and allow its eventual release into the atmosphere, for example, when the products decompose in landfill sites. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon dioxide is CO2. Fossil fuel combustion includes cement production and flaring of natural gas. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula of carbon monoxide is CO. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon monoxide is CO. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon monoxide is CO. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon monoxide is CO. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon monoxide is CO. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon monoxide is CO. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon monoxide is CO. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon monoxide is CO. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon monoxide is CO. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon monoxide is CO. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for carbon monoxide is CO. The "solvent production and use" sector comprises industrial processes related to the consumption of halocarbons, SF6, solvent and other product use. "Solvent production and use" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 2F and 3 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon monoxide is CO. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of carbon tetrachloride is CCl4. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of CFC113a CCl3CF3. The IUPAC name for CFC113a is 1,1,1-trichloro-2,2,2-trifluoro-ethane. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of CFC113 is CCl2FCClF2. The IUPAC name for CFC113 is 1,1,2-trichloro-1,2,2-trifluoro-ethane. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of CFC114 is CClF2CClF2. The IUPAC name for CFC114 is 1,2-dichloro-1,1,2,2-tetrafluoro-ethane. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of CFC115 is CClF2CF3. The IUPAC name for CFC115 is 1-chloro-1,1,2,2,2-pentafluoro-ethane. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula of CFC11 is CFCl3. The IUPAC name fof CFC11 is trichloro-fluoro-methane. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for CFC12 is CF2Cl2. The IUPAC name for CFC12 is dichloro-difluoro-methane. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Chlorinated hydrocarbons are a group of chemicals composed of carbon, chlorine and hydrogen. As pesticides, they are also referred to by several other names, including chlorinated organics, chlorinated insecticides and chlorinated synthetics. In standard names "chlorinated_hydrocarbons" is the term used to describe the group of chlorinated hydrocarbon species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Chlorinated hydrocarbons are a group of chemicals composed of carbon, chlorine and hydrogen. As pesticides, they are also referred to by several other names, including chlorinated organics, chlorinated insecticides and chlorinated synthetics. In standard names "chlorinated_hydrocarbons" is the term used to describe the group of chlorinated hydrocarbon species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Chlorinated hydrocarbons are a group of chemicals composed of carbon, chlorine and hydrogen. As pesticides, they are also referred to by several other names, including chlorinated organics, chlorinated insecticides and chlorinated synthetics. In standard names "chlorinated_hydrocarbons" is the term used to describe the group of chlorinated hydrocarbon species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Chlorinated hydrocarbons are a group of chemicals composed of carbon, chlorine and hydrogen. As pesticides, they are also referred to by several other names, including chlorinated organics, chlorinated insecticides and chlorinated synthetics. In standard names "chlorinated_hydrocarbons" is the term used to describe the group of chlorinated hydrocarbon species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "solvent production and use" sector comprises industrial processes related to the consumption of halocarbons, SF6, solvent and other product use. "Solvent production and use" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 2F and 3 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Chlorinated hydrocarbons are a group of chemicals composed of carbon, chlorine and hydrogen. As pesticides, they are also referred to by several other names, including chlorinated organics, chlorinated insecticides and chlorinated synthetics. In standard names "chlorinated_hydrocarbons" is the term used to describe the group of chlorinated hydrocarbon species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for dimethyl sulfide is (CH3)2S. Dimethyl sulfide is sometimes referred to as DMS. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for dimethyl sulfide is (CH3)2S. Dimethyl sulfide is sometimes referred to as DMS. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Deposition" is the sum of wet and dry deposition. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The sum of turbulent deposition and gravitational settling is dry deposition. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The sum of turbulent deposition and gravitational settling is dry deposition. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Wet deposition" means deposition by precipitation. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol partilces" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The mass is the total mass of the particles. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. The sum of turbulent deposition and gravitational settling is dry deposition. Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the molecules. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The sum of turbulent deposition and gravitational settling is dry deposition. "tendency_of_X" means derivative of X with respect to time. Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Esters in organic chemistry are chemical compounds derived by reacting an oxoacid with a hydroxyl compound such as an alcohol or phenol. Esters are usually derived from an inorganic acid or organic acid in which at least one -OH (hydroxyl) group is replaced by an -O-alkyl (alkoxy) group, and most commonly from carboxylic acids and alcohols. That is, esters are formed by condensing an acid with an alcohol. In standard names "esters" is the term used to describe the group of ester species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Esters in organic chemistry are chemical compounds derived by reacting an oxoacid with a hydroxyl compound such as an alcohol or phenol. Esters are usually derived from an inorganic acid or organic acid in which at least one -OH (hydroxyl) group is replaced by an -O-alkyl (alkoxy) group, and most commonly from carboxylic acids and alcohols. That is, esters are formed by condensing an acid with an alcohol. In standard names "esters" is the term used to describe the group of ester species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "solvent production and use" sector comprises industrial processes related to the consumption of halocarbons, SF6, solvent and other product use. "Solvent production and use" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 2F and 3 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Esters in organic chemistry are chemical compounds derived by reacting an oxoacid with a hydroxyl compound such as an alcohol or phenol. Esters are usually derived from an inorganic acid or organic acid in which at least one -OH (hydroxyl) group is replaced by an -O-alkyl (alkoxy) group, and most commonly from carboxylic acids and alcohols. That is, esters are formed by condensing an acid with an alcohol. In standard names "esters" is the term used to describe the group of ester species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The phrase "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The phrase "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethanol is C2H5OH. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The phrase "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Ethers are a class of organic compounds that contain an ether group - an oxygen atom connected to two alkyl or aryl groups - of general formula R-O-R. In standard names "ethers" is the term used to describe the group of ether species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Ethers are a class of organic compounds that contain an ether group - an oxygen atom connected to two alkyl or aryl groups - of general formula R-O-R. In standard names "ethers" is the term used to describe the group of ether species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Ethers are a class of organic compounds that contain an ether group - an oxygen atom connected to two alkyl or aryl groups - of general formula R-O-R. In standard names "ethers" is the term used to describe the group of ether species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Ethers are a class of organic compounds that contain an ether group - an oxygen atom connected to two alkyl or aryl groups - of general formula R-O-R. In standard names "ethers" is the term used to describe the group of ether species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Ethers are a class of organic compounds that contain an ether group - an oxygen atom connected to two alkyl or aryl groups - of general formula R-O-R. In standard names "ethers" is the term used to describe the group of ether species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Ethers are a class of organic compounds that contain an ether group - an oxygen atom connected to two alkyl or aryl groups - of general formula R-O-R. In standard names "ethers" is the term used to describe the group of ether species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "solvent production and use" sector comprises industrial processes related to the consumption of halocarbons, SF6, solvent and other product use. "Solvent production and use" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 2F and 3 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Ethers are a class of organic compounds that contain an ether group - an oxygen atom connected to two alkyl or aryl groups - of general formula R-O-R. In standard names "ethers" is the term used to describe the group of ether species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The phrase "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for formic acid is HCOOH. The IUPAC name for formic acid is methanoic acid. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Wet deposition" means deposition by precipitation. The chemical formula for formic acid is HCOOH. The IUPAC name for formic acid is methanoic acid. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Divalent mercury" means all compounds in which the mercury has two binding sites to other ion(s) in a salt or to other atom(s) in a molecule. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Divalent mercury" means all compounds in which the mercury has two binding sites to other ion(s) in a salt or to other atom(s) in a molecule. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Divalent mercury" means all compounds in which the mercury has two binding sites to other ion(s) in a salt or to other atom(s) in a molecule. "Wet deposition" means deposition by precipitation. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Wet deposition" means deposition by precipitation. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for halon1202 is CBr2F2. The IUPAC name for halon1202 is dibromo-difluoro-methane. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for halon1211 is CBrClF2. The IUPAC name for halon1211 is bromo-chloro-difluoro-methane. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for halon1301 is CBrF3. The IUPAC name for halon1301 is bromo-trifluoro-methane. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for halo2402 is C2Br2F4. The IUPAC name for halon2402 is 1,2-dibromo-1,1,2,2-tetrafluoro-ethane. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for hcc140a is CH3CCl3. The IUPAC name for hcc140a is 1,1,1-trichloro-ethane. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for HCFC141b is CH3CCl2F. The IUPAC name for HCFC141b is 1,1-dichloro-1-fluoroethane. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for HCFC142b is CH3CClF2. The IUPAC name for HCFC142b is 1-chloro-1,1-difluoroethane. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for HCFC22 is CHClF2. The IUPAC name for HCFC22 is chloro-difluoro-methane. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Re-emission" refers to emission that is not from a primary source; it refers to emission of a species that has previously been deposited and accumulated in soils or water. "Re-emission" is a process entirely distinct from "emission" which is used in some standard names. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Wet deposition" means deposition by precipitation. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for hydrogen cyanide is HCN. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for hydrogen cyanide is HCN. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for hydrogen peroxide is H2O2. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. The chemical formula for hydrogen peroxide is H2O2. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Insoluble aerosol" means aerosol which is not soluble in water, such as mineral dusts. At low temperatures such particles can be efficient nuclei for ice clouds. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Deposition" is the sum of wet and dry deposition. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for isoprene is CH2=C(CH3)CH=CH2. The IUPAC name for isoprene is 2-methyl-buta-1,3-diene. Isoprene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for isoprene is CH2=C(CH3)CH=CH2. The IUPAC name for isoprene is 2-methyl-buta-1,3-diene. Isoprene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for isoprene is CH2=C(CH3)CH=CH2. The IUPAC name for isoprene is 2-methyl-buta-1,3-diene. Isoprene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "solvent production and use" sector comprises industrial processes related to the consumption of halocarbons, SF6, solvent and other product use. "Solvent production and use" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 2F and 3 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. In organic chemistry, a ketone is a compound with the structure RC(=O)R', where R and R' can be a variety of atoms and groups of atoms. It features a carbonyl group (C=O) bonded to two other carbon atoms. Acetone is the simplest example of a ketone. In standard names "ketones" is the term used to describe the group of ketone species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for limonene is C10H16. The IUPAC name for limonene is 1-methyl-4-prop-1-en-2-yl-cyclohexene. Limonene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. he chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Net chemical production" means the net result of all chemical reactions within the atmosphere that produce or destroy a particular species. "tendency_of_X" means derivative of X with respect to time. The chemical formula for methanesulfonic acid is CH3SO3H. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. The chemical formula for methanesulfonic acid is CH3SO3H. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. The chemical formula for methanesulfonic acid is CH3SO3H. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methanol is CH3OH. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methyl bromide is CH3Br. The IUPAC name for methyl bromide is bromomethane. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for methyl chloride is CH3Cl. The IUPAC name for methyl chloride is chloromethane. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for molecular hydrogen is H2. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for molecular hydrogen is H2. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for molecular hydrogen is H2. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for molecular hydrogen is H2. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. Monoterpenes are a class of terpenes that consist of two isoprene units and have the molecular formula C10H16. Terpenes are hydrocarbons. The term "monoterpenes" is used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. The chemical formula for the nitrate anion is NO3-. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Net chemical production" means the net result of all chemical reactions within the atmosphere that produce or destroy a particular species. "tendency_of_X" means derivative of X with respect to time. The chemical formula for the nitrate anion is NO3-. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. The chemical formula for the nitrate anion is NO3-. + + + + kg m-2 s-1 + + + quot;Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Wet deposition" means deposition by precipitation. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Nitrogen compounds" summarizes all chemical species containing nitrogen atoms. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Anthropogenic" means influenced, caused, or created by human activity. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Nitrogen compounds" summarizes all chemical species containing nitrogen atoms. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Anthropogenic" means influenced, caused, or created by human activity. "Anthropogenic land use change" means human changes to land, excluding forest regrowth. It includes fires ignited by humans for the purpose of land use change and the processes of eventual disposal and decomposition of wood products such as paper, cardboard, furniture and timber for construction. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "tendency_of_X" means derivative of X with respect to time. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Deposition" is the sum of wet and dry deposition. "Nitrogen compounds" summarizes all chemical species containing nitrogen atoms. Usually, particle bound and gaseous nitrogen compounds, such as atomic nitrogen (N), nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), nitrate (NO3-), peroxynitric acid (HNO4), ammonia (NH3), ammonium (NH4+), bromine nitrate (BrONO2), chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)) are included. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "tendency_of_X" means derivative of X with respect to time. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "dry_deposition" is the sum of turbulent deposition and gravitational settling. "Nitrogen compounds" summarizes all chemical species containing nitrogen atoms. Usually, particle bound and gaseous nitrogen compounds, such as atomic nitrogen (N), nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), nitrate (NO3-), peroxynitric acid (HNO4), ammonia (NH3), ammonium (NH4+), bromine nitrate (BrONO2), chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)) are included. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "tendency_of_X" means derivative of X with respect to time. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "wet_deposition" means deposition by precipitation. "Nitrogen compounds" summarizes all chemical species containing nitrogen atoms. Usually, particle bound and gaseous nitrogen compounds, such as atomic nitrogen (N), nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), nitrate (NO3-), peroxynitric acid (HNO4), ammon1a (NH3), ammonium (NH4+), bromine nitrate (BrONO2), chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)) are included. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen dioxide is NO2. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen dioxide is NO2. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen dioxide is NO2. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for nitrous acid is HNO2. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrous acid is HNO2. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. The chemical formula for nitrous acid is HNO2. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for nitrous oxide is N2O. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrous oxide is N2O. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "solvent production and use" sector comprises industrial processes related to the consumption of halocarbons, SF6, solvent and other product use. "Solvent production and use" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 2F and 3 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. "nmvoc" means non methane volatile organic compounds. "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Nox" means nitric oxide (NO) and nitrogen dioxide (NO2). "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. The chemical formula for nitrogen monoxide is NO. "Nox" means a combination of two radical species containing nitrogen and oxygen NO+NO2. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "Noy" describes a family of chemical species. The family usually includes atomic nitrogen (N), nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), peroxynitric acid (HNO4), bromine nitrate (BrONO2), chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)). The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. "Noy" describes a family of chemical species. The family usually includes atomic nitrogen (N), nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), peroxynitric acid (HNO4), bromine nitrate (BrONO2), chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)). The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. An organic acid is an organic compound with acidic properties. The most common organic acids are the carboxylic acids, whose acidity is associated with their carboxyl group -COOH. In standard names "organic_acids" is the term used to describe the group of organic acid species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. An organic acid is an organic compound with acidic properties. The most common organic acids are the carboxylic acids, whose acidity is associated with their carboxyl group -COOH. In standard names "organic_acids" is the term used to describe the group of organic acid species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. An organic acid is an organic compound with acidic properties. The most common organic acids are the carboxylic acids, whose acidity is associated with their carboxyl group -COOH. In standard names "organic_acids" is the term used to describe the group of organic acid species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. An organic acid is an organic compound with acidic properties. The most common organic acids are the carboxylic acids, whose acidity is associated with their carboxyl group -COOH. In standard names "organic_acids" is the term used to describe the group of organic acid species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. An organic acid is an organic compound with acidic properties. The most common organic acids are the carboxylic acids, whose acidity is associated with their carboxyl group -COOH. In standard names "organic_acids" is the term used to describe the group of organic acid species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. An organic acid is an organic compound with acidic properties. The most common organic acids are the carboxylic acids, whose acidity is associated with their carboxyl group -COOH. In standard names "organic_acids" is the term used to describe the group of organic acid species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. An organic acid is an organic compound with acidic properties. The most common organic acids are the carboxylic acids, whose acidity is associated with their carboxyl group -COOH. In standard names "organic_acids" is the term used to describe the group of organic acid species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. An organic acid is an organic compound with acidic properties. The most common organic acids are the carboxylic acids, whose acidity is associated with their carboxyl group -COOH. In standard names "organic_acids" is the term used to describe the group of organic acid species that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. Organic nitrates are nitrogen-containing compounds having the general formula RONO2, where R is an alkyl (or organic) group; "organic nitrates" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. Organic nitrates are nitrogen-containing compounds having the general formula RONO2, where R is an alkyl (or organic) group; "organic_nitrates" is the term used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. Organic peroxides are organic molecules containing an oxygen-oxygen bond. The general chemical formula is ROOR or ROOH, where R is an organic group. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. Organic peroxides are organic molecules containing an oxygen-oxygen bond. The general chemical formula is ROOR or ROOH, where R is an organic group. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Deposition" is the sum of wet and dry deposition. "Oxidized nitrogen compounds" means all chemical species containing nitrogen atoms with an oxidation state greater than zero. Usually, particle bound and gaseous nitrogen compounds, such as nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), nitrate (NO3-), peroxynitric acid (HNO4), bromine nitrate (BrONO2), chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)), are included. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "Oxidized nitrogen compounds" means all chemical species containing nitrogen atoms with an oxidation state greater than zero. Usually, particle bound and gaseous nitrogen compounds, such as nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), nitrate (NO3-), peroxynitric acid (HNO4), bromine nitrate (BrONO2), chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)), are included. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "Oxidized nitrogen compounds" means all chemical species containing nitrogen atoms with an oxidation state greater than zero. Usually, particle bound and gaseous nitrogen compounds, such as nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), nitrate (NO3-), peroxynitric acid (HNO4), bromine nitrate (BrONO2), chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)), are included. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition"is the sum of turbulent deposition and gravitational settling. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except black carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The sum of turbulent deposition and gravitational settling is dry deposition. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Net chemical production" means the net result of all chemical reactions within the atmosphere that produce or destroy a particular species. "tendency_of_X" means derivative of X with respect to time. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol.The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The sum of turbulent deposition and gravitational settling is dry deposition. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except black carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except black carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. "Primary particulate organic matter " means all organic matter emitted directly to the atmosphere as particles except elemental carbon. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The "waste treatment and disposal" sector comprises solid waste disposal on land, waste water handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The term "particulate_organic_matter_dry_aerosol" means all particulate organic matter dry aerosol except elemental carbon. It is the sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for pentane is C5H12. Pentane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for pentane is C5H12. Pentane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for pentane is C5H12. Pentane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for pentane is C5H12. Pentane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for pentane is C5H12. Pentane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for pentane is C5H12. Pentane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for pentane is C5H12. Pentane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for pentane is C5H12. Pentane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for peroxyacetyl nitrate, sometimes referred to as PAN, is CH3COO2NO2. The IUPAC name for peroxyacetyl_nitrate is nitroethaneperoxoate. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for peroxynitric acid, sometimes referred to as PNA, is HO2NO2. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm10 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 10 micrometers. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Pm2p5 aerosol" means atmospheric particulate compounds with an aerodynamic diameter of less than or equal to 2.5 micrometers. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol."Dry aerosol particles" means aerosol particles without any water uptake. "Primary particulate organic matter " means all organic matter emitted directly to the atmosphere as particles except elemental carbon. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. "Primary particulate organic matter " means all organic matter emitted directly to the atmosphere as particles except elemental carbon. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical symbol for radon is Rn. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Deposition" is the sum of wet and dry deposition. "Reduced nitrogen compounds" means all chemical species containing nitrogen atoms with an oxidation state less than zero. Usually, particle bound and gaseous nitrogen compounds, primarily ammonium (NH4+) and ammonia (NH3), are included. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "Reduced nitrogen compounds" means all chemical species containing nitrogen atoms with an oxidation state less than zero. Usually, particle bound and gaseous nitrogen compounds, primarily ammonium (NH4+) and ammonia (NH3), are included. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "Reduced nitrogen compounds" means all chemical species containing nitrogen atoms with an oxidation state less than zero. Usually, particle bound and gaseous nitrogen compounds, primarily ammonium (NH4+) and ammonia (NH3), are included. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The sum of turbulent deposition and gravitational settling is dry deposition. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The sum of turbulent deposition and gravitational settling is dry deposition. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Secondary particulate organic matter" means particulate organic matter formed within the atmosphere from gaseous precursors. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Secondary particulate organic matter" means particulate organic matter formed within the atmosphere from gaseous precursors. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Net chemical production" means the net result of all chemical reactions within the atmosphere that produce or destroy a particular species. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "Secondary particulate organic matter" means particulate organic matter formed within the atmosphere from gaseous precursors. The sum of primary_particulate_organic_matter_dry_aerosol and secondary_particulate_organic_matter_dry_aerosol is particulate_organic_matter_dry_aerosol. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. Terpenes are hydrocarbons, that is, they contain only hydrogen and carbon combined in the general proportions (C5H8)n where n is an integer greater than on equal to one. Sesquiterpenes are a class of terpenes that consist of three isoprene units and have the molecular formula C15H24. Terpenes are hydrocarbons. The term "sesquiterpenes" is used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. The chemical formula for the sulfate anion is SO4(2-). + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Net chemical production" means the net result of all chemical reactions within the atmosphere that produce or destroy a particular species. "Aqueous phase net chemical production" means the net result of all aqueous chemical processes in fog and clouds that produce or destroy a species, as opposed to chemical processes in the gaseous phase. "tendency_of_X" means derivative of X with respect to time. The chemical formula for the sulfate anion is SO4(2-). + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. The chemical formula for the sulfate anion is SO4(2-). + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "tendency_of_X" means derivative of X with respect to time. The chemical formula for the sulfate anion is SO4(2-). + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Gaseous phase net chemical production" means the net result of all gaseous chemical processes in the atmosphere that produce or destroy a species, distinct from chemical processes in the aqueous phase. "tendency_of_X" means derivative of X with respect to time. The chemical formula for the sulfate anion is SO4(2-). + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the particles. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. The chemical formula for the sulfate anion is SO4(2-). + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. The chemical formula for the sulfate anion is SO4(2-). + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The sum of turbulent deposition and gravitational settling is dry deposition. "tendency_of_X" means derivative of X with respect to time. The chemical formula for the sulfate anion is SO4(2-). + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The sum of turbulent deposition and gravitational settling is dry deposition. "tendency_of_X" means derivative of X with respect to time. The chemical formula for the sulfate anion is SO4(2-). + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dry deposition" is the sum of turbulent deposition and gravitational settling. The chemical formula for sulfur dioxide is SO2. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for sulfur dioxide is SO2. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for sulfur dioxide is SO2. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for sulfur dioxide is SO2. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for sulfur dioxide is SO2. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for sulfur dioxide is SO2. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for sulfur dioxide is SO2. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for sulfur dioxide is SO2. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for sulfur dioxide is SO2. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for sulfur dioxide is SO2. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Wet deposition" means deposition by precipitation. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Terpenes are hydrocarbons, that is, they contain only hydrogen and carbon combined in the general proportions (C5H8)n where n is an integer greater than on equal to one. The term "terpenes" is used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual terpene species, e.g., isoprene and limonene. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. Terpenes are hydrocarbons, that is, they contain only hydrogen and carbon combined in the general proportions (C5H8)n where n is an integer greater than on equal to one. The term "terpenes" is used in standard names to describe the group of chemical species having this common structure that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names exist for some individual terpene species, e.g., isoprene and limonene. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "solvent production and use" sector comprises industrial processes related to the consumption of halocarbons, SF6, solvent and other product use. "Solvent production and use" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 2F and 3 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for trimethylbenzene is C9H12. The IUPAC names for trimethylbenzene is 1,3,5-trimethylbenzene. Trimethylbenzene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Water" means water in all phases. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Atmosphere water vapor content is sometimes referred to as "precipitable water", although this term does not imply the water could all be precipitated. + + + + kg m-2 s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Atmosphere water vapor content is sometimes referred to as "precipitable water", although this term does not imply the water could all be precipitated. + + + + kg m-2 s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Atmosphere water vapor content is sometimes referred to as "precipitable water", although this term does not imply the water could all be precipitated. + + + + kg m-2 s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Atmosphere water vapor content is sometimes referred to as "precipitable water", although this term does not imply the water could all be precipitated. + + + + kg m-2 s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Atmosphere water vapor content is sometimes referred to as "precipitable water", although this term does not imply the water could all be precipitated. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Atmosphere water vapor content is sometimes referred to as "precipitable water", although this term does not imply the water could all be precipitated. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Sublimation is the conversion of solid into vapor. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Atmosphere water vapor content is sometimes referred to as "precipitable water", although this term does not imply the water could all be precipitated. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Sublimation is the conversion of solid into vapor. The phrase "surface_snow" means snow lying on the surface. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Atmosphere water vapor content is sometimes referred to as "precipitable water", although this term does not imply the water could all be precipitated. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Sublimation is the conversion of solid into vapor. The phrase "surface_snow" means snow lying on the surface. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. + + + + kg m-2 s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Atmosphere water vapor content is sometimes referred to as "precipitable water", although this term does not imply the water could all be precipitated. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "agricultural production" sector comprises the agricultural processes of enteric fermentation, manure management, rice cultivation, agricultural soils and other. It may also include any not-classified or "other" combustion, which is commonly included in agriculture-related inventory data. "Agricultural production" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 4A, 4B, 4C, 4D and 4G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "agricultural waste burning" sector comprises field burning of agricultural residues. "Agricultural waste burning" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 4F as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "energy production and distribution" sector comprises fuel combustion activities related to energy industries and fugitive emissions from fuels. It may also include any not-classified or "other" combustion, which is commonly included in energy-related inventory data. "Energy production and distribution" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A1 and 1B as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "forest fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in forests. "Forest fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "industrial processes and combustion" sector comprises fuel combustion activities related to manufacturing industries and construction, industrial processes related to mineral products, the chemical industry, metal production, the production of pulp, paper, food and drink, and non-energy industry use of lubricants and waxes. It may also include any not-classified or "other" combustion, which is commonly included in industry-related inventory data. "Industrial processes and combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A2, 2A, 2B, 2C, 2D and 2G as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "land transport" sector includes fuel combustion activities related to road transportation, railways and other transportation. "Land transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A3b, 1A3c and 1A3e as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "maritime transport" sector includes fuel combustion activities related to maritime transport. "Maritime transport" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3d as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "residential and commercial combustion" sector comprises fuel combustion activities related to the commercial/institutional sector, the residential sector and the agriculture/forestry/fishing sector. It may also include any not-classified or "other" combustion, which is commonly included in the inventory data. "Residential and commercial combustion" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 1A4a, 1A4b and 1A4c as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "savanna and grassland fires" sector comprises the burning (natural and human-induced) of living or dead vegetation in non-forested areas. It excludes field burning of agricultural residues. "Savanna and grassland fires" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 5 as defined in the 2006 IPCC guidelines for national greenhouse gas Inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "solvent production and use" sector comprises industrial processes related to the consumption of halocarbons, SF6, solvent and other product use. "Solvent production and use" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 2F and 3 as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including "content_of_atmosphere_layer" are used. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. The "waste treatment and disposal" sector comprises solid waste disposal on land, wastewater handling, waste incineration and other waste disposal. "Waste treatment and disposal" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source categories 6A, 6B, 6C and 6D as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "X_area" means the horizontal area occupied by X within the grid cell. + + + + kg m-2 s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "X_area" means the horizontal area occupied by X within the grid cell. + + + + mole m-3 s-1 + + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Chemical destruction" means the result of all chemical reactions within the medium (here, atmosphere) that remove a certain amount of a particular species from the medium. "tendency_of_X" means derivative of X with respect to time. The chemical formula of carbon monoxide is CO. + + + + mole m-3 s-1 + + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Chemical destruction" means the result of all chemical reactions within the medium (here, atmosphere) that remove a certain amount of a particular species from the medium. "tendency_of_X" means derivative of X with respect to time. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + + + + mol m-3 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The chemical formula for nitrous oxide is N2O. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Chemical destruction" means the result of all chemical reactions within the medium (here, atmosphere) that remove a certain amount of a particular species from the medium. + + + + mole m-3 s-1 + + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Chemical destruction" means the result of all chemical reactions within the medium (here, atmosphere) that remove a certain amount of a particular species from the medium. The chemical formula for ozone is O3. The IUPAC name for ozone is trioxygen. + + + + mole m-3 s-1 + + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Chemical production" means the result of all chemical reactions within the medium (here, atmosphere) that produce a certain amount of the particular species. "tendency_of_X" means derivative of X with respect to time. The chemical formula for ozone is O3. The IUPAC name for ozone is trioxygen. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for acetic_acid is CH3COOH. The IUPAC name for acetic acid is ethanoic acid. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for aceto-nitrile is CH3CN. The IUPAC name for aceto-nitrile is ethanenitrile. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for alpha_hexachlorocyclohexane is C6H6Cl6. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for alpha_pinene is C10H16. The IUPAC name for alpha-pinene is (1S,5S)-2,6,6-trimethylbicyclo[3.1.1]hept-2-ene. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for ammonia is NH3. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Anthropogenic" means influenced, caused, or created by human activity. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical symbol for atomic bromine is Br. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical symbol for atomic chlorine is Cl. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical symbol for atomic nitrogen is N. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for benzene is C6H6. Benzene is the simplest aromatic hydrocarbon and has a ring structure consisting of six carbon atoms joined by alternating single and double chemical bonds. Each carbon atom is additionally bonded to one hydrogen atom. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for beta_pinene is C10H16. The IUPAC name for beta-pinene is (1S,5S)-6,6-dimethyl-2-methylenebicyclo[3.1.1]heptane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Biogenic" means influenced, caused, or created by natural processes. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for bromine chloride is BrCl. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for bromine monoxide is BrO. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for bromine nitrate is BrONO2. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "Brox" describes a family of chemical species consisting of inorganic bromine compounds with the exception of hydrogen bromide (HBr) and bromine nitrate (BrONO2). "Brox" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of source gases containing bromine (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. Standard names that use the term "inorganic_bromine" are used for quantities that contain all inorganic bromine species including HCl and ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for butane is C4H10. Butane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for carbon dioxide is CO2. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere,i.e. summed over the atmospheric column and over the entire globe. The chemical formula ofcarbon monoxide is CO. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere,i.e. summed over the atmospheric column and over the entire globe. The chemical formula ofcarbon tetrachloride is CCl4. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere,i.e. summed over the atmospheric column and over the entire globe. The chemical formula ofCFC11 is CFCl3. The IUPAC name fof CFC11 is trichloro-fluoro-methane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. Thechemical formula of CFC113 is CCl2FCClF2. The IUPAC name for CFC113 is 1,1,2-trichloro-1,2,2-trifluoro-ethane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula of CFC113a CCl3CF3. The IUPAC name for CFC113a is 1,1,1-trichloro-2,2,2-trifluoro-ethane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere,i.e. summed over the atmospheric column and over the entire globe. The chemical formula ofCFC114 is CClF2CClF2. The IUPAC name for CFC114 is 1,2-dichloro-1,1,2,2-tetrafluoro-ethane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. Thechemical formula of CFC115 is CClF2CF3. The IUPAC name for CFC115 is 1-chloro-1,1,2,2,2-pentafluoro-ethane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. Thechemical formula for CFC12 is CF2Cl2. The IUPAC name for CFC12 is dichloro-difluoro-methane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for chlorine dioxide is OClO. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for chlorine monoxide is ClO. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for chlorine nitrate is ClONO2. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "Clox" describes a family of chemical species consisting of inorganic chlorine compounds with the exception of hydrogen chloride (HCl) and chlorine nitrate (ClONO2). "Clox" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity with a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Inorganic chlorine", sometimes referred to as Cly, describes a family of chemical species which result from the degradation of source gases containing chlorine (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as seasalt and other aerosols. Standard names that use the term "inorganic_chlorine" are used for quantities that contain all inorganic chlorine species including HCl and ClONO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for dichlorine peroxide is Cl2O2. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for dimethyl sulfide is (CH3)2S. Dimethyl sulfide is sometimes referred to as DMS. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for dinitrogen pentoxide is N2O5. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for ethane is C2H6. Ethane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for ethanol is C2H5OH. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for ethene is C2H4. Ethene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for ethyne is HC2H. Ethyne is the IUPAC name for this species, which is also commonly known as acetylene. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for formic acid is HCOOH. The IUPAC name for formic acid is methanoic acid. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "Divalent mercury" means all compounds in which the mercury has two binding sites to other ion(s) in a salt or to other atom(s) in a molecule. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical symbol for mercury is Hg. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for halon1202 is CBr2F2. The IUPAC name for halon1202 is dibromo-difluoro-methane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for halon1211 is CBrClF2. The IUPAC name for halon1211 is bromo-chloro-difluoro-methane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for halon1301 is CBrF3. The IUPAC name for halon1301 is bromo-trifluoro-methane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for halo2402 is C2Br2F4. The IUPAC name for halon2402 is 1,2-dibromo-1,1,2,2-tetrafluoro-ethane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for hcc140a is CH3CCl3. The IUPAC name for hcc140a is 1,1,1-trichloro-ethane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for HCFC141b is CH3CCl2F. The IUPAC name for HCFC141b is 1,1-dichloro-1-fluoroethane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for HCFC142b is CH3CClF2. The IUPAC name for HCFC142b is 1-chloro-1,1-difluoroethane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for HCFC22 is CHClF2. The IUPAC name for HCFC22 is chloro-difluoro-methane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for hexachlorobiphenyl is C12H4Cl6. This structure of this species consists of two linked benzene rings, each of which is additionally bonded to three chlorine atoms. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "HOx" means a combination of two radical species containing hydrogen and oxygen: OH and HO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for hydrogen bromide is HBr. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for hydrogen chloride is HCl. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for hydrogen cyanide is HCN. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for hydrogen peroxide is H2O2. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for the hydroperoxyl radical is HO2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for the hydroxyl radical is OH. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for hypobromous acid is HOBr. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for hypochlorous acid is HOCl. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "Inorganic bromine", sometimes referred to as Bry, describes a family of chemical species which result from the degradation of source gases containing bromine (halons, methyl bromide, VSLS) and natural inorganic bromine sources such as volcanoes, seasalt and other aerosols. "Inorganic bromine" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names that use the term "brox" are used for quantities that contain all inorganic bromine species except HBr and BrONO2. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "Inorganic chlorine", sometimes referred to as Cly, describes a family of chemical species which result from the degradation of source gases containing chlorine (CFCs, HCFCs, VSLS) and natural inorganic chlorine sources such as seasalt and other aerosols. "Inorganic chlorine" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. Standard names that use the term "clox" are used for quantities that contain all inorganic chlorine species except HCl and ClONO2. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for isoprene is CH2=C(CH3)CH=CH2. The IUPAC name for isoprene is 2-methyl-buta-1,3-diene. Isoprene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for limonene is C10H16. The IUPAC name for limonene is 1-methyl-4-prop-1-en-2-yl-cyclohexene. Limonene is a member of the group of hydrocarbons known as terpenes. There are standard names for the terpene group as well as for some of the individual species. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere,i.e. summed over the atmospheric column and over the entire globe. The chemical formula for methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. Thereare standard names for the alkane group as well as for some of the individual species. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for methanol is CH3OH. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere,i.e. summed over the atmospheric column and over the entire globe. The chemical formula for methyl bromide is CH3Br. The IUPAC name for methyl bromide is bromomethane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X contained in the entire atmosphere, i.e, summed over the atmospheric column and over the entire globe. The chemical formula of methyl chloride is CH3Cl. The IUPAC name for methyl chloride is chloromethane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for methyl hydroperoxide is CH3OOH. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for methyl_peroxy_radical is CH3O2. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X contained in the entire atmosphere, i.e, summed over the atmospheric column and over the entire globe. The chemical formula of molecular hydrogen is H2. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for nitrate is NO3. In chemistry, a 'radical' is a highly reactive, and therefore shortlived, species. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for nitric acid is HNO3. + + + + mol s-1 + + + The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. "tendency_of_X" means derivative of X with respect to time. The chemical formula for nitric acid is HNO3. Nitric acid trihydrate, sometimes referred to as NAT, is a stable crystalline substance consisting of three molecules of water to one molecule of nitric acid. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for nitrogen dioxide is NO2. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for nitrogen monoxide is NO. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for nitrous acid is HNO2. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X contained in the entire atmosphere, i.e, summed over the atmospheric column and over the entire globe. The chemical formula of nitrous oxide is N2O. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "nmvoc" means non methane volatile organic compounds; "nmvoc" is the term used in standard names to describe the group of chemical species having this classification that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "Noy" describes a family of chemical species. The family usually includes atomic nitrogen (N), nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), peroxynitric acid (HNO4), bromine nitrate (BrONO2) , chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)). The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for ozone is O3. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for peroxyacetyl nitrate, sometimes referred to as PAN, is CH3COO2NO2. The IUPAC name for peroxyacetyl_nitrate is nitroethaneperoxoate. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for peroxynitric acid, sometimes referred to as PNA, is HO2NO2. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for propane is C3H8. Propane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for propene is C3H6. Propene is a member of the group of hydrocarbons known as alkenes. There are standard names for the alkene group as well as for some of the individual species. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical symbol for radon is Rn. + + + + mol s-1 + + + The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol particles take up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the particles. "Dry aerosol particles" means aerosol particles without any water uptake. "tendency_of_X" means derivative of X with respect to time. The chemical formula for the sulfate anion is SO4(2-). + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for sulfur dioxide is SO2. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for toluene is C6H5CH3. Toluene has the same structure as benzene, except that one of the hydrogen atoms is replaced by a methyl group. The systematic name for toluene is methylbenzene. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. The construction "atmosphere_moles_of_X" means the total number of moles of X in the entire atmosphere, i.e. summed over the atmospheric column and over the entire globe. The chemical formula for xylene is C6H4C2H6. In chemistry, xylene is a generic term for a group of three isomers of dimethylbenzene. The IUPAC names for the isomers are 1,2-dimethylbenzene, 1,3-dimethylbenzene and 1,4-dimethylbenzene. Xylene is an aromatic hydrocarbon. There are standard names that refer to aromatic_compounds as a group, as well as those for individual species. + + + + m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Dry deposition" is the sum of turbulent deposition and gravitational settling. "tendency_of_X" means derivative of X with respect to time. + + + + m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The sum of turbulent deposition and gravitational settling is dry deposition. "tendency_of_X" means derivative of X with respect to time. + + + + m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The sum of turbulent deposition and gravitational settling is dry deposition. "tendency_of_X" means derivative of X with respect to time. + + + + m-2 s-1 + + + "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Wet deposition" means deposition by precipitation. "tendency_of_X" means derivative of X with respect to time. + + + + W m-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "atmosphere content" of a quantity refers to the vertical integral from the surface to the top of the atmosphere. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) + + + + m s-1 + + + "tendency_of_X" means derivative of X with respect to time. Altitude is the (geometric) height above the geoid, which is the reference geopotential surface. The geoid is similar to mean sea level. "Bedrock" is the solid Earth surface beneath land ice or ocean water. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Amount" means mass per unit area. "Water" means water in all phases. "Canopy" means the vegetative covering over a surface. The canopy is often considered to be the outer surfaces of the vegetation. Plant height and the distribution, orientation and shape of plant leaves within a canopy influence the atmospheric environment and many plant processes within the canopy. Reference: AMS Glossary http://glossary.ametsoc.org/wiki/Canopy. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation"). Canopy interception is the precipitation, including snow, that is intercepted by the canopy of a tree and then evaporates from the leaves. Evaporation of intercepted precipitation excludes plant transpiration and evaporation from the surface beneath the canopy. + + + + kg m-2 s-1 + + + "Amount" means mass per unit area. Zero change in land ice amount is an arbitrary level. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. "tendency_of_X" means derivative of X with respect to time. + + + + W m-2 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Dry energy is the sum of dry static energy and kinetic energy. Dry static energy is the sum of enthalpy and potential energy (itself the sum of gravitational and centripetal potential energy). Enthalpy can be written either as (1) CpT, where Cp is heat capacity at constant pressure, T is absolute temperature, or (2) U+pV, where U is internal energy, p is pressure and V is volume. + + + + W m-2 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Dry static energy is the sum of enthalpy and potential energy (itself the sum of gravitational and centripetal potential energy). Enthalpy can be written either as (1) CpT, where Cp is heat capacity at constant pressure, T is absolute temperature, or (2) U+pV, where U is internal energy, p is pressure and V is volume. + + + + m s-2 + + tnmmutot + "tendency_of_X" means derivative of X with respect to time. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + + + m s-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + + + m s-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name "upward_air_velocity"). The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The "Transformed Eulerian Mean" refers to a formulation of the mean equations which incorporates some eddy terms into the definition of the mean, described in Andrews et al (1987): Middle Atmospheric Dynamics. Academic Press. + + + + m s-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name "upward_air_velocity"). The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The "Transformed Eulerian Mean" refers to a formulation of the mean equations which incorporates some eddy terms into the definition of the mean, described in Andrews et al (1987): Middle Atmospheric Dynamics. Academic Press. + + + + m s-2 + + tnmmuc + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + + + m s-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + + + m s-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Eliassen Palm flux" is a widely used vector in the meridional plane, and the divergence of this flux appears as a forcing in the Transformed Eulerian mean formulation of the zonal mean zonal wind equation. Thus, "eastward_wind" here will generally be the zonally averaged eastward wind. + + + + m s-2 + + tnmmugwd + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) The quantity named tendency_of_eastward_wind_due_to_gravity_wave_drag is the sum of the tendencies due to orographic and nonorographic gravity waves which have standard names of tendency_of_eastward_wind_due_to_orographic_gravity_wave_drag and tendency_of_eastward_wind_due_to_nonorographic_gravity_wave_drag, respectively. + + + + m s-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). The total tendency of the eastward wind due to gravity waves has the standard name tendency_of_eastward_wind_due_to_gravity_wave_drag. It is the sum of the tendencies due to orographic gravity waves and nonorographic waves. The tendency of eastward wind due to orographic gravity waves has the standard name tendency_of_eastward_wind_due_to_orographic_gravity_wave_drag. + + + + m s-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). The total tendency of the eastward wind will include a variety of numerical and diffusive effects: a variable with this standard name is sometimes needed to allow the momentum budget to be closed. + + + + m s-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). The total tendency of the eastward wind due to gravity waves has the standard name tendency_of_eastward_wind_due_to_gravity_wave_drag. It is the sum of the tendencies due to orographic gravity waves and nonorographic waves. The tendency of eastward wind due to nonorographic gravity waves has the standard name tendency_of_eastward_wind_due_to_nonorographic_gravity_wave_drag. + + + + W m-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Enthalpy can be written either as (1) CpT, where Cp is heat capacity at constant pressure, T is absolute temperature, or (2) U+pV, where U is internal energy, p is pressure and V is volume. + + + + m year-1 + + + Global average sea level change is due to change in volume of the water in the ocean, caused by mass and/or density change, or to change in the volume of the ocean basins, caused by tectonics etc. It is sometimes called "eustatic", which is a term that also has other definitions. It differs from the change in the global average sea surface height relative to the centre of the Earth by the global average vertical movement of the ocean floor. Zero sea level change is an arbitrary level. "tendency_of_X" means derivative of X with respect to time. Because global average sea level change quantifies the change in volume of the world ocean, it is not calculated necessarily by considering local changes in mean sea level. + + + + W m-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. + + + + kg s-1 + + + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Mass balance means the net rate at which ice is accumulated. A negative value means loss of ice. The tendency in ice mass due to the basal mass balance is the spatial integral of the quantity with standard name land_ice_basal_specific_mass_balance_flux. The geographical extent of the ice over which the mass is calculated is defined by the horizontal coordinates and any associated coordinate bounds or by a string valued auxiliary coordinate variable with a standard name of "region". + + + + kg s-1 + + + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The tendency in ice mass due to calving is the spatial integral of the quantity named land_ice_specific_mass_flux_due_to_calving. The geographical extent over which the quantity is calculated is defined by the horizontal coordinates and any associated coordinate bounds or by a string valued auxiliary coordinate variable with a standard name of "region". + + + + kg s-1 + + + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. The phrase "tendency_of_X" means derivative of X with respect to time. The surface called "surface" means the lower boundary of the atmosphere. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Mass balance" means the net rate at which ice is added. A negative value means loss of ice. The tendency in ice mass due to the surface mass balance is the spatial integral of the quantity with standard name land_ice_surface_specific_mass_balance_flux. The horizontal domain over which the quantity is described by the associated coordinate variables and coordinate bounds or by a string valued coordinate variable or scalar coordinate variable with a standard name of "region". + + + + m s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. "Thickness" means the vertical extent of a layer.. + + + + kg m-3 s-1 + + + "tendency_of_X" means derivative of X with respect to time. Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The mass is the total mass of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. the surface of the earth). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. Aerosol takes up ambient water (a process known as hygroscopic growth) depending on the relative humidity and the composition of the aerosol. "Dry aerosol particles" means aerosol particles without any water uptake. The "aviation" sector includes fuel combustion activities related to civil aviation. "Aviation" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3a as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". Chemically, "elemental carbon" is the carbonaceous fraction of particulate matter that is thermally stable in an inert atmosphere to high temperatures near 4000K and can only be gasified by oxidation starting at temperatures above 340 C. It is assumed to be inert and non-volatile under atmospheric conditions and insoluble in any solvent (Ogren and Charlson, 1983). + + + + kg m-3 s-1 + + + "tendency_of_X" means derivative of X with respect to time. Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen dioxide is NO2. The "aviation" sector includes fuel combustion activities related to civil aviation. "Aviation" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3a as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-3 s-1 + + + "tendency_of_X" means derivative of X with respect to time. Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The mass is the total mass of the molecules. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. The chemical formula for nitrogen monoxide is NO. The "aviation" sector includes fuel combustion activities related to civil aviation. "Aviation" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3a as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-3 s-1 + + + "tendency_of_X" means derivative of X with respect to time. Mass concentration means mass per unit volume and is used in the construction mass_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Emission" means emission from a primary source located anywhere within the atmosphere, including at the lower boundary (i.e. earth's surface). "Emission" is a process entirely distinct from "re-emission" which is used in some standard names. "Nox" means a combination of two radical species containing nitrogen and oxygen: NO+NO2. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The "aviation" sector includes fuel combustion activities related to civil aviation. "Aviation" is the term used in standard names to describe a collection of emission sources. A variable which has this value for the standard_name attribute should be accompanied by a comment attribute which lists the source categories and provides a reference to the categorization scheme, for example, "IPCC (Intergovernmental Panel on Climate Change) source category 1A3a as defined in the 2006 IPCC guidelines for national greenhouse gas inventories". + + + + kg m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. + + + + kg m-2 s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. + + + + kg m-2 s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. + + + + kg m-2 s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. + + + + kg m-2 s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary variable) as well. + + + + s-1 + + + "Tendency_of_X" means derivative of X with respect to time. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). "Condensed_water" means liquid and ice. + + + + s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "condensed_water" means liquid and ice. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + + + + s-1 + + + "tendency_of_X" means derivative of X with respect to time. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + + + + s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + + + + s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + + + + s-1 + + + "tendency_of_X" means derivative of X with respect to time. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + + + + s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + + + + s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). + + + + s-1 + + + 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convectionschemes). "tendency_of_X" means derivative of X with respect to time. "condensed_water" means liquid and ice. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "condensed_water" means liquid and ice. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Autoconversion is the process of collision and coalescence which results in the formation of precipitation particles from cloud water droplets or ice crystals. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "condensed_water" means liquid and ice. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Autoconversion is the process of collision and coalescence which results in the formation of precipitation particles from cloud water droplets or ice crystals. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "condensed_water" means liquid and ice. + + + + s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convectionschemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The phrase "condensed_water" means liquid and ice. "Boundary layer mixing" means turbulent motions that transport heat, water, momentum and chemical constituents within the atmospheric boundary layer and affect exchanges between the surface and the atmosphere. The atmospheric boundary layer is typically characterised by a well-mixed sub-cloud layer of order 500 metres, and by a more extended conditionally unstable layer with boundary-layer clouds up to 2 km. (Reference: IPCC Third Assessment Report, Working Group 1: The Scientific Basis, 7.2.2.3, https://www.ipcc.ch/ipccreports/tar/wg1/273.htm). + + + + s-1 + + + 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. 'cloud_microphysics' is the sum of many cloud processes such as condensation, evaporation, homogeneous nucleation, heterogeneous nucleation, deposition, sublimation, the Bergeron-Findeisen process, riming, accretion, aggregationand icefall. The precise list of processes that are included in 'cloud_microphysics' canvary between models. Where possible, the data variable should be accompanied by a complete description of the processes included, for example, by using a comment attribute. Standard names also exist to describe the tendencies due to the separate processes. "tendency_of_X" means derivative of X with respect to time. "condensed_water" means liquid and ice. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) Condensation is the conversion of vapor into liquid. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "condensed_water" means liquid and ice. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "condensed_water" means liquid and ice. + + + + s-1 + + + 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convectionschemes). "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Accretion is the growth of a hydrometeor by collision with cloud droplets or ice crystals. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Aggregation is the clumping together of frozen cloud particles to produce snowflakes. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convectionschemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The Bergeron-Findeisen process is the conversion of cloud liquid water to cloud ice arising from the fact that water vapor has a lower equilibrium vapor pressure with respect to ice than it has with respect to liquid water at the same subfreezing temperature. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Boundary layer mixing" means turbulent motions that transport heat, water, momentum and chemical constituents within the atmospheric boundary layer and affect exchanges between the surface and the atmosphere. The atmospheric boundary layer is typically characterised by a well-mixed sub-cloud layer of order 500 metres, and by a more extended conditionally unstable layer with boundary-layer clouds up to 2 km. (Reference: IPCC Third Assessment Report, Working Group 1: The Scientific Basis, 7.2.2.3, https://www.ipcc.ch/ipccreports/tar/wg1/273.htm). + + + + s-1 + + + 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. 'cloud_microphysics' is the sum of many cloud processes such as condensation, evaporation, homogeneous nucleation, heterogeneous nucleation, deposition, sublimation, the Bergeron-Findeisen process, riming, accretion, aggregationand icefall. The precise list of processes that are included in 'cloud_microphysics' canvary between models. Where possible, the data variable should be accompanied by a complete description of the processes included, for example, by using a comment attribute. Standard names also exist to describe the tendencies due to the separate processes. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Sublimation is the conversion of solid into vapor. Deposition is the opposite of sublimation, i.e. it is the conversion of vapor into solid. Deposition is distinct from the processes of dry deposition and wet deposition of atmospheric aerosol particles, which are referred to in some standard names. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Heterogeneous nucleation occurs when a small particle of a substance other than water acts as a freezing or condensation nucleus. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Heterogeneous nucleation occurs when a small particle of a substance other than water acts as a freezing or condensation nucleus. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Homogeneous nucleation occurs when a small number of water molecules combine to form a freezing or condensation nucleus. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Riming is the rapid freezing of supercooled water onto a surface. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Riming is the rapid freezing of supercooled water onto a surface. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convectionschemes). "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Accretion is the growth of a hydrometeor by collision with cloud droplets or ice crystals. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Accretion is the growth of a hydrometeor by collision with cloud droplets or ice crystals. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Autoconversion is the process of collision and coalescence which results in the formation of precipitation particles from cloud water droplets or ice crystals. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The Bergeron-Findeisen process is the conversion of cloud liquid water to cloud ice arising from the fact that water vapor has a lower equilibrium vapor pressure with respect to ice than it has with respect to liquid water at the same subfreezing temperature. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Boundary layer mixing" means turbulent motions that transport heat, water, momentum and chemical constituents within the atmospheric boundary layer and affect exchanges between the surface and the atmosphere. The atmospheric boundary layer is typically characterised by a well-mixed sub-cloud layer of order 500 metres, and by a more extended conditionally unstable layer with boundary-layer clouds up to 2 km. (Reference: IPCC Third Assessment Report, Working Group 1: The Scientific Basis, 7.2.2.3, https://www.ipcc.ch/ipccreports/tar/wg1/273.htm). + + + + s-1 + + + 'Mass fraction' is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convectionschemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. 'cloud_microphysics' is the sum of many cloud processes such as condensation, evaporation, homogeneous nucleation, heterogeneous nucleation, deposition, sublimation, the Bergeron-Findeisen process, riming, accretion, aggregationand icefall. The precise list of processes that are included in 'cloud_microphysics' canvary between models. Where possible, the data variable should be accompanied by a complete description of the processes included, for example, by using a comment attribute. Standard names also exist to describe the tendencies due to the separate processes. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Evaporation is the conversion of liquid or solid into vapor. Condensation is the conversion of vapor into liquid. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Condensation is the conversion of vapor into liquid. Evaporation is the conversion of liquid or solid into vapor. "Boundary layer mixing" means turbulent motions that transport heat, water, momentum and chemical constituents within the atmospheric boundary layer and affect exchanges between the surface and the atmosphere. The atmospheric boundary layer is typically characterised by a well-mixed sub-cloud layer of order 500 metres, and by a more extended conditionally unstable layer with boundary-layer clouds up to 2 km. (Reference: IPCC Third Assessment Report, Working Group 1: The Scientific Basis, 7.2.2.3, https://www.ipcc.ch/ipccreports/tar/wg1/273.htm). + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Evaporation is the conversion of liquid or solid into vapor. Condensation is the conversion of vapor into liquid. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Evaporation is the conversion of liquid or solid into vapor. Condensation is the conversion of vapor into liquid. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "longwave" means longwave radiation. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Evaporation is the conversion of liquid or solid into vapor. Condensation is the conversion of vapor into liquid. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Evaporation is the conversion of liquid or solid into vapor. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "shortwave" means shortwave radiation. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Evaporation is the conversion of liquid or solid into vapor. Condensation is the conversion of vapor into liquid. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Heterogeneous nucleation occurs when a small particle of a substance other than water acts asa freezing or condensation nucleus. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, whereX is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Homogeneous nucleation occurs when a small number of water molecules combine to form a freezing or condensation nucleus. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + s-1 + + + Mass fraction is used in the construction mass_fraction_of_X_in_Y, where X is a material constituent of Y. It means the ratio of the mass of X to the mass of Y (including X). A chemical species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. Riming is the rapid freezing of supercooled water onto a surface. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. "middle_atmosphere_moles_of_X" means the total number of moles of X contained in the troposphere and stratosphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of carbon monoxide is CO. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. "middle_atmosphere_moles_of_X" means the total number of moles of X contained in the troposphere and stratosphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of HCC140a is CH3CCl3. The IUPAC name for HCC 140a is 1,1,1-trichloroethane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. "middle_atmosphere_moles_of_X" means the total number of moles of X contained in the troposphere and stratosphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of methane is CH4. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. "middle_atmosphere_moles_of_X" means the total number of moles of X contained in the troposphere and stratosphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of methyl bromide is CH3Br. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. "middle_atmosphere_moles_of_X" means the total number of moles of X contained in the troposphere and stratosphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of methyl chloride is CH3Cl. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. "middle_atmosphere_moles_of_X" means the total number of moles of X contained in the troposphere and stratosphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of molecular hydrogen is H2. + + + + mol m-3 s-1 + + + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Aragonite is a mineral that is a polymorph of calcium carbonate. The chemical formula of aragonite is CaCO3. Standard names also exist for calcite, another polymorph of calcium carbonate. + + + + mol m-3 s-1 + + + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Aragonite is a mineral that is a polymorph of calcium carbonate. The chemical formula of aragonite is CaCO3. Standard names also exist for calcite, another polymorph of calcium carbonate. + + + + mol m-3 s-1 + + + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Calcite is a mineral that is a polymorph of calcium carbonate. Thechemical formula of calcite is CaCO3. Standard names also exist for aragonite, another polymorph of calcium carbonate. + + + + mol m-3 s-1 + + + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Calcite is a mineral that is a polymorph of calcium carbonate. Thechemical formula of calcite is CaCO3. Standard names also exist for aragonite, another polymorph of calcium carbonate. + + + + mol m-3 s-1 + + + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic carbon" describes a family of chemical species in solution, including carbon dioxide, carbonic acid and the carbonate and bicarbonate anions. "Dissolved inorganic carbon" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + mol m-3 s-1 + + + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic iron" means iron ions, in oxidation states of both Fe2+ and Fe3+, in solution. + + + + mol m-3 s-1 + + + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Inorganic nitrogen" describes a family of chemical species which, in an ocean model, usually includes nitrite, nitrate and ammonium which act as nitrogennutrients. "Inorganic nitrogen" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + mol m-3 s-1 + + + 'Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic phosphorus" means the sum of all inorganic phosphorus in solution (including phosphate, hydrogen phosphate, dihydrogen phosphate, and phosphoric acid). + + + + mol m-3 s-1 + + + 'Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic silicon" means the sum of all inorganic silicon in solution (including silicic acid and its first dissociated anion SiO(OH)3-). + + + + mol m-3 s-1 + + + Dissolution, remineralization and desorption of iron back to the dissolved phase 'Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity namedby omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + mol m-3 s-1 + + + 'Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. 'Grazing of phytoplankton' means the grazing of phytoplankton by zooplankton. + + + + mol m-3 s-1 + + + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + mol m-3 s-1 + + + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + mol m-3 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The term "ox" means a combination of three radical species containing 1 or 3 oxygen atoms: O + O1d + O3. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The phrase "chemical and photolytic production" means the result of all chemical and photolytic reactions within the medium (here, atmosphere) that produce a certain amount of the particular species. + + + + mol m-3 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The term "ox" means a combination of three radical species containing 1 or 3 oxygen atoms: O + O1d + O3. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Chemical destruction" means the result of all chemical reactions within the medium (here, atmosphere) that remove a certain amount of a particular species from the medium. + + + + mol m-3 s-1 + + + "tendency_of_X" means derivative of X with respect to time. Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. "Grazing of phytoplankton" means the grazing of phytoplankton by zooplankton. + + + + mol m-3 s-1 + + + 'Mole concentration' means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Net primary production is the excess of gross primary production (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. In the oceans, carbon production per unit volume is often found at a number of depths at a given horizontal location. That quantity can then be integrated to calculate production per unit area at the location. Standard names for production per unit area use the term "productivity". "tendency_of_X" means derivative of X with respect to time. + + + + mol m-3 s-1 + + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. In the oceans, carbon production per unit volume is often found at a number of depths at a given horizontal location. That quantity can then be integrated to calculate production per unit area at the location. Standard names for production per unit area use the term "productivity". "Calcareous phytoplankton" are phytoplankton that produce calcite. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Standard names also exist for aragonite, another polymorph of calcium carbonate. "tendency_of_X" means derivative of X with respect to time. + + + + mol m-3 s-1 + + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. In the oceans, carbon production per unit volume is often found at a number of depths at a given horizontal location. That quantity can then be integrated to calculate production per unit area at the location. Standard names for production per unit area use the term "productivity". Diatoms are single-celled phytoplankton with an external skeleton made of silica. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. "tendency_of_X" means derivative of X with respect to time. + + + + mol m-3 s-1 + + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction mole_concentration_of_X_in_Y, where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. In the oceans, carbon production per unit volume is often found at a number of depths at a given horizontal location. That quantity can then be integrated to calculate production per unit area at the location. Standard names for production per unit area use the term "productivity". In ocean modelling, diazotrophs are phytoplankton of the phylum cyanobacteria distinct from other phytoplankton groups in their ability to fix nitrogen gas in addition to nitrate and ammonium. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. "tendency_of_X" means derivative of X with respect to time. + + + + mol m-3 s-1 + + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. In the oceans, carbon production per unit volume is often found at a number of depths at a given horizontal location. That quantity can then be integrated to calculate production per unit area at the location. Standard names for production per unit area use the term "productivity". Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. "Miscellaneous phytoplankton" are all those phytoplankton that are not diatoms, diazotrophs, calcareous phytoplankton, picophytoplankton or other seperately named components of the phytoplankton population. "tendency_of_X" means derivative of X with respect to time. + + + + mol m-3 s-1 + + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. In the oceans, carbon production per unit volume is often found at a number of depths at a given horizontal location. That quantity can then be integrated to calculate production per unit area at the location. Standard names for production per unit area use the term "productivity". Picophytoplankton are phytoplankton of less than 2 micrometers in size. Phytoplankton are autotrophic prokaryotic or eukaryotic algae that live near the water surface where there is sufficient light to support photosynthesis. "tendency_of_X" means derivative of X with respect to time. + + + + mol m-3 s-1 + + + Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Nitrate utilization" means net primary production of carbon by phytoplankton based on nitrate alone. "Production of carbon" means the production of biomass expressed as the mass of carbon which it contains. Net primary production is the excess of gross primary production (the rate of synthesis of biomass from inorganic precursors) by autotrophs ("producers"), for example, photosynthesis in plants or phytoplankton, over the rate at which the autotrophs themselves respire some of this biomass. In the oceans, carbon production per unit volume is often found at a number of depths at a given horizontal location. That quantity can then be integrated to calculate production per unit area at the location. Standard names for production per unit area use the term "productivity". "tendency_of_X" means derivative of X with respect to time. The chemical formula for the nitrate anion is NO3-. + + + + mol m-3 s-1 + + + "tendency_of_X" means derivative of X with respect to time. Mole concentration means number of moles per unit volume, also called "molarity", and is used in the construction "mole_concentration_of_X_in_Y", where X is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as "nitrogen" or a phrase such as "nox_expressed_as_nitrogen". The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Remineralization is the degradation of organic matter into inorganic forms of carbon, nitrogen, phosphorus and other micronutrients, which consumes oxygen and releases energy. + + + + mol m-3 s-1 + + + 'Mole concentration' means number of moles per unit volume, also called"molarity", and is used in the construction mole_concentration_of_X_in_Y, whereX is a material constituent of Y. A chemical or biological species denoted by X may be described by a single term such as 'nitrogen' or a phrase such as 'nox_expressed_as_nitrogen'. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + m s-2 + + tnmmvtot + "tendency_of_X" means derivative of X with respect to time. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + + + m s-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + + + m s-2 + + tnmmvc + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + + + m s-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + + + m s-2 + + tnmmvgwd + The phrase "tendency_of_X" means derivative of X with respect to time. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The quantity with standard name tendency_of_northward_wind_due_to_gravity_wave_drag is the total tendency of the northward wind due to gravity waves. It is the sum of the tendencies due to orographic and nonorographic gravity waves which have the standard names tendency_of_northward_wind_due_to_orographic_gravity_wave_drag and tendency_of_northward_wind_due_to_nonorographic_gravity_wave_drag, respectively. + + + + m s-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name "upward_air_velocity"). The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Nonorographic" gravity waves refer to gravity waves which are not generated by flow over orography. The quantity with standard name tendency_of_northward_wind_due_to_gravity_wave_drag is the total tendency of the northward wind due to gravity waves. It is the sum of the tendencies due to orographic and nonorographic gravity waves which have the standard names tendency_of_northward_wind_due_to_orographic_gravity_wave_drag and tendency_of_northward_wind_due_to_nonorographic_gravity_wave_drag, respectively. + + + + m s-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Northward" indicates a vector component which is positive when directed northward (negative southward). Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name "upward_air_velocity"). The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Orographic gravity waves" refer to gravity waves which are generated by flow over orography. The quantity with standard name tendency_of_northward_wind_due_to_gravity_wave_drag is the total tendency of the northward wind due to gravity waves. It is the sum of the tendencies due to orographic and nonorographic gravity waves which have the standard names tendency_of_northward_wind_due_to_orographic_gravity_wave_drag and tendency_of_northward_wind_due_to_nonorographic_gravity_wave_drag, respectively. + + + + m3 s-2 + + + "tendency_of_X" means derivative of X with respect to time. + + + + W m-2 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "ocean content" of a quantity refers to the vertical integral from the surface to the bottom of the ocean. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized eddy advection can be represented on various spatial scales and there are standard names for parameterized_mesoscale_eddy_advection and parameterized_submesoscale_eddy_advection which both contribute to the total parameterized eddy advection. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Aragonite is a mineral that is a polymorph of calcium carbonate. The chemical formula of aragonite is CaCO3. Standard names also exist for calcite, another polymorph of calcium carbonate. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The phrase 'expressed_as' is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Calcite is a mineral that is a polymorph of calcium carbonate. The chemical formula of calcite is CaCO3. Standard names also exist for aragonite, another polymorph of calcium carbonate. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of termswhich together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is asingle term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic carbon" describes a family of chemical species in solution, including carbon dioxide, carbonic acid and the carbonate and bicarbonate anions. "Dissolved inorganic carbon" isthe term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is asingle term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic carbon" describes a family of chemical species in solution, including carbon dioxide, carbonic acid and the carbonate and bicarbonate anions. "Dissolved inorganic carbon" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic iron" means iron ions, in oxidation states of both Fe2+ and Fe3+, in solution. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is asingle term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic iron" means iron ions, in oxidation states of both Fe2+ and Fe3+, in solution. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. "tendency_of_X" means derivative of X with respect to time. "Inorganic nitrogen" describes a family of chemical species which, in an ocean model, usually includes nitrite, nitrate and ammonium which act as nitrogen nutrients. "Inorganic nitrogen" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variableshould be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Inorganic nitrogen" describes a family of chemical species which, in an ocean model, usually includes nitrite, nitrate and ammonium which act as nitrogen nutrients. "Inorganic nitrogen" is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic phosphorus" means the sum of all inorganic phosphorus in solution (including phosphate, hydrogen phosphate, dihydrogen phosphate, and phosphoric acid). + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic phosphorus" means the sum of all inorganic phosphorus in solution (including phosphate, hydrogen phosphate, dihydrogen phosphate, and phosphoric acid). + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic silicon" means the sum of all inorganic silicon in solution (including silicic acid and its first dissociated anion SiO(OH)3-). + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Dissolved inorganic silicon" means the sum of all inorganic silicon in solution (including silicic acid and its first dissociated anion SiO(OH)3-). + + + + mol m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "ocean content" of a quantity refers to the vertical integral from the surface to the bottom of the ocean. The specification of a physical process by the phrase due_to_process means that the quantity named is asingle term in a sum of terms which together compose the general quantity named by omitting the phrase. 'Denitrification' is the conversion of nitrate into gaseous compounds such as nitric oxide, nitrous oxide and molecular nitrogen which are then emitted to the atmosphere. 'Sedimentation' is the sinking of particulate matter to the floor of a body of water. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is asingle term in a sum of terms which together compose the general quantity named by omitting the phrase. Deposition of nitrogen into the ocean is the sum of dry and wet depositionof nitrogen species onto the ocean surface from the atmosphere. 'Nitrogen fixation' means the production of ammonia from nitrogen gas. Organisms that fix nitrogen are termed 'diazotrophs'. Diazotrophic phytoplankton can fix atmospheric nitrogen, thus increasing the content of nitrogen in the ocean. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage."tendency_of_X" means derivative of X with respect to time. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is asingle term in a sum of terms which together compose the general quantity named by omitting the phrase. 'Nitrogen fixation' means the production of ammonia from nitrogen gas. Organisms that fix nitrogen are termed 'diazotrophs'. Diazotrophic phytoplankton can fix atmospheric nitrogen, thus increasing the content of nitrogen in the ocean. "tendency_of_X" means derivative of X with respect to time. + + + + mol m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Inorganic carbon" describes a family of chemical species and is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. + + + + mol m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Inorganic carbon" describes a family of chemical species and is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. + + + + mol m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Inorganic carbon" describes a family of chemical species and is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sedimentation" is the sinking of particulate matter to the floor of a body of water. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of termswhich together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + mol m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Nitrogen" summarizes all chemical species containing nitrogen atoms. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + + mol m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Organic carbon" describes a family of chemical species and is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Runoff is the liquid water which drains from land. If not specified, "runoff" refers to the sum of surface runoff and subsurface drainage. + + + + mol m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Organic carbon" describes a family of chemical species and is the term used in standard names for all species belonging to the family that are represented within a given model. The list of individual species that are included in a quantity having a group chemical standard name can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sedimentation" is the sinking of particulate matter to the floor of a body of water. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The "ocean content" of a quantity refers to the vertical integral from the surface to the bottom of the ocean. "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Deposition of nitrogen into the ocean is the sum of dry and wet deposition of the considered species onto the ocean surface from the atmosphere. "Oxidized nitrogen compounds" means all chemical species containing nitrogen atoms with an oxidation state greater than zero. Usually, particle bound and gaseous nitrogen compounds, such as nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), nitrate (NO3-), peroxynitric acid (HNO4), bromine nitrate (BrONO2), chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)), are included. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The "ocean content" of a quantity refers to the vertical integral from the surface to the bottom of the ocean. "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "dry_deposition" is the sum of turbulent deposition and gravitational settling of the considered species onto the ocean surface from the atmosphere. "Oxidized nitrogen compounds" means all chemical species containing nitrogen atoms with an oxidation state greater than zero. Usually, particle bound and gaseous nitrogen compounds, such as nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), nitrate (NO3-), peroxynitric acid (HNO4), bromine nitrate (BrONO2), chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)), are included. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The "ocean content" of a quantity refers to the vertical integral from the surface to the bottom of the ocean. "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "wet_deposition" means deposition by precipitation. "Oxidized nitrogen compounds" means all chemical species containing nitrogen atoms with an oxidation state greater than zero. Usually, particle bound and gaseous nitrogen compounds, such as nitrogen monoxide (NO), nitrogen dioxide (NO2), dinitrogen pentoxide (N2O5), nitric acid (HNO3), nitrate (NO3-), peroxynitric acid (HNO4), bromine nitrate (BrONO2), chlorine nitrate (ClONO2) and organic nitrates (most notably peroxyacetyl nitrate, sometimes referred to as PAN, (CH3COO2NO2)), are included. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + + + + mol m-2 s-1 + + + "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The "ocean content" of a quantity refers to the vertical integral from the surface to the bottom of the ocean. "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Deposition of nitrogen into the ocean is the sum of dry and wet deposition of nitrogen species onto the ocean surface from the atmosphere. "Reduced nitrogen compounds" means all chemical species containing nitrogen atoms with an oxidation state less than zero. Usually, particle bound and gaseous nitrogen compounds, primarily ammonium (NH4+) and ammonia (NH3), are included. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The "ocean content" of a quantity refers to the vertical integral from the surface to the bottom of the ocean. "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "dry_deposition" is the sum of turbulent deposition and gravitational settling of the considered species onto the ocean surface from the atmosphere. "Reduced nitrogen compounds" means all chemical species containing nitrogen atoms with an oxidation state less than zero. Usually, particle bound and gaseous nitrogen compounds, primarily ammonium (NH4+) and ammonia (NH3), are included. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The "ocean content" of a quantity refers to the vertical integral from the surface to the bottom of the ocean. "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "wet_deposition" means deposition by precipitation. "Reduced nitrogen compounds" means all chemical species containing nitrogen atoms with an oxidation state less than zero. Usually, particle bound and gaseous nitrogen compounds, primarily ammonium (NH4+) and ammonia (NH3), are included. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. + + + + mol m-2 s-1 + + + "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is asingle term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + W m-2 + + + "Content" indicates a quantity per unit area. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) "tendency_of_X" means derivative of X with respect to time. + + + + W m-2 + + + "Content" indicates a quantity per unit area. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) "Due to background" means caused by a time invariant imposed field which may be either constant over the globe or spatially varying, depending on the ocean model used. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + W m-2 + + + "Content" indicates a quantity per unit area. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) "Due to tides" means due to all astronomical gravity changes which manifest as tides. No distinction is made between different tidal components. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. + + + + W m-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) + + + + W m-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) + + + + W m-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Layer" means any layer with upper and lower boundaries that have constant values in some vertical coordinate. There must be a vertical coordinate variable indicating the extent of the layer(s). If the layers are model layers, the vertical coordinate can be model_level_number, but it is recommended to specify a physical coordinate (in a scalar or auxiliary coordinate variable) as well. Potential energy is the sum of the gravitational potential energy relative to the geoid and the centripetal potential energy. (The geopotential is the specific potential energy.) + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Amount" means mass per unit area. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Amount" means mass per unit area. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Congelation ice" means the freezing of sea water onto the underside of thin, new sea ice that has been formed by small areas of frazil ice crystals joining together into a continuous layer at the sea surface. Congelation ice forms under calm water conditions; it thickens and stabilizes the layer of sea ice and produces a smooth bottom surface. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Amount" means mass per unit area. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Conversion of snow to sea ice" occurs when the mass of snow accumulated on an area of sea ice is sufficient to cause the ice to become mostly submerged. Waves can then wash over the ice and snow surface and freeze into a layer that becomes "snow ice". + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Amount" means mass per unit area. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Frazil" consists of needle like crystals of ice, typically between three and four millimeters in diameter, which form as sea water begins to freeze. Salt is expelled during the freezing process and frazil ice consists of nearly pure fresh water. Leads are stretches of open water within wider areas of sea ice. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Amount" means mass per unit area. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. An ice floe is a flat expanse of sea ice, generally taken to be less than 10 km across. "Lateral growth of ice floe" means the accumulation of ice at the extreme edges of the ice area. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Amount" means mass per unit area. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Amount" means mass per unit area. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sea ice dynamics" refers to advection of sea ice. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Amount" means mass per unit area. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sea ice thermodynamics" refers to the addition or subtraction of mass due to surface and basal fluxes, i.e., due to melting, sublimation and fusion. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Amount" means mass per unit area. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The surface called "surface" means the lower boundary of the atmosphere. + + + + s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "X_area_fraction" means the fraction of horizontal area occupied by X. Sea ice area fraction is area of the sea surface occupied by sea ice. It is also called "sea ice concentration". "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sea ice dynamics" refers to the motion of sea ice. + + + + s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "X_area_fraction" means the fraction of horizontal area occupied by X. Sea ice area fraction is area of the sea surface occupied by sea ice. It is also called "sea ice concentration". "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Sea ice "ridging" occurs in rough sea conditions. The motion of the sea surface can cause areas of sea ice to deform and fold resulting in ridged upper and lower surfaces. The ridges can be as much as twenty metres thick if thick ice is deformed. + + + + s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "X_area_fraction" means the fraction of horizontal area occupied by X. Sea ice area fraction is area of the sea surface occupied by sea ice. It is also called "sea ice concentration". "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sea ice thermodynamics" refers to the addition or subtraction of mass due to surface and basal fluxes. + + + + m s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Thickness" means the vertical extent of a layer. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sea ice dynamics" refers to the motion of sea ice. + + + + m s-1 + 97 + + The phrase "tendency_of_X" means derivative of X with respect to time. "Thickness" means the vertical extent of a layer. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms named by omitting the phrase. "Sea ice thermodynamics" refers to the addition or subtraction of mass due to surface and basal fluxes. + + + + m year-1 + + + "Sea surface height" is a time-varying quantity. "tendency_of_X" means derivative of X with respect to time. "Height_above_X" means the vertical distance above the named surface X. "Mean sea level" means the time mean of sea surface elevation at a given location over an arbitrary period sufficient to eliminate the tidal signals. The standard name for the height of the sea surface above the geoid is sea_surface_height_above_geoid. The standard name for the height of the sea surface above the reference ellipsoid is sea_surface_height_above_reference_ellipsoid. + + + + mol m-3 s-1 + + + 'sea_water_alkalinity_expressed_as_mole_equivalent' is the total alkalinity equivalent concentration (including carbonate, nitrogen, silicate, and borate components). The specification of a physical process by the phrase due_to_process means that thequantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X withrespect to time. + + + + W m-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. This tendency encompasses all processes that impact on the time changes for the heat content within a grid cell. The phrase "expressed_as_heat_content" means that this quantity is calculated as the specific heat capacity times density of sea water multiplied by the conservative temperature of the sea water in the grid cell and integrated over depth. If used for a layer heat content, coordinate bounds should be used to define the extent of the layers. If no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is sea water the integral is assumed to be calculated over the full depth of the ocean. Conservative Temperature is defined as part of the Thermodynamic Equation of Seawater 2010 (TEOS-10) which was adopted in 2010 by the International Oceanographic Commission (IOC). Conservative Temperature is specific potential enthalpy (which has the standard name sea_water_specific_potential_enthalpy) divided by a fixed value of the specific heat capacity of sea water, namely cp_0 = 3991.86795711963 J kg-1 K-1. Conservative Temperature is a more accurate measure of the "heat content" of sea water, by a factor of one hundred, than is potential temperature. Because of this, it can be regarded as being proportional to the heat content of sea water per unit mass. Reference: www.teos-10.org; McDougall, 2003 doi: 10.1175/1520-0485(2003)033<0945:PEACOV>2.0.CO;2. + + + + W m-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "expressed_as_heat_content" means that this quantity is calculated as the specific heat capacity times density of sea water multiplied by the conservative temperature of the sea water in the grid cell and integrated over depth. If used for a layer heat content, coordinate bounds should be used to define the extent of the layers. If no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is sea water the integral is assumed to be calculated over the full depth of the ocean. Conservative Temperature is defined as part of the Thermodynamic Equation of Seawater 2010 (TEOS-10) which was adopted in 2010 by the International Oceanographic Commission (IOC). Conservative Temperature is specific potential enthalpy (which has the standard name sea_water_specific_potential_enthalpy) divided by a fixed value of the specific heat capacity of sea water, namely cp_0 = 3991.86795711963 J kg-1 K-1. Conservative Temperature is a more accurate measure of the "heat content" of sea water, by a factor of one hundred, than is potential temperature. Because of this, it can be regarded as being proportional to the heat content of sea water per unit mass. Reference: www.teos-10.org; McDougall, 2003 doi: 10.1175/1520-0485(2003)033<0945:PEACOV>2.0.CO;2. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized eddy advection can be represented on various spatial scales and there are standard names for parameterized_mesoscale_eddy_advection and parameterized_submesoscale_eddy_advection which both contribute to the total parameterized eddy advection. Additionally, when the parameterized advective process is represented in the model as a skew-diffusion rather than an advection, then the parameterized skew diffusion should be included in this diagnostic. The convergence of a skew-flux is identical (in the continuous formulation) to the convergence of an advective flux, making their tendencies the same. + + + + W m-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "expressed_as_heat_content" means that this quantity is calculated as the specific heat capacity times density of sea water multiplied by the conservative temperature of the sea water in the grid cell and integrated over depth. If used for a layer heat content, coordinate bounds should be used to define the extent of the layers. If no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is sea water the integral is assumed to be calculated over the full depth of the ocean. Conservative Temperature is defined as part of the Thermodynamic Equation of Seawater 2010 (TEOS-10) which was adopted in 2010 by the International Oceanographic Commission (IOC). Conservative Temperature is specific potential enthalpy (which has the standard name sea_water_specific_potential_enthalpy) divided by a fixed value of the specific heat capacity of sea water, namely cp_0 = 3991.86795711963 J kg-1 K-1. Conservative Temperature is a more accurate measure of the "heat content" of sea water, by a factor of one hundred, than is potential temperature. Because of this, it can be regarded as being proportional to the heat content of sea water per unit mass. Reference: www.teos-10.org; McDougall, 2003 doi: 10.1175/1520-0485(2003)033<0945:PEACOV>2.0.CO;2. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Eddy dianeutral mixing" means dianeutral mixing, i.e. mixing across neutral directions caused by the unresolved turbulent motion of eddies of all types (e.g., breaking gravity waves, boundary layer turbulence, etc.). + + + + W m-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "expressed_as_heat_content" means that this quantity is calculated as the specific heat capacity times density of sea water multiplied by the conservative temperature of the sea water in the grid cell and integrated over depth. If used for a layer heat content, coordinate bounds should be used to define the extent of the layers. If no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is sea water the integral is assumed to be calculated over the full depth of the ocean. Conservative Temperature is defined as part of the Thermodynamic Equation of Seawater 2010 (TEOS-10) which was adopted in 2010 by the International Oceanographic Commission (IOC). Conservative Temperature is specific potential enthalpy (which has the standard name sea_water_specific_potential_enthalpy) divided by a fixed value of the specific heat capacity of sea water, namely cp_0 = 3991.86795711963 J kg-1 K-1. Conservative Temperature is a more accurate measure of the "heat content" of sea water, by a factor of one hundred, than is potential temperature. Because of this, it can be regarded as being proportional to the heat content of sea water per unit mass. Reference: www.teos-10.org; McDougall, 2003 doi: 10.1175/1520-0485(2003)033<0945:PEACOV>2.0.CO;2. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized mesoscale eddy advection occurs on a spatial scale of many tens of kilometres and an evolutionary time of weeks. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. Parameterized mesoscale eddy advection is represented in ocean models using schemes such as the Gent-McWilliams scheme. There are also standard names for parameterized_submesoscale_eddy_advection which, along with parameterized_mesoscale_eddy_advection, contributes to the total parameterized eddy advection. Additionally, when the parameterized advective process is represented in the model as a skew-diffusion rather than an advection, then the parameterized skew diffusion should be included in this diagnostic. The convergence of a skew-flux is identical (in the continuous formulation) to the convergence of an advective flux, making their tendencies the same. + + + + W m-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "expressed_as_heat_content" means that this quantity is calculated as the specific heat capacity times density of sea water multiplied by the conservative temperature of the sea water in the grid cell and integrated over depth. If used for a layer heat content, coordinate bounds should be used to define the extent of the layers. If no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is sea water the integral is assumed to be calculated over the full depth of the ocean. Conservative Temperature is defined as part of the Thermodynamic Equation of Seawater 2010 (TEOS-10) which was adopted in 2010 by the International Oceanographic Commission (IOC). Conservative Temperature is specific potential enthalpy (which has the standard name sea_water_specific_potential_enthalpy) divided by a fixed value of the specific heat capacity of sea water, namely cp_0 = 3991.86795711963 J kg-1 K-1. Conservative Temperature is a more accurate measure of the "heat content" of sea water, by a factor of one hundred, than is potential temperature. Because of this, it can be regarded as being proportional to the heat content of sea water per unit mass. Reference: www.teos-10.org; McDougall, 2003 doi: 10.1175/1520-0485(2003)033<0945:PEACOV>2.0.CO;2. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized mesoscale eddy diffusive processes include diffusion along neutral directions in the interior of the ocean and horizontal diffusion in the surface boundary layer. The processes occur on a spatial scale of many tens of kilometres and an evolutionary time of weeks. The phrase "expressed_as_heat_content" means that this quantity is calculated as the specific heat capacity times density of sea water multiplied by the conservative temperature of the sea water in the grid cell. + + + + W m-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "expressed_as_heat_content" means that this quantity is calculated as the specific heat capacity times density of sea water multiplied by the conservative temperature of the sea water in the grid cell and integrated over depth. If used for a layer heat content, coordinate bounds should be used to define the extent of the layers. If no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is sea water the integral is assumed to be calculated over the full depth of the ocean. Conservative Temperature is defined as part of the Thermodynamic Equation of Seawater 2010 (TEOS-10) which was adopted in 2010 by the International Oceanographic Commission (IOC). Conservative Temperature is specific potential enthalpy (which has the standard name sea_water_specific_potential_enthalpy) divided by a fixed value of the specific heat capacity of sea water, namely cp_0 = 3991.86795711963 J kg-1 K-1. Conservative Temperature is a more accurate measure of the "heat content" of sea water, by a factor of one hundred, than is potential temperature. Because of this, it can be regarded as being proportional to the heat content of sea water per unit mass. Reference: www.teos-10.org; McDougall, 2003 doi: 10.1175/1520-0485(2003)033<0945:PEACOV>2.0.CO;2. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized submesoscale eddy advection occurs on a spatial scale of the order of 1 km horizontally. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. There are also standard names for parameterized_mesoscale_eddy_advection which, along with parameterized_submesoscale_eddy_advection, contributes to the total parameterized eddy advection. Additionally, when the parameterized advective process is represented in the model as a skew-diffusion rather than an advection, then the parameterized skew diffusion should be included in this diagnostic. The convergence of a skew-flux is identical (in the continuous formulation) to the convergence of an advective flux, making their tendencies the same. + + + + W m-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "expressed_as_heat_content" means that this quantity is calculated as the specific heat capacity times density of sea water multiplied by the conservative temperature of the sea water in the grid cell and integrated over depth. If used for a layer heat content, coordinate bounds should be used to define the extent of the layers. If no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is sea water the integral is assumed to be calculated over the full depth of the ocean. Conservative Temperature is defined as part of the Thermodynamic Equation of Seawater 2010 (TEOS-10) which was adopted in 2010 by the International Oceanographic Commission (IOC). Conservative Temperature is specific potential enthalpy (which has the standard name sea_water_specific_potential_enthalpy) divided by a fixed value of the specific heat capacity of sea water, namely cp_0 = 3991.86795711963 J kg-1 K-1. Conservative Temperature is a more accurate measure of the "heat content" of sea water, by a factor of one hundred, than is potential temperature. Because of this, it can be regarded as being proportional to the heat content of sea water per unit mass. Reference: www.teos-10.org; McDougall, 2003 doi: 10.1175/1520-0485(2003)033<0945:PEACOV>2.0.CO;2. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The phrase "residual_mean_advection" refers to the sum of the model's resolved advective transport plus any parameterized advective transport. Parameterized advective transport includes processes such as parameterized mesoscale and submesoscale transport, as well as any other advectively parameterized transport. When the parameterized advective transport is represented in the model as a skew-diffusion rather than an advection, then the parameterized skew diffusion should be included in this diagnostic, since the convergence of skew-fluxes are identical (in the continuous formulation) to the convergence of advective fluxes. + + + + W m-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. This tendency encompasses all processes that impact on the time changes for the heat content within a grid cell. The phrase "expressed_as_heat_content" means that this quantity is calculated as the specific heat capacity times density of sea water multiplied by the potential temperature of the sea water in the grid cell and integrated over depth. If used for a layer heat content, coordinate bounds should be used to define the extent of the layers. If no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is sea water the integral is assumed to be calculated over the full depth of the ocean. Potential temperature is the temperature a parcel of air or sea water would have if moved adiabatically to sea level pressure. + + + + W m-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "expressed_as_heat_content" means that this quantity is calculated as the specific heat capacity times density of sea water multiplied by the potential temperature of the sea water in the grid cell and integrated over depth. If used for a layer heat content, coordinate bounds should be used to define the extent of the layers. If no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is sea water the integral is assumed to be calculated over the full depth of the ocean. Potential temperature is the temperature a parcel of air or sea water would have if moved adiabatically to sea level pressure. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized eddy advection can be represented on various spatial scales and there are standard names for parameterized_mesoscale_eddy_advection and parameterized_submesoscale_eddy_advection which both contribute to the total parameterized eddy advection. Additionally, when the parameterized advective process is represented in the model as a skew-diffusion rather than an advection, then the parameterized skew diffusion should be included in this diagnostic. The convergence of a skew-flux is identical (in the continuous formulation) to the convergence of an advective flux, making their tendencies the same. + + + + W m-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "expressed_as_heat_content" means that this quantity is calculated as the specific heat capacity times density of sea water multiplied by the potential temperature of the sea water in the grid cell and integrated over depth. If used for a layer heat content, coordinate bounds should be used to define the extent of the layers. If no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is sea water the integral is assumed to be calculated over the full depth of the ocean. Potential temperature is the temperature a parcel of air or sea water would have if moved adiabatically to sea level pressure. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Eddy dianeutral mixing" means dianeutral mixing, i.e. mixing across neutral directions caused by the unresolved turbulent motion of eddies of all types (e.g., breaking gravity waves, boundary layer turbulence, etc.). + + + + W m-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "expressed_as_heat_content" means that this quantity is calculated as the specific heat capacity times density of sea water multiplied by the potential temperature of the sea water in the grid cell and integrated over depth. If used for a layer heat content, coordinate bounds should be used to define the extent of the layers. If no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is sea water the integral is assumed to be calculated over the full depth of the ocean. Potential temperature is the temperature a parcel of air or sea water would have if moved adiabatically to sea level pressure. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized mesoscale eddy advection occurs on a spatial scale of many tens of kilometres and an evolutionary time of weeks. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. Parameterized mesoscale eddy advection is represented in ocean models using schemes such as the Gent-McWilliams scheme. There are also standard names for parameterized_submesoscale_eddy_advection which, along with parameterized_mesoscale_eddy_advection, contributes to the total parameterized eddy advection. Additionally, when the parameterized advective process is represented in the model as a skew-diffusion rather than an advection, then the parameterized skew diffusion should be included in this diagnostic. The convergence of a skew-flux is identical (in the continuous formulation) to the convergence of an advective flux, making their tendencies the same. + + + + W m-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "expressed_as_heat_content" means that this quantity is calculated as the specific heat capacity times density of sea water multiplied by the potential temperature of the sea water in the grid cell and integrated over depth. If used for a layer heat content, coordinate bounds should be used to define the extent of the layers. If no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is sea water the integral is assumed to be calculated over the full depth of the ocean. Potential temperature is the temperature a parcel of air or sea water would have if moved adiabatically to sea level pressure. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized mesoscale eddy diffusive processes include diffusion along neutral directions in the interior of the ocean and horizontal diffusion in the surface boundary layer. The processes occur on a spatial scale of many tens of kilometres and an evolutionary time of weeks. + + + + W m-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "expressed_as_heat_content" means that this quantity is calculated as the specific heat capacity times density of sea water multiplied by the potential temperature of the sea water in the grid cell and integrated over depth. If used for a layer heat content, coordinate bounds should be used to define the extent of the layers. If no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is sea water the integral is assumed to be calculated over the full depth of the ocean. Potential temperature is the temperature a parcel of air or sea water would have if moved adiabatically to sea level pressure. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized submesoscale eddy advection occurs on a spatial scale of the order of 1 km horizontally. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. There are also standard names for parameterized_mesoscale_eddy_advection which, along with parameterized_submesoscale_eddy_advection, contributes to the total parameterized eddy advection. Additionally, when the parameterized advective process is represented in the model as a skew-diffusion rather than an advection, then the parameterized skew diffusion should be included in this diagnostic. The convergence of a skew-flux is identical (in the continuous formulation) to the convergence of an advective flux, making their tendencies the same. + + + + W m-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. The phrase "expressed_as_heat_content" means that this quantity is calculated as the specific heat capacity times density of sea water multiplied by the potential temperature of the sea water in the grid cell and integrated over depth. If used for a layer heat content, coordinate bounds should be used to define the extent of the layers. If no coordinate bounds are specified, it is assumed that the integral is calculated over the entire vertical extent of the medium, e.g, if the medium is sea water the integral is assumed to be calculated over the full depth of the ocean. Potential temperature is the temperature a parcel of air or sea water would have if moved adiabatically to sea level pressure. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The phrase "residual_mean_advection" refers to the sum of the model's resolved advective transport plus any parameterized advective transport. Parameterized advective transport includes processes such as parameterized mesoscale and submesoscale transport, as well as any other advectively parameterized transport. When the parameterized advective transport is represented in the model as a skew-diffusion rather than an advection, then the parameterized skew diffusion should be included in this diagnostic, since the convergence of skew-fluxes are identical (in the continuous formulation) to the convergence of advective fluxes. + + + + 1e-3 s-1 + + + "tendency_of_X" means derivative of X with respect to time. Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and normally given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. + + + + 1e-3 s-1 + + + "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and normally given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. + + + + 1e-3 s-1 + + + "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Horizontal mixing" means any horizontal transport other than by advection and parameterized eddy advection, usually represented as horizontal diffusion in ocean models. Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and normally given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. + + + + 1e-3 s-1 + + + "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized eddy advection can be represented on various spatial scales and there are standard names for parameterized_mesoscale_eddy_advection and parameterized_submesoscale_eddy_advection which both contribute to the total parameterized eddy advection. Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and normally given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. + + + + 1e-3 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and normally given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sea ice thermodynamics" refers to the addition or subtraction of sea ice mass due to surface and basal fluxes, i.e. due to melting, sublimation and fusion. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. + + + + 1e-3 s-1 + + + "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Vertical mixing" means any vertical transport other than by advection and parameterized eddy advection, represented by a combination of vertical diffusion, turbulent mixing and convection in ocean models. Sea water salinity is the salt content of sea water, often on the Practical Salinity Scale of 1978. However, the unqualified term 'salinity' is generic and does not necessarily imply any particular method of calculation. The units of salinity are dimensionless and normally given as 1e-3 or 0.001 i.e. parts per thousand. There are standard names for the more precisely defined salinity quantities: sea_water_knudsen_salinity, S_K (used for salinity observations between 1901 and 1966), sea_water_cox_salinity, S_C (used for salinity observations between 1967 and 1977), sea_water_practical_salinity, S_P (used for salinity observations from 1978 to the present day), sea_water_absolute_salinity, S_A, sea_water_preformed_salinity, S_*, and sea_water_reference_salinity. Practical Salinity is reported on the Practical Salinity Scale of 1978 (PSS-78), and is usually based on the electrical conductivity of sea water in observations since the 1960s. Conversion of data between the observed scales follows: S_P = (S_K - 0.03) * (1.80655 / 1.805) and S_P = S_C, however the accuracy of the latter is dependent on whether chlorinity or conductivity was used to determine the S_C value, with this inconsistency driving the development of PSS-78. The more precise standard names should be used where appropriate for both modelled and observed salinities. In particular, the use of sea_water_salinity to describe salinity observations made from 1978 onwards is now deprecated in favor of the term sea_water_practical_salinity which is the salinity quantity stored by national data centers for post-1978 observations. The only exception to this is where the observed salinities are definitely known not to be recorded on the Practical Salinity Scale. The unit "parts per thousand" was used for sea_water_knudsen_salinity and sea_water_cox_salinity. + + + + kg m-2 s-1 + + + "Content" indicates a quantity per unit area. "tendency_of_X" means derivative of X with respect to time. This tendency encompasses all processes that impact on the time changes for the salt content within a grid cell. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized eddy advection can be represented on various spatial scales and there are standard names for parameterized_mesoscale_eddy_advection and parameterized_submesoscale_eddy_advection which both contribute to the total parameterized eddy advection. Additionally, when the parameterized advective process is represented in the model as a skew-diffusion rather than an advection, then the parameterized skew diffusion should be included in this diagnostic. The convergence of a skew-flux is identical (in the continuous formulation) to the convergence of an advective flux, making their tendencies the same. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Eddy dianeutral mixing" means dianeutral mixing, i.e. mixing across neutral directions caused by the unresolved turbulent motion of eddies of all types (e.g., breaking gravity waves, boundary layer turbulence, etc.). + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized mesoscale eddy advection occurs on a spatial scale of many tens of kilometres and an evolutionary time of weeks. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. Parameterized mesoscale eddy advection is represented in ocean models using schemes such as the Gent-McWilliams scheme. There are also standard names for parameterized_submesoscale_eddy_advection which, along with parameterized_mesoscale_eddy_advection, contributes to the total parameterized eddy advection. Additionally, when the parameterized advective process is represented in the model as a skew-diffusion rather than an advection, then the parameterized skew diffusion should be included in this diagnostic. The convergence of a skew-flux is identical (in the continuous formulation) to the convergence of an advective flux, making their tendencies the same. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized mesoscale eddy diffusive processes include diffusion along neutral directions in the interior of the ocean and horizontal diffusion in the surface boundary layer. The processes occur on a spatial scale of many tens of kilometres and an evolutionary time of weeks. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized submesoscale eddy advection occurs on a spatial scale of the order of 1 km horizontally. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. There are also standard names for parameterized_mesoscale_eddy_advection which, along with parameterized_submesoscale_eddy_advection, contributes to the total parameterized eddy advection. Additionally, when the parameterized advective process is represented in the model as a skew-diffusion rather than an advection, then the parameterized skew diffusion should be included in this diagnostic. The convergence of a skew-flux is identical (in the continuous formulation) to the convergence of an advective flux, making their tendencies the same. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The phrase "residual_mean_advection" refers to the sum of the model's resolved advective transport plus any parameterized advective transport. Parameterized advective transport includes processes such as parameterized mesoscale and submesoscale transport, as well as any other advectively parameterized transport. When the parameterized advective transport is represented in the model as a skew-diffusion rather than an advection, then the parameterized skew diffusion should be included in this diagnostic, since the convergence of skew-fluxes are identical (in the continuous formulation) to the convergence of advective fluxes. + + + + K s-1 + + + "tendency_of_X" means derivative of X with respect to time. Sea water temperature is the in situ temperature of the sea water. For observed data, depending on the period during which the observation was made, the measured in situ temperature was recorded against standard "scales". These historical scales include the International Practical Temperature Scale of 1948 (IPTS-48; 1948-1967), the International Practical Temperature Scale of 1968 (IPTS-68, Barber, 1969; 1968-1989) and the International Temperature Scale of 1990 (ITS-90, Saunders 1990; 1990 onwards). Conversion of data between these scales follows t68 = t48 - (4.4 x 10e-6) * t48(100 - t - 48); t90 = 0.99976 * t68. Observations made prior to 1948 (IPTS-48) have not been documented and therefore a conversion cannot be certain. Differences between t90 and t68 can be up to 0.01 at temperatures of 40 C and above; differences of 0.002-0.007 occur across the standard range of ocean temperatures (-10 - 30 C). The International Equation of State of Seawater 1980 (EOS-80, UNESCO, 1981) and the Practical Salinity Scale (PSS-78) were both based on IPTS-68, while the Thermodynamic Equation of Seawater 2010 (TEOS-10) is based on ITS-90. References: Barber, 1969, doi: 10.1088/0026-1394/5/2/001; UNESCO, 1981; Saunders, 1990, WOCE Newsletter, 10, September 1990. + + + + K s-1 + + + "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Sea water temperature is the in situ temperature of the sea water. For observed data, depending on the period during which the observation was made, the measured in situ temperature was recorded against standard "scales". These historical scales include the International Practical Temperature Scale of 1948 (IPTS-48; 1948-1967), the International Practical Temperature Scale of 1968 (IPTS-68, Barber, 1969; 1968-1989) and the International Temperature Scale of 1990 (ITS-90, Saunders 1990; 1990 onwards). Conversion of data between these scales follows t68 = t48 - (4.4 x 10e-6) * t48(100 - t - 48); t90 = 0.99976 * t68. Observations made prior to 1948 (IPTS-48) have not been documented and therefore a conversion cannot be certain. Differences between t90 and t68 can be up to 0.01 at temperatures of 40 C and above; differences of 0.002-0.007 occur across the standard range of ocean temperatures (-10 - 30 C). The International Equation of State of Seawater 1980 (EOS-80, UNESCO, 1981) and the Practical Salinity Scale (PSS-78) were both based on IPTS-68, while the Thermodynamic Equation of Seawater 2010 (TEOS-10) is based on ITS-90. References: Barber, 1969, doi: 10.1088/0026-1394/5/2/001; UNESCO, 1981; Saunders, 1990, WOCE Newsletter, 10, September 1990. + + + + K s-1 + + + "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Horizontal mixing" means any horizontal transport other than by advection and parameterized eddy advection, usually represented as horizontal diffusion in ocean models. Sea water temperature is the in situ temperature of the sea water. For observed data, depending on the period during which the observation was made, the measured in situ temperature was recorded against standard "scales". These historical scales include the International Practical Temperature Scale of 1948 (IPTS-48; 1948-1967), the International Practical Temperature Scale of 1968 (IPTS-68, Barber, 1969; 1968-1989) and the International Temperature Scale of 1990 (ITS-90, Saunders 1990; 1990 onwards). Conversion of data between these scales follows t68 = t48 - (4.4 x 10e-6) * t48(100 - t - 48); t90 = 0.99976 * t68. Observations made prior to 1948 (IPTS-48) have not been documented and therefore a conversion cannot be certain. Differences between t90 and t68 can be up to 0.01 at temperatures of 40 C and above; differences of 0.002-0.007 occur across the standard range of ocean temperatures (-10 - 30 C). The International Equation of State of Seawater 1980 (EOS-80, UNESCO, 1981) and the Practical Salinity Scale (PSS-78) were both based on IPTS-68, while the Thermodynamic Equation of Seawater 2010 (TEOS-10) is based on ITS-90. References: Barber, 1969, doi: 10.1088/0026-1394/5/2/001; UNESCO, 1981; Saunders, 1990, WOCE Newsletter, 10, September 1990. + + + + K s-1 + + + "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized eddy advection in an ocean model means the part due to a scheme representing parameterized eddy-induced advective effects not included in the resolved model velocity field. Parameterized eddy advection can be represented on various spatial scales and there are standard names for parameterized_mesoscale_eddy_advection and parameterized_submesoscale_eddy_advection which both contribute to the total parameterized eddy advection. Sea water temperature is the in situ temperature of the sea water. For observed data, depending on the period during which the observation was made, the measured in situ temperature was recorded against standard "scales". These historical scales include the International Practical Temperature Scale of 1948 (IPTS-48; 1948-1967), the International Practical Temperature Scale of 1968 (IPTS-68, Barber, 1969; 1968-1989) and the International Temperature Scale of 1990 (ITS-90, Saunders 1990; 1990 onwards). Conversion of data between these scales follows t68 = t48 - (4.4 x 10e-6) * t48(100 - t - 48); t90 = 0.99976 * t68. Observations made prior to 1948 (IPTS-48) have not been documented and therefore a conversion cannot be certain. Differences between t90 and t68 can be up to 0.01 at temperatures of 40 C and above; differences of 0.002-0.007 occur across the standard range of ocean temperatures (-10 - 30 C). The International Equation of State of Seawater 1980 (EOS-80, UNESCO, 1981) and the Practical Salinity Scale (PSS-78) were both based on IPTS-68, while the Thermodynamic Equation of Seawater 2010 (TEOS-10) is based on ITS-90. References: Barber, 1969, doi: 10.1088/0026-1394/5/2/001; UNESCO, 1981; Saunders, 1990, WOCE Newsletter, 10, September 1990. + + + + K s-1 + + + "tendency_of_X" means derivative of X with respect to time. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Vertical mixing" means any vertical transport other than by advection and parameterized eddy advection, represented by a combination of vertical diffusion, turbulent mixing and convection in ocean models. Sea water temperature is the in situ temperature of the sea water. For observed data, depending on the period during which the observation was made, the measured in situ temperature was recorded against standard "scales". These historical scales include the International Practical Temperature Scale of 1948 (IPTS-48; 1948-1967), the International Practical Temperature Scale of 1968 (IPTS-68, Barber, 1969; 1968-1989) and the International Temperature Scale of 1990 (ITS-90, Saunders 1990; 1990 onwards). Conversion of data between these scales follows t68 = t48 - (4.4 x 10e-6) * t48(100 - t - 48); t90 = 0.99976 * t68. Observations made prior to 1948 (IPTS-48) have not been documented and therefore a conversion cannot be certain. Differences between t90 and t68 can be up to 0.01 at temperatures of 40 C and above; differences of 0.002-0.007 occur across the standard range of ocean temperatures (-10 - 30 C). The International Equation of State of Seawater 1980 (EOS-80, UNESCO, 1981) and the Practical Salinity Scale (PSS-78) were both based on IPTS-68, while the Thermodynamic Equation of Seawater 2010 (TEOS-10) is based on ITS-90. References: Barber, 1969, doi: 10.1088/0026-1394/5/2/001; UNESCO, 1981; Saunders, 1990, WOCE Newsletter, 10, September 1990. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. On land, "nitrogen fixation" means the uptake of nitrogen gas directly from the atmosphere. The representation of fixed nitrogen is model dependent, with the nitrogen entering either vegetation, soil or both. "Vegetation" means any living plants e.g. trees, shrubs, grass. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Nitrogen compounds" summarizes all chemical species containing nitrogen atoms. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. The "soil content" of a quantity refers to the vertical integral from the surface down to the bottom of the soil model. For the content between specified levels in the soil, standard names including "content_of_soil_layer" are used. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Nitrogen compounds" summarizes all chemical species containing nitrogen atoms. The list of individual species that are included in this quantity can vary between models. Where possible, the data variable should be accompanied by a complete description of the species represented, for example, by using a comment attribute. "Fertilization" means the addition of artificial fertilizers and animal manure to soil for the purpose of increasing plant nutrient concentrations. + + + + s-1 + + + "tendency_of_X" means derivative of X with respect to time. "specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. + + + + s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. + + + + s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Boundary layer mixing" means turbulent motions that transport heat, water, momentum and chemical constituents within the atmospheric boundary layer and affect exchanges between the surface and the atmosphere. The atmospheric boundary layer is typically characterised by a well-mixed sub-cloud layer of order 500 metres, and by a more extended conditionally unstable layer with boundary-layer clouds up to 2 km. (Reference: IPCC Third Assessment Report, Working Group 1: The Scientific Basis, 7.2.2.3, https://www.ipcc.ch/ipccreports/tar/wg1/273.htm). + + + + s-1 + + tnmrc + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. + + + + s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. + + + + s-1 + + tnmrd + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. "specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. + + + + s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Specific" means per unit mass. Specific humidity is the mass fraction of water vapor in (moist) air. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). "Precipitation" in the earth's atmosphere means precipitation of water in all phases. A variable with the standard name of tendency_of_specific_humidity_due_to_stratiform_cloud_and_precipitation should contain the effects of all processes which convert stratiform clouds and precipitation to or from water vapor. + + + + s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. Specific humidity is the mass fraction of water vapor in (moist) air. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). "Precipitation" in the earth's atmosphere means precipitation of water in all phases. "Boundary layer mixing" means turbulent motions that transport heat, water, momentum and chemical constituents within the atmospheric boundary layer and affect exchanges between the surface and the atmosphere. The atmospheric boundary layer is typically characterised by a well-mixed sub-cloud layer of order 500 metres, and by a more extended conditionally unstable layer with boundary-layer clouds up to 2 km. (Reference: IPCC Third Assessment Report, Working Group 1: The Scientific Basis, 7.2.2.3, https://www.ipcc.ch/ipccreports/tar/wg1/273.htm). + + + + s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. Specific humidity is the mass fraction of water vapor in (moist) air. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. In an atmosphere model, stratiform cloud is that produced by large-scale convergence (not the convection schemes). "Precipitation" in the earth's atmosphere means precipitation of water in all phases. + + + + Pa s-1 + E158 + + The surface called "surface" means the lower boundary of the atmosphere. "tendency_of_X" means derivative of X with respect to time. Air pressure is the force per unit area which would be exerted when the moving gas molecules of which the air is composed strike a theoretical surface of any orientation. + + + + kg m-2 s-1 + + + The surface called "surface" means the lower boundary of the atmosphere. "tendency_of_X" means derivative of X with respect to time. "Amount" means mass per unit area. Surface amount refers to the amount on the ground, excluding that on the plant or vegetation canopy. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Amount" means mass per unit area. The phrase "surface_snow" means snow lying on the surface. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Conversion of snow to sea ice" occurs when the mass of snow accumulated on an area of sea ice is sufficient to cause the ice to become mostly submerged. Waves can then wash over the ice and snow surface and freeze into a layer that becomes "snow ice". "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Amount" means mass per unit area. The phrase "surface_snow" means snow lying on the surface. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The quantity with standard name tendency_of_surface_snow_amount_due_to_drifting is the rate of change of snow amount caused by wind drift of snow into the sea. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Amount" means mass per unit area. The phrase "surface_snow" means snow lying on the surface. The quantity with standard name tendency_of_surface_snow_amount_due_to_sea_ice_dynamics is the rate of change of snow amount caused by advection of the sea ice upon which the snow is lying. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. "Sea ice dynamics" refers to advection of sea ice. + + + + W m-2 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. Thermal energy is the total vibrational energy, kinetic and potential, of all the molecules and atoms in a substance. The phrase "surface_snow" means snow lying on the surface. The quantity with standard name tendency_of_thermal_energy_content_of_surface_snow_due_to_rainfall_temperature_excess_above_freezing is the heat energy carried by rainfall reaching the surface. It is calculated relative to the heat that would be carried by rainfall reaching the surface at zero degrees Celsius. It is calculated as the product QrainCpTrain, where Qrain is the mass flux of rainfall reaching the surface (kg m-2 s-1), Cp is the specific heat capacity of water and Train is the temperature in degrees Celsius of the rain water reaching the surface. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. "troposphere_moles_of_X" means the total number of moles of X contained in the troposphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of carbon monoxide is CO. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. "troposphere_moles_of_X" means the total number of moles of X contained in the troposphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of HCC140a is CH3CCl3. The IUPAC name for HCC140a is 1,1,1-trichloroethane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. "troposphere_moles_of_X" means the total number of moles of X contained in the troposphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of HCFC22 is CHClF2. The IUPAC name for HCFC 22 is chloro-difluoro-methane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. "troposphere_moles_of_X" means the total number of moles of X contained in the troposphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of methane is CH4. Methane is a member of the group of hydrocarbons known as alkanes. There are standard names for the alkane group as well as for some of the individual species. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. "troposphere_moles_of_X" means the total number of moles of X contained in the troposphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of methyl bromide is CH3Br. The IUPAC name for methyl bromide is bromomethane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. "troposphere_moles_of_X" means the total number of moles of X contained in the troposphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of methyl chloride is CH3Cl. The IUPAC name for methyl chloride is chloromethane. + + + + mol s-1 + + + "tendency_of_X" means derivative of X with respect to time. "troposphere_moles_of_X" means the total number of moles of X contained in the troposphere, i.e, summed over that part of the atmospheric column and over the entire globe. The chemical formula of molecular hydrogen is H2. + + + + m s-2 + + + "tendency_of_X" means derivative of X with respect to time. A velocity is a vector quantity. "Upward" indicates a vector component which is positive when directed upward (negative downward). Upward air velocity is the vertical component of the 3D air velocity vector. + + + + m s-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. A velocity is a vector quantity. "Upward" indicates a vector component which is positive when directed upward (negative downward). Upward air velocity is the vertical component of the 3D air velocity vector. + + + + kg m-2 s-1 + + + The phrase "tendency_of_X" means derivative of X with respect to time. "Content" indicates a quantity per unit area. "Vegetation" means any living plants e.g. trees, shrubs, grass. The term "plants" refers to the kingdom of plants in the modern classification which excludes fungi. Plants are autotrophs i.e. "producers" of biomass using carbon obtained from carbon dioxide. The phrase "expressed_as" is used in the construction A_expressed_as_B, where B is a chemical constituent of A. It means that the quantity indicated by the standard name is calculated solely with respect to the B contained in A, neglecting all other chemical constituents of A. "Nitrogen compounds" summarizes all chemical species containing nitrogen atoms. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. On land, "nitrogen fixation" means the uptake of nitrogen gas directly from the atmosphere. The representation of fixed nitrogen is model dependent, with the nitrogen entering either plants, soil or both. + + + + m s-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Speed is the magnitude of velocity. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) The wind speed is the magnitude of the wind velocity. + + + + m s-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "tendency_of_X" means derivative of X with respect to time. Speed is the magnitude of velocity. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) The wind speed is the magnitude of the wind velocity. + + + + J m-2 + + + "Content" indicates a quantity per unit area. Thermal energy is the total vibrational energy, kinetic and potential, of all the molecules and atoms in a substance. The surface called "surface" means the lower boundary of the atmosphere. + + + + 1 + + + "cloud_top" refers to the top of the highest cloud. "Water" means water in all phases. A variable with the standard name of thermodynamic_phase_of_cloud_water_particles_at_cloud_top contains integers which can be translated to strings using flag_values and flag_meanings attributes. Alternatively, the data variable may contain strings which indicate the thermodynamic phase. These strings are standardised. Values must be chosen from the following list: liquid; ice; mixed; clear_sky; super_cooled_liquid_water; unknown. + + + + m + + + Thermosteric sea level change is the part caused by change in sea water density due to change in temperature i.e. thermal expansion. "Mean sea level" means the time mean of sea surface elevation at a given location over an arbitrary period sufficient to eliminate the tidal signals. Zero mean sea level change is an arbitrary level. The sum of the quantities with standard names thermosteric_change_in_mean_sea_level and halosteric_change_in_mean_sea_level has the standard name steric_change_in_mean_sea_level. + + + + m + + + "Sea surface height" is a time-varying quantity. The thermosteric change in sea surface height is the change in height that a water column having standard temperature zero degrees Celsius would undergo when its temperature is changed to the observed value. The sum of the quantities with standard names thermosteric_change_in_sea_surface_height and halosteric_change_in_sea_surface_height is the total steric change in the water column height, which has the standard name of steric_change_in_sea_surface_height. + + + + m + + + "Amount" means mass per unit area. The construction thickness_of_[X_]rainfall_amount means the accumulated "depth" of rainfall i.e. the thickness of a layer of liquid water having the same mass per unit area as the rainfall amount. + + + + m + + + "Amount" means mass per unit area. The construction thickness_of_[X_]snowfall_amount means the accumulated "depth" of snow which fell i.e. the thickness of the layer of snow at its own density. There are corresponding standard names for liquid water equivalent (lwe) thickness. + + + + m + + + "Thickness" means the vertical extent of a layer. Melt ponds occur on top of the existing sea ice. The water in melt ponds can refreeze at the surface, giving rise to a layer of ice on the melt pond, which is turn resting on the sea_ice below. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. + + + + m + + + "Thickness" means the vertical extent of a layer. + + + + m + + + "Amount" means mass per unit area. The construction thickness_of_[X_]rainfall_amount means the accumulated "depth" of rainfall i.e. the thickness of a layer of liquid water having the same mass per unit area as the rainfall amount. + + + + m + + + "Amount" means mass per unit area. The construction thickness_of_[X_]snowfall_amount means the accumulated "depth" of snow which fell i.e. the thickness of the layer of snow at its own density. There are corresponding standard names for liquid water equivalent (lwe) thickness. + + + + m + + + "Amount" means mass per unit area. The construction thickness_of_[X_]rainfall_amount means the accumulated "depth" of rainfall i.e. the thickness of a layer of liquid water having the same mass per unit area as the rainfall amount. Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. + + + + m + + + "Amount" means mass per unit area. The construction thickness_of_[X_]snowfall_amount means the accumulated "depth" of snow which fell i.e. the thickness of the layer of snow at its own density. There are corresponding standard names for liquid water equivalent (lwe) thickness. Stratiform precipitation, whether liquid or frozen, is precipitation that formed in stratiform cloud. + + + + 1 + 60 + + "probability_of_X" means the chance that X is true or of at least one occurrence of X. Space and time coordinates must be used to indicate the area and time-interval to which a probability applies. + + + + m + + + "Sea surface height" is a time-varying quantity. "Height_above_X" means the vertical distance above the named surface X. "Lowest astronomical tide" describes a local vertical reference based on the lowest water level that can be expected to occur under average meteorological conditions and under any combination of astronomical conditions. The tidal component of sea surface height describes the predicted variability of the sea surface due to astronomic forcing (chiefly lunar and solar cycles) and shallow water resonance of tidal components; for example as generated based on harmonic analysis, or resulting from the application of harmonic tidal series as boundary conditions to a numerical tidal model. + + + + m + + + "Sea surface height" is a time-varying quantity. "Height_above_X" means the vertical distance above the named surface X. "Mean sea level" means the time mean of sea surface elevation at a given location over an arbitrary period sufficient to eliminate the tidal signals. The tidal component of sea surface height describes the predicted variability of the sea surface due to astronomic forcing (chiefly lunar and solar cycles) and shallow water resonance of tidal components; for example as generated based on harmonic analysis, or resulting from the application of harmonic tidal series as boundary conditions to a numerical tidal model. + + + + s + + time + + + + + s + + + The quantity with standard name time_of_maximum_flood_depth is the time elapsed between the breaking of a levee (origin of flood water simulation) and the instant when the flood depth reaches its maximum during the simulation for a given point in space. Flood water is water that covers land which is normally not covered by water. + + + + s + + + time_sample_difference_due_to_collocation is the difference in time between two events that are collocated. Two events are deemed to be collocated based on some set of spatial, temporal, and viewing geometry criteria. + + + + s + + + The quantity with standard name time_when_flood_water_falls_below_threshold is the time elapsed between the breaking of a levee (origin of flood water simulation) and the instant when the depth falls below a given threshold for the last time, having already risen to its maximum depth, at a given point in space. If a threshold is supplied, it should be specified by associating a coordinate variable or scalar coordinate variable with the data variable and giving the coordinate variable a standard name of flood_water_thickness. The values of the coordinate variable are the threshold values for the corresponding subarrays of the data variable. If no threshold is specified, its value is taken to be zero. Flood water is water that covers land which is normally not covered by water. + + + + s + + + The quantity with standard name time_when_flood_water_rises_above_threshold is the time elapsed between the breaking of a levee (origin of flood water simulation) and the instant when the depth first rises above a given threshold at a given point in space. If a threshold is supplied, it should be specified by associating a coordinate variable or scalar coordinate variable with the data variable and giving the coordinate variable a standard name of flood_water_thickness. The values of the coordinate variable are the threshold values for the corresponding subarrays of the data variable. If no threshold is specified, its value is taken to be zero. Flood water is water that covers land which is normally not covered by water. + + + + W m-2 + + + "longwave" means longwave radiation. "toa" means top of atmosphere. Adjusted forcing is the radiative flux change caused by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.) after allowance for stratospheric temperature adjustment. + + + + W m-2 + + + "toa" means top of atmosphere. Adjusted forcing is the radiative flux change caused by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.) after allowance for stratospheric temperature adjustment. + + + + W m-2 + + + "shortwave" means shortwave radiation. "toa" means top of atmosphere. Adjusted forcing is the radiative flux change caused by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.) after allowance for stratospheric temperature adjustment. + + + + 1 + + + "Bidirectional_reflectance" depends on the angles of incident and measured radiation. Reflectance is the ratio of the energy of the reflected to the incident radiation. A coordinate variable of radiation_wavelength or radiation_frequency can be used to specify the wavelength or frequency, respectively, of the radiation. "toa" means top of atmosphere. toa_bidirectional_reflectance includes a factor to account for the cosine of the solar zenith angle but does not include any integration over solid angle. + + + + K + + + The brightness temperature of a body is the temperature of a black body which radiates the same power per unit solid angle per unit area. "toa" means top of atmosphere. + + + + K + + + The brightness temperature of a body is the temperature of a black body which radiates the same power per unit solid angle per unit area. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "toa" means top of atmosphere. + + + + K + + + toa_brightness_temperature_bias_at_standard_scene_due_to_intercalibration is the difference between top-of-atmosphere (TOA) brightness temperature +of the reference sensor and TOA brightness temperature of the +monitored sensor. This TOA brightness temperature difference is a measure of the calibration difference between the monitored and reference sensors. The standard scene is a target area with typical Earth surface and atmospheric conditions that is accepted as a reference. Brightness temperature of a body is the temperature of a black body which radiates the same power per unit solid angle per unit area at a given wavenumber. TOA brightness temperature of the standard scene is calculated using a radiative transfer simulation for a given viewing geometry. The resultant top-of-atmosphere spectral radiance is then integrated with each sensor's spectral response function and converted to equivalent brightness temperature. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + + K + + + "toa" means top of atmosphere. The brightness temperature of a body is the temperature of a black body which radiates the same power per unit solid angle per unit area at a given wavenumber. The standard scene is a target area with typical Earth surface and atmospheric conditions that is accepted as a reference. The toa radiance of the standard scene is calculated using a radiative transfer model for a given viewing geometry. The resultant toa spectral radiance is then integrated with a sensor's spectral response function and converted to equivalent brightness temperature. + + + + W m-2 + + + "toa" means top of atmosphere. Cloud radiative effect is also commonly known as "cloud radiative forcing". It is the sum of the quantities with standard names toa_shortwave_cloud_radiative_effect and toa_longwave_cloud_radiative_effect. + + + + W m-2 + + rsdt + "shortwave" means shortwave radiation. "toa" means top of atmosphere. The TOA incoming shortwave flux is the radiative flux from the sun i.e. the "downwelling" TOA shortwave flux. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + "longwave" means longwave radiation. "toa" means top of atmosphere. Instantaneous forcing is the radiative flux change caused instantaneously by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.). + + + + W m-2 + + + "toa" means top of atmosphere. Instantaneous forcing is the radiative flux change caused instantaneously by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.). + + + + W m-2 + + + "shortwave" means shortwave radiation. "toa" means top of atmosphere. Instantaneous forcing is the radiative flux change caused instantaneously by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.). + + + + W m-2 + + + "toa" means top of atmosphere. "Longwave" means longwave radiation. Cloud radiative effect is also commonly known as "cloud radiative forcing". It is the difference in radiative flux resulting from the presence of clouds, i.e. it is the difference between toa_outgoing_longwave_flux_assuming_clear_sky and toa_outgoing_longwave_flux. + + + + W m-2 + + + "toa" means top of atmosphere. The term "longwave" means longwave radiation. "X_direct_radiative_effect" refers to the instantaneous radiative impact of X on the Earth's energy balance, excluding secondary effects such as changes in cloud cover which may be caused by X. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". A phrase "assuming_condition" indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Clear sky" means in the absence of clouds. + + + + W m-2 + + + "longwave" means longwave radiation. "toa" means top of atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "longwave" means longwave radiation. "toa" means top of atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + "toa" means top of atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + rst + "shortwave" means shortwave radiation. "toa" means top of atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "shortwave" means shortwave radiation. "toa" means top of atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + "longwave" means longwave radiation. "toa" means top of atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "longwave" means longwave radiation. "toa" means top of atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + 113 E178 + + "shortwave" means shortwave radiation. "toa" means top of atmosphere. "Upward" indicates a vector component which is positive when directed upward (negative downward). Net upward radiation is the difference between radiation from below (upwelling) and radiation from above (downwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + 114 E179 + rlut + "longwave" means longwave radiation. "toa" means top of atmosphere. The TOA outgoing longwave flux is the upwelling thermal radiative flux, often called the "outgoing longwave radiation" or "OLR". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + rlutcs + A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "longwave" means longwave radiation. "toa" means top of atmosphere. The TOA outgoing longwave flux is the upwelling thermal radiative flux, often called the "outgoing longwave radiation" or "OLR". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + "toa" means top of atmosphere. The term "longwave" means longwave radiation. The TOA outgoing longwave flux is the upwelling thermal radiative flux, often called the "outgoing longwave radiation" or "OLR". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". Volcanic aerosols include both volcanic ash and secondary products such as sulphate aerosols formed from gaseous emissions of volcanic eruptions. A phrase "assuming_condition" indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. + + + + W m-2 sr-1 m-1 + + + "toa" means top of atmosphere. The TOA outgoing radiance is the upwelling radiance, i.e., toward outer space. Radiance is the radiative flux in a particular direction, per unit of solid angle. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 sr-1 (m-1)-1 + + + "toa" means top of atmosphere. The TOA outgoing radiance is the upwelling radiance, i.e., toward outer space. Radiance is the radiative flux in a particular direction, per unit of solid angle. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 sr-1 (m-1)-1 + + + toa_outgoing_radiance_per_unit_wavenumber_mean_within_collocation_scene is an average of observations of the quantity with standard name toa_outgoing_radiance_per_unit_wavenumber from a sensor's adjacent field-of-views within a collocation scene. "toa" means top of atmosphere. The TOA outgoing radiance is the upwelling radiance, i.e., toward outer space. Radiance is the radiative flux in a particular direction, per unit of solid angle. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The "collocation scene" is a grouping of a sensor's adjacent field-of-views centered on a collocation target. The size of the collocation scene is typically about twice that of the collocation target. The "collocation target" is an area on the Earth's surface at which observations from at least two sensors are collected. Its size is defined by the sensor with the largest field-of-view footprint. Two events are deemed to be collocated based on some set of spatial, temporal, and viewing geometry criteria. + + + + W m-2 sr-1 (m-1)-1 + + + toa_outgoing_radiance_per_unit_wavenumber_mean_within_collocation_target is an average of observations of the quantity with standard name toa_outgoing_radiance_per_unit_wavenumber from a sensor's adjacent field-of-views within a collocation target. "toa" means top of atmosphere. The TOA outgoing radiance is the upwelling radiance, i.e., toward outer space. Radiance is the radiative flux in a particular direction, per unit of solid angle. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The "collocation target" is an area on the Earth's surface at which observations from at least two sensors are collected. Its size is defined by the sensor with the largest field-of-view footprint. Two events are deemed to be collocated based on some set of spatial, temporal, and viewing geometry criteria. + + + + W m-2 sr-1 (m-1)-1 + + + toa_outgoing_radiance_per_unit_wavenumber_stdev_within_collocation_scene is the standard deviation of observations of the quantity with standard name toa_outgoing_radiance_per_unit_wavenumber from a sensor's adjacent field-of-views within a collocation scene. "toa" means top of atmosphere. The TOA outgoing radiance is the upwelling radiance, i.e., toward outer space. Radiance is the radiative flux in a particular direction, per unit of solid angle. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The "collocation scene" is a grouping of a sensor's adjacent field-of-views centered on a collocation target. The size of the collocation scene is typically about twice that of the collocation target. The "collocation target" is an area on the Earth's surface at which observations from at least two sensors are collected. Its size is defined by the sensor with the largest field-of-view footprint. Two events are deemed to be collocated based on some set of spatial, temporal, and viewing geometry criteria. + + + + W m-2 sr-1 (m-1)-1 + + + toa_outgoing_radiance_per_unit_wavenumber_stdev_within_collocation_target is the standard deviation of observations of the quantity with standard name toa_outgoing_radiance_per_unit_wavenumber from a sensor's adjacent field-of-views within a collocation target. "toa" means top of atmosphere. The TOA outgoing radiance is the upwelling radiance, i.e., toward outer space. Radiance is the radiative flux in a particular direction, per unit of solid angle. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The "collocation target" is an area on the Earth's surface at which observations from at least two sensors are collected. Its size is defined by the sensor with the largest field-of-view footprint. Two events are deemed to be collocated based on some set of spatial, temporal, and viewing geometry criteria. + + + + W m-2 + + rsut + "shortwave" means shortwave radiation. "toa" means top of atmosphere. The TOA outgoing shortwave flux is the reflected and scattered solar radiative flux i.e. the "upwelling" TOA shortwave flux, sometimes called the "outgoing shortwave radiation" or "OSR". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + rsutcs + A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "shortwave" means shortwave radiation. "toa" means top of atmosphere. The TOA outgoing shortwave flux is the reflected and scattered solar radiative flux i.e. the "upwelling" TOA shortwave flux, sometimes called the "outgoing shortwave radiation" or "OSR". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + The abbreviation "toa" means top of atmosphere. The term "shortwave" means shortwave radiation. The TOA outgoing shortwave flux is the reflected and scattered solar radiative flux i.e. the "upwelling" TOA shortwave flux, sometimes called the "outgoing shortwave radiation" or "OSR". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase "assuming_condition" indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Clear sky" means in the absence of clouds. + + + + W m-2 + + + The abbreviation "toa" means top of atmosphere. The term "shortwave" means shortwave radiation. The TOA outgoing shortwave flux is the reflected and scattered solar radiative flux i.e. the "upwelling" TOA shortwave flux, sometimes called the "outgoing shortwave radiation" or "OSR". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase "assuming_condition" indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. + + + + W m-2 + + + The abbreviation "toa" means top of atmosphere. The term "shortwave" means shortwave radiation. The TOA outgoing shortwave flux is the reflected and scattered solar radiative flux i.e. the "upwelling" TOA shortwave flux, sometimes called the "outgoing shortwave radiation" or "OSR". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". Volcanic aerosols include both volcanic ash and secondary products such as sulphate aerosols formed from gaseous emissions of volcanic eruptions. A phrase "assuming_condition" indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. + + + + W m-2 + + + "toa" means top of atmosphere. "Shortwave" means shortwave radiation. Cloud radiative effect is also commonly known as "cloud radiative forcing". It is the difference in radiative flux resulting from the presence of clouds, i.e. the difference between toa_net_downward_shortwave_flux and toa_net_downward_shortwave_flux_assuming_clear_sky. + + + + s + + + The quantity with standard name tracer_lifetime is the total length of time a passive tracer exists within a medium. Passive tracers are used in models to study processes such as transport and deposition. + + + + kg m-2 + + + "Amount" means mass per unit area. + + + + kg m-2 s-1 + + + In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + K + + + "tropical_cyclone_eye_brightness_temperature" means the warmest brightness temperature value in the eye region of a tropical cyclone (0 - 24 km from the storm center) derived using the Advanced Dvorak Technique, based on satellite observations. Reference: Olander, T. L., & Velden, C. S., The Advanced Dvorak Technique: Continued Development of an Objective Scheme to Estimate Tropical Cyclone Intensity Using Geostationary Infrared Satellite Imagery (2007). American Meterorological Society Weather and Forecasting, 22, 287-298. The brightness temperature of a body is the temperature of a black body which radiates the same power per unit solid angle per unit area. + + + + m s-1 + + + "tropical_cyclone_maximum_sustained_wind_speed" means the maximum sustained wind speed of a tropical cyclone, sustained over a period of one minute at the surface of the earth, derived using the Advanced Dvorak Technique based on satellite observations. Reference: Olander, T. L., & Velden, C. S., The Advanced Dvorak Technique: Continued Development of an Objective Scheme to Estimate Tropical Cyclone Intensity Using Geostationary Infrared Satellite Imagery (2007). American Meterorological Society Weather and Forecasting, 22, 287-298. + + + + W m-2 + + + "longwave" means longwave radiation. Adjusted forcing is the radiative flux change caused by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.) after allowance for stratospheric temperature adjustment. + + + + W m-2 + + + Adjusted forcing is the radiative flux change caused by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.) after allowance for stratospheric temperature adjustment. + + + + W m-2 + + + "shortwave" means shortwave radiation. Adjusted forcing is the radiative flux change caused by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.) after allowance for stratospheric temperature adjustment. + + + + Pa + + + Air pressure is the force per unit area which would be exerted when the moving gas molecules of which the air is composed strike a theoretical surface of any orientation. + + + + K + + + Air temperature is the bulk temperature of the air, not the surface (skin) temperature. + + + + m + + + Altitude is the (geometric) height above the geoid, which is the reference geopotential surface. The geoid is similar to mean sea level. + + + + W m-2 + + + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "longwave" means longwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + "longwave" means longwave radiation. Instantaneous forcing is the radiative flux change caused instantaneously by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.). + + + + W m-2 + + + Instantaneous forcing is the radiative flux change caused instantaneously by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.). + + + + W m-2 + + + "shortwave" means shortwave radiation. Instantaneous forcing is the radiative flux change caused instantaneously by an imposed change in radiative forcing agent (greenhouse gases, aerosol, solar radiation, etc.). + + + + W m-2 + + + "longwave" means longwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + "shortwave" means shortwave radiation. "Downward" indicates a vector component which is positive when directed downward (negative upward). Net downward radiation is the difference between radiation from above (downwelling) and radiation from below (upwelling). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + The term "shortwave" means shortwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + mol m-2 + + + "Content" indicates a quantity per unit area. The "troposphere content" of a quantity refers to the vertical integral from the surface to the tropopause. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for bromine_monoxide is BrO. + + + + mol m-2 + + + "Content" indicates a quantity per unit area. The "troposphere content" of a quantity refers to the vertical integral from the surface to the tropopause. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for formaldehyde is CH2O. The IUPAC name for formaldehyde is methanal. + + + + mol m-2 + + + "Content" indicates a quantity per unit area. The "troposphere content" of a quantity refers to the vertical integral from the surface to the tropopause. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for glyoxal is CHOCHO. The IUPAC name for glyoxal is ethanedial. + + + + mol m-2 + + + "Content" indicates a quantity per unit area. The "troposphere content" of a quantity refers to the vertical integral from the surface to the tropopause. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for iodine_monoxide is IO. + + + + mol m-2 + + + "Content" indicates a quantity per unit area. The "troposphere content" of a quantity refers to the vertical integral from the surface to the tropopause. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for nitrogen_dioxide is NO2. + + + + mol m-2 + + + "Content" indicates a quantity per unit area. The "troposphere content" of a quantity refers to the vertical integral from the surface to the tropopause. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for ozone is O3. The IUPAC name for ozone is trioxygen. + + + + mol m-2 + + + "Content" indicates a quantity per unit area. The "troposphere content" of a quantity refers to the vertical integral from the surface to the tropopause. For the content between specified levels in the atmosphere, standard names including content_of_atmosphere_layer are used. The chemical formula for suflur_dioxide is SO2. + + + + m + + + "Turbulent mixing length" is used in models to describe the average distance over which a fluid parcel can travel while retaining properties that allow the parcel to be distinguished from its immediate environonment. "Turbulent mixing" means chaotic fluctuations of the fluid flow. + + + + 1 + + + The "Ultraviolet Index" (UVI) is a measure of the amount of solar ultraviolet radiation that reaches the surface of the earth depending on factors such as time of day and cloud cover. It is often used to alert the public of the need to limit sun exposure and use sun creams to protect the skin. Each point on the Index scale is equivalent to 25 mW m-2 of UV radiation (reference: Australian Bureau of Meteorology, http://www.bom.gov.au/uv/about_uv_index.shtml). The UVI range is expressed as a numeric value from 0 to 20 and sometimes graphically as bands of color indicating the attendant risk of skin damage. A UVI of 0-2 is described as 'Low' (represented graphically in green); a UVI of 11 or greater is described as "Extreme" (represented graphically in purple). The higher the UVI, the greater the potential health risk to humans and the less time it takes for harm to occur. To specify the amount of cloud cover at which the data variable applies, provide a scalar coordinate variable with standard name "cloud_area_fraction". Standard names are also defined for the quantities ultraviolet_index_assuming_clear_sky and ultraviolet_index_assuming_overcast_sky. + + + + 1 + + + The "Ultraviolet Index" (UVI) is a measure of the amount of solar ultraviolet radiation that reaches the surface of the earth depending on factors such as time of day and cloud cover. It is often used to alert the public of the need to limit sun exposure and use sun creams to protect the skin. Each point on the Index scale is equivalent to 25 mW m-2 of UV radiation (reference: Australian Bureau of Meteorology, http://www.bom.gov.au/uv/about_uv_index.shtml). The UVI range is expressed as a numeric value from 0 to 20 and sometimes graphically as bands of color indicating the attendant risk of skin damage. A UVI of 0-2 is described as 'Low' (represented graphically in green); a UVI of 11 or greater is described as "Extreme" (represented graphically in purple). The higher the UVI, the greater the potential health risk to humans and the less time it takes for harm to occur. A phrase "assuming_condition" indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. Standard names are also defined for the quantities ultraviolet_index and ultraviolet_index_assuming_overcast_sky. + + + + 1 + + + The "Ultraviolet Index" (UVI) is a measure of the amount of solar ultraviolet radiation that reaches the surface of the earth depending on factors such as time of day and cloud cover. It is often used to alert the public of the need to limit sun exposure and use sun creams to protect the skin. Each point on the Index scale is equivalent to 25 mW m-2 of UV radiation (reference: Australian Bureau of Meteorology, http://www.bom.gov.au/uv/about_uv_index.shtml). The UVI range is expressed as a numeric value from 0 to 20 and sometimes graphically as bands of color indicating the attendant risk of skin damage. A UVI of 0-2 is described as 'Low' (represented graphically in green); a UVI of 11 or greater is described as "Extreme" (represented graphically in purple). The higher the UVI, the greater the potential health risk to humans and the less time it takes for harm to occur. A phrase "assuming_condition" indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Overcast" means a fractional sky cover of 95% or more when at least a portion of this amount is attributable to clouds or obscuring phenomena (such as haze, dust, smoke, fog, etc.) aloft. (Reference: AMS Glossary: http://glossary.ametsoc.org/wiki/Main_Page). Standard names are also defined for the quantities ultraviolet_index and ultraviolet_index_assuming_clear_sky. + + + + m s-1 + 40 + + A velocity is a vector quantity. "Upward" indicates a vector component which is positive when directed upward (negative downward). Upward air velocity is the vertical component of the 3D air velocity vector. The standard name downward_air_velocity may be used for a vector component with the opposite sign convention. + + + + W m-2 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Upward" indicates a vector component which is positive when directed upward (negative downward). Dry static energy is the sum of enthalpy and potential energy (itself the sum of gravitational and centripetal potential energy). Enthalpy can be written either as (1) CpT, where Cp is heat capacity at constant pressure, T is absolute temperature, or (2) U+pV, where U is internal energy, p is pressure and V is volume. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + Pa + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Upward" indicates a vector component which is positive when directed upward (negative downward). "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Upward eastward" indicates the ZX component of a tensor. An upward eastward momentum flux is an upward flux of eastward momentum, which accelerates the upper medium eastward and the lower medium westward. Momentum flux is dimensionally equivalent to stress and pressure. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The total upward eastward momentum flux due to gravity waves is the sum of the fluxes due to orographic gravity waves and nonorographic waves. The upward eastward momentum flux due to orographic gravity waves has the standard name upward_eastward_momentum_flux_in_air_due_to_orographic_gravity_waves. The total upward eastward momentum flux due to nonorographic gravity waves is the sum of the fluxes due to eastward and westward propagating waves. The latter has the standard name upward_eastward_momentum_flux_in_air_due_to_nonorographic_westward_gravity_waves. + + + + Pa + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Upward" indicates a vector component which is positive when directed upward (negative downward). "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Upward eastward" indicates the ZX component of a tensor. An upward eastward momentum flux is an upward flux of eastward momentum, which accelerates the upper medium eastward and the lower medium westward. Momentum flux is dimensionally equivalent to stress and pressure. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The total upward eastward momentum flux due to gravity waves is the sum of the fluxes due to orographic gravity waves and nonorographic waves. The upward eastward momentum flux due to orographic gravity waves has the standard name upward_eastward_momentum_flux_in_air_due_to_orographic_gravity_waves. The total upward eastward momentum flux due to nonorographic gravity waves is the sum of the fluxes due to eastward and westward propagating waves. The former has the standard name upward_eastward_momentum_flux_in_air_due_to_nonorographic_eastward _gravity_waves. + + + + Pa + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Upward" indicates a vector component which is positive when directed upward (negative downward). "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Upward eastward" indicates the ZX component of a tensor. An upward eastward momentum flux is an upward flux of eastward momentum, which accelerates the upper medium eastward and the lower medium westward. Momentum flux is dimensionally equivalent to stress and pressure. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The total upward eastward momentum flux due to gravity waves is the sum of the fluxes due to orographic gravity waves and nonorographic waves. The total upward eastward momentum flux due to nonorographic gravity waves is the sum of the fluxes due to eastward and westward propagating waves. These quantities have the standard names upward_eastward_momentum_flux_in_air_due_to_nonorographic_eastward_gravity_waves and upward_eastward_momentum_flux_in_air_due_to_nonorographic_westward_gravity_waves, respectively. + + + + Pa + + + "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. "Eastward" indicates a vector component which is positive when directed eastward (negative westward). "Upward" indicates a vector component which is positive when directed upward (negative downward). "Upward eastward" indicates the ZX component of a tensor. An upward eastward stress is an upward flux of eastward momentum, which accelerates the upper medium eastward and the lower medium westward. + + + + m3 s-2 + + + "Eliassen Palm flux" is a widely used vector in the meridional plane, and the divergence of this flux appears as a forcing in the Transformed Eulerian mean formulation of the zonal mean zonal wind equation. "Upward" indicates a vector component which is positive when directed upward (negative downward). + + + + W m-2 + + + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. "ground_level" means the land surface (including beneath snow, ice and surface water, if any). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Upward" indicates a vector component which is positive when directed upward (negative downward). The quantity with standard name upward_geothermal_heat_flux_at_ground_level_in_land_ice is the upward heat flux at the interface between the ice and bedrock. It does not include any heat flux from the ocean into an ice shelf. + + + + W m-2 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + ground_level means the land surface (beneath the snow and surface water, if any). "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + ground_level means the land surface (beneath the snow and surface water, if any). "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). The vertical heat flux in air is the sum of all heat fluxes i.e. radiative, latent and sensible. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). The latent heat flux is the exchange of heat across a surface on account of evaporation and condensation (including sublimation and deposition). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + Pa + + + "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. "Northward" indicates a vector component which is positive when directed northward (negative southward). "Upward" indicates a vector component which is positive when directed upward (negative downward). "Upward northward" indicates the ZY component of a tensor. An upward northward stress is an upward flux of northward momentum, which accelerates the upper medium northward and the lower medium southward. + + + + kg s-1 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). + + + + W m-2 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). The sea ice basal heat flux is the vertical heat flux (apart from radiation i.e. "diffusive") in sea water at the base of the sea ice. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. + + + + m s-1 + + + A velocity is a vector quantity. "Upward" indicates a vector component which is positive when directed upward (negative downward). + + + + m s-1 + + + A velocity is a vector quantity. "Upward" indicates a vector component which is positive when directed upward (negative downward). The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Parameterized mesoscale eddies occur on a spatial scale of many tens of kilometres and an evolutionary time of weeks. Reference: James C. McWilliams 2016, Submesoscale currents in the ocean, Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, volume 472, issue 2189. DOI: 10.1098/rspa.2016.0117. Parameterized mesoscale eddies are represented in ocean models using schemes such as the Gent-McWilliams scheme. + + + + W m-2 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). The sensible heat flux, also called "turbulent" heat flux, is the exchange of heat caused by the motion of air. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + m s-1 + + + A velocity is a vector quantity. "Upward" indicates a vector component which is positive when directed upward (negative downward). Upward air velocity is the vertical component of the 3D air velocity vector. The "Transformed Eulerian Mean" refers to a formulation of the mean equations which incorporates some eddy terms into the definition of the mean, described in Andrews et al (1987): Middle Atmospheric Dynamics. Academic Press. + + + + s-2 + + + A quantity with standard name Xward_Yward_derivative_of_geopotential is a second spatial derivative of geopotential in the direction specified by X and Y, i.e., d2P/dXdY. Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. "Upward" indicates a vector component which is positive when directed upward (negative downward). "component_derivative_of_X" means derivative of X with respect to distance in the component direction, which may be "northward", "southward", "eastward", "westward", "x" or "y". The last two indicate derivatives along the axes of the grid, in the case where they are not true longitude and latitude. + + + + kg m-2 s-1 + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Upward" indicates a vector component which is positive when directed upward (negative downward). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + Pa + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). "x" indicates a vector component along the grid x-axis, positive with increasing x. "Upward x" indicates the ZX component of a tensor. An upward x stress is an upward flux of x-ward momentum, which accelerates the upper medium in the positive x direction and the lower medium in the negative x direction. + + + + Pa + + + "Upward" indicates a vector component which is positive when directed upward (negative downward). "y" indicates a vector component along the grid y-axis, positive with increasing y. "Upward y" indicates the ZY component of a tensor. An upward y-ward stress is an upward flux of momentum, which accelerates the upper medium in the positive y direction and the lower medium in the negative y direction. + + + + W m-2 + + + The term "longwave" means longwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + The term "longwave" means longwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Clear sky" means in the absence of clouds. + + + + W m-2 sr-1 + + + The term "longwave" means longwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + + + + W m-2 m-1 sr-1 + + + Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. + + + + W m-2 m-1 + + + Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. + + + + W m-2 m-1 + + + Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A coordinate variable for radiation wavelength should be given the standard name radiation_wavelength. + + + + W m-2 + + + The term "shortwave" means shortwave radiation. Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + W m-2 + + + Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase assuming_condition indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Clear sky" means in the absence of clouds. + + + + W m-2 + + + Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. A phrase "assuming_condition" indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Clear sky" means in the absence of clouds. + + + + W m-2 sr-1 + + + Upwelling radiation is radiation from below. It does not mean "net upward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. The term "shortwave" means shortwave radiation. Radiance is the radiative flux in a particular direction, per unit of solid angle. The direction towards which it is going must be specified, for instance with a coordinate of zenith_angle. If the radiation does not depend on direction, a standard name of isotropic radiance should be chosen instead. + + + + 1 + 87 + + "X_area_fraction" means the fraction of horizontal area occupied by X. "X_area" means the horizontal area occupied by X within the grid cell. "Vegetation" means any plants e.g. trees, shrubs, grass. + + + + kg m-2 + + + "Content" indicates a quantity per unit area. "Vegetation" means any plants e.g. trees, shrubs, grass. Plants are autotrophs i.e. "producers" of biomass using carbon obtained from carbon dioxide. + + + + kg m-2 + + + "Content" indicates a quantity per unit area. "Vegetation" means any living plants e.g. trees, shrubs, grass. "C" means the element carbon and "13C" is the stable isotope "carbon-13", having six protons and seven neutrons. + + + + kg m-2 + + + "Content" indicates a quantity per unit area. "Vegetation" means any living plants e.g. trees, shrubs, grass. "C" means the element carbon and "14C" is the radioactive isotope "carbon-14", having six protons and eight neutrons and used in radiocarbon dating. + + + + kg m-2 + + + "Content" indicates a quantity per unit area. "Vegetation" means any living plants e.g. trees, shrubs, grass. The term "plants" refers to the kingdom of plants in the modern classification which excludes fungi. Plants are autotrophs i.e. "producers" of biomass using carbon obtained from carbon dioxide. + + + + m2 s-1 + + + The vertical_component_of_ocean_xy_tracer_diffusivity means the vertical component of the diffusivity of tracers in the ocean due to lateral mixing. This quantity could appear in formulations of lateral diffusivity in which "lateral" does not mean "iso-level", e.g. it would not be used for isopycnal diffusivity. "Tracer diffusivity" means the diffusivity of heat and salinity due to motion which is not resolved on the grid scale of the model. + + + + kg m-2 s-1 + + + The virtual_salt_flux_into_sea_water_due_to_process is the salt flux that would have the same effect on the sea surface salinity as water_flux_out_of_sea_water_due_to_process. Flux correction is also called "flux adjustment". A positive flux correction is downward i.e. added to the ocean. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + + The virtual_salt_flux_into_sea_water is the salt flux that would have the same effect on the sea surface salinity as the water_flux_out_of_sea_water. It includes the effects of precipitation, evaporation, river outflow, sea-ice and any water flux relaxation(s) and correction(s) that may have been applied. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + + The virtual_salt_flux_into_sea_water_due_to_process is the salt flux that would have the same effect on the sea surface salinity as water_flux_out_of_sea_water_due_to_process. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + + kg m-2 s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The virtual_salt_flux_into_sea_water_due_to_newtonian_relaxation is the salt flux that would have the same effect on the sea surface salinity as water_flux_out_of_sea_water_due_to_newtonian_relaxation. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + + The virtual_salt_flux_into_sea_water_due_to_process is the salt flux that would have the same effect on the sea surface salinity as water_flux_out_of_sea_water_due_to_process. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + + kg m-2 s-1 + + + The virtual_salt_flux_into_sea_water_due_to_process is the salt flux that would have the same effect on the sea surface salinity as water_flux_out_of_sea_water_due_to_process. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sea ice thermodynamics" refers to the addition or subtraction of mass due to surface and basal fluxes, i.e., due to melting, sublimation and fusion. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. + + + + kg m-2 s-1 + + + The virtual_salt_flux_into_sea_water_due_to_process is the salt flux that would have the same effect on the sea surface salinity as water_flux_out_of_sea_water_due_to_process. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "River" refers to water in the fluvial system (stream and floodplain). + + + + K + 12 + + The virtual temperature of air is the temperature at which the dry air constituent of a parcel of moist air would have the same density as the moist air at the same pressure. + + + + m + 20 + + The visibility is the distance at which something can be seen. + + + + m-1 + + + The volume scattering/absorption/attenuation coefficient is the fractional change of radiative flux per unit path length due to the stated process. Coefficients with canonical units of m2 s-1 i.e. multiplied by density have standard names with "specific_" instead of "volume_". The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths unless a coordinate of "radiation_wavelength" or "radiation_frequency" is included to specify the wavelength. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Dried_aerosol" means that the aerosol sample has been dried from the ambient state, but that the dry state (relative humidity less than 40 per cent) has not necessarily been reached. To specify the relative humidity at which the sample was measured, provide a scalar coordinate variable with the standard name of "relative_humidity". The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + + m-1 + + + Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The volume scattering/absorption/attenuation coefficient is the fractional change of radiative flux per unit path length due to the stated process. Coefficients with canonical units of m2 s-1 i.e. multiplied by density have standard names with specific_ instead of volume_. The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength is included to specify the wavelength. + + + + m-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The volume scattering/absorption/attenuation coefficient is the fractional change of radiative flux per unit path length due to the stated process. Coefficients with canonical units of m2 s-1 i.e. multiplied by density have standard names with specific_ instead of volume_. The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength is included to specify the wavelength. + + + + m-1 sr-1 + + + Attenuation is the sum of absorption and scattering. Attenuation is sometimes called "extinction". The attenuated backwards scattering function includes the effects of two-way attenuation by the medium between a radar source and receiver. The volume scattering function is the fraction of incident radiative flux scattered into unit solid angle per unit path length. Backwards scattering refers to the sum of scattering into all backward angles i.e. scattering_angle exceeding pi/2 radians. A scattering_angle should not be specified with this quantity. + + + + m-1 sr-1 + + + Attenuation is the sum of absorption and scattering. Attenuation is sometimes called "extinction". The attenuated backwards scattering function includes the effects of two-way attenuation by the medium between a radar source and receiver. The volume scattering function is the fraction of incident radiative flux scattered into unit solid angle per unit path length. Backwards scattering refers to the sum of scattering into all backward angles i.e. scattering_angle exceeding pi/2 radians. A scattering_angle should not be specified with this quantity. A phrase "assuming_condition" indicates that the named quantity is the value which would obtain if all aspects of the system were unaltered except for the assumption of the circumstances specified by the condition. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. + + + + m-1 + + + Downwelling radiation is radiation from above. It does not mean "net downward". The sign convention is that "upwelling" is positive upwards and "downwelling" is positive downwards. Radiative flux is the sum of shortwave and longwave radiative fluxes. When thought of as being incident on a surface, a radiative flux is sometimes called "irradiance". In addition, it is identical with the quantity measured by a cosine-collector light-meter and sometimes called "vector irradiance". In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The volume scattering/absorption/attenuation coefficient is the fractional change of radiative flux per unit path length due to the stated process. Coefficients with canonical units of m2 s-1 i.e. multiplied by density have standard names with specific_ instead of volume_. The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength is included to specify the wavelength. Attenuation is the sum of absorption and scattering. Attenuation is sometimes called "extinction". Also called "diffuse" attenuation, the attenuation of downwelling radiative flux refers to the decrease with decreasing height or increasing depth of the downwelling component of radiative flux, regardless of incident direction. + + + + m-1 + + + The volume scattering/absorption/attenuation coefficient is the fractional change of radiative flux per unit path length due to the stated process. Coefficients with canonical units of m2 s-1 i.e. multiplied by density have standard names with specific_ instead of volume_. Backwards scattering refers to the sum of scattering into all backward angles i.e. scattering_angle exceeds pi/2 radians. A scattering_angle should not be specified with this quantity. The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength is included to specify the wavelength. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Dried_aerosol" means that the aerosol sample has been dried from the ambient state, but that the dry state (relative humidity less than 40 per cent) has not necessarily been reached. To specify the relative humidity at which the sample was measured, provide a scalar coordinate variable with the standard name of "relative_humidity". The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + + m-1 + + + Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The volume scattering/absorption/attenuation coefficient is the fractional change of radiative flux per unit path length due to the stated process. Coefficients with canonical units of m2 s-1 i.e. multiplied by density have standard names with specific_ instead of volume_. The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength is included to specify the wavelength. Scattering of radiation is its deflection from its incident path without loss of energy. Backwards scattering refers to the sum of scattering into all backward angles i.e. scattering_angle exceeding pi/2 radians. A scattering_angle should not be specified with this quantity. + + + + m-1 + + + Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The volume scattering/absorption/attenuation coefficient is the fractional change of radiative flux per unit path length due to the stated process. Coefficients with canonical units of m2 s-1 i.e. multiplied by density have standard names with specific_ instead of volume_. The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength is included to specify the wavelength. Attenuation is the sum of absorption and scattering. Attenuation is sometimes called "extinction". Beam attenuation refers to the decrease of radiative flux along the direction of the incident path. It is distinguished from attenuation of the downwelling component of radiative flux from any incident direction, also called "diffuse" attenuation. + + + + m-1 + + + Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The volume scattering/absorption/attenuation coefficient is the fractional change of radiative flux per unit path length due to the stated process. The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength is included to specify the wavelength. Attenuation is the sum of absorption and scattering. Attenuation is sometimes called "extinction". Beam attenuation refers to the decrease of radiative flux along the direction of the incident path. It is distinguished from attenuation of the downwelling component of radiative flux from any incident direction, also called "diffuse" attenuation. The phrase "corrected for pure water attenuance" means the attenuation coefficient has been adjusted/calibrated to remove the influence of absorption/scattering by the water itself. Coefficients with canonical units of m2 s-1 i.e. multiplied by density have standard names with specific_ instead of volume_. + + + + m -1 + + + The volume extinction coefficient is the fractional change of radiative flux per unit path length. Extinction is the sum of absorption and scattering, sometimes called "attenuation". "Extinction" is the term most commonly used at optical wavelengths whereas "attenuation" is more often used at radio and radar wavelengths. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. + + + + m-1 + + + The volume extinction coefficient is the fractional change of radiative flux per unit path length. Extinction is the sum of absorption and scattering, sometimes called "attenuation". "Extinction" is the term most commonly used at optical wavelengths whereas "attenuation" is more often used at radio and radar wavelengths. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Cloud particles" means suspended liquid or ice water droplets. A coordinate of radiation_wavelength or radiation_frequency should be included to specify either the wavelength or frequency. + + + + 1 + + + "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. + + + + 1 + + + "Condensed water" means liquid and ice. "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. + + + + 1 + + + "Condensed water" means liquid and ice. "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. When soil moisture equals or exceeds the critical point evapotranspiration takes place at the potential rate and is controlled by the ambient meteorological conditions (temperature, wind, relative humidity). Evapotranspiration is the sum of evaporation and plant transpiration. Potential evapotranspiration is the rate at which evapotranspiration would occur under ambient conditions from a uniformly vegetated area when the water supply is not limiting. + + + + 1 + + + "Condensed water" means liquid and ice. "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. The field capacity of soil is the maximum content of water it can retain against gravitational drainage. + + + + 1 + + + "Condensed water" means liquid and ice. "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. The wilting point of soil is the water content below which plants cannot extract sufficient water to balance their loss through transpiration. + + + + 1 + + + "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. "Condensed water" means liquid and ice. "Volume_fraction_of_condensed_water_in_soil_pores" is the ratio of the volume of condensed water in soil pores to the volume of the pores themselves. + + + + 1 + + + "frozen_water" means ice. "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. + + + + 1 + + + "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. + + + + 1 + + + "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. + + + + 1 + + + "Volume fraction" is used in the construction volume_fraction_of_X_in_Y, where X is a material constituent of Y. + + + + 1 + + + "ratio_of_X_to_Y" means X/Y. "stp" means standard temperature (0 degC) and pressure (101325 Pa). + + + + m-1 + + + Radiative flux is the sum of shortwave and longwave radiative fluxes. Scattering of radiation is its deflection from its incident path without loss of energy. The volume scattering/absorption/attenuation coefficient is the fractional change of radiative flux per unit path length due to the stated process. Coefficients with canonical units of m2 s-1 i.e. multiplied by density have standard names with "specific_" instead of "volume_". The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths unless a coordinate of "radiation_wavelength" or "radiation_frequency" is included to specify the wavelength. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exist in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity at which the quantity described by the standard name applies, provide a scalar coordinate variable with the standard name of "relative_humidity". + + + + m-1 + + + Radiative flux is the sum of shortwave and longwave radiative fluxes. Scattering of radiation is its deflection from its incident path without loss of energy. The volume scattering/absorption/attenuation coefficient is the fractional change of radiative flux per unit path length due to the stated process. Coefficients with canonical units of m2 s-1 i.e. multiplied by density have standard names with "specific_" instead of "volume_". The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths unless a coordinate of "radiation_wavelength" or "radiation_frequency" is included to specify the wavelength. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Dried_aerosol" means that the aerosol sample has been dried from the ambient state before sizing, but that the dry state (relative humidity less than 40 per cent) has not necessarily been reached. To specify the relative humidity at which the sample was measured, provide a scalar coordinate variable with the standard name of "relative_humidity". + + + + m-1 + + + Radiative flux is the sum of shortwave and longwave radiative fluxes. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The volume scattering/absorption/attenuation coefficient is the fractional change of radiative flux per unit path length due to the stated process. Coefficients with canonical units of m2 s-1 i.e. multiplied by density have standard names with specific_ instead of volume_. The scattering/absorption/attenuation coefficient is assumed to be an integral over all wavelengths, unless a coordinate of radiation_wavelength is included to specify the wavelength. Scattering of radiation is its deflection from its incident path without loss of energy. The (range of) direction(s) of scattering can be specified by a coordinate of scattering_angle. + + + + m-1 sr-1 + + + Radiative flux is the sum of shortwave and longwave radiative fluxes. Scattering of radiation is its deflection from its incident path without loss of energy. The volume scattering function is the intensity (flux per unit solid angle) of scattered radiation per unit length of scattering medium, normalised by the incident radiation flux. The (range of) direction(s) of scattering can be specified by a coordinate of scattering_angle. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the scattering applies at specific wavelengths or frequencies. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Aerosol" means the system of suspended liquid or solid particles in air (except cloud droplets) and their carrier gas, the air itself. "Ambient_aerosol" means that the aerosol is measured or modelled at the ambient state of pressure, temperature and relative humidity that exists in its immediate environment. "Ambient aerosol particles" are aerosol particles that have taken up ambient water through hygroscopic growth. The extent of hygroscopic growth depends on the relative humidity and the composition of the particles. To specify the relative humidity and temperature at which the quantity described by the standard name applies, provide scalar coordinate variables with standard names of "relative_humidity" and "air_temperature". + + + + m-1 sr-1 + + + Radiative flux is the sum of shortwave and longwave radiative fluxes. Scattering of radiation is its deflection from its incident path without loss of energy. The volume scattering function is the intensity (flux per unit solid angle) of scattered radiation per unit length of scattering medium, normalised by the incident radiation flux. The (range of) direction(s) of scattering can be specified by a coordinate of scattering_angle. A coordinate variable of radiation_wavelength or radiation_frequency can be specified to indicate that the scattering applies at specific wavelengths or frequencies. + + + + kg m-2 + 57 + + "Amount" means mass per unit area. "Water" means water in all phases. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) + + + + kg m-2 + + + "Amount" means mass per unit area. "Water" means water in all phases. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) "Canopy" means the vegetative covering over a surface. The canopy is often considered to be the outer surfaces of the vegetation. Plant height and the distribution, orientation and shape of plant leaves within a canopy influence the atmospheric environment and many plant processes within the canopy. Reference: AMS Glossary http://glossary.ametsoc.org/wiki/Canopy. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. Previously, the qualifier "where_type" was used to specify that the quantity applies only to the part of the grid box of the named type. Names containing the where_type qualifier are deprecated and newly created data should use the cell_methods attribute to indicate the horizontal area to which the quantity applies. + + + + kg m-2 s-1 + + + "Water" means water in all phases. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. Previously, the qualifier where_type was used to specify that the quantity applies only to the part of the grid box of the named type. Names containing the where_type qualifier are deprecated and newly created data should use the cell_methods attribute to indicate the horizontal area to which the quantity applies."Canopy" means the vegetative covering over a surface. The canopy is often considered to be the outer surfaces of the vegetation. Plant height and the distribution, orientation and shape of plant leaves within a canopy influence the atmospheric environment and many plant processes within the canopy. Reference: AMS Glossary http://glossary.ametsoc.org/wiki/Canopy. + + + + kg m-2 s-1 + + + "Water" means water in all phases. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + evspsbl + Water means water in all phases. "Evapotranspiration" means all water vapor fluxes into the atmosphere from the surface: liquid evaporation, sublimation and transpiration. Evaporation is the conversion of liquid or solid into vapor. Transpiration is the process by which water is carried from the roots of plants and evaporates from the stomata. (The conversion of solid alone into vapor is called "sublimation".) In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. Unless indicated in the cell_methods attribute, a quantity is assumed to apply to the whole area of each horizontal grid box. + + + + kg m-2 s-1 + + + "Water" means water in all phases. Flux correction is also called "flux adjustment". A positive flux correction is downward i.e. added to the ocean. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + wfo + "Water" means water in all phases. The water flux into sea water is the freshwater entering as a result of precipitation, evaporation, river inflow, sea ice effects and water flux relaxation and correction (if applied). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + + The water flux into sea water is the freshwater entering as a result of precipitation, evaporation, river inflow, sea ice effects and water flux correction (if applied). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sea ice thermodynamics" refers to the addition or subtraction of mass due to surface and basal fluxes, i.e., due to melting, sublimation and fusion. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. + + + + kg m-2 s-1 + + + The water flux into the ocean is the freshwater entering the sea water as a result of precipitation, evaporation, river inflow, sea ice effects and water flux correction (if applied). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase "due_to_" process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Surface drainage" refers to all melt water forming at the sea ice surface and subsequently running into the sea. + + + + kg m-2 s-1 + + + The water flux into sea water is the freshwater entering as a result of precipitation, evaporation, river inflow, sea ice effects and water flux correction (if applied). The water flux into sea water from icebergs is due to the melting of the iceberg. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + + "Land ice" means glaciers, ice-caps and ice-sheets resting on bedrock and also includes ice-shelves. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The water flux into sea water from land ice is the freshwater entering the ocean as a result of runoff from the surface and base of the ice and melting from the ice shelf base and vertical ice front. For an area-average, the cell_methods attribute should be used to specify whether the average is over the area of the whole grid cell or the area of the ocean portion only. + + + + kg m-2 s-1 + + + "Water" means water in all phases. The water flux or volume transport into sea water from rivers is the inflow to the ocean, often applied to the surface in ocean models. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "River" refers to water in the fluvial system (stream and floodplain). + + + + kg m-2 s-1 + + + "Water" means water in all phases, including frozen i.e. ice and snow. The surface called "surface" means the lower boundary of the atmosphere. "Downward" indicates a vector component which is positive when directed downward (negative upward). The surface water flux is the result of precipitation and evaporation. The water flux into sea water is the freshwater entering as a result of precipitation, evaporation, river inflow, sea ice effects and water flux correction (if applied). The water flux or volume transport into sea water from rivers is the inflow to the ocean, often applied to the surface in ocean models. "River" refers to water in the fluvial system (stream and floodplain). In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + + Water means water in all phases. The water_flux_into_sea_water_without_flux_correction is the freshwater entering as a result of precipitation, evaporation, river inflow and sea ice effects. The total water flux including any flux relaxation(s) or correction(s) is described by the standard name water_flux_into_sea_water. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + + "Water" means water in all phases. The water_flux_out_of_sea_ice_and_sea_water is the freshwater leaving the ocean as a result of precipitation, evaporation, river outflow and any water flux relaxation(s) and correction(s) that may have been applied. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. "Sea ice" means all ice floating in the sea which has formed from freezing sea water, rather than by other processes such as calving of land ice to form icebergs. + + + + kg m-2 s-1 + + + The quantity water_flux_out_of_sea_water is the quantity with standard name water_flux_into_sea_water multiplied by -1. "Water" means water in all phases. The water flux out of sea water is the freshwater leaving as a result of precipitation, evaporation, river outflow, sea-ice and any water flux relaxation(s) and correction(s) that may have been applied. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + + The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. The water_flux_out_of_sea_water_due_to_newtonian_relaxation is the freshwater leaving as a result of the Newtonian relaxation of the sea surface salinity. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + + The water flux out of sea water is the freshwater leaving the sea water. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. "Sea ice thermodynamics" refers to the addition or subtraction of sea ice mass due to surface and basal fluxes, i.e. due to melting, sublimation and fusion. + + + + kg m-2 + + + "Amount" means mass per unit area. "Water" means water in all phases. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) Potential evaporation is the rate at which evaporation would take place under unaltered ambient conditions (temperature, relative humidity, wind, etc.) if the supply of water were unlimited, as if from an open water surface. + + + + kg m-2 s-1 + + + "Water" means water in all phases. Evaporation is the conversion of liquid or solid into vapor. (The conversion of solid alone into vapor is called "sublimation".) Potential evaporation is the rate at which evaporation would take place under unaltered ambient conditions (temperature, relative humidity, wind, etc.) if the supply of water were unlimited, as if from an open water surface. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + kg m-2 s-1 + + + "Water" means water in all phases. Sublimation is the conversion of solid into vapor. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + m + + + 'Water surface height above reference datum' means the height of the upper surface of a body of liquid water, such as sea, lake or river, above an arbitrary reference datum. The altitude of the datum should be provided in a variable with standard name water_surface_reference_datum_altitude. The surface called "surface" means the lower boundary of the atmosphere. + + + + m + + + Altitude is the (geometric) height above the geoid, which is the reference geopotential surface. The geoid is similar to mean sea level. 'Water surface reference datum altitude' means the altitude of the arbitrary datum referred to by a quantity with standard name 'water_surface_height_above_reference_datum'. The surface called "surface" means the lower boundary of the atmosphere. + + + + m + + + Depth is the vertical distance below the surface. The water table is the surface below which the soil is saturated with water such that all pore spaces are filled. + + + + Pa + 55 + + The partial pressure of a gaseous constituent of air is the pressure which it alone would exert with unchanged temperature and number of moles per unit volume. + + + + Pa + 56 + + Water vapor saturation deficit is the difference between the saturationwater vapor partial pressure and the actual water vapor partial pressure in air. + + + + m3 s-1 + + + The water flux or volume transport in rivers is the amount of water flowing in the river channel and flood plain. "Water" means water in all phases. + + + + m3 s-1 + + + "Water" means water in all phases. The water flux or volume transport into sea water from rivers is the inflow to the ocean, often applied to the surface in ocean models. "River" refers to water in the fluvial system (stream and floodplain). + + + + s-1 + + + Frequency is the number of oscillations of a wave per unit time. + + + + s-2 + + + A quantity with standard name Xward_Yward_derivative_of_geopotential is a second spatial derivative of geopotential, P, in the direction specified by X and Y, i.e., d2P/dXdY. Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. "Westward" indicates a vector component which is positive when directed westward (negative eastward). "Upward" indicates a vector component which is positive when directed upward (negative downward). "component_derivative_of_X" means derivative of X with respect to distance in the component direction, which may be "northward", "southward", "eastward", "westward", "x" or "y". The last two indicate derivatives along the axes of the grid, in the case where they are not true longitude and latitude. + + + + s-2 + + + A quantity with standard name Xward_Yward_derivative_of_geopotential is a second spatial derivative of geopotential, P, in the direction specified by X and Y, i.e., d2P/dXdY. Geopotential is the sum of the specific gravitational potential energy relative to the geoid and the specific centripetal potential energy. "Westward" indicates a vector component which is positive when directed westward (negative eastward). "component_derivative_of_X" means derivative of X with respect to distance in the component direction, which may be "northward", "southward", "eastward", "westward", "x" or "y". The last two indicate derivatives along the axes of the grid, in the case where they are not true longitude and latitude. + + + + K + + + Wet bulb potential temperature is the temperature a parcel of air would have if moved dry adiabatically until it reaches saturation and thereafter moist adiabatically to sea level pressure. + + + + K + + + + + + + degree + 31 + + Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) In meteorological reports, the direction of the wind vector is usually (but not always) given as the direction from which it is blowing (wind_from_direction) (westerly, northerly, etc.). In other contexts, such as atmospheric modelling, it is often natural to give the direction in the usual manner of vectors as the heading or the direction to which it is blowing (wind_to_direction) (eastward, southward, etc.) "from_direction" is used in the construction X_from_direction and indicates the direction from which the velocity vector of X is coming. + + + + degree + + + The phrase "from_direction" is used in the construction X_from_direction and indicates the direction from which the velocity vector of X is coming. The direction is a bearing in the usual geographical sense, measured positive clockwise from due north. A gust is a sudden brief period of high wind speed. In an observed time series of wind speed, the gust wind speed can be indicated by a cell_methods of "maximum" for the time-interval. In an atmospheric model which has a parametrised calculation of gustiness, the gust wind speed may be separately diagnosed from the wind speed. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name "upward_air_velocity".) In meteorological reports, the direction of the wind vector is usually (but not always) given as the direction from which it is blowing ("wind_from_direction") (westerly, northerly, etc.). In other contexts, such as atmospheric modelling, it is often natural to give the direction in the usual manner of vectors as the heading or the direction to which it is blowing ("wind_to_direction") (eastward, southward, etc.). + + + + W m-2 + 126 + + Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + m s-1 + 32 + + Speed is the magnitude of velocity. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) The wind speed is the magnitude of the wind velocity. + + + + m s-1 + + + Speed is the magnitude of velocity. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) The wind speed is the magnitude of the wind velocity. A gust is a sudden brief period of high wind speed. In an observed timeseries of wind speed, the gust wind speed can be indicated by a cell_methods of maximum for the time-interval. In an atmospheric model which has a parametrised calculation of gustiness, the gust wind speed may be separately diagnosed from the wind speed. + + + + s-1 + N136 + + Speed is the magnitude of velocity. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) The wind speed is the magnitude of the wind velocity. Wind speed shear is the derivative of wind speed with respect to height. + + + + degree + + + Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) In meteorological reports, the direction of the wind vector is usually (but not always) given as the direction from which it is blowing (wind_from_direction) (westerly, northerly, etc.). In other contexts, such as atmospheric modelling, it is often natural to give the direction in the usual manner of vectors as the heading or the direction to which it is blowing (wind_to_direction) (eastward, southward, etc.) "to_direction" is used in the construction X_to_direction and indicates the direction towards which the velocity vector of X is headed. The direction is a bearing in the usual geographical sense, measured positive clockwise from due north. + + + + kg m-2 + + + "Content" indicates a quantity per unit area. "Wood debris" means dead organic matter composed of coarse wood. It is distinct from fine litter. The precise distinction between "fine" and "coarse" is model dependent. + + + + kg m-2 + + + "Content" indicates a quantity per unit area. "Wood debris" means dead organic matter composed of coarse wood. It is distinct from fine litter. The precise distinction between "fine" and "coarse" is model dependent. The sum of the quantities with standard names wood_debris_mass_content_of_nitrogen, surface_litter_mass_content_of_nitrogen and subsurface_litter_mass_content_of_nitrogen is the total nitrogen mass content of dead plant material. + + + + Pa m-1 + + + "component_derivative_of_X" means the derivative of X with respect to distance in the component direction, which may be northward, southward, eastward, westward, x or y. The last two indicate derivatives along the axes of the grid, whether or not they are true longitude and latitude. x_derivative_of_ocean_rigid_lid_pressure means (d/dx) of the ocean surface pressure, as derived by a rigid lid approximation, keeping the other horizontal coordinate (y, presumably) constant. + + + + W m-2 + + + "x" indicates a vector component along the grid x-axis, positive with increasing x. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + m s-1 + + + "x" indicates a vector component along the grid x-axis, positive with increasing x. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + + + m s-1 + + + "x" indicates a vector component along the grid x-axis, positive with increasing x. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) A gust is a sudden brief period of high wind speed. In an observed timeseries of wind speed, the gust wind speed can be indicated by a cell_methods of maximum for the time-interval. In an atmospheric model which has a parametrised calculation of gustiness, the gust wind speed may be separately diagnosed from the wind speed. + + + + Pa m-1 + + + "component_derivative_of_X" means the derivative of X with respect to distance in the component direction, which may be northward, southward, eastward, westward, x or y. The last two indicate derivatives along the axes of the grid, whether or not they are true longitude and latitude. y_derivative_of_ocean_rigid_lid_pressure means (d/dy) of the ocean surface pressure, as derived by a rigid lid approximation, keeping the other horizontal coordinate (x, presumably) constant. + + + + W m-2 + + + "y" indicates a vector component along the grid y-axis, positive with increasing y. The specification of a physical process by the phrase due_to_process means that the quantity named is a single term in a sum of terms which together compose the general quantity named by omitting the phrase. In accordance with common usage in geophysical disciplines, "flux" implies per unit area, called "flux density" in physics. + + + + m s-1 + + + "y" indicates a vector component along the grid y-axis, positive with increasing y. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) + + + + m s-1 + + + "y" indicates a vector component along the grid y-axis, positive with increasing y. Wind is defined as a two-dimensional (horizontal) air velocity vector, with no vertical component. (Vertical motion in the atmosphere has the standard name upward_air_velocity.) A gust is a sudden brief period of high wind speed. In an observed time series of wind speed, the gust wind speed can be indicated by a cell_methods of maximum for the time-interval. In an atmospheric model which has a parametrised calculation of gustiness, the gust wind speed may be separately diagnosed from the wind speed. + + + + degree + + + Zenith angle is the angle to the local vertical; a value of zero is directly overhead. + + + + + isotropic_longwave_radiance_in_air + + + + isotropic_shortwave_radiance_in_air + + + + lagrangian_tendency_of_atmosphere_sigma_coordinate + + + + lagrangian_tendency_of_atmosphere_sigma_coordinate + + + + mole_fraction_of_ozone_in_air + + + + product_of_northward_wind_and_specific_humidity + + + + radiation_wavelength + + + + specific_gravitational_potential_energy + + + + surface_drag_coefficient_for_heat_in_air + + + + surface_drag_coefficient_for_momentum_in_air + + + + surface_drag_coefficient_in_air + + + + sea_surface_swell_wave_period + + + + sea_surface_wind_wave_period + + + + volume_fraction_of_condensed_water_in_soil + + + + volume_fraction_of_condensed_water_in_soil_at_critical_point + + + + volume_fraction_of_condensed_water_in_soil_at_field_capacity + + + + volume_fraction_of_condensed_water_in_soil_at_wilting_point + + + + mass_fraction_of_convective_cloud_condensed_water_in_air + + + + mass_fraction_of_ozone_in_air + + + + wave_frequency + + + + northward_eliassen_palm_flux_in_air + + + + northward_heat_flux_in_air_due_to_eddy_advection + + + + upward_eliassen_palm_flux_in_air + + + + upward_eastward_momentum_flux_in_air_due_to_nonorographic_eastward_gravity_waves + + + + upward_eastward_momentum_flux_in_air_due_to_nonorographic_westward_gravity_waves + + + + upward_eastward_momentum_flux_in_air_due_to_orographic_gravity_waves + + + + water_flux_into_sea_water + + + + wind_mixing_energy_flux_into_sea_water + + + + mole_fraction_of_chlorine_dioxide_in_air + + + + mole_fraction_of_chlorine_monoxide_in_air + + + + mole_fraction_of_dichlorine_peroxide_in_air + + + + mole_fraction_of_hypochlorous_acid_in_air + + + + surface_net_downward_radiative_flux + + + + surface_snow_thickness + + + + surface_temperature + + + + surface_temperature + + + + surface_temperature + + + + surface_upward_sensible_heat_flux + + + + atmosphere_moles_of_carbon_monoxide + + + + atmosphere_moles_of_carbon_tetrachloride + + + + atmosphere_moles_of_cfc11 + + + + atmosphere_moles_of_cfc113 + + + + atmosphere_moles_of_cfc114 + + + + atmosphere_moles_of_cfc115 + + + + atmosphere_moles_of_cfc12 + + + + atmosphere_moles_of_halon1202 + + + + atmosphere_moles_of_halon1211 + + + + atmosphere_moles_of_halon1301 + + + + atmosphere_moles_of_halon2402 + + + + atmosphere_moles_of_hcc140a + + + + atmosphere_moles_of_hcfc22 + + + + atmosphere_moles_of_methane + + + + atmosphere_moles_of_methyl_bromide + + + + atmosphere_moles_of_methyl_chloride + + + + atmosphere_moles_of_molecular_hydrogen + + + + atmosphere_moles_of_nitrous_oxide + + + + mass_concentration_of_suspended_matter_in_sea_water + + + + mole_concentration_of_diatoms_expressed_as_nitrogen_in_sea_water + + + + mole_concentration_of_mesozooplankton_expressed_as_nitrogen_in_sea_water + + + + mole_concentration_of_microzooplankton_expressed_as_nitrogen_in_sea_water + + + + mole_concentration_of_organic_detritus_expressed_as_nitrogen_in_sea_water + + + + mole_concentration_of_organic_detritus_expressed_as_silicon_in_sea_water + + + + mole_concentration_of_phytoplankton_expressed_as_nitrogen_in_sea_water + + + + mole_fraction_of_inorganic_bromine_in_air + + + + mole_fraction_of_noy_expressed_as_nitrogen_in_air + + + + tendency_of_atmosphere_moles_of_carbon_monoxide + + + + tendency_of_atmosphere_moles_of_carbon_tetrachloride + + + + tendency_of_atmosphere_moles_of_cfc11 + + + + tendency_of_atmosphere_moles_of_cfc113 + + + + tendency_of_atmosphere_moles_of_cfc114 + + + + tendency_of_atmosphere_moles_of_cfc115 + + + + tendency_of_atmosphere_moles_of_cfc12 + + + + tendency_of_atmosphere_moles_of_halon1202 + + + + tendency_of_atmosphere_moles_of_halon1211 + + + + tendency_of_atmosphere_moles_of_halon1301 + + + + tendency_of_atmosphere_moles_of_halon2402 + + + + tendency_of_atmosphere_moles_of_hcc140a + + + + tendency_of_atmosphere_moles_of_hcfc22 + + + + tendency_of_atmosphere_moles_of_methane + + + + tendency_of_atmosphere_moles_of_methyl_bromide + + + + tendency_of_atmosphere_moles_of_methyl_chloride + + + + tendency_of_atmosphere_moles_of_molecular_hydrogen + + + + tendency_of_atmosphere_moles_of_nitrous_oxide + + + + tendency_of_middle_atmosphere_moles_of_carbon_monoxide + + + + tendency_of_middle_atmosphere_moles_of_hcc140a + + + + tendency_of_middle_atmosphere_moles_of_methane + + + + tendency_of_middle_atmosphere_moles_of_methyl_bromide + + + + tendency_of_middle_atmosphere_moles_of_methyl_chloride + + + + tendency_of_middle_atmosphere_moles_of_molecular_hydrogen + + + + tendency_of_troposphere_moles_of_carbon_monoxide + + + + tendency_of_troposphere_moles_of_hcc140a + + + + tendency_of_troposphere_moles_of_hcfc22 + + + + tendency_of_troposphere_moles_of_methane + + + + tendency_of_troposphere_moles_of_methyl_bromide + + + + tendency_of_troposphere_moles_of_methyl_chloride + + + + tendency_of_troposphere_moles_of_molecular_hydrogen + + + + atmosphere_net_upward_convective_mass_flux + + + + moles_of_cfc11_per_unit_mass_in_sea_water + + + + tendency_of_mass_fraction_of_stratiform_cloud_ice_in_air_due_to_melting_to_cloud_liquid_water + + + + tendency_of_mass_fraction_of_stratiform_cloud_ice_in_air_due_to_riming_from_cloud_liquid_water + + + + tendency_of_mass_fraction_of_stratiform_cloud_ice_in_air_due_to_heterogeneous_nucleation_from_cloud_liquid_water + + + + eastward_water_vapor_flux_in_air + + + + kinetic_energy_dissipation_in_atmosphere_boundary_layer + + + + liquid_water_content_of_surface_snow + + + + lwe_stratiform_snowfall_rate + + + + lwe_thickness_of_stratiform_snowfall_amount + + + + northward_water_vapor_flux_in_air + + + + soot_content_of_surface_snow + + + + stratiform_cloud_area_fraction + + + + stratiform_rainfall_amount + + + + stratiform_rainfall_flux + + + + stratiform_rainfall_rate + + + + stratiform_snowfall_amount + + + + stratiform_snowfall_flux + + + + temperature_in_surface_snow + + + + thermal_energy_content_of_surface_snow + + + + thickness_of_stratiform_rainfall_amount + + + + thickness_of_stratiform_snowfall_amount + + + + water_vapor_partial_pressure_in_air + + + + water_vapor_saturation_deficit_in_air + + + + atmosphere_mass_content_of_cloud_condensed_water + + + + atmosphere_mass_content_of_cloud_ice + + + + atmosphere_mass_content_of_cloud_liquid_water + + + + atmosphere_mass_content_of_convective_cloud_condensed_water + + + + atmosphere_mass_content_of_convective_cloud_liquid_water + + + + atmosphere_mass_content_of_water_vapor + + + + surface_downward_mole_flux_of_carbon_dioxide + + + + surface_upward_mole_flux_of_carbon_dioxide + + + + atmosphere_mass_content_of_sulfate + + + + atmosphere_mass_content_of_sulfate + + + + change_over_time_in_atmosphere_mass_content_of_water_due_to_advection + + + + change_over_time_in_atmosphere_mass_content_of_water_due_to_advection + + + + lwe_thickness_of_atmosphere_mass_content_of_water_vapor + + + + mass_content_of_cloud_condensed_water_in_atmosphere_layer + + + + mass_content_of_cloud_ice_in_atmosphere_layer + + + + mass_content_of_cloud_liquid_water_in_atmosphere_layer + + + + mass_content_of_water_in_atmosphere_layer + + + + mass_content_of_water_vapor_in_atmosphere_layer + + + + tendency_of_atmosphere_mass_content_of_water_due_to_advection + + + + tendency_of_atmosphere_mass_content_of_water_vapor + + + + tendency_of_atmosphere_mass_content_of_water_vapor_due_to_convection + + + + tendency_of_atmosphere_mass_content_of_water_vapor_due_to_deep_convection + + + + tendency_of_atmosphere_mass_content_of_water_vapor_due_to_shallow_convection + + + + tendency_of_atmosphere_mass_content_of_water_vapor_due_to_turbulence + + + + tendency_of_mass_content_of_water_vapor_in_atmosphere_layer + + + + tendency_of_mass_content_of_water_vapor_in_atmosphere_layer_due_to_convection + + + + tendency_of_mass_content_of_water_vapor_in_atmosphere_layer_due_to_deep_convection + + + + tendency_of_mass_content_of_water_vapor_in_atmosphere_layer_due_to_shallow_convection + + + + tendency_of_mass_content_of_water_vapor_in_atmosphere_layer_due_to_turbulence + + + + equivalent_thickness_at_stp_of_atmosphere_ozone_content + + + + sea_water_x_velocity + + + + sea_water_y_velocity + + + + x_wind + + + + y_wind + + + + tendency_of_atmosphere_mass_content_of_water_vapor_due_to_advection + + + + land_ice_surface_specific_mass_balance_rate + + + + land_ice_lwe_surface_specific_mass_balance_rate + + + + isotropic_radiance_per_unit_wavelength_in_air + + + + isotropic_radiance_per_unit_wavelength_in_air + + + + omnidirectional_spherical_irradiance_per_unit_wavelength_in_sea_water + + + + mass_concentration_of_chlorophyll_in_sea_water + + + + mass_concentration_of_chlorophyll_in_sea_water + + + + atmosphere_convective_available_potential_energy + + + + atmosphere_convective_available_potential_energy + + + + net_primary_mole_productivity_of_biomass_expressed_as_carbon_by_diatoms + + + + gross_primary_productivity_of_biomass_expressed_as_carbon + + + + net_primary_mole_productivity_of_biomass_expressed_as_carbon_by_calcareous_phytoplankton + + + + net_primary_mole_productivity_of_biomass_expressed_as_carbon_by_miscellaneous_phytoplankton + + + + net_primary_mole_productivity_of_biomass_expressed_as_carbon_by_diazotrophs + + + + net_primary_mole_productivity_of_biomass_expressed_as_carbon_by_phytoplankton + + + + net_primary_mole_productivity_of_biomass_expressed_as_carbon_due_to_nitrate_utilization + + + + net_primary_productivity_of_biomass_expressed_as_carbon + + + + net_primary_productivity_of_biomass_expressed_as_carbon_accumulated_in_leaves + + + + net_primary_productivity_of_biomass_expressed_as_carbon_accumulated_in_roots + + + + net_primary_productivity_of_biomass_expressed_as_carbon_accumulated_in_wood + + + + net_primary_mole_productivity_of_biomass_expressed_as_carbon_by_picophytoplankton + + + + atmosphere_mass_content_of_particulate_organic_matter_dry_aerosol_particles + + + + atmosphere_mass_content_of_primary_particulate_organic_matter_dry_aerosol_particles + + + + mass_fraction_of_particulate_organic_matter_dry_aerosol_particles_in_air + + + + mass_fraction_of_primary_particulate_organic_matter_dry_aerosol_particles_in_air + + + + tendency_of_atmosphere_mass_content_of_particulate_organic_matter_dry_aerosol_particles_due_to_dry_deposition + + + + tendency_of_atmosphere_mass_content_of_particulate_organic_matter_dry_aerosol_particles_due_to_gravitational_settling + + + + tendency_of_atmosphere_mass_content_of_particulate_organic_matter_dry_aerosol_particles_due_to_turbulent_deposition + + + + tendency_of_atmosphere_mass_content_of_particulate_organic_matter_dry_aerosol_particles_due_to_wet_deposition + + + + tendency_of_atmosphere_mass_content_of_primary_particulate_organic_matter_dry_aerosol_particles_due_to_dry_deposition + + + + tendency_of_atmosphere_mass_content_of_primary_particulate_organic_matter_dry_aerosol_particles_due_to_wet_deposition + + + + atmosphere_absorption_optical_thickness_due_to_ambient_aerosol_particles + + + + angstrom_exponent_of_ambient_aerosol_in_air + + + + atmosphere_absorption_optical_thickness_due_to_dust_ambient_aerosol_particles + + + + atmosphere_absorption_optical_thickness_due_to_particulate_organic_matter_ambient_aerosol_particles + + + + atmosphere_absorption_optical_thickness_due_to_sulfate_ambient_aerosol_particles + + + + atmosphere_mass_content_of_ammonium_dry_aerosol_particles + + + + atmosphere_mass_content_of_dust_dry_aerosol_particles + + + + atmosphere_mass_content_of_mercury_dry_aerosol_particles + + + + atmosphere_mass_content_of_nitrate_dry_aerosol_particles + + + + atmosphere_mass_content_of_nitric_acid_trihydrate_ambient_aerosol_particles + + + + atmosphere_mass_content_of_secondary_particulate_organic_matter_dry_aerosol_particles + + + + atmosphere_mass_content_of_sulfate_ambient_aerosol_particles + + + + atmosphere_mass_content_of_sulfate_ambient_aerosol_particles + + + + atmosphere_mass_content_of_sulfate_dry_aerosol_particles + + + + atmosphere_mass_content_of_water_in_ambient_aerosol_particles + + + + atmosphere_moles_of_nitric_acid_trihydrate_ambient_aerosol_particles + + + + atmosphere_optical_thickness_due_to_ambient_aerosol_particles + + + + atmosphere_optical_thickness_due_to_ambient_aerosol_particles + + + + atmosphere_optical_thickness_due_to_dust_ambient_aerosol_particles + + + + atmosphere_optical_thickness_due_to_dust_dry_aerosol_particles + + + + atmosphere_optical_thickness_due_to_particulate_organic_matter_ambient_aerosol_particles + + + + mass_concentration_of_dust_dry_aerosol_particles_in_air + + + + mass_concentration_of_coarse_mode_ambient_aerosol_particles_in_air + + + + mass_concentration_of_ammonium_dry_aerosol_particles_in_air + + + + atmosphere_mass_content_of_sulfate_dry_aerosol_particles_expressed_as_sulfur + + + + atmosphere_mass_content_of_sulfate_dry_aerosol_particles_expressed_as_sulfur + + + + mass_concentration_of_primary_particulate_organic_matter_dry_aerosol_particles_in_air + + + + mass_concentration_of_particulate_organic_matter_dry_aerosol_particles_in_air + + + + atmosphere_optical_thickness_due_to_water_in_ambient_aerosol_particles + + + + mass_concentration_of_mercury_dry_aerosol_particles_in_air + + + + mass_concentration_of_nitrate_dry_aerosol_particles_in_air + + + + mass_concentration_of_nitric_acid_trihydrate_ambient_aerosol_particles_in_air + + + + mass_concentration_of_secondary_particulate_organic_matter_dry_aerosol_particles_in_air + + + + mass_concentration_of_sulfate_ambient_aerosol_particles_in_air + + + + mass_concentration_of_sulfate_ambient_aerosol_particles_in_air + + + + mass_concentration_of_sulfate_dry_aerosol_particles_in_air + + + + mass_concentration_of_water_in_ambient_aerosol_particles_in_air + + + + mass_fraction_of_ammonium_dry_aerosol_particles_in_air + + + + mass_fraction_of_dust_dry_aerosol_particles_in_air + + + + mass_fraction_of_nitrate_dry_aerosol_particles_in_air + + + + mass_fraction_of_nitric_acid_trihydrate_ambient_aerosol_particles_in_air + + + + mass_fraction_of_secondary_particulate_organic_matter_dry_aerosol_particles_in_air + + + + mass_fraction_of_sulfate_dry_aerosol_particles_in_air + + + + mass_fraction_of_water_in_ambient_aerosol_particles_in_air + + + + mole_concentration_of_nitric_acid_trihydrate_ambient_aerosol_particles_in_air + + + + mole_fraction_of_nitric_acid_trihydrate_ambient_aerosol_particles_in_air + + + + number_concentration_of_ambient_aerosol_particles_in_air + + + + number_concentration_of_coarse_mode_ambient_aerosol_particles_in_air + + + + number_concentration_of_nucleation_mode_ambient_aerosol_particles_in_air + + + + optical_thickness_of_atmosphere_layer_due_to_ambient_aerosol_particles + + + + optical_thickness_of_atmosphere_layer_due_to_ambient_aerosol_particles + + + + tendency_of_atmosphere_mass_content_of_ammonium_dry_aerosol_particles_due_to_dry_deposition + + + + tendency_of_atmosphere_mass_content_of_ammonium_dry_aerosol_particles_due_to_wet_deposition + + + + tendency_of_atmosphere_mass_content_of_dust_dry_aerosol_particles_due_to_dry_deposition + + + + tendency_of_atmosphere_mass_content_of_dust_dry_aerosol_particles_due_to_gravitational_settling + + + + tendency_of_atmosphere_mass_content_of_dust_dry_aerosol_particles_due_to_turbulent_deposition + + + + tendency_of_atmosphere_mass_content_of_dust_dry_aerosol_particles_due_to_wet_deposition + + + + tendency_of_atmosphere_mass_content_of_mercury_dry_aerosol_particles_due_to_dry_deposition + + + + tendency_of_atmosphere_mass_content_of_mercury_dry_aerosol_particles_due_to_wet_deposition + + + + tendency_of_atmosphere_mass_content_of_nitrate_dry_aerosol_particles_due_to_dry_deposition + + + + tendency_of_atmosphere_mass_content_of_secondary_particulate_organic_matter_dry_aerosol_particles_due_to_dry_deposition + + + + tendency_of_atmosphere_mass_content_of_secondary_particulate_organic_matter_dry_aerosol_particles_due_to_net_chemical_production + + + + tendency_of_atmosphere_mass_content_of_secondary_particulate_organic_matter_dry_aerosol_particles_due_to_net_chemical_production + + + + tendency_of_atmosphere_mass_content_of_secondary_particulate_organic_matter_dry_aerosol_particles_due_to_wet_deposition + + + + tendency_of_atmosphere_mass_content_of_sulfate_dry_aerosol_particles_due_to_dry_deposition + + + + tendency_of_atmosphere_mass_content_of_sulfate_dry_aerosol_particles_expressed_as_sulfur_due_to_dry_deposition + + + + tendency_of_atmosphere_mass_content_of_sulfate_dry_aerosol_particles_expressed_as_sulfur_due_to_dry_deposition + + + + tendency_of_atmosphere_mass_content_of_sulfate_dry_aerosol_particles_expressed_as_sulfur_due_to_gravitational_settling + + + + tendency_of_atmosphere_mass_content_of_sulfate_dry_aerosol_particles_expressed_as_sulfur_due_to_gravitational_settling + + + + tendency_of_atmosphere_mass_content_of_sulfate_dry_aerosol_particles_expressed_as_sulfur_due_to_turbulent_deposition + + + + tendency_of_atmosphere_mass_content_of_sulfate_dry_aerosol_particles_expressed_as_sulfur_due_to_turbulent_deposition + + + + tendency_of_atmosphere_mass_content_of_sulfate_dry_aerosol_expressed_as_sulfur_due_to_wet_deposition + + + + tendency_of_atmosphere_moles_of_nitric_acid_trihydrate_ambient_aerosol_particles + + + + tendency_of_atmosphere_moles_of_sulfate_dry_aerosol_particles + + + + volume_extinction_coefficient_in_air_due_to_ambient_aerosol_particles + + + + tendency_of_atmosphere_mass_content_of_sulfate_dry_aerosol_particles_due_to_emission + + + + tendency_of_atmosphere_mass_content_of_dust_dry_aerosol_particles_due_to_emission + + + + tendency_of_atmosphere_mass_content_of_particulate_organic_matter_dry_aerosol_particles_expressed_as_carbon_due_to_emission_from_residential_and_commercial_combustion + + + + tendency_of_atmosphere_mass_content_of_particulate_organic_matter_dry_aerosol_particles_expressed_as_carbon_due_to_emission_from_waste_treatment_and_disposal + + + + tendency_of_atmosphere_mass_content_of_particulate_organic_matter_dry_aerosol_particles_expressed_as_carbon_due_to_emission_from_savanna_and_grassland_fires + + + + tendency_of_atmosphere_mass_content_of_primary_particulate_organic_matter_dry_aerosol_particles_due_to_emission + + + + tendency_of_atmosphere_mass_content_of_particulate_organic_matter_dry_aerosol_particles_expressed_as_carbon_due_to_emission_from_land_transport + + + + tendency_of_atmosphere_mass_content_of_particulate_organic_matter_dry_aerosol_particles_expressed_as_carbon_due_to_emission_from_agricultural_waste_burning + + + + tendency_of_atmosphere_mass_content_of_particulate_organic_matter_dry_aerosol_particles_expressed_as_carbon_due_to_emission_from_energy_production_and_distribution + + + + tendency_of_atmosphere_mass_content_of_particulate_organic_matter_dry_aerosol_particles_expressed_as_carbon_due_to_emission_from_maritime_transport + + + + tendency_of_atmosphere_mass_content_of_particulate_organic_matter_dry_aerosol_particles_due_to_net_chemical_production_and_emission + + + + tendency_of_atmosphere_mass_content_of_particulate_organic_matter_dry_aerosol_particles_due_to_net_chemical_production_and_emission + - - angstrom_exponent_of_ambient_aerosol_in_air + + tendency_of_atmosphere_mass_content_of_particulate_organic_matter_dry_aerosol_particles_expressed_as_carbon_due_to_emission_from_forest_fires + + + + tendency_of_atmosphere_mass_content_of_particulate_organic_matter_dry_aerosol_particles_expressed_as_carbon_due_to_emission_from_industrial_processes_and_combustion @@ -17288,856 +31177,888 @@ area_type - - atmosphere_mass_content_of_cloud_condensed_water + + sea_surface_swell_wave_significant_height - - atmosphere_mass_content_of_cloud_ice + + sea_surface_wind_wave_significant_height - - atmosphere_mass_content_of_cloud_liquid_water + + sea_surface_wave_significant_height - - atmosphere_mass_content_of_convective_cloud_condensed_water + + rate_of_hydroxyl_radical_destruction_due_to_reaction_with_nmvoc - - atmosphere_mass_content_of_convective_cloud_liquid_water + + mass_content_of_water_in_soil_layer - - atmosphere_mass_content_of_sulfate + + mass_content_of_water_in_soil - - atmosphere_mass_content_of_sulfate + + floating_ice_shelf_area_fraction - - atmosphere_mass_content_of_sulfate_ambient_aerosol + + sea_surface_swell_wave_to_direction - - atmosphere_mass_content_of_sulfate_dry_aerosol_expressed_as_sulfur + + sea_surface_wind_wave_to_direction - - atmosphere_mass_content_of_water_vapor + + sea_surface_wave_mean_period - - atmosphere_moles_of_carbon_monoxide + + sea_surface_wind_wave_mean_period - - atmosphere_moles_of_carbon_tetrachloride + + sea_surface_swell_wave_mean_period - - atmosphere_moles_of_cfc11 + + ocean_mixed_layer_thickness_defined_by_vertical_tracer_diffusivity_deficit - - atmosphere_moles_of_cfc113 + + tendency_of_mole_concentration_of_dissolved_inorganic_phosphorus_in_sea_water_due_to_biological_processes - - atmosphere_moles_of_cfc114 + + tendency_of_mole_concentration_of_dissolved_inorganic_silicon_in_sea_water_due_to_biological_processes - - atmosphere_moles_of_cfc115 + + atmosphere_mass_content_of_sea_salt_dry_aerosol_particles - - atmosphere_moles_of_cfc12 + + atmosphere_mass_content_of_sea_salt_dry_aerosol_particles - - atmosphere_moles_of_halon1202 + + atmosphere_optical_thickness_due_to_sea_salt_ambient_aerosol_particles - - atmosphere_moles_of_halon1211 + + atmosphere_optical_thickness_due_to_sea_salt_ambient_aerosol_particles - - atmosphere_moles_of_halon1301 + + mass_concentration_of_sea_salt_dry_aerosol_particles_in_air - - atmosphere_moles_of_halon2402 + + mass_concentration_of_sea_salt_dry_aerosol_particles_in_air - - atmosphere_moles_of_hcc140a + + mass_fraction_of_sea_salt_dry_aerosol_particles_in_air - - atmosphere_moles_of_hcfc22 + + mass_fraction_of_sea_salt_dry_aerosol_particles_in_air - - atmosphere_moles_of_methane + + tendency_of_atmosphere_mass_content_of_pm10_sea_salt_dry_aerosol_particles_due_to_dry_deposition - - atmosphere_moles_of_methyl_bromide + + tendency_of_atmosphere_mass_content_of_pm10_sea_salt_dry_aerosol_particles_due_to_emission - - atmosphere_moles_of_methyl_chloride + + tendency_of_atmosphere_mass_content_of_pm10_sea_salt_dry_aerosol_particles_due_to_wet_deposition - - atmosphere_moles_of_molecular_hydrogen + + tendency_of_atmosphere_mass_content_of_pm2p5_sea_salt_dry_aerosol_particles_due_to_wet_deposition - - atmosphere_moles_of_nitrous_oxide + + tendency_of_atmosphere_mass_content_of_sea_salt_dry_aerosol_particles_due_to_dry_deposition - - atmosphere_net_upward_convective_mass_flux + + tendency_of_atmosphere_mass_content_of_sea_salt_dry_aerosol_particles_due_to_dry_deposition - - atmosphere_optical_thickness_due_to_ambient_aerosol + + tendency_of_atmosphere_mass_content_of_sea_salt_dry_aerosol_particles_due_to_gravitational_settling - - atmosphere_specific_convective_available_potential_energy + + tendency_of_atmosphere_mass_content_of_sea_salt_dry_aerosol_particles_due_to_gravitational_settling - - change_over_time_in_atmosphere_mass_content_of_water_due_to_advection + + tendency_of_atmosphere_mass_content_of_sea_salt_dry_aerosol_particles_due_to_turbulent_deposition - - change_over_time_in_atmosphere_mass_content_of_water_due_to_advection + + tendency_of_atmosphere_mass_content_of_sea_salt_dry_aerosol_particles_due_to_turbulent_deposition - - eastward_transformed_eulerian_mean_air_velocity + + tendency_of_atmosphere_mass_content_of_sea_salt_dry_aerosol_particles_due_to_wet_deposition - - eastward_water_vapor_flux_in_air + + tendency_of_atmosphere_mass_content_of_sea_salt_dry_aerosol_particles_due_to_wet_deposition - - equivalent_thickness_at_stp_of_atmosphere_ozone_content + + atmosphere_optical_thickness_due_to_pm1_ambient_aerosol_particles - - isotropic_longwave_radiance_in_air + + mass_concentration_of_pm1_ambient_aerosol_particles_in_air - - isotropic_shortwave_radiance_in_air + + mass_fraction_of_pm1_ambient_aerosol_particles_in_air - - isotropic_spectral_radiance_in_air + + mass_fraction_of_pm1_ambient_aerosol_particles_in_air - - kinetic_energy_dissipation_in_atmosphere_boundary_layer + + atmosphere_optical_thickness_due_to_pm2p5_ambient_aerosol_particles - - lagrangian_tendency_of_air_pressure + + mass_concentration_of_pm2p5_ambient_aerosol_particles_in_air - - lagrangian_tendency_of_air_pressure + + mass_fraction_of_pm2p5_ambient_aerosol_particles_in_air - - lagrangian_tendency_of_atmosphere_sigma_coordinate + + mass_fraction_of_pm2p5_ambient_aerosol_particles_in_air - - lagrangian_tendency_of_atmosphere_sigma_coordinate + + atmosphere_optical_thickness_due_to_pm10_ambient_aerosol_particles - - liquid_water_content_of_surface_snow + + mass_concentration_of_pm10_ambient_aerosol_particles_in_air - - lwe_stratiform_precipitation_rate + + mass_fraction_of_pm10_ambient_aerosol_particles_in_air - - lwe_stratiform_snowfall_rate + + mass_fraction_of_pm10_ambient_aerosol_particles_in_air - - lwe_thickness_of_atmosphere_mass_content_of_water_vapor + + tendency_of_atmosphere_mass_content_of_pm2p5_sea_salt_dry_aerosol_particles_due_to_dry_deposition - - lwe_thickness_of_stratiform_precipitation_amount + + tendency_of_atmosphere_mass_content_of_pm2p5_sea_salt_dry_aerosol_particles_due_to_emission - - lwe_thickness_of_stratiform_snowfall_amount + + sea_floor_depth_below_mean_sea_level - - magnitude_of_sea_ice_displacement + + sea_surface_height_above_mean_sea_level - - mass_concentration_of_chlorophyll_in_sea_water + + sea_surface_height_above_mean_sea_level - - mass_concentration_of_chlorophyll_in_sea_water + + surface_geostrophic_eastward_sea_water_velocity_assuming_mean_sea_level_for_geoid - - mass_concentration_of_sulfate_ambient_aerosol_in_air + + surface_geostrophic_eastward_sea_water_velocity_assuming_mean_sea_level_for_geoid - - mass_concentration_of_suspended_matter_in_sea_water + + surface_geostrophic_northward_sea_water_velocity_assuming_mean_sea_level_for_geoid - - mass_content_of_cloud_condensed_water_in_atmosphere_layer + + surface_geostrophic_northward_sea_water_velocity_assuming_mean_sea_level_for_geoid - - mass_content_of_cloud_ice_in_atmosphere_layer + + surface_geostrophic_sea_water_x_velocity_assuming_mean_sea_level_for_geoid - - mass_content_of_cloud_liquid_water_in_atmosphere_layer + + surface_geostrophic_sea_water_y_velocity_assuming_mean_sea_level_for_geoid - - mass_content_of_water_in_atmosphere_layer + + tendency_of_sea_surface_height_above_mean_sea_level - - mass_content_of_water_vapor_in_atmosphere_layer + + surface_geostrophic_northward_sea_water_velocity - - mass_fraction_of_convective_cloud_condensed_water_in_air + + surface_geostrophic_eastward_sea_water_velocity - - mass_fraction_of_ozone_in_air + + tendency_of_atmosphere_mass_content_of_nitrogen_compounds_expressed_as_nitrogen_due_to_wet_deposition - - mass_fraction_of_pm10_ambient_aerosol_in_air + + tendency_of_atmosphere_mass_content_of_nitrogen_compounds_expressed_as_nitrogen_due_to_dry_deposition - - mass_fraction_of_pm1_ambient_aerosol_in_air + + tendency_of_atmosphere_mass_content_of_nitrogen_compounds_expressed_as_nitrogen_due_to_deposition - - mass_fraction_of_pm2p5_ambient_aerosol_in_air + + atmosphere_absorption_optical_thickness_due_to_sea_salt_ambient_aerosol_particles - - mole_concentration_of_diatoms_expressed_as_nitrogen_in_sea_water + + atmosphere_absorption_optical_thickness_due_to_sea_salt_ambient_aerosol_particles - - mole_concentration_of_mesozooplankton_expressed_as_nitrogen_in_sea_water + + tendency_of_atmosphere_mass_content_of_sea_salt_dry_aerosol_particles_due_to_emission - - mole_concentration_of_microzooplankton_expressed_as_nitrogen_in_sea_water + + tendency_of_atmosphere_mass_content_of_sea_salt_dry_aerosol_particles_due_to_emission - - mole_concentration_of_organic_detritus_expressed_as_nitrogen_in_sea_water + + sea_surface_height_above_geoid - - mole_concentration_of_organic_detritus_expressed_as_silicon_in_sea_water + + sea_surface_height_above_geoid - - mole_concentration_of_phytoplankton_expressed_as_nitrogen_in_sea_water + + sea_floor_depth_below_geoid - - mole_fraction_of_chlorine_dioxide_in_air + + air_pressure_at_mean_sea_level - - mole_fraction_of_chlorine_monoxide_in_air + + lagrangian_tendency_of_air_pressure - - mole_fraction_of_dichlorine_peroxide_in_air + + lagrangian_tendency_of_air_pressure - - mole_fraction_of_hypochlorous_acid_in_air + + mass_concentration_of_elemental_carbon_dry_aerosol_particles_in_air - - mole_fraction_of_inorganic_bromine_in_air + + atmosphere_mass_content_of_elemental_carbon_dry_aerosol_particles - - mole_fraction_of_noy_expressed_as_nitrogen_in_air + + mass_fraction_of_elemental_carbon_dry_aerosol_particles_in_air - - mole_fraction_of_ozone_in_air + + tendency_of_atmosphere_mass_content_of_elemental_carbon_dry_aerosol_particles_due_to_dry_deposition - - moles_of_cfc11_per_unit_mass_in_sea_water + + tendency_of_atmosphere_mass_content_of_elemental_carbon_dry_aerosol_particles_due_to_emission - - northward_eliassen_palm_flux_in_air + + tendency_of_atmosphere_mass_content_of_elemental_carbon_dry_aerosol_particles_due_to_emission_from_agricultural_waste_burning - - northward_heat_flux_in_air_due_to_eddy_advection + + tendency_of_atmosphere_mass_content_of_elemental_carbon_dry_aerosol_particles_due_to_emission_from_energy_production_and_distribution - - northward_transformed_eulerian_mean_air_velocity + + tendency_of_atmosphere_mass_content_of_elemental_carbon_dry_aerosol_particles_due_to_emission_from_forest_fires - - northward_water_vapor_flux_in_air + + tendency_of_atmosphere_mass_content_of_elemental_carbon_dry_aerosol_particles_due_to_emission_from_industrial_processes_and_combustion - - optical_thickness_of_atmosphere_layer_due_to_ambient_aerosol + + tendency_of_atmosphere_mass_content_of_elemental_carbon_dry_aerosol_particles_due_to_emission_from_land_transport - - precipitation_flux_onto_canopy + + tendency_of_atmosphere_mass_content_of_elemental_carbon_dry_aerosol_particles_due_to_emission_from_maritime_transport - - product_of_northward_wind_and_specific_humidity + + tendency_of_atmosphere_mass_content_of_elemental_carbon_dry_aerosol_particles_due_to_emission_from_residential_and_commercial_combustion - - radiation_wavelength + + tendency_of_atmosphere_mass_content_of_elemental_carbon_dry_aerosol_particles_due_to_emission_from_savanna_and_grassland_fires - - sea_floor_depth_below_geoid + + tendency_of_atmosphere_mass_content_of_elemental_carbon_dry_aerosol_particles_due_to_emission_from_waste_treatment_and_disposal - - sea_surface_height_above_geoid + + tendency_of_atmosphere_mass_content_of_elemental_carbon_dry_aerosol_particles_due_to_gravitational_settling - - sea_surface_height_above_geoid + + tendency_of_atmosphere_mass_content_of_elemental_carbon_dry_aerosol_particles_due_to_turbulent_deposition - - sea_surface_height_above_sea_level + + tendency_of_atmosphere_mass_content_of_elemental_carbon_dry_aerosol_particles_due_to_wet_deposition - - sea_surface_swell_wave_period + + tendency_of_mass_concentration_of_elemental_carbon_dry_aerosol_particles_in_air_due_to_emission_from_aviation - - sea_surface_swell_wave_significant_height + + sea_water_to_direction - - sea_surface_swell_wave_to_direction + + integral_wrt_time_of_air_temperature_deficit - - sea_surface_wave_significant_height + + integral_wrt_time_of_air_temperature_excess - - sea_surface_wind_wave_period + + integral_wrt_time_of_surface_downward_eastward_stress - - sea_surface_wind_wave_significant_height + + integral_wrt_time_of_surface_downward_northward_stress - - sea_surface_wind_wave_to_direction + + integral_wrt_time_of_surface_downward_latent_heat_flux - - sea_water_x_velocity + + integral_wrt_time_of_surface_downward_sensible_heat_flux - - sea_water_y_velocity + + integral_wrt_time_of_surface_net_downward_longwave_flux - - soot_content_of_surface_snow + + integral_wrt_time_of_surface_net_downward_shortwave_flux - - specific_gravitational_potential_energy + + integral_wrt_time_of_toa_net_downward_shortwave_flux + + + + integral_wrt_time_of_toa_outgoing_longwave_flux + + + + northward_ocean_freshwater_transport_due_to_parameterized_eddy_advection + + + + northward_ocean_salt_transport_due_to_parameterized_eddy_advection + + + + ocean_heat_x_transport_due_to_parameterized_eddy_advection + + + + ocean_heat_y_transport_due_to_parameterized_eddy_advection + + + + ocean_mass_x_transport_due_to_advection_and_parameterized_eddy_advection + + + + ocean_mass_y_transport_due_to_advection_and_parameterized_eddy_advection + + + + ocean_meridional_overturning_mass_streamfunction_due_to_parameterized_eddy_advection - - stratiform_cloud_area_fraction + + ocean_y_overturning_mass_streamfunction_due_to_parameterized_eddy_advection - - stratiform_graupel_flux + + tendency_of_sea_water_salinity_due_to_parameterized_eddy_advection - - stratiform_precipitation_amount + + tendency_of_sea_water_temperature_due_to_parameterized_eddy_advection - - stratiform_precipitation_flux + + northward_sea_water_velocity_due_to_parameterized_mesoscale_eddies - - stratiform_rainfall_amount + + eastward_sea_water_velocity_due_to_parameterized_mesoscale_eddies - - stratiform_rainfall_flux + + sea_water_x_velocity_due_to_parameterized_mesoscale_eddies - - stratiform_rainfall_rate + + sea_water_y_velocity_due_to_parameterized_mesoscale_eddies - - stratiform_snowfall_amount + + upward_sea_water_velocity_due_to_parameterized_mesoscale_eddies - - stratiform_snowfall_flux + + ocean_tracer_biharmonic_diffusivity_due_to_parameterized_mesoscale_eddy_advection - - surface_downward_mole_flux_of_carbon_dioxide + + ocean_tracer_laplacian_diffusivity_due_to_parameterized_mesoscale_eddy_advection - - surface_downwelling_longwave_flux_in_air + + tendency_of_ocean_eddy_kinetic_energy_content_due_to_parameterized_eddy_advection - - surface_downwelling_shortwave_flux_in_air + + northward_ocean_heat_transport_due_to_parameterized_eddy_advection - - surface_downwelling_shortwave_flux_in_air_assuming_clear_sky + + mole_concentration_of_dissolved_inorganic_13C_in_sea_water - - surface_drag_coefficient_for_heat_in_air + + surface_downward_mass_flux_of_13C_dioxide_abiotic_analogue_expressed_as_13C - - surface_drag_coefficient_for_momentum_in_air + + surface_downward_mass_flux_of_14C_dioxide_abiotic_analogue_expressed_as_carbon - - surface_drag_coefficient_in_air + + mole_concentration_of_dissolved_inorganic_14C_in_sea_water - - surface_geostrophic_eastward_sea_water_velocity + + stem_mass_content_of_carbon - - surface_geostrophic_eastward_sea_water_velocity_assuming_sea_level_for_geoid + + subsurface_litter_mass_content_of_carbon - - surface_geostrophic_northward_sea_water_velocity + + mass_flux_of_carbon_into_litter_from_vegetation - - surface_geostrophic_northward_sea_water_velocity_assuming_sea_level_for_geoid + + litter_mass_content_of_carbon - - surface_net_downward_radiative_flux + + surface_litter_mass_content_of_carbon - - surface_snow_thickness + + eastward_transformed_eulerian_mean_air_velocity - - surface_temperature + + northward_transformed_eulerian_mean_air_velocity - - surface_temperature + + surface_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_heterotrophic_respiration - - surface_temperature + + surface_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_respiration_in_soil - - surface_upward_mole_flux_of_carbon_dioxide + + surface_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_plant_respiration - - surface_upward_sensible_heat_flux + + surface_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_plant_respiration_for_biomass_growth - - surface_upwelling_longwave_flux_in_air + + surface_upward_mass_flux_of_carbon_dioxide_expressed_as_carbon_due_to_plant_respiration_for_biomass_maintenance - - surface_upwelling_longwave_flux_in_air_assuming_clear_sky + + carbon_mass_content_of_forestry_and_agricultural_products - - surface_upwelling_shortwave_flux_in_air + + carbon_mass_content_of_forestry_and_agricultural_products - - surface_upwelling_shortwave_flux_in_air_assuming_clear_sky + + leaf_mass_content_of_carbon - - temperature_in_surface_snow + + medium_soil_pool_mass_content_of_carbon - - tendency_of_air_temperature_due_to_stratiform_precipitation + + fast_soil_pool_mass_content_of_carbon - - tendency_of_atmosphere_mass_content_of_particulate_organic_matter_dry_aerosol_due_to_net_chemical_production_and_emission + + miscellaneous_living_matter_mass_content_of_carbon - - tendency_of_atmosphere_mass_content_of_secondary_particulate_organic_matter_dry_aerosol_due_to_net_chemical_production + + root_mass_content_of_carbon - - tendency_of_atmosphere_mass_content_of_sulfate_dry_aerosol_expressed_as_sulfur_due_to_dry_deposition + + slow_soil_pool_mass_content_of_carbon - - tendency_of_atmosphere_mass_content_of_sulfate_dry_aerosol_expressed_as_sulfur_due_to_gravitational_settling + + soil_mass_content_of_carbon - - tendency_of_atmosphere_mass_content_of_sulfate_dry_aerosol_expressed_as_sulfur_due_to_turbulent_deposition + + tendency_of_atmosphere_mole_concentration_of_carbon_monoxide_due_to_chemical_destruction - - tendency_of_atmosphere_mass_content_of_sulfate_dry_aerosol_expressed_as_sulfur_due_to_wet_deposition + + volume_scattering_coefficient_of_radiative_flux_in_air_due_to_dried_aerosol_particles - - tendency_of_atmosphere_mass_content_of_water_due_to_advection + + volume_scattering_coefficient_of_radiative_flux_in_air_due_to_ambient_aerosol_particles - - tendency_of_atmosphere_mass_content_of_water_vapor + + integral_wrt_depth_of_sea_water_practical_salinity - - tendency_of_atmosphere_mass_content_of_water_vapor_due_to_convection + + integral_wrt_depth_of_sea_water_temperature - - tendency_of_atmosphere_mass_content_of_water_vapor_due_to_deep_convection + + integral_wrt_depth_of_sea_water_temperature - - tendency_of_atmosphere_mass_content_of_water_vapor_due_to_shallow_convection + + integral_wrt_depth_of_sea_water_temperature - - tendency_of_atmosphere_mass_content_of_water_vapor_due_to_turbulence + + integral_wrt_depth_of_sea_water_temperature - - tendency_of_atmosphere_moles_of_carbon_monoxide + + integral_wrt_height_of_product_of_eastward_wind_and_specific_humidity - - tendency_of_atmosphere_moles_of_carbon_tetrachloride + + integral_wrt_height_of_product_of_northward_wind_and_specific_humidity - - tendency_of_atmosphere_moles_of_cfc11 + + water_flux_into_sea_water_from_rivers - - tendency_of_atmosphere_moles_of_cfc113 + + toa_outgoing_shortwave_flux_assuming_clear_sky_and_no_aerosol - - tendency_of_atmosphere_moles_of_cfc114 + + wood_debris_mass_content_of_carbon - - tendency_of_atmosphere_moles_of_cfc115 + + stratiform_graupel_flux - - tendency_of_atmosphere_moles_of_cfc12 + + water_volume_transport_into_sea_water_from_rivers - - tendency_of_atmosphere_moles_of_halon1202 + + surface_water_evaporation_flux - - tendency_of_atmosphere_moles_of_halon1211 + + water_evapotranspiration_flux - - tendency_of_atmosphere_moles_of_halon1301 + + sea_ice_temperature_expressed_as_heat_content - - tendency_of_atmosphere_moles_of_halon2402 + + sea_ice_temperature_expressed_as_heat_content - - tendency_of_atmosphere_moles_of_hcc140a + + sea_water_potential_temperature_expressed_as_heat_content - - tendency_of_atmosphere_moles_of_hcfc22 + + sea_water_potential_temperature_expressed_as_heat_content - - tendency_of_atmosphere_moles_of_methane + + incoming_water_volume_transport_along_river_channel - - tendency_of_atmosphere_moles_of_methyl_bromide + + surface_upwelling_longwave_flux_in_air - - tendency_of_atmosphere_moles_of_methyl_chloride + + surface_upwelling_radiance_per_unit_wavelength_in_air - - tendency_of_atmosphere_moles_of_molecular_hydrogen + + surface_upwelling_radiance_per_unit_wavelength_in_air_emerging_from_sea_water - - tendency_of_atmosphere_moles_of_nitrous_oxide + + surface_upwelling_radiance_per_unit_wavelength_in_air_reflected_by_sea_water - - tendency_of_mass_content_of_water_vapor_in_atmosphere_layer + + surface_upwelling_radiance_per_unit_wavelength_in_sea_water - - tendency_of_mass_content_of_water_vapor_in_atmosphere_layer_due_to_convection + + surface_upwelling_radiative_flux_per_unit_wavelength_in_air - - tendency_of_mass_content_of_water_vapor_in_atmosphere_layer_due_to_deep_convection + + surface_upwelling_radiative_flux_per_unit_wavelength_in_sea_water - - tendency_of_mass_content_of_water_vapor_in_atmosphere_layer_due_to_shallow_convection + + surface_upwelling_shortwave_flux_in_air - - tendency_of_mass_content_of_water_vapor_in_atmosphere_layer_due_to_turbulence + + surface_upwelling_shortwave_flux_in_air_assuming_clear_sky_and_no_aerosol - - tendency_of_mass_fraction_of_stratiform_cloud_ice_in_air_due_to_heterogeneous_nucleation_from_cloud_liquid_water + + upwelling_radiance_per_unit_wavelength_in_air - - tendency_of_mass_fraction_of_stratiform_cloud_ice_in_air_due_to_melting_to_cloud_liquid_water + + upwelling_radiative_flux_per_unit_wavelength_in_air - - tendency_of_mass_fraction_of_stratiform_cloud_ice_in_air_due_to_riming_from_cloud_liquid_water + + upwelling_radiative_flux_per_unit_wavelength_in_sea_water - - tendency_of_middle_atmosphere_moles_of_carbon_monoxide + + upwelling_shortwave_flux_in_air_assuming_clear_sky_and_no_aerosol - - tendency_of_middle_atmosphere_moles_of_hcc140a + + surface_upwelling_longwave_flux_in_air_assuming_clear_sky - - tendency_of_middle_atmosphere_moles_of_methane + + surface_upwelling_shortwave_flux_in_air_assuming_clear_sky - - tendency_of_middle_atmosphere_moles_of_methyl_bromide + + downwelling_photon_flux_per_unit_wavelength_in_sea_water - - tendency_of_middle_atmosphere_moles_of_methyl_chloride + + downwelling_photon_radiance_per_unit_wavelength_in_sea_water - - tendency_of_middle_atmosphere_moles_of_molecular_hydrogen + + downwelling_photon_spherical_irradiance_per_unit_wavelength_in_sea_water - - tendency_of_mole_concentration_of_dissolved_inorganic_phosphorus_in_sea_water_due_to_biological_processes + + downwelling_radiance_per_unit_wavelength_in_air - - tendency_of_mole_concentration_of_dissolved_inorganic_silicon_in_sea_water_due_to_biological_processes + + downwelling_radiance_per_unit_wavelength_in_sea_water - - tendency_of_specific_humidity_due_to_stratiform_precipitation + + downwelling_radiative_flux_per_unit_wavelength_in_air - - tendency_of_troposphere_moles_of_carbon_monoxide + + downwelling_radiative_flux_per_unit_wavelength_in_sea_water - - tendency_of_troposphere_moles_of_hcc140a + + downwelling_shortwave_flux_in_air_assuming_clear_sky_and_no_aerosol - - tendency_of_troposphere_moles_of_hcfc22 + + downwelling_spherical_irradiance_per_unit_wavelength_in_sea_water - - tendency_of_troposphere_moles_of_methane + + integral_wrt_time_of_surface_downwelling_longwave_flux_in_air - - tendency_of_troposphere_moles_of_methyl_bromide + + integral_wrt_time_of_surface_downwelling_shortwave_flux_in_air - - tendency_of_troposphere_moles_of_methyl_chloride + + surface_downwelling_longwave_flux_in_air - - tendency_of_troposphere_moles_of_molecular_hydrogen + + surface_downwelling_photon_flux_per_unit_wavelength_in_sea_water - - thermal_energy_content_of_surface_snow + + surface_downwelling_photon_radiance_per_unit_wavelength_in_sea_water - - thickness_of_stratiform_rainfall_amount + + surface_downwelling_photon_spherical_irradiance_per_unit_wavelength_in_sea_water - - thickness_of_stratiform_snowfall_amount + + surface_downwelling_radiance_per_unit_wavelength_in_sea_water - - upward_eastward_momentum_flux_in_air_due_to_nonorographic_eastward_gravity_waves + + surface_downwelling_radiative_flux_per_unit_wavelength_in_air - - upward_eastward_momentum_flux_in_air_due_to_nonorographic_westward_gravity_waves + + surface_downwelling_radiative_flux_per_unit_wavelength_in_sea_water - - upward_eastward_momentum_flux_in_air_due_to_orographic_gravity_waves + + surface_downwelling_shortwave_flux_in_air - - upward_eliassen_palm_flux_in_air + + surface_downwelling_shortwave_flux_in_air_assuming_clear_sky - - volume_fraction_of_condensed_water_in_soil + + surface_downwelling_shortwave_flux_in_air_assuming_clear_sky_and_no_aerosol - - volume_fraction_of_condensed_water_in_soil_at_critical_point + + surface_downwelling_spherical_irradiance_per_unit_wavelength_in_sea_water - - volume_fraction_of_condensed_water_in_soil_at_field_capacity + + magnitude_of_sea_ice_displacement - - volume_fraction_of_condensed_water_in_soil_at_wilting_point + + tendency_of_sea_ice_amount_due_to_conversion_of_snow_to_sea_ice - - water_evaporation_amount_from_canopy + + outgoing_water_volume_transport_along_river_channel - - water_evaporation_flux + + precipitation_flux_onto_canopy water_evaporation_flux_from_canopy - - water_flux_into_sea_water + + tendency_of_atmosphere_mass_content_of_water_vapor_due_to_sublimation_of_surface_snow_and_ice - - water_flux_into_sea_water_from_rivers + + water_evaporation_amount_from_canopy - - water_vapor_partial_pressure_in_air + + lwe_stratiform_precipitation_rate - - water_vapor_saturation_deficit_in_air + + lwe_thickness_of_stratiform_precipitation_amount - - water_volume_transport_into_sea_water_from_rivers + + stratiform_precipitation_amount - - wave_frequency + + stratiform_precipitation_flux - - wind_mixing_energy_flux_into_sea_water + + tendency_of_air_temperature_due_to_stratiform_precipitation - - x_wind + + tendency_of_specific_humidity_due_to_stratiform_precipitation - - y_wind + + platform_id - - tendency_of_atmosphere_mass_content_of_water_vapor_due_to_advection + + platform_name diff --git a/lib/iris/__init__.py b/lib/iris/__init__.py index 411e593754..29a175f31d 100644 --- a/lib/iris/__init__.py +++ b/lib/iris/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -57,9 +57,12 @@ * constraints: Either a single constraint, or an iterable of constraints. - Each constraint can be either a CF standard name, an instance of + Each constraint can be either a string, an instance of :class:`iris.Constraint`, or an instance of - :class:`iris.AttributeConstraint`. + :class:`iris.AttributeConstraint`. If the constraint is a string + it will be used to match against cube.name(). + + .. _constraint_egs: For example:: @@ -91,37 +94,40 @@ def callback(cube, field, filename): experiment_id, long_name='experiment_id') cube.add_aux_coord(experiment_coord) -Format-specific translation behaviour can be modified by using: - :func:`iris.fileformats.pp.add_load_rules` +""" - :func:`iris.fileformats.grib.add_load_rules` +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six -""" import contextlib +import glob import itertools -import logging -import os +import os.path import threading import iris.config import iris.cube import iris._constraints +from iris._deprecation import IrisDeprecation, warn_deprecated import iris.fileformats import iris.io +try: + import iris_sample_data +except ImportError: + iris_sample_data = None + + # Iris revision. -__version__ = '1.7.0-dev' +__version__ = '2.3.0dev0' # Restrict the names imported when using "from iris import *" __all__ = ['load', 'load_cube', 'load_cubes', 'load_raw', 'save', 'Constraint', 'AttributeConstraint', 'sample_data_path', - 'site_configuration', 'Future', 'FUTURE'] - - -# When required, log the usage of Iris. -if iris.config.IMPORT_LOGGER: - logging.getLogger(iris.config.IMPORT_LOGGER).info('iris %s' % __version__) + 'site_configuration', 'Future', 'FUTURE', + 'IrisDeprecation'] Constraint = iris._constraints.Constraint @@ -131,41 +137,104 @@ def callback(cube, field, filename): class Future(threading.local): """Run-time configuration controller.""" - def __init__(self, cell_datetime_objects=False): + def __init__(self, cell_datetime_objects=True, netcdf_promote=True, + netcdf_no_unlimited=True, clip_latitudes=True): """ A container for run-time options controls. To adjust the values simply update the relevant attribute from within your code. For example:: - iris.FUTURE.cell_datetime_objects = True + iris.FUTURE.cell_datetime_objects = False If Iris code is executed with multiple threads, note the values of these options are thread-specific. - Currently, the only option available is `cell_datetime_objects` which - controls whether the :meth:`iris.coords.Coord.cell()` method returns - time coordinate values as simple numbers or as time objects with - attributes for year, month, day, etc. In particular, this allows one - to express certain time constraints using a simpler, more - transparent syntax, such as:: + .. deprecated:: 2.0.0 + + The option `cell_datetime_objects` is deprecated and will be + removed in a future release. `cell_datetime_objects` is set + to True by default and should not be altered. + + The option `cell_datetime_objects` controlled whether the + :meth:`iris.coords.Coord.cell()` method would return time + coordinate values as simple numbers or as time objects with + attributes for year, month, day, etc. + + Cells are now represented as time objects by default, allowing + you to express time constraints using a simpler syntax. For + example:: + + # To select all data defined at midday. + Constraint(time=lambda cell: cell.point.hour == 12) + + # To ignore the 29th of February. + Constraint(time=lambda cell: cell.point.day != 29 and + cell.point.month != 2) + + For more details, see :ref:`using-time-constraints`. + + .. deprecated:: 2.0.0 + + The option `netcdf_promote` is deprecated and will be removed in a + future release and the deprecated code paths this option used to + toggle have been removed. - # To select all data defined at midday. - Constraint(time=lambda cell: cell.point.hour == 12) + The option `netcdf_promote` controlled whether the netCDF loader + exposed variables that defined reference surfaces for + dimensionless vertical coordinates as independent Cubes. - # To ignore the 29th of February. - Constraint(time=lambda cell: cell.point.day != 29 and - cell.point.month != 2) + .. deprecated:: 2.0.0 + + The option `netcdf_no_unlimited` is deprecated and will be removed + in a future release. The deprecated code paths this option used to + toggle have been removed. + + The option `netcdf_no_unlimited` changed the behaviour of the + netCDF saver regarding unlimited dimensions. The netCDF saver now + sets no dimensions to unlimited. + + .. deprecated:: 2.0.0 + + The option `clip_latitudes` is deprecated and will be removed in a + future release. `clip_latitudes` is set to True by default and + should not be altered. + + The option `clip_latitudes` controlled whether the + :meth:`iris.coords.Coord.guess_bounds()` method would limit the + guessed bounds to [-90, 90] for latitudes. - For more details, see :ref:`using-time-constraints`. """ self.__dict__['cell_datetime_objects'] = cell_datetime_objects + self.__dict__['netcdf_promote'] = netcdf_promote + self.__dict__['netcdf_no_unlimited'] = netcdf_no_unlimited + self.__dict__['clip_latitudes'] = clip_latitudes def __repr__(self): - return 'Future(cell_datetime_objects={})'.format( - self.cell_datetime_objects) + msg = ('Future(cell_datetime_objects={}, netcdf_promote={}, ' + 'netcdf_no_unlimited={}, clip_latitudes={})') + return msg.format(self.cell_datetime_objects, self.netcdf_promote, + self.netcdf_no_unlimited, self.clip_latitudes) + + deprecated_options = {'cell_datetime_objects': 'warning', + 'netcdf_no_unlimited': 'error', + 'netcdf_promote': 'error', + 'clip_latitudes': 'warning'} def __setattr__(self, name, value): + if name in self.deprecated_options: + level = self.deprecated_options[name] + if level == 'error' and not value: + emsg = ("setting the 'Future' property {prop!r} has been " + "deprecated to be removed in a future release, and " + "deprecated {prop!r} behaviour has been removed. " + "Please remove code that sets this property.") + raise AttributeError(emsg.format(prop=name)) + else: + msg = ("setting the 'Future' property {!r} is deprecated " + "and will be removed in a future release. " + "Please remove code that sets this property.") + warn_deprecated(msg.format(name)) if name not in self.__dict__: msg = "'Future' object has no attribute {!r}".format(name) raise AttributeError(msg) @@ -182,21 +251,14 @@ def context(self, **kwargs): statement, the previous state is restored. For example:: - - with iris.FUTURE.context(): - iris.FUTURE.cell_datetime_objects = True - # ... code which expects time objects - - Or more concisely:: - - with iris.FUTURE.context(cell_datetime_objects=True): - # ... code which expects time objects + with iris.FUTURE.context(cell_datetime_objects=False): + # ... code that expects numbers and not datetimes """ # Save the current context current_state = self.__dict__.copy() # Update the state - for name, value in kwargs.iteritems(): + for name, value in six.iteritems(kwargs): setattr(self, name, value) try: yield @@ -222,9 +284,9 @@ def context(self, **kwargs): _update(site_configuration) -def _generate_cubes(uris, callback): +def _generate_cubes(uris, callback, constraints): """Returns a generator of cubes given the URIs and a callback.""" - if isinstance(uris, basestring): + if isinstance(uris, six.string_types): uris = [uris] # Group collections of uris by their iris handler @@ -235,7 +297,7 @@ def _generate_cubes(uris, callback): # Call each scheme handler with the appropriate URIs if scheme == 'file': part_names = [x[1] for x in groups] - for cube in iris.io.load_files(part_names, callback): + for cube in iris.io.load_files(part_names, callback, constraints): yield cube elif scheme in ['http', 'https']: urls = [':'.join(x) for x in groups] @@ -247,11 +309,11 @@ def _generate_cubes(uris, callback): def _load_collection(uris, constraints=None, callback=None): try: - cubes = _generate_cubes(uris, callback) + cubes = _generate_cubes(uris, callback, constraints) result = iris.cube._CubeFilterCollection.from_cubes(cubes, constraints) except EOFError as e: raise iris.exceptions.TranslationError( - "The file appears empty or incomplete: {!r}".format(e.message)) + "The file appears empty or incomplete: {!r}".format(str(e))) return result @@ -308,12 +370,17 @@ def load_cube(uris, constraint=None, callback=None): if len(constraints) != 1: raise ValueError('only a single constraint is allowed') - cubes = _load_collection(uris, constraints, callback).merged().cubes() + cubes = _load_collection(uris, constraints, callback) + cubes = cubes.merged().cubes() - if len(cubes) != 1: - msg = 'Expected exactly one cube, found {}.'.format(len(cubes)) - raise iris.exceptions.ConstraintMismatchError(msg) - return cubes[0] + try: + cube = cubes.merge_cube() + except iris.exceptions.MergeError as e: + raise iris.exceptions.ConstraintMismatchError(str(e)) + except ValueError: + raise iris.exceptions.ConstraintMismatchError('no cubes found') + + return cube def load_cubes(uris, constraints=None, callback=None): @@ -343,7 +410,7 @@ def load_cubes(uris, constraints=None, callback=None): collection = _load_collection(uris, constraints, callback).merged() # Make sure we have exactly one merged cube per constraint - bad_pairs = filter(lambda pair: len(pair) != 1, collection.pairs) + bad_pairs = [pair for pair in collection.pairs if len(pair) != 1] if bad_pairs: fmt = ' {} -> {} cubes' bits = [fmt.format(pair.constraint, len(pair)) for pair in bad_pairs] @@ -382,12 +449,39 @@ def load_raw(uris, constraints=None, callback=None): An :class:`iris.cube.CubeList`. """ - return _load_collection(uris, constraints, callback).cubes() + from iris.fileformats.um._fast_load import _raw_structured_loading + with _raw_structured_loading(): + return _load_collection(uris, constraints, callback).cubes() save = iris.io.save def sample_data_path(*path_to_join): - """Given the sample data resource, returns the full path to the file.""" - return os.path.join(iris.config.SAMPLE_DATA_DIR, *path_to_join) + """ + Given the sample data resource, returns the full path to the file. + + .. note:: + + This function is only for locating files in the iris sample data + collection (installed separately from iris). It is not needed or + appropriate for general file access. + + """ + target = os.path.join(*path_to_join) + if os.path.isabs(target): + raise ValueError('Absolute paths, such as {!r}, are not supported.\n' + 'NB. This function is only for locating files in the ' + 'iris sample data collection. It is not needed or ' + 'appropriate for general file access.'.format(target)) + if iris_sample_data is not None: + target = os.path.join(iris_sample_data.path, target) + else: + raise ImportError("Please install the 'iris-sample-data' package to " + "access sample data.") + if not glob.glob(target): + raise ValueError('Sample data file(s) at {!r} not found.\n' + 'NB. This function is only for locating files in the ' + 'iris sample data collection. It is not needed or ' + 'appropriate for general file access.'.format(target)) + return target diff --git a/lib/iris/_concatenate.py b/lib/iris/_concatenate.py index 868db1edb9..9f37fd24b2 100644 --- a/lib/iris/_concatenate.py +++ b/lib/iris/_concatenate.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -17,19 +17,17 @@ """ Automatic concatenation of multiple cubes over one or more existing dimensions. -.. warning:: - - Currently, the :func:`concatenate` routine will load the data payload - of all cubes passed to it. - - This restriction will be relaxed in a future release. - """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + from collections import defaultdict, namedtuple +from copy import deepcopy +import dask.array as da import numpy as np -import numpy.ma as ma import iris.coords import iris.cube @@ -39,18 +37,8 @@ # # TODO: # -# * Deal with scalar coordinate promotion to a new dimension -# e.g. promote scalar z coordinate in 2D cube (y:m, x:n) to -# give the similar 3D cube (z:1, y:m, x:n). These two types -# of cubes are one and the same, and as such should concatenate -# together. -# # * Cope with auxiliary coordinate factories. # -# * Don't load the cube data payload. -# -# * Deal with anonymous dimensions. -# # * Allow concatentation over a user specified dimension. # @@ -81,6 +69,8 @@ class _CoordAndDims(namedtuple('CoordAndDims', """ + __slots__ = () + class _CoordMetaData(namedtuple('CoordMetaData', ['defn', 'dims', 'points_dtype', @@ -129,6 +119,8 @@ def __new__(cls, coord, dims): bounds_dtype = coord.bounds.dtype if coord.bounds is not None \ else None kwargs = {} + # Add scalar flag metadata. + kwargs['scalar'] = coord.points.size == 1 # Add circular flag metadata for dimensional coordinates. if hasattr(coord, 'circular'): kwargs['circular'] = coord.circular @@ -147,6 +139,42 @@ def __new__(cls, coord, dims): kwargs) return metadata + __slots__ = () + + def __hash__(self): + return super(_CoordMetaData, self).__hash__() + + def __eq__(self, other): + result = NotImplemented + if isinstance(other, _CoordMetaData): + sprops, oprops = self._asdict(), other._asdict() + # Ignore "kwargs" meta-data for the first comparison. + sprops['kwargs'] = oprops['kwargs'] = None + result = sprops == oprops + if result: + skwargs, okwargs = self.kwargs.copy(), other.kwargs.copy() + # Monotonic "order" only applies to DimCoord's. + # The monotonic "order" must be _INCREASING or _DECREASING if + # the DimCoord is NOT "scalar". Otherwise, if the DimCoord is + # "scalar" then the "order" must be _CONSTANT. + if skwargs['scalar'] or okwargs['scalar']: + # We don't care about the monotonic "order" given that + # at least one coordinate is a scalar coordinate. + skwargs['scalar'] = okwargs['scalar'] = None + skwargs['order'] = okwargs['order'] = None + result = skwargs == okwargs + return result + + def __ne__(self, other): + result = self.__eq__(other) + if result is not NotImplemented: + result = not result + return result + + def name(self): + """Get the name from the coordinate definition.""" + return self.defn.name() + class _SkeletonCube(namedtuple('SkeletonCube', ['signature', 'data'])): @@ -164,6 +192,8 @@ class _SkeletonCube(namedtuple('SkeletonCube', """ + __slots__ = () + class _Extent(namedtuple('Extent', ['min', 'max'])): @@ -180,6 +210,8 @@ class _Extent(namedtuple('Extent', """ + __slots__ = () + class _CoordExtent(namedtuple('CoordExtent', ['points', 'bounds'])): @@ -199,8 +231,10 @@ class _CoordExtent(namedtuple('CoordExtent', """ + __slots__ = () -def concatenate(cubes): + +def concatenate(cubes, error_on_mismatch=False, check_aux_coords=True): """ Concatenate the provided cubes over common existing dimensions. @@ -210,14 +244,16 @@ def concatenate(cubes): An iterable containing one or more :class:`iris.cube.Cube` instances to be concatenated together. + Kwargs: + + * error_on_mismatch: + If True, raise an informative + :class:`~iris.exceptions.ContatenateError` if registration fails. + Returns: A :class:`iris.cube.CubeList` of concatenated :class:`iris.cube.Cube` instances. - .. warning:: - - This routine will load your data payload! - """ proto_cubes_by_name = defaultdict(list) # Initialise the nominated axis (dimension) of concatenation @@ -226,17 +262,14 @@ def concatenate(cubes): # Register each cube with its appropriate proto-cube. for cube in cubes: - # TODO: Remove this when new deferred data mechanism is available. - # Avoid deferred data/data manager issues, and load the cube data! - cube.data - name = cube.standard_name or cube.long_name proto_cubes = proto_cubes_by_name[name] registered = False # Register cube with an existing proto-cube. for proto_cube in proto_cubes: - registered = proto_cube.register(cube, axis) + registered = proto_cube.register(cube, axis, error_on_mismatch, + check_aux_coords) if registered: axis = proto_cube.axis break @@ -248,7 +281,11 @@ def concatenate(cubes): # Construct a concatenated cube from each of the proto-cubes. concatenated_cubes = iris.cube.CubeList() - for name in sorted(proto_cubes_by_name): + # Emulate Python 2 behaviour. + def _none_sort(item): + return (item is not None, item) + + for name in sorted(proto_cubes_by_name, key=_none_sort): for proto_cube in proto_cubes_by_name[name]: # Construct the concatenated cube. concatenated_cubes.append(proto_cube.concatenate()) @@ -264,7 +301,7 @@ def concatenate(cubes): class _CubeSignature(object): """ Template for identifying a specific type of :class:`iris.cube.Cube` based - on its metadata and coordinates. + on its metadata, coordinates and cell_measures. """ def __init__(self, cube): @@ -282,38 +319,38 @@ def __init__(self, cube): self.aux_metadata = [] self.dim_coords = cube.dim_coords self.dim_metadata = [] - self.mdi = None self.ndim = cube.ndim self.scalar_coords = [] + self.cell_measures_and_dims = cube._cell_measures_and_dims + self.dim_mapping = [] # Determine whether there are any anonymous cube dimensions. covered = set(cube.coord_dims(coord)[0] for coord in self.dim_coords) self.anonymous = covered != set(range(self.ndim)) self.defn = cube.metadata - self.data_type = cube.data.dtype - - if ma.isMaskedArray(cube.data): - # Only set when we're dealing with a masked payload. - self.mdi = cube.data.fill_value + self.data_type = cube.dtype # # Collate the dimension coordinate metadata. # - for coord in self.dim_coords: - metadata = _CoordMetaData(coord, cube.coord_dims(coord)) + for ind, coord in enumerate(self.dim_coords): + dims = cube.coord_dims(coord) + metadata = _CoordMetaData(coord, dims) self.dim_metadata.append(metadata) + self.dim_mapping.append(dims[0]) # # Collate the auxiliary coordinate metadata and scalar coordinates. # axes = dict(T=0, Z=1, Y=2, X=3) + # Coordinate sort function - by guessed coordinate axis, then # by coordinate definition, then by dimensions, in ascending order. - key_func = lambda coord: (axes.get(guess_coord_axis(coord), - len(axes) + 1), - coord._as_defn(), - cube.coord_dims(coord)) + def key_func(coord): + return (axes.get(guess_coord_axis(coord), len(axes) + 1), + coord._as_defn(), + cube.coord_dims(coord)) for coord in sorted(cube.aux_coords, key=key_func): dims = cube.coord_dims(coord) @@ -325,30 +362,120 @@ def __init__(self, cube): else: self.scalar_coords.append(coord) - def __eq__(self, other): - result = NotImplemented + def _coordinate_differences(self, other, attr): + """ + Determine the names of the coordinates that differ between `self` and + `other` for a coordinate attribute on a _CubeSignature. - if isinstance(other, _CubeSignature): - # Only concatenate with fully described cubes. - if self.anonymous or other.anonymous: - result = False - else: - result = self.aux_metadata == other.aux_metadata and \ - self.data_type == other.data_type and \ - self.defn == other.defn and \ - self.dim_metadata == other.dim_metadata and \ - self.mdi == other.mdi and \ - self.ndim == other.ndim and \ - self.scalar_coords == other.scalar_coords + Args: - return result + * other (_CubeSignature): + The _CubeSignature to compare against. - def __ne__(self, other): - result = self.__eq__(other) - if result is not NotImplemented: - result = not result + * attr (string): + The _CubeSignature attribute within which differences exist + between `self` and `other`. + + Returns: + Tuple of a descriptive error message and the names of coordinates + that differ between `self` and `other`. + + """ + # Set up {name: coord_metadata} dictionaries. + self_dict = {x.name(): x for x in getattr(self, attr)} + other_dict = {x.name(): x for x in getattr(other, attr)} + if len(self_dict) == 0: + self_dict = {'< None >': None} + if len(other_dict) == 0: + other_dict = {'< None >': None} + self_names = sorted(self_dict.keys()) + other_names = sorted(other_dict.keys()) + + # Compare coord metadata. + if len(self_names) != len(other_names) or self_names != other_names: + result = ('', ', '.join(self_names), ', '.join(other_names)) + else: + diff_names = [] + for self_key, self_value in six.iteritems(self_dict): + other_value = other_dict[self_key] + if self_value != other_value: + diff_names.append(self_key) + result = (' metadata', + ', '.join(diff_names), + ', '.join(diff_names)) return result + def match(self, other, error_on_mismatch): + """ + Return whether this _CubeSignature equals another. + + This is the first step to determine if two "cubes" (either a + real Cube or a ProtoCube) can be concatenated, by considering: + - data dimensions + - dimensions metadata + - aux coords metadata + - scalar coords + - attributes + - dtype + + Args: + + * other (_CubeSignature): + The _CubeSignature to compare against. + + * error_on_mismatch (bool): + If True, raise a :class:`~iris.exceptions.MergeException` + with a detailed explanation if the two do not match. + + Returns: + Boolean. True if and only if this _CubeSignature matches the other. + + """ + msg_template = '{}{} differ: {} != {}' + msgs = [] + + # Check cube definitions. + if self.defn != other.defn: + # Note that the case of different phenomenon names is dealt + # with in :meth:`iris.cube.CubeList.concatenate_cube()`. + msg = 'Cube metadata differs for phenomenon: {}' + msgs.append(msg.format(self.defn.name())) + + # Check dim coordinates. + if self.dim_metadata != other.dim_metadata: + differences = self._coordinate_differences(other, 'dim_metadata') + msgs.append(msg_template.format('Dimension coordinates', + *differences)) + # Check aux coordinates. + if self.aux_metadata != other.aux_metadata: + differences = self._coordinate_differences(other, 'aux_metadata') + msgs.append(msg_template.format('Auxiliary coordinates', + *differences)) + # Check scalar coordinates. + if self.scalar_coords != other.scalar_coords: + differences = self._coordinate_differences(other, 'scalar_coords') + msgs.append(msg_template.format('Scalar coordinates', + *differences)) + # Check ndim. + if self.ndim != other.ndim: + msgs.append(msg_template.format('Data dimensions', '', + self.ndim, other.ndim)) + # Check data type. + if self.data_type != other.data_type: + msgs.append(msg_template.format('Data types', '', + self.data_type, other.data_type)) + + # Check _cell_measures_and_dims + if self.cell_measures_and_dims != other.cell_measures_and_dims: + msgs.append(msg_template.format('CellMeasures', '', + self.cell_measures_and_dims, + other.cell_measures_and_dims)) + + match = not bool(msgs) + if error_on_mismatch and not match: + raise iris.exceptions.ConcatenateError(msgs) + return match + class _CoordSignature(object): """ @@ -370,6 +497,7 @@ def __init__(self, cube_signature): """ self.aux_coords_and_dims = cube_signature.aux_coords_and_dims self.dim_coords = cube_signature.dim_coords + self.dim_mapping = cube_signature.dim_mapping self.dim_extents = [] self.dim_order = [metadata.kwargs['order'] for metadata in cube_signature.dim_metadata] @@ -425,12 +553,12 @@ def candidate_axis(self, other): candidate_axes = [] # Compare dimension coordinates. - for dim, coord in enumerate(self.dim_coords): - result, candidate_axis = self._cmp(coord, - other.dim_coords[dim]) + for ind, coord in enumerate(self.dim_coords): + result, candidate_axis = self._cmp(coord, other.dim_coords[ind]) if not result: break if candidate_axis: + dim = self.dim_mapping[ind] candidate_axes.append(dim) # Only permit one degree of dimensional freedom when @@ -498,7 +626,7 @@ def __init__(self, cube): # The list of source-cubes relevant to this proto-cube. self._skeletons = [] - self._add_skeleton(self._coord_signature, cube.data) + self._add_skeleton(self._coord_signature, cube.lazy_data()) # The nominated axis of concatenation. self._axis = None @@ -520,13 +648,13 @@ def concatenate(self): """ if len(self._skeletons) > 1: skeletons = self._skeletons - order = self._coord_signature.dim_order[self.axis] + dim_ind = self._coord_signature.dim_mapping.index(self.axis) + order = self._coord_signature.dim_order[dim_ind] cube_signature = self._cube_signature # Sequence the skeleton segments into the correct order # pending concatenation. - key_func = lambda skeleton: skeleton.signature.dim_extents - skeletons.sort(key=key_func, + skeletons.sort(key=lambda skeleton: skeleton.signature.dim_extents, reverse=(order == _DECREASING)) # Concatenate the new dimension coordinate. @@ -540,9 +668,12 @@ def concatenate(self): # Build the new cube. kwargs = cube_signature.defn._asdict() + new_cm_and_dims = [(deepcopy(cm), dims) for cm, dims + in self._cube._cell_measures_and_dims] cube = iris.cube.Cube(data, dim_coords_and_dims=dim_coords_and_dims, aux_coords_and_dims=aux_coords_and_dims, + cell_measures_and_dims=new_cm_and_dims, **kwargs) else: # There are no other source-cubes to concatenate @@ -551,7 +682,8 @@ def concatenate(self): return cube - def register(self, cube, axis=None): + def register(self, cube, axis=None, error_on_mismatch=False, + check_aux_coords=False): """ Determine whether the given source-cube is suitable for concatenation with this :class:`_ProtoCube`. @@ -568,6 +700,9 @@ def register(self, cube, axis=None): Seed the dimension of concatenation for the :class:`_ProtoCube` rather than rely on negotiation with source-cubes. + * error_on_mismatch: + If True, raise an informative error if registration fails. + Returns: Boolean. @@ -580,7 +715,7 @@ def register(self, cube, axis=None): # Check for compatible cube signatures. cube_signature = _CubeSignature(cube) - match = self._cube_signature == cube_signature + match = self._cube_signature.match(cube_signature, error_on_mismatch) # Check for compatible coordinate signatures. if match: @@ -592,15 +727,40 @@ def register(self, cube, axis=None): # Check for compatible coordinate extents. if match: - match = self._sequence(coord_signature.dim_extents[candidate_axis], + dim_ind = self._coord_signature.dim_mapping.index(candidate_axis) + match = self._sequence(coord_signature.dim_extents[dim_ind], candidate_axis) + # Check for compatible AuxCoords. + if match: + if check_aux_coords: + for coord_a, coord_b in zip( + self._cube_signature.aux_coords_and_dims, + cube_signature.aux_coords_and_dims): + # AuxCoords that span the candidate axis can difffer + if (candidate_axis not in coord_a.dims or + candidate_axis not in coord_b.dims): + if not coord_a == coord_b: + match = False + if match: # Register the cube as a source-cube for this proto-cube. - self._add_skeleton(coord_signature, cube.data) + self._add_skeleton(coord_signature, cube.lazy_data()) # Declare the nominated axis of concatenation. self._axis = candidate_axis + if match: + # If the protocube dimension order is constant (indicating it was + # created from a cube with a length 1 dimension coordinate) but + # a subsequently registered cube has a non-constant dimension + # order we should use that instead of _CONSTANT to make sure all + # the ordering checks and sorts work as expected. + dim_ind = self._coord_signature.dim_mapping.index(candidate_axis) + existing_order = self._coord_signature.dim_order[dim_ind] + this_order = coord_signature.dim_order[dim_ind] + if existing_order == _CONSTANT and this_order != _CONSTANT: + self._coord_signature.dim_order[dim_ind] = this_order + return match def _add_skeleton(self, coord_signature, data): @@ -690,11 +850,7 @@ def _build_data(self): skeletons = self._skeletons data = [skeleton.data for skeleton in skeletons] - if self._cube_signature.mdi is not None: - # Preserve masked entries. - data = ma.concatenate(tuple(data), axis=self.axis) - else: - data = np.concatenate(tuple(data), axis=self.axis) + data = da.concatenate(data, self.axis) return data @@ -710,18 +866,19 @@ def _build_dim_coordinates(self): # Setup convenience hooks. skeletons = self._skeletons axis = self.axis - defn = self._cube_signature.dim_metadata[axis].defn - circular = self._cube_signature.dim_metadata[axis].kwargs['circular'] + dim_ind = self._cube_signature.dim_mapping.index(axis) + metadata = self._cube_signature.dim_metadata[dim_ind] + defn, circular = metadata.defn, metadata.kwargs['circular'] # Concatenate the points together for the nominated dimension. - points = [skeleton.signature.dim_coords[axis].points + points = [skeleton.signature.dim_coords[dim_ind].points for skeleton in skeletons] points = np.concatenate(tuple(points)) # Concatenate the bounds together for the nominated dimension. bounds = None - if self._cube_signature.dim_coords[axis].has_bounds(): - bounds = [skeleton.signature.dim_coords[axis].bounds + if self._cube_signature.dim_coords[dim_ind].has_bounds(): + bounds = [skeleton.signature.dim_coords[dim_ind].bounds for skeleton in skeletons] bounds = np.concatenate(tuple(bounds)) @@ -733,7 +890,8 @@ def _build_dim_coordinates(self): # Generate all the dimension coordinates for the new concatenated cube. dim_coords_and_dims = [] - for dim, coord in enumerate(self._cube_signature.dim_coords): + for ind, coord in enumerate(self._cube_signature.dim_coords): + dim = self._cube_signature.dim_mapping[ind] if dim == axis: dim_coords_and_dims.append((dim_coord, dim)) else: @@ -763,12 +921,13 @@ def _sequence(self, extent, axis): result = True # Add the new extent to the current extents collection. - dim_extents = [skeleton.signature.dim_extents[axis] + dim_ind = self._coord_signature.dim_mapping.index(axis) + dim_extents = [skeleton.signature.dim_extents[dim_ind] for skeleton in self._skeletons] dim_extents.append(extent) # Sort into the appropriate dimension order. - order = self._coord_signature.dim_order[axis] + order = self._coord_signature.dim_order[dim_ind] dim_extents.sort(reverse=(order == _DECREASING)) # Ensure that the extents don't overlap. @@ -776,31 +935,31 @@ def _sequence(self, extent, axis): for i, extent in enumerate(dim_extents[1:]): # Check the points - must be strictly monotonic. if order == _DECREASING: - left = dim_extents[i].points.min - right = extent.points.max + big = dim_extents[i].points.min + small = extent.points.max else: - left = dim_extents[i].points.max - right = extent.points.min + small = dim_extents[i].points.max + big = extent.points.min - if left >= right: + if small >= big: result = False break # Check the bounds - must be strictly monotonic. if extent.bounds is not None: if order == _DECREASING: - left_0 = dim_extents[i].bounds[0].min - left_1 = dim_extents[1].bounds[1].min - right_0 = extent.bounds[0].max - right_1 = extent.bounds[1].max + big_0 = dim_extents[i].bounds[0].min + big_1 = dim_extents[i].bounds[1].min + small_0 = extent.bounds[0].max + small_1 = extent.bounds[1].max else: - left_0 = dim_extents[i].bounds[0].max - left_1 = dim_extents[i].bounds[1].max - right_0 = extent.bounds[0].min - right_1 = extent.bounds[1].min + small_0 = dim_extents[i].bounds[0].max + small_1 = dim_extents[i].bounds[1].max + big_0 = extent.bounds[0].min + big_1 = extent.bounds[1].min - lower_bound_fail = left_0 >= right_0 - upper_bound_fail = left_1 >= right_1 + lower_bound_fail = small_0 >= big_0 + upper_bound_fail = small_1 >= big_1 if lower_bound_fail or upper_bound_fail: result = False diff --git a/lib/iris/_constraints.py b/lib/iris/_constraints.py index dd7dffac64..3b212bf6f2 100644 --- a/lib/iris/_constraints.py +++ b/lib/iris/_constraints.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -18,9 +18,13 @@ Provides objects for building up expressions useful for pattern matching. """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + import collections import operator -import warnings import numpy as np @@ -88,7 +92,7 @@ def __init__(self, name=None, cube_func=None, coord_values=None, **kwargs): :class:`iris.coords.Cell`. """ - if not (name is None or isinstance(name, basestring)): + if not (name is None or isinstance(name, six.string_types)): raise TypeError('name must be None or string, got %r' % name) if not (cube_func is None or callable(cube_func)): raise TypeError('cube_func must be None or callable, got %r' @@ -99,7 +103,7 @@ def __init__(self, name=None, cube_func=None, coord_values=None, **kwargs): 'collections.Mapping, got %r' % coord_values) coord_values = coord_values or {} - duplicate_keys = coord_values.viewkeys() & kwargs.viewkeys() + duplicate_keys = set(coord_values.keys()) & set(kwargs.keys()) if duplicate_keys: raise ValueError('Duplicate coordinate conditions specified for: ' '%s' % list(duplicate_keys)) @@ -159,7 +163,10 @@ def extract(self, cube): def _CIM_extract(self, cube): # Returns _ColumnIndexManager - resultant_CIM = _ColumnIndexManager(len(cube.shape)) + + # Cater for scalar cubes by setting the dimensionality to 1 + # when cube.ndim is 0. + resultant_CIM = _ColumnIndexManager(cube.ndim or 1) if not self._coordless_match(cube): resultant_CIM.all_false() @@ -235,7 +242,9 @@ def extract(self, cube): match the constraint. """ - cube_cim = _ColumnIndexManager(len(cube.shape)) + # Cater for scalar cubes by setting the dimensionality to 1 + # when cube.ndim is 0. + cube_cim = _ColumnIndexManager(cube.ndim or 1) try: coord = cube.coord(self.coord_name) except iris.exceptions.CoordinateNotFoundError: @@ -251,10 +260,19 @@ def extract(self, cube): call_func = self._coord_thing elif (isinstance(self._coord_thing, collections.Iterable) and not isinstance(self._coord_thing, - (basestring, iris.coords.Cell))): - call_func = lambda cell: cell in list(self._coord_thing) + (six.string_types, iris.coords.Cell))): + desired_values = list(self._coord_thing) + # A dramatic speedup can be had if we don't have bounds. + if coord.has_bounds(): + def call_func(cell): + return cell in desired_values + else: + def call_func(cell): + return cell.point in desired_values else: - call_func = lambda c: c == self._coord_thing + def call_func(c): + return c == self._coord_thing + try_quick = (isinstance(coord, iris.coords.DimCoord) and not isinstance(self._coord_thing, iris.coords.Cell)) @@ -288,7 +306,7 @@ class _ColumnIndexManager(object): import numpy as np cim = _ColumnIndexManager(4) cim[1] = np.array([3, 4, 5]) > 3 - print cim.as_slice() + print(cim.as_slice()) """ def __init__(self, ndims): @@ -412,7 +430,7 @@ def as_constraint(thing): return thing elif thing is None: return Constraint() - elif isinstance(thing, basestring): + elif isinstance(thing, six.string_types): return Constraint(thing) else: raise TypeError('%r cannot be cast to a constraint.' % thing) @@ -427,7 +445,7 @@ def __init__(self, **attributes): iris.AttributeConstraint(STASH='m01s16i004') iris.AttributeConstraint( - STASH=lambda stash: stash.endswith('i005')) + STASH=lambda stash: str(stash).endswith('i005')) .. note:: Attribute constraint names are case sensitive. @@ -437,7 +455,7 @@ def __init__(self, **attributes): def _cube_func(self, cube): match = True - for name, value in self._attributes.iteritems(): + for name, value in six.iteritems(self._attributes): if name in cube.attributes: cube_attr = cube.attributes.get(name) # if we have a callable, then call it with the value, diff --git a/lib/iris/_cube_coord_common.py b/lib/iris/_cube_coord_common.py index 07a07ab7e6..9eba266ff6 100644 --- a/lib/iris/_cube_coord_common.py +++ b/lib/iris/_cube_coord_common.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -15,13 +15,17 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six # TODO: Is this a mixin or a base class? import string +import cf_units + import iris.std_names -import iris.unit class LimitedAttributeDict(dict): @@ -29,21 +33,21 @@ class LimitedAttributeDict(dict): 'calendar', 'leap_month', 'leap_year', 'month_lengths', 'coordinates', 'grid_mapping', 'climatology', 'cell_methods', 'formula_terms', 'compress', - 'missing_value', 'add_offset', 'scale_factor', - 'valid_max', 'valid_min', 'valid_range', '_FillValue') + 'add_offset', 'scale_factor', + '_FillValue') def __init__(self, *args, **kwargs): dict.__init__(self, *args, **kwargs) # Check validity of keys - for key in self.iterkeys(): + for key in six.iterkeys(self): if key in self._forbidden_keys: raise ValueError('%r is not a permitted attribute' % key) def __eq__(self, other): # Extend equality to allow for NumPy arrays. - match = self.viewkeys() == other.viewkeys() + match = set(self.keys()) == set(other.keys()) if match: - for key, value in self.iteritems(): + for key, value in six.iteritems(self): match = value == other[key] try: match = bool(match) @@ -65,11 +69,11 @@ def update(self, other, **kwargs): # Gather incoming keys keys = [] if hasattr(other, "keys"): - keys += other.keys() + keys += list(other.keys()) else: keys += [k for k, v in other] - keys += kwargs.keys() + keys += list(kwargs.keys()) # Check validity of keys for key in keys: @@ -84,12 +88,13 @@ def name(self, default='unknown'): """ Returns a human-readable name. - First it tries :attr:`standard_name`, then 'long_name', then 'var_name' - before falling back to the value of `default` (which itself defaults to - 'unknown'). + First it tries :attr:`standard_name`, then 'long_name', then + 'var_name', then the STASH attribute before falling back to + the value of `default` (which itself defaults to 'unknown'). """ - return self.standard_name or self.long_name or self.var_name or default + return self.standard_name or self.long_name or self.var_name or \ + str(self.attributes.get('STASH', '')) or default def rename(self, name): """ @@ -105,7 +110,7 @@ def rename(self, name): self.long_name = None except ValueError: self.standard_name = None - self.long_name = unicode(name) + self.long_name = six.text_type(name) # Always clear var_name when renaming. self.var_name = None @@ -124,27 +129,27 @@ def standard_name(self, name): @property def units(self): - """The :mod:`~iris.unit.Unit` instance of the object.""" + """The :mod:`~cf_units.Unit` instance of the object.""" return self._units @units.setter def units(self, unit): - self._units = iris.unit.as_unit(unit) + self._units = cf_units.as_unit(unit) @property def var_name(self): - """The CF variable name for the object.""" + """The netCDF variable name for the object.""" return self._var_name @var_name.setter def var_name(self, name): if name is not None: if not name: - raise ValueError('An empty string is not a valid CF variable ' - 'name.') + raise ValueError('An empty string is not a valid netCDF ' + 'variable name.') elif set(name).intersection(string.whitespace): - raise ValueError('{!r} is not a valid CF variable name because' - ' it contains whitespace.'.format(name)) + raise ValueError('{!r} is not a valid netCDF variable name ' + 'as it contains whitespace.'.format(name)) self._var_name = name @property diff --git a/lib/iris/_data_manager.py b/lib/iris/_data_manager.py new file mode 100644 index 0000000000..8f6e9e4e0c --- /dev/null +++ b/lib/iris/_data_manager.py @@ -0,0 +1,373 @@ +# (C) British Crown Copyright 2010 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Management of common state and behaviour for cube and coordinate data. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +import copy +import numpy as np +import numpy.ma as ma + +from iris._lazy_data import as_concrete_data, as_lazy_data, is_lazy_data +from iris.util import array_equal + + +class DataManager(object): + """ + Provides a well defined API for management of real or lazy data. + + """ + + def __init__(self, data): + """ + Create a data manager for the specified data. + + Args: + + * data: + The :class:`~numpy.ndarray` or :class:`~numpy.ma.core.MaskedArray` + real data, or :class:`~dask.array.core.Array` lazy data to be + managed. + + """ + # Initialise the instance. + self._lazy_array = None + self._real_array = None + + # Assign the data payload to be managed. + self.data = data + + # Enforce the manager contract. + self._assert_axioms() + + def __copy__(self): + """ + Forbid :class:`~iris._data_manager.DataManager` instance + shallow-copy support. + + """ + name = type(self).__name__ + emsg = ('Shallow-copy of {!r} is not permitted. Use ' + 'copy.deepcopy() or {}.copy() instead.') + raise copy.Error(emsg.format(name, name)) + + def __deepcopy__(self, memo): + """ + Allow :class:`~iris._data_manager.DataManager` instance + deepcopy support. + + Args: + + * memo: + :class:`copy` memo dictionary. + + """ + return self._deepcopy(memo) + + def __eq__(self, other): + """ + Perform :class:`~iris._data_manager.DataManager` instance equality. + Note that, this is explicitly not a lazy operation and will load any + lazy payload to determine the equality result. + + Comparison is strict with regards to lazy or real managed payload, + the realised_dtype, the dtype of the payload, the fill-value and the + payload content. + + Args: + + * other: + The :class:`~iris._data_manager.DataManager` instance to + compare with. + + Returns: + Boolean. + + """ + result = NotImplemented + + if isinstance(other, type(self)): + result = False + same_lazy = self.has_lazy_data() == other.has_lazy_data() + same_dtype = self.dtype == other.dtype + if same_lazy and same_dtype: + result = array_equal(self.core_data(), other.core_data()) + + return result + + def __ne__(self, other): + """ + Perform :class:`~iris._data_manager.DataManager` instance inequality. + Note that, this is explicitly not a lazy operation and will load any + lazy payload to determine the inequality result. + + Args: + + * other: + The :class:`~iris._data_manager.DataManager` instance to + compare with. + + Returns: + Boolean. + + """ + result = self.__eq__(other) + + if result is not NotImplemented: + result = not result + + return result + + def __repr__(self): + """ + Returns an string representation of the instance. + + """ + fmt = '{cls}({data!r})' + result = fmt.format(data=self.core_data(), cls=type(self).__name__) + + return result + + def _assert_axioms(self): + """ + Definition of the manager state, that should never be violated. + + """ + # Ensure there is a valid data state. + is_lazy = self._lazy_array is not None + is_real = self._real_array is not None + emsg = 'Unexpected data state, got {}lazy and {}real data.' + state = is_lazy ^ is_real + assert state, emsg.format('' if is_lazy else 'no ', + '' if is_real else 'no ') + + def _deepcopy(self, memo, data=None): + """ + Perform a deepcopy of the :class:`~iris._data_manager.DataManager` + instance. + + Args: + + * memo: + :class:`copy` memo dictionary. + + Kwargs: + + * data: + Replacement data to substitute the currently managed + data with. + + Returns: + :class:`~iris._data_manager.DataManager` instance. + + """ + try: + if data is None: + # Copy the managed data. + if self.has_lazy_data(): + data = copy.deepcopy(self._lazy_array, memo) + else: + data = self._real_array.copy() + else: + # Check that the replacement data is valid relative to + # the currently managed data. + dm_check = DataManager(self.core_data()) + dm_check.data = data + # If the replacement data is valid, then use it but + # without copying it. + result = DataManager(data) + except ValueError as error: + emsg = 'Cannot copy {!r} - {}' + raise ValueError(emsg.format(type(self).__name__, error)) + + return result + + @property + def data(self): + """ + Returns the real data. Any lazy data being managed will be realised. + + Returns: + :class:`~numpy.ndarray` or :class:`numpy.ma.core.MaskedArray`. + + """ + if self.has_lazy_data(): + try: + # Realise the lazy data. + result = as_concrete_data(self._lazy_array) + # Assign the realised result. + self._real_array = result + # Reset the lazy data and the realised dtype. + self._lazy_array = None + except MemoryError: + emsg = ('Failed to realise the lazy data as there was not ' + 'enough memory available.\n' + 'The data shape would have been {!r} with {!r}.\n ' + 'Consider freeing up variables or indexing the data ' + 'before trying again.') + raise MemoryError(emsg.format(self.shape, self.dtype)) + + # Check the manager contract, as the managed data has changed. + self._assert_axioms() + + return self._real_array + + @data.setter + def data(self, data): + """ + Replaces the currently managed data with the specified data, which must + be of an equivalent shape. + + Note that, the only shape promotion permitted is for 0-dimensional + scalar data to be replaced with a single item 1-dimensional data. + + Args: + + * data: + The :class:`~numpy.ndarray` or :class:`~numpy.ma.core.MaskedArray` + real data, or :class:`~dask.array.core.Array` lazy data to be + managed. + + """ + # Ensure we have numpy-like data. + if not (hasattr(data, 'shape') and hasattr(data, 'dtype')): + data = np.asanyarray(data) + + # Determine whether the class instance has been created, + # as this method is called from within the __init__. + init_done = (self._lazy_array is not None or + self._real_array is not None) + + if init_done and self.shape != data.shape: + # The _ONLY_ data reshape permitted is converting a 0-dimensional + # array i.e. self.shape == () into a 1-dimensional array of length + # one i.e. data.shape == (1,) + if self.shape or data.shape != (1,): + emsg = 'Require data with shape {!r}, got {!r}.' + raise ValueError(emsg.format(self.shape, data.shape)) + + # Set lazy or real data, and reset the other. + if is_lazy_data(data): + self._lazy_array = data + self._real_array = None + else: + if not ma.isMaskedArray(data): + # Coerce input data to ndarray (including ndarray subclasses). + data = np.asarray(data) + if isinstance(data, ma.core.MaskedConstant): + # Promote to a masked array so that the fill-value is + # writeable to the data owner. + data = ma.array(data.data, mask=data.mask, dtype=data.dtype) + self._lazy_array = None + self._real_array = data + + # Check the manager contract, as the managed data has changed. + self._assert_axioms() + + @property + def dtype(self): + """ + The dtype of the realised lazy data or the dtype of the real data. + + """ + return self.core_data().dtype + + @property + def ndim(self): + """ + The number of dimensions covered by the data being managed. + + """ + return self.core_data().ndim + + @property + def shape(self): + """ + The shape of the data being managed. + + """ + return self.core_data().shape + + def copy(self, data=None): + """ + Returns a deep copy of this :class:`~iris._data_manager.DataManager` + instance. + + Kwargs: + + * data: + Replace the data of the copy with this data. + + Returns: + A copy :class:`~iris._data_manager.DataManager` instance. + + """ + memo = {} + return self._deepcopy(memo, data=data) + + def core_data(self): + """ + If real data is being managed, then return the :class:`~numpy.ndarray` + or :class:`numpy.ma.core.MaskedArray`. Otherwise, return the lazy + :class:`~dask.array.core.Array`. + + Returns: + The real or lazy data. + + """ + if self.has_lazy_data(): + result = self._lazy_array + else: + result = self._real_array + + return result + + def has_lazy_data(self): + """ + Determine whether lazy data is being managed. + + Returns: + Boolean. + + """ + return self._lazy_array is not None + + def lazy_data(self): + """ + Return the lazy representation of the managed data. + + If only real data is being managed, then return a lazy + representation of that real data. + + Returns: + :class:`~dask.array.core.Array` + + .. note:: + This method will never realise any lazy data. + + """ + if self.has_lazy_data(): + result = self._lazy_array + else: + result = as_lazy_data(self._real_array) + + return result diff --git a/lib/iris/_deprecation.py b/lib/iris/_deprecation.py new file mode 100644 index 0000000000..e818bfede1 --- /dev/null +++ b/lib/iris/_deprecation.py @@ -0,0 +1,81 @@ +# (C) British Crown Copyright 2010 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Utilities for producing runtime deprecation messages. + +""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +import warnings + +from iris.exceptions import IrisError + + +class IrisDeprecation(UserWarning): + """An Iris deprecation warning.""" + pass + + +def warn_deprecated(msg, stacklevel=2): + """ + Issue an Iris deprecation warning. + + Calls :func:`warnings.warn', to emit the message 'msg' as a + :class:`warnings.warning`, of the subclass :class:`IrisDeprecationWarning`. + + The 'stacklevel' keyword is passed through to warnings.warn. However by + default this is set to 2, which ensures that the identified code line is in + the caller, rather than in this routine. + See :mod:`warnings` module documentation. + + For example:: + + >>> from iris._deprecation import warn_deprecated + >>> def arrgh(): + ... warn_deprecated('"arrgh" is deprecated since version 3.5.') + ... return 1 + ... + >>> arrgh() + __main__:2: IrisDeprecation: "arrgh" is deprecated since version 3.5. + 1 + >>> arrgh() + 1 + >>> + + """ + warnings.warn(msg, IrisDeprecation, stacklevel=stacklevel) + + +# A Mixin for a wrapper class that copies the docstring of the wrapped class +# into the wrapper. +# This is useful in producing wrapper classes that need to mimic the original +# but emit deprecation warnings when used. +class ClassWrapperSameDocstring(type): + def __new__(metacls, classname, bases, class_dict): + # Patch the subclass to duplicate the class docstring from the wrapped + # class, and give it a special '__new__' that issues a deprecation + # warning when creating an instance. + parent_class = bases[0] + + # Copy the original class docstring. + class_dict['__doc__'] = parent_class.__doc__ + + # Return the result. + return super(ClassWrapperSameDocstring, metacls).__new__( + metacls, classname, bases, class_dict) diff --git a/lib/iris/_lazy_data.py b/lib/iris/_lazy_data.py new file mode 100644 index 0000000000..f5312b7d3a --- /dev/null +++ b/lib/iris/_lazy_data.py @@ -0,0 +1,270 @@ +# (C) British Crown Copyright 2017 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Routines for lazy data handling. + +To avoid replicating implementation-dependent test and conversion code. + +""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +from functools import wraps + +import dask +import dask.array as da +import dask.context +from dask.local import get_sync as dget_sync +import numpy as np +import numpy.ma as ma + + +def non_lazy(func): + """ + Turn a lazy function into a function that returns a result immediately. + + """ + @wraps(func) + def inner(*args, **kwargs): + """Immediately return the results of a lazy function.""" + result = func(*args, **kwargs) + return dask.compute(result)[0] + return inner + + +def is_lazy_data(data): + """ + Return whether the argument is an Iris 'lazy' data array. + + At present, this means simply a Dask array. + We determine this by checking for a "compute" property. + + """ + result = hasattr(data, 'compute') + return result + + +# A magic value, chosen to minimise chunk creation time and chunk processing +# time within dask. +_MAX_CHUNK_SIZE = 8 * 1024 * 1024 * 2 + + +def _limited_shape(shape): + # Reduce a shape to less than a default overall number-of-points, reducing + # earlier dimensions preferentially. + # Note: this is only a heuristic, assuming that earlier dimensions are + # 'outer' storage dimensions -- not *always* true, even for NetCDF data. + shape = list(shape) + i_reduce = 0 + while np.prod(shape) > _MAX_CHUNK_SIZE: + factor = np.ceil(np.prod(shape) / _MAX_CHUNK_SIZE) + new_dim = int(shape[i_reduce] / factor) + if new_dim < 1: + new_dim = 1 + shape[i_reduce] = new_dim + i_reduce += 1 + return tuple(shape) + + +def as_lazy_data(data, chunks=None, asarray=False): + """ + Convert the input array `data` to a dask array. + + Args: + + * data: + An array. This will be converted to a dask array. + + Kwargs: + + * chunks: + Describes how the created dask array should be split up. Defaults to a + value first defined in biggus (being `8 * 1024 * 1024 * 2`). + For more information see + http://dask.pydata.org/en/latest/array-creation.html#chunks. + + * asarray: + If True, then chunks will be converted to instances of `ndarray`. + Set to False (default) to pass passed chunks through unchanged. + + Returns: + The input array converted to a dask array. + + """ + if chunks is None: + # Default to the shape of the wrapped array-like, + # but reduce it if larger than a default maximum size. + chunks = _limited_shape(data.shape) + + if isinstance(data, ma.core.MaskedConstant): + data = ma.masked_array(data.data, mask=data.mask) + if not is_lazy_data(data): + data = da.from_array(data, chunks=chunks, asarray=asarray) + return data + + +def _co_realise_lazy_arrays(arrays): + """ + Compute multiple lazy arrays and return a list of real values. + + All the arrays are computed together, so they can share results for common + graph elements. + + Casts all results with `np.asanyarray`, and converts any MaskedConstants + appearing into masked arrays, to ensure that all return values are + writeable NumPy array objects. + + Any non-lazy arrays are passed through, as they are by `da.compute`. + They undergo the same result standardisation. + + """ + computed_arrays = da.compute(*arrays) + results = [] + for lazy_in, real_out in zip(arrays, computed_arrays): + # Ensure we always have arrays. + # Note : in some cases dask (and numpy) will return a scalar + # numpy.int/numpy.float object rather than an ndarray. + # Recorded in https://github.com/dask/dask/issues/2111. + real_out = np.asanyarray(real_out) + if isinstance(real_out, ma.core.MaskedConstant): + # Convert any masked constants into NumPy masked arrays. + # NOTE: in this case, also apply the original lazy-array dtype, as + # masked constants *always* have dtype float64. + real_out = ma.masked_array(real_out.data, mask=real_out.mask, + dtype=lazy_in.dtype) + results.append(real_out) + return results + + +def as_concrete_data(data): + """ + Return the actual content of a lazy array, as a numpy array. + If the input data is a NumPy `ndarray` or masked array, return it + unchanged. + + If the input data is lazy, return the realised result. + + Args: + + * data: + A dask array, NumPy `ndarray` or masked array + + Returns: + A NumPy `ndarray` or masked array. + + """ + if is_lazy_data(data): + data, = _co_realise_lazy_arrays([data]) + + return data + + +def multidim_lazy_stack(stack): + """ + Recursively build a multidimensional stacked dask array. + + This is needed because dask.array.stack only accepts a 1-dimensional list. + + Args: + + * stack: + An ndarray of dask arrays. + + Returns: + The input array converted to a lazy dask array. + + """ + if stack.ndim == 0: + # A 0-d array cannot be stacked. + result = stack.item() + elif stack.ndim == 1: + # Another base case : simple 1-d goes direct in dask. + result = da.stack(list(stack)) + else: + # Recurse because dask.stack does not do multi-dimensional. + result = da.stack([multidim_lazy_stack(subarray) + for subarray in stack]) + return result + + +def co_realise_cubes(*cubes): + """ + Fetch 'real' data for multiple cubes, in a shared calculation. + + This computes any lazy data, equivalent to accessing each `cube.data`. + However, lazy calculations and data fetches can be shared between the + computations, improving performance. + + Args: + + * cubes (list of :class:`~iris.cube.Cube`): + Arguments, each of which is a cube to be realised. + + For example:: + + # Form stats. + a_std = cube_a.collapsed(['x', 'y'], iris.analysis.STD_DEV) + b_std = cube_b.collapsed(['x', 'y'], iris.analysis.STD_DEV) + ab_mean_diff = (cube_b - cube_a).collapsed(['x', 'y'], + iris.analysis.MEAN) + std_err = (a_std * a_std + b_std * b_std) ** 0.5 + + # Compute stats together (to avoid multiple data passes). + co_realise_cubes(a_std, b_std, ab_mean_diff, std_err) + + + .. Note:: + + Cubes with non-lazy data may also be passed, with no ill effect. + + """ + results = _co_realise_lazy_arrays([cube.core_data() for cube in cubes]) + for cube, result in zip(cubes, results): + cube.data = result + + +def lazy_elementwise(lazy_array, elementwise_op): + """ + Apply a (numpy-style) elementwise array operation to a lazy array. + + Elementwise means that it performs a independent calculation at each point + of the input, producing a result array of the same shape. + + Args: + + * lazy_array: + The lazy array object to operate on. + * elementwise_op: + The elementwise operation, a function operating on numpy arrays. + + .. note: + + A single-point "dummy" call is made to the operation function, to + determine dtype of the result. + This return dtype must be stable in actual operation (!) + + """ + # This is just a wrapper to provide an Iris-specific abstraction for a + # lazy operation in Dask (map_blocks). + + # Explicitly determine the return type with a dummy call. + # This makes good practical sense for unit conversions, as a Unit.convert + # call may cast to float, or not, depending on unit equality : Thus, it's + # much safer to get udunits to decide that for us. + dtype = elementwise_op(np.zeros(1, lazy_array.dtype)).dtype + + return da.map_blocks(elementwise_op, lazy_array, dtype=dtype) diff --git a/lib/iris/_merge.py b/lib/iris/_merge.py index d616205b26..a1eafdbc3a 100644 --- a/lib/iris/_merge.py +++ b/lib/iris/_merge.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -21,17 +21,22 @@ :method:`iris.cube.CubeList.merge`. """ -from collections import namedtuple + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +from collections import namedtuple, OrderedDict from copy import deepcopy -import biggus import numpy as np import numpy.ma as ma +from iris._lazy_data import (as_lazy_data, as_concrete_data, is_lazy_data, + multidim_lazy_stack) import iris.cube import iris.coords import iris.exceptions -import iris.unit import iris.util @@ -62,6 +67,8 @@ class _Template(namedtuple('Template', """ + __slots__ = () + class _CoordMetaData(namedtuple('CoordMetaData', ['points_dtype', 'bounds_dtype', 'kwargs'])): @@ -83,6 +90,8 @@ class _CoordMetaData(namedtuple('CoordMetaData', """ + __slots__ = () + class _CoordAndDims(namedtuple('CoordAndDims', ['coord', 'dims'])): @@ -97,10 +106,12 @@ class _CoordAndDims(namedtuple('CoordAndDims', coordinate instance. * dims: - A tuple of the data dimesion/s spanned by the coordinate. + A tuple of the data dimension/s spanned by the coordinate. """ + __slots__ = () + class _ScalarCoordPayload(namedtuple('ScalarCoordPayload', ['defns', 'values', 'metadata'])): @@ -128,6 +139,8 @@ class _ScalarCoordPayload(namedtuple('ScalarCoordPayload', """ + __slots__ = () + class _VectorCoordPayload(namedtuple('VectorCoordPayload', ['dim_coords_and_dims', @@ -152,6 +165,8 @@ class _VectorCoordPayload(namedtuple('VectorCoordPayload', """ + __slots__ = () + class _CoordPayload(namedtuple('CoordPayload', ['scalar', 'vector', 'factory_defns'])): @@ -175,6 +190,9 @@ class _CoordPayload(namedtuple('CoordPayload', A list of :class:`_FactoryDefn` instances. """ + + __slots__ = () + def as_signature(self): """Construct and return a :class:`_CoordSignature` from the payload.""" @@ -196,7 +214,7 @@ def _coords_msgs(msgs, coord_group, defns_a, defns_b): diff_defns.append(defn_a) diff_defns.extend(defns_b) if diff_defns: - names = set(defn.name() for defn in diff_defns) + names = sorted(set(defn.name() for defn in diff_defns)) msgs.append('Coordinates in {} differ: {}.'.format( coord_group, ', '.join(names))) else: @@ -292,10 +310,12 @@ class _CoordSignature(namedtuple('CoordSignature', """ + __slots__ = () + class _CubeSignature(namedtuple('CubeSignature', ['defn', 'data_shape', 'data_type', - 'fill_value'])): + 'cell_measures_and_dims'])): """ Criterion for identifying a specific type of :class:`iris.cube.Cube` based on its metadata. @@ -311,11 +331,13 @@ class _CubeSignature(namedtuple('CubeSignature', * data_type: The data payload :class:`numpy.dtype` of a :class:`iris.cube.Cube`. - * fill_value: - The value to be used to mark missing data in the data payload, - or None if no such value exists. + * cell_measures_and_dims: + A list of cell_measures and dims for the cube. """ + + __slots__ = () + def _defn_msgs(self, other_defn): msgs = [] self_defn = self.defn @@ -332,8 +354,8 @@ def _defn_msgs(self, other_defn): msgs.append('cube.units differs: {!r} != {!r}'.format( self_defn.units, other_defn.units)) if self_defn.attributes != other_defn.attributes: - diff_keys = (self_defn.attributes.viewkeys() ^ - other_defn.attributes.viewkeys()) + diff_keys = (set(self_defn.attributes.keys()) ^ + set(other_defn.attributes.keys())) if diff_keys: msgs.append('cube.attributes keys differ: ' + ', '.join(repr(key) for key in diff_keys)) @@ -359,7 +381,7 @@ def match(self, other, error_on_mismatch): - units - attributes - cell_methods - - shape, dtype, fill_value + - shape, dtype Args: @@ -376,14 +398,14 @@ def match(self, other, error_on_mismatch): """ msgs = self._defn_msgs(other.defn) if self.data_shape != other.data_shape: - msgs.append('cube.shape differs: {} != {}'.format( - self.data_shape, other.data_shape)) + msg = 'cube.shape differs: {} != {}' + msgs.append(msg.format(self.data_shape, other.data_shape)) if self.data_type != other.data_type: - msgs.append('cube data dtype differs: {} != {}'.format( - self.data_type, other.data_type)) - if self.fill_value != other.fill_value: - msgs.append('cube data fill_value differs: {!r} != {!r}'.format( - self.fill_value, other.fill_value)) + msg = 'cube data dtype differs: {} != {}' + msgs.append(msg.format(self.data_type, other.data_type)) + if (self.cell_measures_and_dims != other.cell_measures_and_dims): + msgs.append('cube.cell_measures differ') + match = not bool(msgs) if error_on_mismatch and not match: raise iris.exceptions.MergeError(msgs) @@ -409,6 +431,8 @@ class _Skeleton(namedtuple('Skeleton', """ + __slots__ = () + class _FactoryDefn(namedtuple('_FactoryDefn', ['class_', 'dependency_defns'])): @@ -426,6 +450,8 @@ class _FactoryDefn(namedtuple('_FactoryDefn', """ + __slots__ = () + class _Relation(namedtuple('Relation', ['separable', 'inseparable'])): @@ -444,6 +470,8 @@ class _Relation(namedtuple('Relation', """ + __slots__ = () + _COMBINATION_JOIN = '-' @@ -480,12 +508,12 @@ def build_indexes(positions): ... >>> indexes = build_indexes(positions) >>> for k in sorted(indexes): - ... print '%r:' % k + ... print('%r:' % k) ... for kk in sorted(indexes[k]): - ... print '\t%r:' % kk, + ... print('\t%r:' % kk, end=' ') ... for kkk in sorted(indexes[k][kk]): - ... print '%r: %r' % (kkk, indexes[k][kk][kkk]), - ... print + ... print('%r: %r' % (kkk, indexes[k][kk][kkk]), end=' ') + ... print() ... 'a': 0: 'b': set([10]) 'c': set([100]) @@ -513,7 +541,7 @@ def build_indexes(positions): scalar_index_by_name = {name: {} for name in names} for position in positions: - for name, value in position.iteritems(): + for name, value in six.iteritems(position): name_index_by_scalar = scalar_index_by_name[name] if value in name_index_by_scalar: @@ -553,7 +581,7 @@ def _separable_pair(name, index): Boolean. """ - items = index.itervalues() + items = six.itervalues(index) reference = next(items)[name] return all([item[name] == reference for item in items]) @@ -614,7 +642,7 @@ def derive_relation_matrix(indexes): >>> indexes = build_indexes(positions) >>> matrix = derive_relation_matrix(indexes) >>> for k, v in matrix.iteritems(): - ... print '%r: %r' % (k, v) + ... print('%r: %r' % (k, v)) ... 'a': Relation(separable=set([]), inseparable=set(['c', 'b'])) 'c': Relation(separable=set([]), inseparable=set(['a', 'b'])) @@ -1023,7 +1051,7 @@ def derive_space(groups, relation_matrix, positions, function_matrix=None): positions, function_matrix): # There is no relationship between any of the candidate # dimensions in the separable group, so merge them together - # into a new combined dimesion of the space. + # into a new combined dimension of the space. _build_combination_group(space, group, positions, function_matrix) else: @@ -1059,6 +1087,9 @@ def __init__(self, cube): self._hints = ['time', 'forecast_reference_time', 'forecast_period', 'model_level_number'] + # The proto-cube source. + self._source = cube + # The cube signature is metadata that defines this ProtoCube. self._cube_signature = self._build_signature(cube) @@ -1099,6 +1130,10 @@ def __init__(self, cube): self._vector_dim_coords_dims = [] self._vector_aux_coords_dims = [] + # cell measures are not merge candidates + # they are checked and preserved through merge + self._cell_measures_and_dims = cube._cell_measures_and_dims + def _report_duplicate(self, nd_indexes, group_by_nd_index): # Find the first offending source-cube with duplicate metadata. index = [group_by_nd_index[nd_index][1] @@ -1152,20 +1187,27 @@ def merge(self, unique=True): # Determine the largest group of source-cubes that want to occupy # the same nd-index in the final merged cube. group_depth = max([len(group) for group in group_by_nd_index.values()]) - nd_indexes = group_by_nd_index.keys() - nd_indexes.sort() + nd_indexes = sorted(group_by_nd_index.keys()) # Check for unique data. if unique and group_depth > 1: self._report_duplicate(nd_indexes, group_by_nd_index) # Generate group-depth merged cubes from the source-cubes. - for level in xrange(group_depth): + for level in range(group_depth): + # Track the largest dtype of the data to be merged. + # Unfortunately, da.stack() is not symmetric with regards + # to dtypes. So stacking float + int yields a float, but + # stacking an int + float yields an int! We need to ensure + # that the largest dtype prevails i.e. float, in order to + # support the masked case for dask. + # Reference https://github.com/dask/dask/issues/2273. + dtype = None # Stack up all the data from all of the relevant source - # cubes in a single biggus ArrayStack. + # cubes in a single dask "stacked" array. # If it turns out that all the source cubes already had - # their data loaded then at the end we can convert the - # ArrayStack back to a numpy array. + # their data loaded then at the end we convert the stack back + # into a plain numpy array. stack = np.empty(self._stack_shape, 'object') all_have_data = True for nd_index in nd_indexes: @@ -1174,21 +1216,29 @@ def merge(self, unique=True): group = group_by_nd_index[nd_index] offset = min(level, len(group) - 1) data = self._skeletons[group[offset]].data - # Ensure the data is represented as a biggus.Array and - # slot that Array into the stack. - if isinstance(data, biggus.Array): + # Ensure the data is represented as a dask array and + # slot that array into the stack. + if is_lazy_data(data): all_have_data = False else: - data = biggus.NumpyArrayAdapter(data) + data = as_lazy_data(data) stack[nd_index] = data + # Determine the largest dtype. + if dtype is None: + dtype = data.dtype + else: + dtype = np.promote_types(data.dtype, dtype) + + # Coerce to the largest dtype. + for nd_index in nd_indexes: + stack[nd_index] = stack[nd_index].astype(dtype) - merged_data = biggus.ArrayStack(stack) + merged_data = multidim_lazy_stack(stack) if all_have_data: - merged_data = merged_data.masked_array() - # Unmask the array only if it is filled. - if (ma.isMaskedArray(merged_data) and - ma.count_masked(merged_data) == 0): - merged_data = merged_data.data + # All inputs were concrete, so turn the result back into a + # normal array. + dtype = self._cube_signature.data_type + merged_data = as_concrete_data(merged_data) merged_cube = self._get_cube(merged_data) merged_cubes.append(merged_cube) @@ -1220,8 +1270,9 @@ def register(self, cube, error_on_mismatch=False): this :class:`ProtoCube`. """ - match = self._cube_signature.match(self._build_signature(cube), - error_on_mismatch) + cube_signature = self._cube_signature + other = self._build_signature(cube) + match = cube_signature.match(other, error_on_mismatch) if match: coord_payload = self._extract_coord_payload(cube) match = coord_payload.match_signature(self._coord_signature, @@ -1288,7 +1339,8 @@ def _define_space(self, space, positions, indexes, function_matrix): def axis_and_name(name): axis_dict = {'T': 1, 'Z': 2, 'Y': 3, 'X': 4} axis_index = axis_dict.get(self._guess_axis(name), 0) - return (axis_index, name) + # The middle element ensures sorting is the same as Python 2. + return (axis_index, not isinstance(name, six.integer_types), name) names = sorted(space, key=axis_and_name) dim_by_name = {} @@ -1304,9 +1356,14 @@ def axis_and_name(name): if space[name] is None: if _is_combination(name): members = name.split(_COMBINATION_JOIN) - cells = [tuple( - position[int(member) if member.isdigit() else member] - for member in members) for position in positions] + # Create list of unique tuples from all combinations of + # scalars for each source cube. The keys of an OrderedDict + # are used to retain the ordering of source cubes but to + # remove any duplicate tuples. + cells = OrderedDict( + (tuple(position[int(member) if member.isdigit() else + member] for member in members), None) + for position in positions).keys() dim_by_name[name] = len(self._shape) self._nd_names.append(name) self._shape.append(len(cells)) @@ -1330,7 +1387,7 @@ def axis_and_name(name): def name_in_independents(): return any(name in independents - for independents in space.itervalues() + for independents in six.itervalues(space) if independents is not None) if len(cells) == 1 and not name_in_independents(): # A scalar coordinate not participating in a @@ -1342,7 +1399,7 @@ def name_in_independents(): # string like). dim_by_name[name] = dim = len(self._shape) self._nd_names.append(name) - if metadata[name].points_dtype.kind == 'S': + if metadata[name].points_dtype.kind in 'SU': self._aux_templates.append( _Template(dim, points, bounds, kwargs)) else: @@ -1374,7 +1431,7 @@ def name_in_independents(): # Populate the points and bounds based on the appropriate # function mapping. - temp = function_matrix[name].iteritems() + temp = six.iteritems(function_matrix[name]) for function_independents, name_value in temp: # Build the index (and cache it) for the auxiliary # coordinate based on the associated independent @@ -1424,9 +1481,12 @@ def _get_cube(self, data): for coord, dims in self._aux_coords_and_dims] kwargs = dict(zip(iris.cube.CubeMetadata._fields, signature.defn)) + cms_and_dims = [(deepcopy(cm), dims) + for cm, dims in self._cell_measures_and_dims] cube = iris.cube.Cube(data, dim_coords_and_dims=dim_coords_and_dims, aux_coords_and_dims=aux_coords_and_dims, + cell_measures_and_dims=cms_and_dims, **kwargs) # Add on any aux coord factories. @@ -1533,18 +1593,26 @@ def _build_coordinates(self): aux_coords_and_dims.append(_CoordAndDims(item.coord, dims)) def _build_signature(self, cube): - """Generate the signature that defines this cube.""" - array = cube.lazy_data() - return _CubeSignature(cube.metadata, cube.shape, array.dtype, - array.fill_value) + """ + Generate the signature that defines this cube. + + Args: + + * cube: + The source cube to create the cube signature from. + + Returns: + The cube signature. + + """ + + return _CubeSignature(cube.metadata, cube.shape, + cube.dtype, cube._cell_measures_and_dims) def _add_cube(self, cube, coord_payload): """Create and add the source-cube skeleton to the ProtoCube.""" - if cube.has_lazy_data(): - data = cube.lazy_data() - else: - data = cube.data - skeleton = _Skeleton(coord_payload.scalar.values, data) + skeleton = _Skeleton(coord_payload.scalar.values, + cube.core_data()) # Attempt to do something sensible with mixed scalar dtypes. for i, metadata in enumerate(coord_payload.scalar.metadata): if metadata.points_dtype > self._coord_metadata[i].points_dtype: @@ -1588,7 +1656,8 @@ def _extract_coord_payload(self, cube): # the CoordDefn used by scalar_defns: `coord.points.dtype` and # `type(coord)`. def key_func(coord): - return (not np.issubdtype(coord.points.dtype, np.number), + points_dtype = coord.dtype + return (not np.issubdtype(points_dtype, np.number), not isinstance(coord, iris.coords.DimCoord), hint_dict.get(coord.name(), len(hint_dict) + 1), axis_dict.get(iris.util.guess_coord_axis(coord), @@ -1633,7 +1702,8 @@ def key_func(coord): dependencies = factory.dependencies for key in sorted(dependencies): coord = dependencies[key] - dependency_defns.append((key, coord._as_defn())) + if coord is not None: + dependency_defns.append((key, coord._as_defn())) factory_defn = _FactoryDefn(type(factory), dependency_defns) factory_defns.append(factory_defn) diff --git a/lib/iris/analysis/__init__.py b/lib/iris/analysis/__init__.py index d3a2ae7082..ec4d341d25 100644 --- a/lib/iris/analysis/__init__.py +++ b/lib/iris/analysis/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -15,37 +15,63 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """ -A package providing various analysis facilities. - -Primarily, this module provides definitions of statistical operations, such as -:const:`MEAN` and :const:`STD_DEV`, that can be applied to Cubes via methods -such as: :meth:`iris.cube.Cube.collapsed` and -:meth:`iris.cube.Cube.aggregated_by`. - - .. note:: - - These statistical operations define how to transform both the - metadata and the data. +A package providing :class:`iris.cube.Cube` analysis support. + +This module defines a suite of :class:`~iris.analysis.Aggregator` instances, +which are used to specify the statistical measure to calculate over a +:class:`~iris.cube.Cube`, using methods such as +:meth:`~iris.cube.Cube.aggregated_by` and :meth:`~iris.cube.Cube.collapsed`. + +The :class:`~iris.analysis.Aggregator` is a convenience class that allows +specific statistical aggregation operators to be defined and instantiated. +These operators can then be used to collapse, or partially collapse, one or +more dimensions of a :class:`~iris.cube.Cube`, as discussed in +:ref:`cube-statistics`. + +In particular, :ref:`cube-statistics-collapsing` discusses how to use +:const:`MEAN` to average over one dimension of a :class:`~iris.cube.Cube`, +and also how to perform weighted :ref:`cube-statistics-collapsing-average`. +While :ref:`cube-statistics-aggregated-by` shows how to aggregate similar +groups of data points along a single dimension, to result in fewer points +in that dimension. + +The gallery contains several interesting worked examples of how an +:class:`~iris.analysis.Aggregator` may be used, including: + + * :ref:`Meteorology-COP_1d_plot` + * :ref:`General-SOI_filtering` + * :ref:`Meteorology-hovmoller` + * :ref:`Meteorology-lagged_ensemble` + * :ref:`General-custom_aggregation` """ -from __future__ import division + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six import collections -from copy import deepcopy +from functools import wraps -import biggus +import dask.array as da import numpy as np import numpy.ma as ma import scipy.interpolate import scipy.stats.mstats +from iris.analysis._area_weighted import AreaWeightedRegridder +from iris.analysis._interpolation import (EXTRAPOLATION_MODES, + RectilinearInterpolator) +from iris.analysis._regrid import RectilinearRegridder import iris.coords from iris.exceptions import LazyAggregatorError +import iris._lazy_data __all__ = ('COUNT', 'GMEAN', 'HMEAN', 'MAX', 'MEAN', 'MEDIAN', 'MIN', 'PEAK', 'PERCENTILE', 'PROPORTION', 'RMS', 'STD_DEV', 'SUM', - 'VARIANCE', 'coord_comparison', 'Aggregator', - 'clear_phenomenon_identity') + 'VARIANCE', 'WPERCENTILE', 'coord_comparison', 'Aggregator', + 'WeightedAggregator', 'clear_phenomenon_identity', 'Linear', + 'AreaWeighted', 'Nearest', 'UnstructuredNearest') class _CoordGroup(object): @@ -70,8 +96,8 @@ def _first_coord_w_cube(self): as (cube, coord). """ - return filter(lambda cube_coord: cube_coord[1] is not None, - zip(self.cubes, self.coords))[0] + return next(filter(lambda cube_coord: cube_coord[1] is not None, + zip(self.cubes, self.coords))) def __repr__(self): # No exact repr, so a helpful string is given instead @@ -190,7 +216,7 @@ def coord_comparison(*cubes): Example usage:: result = coord_comparison(cube1, cube2) - print 'All equal coordinates: ', result['equal'] + print('All equal coordinates: ', result['equal']) """ all_coords = [cube.coords() for cube in cubes] @@ -227,7 +253,7 @@ def coord_comparison(*cubes): for other_coord in all_coords[other_cube_i]: # for optimisation, check that the name is equivalent # *before* checking all of the metadata is equivalent - eq = (id(other_coord) not in processed_coords and + eq = (other_coord is coord or other_coord.name() == coord.name() and other_coord._as_defn() == coord._as_defn()) if eq: @@ -259,39 +285,50 @@ def coord_comparison(*cubes): # Get all coordinate groups which aren't complete (i.e. there is a # None in the group) - coord_is_None_fn = lambda cube, coord: coord is None + def coord_is_None_fn(cube, coord): + return coord is None + if coord_group.matches_any(coord_is_None_fn): ungroupable.add(coord_group) # Get all coordinate groups which don't all equal one another # (None -> group not all equal) - not_equal_fn = lambda cube, coord: coord != first_coord + def not_equal_fn(cube, coord): + return coord != first_coord + if coord_group.matches_any(not_equal_fn): not_equal.add(coord_group) # Get all coordinate groups which don't all share the same shape # (None -> group has different shapes) - diff_shape_fn = lambda cube, coord: coord.shape != first_coord.shape + def diff_shape_fn(cube, coord): + return coord.shape != first_coord.shape + if coord_group.matches_any(diff_shape_fn): different_shaped_coords.add(coord_group) # Get all coordinate groups which don't all share the same data # dimension on their respective cubes # (None -> group describes a different dimension) - diff_data_dim_fn = lambda cube, coord: \ - cube.coord_dims(coord) != first_cube.coord_dims(first_coord) + def diff_data_dim_fn(cube, coord): + return cube.coord_dims(coord) != first_cube.coord_dims(first_coord) + if coord_group.matches_any(diff_data_dim_fn): different_data_dimension.add(coord_group) # get all coordinate groups which don't describe a dimension # (None -> doesn't describe a dimension) - no_data_dim_fn = lambda cube, coord: cube.coord_dims(coord) == () + def no_data_dim_fn(cube, coord): + return cube.coord_dims(coord) == () + if coord_group.matches_all(no_data_dim_fn): no_data_dimension.add(coord_group) # get all coordinate groups which don't describe a dimension # (None -> not a scalar coordinate) - no_data_dim_fn = lambda cube, coord: coord.shape == (1, ) + def no_data_dim_fn(cube, coord): + return coord.shape == (1, ) + if coord_group.matches_all(no_data_dim_fn): scalar_coords.add(coord_group) @@ -320,37 +357,64 @@ def coord_comparison(*cubes): # for convenience, turn all of the sets in the dictionary into lists, # sorted by the name of the group - for key, groups in result.iteritems(): + for key, groups in six.iteritems(result): result[key] = sorted(groups, key=lambda group: group.name()) return result -class Aggregator(object): - """Convenience class that supports common aggregation functionality.""" +class _Aggregator(object): + """ + The :class:`_Aggregator` base class provides common aggregation + functionality. + """ def __init__(self, cell_method, call_func, units_func=None, lazy_func=None, **kwargs): """ - Create an aggregator for the given call_func. + Create an aggregator for the given :data:`call_func`. Args: * cell_method (string): - Cell method string that supports string format substitution. + Cell method definition formatter. Used in the fashion + "cell_method.format(\**kwargs)", to produce a cell-method string + which can include keyword values. + * call_func (callable): - Data aggregation function. Call signature: (data, axis, **kwargs). + | *Call signature*: (data, axis=None, \**kwargs) + + Data aggregation function. + Returns an aggregation result, collapsing the 'axis' dimension of + the 'data' argument. Kwargs: * units_func (callable): - Units conversion function. - * lazy_func (callable): - An alternative to 'call_func' implementing a lazy aggregation. - (Note: need not support all features of the main operation, but - should raise an error in unhandled cases.) - * kwargs: - Passed through to call_func. + | *Call signature*: (units) + + If provided, called to convert a cube's units. + Returns an :class:`cf_units.Unit`, or a + value that can be made into one. + + * lazy_func (callable or None): + An alternative to :data:`call_func` implementing a lazy + aggregation. Note that, it need not support all features of the + main operation, but should raise an error in unhandled cases. + + Additional kwargs:: + Passed through to :data:`call_func` and :data:`lazy_func`. + + Aggregators are used by cube aggregation methods such as + :meth:`~iris.cube.Cube.collapsed` and + :meth:`~iris.cube.Cube.aggregated_by`. For example:: + + result = cube.collapsed('longitude', iris.analysis.MEAN) + + A variety of ready-made aggregators are provided in this module, such + as :data:`~iris.analysis.MEAN` and :data:`~iris.analysis.MAX`. Custom + aggregators can also be created for special purposes, see + :ref:`General-custom_aggregation` for a worked example. """ #: Cube cell method string. @@ -359,14 +423,15 @@ def __init__(self, cell_method, call_func, units_func=None, self.call_func = call_func #: Unit conversion function. self.units_func = units_func - #: Lazy aggregation function. + #: Lazy aggregation function, may be None to indicate that a lazy + #: operation is not available. self.lazy_func = lazy_func self._kwargs = kwargs def lazy_aggregate(self, data, axis, **kwargs): """ - Peform aggregation over the data with a lazy operation, analagous to + Perform aggregation over the data with a lazy operation, analogous to the 'aggregate' result. Keyword arguments are passed through to the data aggregation function @@ -377,7 +442,7 @@ def lazy_aggregate(self, data, axis, **kwargs): Args: * data (array): - A lazy array (:class:`biggus.Array`). + A lazy array (:class:`dask.array.Array`). * axis (int or list of int): The dimensions to aggregate over -- note that this is defined @@ -386,33 +451,24 @@ def lazy_aggregate(self, data, axis, **kwargs): Kwargs: - * mdtol (float): - Tolerance of missing data. The value returned will be masked if - the fraction of data to missing data is less than or equal to - mdtol. mdtol=0 means no missing data is tolerated while mdtol=1 - will return the resulting value from the aggregation function. - Default mdtol=1. - - .. warning:: - - This may not be supported by all lazy operations. Where it is - not supported, *any* mention of this keyword will produce an - error. - * kwargs: - All keyword arguments apart from those specified above, are - passed through to the data aggregation function. + All keyword arguments are passed through to the data aggregation + function. Returns: A lazy array representing the aggregation operation - (:class:`biggus.Array`). + (:class:`dask.array.Array`). """ - if not self.lazy_func: - raise LazyAggregatorError( - '{} aggregator does not support lazy operation.'.format( - self.cell_method)) - return self.lazy_func(data, axis, **kwargs) + if self.lazy_func is None: + msg = '{} aggregator does not support lazy operation.' + raise LazyAggregatorError(msg.format(self.name())) + + # Combine keyword args with `kwargs` taking priority over those + # provided to __init__. + kwargs = dict(list(self._kwargs.items()) + list(kwargs.items())) + + return self.lazy_func(data, axis=axis, **kwargs) def aggregate(self, data, axis, **kwargs): """ @@ -438,7 +494,7 @@ def aggregate(self, data, axis, **kwargs): the fraction of data to missing data is less than or equal to mdtol. mdtol=0 means no missing data is tolerated while mdtol=1 will return the resulting value from the aggregation function. - Default mdtol=1. + Defaults to 1. * kwargs: All keyword arguments apart from those specified above, are @@ -448,7 +504,7 @@ def aggregate(self, data, axis, **kwargs): The aggregated data. """ - kwargs = dict(self._kwargs.items() + kwargs.items()) + kwargs = dict(list(self._kwargs.items()) + list(kwargs.items())) mdtol = kwargs.pop('mdtol', None) result = self.call_func(data, axis=axis, **kwargs) @@ -459,31 +515,391 @@ def aggregate(self, data, axis, **kwargs): result.mask = result.mask | mask_update else: result = ma.array(result, mask=mask_update) - if result.ndim is 0: - result = result * np.array([1]) - result.mask = result.mask[np.newaxis] return result def update_metadata(self, cube, coords, **kwargs): """ - Update cube cell method metadata w.r.t the aggregation function. + Update common cube metadata w.r.t the aggregation function. Args: * cube (:class:`iris.cube.Cube`): Source cube that requires metadata update. * coords (:class:`iris.coords.Coord`): - The coords that were aggregated. + The one or more coordinates that were aggregated. Kwargs: * This function is intended to be used in conjuction with aggregate() + and should be passed the same keywords (for example, the "ddof" + keyword for a standard deviation aggregator). + + """ + # Update the units if required. + if self.units_func is not None: + cube.units = self.units_func(cube.units) + + def post_process(self, collapsed_cube, data_result, coords, **kwargs): + """ + Process the result from :func:`iris.analysis.Aggregator.aggregate`. + + Args: + + * collapsed_cube: + A :class:`iris.cube.Cube`. + * data_result: + Result from :func:`iris.analysis.Aggregator.aggregate` + * coords: + The one or more coordinates that were aggregated over. + + Kwargs: + + * This function is intended to be used in conjunction with aggregate() + and should be passed the same keywords (for example, the "ddof" + keyword from a standard deviation aggregator). + + Returns: + The collapsed cube with its aggregated data payload. + + """ + collapsed_cube.data = data_result + return collapsed_cube + + def aggregate_shape(self, **kwargs): + """ + The shape of the new dimension/s created by the aggregator. + + Kwargs: + + * This function is intended to be used in conjunction with aggregate() + and should be passed the same keywords. + + Returns: + A tuple of the aggregate shape. + + """ + return () + + def name(self): + """ + Returns the name of the aggregator. + + """ + try: + name = '_'.join(self.cell_method.split()) + except AttributeError: + name = 'unknown' + return name + + +class PercentileAggregator(_Aggregator): + """ + The :class:`PercentileAggregator` class provides percentile aggregation + functionality. + + This aggregator *may* introduce a new dimension to the data for the + statistic being calculated, but only if more than one quantile is required. + For example, calculating the 50th and 90th percentile will result in a new + data dimension with an extent of 2, for each of the quantiles calculated. + + """ + def __init__(self, units_func=None, lazy_func=None, **kwargs): + """ + Create a percentile aggregator. + + Kwargs: + + * units_func (callable): + | *Call signature*: (units) + + If provided, called to convert a cube's units. + Returns an :class:`cf_units.Unit`, or a + value that can be made into one. + + * lazy_func (callable or None): + An alternative to :data:`call_func` implementing a lazy + aggregation. Note that, it need not support all features of the + main operation, but should raise an error in unhandled cases. + + Additional kwargs:: + Passed through to :data:`call_func` and :data:`lazy_func`. + + This aggregator can used by cube aggregation methods such as + :meth:`~iris.cube.Cube.collapsed` and + :meth:`~iris.cube.Cube.aggregated_by`. For example:: + + cube.collapsed('longitude', iris.analysis.PERCENTILE, percent=50) + + """ + self._name = 'percentile' + self._args = ['percent'] + _Aggregator.__init__(self, None, _percentile, + units_func=units_func, lazy_func=lazy_func, + **kwargs) + + def aggregate(self, data, axis, **kwargs): + """ + Perform the percentile aggregation over the given data. + + Keyword arguments are passed through to the data aggregation function + (for example, the "percent" keyword for a percentile aggregator). + This function is usually used in conjunction with update_metadata(), + which should be passed the same keyword arguments. + + Args: + + * data (array): + Data array. + + * axis (int): + Axis to aggregate over. + + Kwargs: + + * mdtol (float): + Tolerance of missing data. The value returned will be masked if + the fraction of data to missing data is less than or equal to + mdtol. mdtol=0 means no missing data is tolerated while mdtol=1 + will return the resulting value from the aggregation function. + Defaults to 1. + + * kwargs: + All keyword arguments apart from those specified above, are + passed through to the data aggregation function. + + Returns: + The aggregated data. + + """ + + msg = '{} aggregator requires the mandatory keyword argument {!r}.' + for arg in self._args: + if arg not in kwargs: + raise ValueError(msg.format(self.name(), arg)) + + return _Aggregator.aggregate(self, data, axis, **kwargs) + + def post_process(self, collapsed_cube, data_result, coords, **kwargs): + """ + Process the result from :func:`iris.analysis.Aggregator.aggregate`. + + Args: + + * collapsed_cube: + A :class:`iris.cube.Cube`. + * data_result: + Result from :func:`iris.analysis.Aggregator.aggregate` + * coords: + The one or more coordinates that were aggregated over. + + Kwargs: + + * This function is intended to be used in conjunction with aggregate() and should be passed the same keywords (for example, the "percent" - keyword for a percentile aggregator). + keywords from a percentile aggregator). + + Returns: + The collapsed cube with it's aggregated data payload. + + """ + cubes = iris.cube.CubeList() + # The additive aggregator requires a mandatory keyword. + msg = '{} aggregator requires the mandatory keyword argument {!r}.' + for arg in self._args: + if arg not in kwargs: + raise ValueError(msg.format(self.name(), arg)) + + points = kwargs[self._args[0]] + # Derive the name of the additive coordinate. + names = [coord.name() for coord in coords] + coord_name = '{}_over_{}'.format(self.name(), '_'.join(names)) + + if not isinstance(points, collections.Iterable): + points = [points] + + # Decorate a collapsed cube with a scalar additive coordinate + # for each of the additive points, to result in a possibly higher + # order cube. + for point in points: + cube = collapsed_cube.copy() + coord = iris.coords.AuxCoord(point, long_name=coord_name) + cube.add_aux_coord(coord) + cubes.append(cube) + + collapsed_cube = cubes.merge_cube() + + # Ensure to roll the data payload additive dimension, which should + # be the last dimension for an additive operation with more than + # one point, to be the first dimension, thus matching the collapsed + # cube. + if self.aggregate_shape(**kwargs): + # Roll the last additive dimension to be the first. + data_result = np.rollaxis(data_result, -1) + + # Marry the collapsed cube and the data payload together. + result = _Aggregator.post_process(self, collapsed_cube, data_result, + coords, **kwargs) + return result + + def aggregate_shape(self, **kwargs): + """ + The shape of the additive dimension created by the aggregator. + + Kwargs: + + * This function is intended to be used in conjunction with aggregate() + and should be passed the same keywords. + + Returns: + A tuple of the additive dimension shape. + + """ + + msg = '{} aggregator requires the mandatory keyword argument {!r}.' + for arg in self._args: + if arg not in kwargs: + raise ValueError(msg.format(self.name(), arg)) + + points = kwargs[self._args[0]] + shape = () + if not isinstance(points, collections.Iterable): + points = [points] + + points = np.array(points) + + if points.shape > (1,): + shape = points.shape + + return shape + + def name(self): """ - kwargs = dict(self._kwargs.items() + kwargs.items()) + Returns the name of the aggregator. + + """ + return self._name + + +class WeightedPercentileAggregator(PercentileAggregator): + """ + The :class:`WeightedPercentileAggregator` class provides percentile + aggregation functionality. + + This aggregator *may* introduce a new dimension to the data for the + statistic being calculated, but only if more than one quantile is required. + For example, calculating the 50th and 90th percentile will result in a new + data dimension with an extent of 2, for each of the quantiles calculated. + + """ + def __init__(self, units_func=None, lazy_func=None, **kwargs): + """ + Create a weighted percentile aggregator. + + Kwargs: + + * units_func (callable): + | *Call signature*: (units) + + If provided, called to convert a cube's units. + Returns an :class:`cf_units.Unit`, or a + value that can be made into one. + + * lazy_func (callable or None): + An alternative to :data:`call_func` implementing a lazy + aggregation. Note that, it need not support all features of the + main operation, but should raise an error in unhandled cases. + + Additional kwargs:: + Passed through to :data:`call_func` and :data:`lazy_func`. + + This aggregator can used by cube aggregation methods such as + :meth:`~iris.cube.Cube.collapsed` and + :meth:`~iris.cube.Cube.aggregated_by`. For example:: + + cube.collapsed('longitude', iris.analysis.WPERCENTILE, percent=50, + weights=iris.analysis.cartography.area_weights(cube)) + + """ + _Aggregator.__init__(self, None, _weighted_percentile, + units_func=units_func, lazy_func=lazy_func, + **kwargs) + + self._name = "weighted_percentile" + self._args = ["percent", "weights"] + + #: A list of keywords associated with weighted behaviour. + self._weighting_keywords = ["returned", "weights"] + + def post_process(self, collapsed_cube, data_result, coords, **kwargs): + """ + Process the result from :func:`iris.analysis.Aggregator.aggregate`. + + Returns a tuple(cube, weights) if a tuple(data, weights) was returned + from :func:`iris.analysis.Aggregator.aggregate`. + + Args: + + * collapsed_cube: + A :class:`iris.cube.Cube`. + * data_result: + Result from :func:`iris.analysis.Aggregator.aggregate` + * coords: + The one or more coordinates that were aggregated over. + + Kwargs: + + * This function is intended to be used in conjunction with aggregate() + and should be passed the same keywords (for example, the "weights" + keyword). + + Returns: + The collapsed cube with it's aggregated data payload. Or a tuple + pair of (cube, weights) if the keyword "returned" is specified + and True. + + """ + if kwargs.get('returned', False): + # Package the data into the cube and return a tuple + collapsed_cube = PercentileAggregator.post_process( + self, collapsed_cube, data_result[0], coords, **kwargs) + + result = (collapsed_cube, data_result[1]) + else: + result = PercentileAggregator.post_process(self, collapsed_cube, + data_result, coords, + **kwargs) + + return result + + +class Aggregator(_Aggregator): + """ + The :class:`Aggregator` class provides common aggregation functionality. + + """ + def update_metadata(self, cube, coords, **kwargs): + """ + Update cube cell method metadata w.r.t the aggregation function. + + Args: + + * cube (:class:`iris.cube.Cube`): + Source cube that requires metadata update. + * coords (:class:`iris.coords.Coord`): + The one or more coordinates that were aggregated. + + Kwargs: + + * This function is intended to be used in conjuction with aggregate() + and should be passed the same keywords (for example, the "ddof" + keyword for a standard deviation aggregator). + + """ + _Aggregator.update_metadata(self, cube, coords, **kwargs) + + kwargs = dict(list(self._kwargs.items()) + list(kwargs.items())) if not isinstance(coords, (list, tuple)): coords = [coords] @@ -500,112 +916,347 @@ def update_metadata(self, cube, coords, **kwargs): cell_method = iris.coords.CellMethod(method_name, coord_names) cube.add_cell_method(cell_method) - # Update the units if required. - if self.units_func is not None: - cube.units = self.units_func(cube.units) - def post_process(self, collapsed_cube, data_result, **kwargs): +class WeightedAggregator(Aggregator): + """ + Convenience class that supports common weighted aggregation functionality. + + """ + def __init__(self, cell_method, call_func, units_func=None, + lazy_func=None, **kwargs): + """ + Create a weighted aggregator for the given :data:`call_func`. + + Args: + + * cell_method (string): + Cell method string that supports string format substitution. + + * call_func (callable): + Data aggregation function. Call signature `(data, axis, **kwargs)`. + + Kwargs: + + * units_func (callable): + Units conversion function. + + * lazy_func (callable or None): + An alternative to :data:`call_func` implementing a lazy + aggregation. Note that, it need not support all features of the + main operation, but should raise an error in unhandled cases. + + Additional kwargs: + Passed through to :data:`call_func` and :data:`lazy_func`. + + """ + Aggregator.__init__(self, cell_method, call_func, + units_func=units_func, lazy_func=lazy_func, + **kwargs) + + #: A list of keywords that trigger weighted behaviour. + self._weighting_keywords = ["returned", "weights"] + + def uses_weighting(self, **kwargs): + """ + Determine whether this aggregator uses weighting. + + Kwargs: + + * kwargs: + Arguments to filter of weighted keywords. + + Returns: + Boolean. + + """ + result = False + for kwarg in kwargs.keys(): + if kwarg in self._weighting_keywords: + result = True + break + return result + + def post_process(self, collapsed_cube, data_result, coords, **kwargs): """ Process the result from :func:`iris.analysis.Aggregator.aggregate`. - Ensures data is an array, when collapsed to a single value. + Returns a tuple(cube, weights) if a tuple(data, weights) was returned + from :func:`iris.analysis.Aggregator.aggregate`. Args: - * collapsed_cube + * collapsed_cube: A :class:`iris.cube.Cube`. - * data_result + * data_result: Result from :func:`iris.analysis.Aggregator.aggregate` + * coords: + The one or more coordinates that were aggregated over. + + Kwargs: + + * This function is intended to be used in conjunction with aggregate() + and should be passed the same keywords (for example, the "weights" + keywords from a mean aggregator). + + Returns: + The collapsed cube with it's aggregated data payload. Or a tuple + pair of (cube, weights) if the keyword "returned" is specified + and True. """ - if isinstance(data_result, biggus.Array): - collapsed_cube.lazy_data(data_result) + if kwargs.get('returned', False): + # Package the data into the cube and return a tuple + collapsed_cube.data, collapsed_weights = data_result + result = (collapsed_cube, collapsed_weights) else: - collapsed_cube.data = iris.util.ensure_array(data_result) - return collapsed_cube + result = Aggregator.post_process(self, collapsed_cube, + data_result, coords, **kwargs) + return result -class WeightedAggregator(Aggregator): - def __init__(self, cell_method, call_func, **kwargs): - Aggregator.__init__(self, cell_method, call_func, **kwargs) +def _build_dask_mdtol_function(dask_stats_function): + """ + Make a wrapped dask statistic function that supports the 'mdtol' keyword. + + 'dask_function' must be a dask statistical function, compatible with the + call signature : "dask_stats_function(data, axis=axis, **kwargs)". + It must be masked-data tolerant, i.e. it ignores masked input points and + performs a calculation on only the unmasked points. + For example, mean([1, --, 2]) = (1 + 2) / 2 = 1.5. + + The returned value is a new function operating on dask arrays. + It has the call signature `stat(data, axis=-1, mdtol=None, **kwargs)`. + + """ + @wraps(dask_stats_function) + def inner_stat(array, axis=-1, mdtol=None, **kwargs): + # Call the statistic to get the basic result (missing-data tolerant). + dask_result = dask_stats_function(array, axis=axis, **kwargs) + if mdtol is None or mdtol >= 1.0: + result = dask_result + else: + # Build a lazy computation to compare the fraction of missing + # input points at each output point to the 'mdtol' threshold. + point_mask_counts = da.sum(da.ma.getmaskarray(array), axis=axis) + points_per_calc = array.size / dask_result.size + masked_point_fractions = point_mask_counts / points_per_calc + boolean_mask = masked_point_fractions > mdtol + # Return an mdtol-masked version of the basic result. + result = da.ma.masked_array(da.ma.getdata(dask_result), + boolean_mask) + return result + return inner_stat + + +def _percentile(data, axis, percent, fast_percentile_method=False, + **kwargs): + """ + The percentile aggregator is an additive operation. This means that + it *may* introduce a new dimension to the data for the statistic being + calculated, but only if more than one percentile point is requested. + + If a new additive dimension is formed, then it will always be the last + dimension of the resulting percentile data payload. + + Kwargs: + + * fast_percentile_method (boolean) : + When set to True, uses the numpy.percentiles method as a faster + alternative to the scipy.mstats.mquantiles method. Does not handle + masked arrays. + + """ + # Ensure that the target axis is the last dimension. + data = np.rollaxis(data, axis, start=data.ndim) + shape = data.shape[:-1] + # Flatten any leading dimensions. + if shape: + data = data.reshape([np.prod(shape), data.shape[-1]]) + # Perform the percentile calculation. + if fast_percentile_method: + msg = 'Cannot use fast np.percentile method with masked array.' + if ma.isMaskedArray(data): + raise TypeError(msg) + result = np.percentile(data, percent, axis=-1) + result = result.T + else: + quantiles = np.array(percent) / 100. + result = scipy.stats.mstats.mquantiles(data, quantiles, axis=-1, + **kwargs) + if not ma.isMaskedArray(data) and not ma.is_masked(result): + result = np.asarray(result) + + # Ensure to unflatten any leading dimensions. + if shape: + if not isinstance(percent, collections.Iterable): + percent = [percent] + percent = np.array(percent) + # Account for the additive dimension. + if percent.shape > (1,): + shape += percent.shape + result = result.reshape(shape) + # Check whether to reduce to a scalar result, as per the behaviour + # of other aggregators. + if result.shape == (1,) and quantiles.ndim == 0: + result = result[0] + + return result + + +def _weighted_quantile_1D(data, weights, quantiles, **kwargs): + """ + Compute the weighted quantile of a 1D numpy array. + + Adapted from `wquantiles `_ + + Args: + + * data (array) + One dimensional data array + * weights (array) + Array of the same size of `data`. If data is masked, weights must have + matching mask. + * quantiles : (float or sequence of floats) + Quantile(s) to compute. Must have a value between 0 and 1. + + **kwargs + passed to `scipy.interpolate.interp1d` + + Returns: + array or float. Calculated quantile values (set to np.nan wherever sum + of weights is zero or masked) + """ + # Return np.nan if no useable points found + if np.isclose(weights.sum(), 0.) or ma.is_masked(weights.sum()): + return np.resize(np.array(np.nan), len(quantiles)) + # Sort the data + ind_sorted = ma.argsort(data) + sorted_data = data[ind_sorted] + sorted_weights = weights[ind_sorted] + # Compute the auxiliary arrays + Sn = np.cumsum(sorted_weights) + Pn = (Sn-0.5*sorted_weights)/np.sum(sorted_weights) + # Get the value of the weighted quantiles + interpolator = scipy.interpolate.interp1d(Pn, sorted_data, + bounds_error=False, **kwargs) + result = interpolator(quantiles) + # Set cases where quantile falls outside data range to min or max + np.place(result, Pn.min() > quantiles, sorted_data.min()) + np.place(result, Pn.max() < quantiles, sorted_data.max()) + + return result - #: A list of keywords that trigger weighted behaviour. - self._weighting_keywords = ["returned", "weights"] - def uses_weighting(self, **kwargs): - """Does this aggregator use weighting with the given keywords?""" - result = False - for kwarg in kwargs.keys(): - if kwarg in self._weighting_keywords: - result = True - break - return result +def _weighted_percentile(data, axis, weights, percent, returned=False, + **kwargs): + """ + The weighted_percentile aggregator is an additive operation. This means + that it *may* introduce a new dimension to the data for the statistic being + calculated, but only if more than one percentile point is requested. - def post_process(self, collapsed_cube, data_result, **kwargs): - """ - Process the result from :func:`iris.analysis.Aggregator.aggregate`. + If a new additive dimension is formed, then it will always be the last + dimension of the resulting percentile data payload. - Ensures data is an array, when collapsed to a single value. - Returns a tuple(cube, weights) if a tuple(data, weights) was returned - from :func:`iris.analysis.Aggregator.aggregate`. + Args: - Args: + * data: ndarray or masked array - * collapsed_cube - A :class:`iris.cube.Cube`. - * data_result - Result from :func:`iris.analysis.Aggregator.aggregate` + * axis: int + axis to calculate percentiles over - """ - if kwargs.get('returned', False): - # Package the data into the cube and return a tuple - collapsed_cube.data, collapsed_weights = data_result - collapsed_cube.data = iris.util.ensure_array(collapsed_cube.data) - result = (collapsed_cube, collapsed_weights) - else: - result = Aggregator.post_process(self, collapsed_cube, - data_result, **kwargs) + * weights: ndarray + array with the weights. Must have same shape as data - return result + * percent: float or sequence of floats + Percentile rank/s at which to extract value/s. + * returned: bool, optional + Default False. If True, returns a tuple with the percentiles as the + first element and the sum of the weights as the second element. -def _percentile(data, axis, percent, **kwargs): - # NB. scipy.stats.mstats.scoreatpercentile always works across just the - # first dimension of its input data, and returns a result that has one - # fewer dimension than the input. - # So shape=(3, 4, 5) -> shape(4, 5) - data = np.rollaxis(data, axis) - shape = data.shape[1:] + """ + # Ensure that data and weights arrays are same shape. + if data.shape != weights.shape: + raise ValueError('_weighted_percentile: weights wrong shape.') + # Ensure that the target axis is the last dimension. + data = np.rollaxis(data, axis, start=data.ndim) + weights = np.rollaxis(weights, axis, start=data.ndim) + quantiles = np.array(percent) / 100. + # Add data mask to weights if necessary. + if ma.isMaskedArray(data): + weights = ma.array(weights, mask=data.mask) + shape = data.shape[:-1] + # Flatten any leading dimensions and loop over them if shape: - data = data.reshape([data.shape[0], np.prod(shape)]) - result = scipy.stats.mstats.scoreatpercentile(data, percent, **kwargs) + data = data.reshape([np.prod(shape), data.shape[-1]]) + weights = weights.reshape([np.prod(shape), data.shape[-1]]) + result = np.empty((np.prod(shape), quantiles.size)) + # Perform the percentile calculation. + for res, dat, wt in zip(result, data, weights): + res[:] = _weighted_quantile_1D(dat, wt, quantiles, **kwargs) + else: + # Data is 1D + result = _weighted_quantile_1D(data, weights, quantiles, **kwargs) + + if np.any(np.isnan(result)): + result = ma.masked_invalid(result) + if not ma.isMaskedArray(data) and not ma.is_masked(result): result = np.asarray(result) + + # Ensure to unflatten any leading dimensions. if shape: + if not isinstance(percent, collections.Iterable): + percent = [percent] + percent = np.array(percent) + # Account for the additive dimension. + if percent.shape > (1,): + shape += percent.shape result = result.reshape(shape) - return result + # Check whether to reduce to a scalar result, as per the behaviour + # of other aggregators. + if result.shape == (1,) and quantiles.ndim == 0: + result = result[0] + + if returned: + return result, weights.sum(axis=-1) + else: + return result -def _count(array, function, axis, **kwargs): - if not callable(function): - raise ValueError('function must be a callable. Got %s.' - % type(function)) - return ma.sum(function(array), axis=axis, **kwargs) +@_build_dask_mdtol_function +def _lazy_count(array, **kwargs): + array = iris._lazy_data.as_lazy_data(array) + func = kwargs.pop('function', None) + if not callable(func): + emsg = 'function must be a callable. Got {}.' + raise TypeError(emsg.format(type(func))) + return da.sum(func(array), **kwargs) def _proportion(array, function, axis, **kwargs): + count = iris._lazy_data.non_lazy(_lazy_count) # if the incoming array is masked use that to count the total number of # values - if isinstance(array, ma.MaskedArray): + if ma.isMaskedArray(array): # calculate the total number of non-masked values across the given axis - total_non_masked = _count(array.mask, np.logical_not, - axis=axis, **kwargs) + total_non_masked = count( + array.mask, axis=axis, function=np.logical_not, **kwargs) total_non_masked = ma.masked_equal(total_non_masked, 0) else: total_non_masked = array.shape[axis] - return _count(array, function, axis=axis, **kwargs) / total_non_masked + # Sanitise the result of this operation thru ma.asarray to ensure that + # the dtype of the fill-value and the dtype of the array are aligned. + # Otherwise, it is possible for numpy to return a masked array that has + # a dtype for its data that is different to the dtype of the fill-value, + # which can cause issues outside this function. + # Reference - tests/unit/analyis/test_PROPORTION.py Test_masked.test_ma + numerator = count(array, axis=axis, function=function, **kwargs) + result = ma.asarray(numerator / total_non_masked) + + return result def _rms(array, axis, **kwargs): @@ -615,21 +1266,23 @@ def _rms(array, axis, **kwargs): return rval -def _sum(array, **kwargs): +@_build_dask_mdtol_function +def _lazy_sum(array, **kwargs): + array = iris._lazy_data.as_lazy_data(array) # weighted or scaled sum axis_in = kwargs.get('axis', None) weights_in = kwargs.pop('weights', None) returned_in = kwargs.pop('returned', False) if weights_in is not None: - wsum = ma.sum(weights_in * array, **kwargs) + wsum = da.sum(weights_in * array, **kwargs) else: - wsum = ma.sum(array, **kwargs) + wsum = da.sum(array, **kwargs) if returned_in: if weights_in is None: - weights = np.ones_like(array) + weights = iris._lazy_data.as_lazy_data(np.ones_like(array)) else: weights = weights_in - rvalue = (wsum, ma.sum(weights, axis=axis_in)) + rvalue = (wsum, da.sum(weights, axis=axis_in)) else: rvalue = wsum return rvalue @@ -717,7 +1370,7 @@ def interp_order(length): column_peaks.append(column[0]) continue - tck = scipy.interpolate.splrep(range(column.size), column, k=k) + tck = scipy.interpolate.splrep(np.arange(column.size), column, k=k) npoints = column.size * 100 points = np.linspace(0, column.size - 1, npoints) spline = scipy.interpolate.splev(points, tck) @@ -739,43 +1392,61 @@ def interp_order(length): # # Common partial Aggregation class constructors. # -COUNT = Aggregator('count', _count, lambda units: 1) +COUNT = Aggregator('count', iris._lazy_data.non_lazy(_lazy_count), + units_func=lambda units: 1, + lazy_func=_lazy_count) """ -The number of data that match the given function. +An :class:`~iris.analysis.Aggregator` instance that counts the number +of :class:`~iris.cube.Cube` data occurrences that satisfy a particular +criterion, as defined by a user supplied *function*. -Args: +**Required** kwargs associated with the use of this aggregator: -* function: +* function (callable): A function which converts an array of data values into a corresponding array of True/False values. -For example, the number of ensembles with precipitation exceeding 10 +**For example**: + +To compute the number of *ensemble members* with precipitation exceeding 10 (in cube data units) could be calculated with:: result = precip_cube.collapsed('ensemble_member', iris.analysis.COUNT, function=lambda values: values > 10) -.. seealso:: :func:`iris.analysis.PROPORTION` +.. seealso:: The :func:`~iris.analysis.PROPORTION` aggregator. + +This aggregator handles masked data. """ GMEAN = Aggregator('geometric_mean', scipy.stats.mstats.gmean) """ -The geometric mean, as computed by :func:`scipy.stats.mstats.gmean`. +An :class:`~iris.analysis.Aggregator` instance that calculates the +geometric mean over a :class:`~iris.cube.Cube`, as computed by +:func:`scipy.stats.mstats.gmean`. -For example, to compute zonal geometric means:: +**For example**: + +To compute zonal geometric means over the *longitude* axis of a cube:: result = cube.collapsed('longitude', iris.analysis.GMEAN) +This aggregator handles masked data. + """ HMEAN = Aggregator('harmonic_mean', scipy.stats.mstats.hmean) """ -The harmonic mean, as computed by :func:`scipy.stats.mstats.hmean`. +An :class:`~iris.analysis.Aggregator` instance that calculates the +harmonic mean over a :class:`~iris.cube.Cube`, as computed by +:func:`scipy.stats.mstats.hmean`. -For example, to compute zonal harmonic means:: +**For example**: + +To compute zonal harmonic mean over the *longitude* axis of a cube:: result = cube.collapsed('longitude', iris.analysis.HMEAN) @@ -784,244 +1455,356 @@ def interp_order(length): The harmonic mean is only valid if all data values are greater than zero. +This aggregator handles masked data. + """ -MAX = Aggregator('maximum', ma.max) +MEAN = WeightedAggregator('mean', ma.average, + lazy_func=_build_dask_mdtol_function(da.mean)) """ -The maximum, as computed by :func:`numpy.ma.max`. +An :class:`~iris.analysis.Aggregator` instance that calculates +the mean over a :class:`~iris.cube.Cube`, as computed by +:func:`numpy.ma.average`. + +Additional kwargs associated with the use of this aggregator: + +* mdtol (float): + Tolerance of missing data. The value returned in each element of the + returned array will be masked if the fraction of masked data contributing + to that element exceeds mdtol. This fraction is calculated based on the + number of masked elements. mdtol=0 means no missing data is tolerated + while mdtol=1 means the resulting element will be masked if and only if + all the contributing elements are masked. Defaults to 1. +* weights (float ndarray): + Weights matching the shape of the cube or the length of the window + for rolling window operations. Note that, latitude/longitude area + weights can be calculated using + :func:`iris.analysis.cartography.area_weights`. +* returned (boolean): + Set this to True to indicate that the collapsed weights are to be + returned along with the collapsed data. Defaults to False. -For example, to compute zonal maximums:: +**For example**: - result = cube.collapsed('longitude', iris.analysis.MAX) +To compute zonal means over the *longitude* axis of a cube:: -""" + result = cube.collapsed('longitude', iris.analysis.MEAN) +To compute a weighted area average:: -MEAN = WeightedAggregator('mean', ma.average, lazy_func=biggus.mean) -""" -The mean, as computed by :func:`numpy.ma.average`. + coords = ('longitude', 'latitude') + collapsed_cube, collapsed_weights = cube.collapsed(coords, + iris.analysis.MEAN, + weights=weights, + returned=True) -For example, to compute zonal means:: +.. note:: - result = cube.collapsed('longitude', iris.analysis.MEAN) + Lazy operation is supported, via :func:`dask.array.nanmean`. -Additional kwargs available: +This aggregator handles masked data. -* weights - Optional array of floats. If supplied, the shape must match the cube. +""" - LatLon area weights can be calculated using - :func:`iris.analysis.cartography.area_weights`. -* returned - Set this to True to indicate the collapsed weights are to be returned - along with the collapsed data. Defaults to False. -For example:: +MEDIAN = Aggregator('median', ma.median) +""" +An :class:`~iris.analysis.Aggregator` instance that calculates +the median over a :class:`~iris.cube.Cube`, as computed by +:func:`numpy.ma.median`. - cube_out, weights_out = cube_in.collapsed(coord_names, iris.analysis.MEAN, - weights=weights_in, returned=True) +**For example**: -.. note:: - Lazy operation is supported, via :func:`biggus.mean`. +To compute zonal medians over the *longitude* axis of a cube:: - For example:: + result = cube.collapsed('longitude', iris.analysis.MEDIAN) - cube.collapsed('x', MEAN, lazy=True) +This aggregator handles masked data. """ -MEDIAN = Aggregator('median', ma.median) +MIN = Aggregator('minimum', ma.min, + lazy_func=_build_dask_mdtol_function(da.min)) """ -The median, as computed by :func:`numpy.ma.median`. +An :class:`~iris.analysis.Aggregator` instance that calculates +the minimum over a :class:`~iris.cube.Cube`, as computed by +:func:`numpy.ma.min`. -For example, to compute zonal medians:: +**For example**: - result = cube.collapsed('longitude', iris.analysis.MEDIAN) +To compute zonal minimums over the *longitude* axis of a cube:: + + result = cube.collapsed('longitude', iris.analysis.MIN) + +This aggregator handles masked data. """ -MIN = Aggregator('minimum', ma.min) +MAX = Aggregator('maximum', ma.max, + lazy_func=_build_dask_mdtol_function(da.max)) """ -The minimum, as computed by :func:`numpy.ma.min`. +An :class:`~iris.analysis.Aggregator` instance that calculates +the maximum over a :class:`~iris.cube.Cube`, as computed by +:func:`numpy.ma.max`. -For example, to compute zonal minimums:: +**For example**: - result = cube.collapsed('longitude', iris.analysis.MIN) +To compute zonal maximums over the *longitude* axis of a cube:: + + result = cube.collapsed('longitude', iris.analysis.MAX) + +This aggregator handles masked data. """ PEAK = Aggregator('peak', _peak) """ -The global peak value, from a spline interpolation of the cube data, -along the coordinate axis. +An :class:`~iris.analysis.Aggregator` instance that calculates +the peak value derived from a spline interpolation over a +:class:`~iris.cube.Cube`. -The peak calculation takes into account nan values, therefore if the number +The peak calculation takes into account nan values. Therefore, if the number of non-nan values is zero the result itself will be an array of nan values. -The peak calculation also takes into account masked values, therefore if the +The peak calculation also takes into account masked values. Therefore, if the number of non-masked values is zero the result itself will be a masked array. -If multiple coordinates are to be collapsed, the peak calculations are +If multiple coordinates are specified, then the peak calculations are performed individually, in sequence, for each coordinate specified. -For example, to compute the peak over time:: +**For example**: + +To compute the peak over the *time* axis of a cube:: result = cube.collapsed('time', iris.analysis.PEAK) +This aggregator handles masked data. + """ -PERCENTILE = Aggregator('percentile ({percent}%)', - _percentile, - alphap=1, - betap=1) +PERCENTILE = PercentileAggregator(alphap=1, betap=1) """ -The percentile, as computed by :func:`scipy.stats.mstats.scoreatpercentile`. +An :class:`~iris.analysis.PercentileAggregator` instance that calculates the +percentile over a :class:`~iris.cube.Cube`, as computed by +:func:`scipy.stats.mstats.mquantiles`. -Required kwargs: +**Required** kwargs associated with the use of this aggregator: -* percent: - Percentile rank at which to extract value. No default. +* percent (float or sequence of floats): + Percentile rank/s at which to extract value/s. -For example, to compute the 90th percentile over time:: +Additional kwargs associated with the use of this aggregator: - result = cube.collapsed('time', iris.analysis.PERCENTILE, percent=90) +* alphap (float): + Plotting positions parameter, see :func:`scipy.stats.mstats.mquantiles`. + Defaults to 1. +* betap (float): + Plotting positions parameter, see :func:`scipy.stats.mstats.mquantiles`. + Defaults to 1. -.. note:: +**For example**: - The default values of ``alphap`` and ``betap`` are both 1. For detailed - meanings on these values see :func:`scipy.stats.mstats.mquantiles`. +To compute the 10th and 90th percentile over *time*:: -""" + result = cube.collapsed('time', iris.analysis.PERCENTILE, percent=[10, 90]) +This aggregator handles masked data. -PROPORTION = Aggregator('proportion', _proportion, lambda units: 1) """ -The proportion, as a decimal, of data that match the given function. -The proportion calculation takes into account masked values, therefore if the -number of non-masked values is zero the result itself will be a masked array. -Args: +PROPORTION = Aggregator('proportion', + _proportion, + units_func=lambda units: 1) +""" +An :class:`~iris.analysis.Aggregator` instance that calculates the +proportion, as a fraction, of :class:`~iris.cube.Cube` data occurrences +that satisfy a particular criterion, as defined by a user supplied +*function*. + +**Required** kwargs associated with the use of this aggregator: -* function: +* function (callable): A function which converts an array of data values into a corresponding array of True/False values. -For example, the probability of precipitation exceeding 10 -(in cube data units) across ensemble members could be calculated with:: +**For example**: + +To compute the probability of precipitation exceeding 10 +(in cube data units) across *ensemble members* could be calculated with:: result = precip_cube.collapsed('ensemble_member', iris.analysis.PROPORTION, function=lambda values: values > 10) -Similarly, the proportion of times precipitation exceeded 10 +Similarly, the proportion of *time* precipitation exceeded 10 (in cube data units) could be calculated with:: result = precip_cube.collapsed('time', iris.analysis.PROPORTION, function=lambda values: values > 10) -.. seealso:: :func:`iris.analysis.COUNT` +.. seealso:: The :func:`~iris.analysis.COUNT` aggregator. + +This aggregator handles masked data. """ RMS = WeightedAggregator('root mean square', _rms) """ -The root mean square, as computed by +An :class:`~iris.analysis.Aggregator` instance that calculates +the root mean square over a :class:`~iris.cube.Cube`, as computed by ((x0**2 + x1**2 + ... + xN-1**2) / N) ** 0.5. -For example, to compute zonal root mean square:: +Additional kwargs associated with the use of this aggregator: - result = cube.collapsed('longitude', iris.analysis.RMS) +* weights (float ndarray): + Weights matching the shape of the cube or the length of the window for + rolling window operations. The weights are applied to the squares when + taking the mean. -Additional kwargs available: +**For example**: -* weights - Optional array of floats. If supplied, the shape must match the - cube. The weights are applied to the squares when taking the mean. +To compute the zonal root mean square over the *longitude* axis of a cube:: + + result = cube.collapsed('longitude', iris.analysis.RMS) + +This aggregator handles masked data. """ -STD_DEV = Aggregator('standard_deviation', ma.std, ddof=1) +STD_DEV = Aggregator('standard_deviation', ma.std, ddof=1, + lazy_func=_build_dask_mdtol_function(da.std)) """ -The standard deviation, as computed by :func:`numpy.ma.std`. +An :class:`~iris.analysis.Aggregator` instance that calculates +the standard deviation over a :class:`~iris.cube.Cube`, as +computed by :func:`numpy.ma.std`. + +Additional kwargs associated with the use of this aggregator: -For example, to compute zonal standard deviations:: +* ddof (integer): + Delta degrees of freedom. The divisor used in calculations is N - ddof, + where N represents the number of elements. Defaults to 1. + +**For example**: + +To compute zonal standard deviations over the *longitude* axis of a cube:: result = cube.collapsed('longitude', iris.analysis.STD_DEV) -Additional kwargs available: +To obtain the biased standard deviation:: -* ddof: - Delta degrees of freedom. The divisor used in calculations is N - ddof, - where N represents the number of elements. By default ddof is one. + result = cube.collapsed('longitude', iris.analysis.STD_DEV, ddof=0) -For example, to obtain the biased standard deviation:: +.. note:: + + Lazy operation is supported, via :func:`dask.array.nanstd`. - result = cube.collapsed(coord_to_collapse, iris.analysis.STD_DEV, ddof=0) +This aggregator handles masked data. """ -SUM = WeightedAggregator('sum', _sum) +SUM = WeightedAggregator('sum', iris._lazy_data.non_lazy(_lazy_sum), + lazy_func=_build_dask_mdtol_function(_lazy_sum)) """ -The sum of a dataset, as computed by :func:`numpy.ma.sum`. +An :class:`~iris.analysis.Aggregator` instance that calculates +the sum over a :class:`~iris.cube.Cube`, as computed by :func:`numpy.ma.sum`. -For example, to compute an accumulation over time:: +Additional kwargs associated with the use of this aggregator: - result = cube.collapsed('time', iris.analysis.SUM) +* weights (float ndarray): + Weights matching the shape of the cube, or the length of + the window for rolling window operations. Weights should be + normalized before using them with this aggregator if scaling + is not intended. +* returned (boolean): + Set this to True to indicate the collapsed weights are to be returned + along with the collapsed data. Defaults to False. -Additional kwargs available: +**For example**: -* weights - Optional array of floats. If supplied, the shape must match the - shape of the cube for collapsing, or the length of the window for - rolling window operations. +To compute an accumulation over the *time* axis of a cube:: -* returned - Set this to True to indicate the collapsed weights are to be returned - along with the collapsed data. Defaults to False. + result = cube.collapsed('time', iris.analysis.SUM) -For example to compute a weighted rolling sum -(e.g., to apply a digital filter):: +To compute a weighted rolling sum e.g. to apply a digital filter:: weights = np.array([.1, .2, .4, .2, .1]) result = cube.rolling_window('time', iris.analysis.SUM, len(weights), weights=weights) +This aggregator handles masked data. + """ -VARIANCE = Aggregator('variance', ma.var, lambda units: units * units, - lazy_func=biggus.var, ddof=1) +VARIANCE = Aggregator('variance', + ma.var, + units_func=lambda units: units * units, + lazy_func=_build_dask_mdtol_function(da.var), + ddof=1) """ -The variance, as computed by :func:`numpy.ma.var`. +An :class:`~iris.analysis.Aggregator` instance that calculates +the variance over a :class:`~iris.cube.Cube`, as computed by +:func:`numpy.ma.var`. -For example, to compute zonal variance:: +Additional kwargs associated with the use of this aggregator: - result = cube.collapsed('longitude', iris.analysis.VARIANCE) +* ddof (integer): + Delta degrees of freedom. The divisor used in calculations is N - ddof, + where N represents the number of elements. Defaults to 1. -Additional kwargs available: +**For example**: -* ddof: - Delta degrees of freedom. The divisor used in calculations is N - ddof, - where N represents the number of elements. By default ddof is one. +To compute zonal variance over the *longitude* axis of a cube:: -For example, to obtain the biased variance:: + result = cube.collapsed('longitude', iris.analysis.VARIANCE) + +To obtain the biased variance:: - result = cube.collapsed(coord_to_collapse, iris.analysis.VARIANCE, ddof=0) + result = cube.collapsed('longitude', iris.analysis.VARIANCE, ddof=0) .. note:: - Lazy operation is supported, via :func:`biggus.var`. - For example:: + Lazy operation is supported, via :func:`dask.array.nanvar`. + +This aggregator handles masked data. + +""" + + +WPERCENTILE = WeightedPercentileAggregator() +""" +An :class:`~iris.analysis.WeightedPercentileAggregator` instance that +calculates the weighted percentile over a :class:`~iris.cube.Cube`. + +**Required** kwargs associated with the use of this aggregator: + +* percent (float or sequence of floats): + Percentile rank/s at which to extract value/s. + +* weights (float ndarray): + Weights matching the shape of the cube or the length of the window + for rolling window operations. Note that, latitude/longitude area + weights can be calculated using + :func:`iris.analysis.cartography.area_weights`. + +Additional kwargs associated with the use of this aggregator: + +* returned (boolean): + Set this to True to indicate that the collapsed weights are to be + returned along with the collapsed data. Defaults to False. - cube.collapsed('x', VARIANCE, lazy=True) +* kind (string or int): + Specifies the kind of interpolation used, see + :func:`scipy.interpolate.interp1d` Defaults to "linear", which is + equivalent to alphap=0.5, betap=0.5 in `iris.analysis.PERCENTILE` """ @@ -1123,7 +1906,7 @@ def group(self): for coord in self._groupby_coords: groups.append(iris.coords._GroupIterator(coord.points)) - items.append(groups[-1].next()) + items.append(next(groups[-1])) # Construct the group slice for each group over the group-by # coordinates. Keep constructing until all group-by coordinate @@ -1137,7 +1920,7 @@ def group(self): if item is not None]) # Construct composite group key for the group using the # start value from each group-by coordinate. - key = tuple([coord._points[start] for coord + key = tuple([coord.points[start] for coord in self._groupby_coords]) # Associate group slice with group key within the ordered # dictionary. @@ -1160,7 +1943,7 @@ def group(self): elif groupby_slice.stop == stop: # The current group of this coordinate is # exhausted, so get the next one. - items[item_index] = groups[item_index].next() + items[item_index] = next(groups[item_index]) # Merge multiple slices together into one tuple. self._slice_merge() @@ -1169,7 +1952,7 @@ def group(self): # Calculate the new shared coordinates. self._compute_shared_coords() # Generate the group-by slices/groups. - for groupby_slice in self._slices_by_key.itervalues(): + for groupby_slice in six.itervalues(self._slices_by_key): yield groupby_slice return @@ -1183,7 +1966,7 @@ def _slice_merge(self): # Iterate over the ordered dictionary in order to reduce # multiple slices into a single tuple and collapse # all items from containing list. - for key, groupby_slices in self._slices_by_key.iteritems(): + for key, groupby_slices in six.iteritems(self._slices_by_key): if len(groupby_slices) > 1: # Compress multiple slices into tuple representation. groupby_indicies = [] @@ -1204,7 +1987,7 @@ def _compute_groupby_coords(self): # Iterate over the ordered dictionary in order to construct # a group-by slice that samples the first element from each group. - for key_slice in self._slices_by_key.itervalues(): + for key_slice in six.itervalues(self._slices_by_key): if isinstance(key_slice, tuple): groupby_slice.append(key_slice[0]) else: @@ -1222,7 +2005,7 @@ def _compute_shared_coords(self): # Iterate over the ordered dictionary in order to construct # a list of tuple group boundary indexes. - for key_slice in self._slices_by_key.itervalues(): + for key_slice in six.itervalues(self._slices_by_key): if isinstance(key_slice, tuple): groupby_bounds.append((key_slice[0], key_slice[-1])) else: @@ -1230,12 +2013,16 @@ def _compute_shared_coords(self): # Create new shared bounded coordinates. for coord in self._shared_coords: - if coord.points.dtype.kind == 'S': + if coord.points.dtype.kind in 'SU': if coord.bounds is None: new_points = [] new_bounds = None - for key_slice in self._slices_by_key.itervalues(): - new_pt = '|'.join(coord.points[i] for i in key_slice) + for key_slice in six.itervalues(self._slices_by_key): + if isinstance(key_slice, slice): + indices = key_slice.indices(coord.points.shape[0]) + key_slice = range(*indices) + new_pt = '|'.join([coord.points[i] + for i in key_slice]) new_points.append(new_pt) else: msg = ('collapsing the bounded string coordinate {0!r}' @@ -1315,3 +2102,406 @@ def clear_phenomenon_identity(cube): cube.rename(None) cube.attributes.clear() cube.cell_methods = tuple() + + +############################################################################### +# +# Interpolation API +# +############################################################################### + +class Linear(object): + """ + This class describes the linear interpolation and regridding scheme for + interpolating or regridding over one or more orthogonal coordinates, + typically for use with :meth:`iris.cube.Cube.interpolate()` or + :meth:`iris.cube.Cube.regrid()`. + + """ + + LINEAR_EXTRAPOLATION_MODES = list(EXTRAPOLATION_MODES.keys()) + ['linear'] + + def __init__(self, extrapolation_mode='linear'): + """ + Linear interpolation and regridding scheme suitable for interpolating + or regridding over one or more orthogonal coordinates. + + Kwargs: + + * extrapolation_mode: + Must be one of the following strings: + + * 'extrapolate' or 'linear' - The extrapolation points + will be calculated by extending the gradient of the + closest two points. + * 'nan' - The extrapolation points will be be set to NaN. + * 'error' - A ValueError exception will be raised, notifying an + attempt to extrapolate. + * 'mask' - The extrapolation points will always be masked, even + if the source data is not a MaskedArray. + * 'nanmask' - If the source data is a MaskedArray the + extrapolation points will be masked. Otherwise they will be + set to NaN. + + The default mode of extrapolation is 'linear'. + + """ + if extrapolation_mode not in self.LINEAR_EXTRAPOLATION_MODES: + msg = 'Extrapolation mode {!r} not supported.' + raise ValueError(msg.format(extrapolation_mode)) + self.extrapolation_mode = extrapolation_mode + + def __repr__(self): + return 'Linear({!r})'.format(self.extrapolation_mode) + + def _normalised_extrapolation_mode(self): + mode = self.extrapolation_mode + if mode == 'linear': + mode = 'extrapolate' + return mode + + def interpolator(self, cube, coords): + """ + Creates a linear interpolator to perform interpolation over the + given :class:`~iris.cube.Cube` specified by the dimensions of + the given coordinates. + + Typically you should use :meth:`iris.cube.Cube.interpolate` for + interpolating a cube. There are, however, some situations when + constructing your own interpolator is preferable. These are detailed + in the :ref:`user guide `. + + Args: + + * cube: + The source :class:`iris.cube.Cube` to be interpolated. + * coords: + The names or coordinate instances that are to be + interpolated over. + + Returns: + A callable with the interface: + + `callable(sample_points, collapse_scalar=True)` + + where `sample_points` is a sequence containing an array of values + for each of the coordinates passed to this method, and + `collapse_scalar` determines whether to remove length one + dimensions in the result cube caused by scalar values in + `sample_points`. + + The values for coordinates that correspond to date/times + may optionally be supplied as datetime.datetime or + cftime.datetime instances. + + For example, for the callable returned by: + `Linear().interpolator(cube, ['latitude', 'longitude'])`, + sample_points must have the form + `[new_lat_values, new_lon_values]`. + + """ + return RectilinearInterpolator(cube, coords, 'linear', + self._normalised_extrapolation_mode()) + + def regridder(self, src_grid, target_grid): + """ + Creates a linear regridder to perform regridding from the source + grid to the target grid. + + Typically you should use :meth:`iris.cube.Cube.regrid` for + regridding a cube. There are, however, some situations when + constructing your own regridder is preferable. These are detailed in + the :ref:`user guide `. + + Args: + + * src_grid: + The :class:`~iris.cube.Cube` defining the source grid. + * target_grid: + The :class:`~iris.cube.Cube` defining the target grid. + + Returns: + A callable with the interface: + + `callable(cube)` + + where `cube` is a cube with the same grid as `src_grid` + that is to be regridded to the `target_grid`. + + """ + return RectilinearRegridder(src_grid, target_grid, 'linear', + self._normalised_extrapolation_mode()) + + +class AreaWeighted(object): + """ + This class describes an area-weighted regridding scheme for regridding + between 'ordinary' horizontal grids with separated X and Y coordinates in a + common coordinate system. + Typically for use with :meth:`iris.cube.Cube.regrid()`. + + """ + + def __init__(self, mdtol=1): + """ + Area-weighted regridding scheme suitable for regridding between + different orthogonal XY grids in the same coordinate system. + + Kwargs: + + * mdtol (float): + Tolerance of missing data. The value returned in each element of + the returned array will be masked if the fraction of missing data + exceeds mdtol. This fraction is calculated based on the area of + masked cells within each target cell. mdtol=0 means no masked + data is tolerated while mdtol=1 will mean the resulting element + will be masked if and only if all the overlapping elements of the + source grid are masked. Defaults to 1. + + .. Note: + Both sourge and target cubes must have an XY grid defined by + separate X and Y dimensions with dimension coordinates. + All of the XY dimension coordinates must also be bounded, and have + the same cooordinate system. + + """ + if not (0 <= mdtol <= 1): + msg = 'Value for mdtol must be in range 0 - 1, got {}.' + raise ValueError(msg.format(mdtol)) + self.mdtol = mdtol + + def __repr__(self): + return 'AreaWeighted(mdtol={})'.format(self.mdtol) + + def regridder(self, src_grid_cube, target_grid_cube): + """ + Creates an area-weighted regridder to perform regridding from the + source grid to the target grid. + + Typically you should use :meth:`iris.cube.Cube.regrid` for + regridding a cube. There are, however, some situations when + constructing your own regridder is preferable. These are detailed in + the :ref:`user guide `. + + Args: + + * src_grid_cube: + The :class:`~iris.cube.Cube` defining the source grid. + * target_grid_cube: + The :class:`~iris.cube.Cube` defining the target grid. + + Returns: + A callable with the interface: + + `callable(cube)` + + where `cube` is a cube with the same grid as `src_grid_cube` + that is to be regridded to the grid of `target_grid_cube`. + + """ + return AreaWeightedRegridder(src_grid_cube, target_grid_cube, + mdtol=self.mdtol) + + +class Nearest(object): + """ + This class describes the nearest-neighbour interpolation and regridding + scheme for interpolating or regridding over one or more orthogonal + coordinates, typically for use with :meth:`iris.cube.Cube.interpolate()` + or :meth:`iris.cube.Cube.regrid()`. + + """ + def __init__(self, extrapolation_mode='extrapolate'): + """ + Nearest-neighbour interpolation and regridding scheme suitable for + interpolating or regridding over one or more orthogonal coordinates. + + Kwargs: + + * extrapolation_mode: + Must be one of the following strings: + + * 'extrapolate' - The extrapolation points will take their + value from the nearest source point. + * 'nan' - The extrapolation points will be be set to NaN. + * 'error' - A ValueError exception will be raised, notifying an + attempt to extrapolate. + * 'mask' - The extrapolation points will always be masked, even + if the source data is not a MaskedArray. + * 'nanmask' - If the source data is a MaskedArray the + extrapolation points will be masked. Otherwise they will be + set to NaN. + + The default mode of extrapolation is 'extrapolate'. + + """ + if extrapolation_mode not in EXTRAPOLATION_MODES: + msg = 'Extrapolation mode {!r} not supported.' + raise ValueError(msg.format(extrapolation_mode)) + self.extrapolation_mode = extrapolation_mode + + def __repr__(self): + return 'Nearest({!r})'.format(self.extrapolation_mode) + + def interpolator(self, cube, coords): + """ + Creates a nearest-neighbour interpolator to perform + interpolation over the given :class:`~iris.cube.Cube` specified + by the dimensions of the specified coordinates. + + Typically you should use :meth:`iris.cube.Cube.interpolate` for + interpolating a cube. There are, however, some situations when + constructing your own interpolator is preferable. These are detailed + in the :ref:`user guide `. + + Args: + + * cube: + The source :class:`iris.cube.Cube` to be interpolated. + * coords: + The names or coordinate instances that are to be + interpolated over. + + Returns: + A callable with the interface: + + `callable(sample_points, collapse_scalar=True)` + + where `sample_points` is a sequence containing an array of values + for each of the coordinates passed to this method, and + `collapse_scalar` determines whether to remove length one + dimensions in the result cube caused by scalar values in + `sample_points`. + + The values for coordinates that correspond to date/times + may optionally be supplied as datetime.datetime or + cftime.datetime instances. + + For example, for the callable returned by: + `Nearest().interpolator(cube, ['latitude', 'longitude'])`, + sample_points must have the form + `[new_lat_values, new_lon_values]`. + + """ + return RectilinearInterpolator(cube, coords, 'nearest', + self.extrapolation_mode) + + def regridder(self, src_grid, target_grid): + """ + Creates a nearest-neighbour regridder to perform regridding from the + source grid to the target grid. + + Typically you should use :meth:`iris.cube.Cube.regrid` for + regridding a cube. There are, however, some situations when + constructing your own regridder is preferable. These are detailed in + the :ref:`user guide `. + + Args: + + * src_grid: + The :class:`~iris.cube.Cube` defining the source grid. + * target_grid: + The :class:`~iris.cube.Cube` defining the target grid. + + Returns: + A callable with the interface: + + `callable(cube)` + + where `cube` is a cube with the same grid as `src_grid` + that is to be regridded to the `target_grid`. + + """ + return RectilinearRegridder(src_grid, target_grid, 'nearest', + self.extrapolation_mode) + + +class UnstructuredNearest(object): + """ + This is a nearest-neighbour regridding scheme for regridding data whose + horizontal (X- and Y-axis) coordinates are mapped to the *same* dimensions, + rather than being orthogonal on independent dimensions. + + For latitude-longitude coordinates, the nearest-neighbour distances are + computed on the sphere, otherwise flat Euclidean distances are used. + + The source X and Y coordinates can have any shape. + + The target grid must be of the "normal" kind, i.e. it has separate, + 1-dimensional X and Y coordinates. + + Source and target XY coordinates must have the same coordinate system, + which may also be None. + If any of the XY coordinates are latitudes or longitudes, then they *all* + must be. Otherwise, the corresponding X and Y coordinates must have the + same units in the source and grid cubes. + + .. Note:: + Currently only supports regridding, not interpolation. + + .. Note:: + This scheme performs essentially the same job as + :class:`iris.experimental.regrid.ProjectedUnstructuredNearest`. + That scheme is faster, but only works well on data in a limited + region of the globe, covered by a specified projection. + This approach is more rigorously correct and can be applied to global + datasets. + + """ + # Note: the argument requirements are simply those of the underlying + # regridder class, + # :class:`iris.analysis.trajectory.UnstructuredNearestNeigbourRegridder`. + def __init__(self): + """ + Nearest-neighbour interpolation and regridding scheme suitable for + interpolating or regridding from un-gridded data such as trajectories + or other data where the X and Y coordinates share the same dimensions. + + """ + pass + + def __repr__(self): + return 'UnstructuredNearest()' + + # TODO: add interpolator usage + # def interpolator(self, cube): + + def regridder(self, src_cube, target_grid): + """ + Creates a nearest-neighbour regridder, of the + :class:`~iris.analysis.trajectory.UnstructuredNearestNeigbourRegridder` + type, to perform regridding from the source grid to the target grid. + + This can then be applied to any source data with the same structure as + the original 'src_cube'. + + Typically you should use :meth:`iris.cube.Cube.regrid` for + regridding a cube. There are, however, some situations when + constructing your own regridder is preferable. These are detailed in + the :ref:`user guide `. + + Args: + + * src_cube: + The :class:`~iris.cube.Cube` defining the source grid. + The X and Y coordinates can have any shape, but must be mapped over + the same cube dimensions. + + * target_grid: + The :class:`~iris.cube.Cube` defining the target grid. + The X and Y coordinates must be one-dimensional dimension + coordinates, mapped to different dimensions. + All other cube components are ignored. + + Returns: + A callable with the interface: + + `callable(cube)` + + where `cube` is a cube with the same grid as `src_cube` + that is to be regridded to the `target_grid`. + + """ + from iris.analysis.trajectory import \ + UnstructuredNearestNeigbourRegridder + return UnstructuredNearestNeigbourRegridder(src_cube, target_grid) diff --git a/lib/iris/analysis/_area_weighted.py b/lib/iris/analysis/_area_weighted.py new file mode 100644 index 0000000000..2c484e4626 --- /dev/null +++ b/lib/iris/analysis/_area_weighted.py @@ -0,0 +1,113 @@ +# (C) British Crown Copyright 2014 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import numpy as np + +from iris.analysis._interpolation import get_xy_dim_coords, snapshot_grid +import iris +import iris.experimental.regrid as eregrid + + +class AreaWeightedRegridder(object): + """ + This class provides support for performing area-weighted regridding. + + """ + + def __init__(self, src_grid_cube, target_grid_cube, mdtol=1): + """ + Create an area-weighted regridder for conversions between the source + and target grids. + + Args: + + * src_grid_cube: + The :class:`~iris.cube.Cube` providing the source grid. + * target_grid_cube: + The :class:`~iris.cube.Cube` providing the target grid. + + Kwargs: + + * mdtol (float): + Tolerance of missing data. The value returned in each element of + the returned array will be masked if the fraction of masked data + exceeds mdtol. mdtol=0 means no missing data is tolerated while + mdtol=1 will mean the resulting element will be masked if and only + if all the contributing elements of data are masked. + Defaults to 1. + + .. Note:: + + Both sourge and target cubes must have an XY grid defined by + separate X and Y dimensions with dimension coordinates. + All of the XY dimension coordinates must also be bounded, and have + the same cooordinate system. + + """ + # Snapshot the state of the cubes to ensure that the regridder is + # impervious to external changes to the original source cubes. + self._src_grid = snapshot_grid(src_grid_cube) + self._target_grid = snapshot_grid(target_grid_cube) + # Missing data tolerance. + if not (0 <= mdtol <= 1): + msg = 'Value for mdtol must be in range 0 - 1, got {}.' + raise ValueError(msg.format(mdtol)) + self._mdtol = mdtol + + # The need for an actual Cube is an implementation quirk caused by the + # current usage of the experimental regrid function. + self._target_grid_cube_cache = None + + @property + def _target_grid_cube(self): + if self._target_grid_cube_cache is None: + x, y = self._target_grid + data = np.empty((y.points.size, x.points.size)) + cube = iris.cube.Cube(data) + cube.add_dim_coord(y, 0) + cube.add_dim_coord(x, 1) + self._target_grid_cube_cache = cube + return self._target_grid_cube_cache + + def __call__(self, cube): + """ + Regrid this :class:`~iris.cube.Cube` onto the target grid of + this :class:`AreaWeightedRegridder`. + + The given cube must be defined with the same grid as the source + grid used to create this :class:`AreaWeightedRegridder`. + + Args: + + * cube: + A :class:`~iris.cube.Cube` to be regridded. + + Returns: + A cube defined with the horizontal dimensions of the target + and the other dimensions from this cube. The data values of + this cube will be converted to values on the new grid using + area-weighted regridding. + + """ + if get_xy_dim_coords(cube) != self._src_grid: + raise ValueError('The given cube is not defined on the same ' + 'source grid as this regridder.') + return eregrid.regrid_area_weighted_rectilinear_src_and_grid( + cube, self._target_grid_cube, mdtol=self._mdtol) diff --git a/lib/iris/analysis/_grid_angles.py b/lib/iris/analysis/_grid_angles.py new file mode 100644 index 0000000000..90876840af --- /dev/null +++ b/lib/iris/analysis/_grid_angles.py @@ -0,0 +1,451 @@ +# (C) British Crown Copyright 2010 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Code to implement vector rotation by angles, and inferring gridcell angles +from coordinate points and bounds. + +""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import numpy as np + +import cartopy.crs as ccrs +import iris + + +def _3d_xyz_from_latlon(lon, lat): + """ + Return locations of (lon, lat) in 3D space. + + Args: + + * lon, lat: (float array) + Arrays of longitudes and latitudes, in degrees. + Both the same shape. + + Returns: + + * xyz : (array, dtype=float64) + Cartesian coordinates on a unit sphere. + Shape is (3, ). + The x / y / z coordinates are in xyz[0 / 1 / 2]. + + """ + lon1 = np.deg2rad(lon).astype(np.float64) + lat1 = np.deg2rad(lat).astype(np.float64) + + x = np.cos(lat1) * np.cos(lon1) + y = np.cos(lat1) * np.sin(lon1) + z = np.sin(lat1) + + result = np.concatenate([array[np.newaxis] for array in (x, y, z)]) + + return result + + +def _latlon_from_xyz(xyz): + """ + Return arrays of lons+lats angles from xyz locations. + + Args: + + * xyz: (array) + Array of 3-D cartesian coordinates. + Shape (3, ). + x / y / z values are in xyz[0 / 1 / 2], + + Returns: + + * lonlat : (array) + longitude and latitude position angles, in degrees. + Shape (2, ). + The longitudes / latitudes are in lonlat[0 / 1]. + + """ + lons = np.rad2deg(np.arctan2(xyz[1], xyz[0])) + radii = np.sqrt(np.sum(xyz * xyz, axis=0)) + lats = np.rad2deg(np.arcsin(xyz[2] / radii)) + return np.array([lons, lats]) + + +def _angle(p, q, r): + """ + Estimate grid-angles to true-Eastward direction from positions in the same + grid row, but at increasing column (grid-Eastward) positions. + + {P, Q, R} are locations of consecutive points in the same grid row. + These could be successive points in a single grid, + e.g. {T(i-1,j), T(i,j), T(i+1,j)} + or a mixture of U/V and T gridpoints if row positions are aligned, + e.g. {v(i,j), f(i,j), v(i+1,j)}. + + Method: + + Calculate dot product of a unit-vector parallel to P-->R, unit-scaled, + with the unit eastward (true longitude) vector at Q. + This value is cos(required angle). + Discriminate between +/- angles by comparing latitudes of P and R. + Return NaN where any P-->R are zero. + + .. NOTE:: + + This method assumes that the vector PR is parallel to the surface + at the longitude of Q, as it uses the length of PR as the basis for + the cosine ratio. + That is only exact when Q is at the same longitude as the midpoint + of PR, and this typically causes errors which grow with increasing + gridcell angle. + However, we retain this method because it reproduces the "standard" + gridcell-orientation-angle arrays found in files output by the CICE + model, which presumably uses an equivalent calculation. + + Args: + + * p, q, r : (float array) + Arrays of angles, in degrees. + All the same shape. + Shape is (2, ). + Longitudes / latitudes are in array[0 / 1]. + + Returns: + + * angle : (float array) + Grid angles relative to true-East, in degrees. + Positive when grid-East is anticlockwise from true-East. + Shape is same as . + + """ + mid_lons = np.deg2rad(q[0]) + + pr = _3d_xyz_from_latlon(r[0], r[1]) - _3d_xyz_from_latlon(p[0], p[1]) + pr_norm = np.sqrt(np.sum(pr**2, axis=0)) + pr_top = pr[1] * np.cos(mid_lons) - pr[0] * np.sin(mid_lons) + + index = pr_norm == 0 + pr_norm[index] = 1 + + cosine = np.maximum(np.minimum(pr_top / pr_norm, 1), -1) + cosine[index] = 0 + + psi = np.arccos(cosine) * np.sign(r[1] - p[1]) + psi[index] = np.nan + + return np.rad2deg(psi) + + +def gridcell_angles(x, y=None, cell_angle_boundpoints='mid-lhs, mid-rhs'): + """ + Calculate gridcell orientations for an arbitrary 2-dimensional grid. + + The input grid is defined by two 2-dimensional coordinate arrays with the + same dimensions (ny, nx), specifying the geolocations of a 2D mesh. + + Input values may be coordinate points (ny, nx) or bounds (ny, nx, 4). + However, if points, the edges in the X direction are assumed to be + connected by wraparound. + + Input can be either two arrays, two coordinates, or a single cube + containing two suitable coordinates identified with the 'x' and'y' axes. + + Args: + + The inputs (x [,y]) can be any of the folliwing : + + * x (:class:`~iris.cube.Cube`): + a grid cube with 2D X and Y coordinates, identified by 'axis'. + The coordinates must be 2-dimensional with the same shape. + The two dimensions represent grid dimensions in the order Y, then X. + + * x, y (:class:`~iris.coords.Coord`): + X and Y coordinates, specifying grid locations on the globe. + The coordinates must be 2-dimensional with the same shape. + The two dimensions represent grid dimensions in the order Y, then X. + If there is no coordinate system, they are assumed to be true + longitudes and latitudes. Units must convertible to 'degrees'. + + * x, y (2-dimensional arrays of same shape (ny, nx)): + longitude and latitude cell center locations, in degrees. + The two dimensions represent grid dimensions in the order Y, then X. + + * x, y (3-dimensional arrays of same shape (ny, nx, 4)): + longitude and latitude cell bounds, in degrees. + The first two dimensions are grid dimensions in the order Y, then X. + The last index maps cell corners anticlockwise from bottom-left. + + Optional Args: + + * cell_angle_boundpoints (string): + Controls which gridcell bounds locations are used to calculate angles, + if the inputs are bounds or bounded coordinates. + Valid values are 'lower-left, lower-right', which takes the angle from + the lower left to the lower right corner, and 'mid-lhs, mid-rhs' which + takes an angles between the average of the left-hand and right-hand + pairs of corners. The default is 'mid-lhs, mid-rhs'. + + Returns: + + angles : (2-dimensional cube) + + Cube of angles of grid-x vector from true Eastward direction for + each gridcell, in degrees. + It also has "true" longitude and latitude coordinates, with no + coordinate system. + When the input has coords, then the output ones are identical if + the inputs are true-latlons, otherwise they are transformed + true-latlon versions. + When the input has bounded coords, then the output coords have + matching bounds and centrepoints (possibly transformed). + When the input is 2d arrays, or has unbounded coords, then the + output coords have matching points and no bounds. + When the input is 3d arrays, then the output coords have matching + bounds, and the centrepoints are an average of the 4 boundpoints. + + """ + cube = None + if hasattr(x, 'add_aux_coord'): + # Passed a cube : extract 'x' and ;'y' axis coordinates. + cube = x # Save for later checking. + x, y = cube.coord(axis='x'), cube.coord(axis='y') + + # Now should have either 2 coords or 2 arrays. + if not hasattr(x, 'shape') or not hasattr(y, 'shape'): + msg = ('Inputs (x,y) must have array shape property.' + 'Got type(x)={} and type(y)={}.') + raise ValueError(msg.format(type(x), type(y))) + + x_coord, y_coord = None, None + if hasattr(x, 'bounds') and hasattr(y, 'bounds'): + # x and y are Coords. + x_coord, y_coord = x.copy(), y.copy() + + # They must be angles : convert into degrees + for coord in (x_coord, y_coord): + if not coord.units.is_convertible('degrees'): + msg = ('Input X and Y coordinates must have angular ' + 'units. Got units of "{!s}" and "{!s}".') + raise ValueError(msg.format(x_coord.units, y_coord.units)) + coord.convert_units('degrees') + + if x_coord.ndim != 2 or y_coord.ndim != 2: + msg = ('Coordinate inputs must have 2-dimensional shape. ' + 'Got x-shape of {} and y-shape of {}.') + raise ValueError(msg.format(x_coord.shape, y_coord.shape)) + if x_coord.shape != y_coord.shape: + msg = ('Coordinate inputs must have same shape. ' + 'Got x-shape of {} and y-shape of {}.') + raise ValueError(msg.format(x_coord.shape, y_coord.shape)) + if cube: + x_dims, y_dims = (cube.coord_dims(co) for co in (x, y)) + if x_dims != y_dims: + msg = ('X and Y coordinates must have the same cube ' + 'dimensions. Got x-dims = {} and y-dims = {}.') + raise ValueError(msg.format(x_dims, y_dims)) + cs = x_coord.coord_system + if y_coord.coord_system != cs: + msg = ('Coordinate inputs must have same coordinate system. ' + 'Got x of {} and y of {}.') + raise ValueError(msg.format(cs, y_coord.coord_system)) + + # Base calculation on bounds if we have them, or points as a fallback. + if x_coord.has_bounds() and y_coord.has_bounds(): + x, y = x_coord.bounds, y_coord.bounds + else: + x, y = x_coord.points, y_coord.points + + # Make sure these arrays are ordinary lats+lons, in degrees. + if cs is not None: + # Transform points into true lats + lons. + crs_src = cs.as_cartopy_crs() + crs_pc = ccrs.PlateCarree() + + def transform_xy_arrays(x, y): + # Note: flatten, as transform_points is limited to 2D arrays. + shape = x.shape + x, y = (arr.flatten() for arr in (x, y)) + pts = crs_pc.transform_points(crs_src, x, y) + x = pts[..., 0].reshape(shape) + y = pts[..., 1].reshape(shape) + return x, y + + # Transform the main reference points into standard lats+lons. + x, y = transform_xy_arrays(x, y) + + # Likewise replace the original coordinates with transformed ones, + # because the calculation also needs the centrepoint values. + xpts, ypts = (coord.points for coord in (x_coord, y_coord)) + xbds, ybds = (coord.bounds for coord in (x_coord, y_coord)) + xpts, ypts = transform_xy_arrays(xpts, ypts) + xbds, ybds = transform_xy_arrays(xbds, ybds) + x_coord = iris.coords.AuxCoord( + points=xpts, bounds=xbds, + standard_name='longitude', units='degrees') + y_coord = iris.coords.AuxCoord( + points=ypts, bounds=ybds, + standard_name='latitude', units='degrees') + + elif hasattr(x, 'bounds') or hasattr(y, 'bounds'): + # One was a Coord, and the other not ? + is_and_not = ('x', 'y') + if hasattr(y, 'bounds'): + is_and_not = reversed(is_and_not) + msg = 'Input {!r} is a Coordinate, but {!r} is not.' + raise ValueError(msg.format(*is_and_not)) + + # Now have either 2 points arrays (ny, nx) or 2 bounds arrays (ny, nx, 4). + # Construct (lhs, mid, rhs) where these represent 3 points at increasing + # grid-x indices (columns). + # Also make suitable X and Y coordinates for the result cube. + if x.ndim == 2: + # Data is points arrays. + # Use previous + subsequent points along grid-x-axis as references. + + # PROBLEM: we assume that the rhs connects to the lhs, so we should + # really only use this if data is full-longitudes (as a 'circular' + # coordinate). + # This is mentioned in the docstring, but we have no general means of + # checking it. + + # NOTE: we take the 2d grid as presented, so the second dimension is + # the 'X' dim. Again, that is implicit + can't be checked. + mid = np.array([x, y]) + lhs = np.roll(mid, 1, 2) + rhs = np.roll(mid, -1, 2) + if not x_coord: + # Create coords for result cube : with no bounds. + y_coord = iris.coords.AuxCoord(x, standard_name='latitude', + units='degrees') + x_coord = iris.coords.AuxCoord(y, standard_name='longitude', + units='degrees') + else: + # Data is bounds arrays. + # Use gridcell corners at different grid-x positions as references. + # NOTE: so with bounds, we *don't* need full circular longitudes. + xyz = _3d_xyz_from_latlon(x, y) + # Support two different choices of reference points locations. + angle_boundpoints_vals = {'mid-lhs, mid-rhs': '03_to_12', + 'lower-left, lower-right': '0_to_1'} + bounds_pos = angle_boundpoints_vals.get(cell_angle_boundpoints) + if bounds_pos == '0_to_1': + lhs_xyz = xyz[..., 0] + rhs_xyz = xyz[..., 1] + elif bounds_pos == '03_to_12': + lhs_xyz = 0.5 * (xyz[..., 0] + xyz[..., 3]) + rhs_xyz = 0.5 * (xyz[..., 1] + xyz[..., 2]) + else: + msg = ('unrecognised cell_angle_boundpoints of "{}", ' + 'must be one of {}') + raise ValueError(msg.format(cell_angle_boundpoints, + list(angle_boundpoints_vals.keys()))) + if not x_coord: + # Create bounded coords for result cube. + # Use average of lhs+rhs points in 3d to get 'mid' points, + # as coords without points are not allowed. + mid_xyz = 0.5 * (lhs_xyz + rhs_xyz) + mid_latlons = _latlon_from_xyz(mid_xyz) + # Create coords with given bounds, and averaged centrepoints. + x_coord = iris.coords.AuxCoord( + points=mid_latlons[0], bounds=x, + standard_name='longitude', units='degrees') + y_coord = iris.coords.AuxCoord( + points=mid_latlons[1], bounds=y, + standard_name='latitude', units='degrees') + + # Convert lhs and rhs points back to latlon form -- IN DEGREES ! + lhs = _latlon_from_xyz(lhs_xyz) + rhs = _latlon_from_xyz(rhs_xyz) + # 'mid' is coord.points, whether from input or just made up. + mid = np.array([x_coord.points, y_coord.points]) + + # Do the angle calcs, and return as a suitable cube. + angles = _angle(lhs, mid, rhs) + result = iris.cube.Cube(angles, + long_name='gridcell_angle_from_true_east', + units='degrees') + result.add_aux_coord(x_coord, (0, 1)) + result.add_aux_coord(y_coord, (0, 1)) + return result + + +def rotate_grid_vectors(u_cube, v_cube, grid_angles_cube=None, + grid_angles_kwargs=None): + """ + Rotate distance vectors from grid-oriented to true-latlon-oriented. + + Can also rotate by arbitrary angles, if they are passed in. + + .. Note:: + + This operation overlaps somewhat in function with + :func:`iris.analysis.cartography.rotate_winds`. + However, that routine only rotates vectors according to transformations + between coordinate systems. + This function, by contrast, can rotate vectors by arbitrary angles. + Most commonly, the angles are estimated solely from grid sampling + points, using :func:`gridcell_angles` : This allows operation on + complex meshes defined by two-dimensional coordinates, such as most + ocean grids. + + Args: + + * u_cube, v_cube : (cube) + Cubes of grid-u and grid-v vector components. + Units should be differentials of true-distance, e.g. 'm/s'. + + Optional args: + + * grid_angles_cube : (cube) + gridcell orientation angles. + Units must be angular, i.e. can be converted to 'radians'. + If not provided, grid angles are estimated from 'u_cube' using the + :func:`gridcell_angles` method. + + * grid_angles_kwargs : (dict or None) + Additional keyword args to be passed to the :func:`gridcell_angles` + method, if it is used. + + Returns: + + true_u, true_v : (cube) + Cubes of true-north oriented vector components. + Units are same as inputs. + + .. Note:: + + Vector magnitudes will always be the same as the inputs. + + """ + u_out, v_out = (cube.copy() for cube in (u_cube, v_cube)) + if not grid_angles_cube: + grid_angles_kwargs = grid_angles_kwargs or {} + grid_angles_cube = gridcell_angles(u_cube, **grid_angles_kwargs) + gridangles = grid_angles_cube.copy() + gridangles.convert_units('radians') + uu, vv, aa = (cube.data for cube in (u_out, v_out, gridangles)) + mags = np.sqrt(uu*uu + vv*vv) + angs = np.arctan2(vv, uu) + aa + uu, vv = mags * np.cos(angs), mags * np.sin(angs) + + # Promote all to masked arrays, and also apply mask at bad (NaN) angles. + mask = np.isnan(aa) + for cube in (u_out, v_out, aa): + if hasattr(cube.data, 'mask'): + mask |= cube.data.mask + u_out.data = np.ma.masked_array(uu, mask=mask) + v_out.data = np.ma.masked_array(vv, mask=mask) + + return u_out, v_out diff --git a/lib/iris/analysis/_interpolation.py b/lib/iris/analysis/_interpolation.py new file mode 100644 index 0000000000..405a14e24e --- /dev/null +++ b/lib/iris/analysis/_interpolation.py @@ -0,0 +1,685 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""A collection of helpers for interpolation.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +from collections import namedtuple +from itertools import product +import operator + +from numpy.lib.stride_tricks import as_strided +import numpy as np +import numpy.ma as ma + +from iris.analysis._scipy_interpolate import _RegularGridInterpolator +from iris.analysis.cartography import wrap_lons as wrap_circular_points +from iris.coords import DimCoord, AuxCoord +import iris.util + + +_DEFAULT_DTYPE = np.float16 + + +ExtrapolationMode = namedtuple('ExtrapolationMode', ['bounds_error', + 'fill_value', + 'mask_fill_value', + 'force_mask']) + +EXTRAPOLATION_MODES = { + 'extrapolate': ExtrapolationMode(False, None, None, False), + 'error': ExtrapolationMode(True, 0, 0, False), + 'nan': ExtrapolationMode(False, np.nan, 0, False), + 'mask': ExtrapolationMode(False, np.nan, 1, True), + 'nanmask': ExtrapolationMode(False, np.nan, 1, False) +} + + +def _canonical_sample_points(coords, sample_points): + """ + Return the canonical form of the points values. + + Ensures that any points supplied as datetime objects, or similar, + are converted to their numeric form. + + """ + canonical_sample_points = [] + for coord, points in zip(coords, sample_points): + if coord.units.is_time_reference(): + def convert_date(date): + try: + date = coord.units.date2num(date) + except AttributeError: + pass + return date + convert_dates = np.vectorize(convert_date, [np.dtype(float)]) + points = convert_dates(points) + canonical_sample_points.append(points) + return canonical_sample_points + + +def extend_circular_coord(coord, points): + """ + Return coordinates points with a shape extended by one + This is common when dealing with circular coordinates. + + """ + modulus = np.array(coord.units.modulus or 0, + dtype=coord.dtype) + points = np.append(points, points[0] + modulus) + return points + + +def extend_circular_coord_and_data(coord, data, coord_dim): + """ + Return coordinate points and a data array with a shape extended by one + in the coord_dim axis. This is common when dealing with circular + coordinates. + + """ + points = extend_circular_coord(coord, coord.points) + data = extend_circular_data(data, coord_dim) + return points, data + + +def extend_circular_data(data, coord_dim): + coord_slice_in_cube = [slice(None)] * data.ndim + coord_slice_in_cube[coord_dim] = slice(0, 1) + + mod = ma if ma.isMaskedArray(data) else np + data = mod.concatenate((data, + data[tuple(coord_slice_in_cube)]), + axis=coord_dim) + return data + + +def get_xy_dim_coords(cube): + """ + Return the x and y dimension coordinates from a cube. + + This function raises a ValueError if the cube does not contain one and + only one set of x and y dimension coordinates. It also raises a ValueError + if the identified x and y coordinates do not have coordinate systems that + are equal. + + Args: + + * cube: + An instance of :class:`iris.cube.Cube`. + + Returns: + A tuple containing the cube's x and y dimension coordinates. + + """ + return get_xy_coords(cube, dim_coords=True) + + +def get_xy_coords(cube, dim_coords=False): + """ + Return the x and y coordinates from a cube. + + This function raises a ValueError if the cube does not contain one and + only one set of x and y coordinates. It also raises a ValueError + if the identified x and y coordinates do not have coordinate systems that + are equal. + + Args: + + * cube: + An instance of :class:`iris.cube.Cube`. + + Kwargs: + + * dim_coords: + Set this to True to only return dimension coordinates. Defaults to + False. + + Returns: + A tuple containing the cube's x and y dimension coordinates. + + """ + x_coords = cube.coords(axis='x', dim_coords=dim_coords) + if len(x_coords) != 1 or x_coords[0].ndim != 1: + raise ValueError('Cube {!r} must contain a single 1D x ' + 'coordinate.'.format(cube.name())) + x_coord = x_coords[0] + + y_coords = cube.coords(axis='y', dim_coords=dim_coords) + if len(y_coords) != 1 or y_coords[0].ndim != 1: + raise ValueError('Cube {!r} must contain a single 1D y ' + 'coordinate.'.format(cube.name())) + y_coord = y_coords[0] + + if x_coord.coord_system != y_coord.coord_system: + raise ValueError("The cube's x ({!r}) and y ({!r}) " + "coordinates must have the same coordinate " + "system.".format(x_coord.name(), y_coord.name())) + + return x_coord, y_coord + + +def snapshot_grid(cube): + """ + Helper function that returns deep copies of lateral (dimension) coordinates + from a cube. + + """ + x, y = get_xy_dim_coords(cube) + return x.copy(), y.copy() + + +class RectilinearInterpolator(object): + """ + This class provides support for performing nearest-neighbour or + linear interpolation over one or more orthogonal dimensions. + + """ + def __init__(self, src_cube, coords, method, extrapolation_mode): + """ + Perform interpolation over one or more orthogonal coordinates. + + Args: + + * src_cube: + The :class:`iris.cube.Cube` which is to be interpolated. + * coords: + The names or coordinate instances which are to be + interpolated over + * method: + Either 'linear' or 'nearest'. + * extrapolation_mode: + Must be one of the following strings: + + * 'extrapolate' - The extrapolation points will be calculated + according to the method. The 'linear' method extends the + gradient of the closest two points. The 'nearest' method + uses the value of the closest point. + * 'nan' - The extrapolation points will be be set to NaN. + * 'error' - A ValueError exception will be raised, notifying an + attempt to extrapolate. + * 'mask' - The extrapolation points will always be masked, even + if the source data is not a MaskedArray. + * 'nanmask' - If the source data is a MaskedArray the + extrapolation points will be masked. Otherwise they will be + set to NaN. + + """ + # Trigger any deferred loading of the source cube's data and snapshot + # its state to ensure that the interpolator is impervious to external + # changes to the original source cube. The data is loaded to prevent + # the snaphot having lazy data, avoiding the potential for the + # same data to be loaded again and again. + if src_cube.has_lazy_data(): + src_cube.data + self._src_cube = src_cube.copy() + # Coordinates defining the dimensions to be interpolated. + self._src_coords = [self._src_cube.coord(coord) for coord in coords] + # Whether to use linear or nearest-neighbour interpolation. + if method not in ('linear', 'nearest'): + msg = 'Interpolation method {!r} not supported'.format(method) + raise ValueError(msg) + self._method = method + # The extrapolation mode. + if extrapolation_mode not in EXTRAPOLATION_MODES: + msg = 'Extrapolation mode {!r} not supported.' + raise ValueError(msg.format(extrapolation_mode)) + self._mode = extrapolation_mode + # The point values defining the dimensions to be interpolated. + self._src_points = [] + # A list of flags indicating dimensions that need to be reversed. + self._coord_decreasing = [] + # The cube dimensions to be interpolated over. + self._interp_dims = [] + # meta-data to support circular data-sets. + self._circulars = [] + # Instance of the interpolator that performs the actual interpolation. + self._interpolator = None + + # Perform initial start-up configuration and validation. + self._setup() + + @property + def cube(self): + return self._src_cube + + @property + def coords(self): + return self._src_coords + + @property + def method(self): + return self._method + + @property + def extrapolation_mode(self): + return self._mode + + def _account_for_circular(self, points, data): + """ + Extend the given data array, and re-centralise coordinate points + for circular (1D) coordinates. + + """ + for (circular, modulus, index, dim, offset) in self._circulars: + if modulus: + # Map all the requested values into the range of the source + # data (centred over the centre of the source data to allow + # extrapolation where required). + points[:, index] = wrap_circular_points(points[:, index], + offset, modulus) + + # Also extend data if circular (to match the coord points, which + # 'setup' already extended). + if circular: + data = extend_circular_data(data, dim) + + return points, data + + def _account_for_inverted(self, data): + if np.any(self._coord_decreasing): + dim_slices = [slice(None)] * data.ndim + for interp_dim, flip in zip(self._interp_dims, + self._coord_decreasing): + if flip: + dim_slices[interp_dim] = slice(-1, None, -1) + data = data[dim_slices] + return data + + def _interpolate(self, data, interp_points): + """ + Interpolate a data array over N dimensions. + + Create and cache the underlying interpolator instance before invoking + it to perform interpolation over the data at the given coordinate point + values. + + * data (ndarray): + A data array, to be interpolated in its first 'N' dimensions. + + * interp_points (ndarray): + An array of interpolation coordinate values. + Its shape is (..., N) where N is the number of interpolation + dimensions. + "interp_points[..., i]" are interpolation point values for the i'th + coordinate, which is mapped to the i'th data dimension. + The other (leading) dimensions index over the different required + sample points. + + Returns: + + A :class:`np.ndarray`. Its shape is "points_shape + extra_shape", + where "extra_shape" is the remaining non-interpolated dimensions of + the data array (i.e. 'data.shape[N:]'), and "points_shape" is the + leading dimensions of interp_points, + (i.e. 'interp_points.shape[:-1]'). + + """ + dtype = self._interpolated_dtype(data.dtype) + if data.dtype != dtype: + # Perform dtype promotion. + data = data.astype(dtype) + + mode = EXTRAPOLATION_MODES[self._mode] + if self._interpolator is None: + # Cache the interpolator instance. + # NB. The constructor of the _RegularGridInterpolator class does + # some unnecessary checks on the fill_value parameter, + # so we set it afterwards instead. Sneaky. ;-) + self._interpolator = _RegularGridInterpolator( + self._src_points, data, method=self.method, + bounds_error=mode.bounds_error, fill_value=None) + else: + self._interpolator.values = data + + # We may be re-using a cached interpolator, so ensure the fill + # value is set appropriately for extrapolating data values. + self._interpolator.fill_value = mode.fill_value + result = self._interpolator(interp_points) + + if result.dtype != data.dtype: + # Cast the data dtype to be as expected. Note that, the dtype + # of the interpolated result is influenced by the dtype of the + # interpolation points. + result = result.astype(data.dtype) + + if np.ma.isMaskedArray(data) or mode.force_mask: + # NB. np.ma.getmaskarray returns an array of `False` if + # `data` is not a masked array. + src_mask = np.ma.getmaskarray(data) + # Switch the extrapolation to work with mask values. + self._interpolator.fill_value = mode.mask_fill_value + self._interpolator.values = src_mask + mask_fraction = self._interpolator(interp_points) + new_mask = (mask_fraction > 0) + if ma.isMaskedArray(data) or np.any(new_mask): + result = np.ma.MaskedArray(result, new_mask) + + return result + + def _resample_coord(self, sample_points, coord, coord_dims): + """ + Interpolate the given coordinate at the provided sample points. + + """ + # NB. This section is ripe for improvement: + # - Internally self._points() expands coord.points to the same + # N-dimensional shape as the cube's data, but it doesn't + # collapse it again before returning so we have to do that + # here. + # - By expanding to N dimensions self._points() is doing + # unnecessary work. + data = self._points(sample_points, coord.points, coord_dims) + index = tuple(0 if dim not in coord_dims else slice(None) + for dim in range(self._src_cube.ndim)) + new_points = data[index] + # Watch out for DimCoord instances that are no longer monotonic + # after the resampling. + try: + new_coord = coord.copy(new_points) + except ValueError: + aux_coord = AuxCoord.from_coord(coord) + new_coord = aux_coord.copy(new_points) + return new_coord + + def _setup(self): + """ + Perform initial start-up configuration and validation based on the + cube and the specified coordinates to be interpolated over. + + """ + # Pre-calculate control data for each interpolation coordinate. + self._src_points = [] + self._coord_decreasing = [] + self._circulars = [] + self._interp_dims = [] + for index, coord in enumerate(self._src_coords): + coord_dims = self._src_cube.coord_dims(coord) + coord_points = coord.points + + # Record if coord is descending-order, and adjust points. + # (notes copied from pelson :- + # Force all coordinates to be monotonically increasing. + # Generally this isn't always necessary for a rectilinear + # interpolator, but it is a common requirement.) + decreasing = (coord.ndim == 1 and + # NOTE: this clause avoids an error when > 1D, + # as '_validate' raises a more readable error. + coord_points.size > 1 and + coord_points[1] < coord_points[0]) + self._coord_decreasing.append(decreasing) + if decreasing: + coord_points = coord_points[::-1] + + # Record info if coord is circular, and adjust points. + circular = getattr(coord, 'circular', False) + modulus = getattr(coord.units, 'modulus', 0) + if circular or modulus: + # Only DimCoords can be circular. + if circular: + coord_points = extend_circular_coord(coord, coord_points) + offset = 0.5 * (coord_points.max() + coord_points.min() - + modulus) + self._circulars.append((circular, modulus, + index, coord_dims[0], + offset)) + + self._src_points.append(coord_points) + + # Record any interpolation cube dims we haven't already seen. + coord_dims = [c for c in coord_dims + if c not in self._interp_dims] + self._interp_dims += coord_dims + + self._validate() + + def _validate(self): + """ + Perform all sanity checks to ensure that the interpolation request + over the cube with the specified coordinates is valid and can be + performed. + + """ + if len(set(self._interp_dims)) != len(self._src_coords): + raise ValueError('Coordinates repeat a data dimension - the ' + 'interpolation would be over-specified.') + + for coord in self._src_coords: + if coord.ndim != 1: + raise ValueError('Interpolation coords must be 1-d for ' + 'rectilinear interpolation.') + + if not isinstance(coord, DimCoord): + # Check monotonic. + if not iris.util.monotonic(coord.points, strict=True): + msg = 'Cannot interpolate over the non-' \ + 'monotonic coordinate {}.' + raise ValueError(msg.format(coord.name())) + + def _interpolated_dtype(self, dtype): + """ + Determine the minimum base dtype required by the + underlying interpolator. + + """ + if self._method == 'nearest': + result = dtype + else: + result = np.result_type(_DEFAULT_DTYPE, dtype) + return result + + def _points(self, sample_points, data, data_dims=None): + """ + Interpolate the given data values at the specified list of orthogonal + (coord, points) pairs. + + Args: + + * sample_points: + A list of N iterables, where N is the number of coordinates + passed to the constructor. + [sample_values_for_coord_0, sample_values_for_coord_1, ...] + * data: + The data to interpolate - not necessarily the data from the cube + that was used to construct this interpolator. If the data has + fewer dimensions, then data_dims must be defined. + + Kwargs: + + * data_dims: + The dimensions of the given data array in terms of the original + cube passed through to this interpolator's constructor. If None, + the data dimensions must map one-to-one onto the increasing + dimension order of the cube. + + Returns: + An :class:`~numpy.ndarray` or :class:`~numpy.ma.MaskedArray` + instance of the interpolated data. + + """ + dims = list(range(self._src_cube.ndim)) + data_dims = data_dims or dims + + if len(data_dims) != data.ndim: + msg = 'Data being interpolated is not consistent with ' \ + 'the data passed through.' + raise ValueError(msg) + + if sorted(data_dims) != list(data_dims): + # To do this, a pre & post transpose will be necessary. + msg = 'Currently only increasing data_dims is supported.' + raise NotImplementedError(msg) + + # Broadcast the data into the shape of the original cube. + if data_dims != list(range(self._src_cube.ndim)): + strides = list(data.strides) + for dim in range(self._src_cube.ndim): + if dim not in data_dims: + strides.insert(dim, 0) + data = as_strided(data, strides=strides, + shape=self._src_cube.shape) + + data = self._account_for_inverted(data) + # Calculate the transpose order to shuffle the interpolated dimensions + # to the lower dimensions for the interpolation algorithm. Then the + # transpose order to restore the dimensions to their original + # positions. + di = self._interp_dims + ds = sorted(dims, key=lambda d: d not in di) + dmap = {d: di.index(d) if d in di else ds.index(d) for d in dims} + interp_order, _ = zip(*sorted(dmap.items(), + key=operator.itemgetter(1))) + _, src_order = zip(*sorted(dmap.items(), key=operator.itemgetter(0))) + + # Prepare the sample points for interpolation and calculate the + # shape of the interpolated result. + interp_points = [] + interp_shape = [] + for index, points in enumerate(sample_points): + dtype = self._interpolated_dtype(self._src_points[index].dtype) + points = np.array(points, dtype=dtype, ndmin=1) + interp_points.append(points) + interp_shape.append(points.size) + + interp_shape.extend(length for dim, length in enumerate(data.shape) if + dim not in di) + + # Convert the interpolation points into a cross-product array + # with shape (n_cross_points, n_dims) + interp_points = np.asarray([pts for pts in product(*interp_points)]) + + # Adjust for circularity. + interp_points, data = self._account_for_circular(interp_points, data) + + if interp_order != dims: + # Transpose data in preparation for interpolation. + data = np.transpose(data, interp_order) + + # Interpolate and reshape the data ... + result = self._interpolate(data, interp_points) + result = result.reshape(interp_shape) + + if src_order != dims: + # Restore the interpolated result to the original + # source cube dimensional order. + result = np.transpose(result, src_order) + + return result + + def __call__(self, sample_points, collapse_scalar=True): + """ + Construct a cube from the specified orthogonal interpolation points. + + Args: + + * sample_points: + A list of N iterables, where N is the number of coordinates + passed to the constructor. + [sample_values_for_coord_0, sample_values_for_coord_1, ...] + + Kwargs: + + * collapse_scalar: + Whether to collapse the dimension of the scalar sample points + in the resulting cube. Default is True. + + Returns: + A cube interpolated at the given sample points. The dimensionality + of the cube will be the number of original cube dimensions minus + the number of scalar coordinates, if collapse_scalar is True. + + """ + if len(sample_points) != len(self._src_coords): + msg = 'Expected sample points for {} coordinates, got {}.' + raise ValueError(msg.format(len(self._src_coords), + len(sample_points))) + + sample_points = _canonical_sample_points(self._src_coords, + sample_points) + + data = self._src_cube.data + # Interpolate the cube payload. + interpolated_data = self._points(sample_points, data) + + if collapse_scalar: + # When collapse_scalar is True, keep track of the dimensions for + # which sample points is scalar : We will remove these dimensions + # later on. + _new_scalar_dims = [] + for dim, points in zip(self._interp_dims, sample_points): + if np.array(points).ndim == 0: + _new_scalar_dims.append(dim) + + cube = self._src_cube + new_cube = iris.cube.Cube(interpolated_data) + new_cube.metadata = cube.metadata + + def construct_new_coord_given_points(coord, points): + # Handle what was previously a DimCoord which may no longer be + # monotonic. + try: + return coord.copy(points) + except ValueError: + return AuxCoord.from_coord(coord).copy(points) + + # Keep track of id(coord) -> new_coord for aux factory construction + # later on. + coord_mapping = {} + dims_with_dim_coords = [] + + def construct_new_coord(coord): + dims = cube.coord_dims(coord) + if coord in self._src_coords: + index = self._src_coords.index(coord) + new_points = sample_points[index] + new_coord = construct_new_coord_given_points(coord, new_points) + # isinstance not possible here as a dimension coordinate can be + # mapped to the aux coordinates of a cube. + if coord in cube.aux_coords: + dims = [self._interp_dims[index]] + else: + if set(dims).intersection(set(self._interp_dims)): + # Interpolate the coordinate payload. + new_coord = self._resample_coord(sample_points, coord, + dims) + else: + new_coord = coord.copy() + return new_coord, dims + + def gen_new_cube(): + if (isinstance(new_coord, DimCoord) and len(dims) > 0 and + dims[0] not in dims_with_dim_coords): + new_cube._add_unique_dim_coord(new_coord, dims) + dims_with_dim_coords.append(dims[0]) + else: + new_cube._add_unique_aux_coord(new_coord, dims) + coord_mapping[id(coord)] = new_coord + + # Copy/interpolate the coordinates. + for coord in (cube.dim_coords + cube.aux_coords): + new_coord, dims = construct_new_coord(coord) + gen_new_cube() + + for factory in self._src_cube.aux_factories: + new_cube.add_aux_factory(factory.updated(coord_mapping)) + + if collapse_scalar and _new_scalar_dims: + dim_slices = [0 if dim in _new_scalar_dims else slice(None) + for dim in range(new_cube.ndim)] + new_cube = new_cube[tuple(dim_slices)] + + return new_cube diff --git a/lib/iris/analysis/_regrid.py b/lib/iris/analysis/_regrid.py new file mode 100644 index 0000000000..83561a2b94 --- /dev/null +++ b/lib/iris/analysis/_regrid.py @@ -0,0 +1,547 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +import copy +import functools +import warnings + +import numpy as np +import numpy.ma as ma + +from iris.analysis._interpolation import (EXTRAPOLATION_MODES, + extend_circular_coord_and_data, + get_xy_dim_coords, snapshot_grid) +from iris.analysis._scipy_interpolate import _RegularGridInterpolator +import iris.cube +from iris.util import _meshgrid + + +class RectilinearRegridder(object): + """ + This class provides support for performing nearest-neighbour or + linear regridding between source and target grids. + + """ + def __init__(self, src_grid_cube, tgt_grid_cube, method, + extrapolation_mode): + """ + Create a regridder for conversions between the source + and target grids. + + Args: + + * src_grid_cube: + The :class:`~iris.cube.Cube` providing the source grid. + * tgt_grid_cube: + The :class:`~iris.cube.Cube` providing the target grid. + * method: + Either 'linear' or 'nearest'. + * extrapolation_mode: + Must be one of the following strings: + + * 'extrapolate' - The extrapolation points will be + calculated by extending the gradient of the closest two + points. + * 'nan' - The extrapolation points will be be set to NaN. + * 'error' - An exception will be raised, notifying an + attempt to extrapolate. + * 'mask' - The extrapolation points will always be masked, even + if the source data is not a MaskedArray. + * 'nanmask' - If the source data is a MaskedArray the + extrapolation points will be masked. Otherwise they will be + set to NaN. + + """ + # Validity checks. + if not isinstance(src_grid_cube, iris.cube.Cube): + raise TypeError("'src_grid_cube' must be a Cube") + if not isinstance(tgt_grid_cube, iris.cube.Cube): + raise TypeError("'tgt_grid_cube' must be a Cube") + # Snapshot the state of the cubes to ensure that the regridder + # is impervious to external changes to the original source cubes. + self._src_grid = snapshot_grid(src_grid_cube) + self._tgt_grid = snapshot_grid(tgt_grid_cube) + # Check the target grid units. + for coord in self._tgt_grid: + self._check_units(coord) + # Whether to use linear or nearest-neighbour interpolation. + if method not in ('linear', 'nearest'): + msg = 'Regridding method {!r} not supported.'.format(method) + raise ValueError(msg) + self._method = method + # The extrapolation mode. + if extrapolation_mode not in EXTRAPOLATION_MODES: + msg = 'Invalid extrapolation mode {!r}' + raise ValueError(msg.format(extrapolation_mode)) + self._extrapolation_mode = extrapolation_mode + + @property + def method(self): + return self._method + + @property + def extrapolation_mode(self): + return self._extrapolation_mode + + @staticmethod + def _sample_grid(src_coord_system, grid_x_coord, grid_y_coord): + """ + Convert the rectilinear grid coordinates to a curvilinear grid in + the source coordinate system. + + The `grid_x_coord` and `grid_y_coord` must share a common coordinate + system. + + Args: + + * src_coord_system: + The :class:`iris.coord_system.CoordSystem` for the grid of the + source Cube. + * grid_x_coord: + The :class:`iris.coords.DimCoord` for the X coordinate. + * grid_y_coord: + The :class:`iris.coords.DimCoord` for the Y coordinate. + + Returns: + A tuple of the X and Y coordinate values as 2-dimensional + arrays. + + """ + grid_x, grid_y = _meshgrid(grid_x_coord.points, grid_y_coord.points) + # Skip the CRS transform if we can to avoid precision problems. + if src_coord_system == grid_x_coord.coord_system: + sample_grid_x = grid_x + sample_grid_y = grid_y + else: + src_crs = src_coord_system.as_cartopy_crs() + grid_crs = grid_x_coord.coord_system.as_cartopy_crs() + sample_xyz = src_crs.transform_points(grid_crs, grid_x, grid_y) + sample_grid_x = sample_xyz[..., 0] + sample_grid_y = sample_xyz[..., 1] + return sample_grid_x, sample_grid_y + + @staticmethod + def _regrid(src_data, x_dim, y_dim, + src_x_coord, src_y_coord, + sample_grid_x, sample_grid_y, + method='linear', extrapolation_mode='nanmask'): + """ + Regrid the given data from the src grid to the sample grid. + + The result will be a MaskedArray if either/both of: + - the source array is a MaskedArray, + - the extrapolation_mode is 'mask' and the result requires + extrapolation. + + If the result is a MaskedArray the mask for each element will be set + if either/both of: + - there is a non-zero contribution from masked items in the input data + - the element requires extrapolation and the extrapolation_mode + dictates a masked value. + + Args: + + * src_data: + An N-dimensional NumPy array or MaskedArray. + * x_dim: + The X dimension within `src_data`. + * y_dim: + The Y dimension within `src_data`. + * src_x_coord: + The X :class:`iris.coords.DimCoord`. + * src_y_coord: + The Y :class:`iris.coords.DimCoord`. + * sample_grid_x: + A 2-dimensional array of sample X values. + * sample_grid_y: + A 2-dimensional array of sample Y values. + + Kwargs: + + * method: + Either 'linear' or 'nearest'. The default method is 'linear'. + * extrapolation_mode: + Must be one of the following strings: + + * 'linear' - The extrapolation points will be calculated by + extending the gradient of the closest two points. + * 'nan' - The extrapolation points will be be set to NaN. + * 'error' - A ValueError exception will be raised, notifying an + attempt to extrapolate. + * 'mask' - The extrapolation points will always be masked, even + if the source data is not a MaskedArray. + * 'nanmask' - If the source data is a MaskedArray the + extrapolation points will be masked. Otherwise they will be + set to NaN. + + The default mode of extrapolation is 'nanmask'. + + Returns: + The regridded data as an N-dimensional NumPy array. The lengths + of the X and Y dimensions will now match those of the sample + grid. + + """ + # + # XXX: At the moment requires to be a static method as used by + # experimental regrid_area_weighted_rectilinear_src_and_grid + # + if sample_grid_x.shape != sample_grid_y.shape: + raise ValueError('Inconsistent sample grid shapes.') + if sample_grid_x.ndim != 2: + raise ValueError('Sample grid must be 2-dimensional.') + + # Prepare the result data array + shape = list(src_data.shape) + assert shape[x_dim] == src_x_coord.shape[0] + assert shape[y_dim] == src_y_coord.shape[0] + + shape[y_dim] = sample_grid_x.shape[0] + shape[x_dim] = sample_grid_x.shape[1] + + dtype = src_data.dtype + if method == 'linear': + # If we're given integer values, convert them to the smallest + # possible float dtype that can accurately preserve the values. + if dtype.kind == 'i': + dtype = np.promote_types(dtype, np.float16) + + if ma.isMaskedArray(src_data): + data = ma.empty(shape, dtype=dtype) + data.mask = np.zeros(data.shape, dtype=np.bool) + else: + data = np.empty(shape, dtype=dtype) + + # The interpolation class requires monotonically increasing + # coordinates, so flip the coordinate(s) and data if they aren't. + reverse_x = (src_x_coord.points[0] > src_x_coord.points[1] if + src_x_coord.points.size > 1 else False) + reverse_y = src_y_coord.points[0] > src_y_coord.points[1] + flip_index = [slice(None)] * src_data.ndim + if reverse_x: + src_x_coord = src_x_coord[::-1] + flip_index[x_dim] = slice(None, None, -1) + if reverse_y: + src_y_coord = src_y_coord[::-1] + flip_index[y_dim] = slice(None, None, -1) + src_data = src_data[tuple(flip_index)] + + if src_x_coord.circular: + x_points, src_data = extend_circular_coord_and_data(src_x_coord, + src_data, + x_dim) + else: + x_points = src_x_coord.points + + # Slice out the first full 2D piece of data for construction of the + # interpolator. + index = [0] * src_data.ndim + index[x_dim] = index[y_dim] = slice(None) + initial_data = src_data[tuple(index)] + if y_dim < x_dim: + initial_data = initial_data.T + + # Construct the interpolator, we will fill in any values out of bounds + # manually. + interpolator = _RegularGridInterpolator([x_points, src_y_coord.points], + initial_data, method=method, + bounds_error=False, + fill_value=None) + # The constructor of the _RegularGridInterpolator class does + # some unnecessary checks on these values, so we set them + # afterwards instead. Sneaky. ;-) + try: + mode = EXTRAPOLATION_MODES[extrapolation_mode] + except KeyError: + raise ValueError('Invalid extrapolation mode.') + interpolator.bounds_error = mode.bounds_error + interpolator.fill_value = mode.fill_value + + # Construct the target coordinate points array, suitable for passing to + # the interpolator multiple times. + interp_coords = [sample_grid_x.astype(np.float64)[..., np.newaxis], + sample_grid_y.astype(np.float64)[..., np.newaxis]] + + # Map all the requested values into the range of the source + # data (centred over the centre of the source data to allow + # extrapolation where required). + min_x, max_x = x_points.min(), x_points.max() + min_y, max_y = src_y_coord.points.min(), src_y_coord.points.max() + if src_x_coord.units.modulus: + modulus = src_x_coord.units.modulus + offset = (max_x + min_x - modulus) * 0.5 + interp_coords[0] -= offset + interp_coords[0] = (interp_coords[0] % modulus) + offset + + interp_coords = np.dstack(interp_coords) + + weights = interpolator.compute_interp_weights(interp_coords) + + def interpolate(data): + # Update the interpolator for this data slice. + data = data.astype(interpolator.values.dtype) + if y_dim < x_dim: + data = data.T + interpolator.values = data + data = interpolator.interp_using_pre_computed_weights(weights) + if y_dim > x_dim: + data = data.T + return data + + # Build up a shape suitable for passing to ndindex, inside the loop we + # will insert slice(None) on the data indices. + iter_shape = list(shape) + iter_shape[x_dim] = iter_shape[y_dim] = 1 + + # Iterate through each 2d slice of the data, updating the interpolator + # with the new data as we go. + for index in np.ndindex(tuple(iter_shape)): + index = list(index) + index[x_dim] = index[y_dim] = slice(None) + + src_subset = src_data[tuple(index)] + interpolator.fill_value = mode.fill_value + data[tuple(index)] = interpolate(src_subset) + + if ma.isMaskedArray(data) or mode.force_mask: + # NB. np.ma.getmaskarray returns an array of `False` if + # `src_subset` is not a masked array. + src_mask = np.ma.getmaskarray(src_subset) + interpolator.fill_value = mode.mask_fill_value + mask_fraction = interpolate(src_mask) + new_mask = (mask_fraction > 0) + + if np.ma.isMaskedArray(data): + data.mask[tuple(index)] = new_mask + elif np.any(new_mask): + # Set mask=False to ensure we have an expanded mask array. + data = np.ma.MaskedArray(data, mask=False) + data.mask[tuple(index)] = new_mask + + return data + + @staticmethod + def _create_cube(data, src, x_dim, y_dim, src_x_coord, src_y_coord, + grid_x_coord, grid_y_coord, sample_grid_x, sample_grid_y, + regrid_callback): + """ + Return a new Cube for the result of regridding the source Cube onto + the new grid. + + All the metadata and coordinates of the result Cube are copied from + the source Cube, with two exceptions: + - Grid dimension coordinates are copied from the grid Cube. + - Auxiliary coordinates which span the grid dimensions are + ignored, except where they provide a reference surface for an + :class:`iris.aux_factory.AuxCoordFactory`. + + Args: + + * data: + The regridded data as an N-dimensional NumPy array. + * src: + The source Cube. + * x_dim: + The X dimension within the source Cube. + * y_dim: + The Y dimension within the source Cube. + * src_x_coord: + The X :class:`iris.coords.DimCoord`. + * src_y_coord: + The Y :class:`iris.coords.DimCoord`. + * grid_x_coord: + The :class:`iris.coords.DimCoord` for the new grid's X + coordinate. + * grid_y_coord: + The :class:`iris.coords.DimCoord` for the new grid's Y + coordinate. + * sample_grid_x: + A 2-dimensional array of sample X values. + * sample_grid_y: + A 2-dimensional array of sample Y values. + * regrid_callback: + The routine that will be used to calculate the interpolated + values of any reference surfaces. + + Returns: + The new, regridded Cube. + + """ + # + # XXX: At the moment requires to be a static method as used by + # experimental regrid_area_weighted_rectilinear_src_and_grid + # + # Create a result cube with the appropriate metadata + result = iris.cube.Cube(data) + result.metadata = copy.deepcopy(src.metadata) + + # Copy across all the coordinates which don't span the grid. + # Record a mapping from old coordinate IDs to new coordinates, + # for subsequent use in creating updated aux_factories. + coord_mapping = {} + + def copy_coords(src_coords, add_method): + for coord in src_coords: + dims = src.coord_dims(coord) + if coord is src_x_coord: + coord = grid_x_coord + elif coord is src_y_coord: + coord = grid_y_coord + elif x_dim in dims or y_dim in dims: + continue + result_coord = coord.copy() + add_method(result_coord, dims) + coord_mapping[id(coord)] = result_coord + + copy_coords(src.dim_coords, result.add_dim_coord) + copy_coords(src.aux_coords, result.add_aux_coord) + + def regrid_reference_surface(src_surface_coord, surface_dims, + x_dim, y_dim, src_x_coord, src_y_coord, + sample_grid_x, sample_grid_y, + regrid_callback): + # Determine which of the reference surface's dimensions span the X + # and Y dimensions of the source cube. + surface_x_dim = surface_dims.index(x_dim) + surface_y_dim = surface_dims.index(y_dim) + surface = regrid_callback(src_surface_coord.points, + surface_x_dim, surface_y_dim, + src_x_coord, src_y_coord, + sample_grid_x, sample_grid_y) + surface_coord = src_surface_coord.copy(surface) + return surface_coord + + # Copy across any AuxFactory instances, and regrid their reference + # surfaces where required. + for factory in src.aux_factories: + for coord in six.itervalues(factory.dependencies): + if coord is None: + continue + dims = src.coord_dims(coord) + if x_dim in dims and y_dim in dims: + result_coord = regrid_reference_surface(coord, dims, + x_dim, y_dim, + src_x_coord, + src_y_coord, + sample_grid_x, + sample_grid_y, + regrid_callback) + result.add_aux_coord(result_coord, dims) + coord_mapping[id(coord)] = result_coord + try: + result.add_aux_factory(factory.updated(coord_mapping)) + except KeyError: + msg = 'Cannot update aux_factory {!r} because of dropped' \ + ' coordinates.'.format(factory.name()) + warnings.warn(msg) + return result + + def _check_units(self, coord): + if coord.coord_system is None: + # No restriction on units. + pass + elif isinstance(coord.coord_system, + (iris.coord_systems.GeogCS, + iris.coord_systems.RotatedGeogCS)): + # Units for lat-lon or rotated pole must be 'degrees'. Note + # that 'degrees_east' etc. are equal to 'degrees'. + if coord.units != 'degrees': + msg = "Unsupported units for coordinate system. " \ + "Expected 'degrees' got {!r}.".format(coord.units) + raise ValueError(msg) + else: + # Units for other coord systems must be equal to metres. + if coord.units != 'm': + msg = "Unsupported units for coordinate system. " \ + "Expected 'metres' got {!r}.".format(coord.units) + raise ValueError(msg) + + def __call__(self, src): + """ + Regrid this :class:`~iris.cube.Cube` on to the target grid of + this :class:`RectilinearRegridder`. + + The given cube must be defined with the same grid as the source + grid used to create this :class:`RectilinearRegridder`. + + Args: + + * src: + A :class:`~iris.cube.Cube` to be regridded. + + Returns: + A cube defined with the horizontal dimensions of the target + and the other dimensions from this cube. The data values of + this cube will be converted to values on the new grid using + either nearest-neighbour or linear interpolation. + + """ + # Validity checks. + if not isinstance(src, iris.cube.Cube): + raise TypeError("'src' must be a Cube") + if get_xy_dim_coords(src) != self._src_grid: + raise ValueError('The given cube is not defined on the same ' + 'source grid as this regridder.') + + src_x_coord, src_y_coord = get_xy_dim_coords(src) + grid_x_coord, grid_y_coord = self._tgt_grid + src_cs = src_x_coord.coord_system + grid_cs = grid_x_coord.coord_system + + if src_cs is None and grid_cs is None: + if not (src_x_coord.is_compatible(grid_x_coord) and + src_y_coord.is_compatible(grid_y_coord)): + raise ValueError("The rectilinear grid coordinates of the " + "given cube and target grid have no " + "coordinate system but they do not have " + "matching coordinate metadata.") + elif src_cs is None or grid_cs is None: + raise ValueError("The rectilinear grid coordinates of the given " + "cube and target grid must either both have " + "coordinate systems or both have no coordinate " + "system but with matching coordinate metadata.") + + # Check the source grid units. + for coord in (src_x_coord, src_y_coord): + self._check_units(coord) + + # Convert the grid to a 2D sample grid in the src CRS. + sample_grid = self._sample_grid(src_cs, grid_x_coord, grid_y_coord) + sample_grid_x, sample_grid_y = sample_grid + + # Compute the interpolated data values. + x_dim = src.coord_dims(src_x_coord)[0] + y_dim = src.coord_dims(src_y_coord)[0] + data = self._regrid(src.data, x_dim, y_dim, + src_x_coord, src_y_coord, + sample_grid_x, sample_grid_y, + self._method, self._extrapolation_mode) + + # Wrap up the data as a Cube. + regrid_callback = functools.partial(self._regrid, + method=self._method, + extrapolation_mode='nan') + result = self._create_cube(data, src, x_dim, y_dim, + src_x_coord, src_y_coord, + grid_x_coord, grid_y_coord, + sample_grid_x, sample_grid_y, + regrid_callback) + return result diff --git a/lib/iris/analysis/_scipy_interpolate.py b/lib/iris/analysis/_scipy_interpolate.py new file mode 100644 index 0000000000..c93234e5d7 --- /dev/null +++ b/lib/iris/analysis/_scipy_interpolate.py @@ -0,0 +1,318 @@ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import itertools + +from scipy.sparse import csr_matrix +import numpy as np + + +# ============================================================================ +# | Copyright SciPy | +# | Code from this point unto the termination banner is copyright SciPy. | +# | License details can be found at scipy.org/scipylib/license.html | +# ============================================================================ + +# Source: https://github.com/scipy/scipy/blob/b94a5d5ccc08dddbc88453477ff2625\ +# 9aeaafb32/scipy/interpolate/interpnd.pyx#L167 +def _ndim_coords_from_arrays(points, ndim=None): + """ + Convert a tuple of coordinate arrays to a (..., ndim)-shaped array. + + """ + if isinstance(points, tuple) and len(points) == 1: + # handle argument tuple + points = points[0] + if isinstance(points, tuple): + p = np.broadcast_arrays(*points) + for j in range(1, len(p)): + if p[j].shape != p[0].shape: + raise ValueError( + "coordinate arrays do not have the same shape") + points = np.empty(p[0].shape + (len(points),), dtype=float) + for j, item in enumerate(p): + points[..., j] = item + else: + points = np.asanyarray(points) + # XXX Feed back to scipy. + if points.ndim <= 1: + if ndim is None: + points = points.reshape(-1, 1) + else: + points = points.reshape(-1, ndim) + return points + + +# source: https://github.com/scipy/scipy/blob/b94a5d5ccc08dddbc88453477ff2625\ +# 9aeaafb32/scipy/interpolate/interpolate.py#L1400 +class _RegularGridInterpolator(object): + + """ + Interpolation on a regular grid in arbitrary dimensions + + The data must be defined on a regular grid; the grid spacing however may be + uneven. Linear and nearest-neighbour interpolation are supported. After + setting up the interpolator object, the interpolation method (*linear* or + *nearest*) may be chosen at each evaluation. + + .. versionadded:: 0.14 + + Parameters + ---------- + points : tuple of ndarray of float, with shapes (m1, ), ..., (mn, ) + The points defining the regular grid in n dimensions. + + values : array_like, shape (m1, ..., mn, ...) + The data on the regular grid in n dimensions. + + method : str + The method of interpolation to perform. Supported are "linear" and + "nearest". This parameter will become the default for the object's + ``__call__`` method. + + bounds_error : bool, optional + If True, when interpolated values are requested outside of the + domain of the input data, a ValueError is raised. + If False, then `fill_value` is used. + + fill_value : number, optional + If provided, the value to use for points outside of the + interpolation domain. If None, values outside + the domain are extrapolated. + + Methods + ------- + __call__ + + Notes + ----- + Contrary to LinearNDInterpolator and NearestNDInterpolator, this class + avoids expensive triangulation of the input data by taking advantage of the + regular grid structure. + + """ + # this class is based on code originally programmed by Johannes Buchner, + # see https://github.com/JohannesBuchner/regulargrid + + def __init__(self, points, values, method="linear", bounds_error=True, + fill_value=np.nan): + if method not in ["linear", "nearest"]: + raise ValueError("Method '%s' is not defined" % method) + self.method = method + self.bounds_error = bounds_error + + if not hasattr(values, 'ndim'): + # allow reasonable duck-typed values + values = np.asarray(values) + + if len(points) > values.ndim: + raise ValueError("There are %d point arrays, but values has %d " + "dimensions" % (len(points), values.ndim)) + + if hasattr(values, 'dtype') and hasattr(values, 'astype'): + if not np.issubdtype(values.dtype, np.inexact): + values = values.astype(float) + + self.fill_value = fill_value + if fill_value is not None: + if hasattr(values, 'dtype') and not np.can_cast(fill_value, + values.dtype): + raise ValueError("fill_value must be either 'None' or " + "of a type compatible with values") + + for i, p in enumerate(points): + if not np.all(np.diff(p) > 0.): + raise ValueError("The points in dimension %d must be strictly " + "ascending" % i) + if not np.asarray(p).ndim == 1: + raise ValueError("The points in dimension %d must be " + "1-dimensional" % i) + if not values.shape[i] == len(p): + raise ValueError("There are %d points and %d values in " + "dimension %d" % (len(p), values.shape[i], i)) + self.grid = tuple([np.asarray(p) for p in points]) + self.values = values + + def __call__(self, xi, method=None): + """ + Interpolation at coordinates + + Parameters + ---------- + xi : ndarray of shape (..., ndim) + The coordinates to sample the gridded data at. + + method : str + The method of interpolation to perform. Supported are "linear" and + "nearest". + + """ + # Note: No functionality should live in this method. It should all be + # decomposed into the two interfaces (compute weights + use weights). + weights = self.compute_interp_weights(xi, method) + return self.interp_using_pre_computed_weights(weights) + + def compute_interp_weights(self, xi, method=None): + """ + Prepare the interpolator for interpolation to the given sample points. + + .. note:: + This interface provides the ability to reuse weights on multiple + data sources, such as in the case of regridding. For normal + interpolation, simply call the interpolator with the sample points. + + Parameters + ---------- + xi : ndarray of shape (..., ndim) + The coordinates to sample the gridded data at. + + Returns + ------- + A tuple of the items necessary for passing to + :meth:`interp_using_pre_computed_weights`. The contents of this return + value are not guaranteed to be consistent across Iris versions, and + should only be used for passing to + :meth:`interp_using_pre_computed_weights`. + + Example + ------- + >>> coords = np.array([[[50.7, -3.5], + [50.6, -3.5]], + [[50.7, -3.1], + [50.6, -3.1]]]) + >>> compute_interp_weights(coords) + + """ + ndim = len(self.grid) + xi = _ndim_coords_from_arrays(xi, ndim=ndim) + if xi.shape[-1] != ndim: + raise ValueError("The requested sample points xi have dimension " + "%d, but this RegularGridInterpolator has " + "dimension %d" % (xi.shape[1], ndim)) + + xi_shape = xi.shape + xi = xi.reshape(-1, xi_shape[-1]) + + if self.bounds_error: + for i, p in enumerate(xi.T): + if not np.logical_and(np.all(self.grid[i][0] <= p), + np.all(p <= self.grid[i][-1])): + raise ValueError("One of the requested xi is out of " + "bounds in dimension %d" % i) + + method = self.method if method is None else method + prepared = (xi_shape, method) + self._find_indices(xi.T) + + if method == 'linear': + + xi_shape, method, indices, norm_distances, out_of_bounds = prepared + + # Allocate arrays for describing the sparse matrix. + n_src_values_per_result_value = 2 ** ndim + n_result_values = len(indices[0]) + n_non_zero = n_result_values * n_src_values_per_result_value + weights = np.ones(n_non_zero, dtype=norm_distances[0].dtype) + col_indices = np.empty(n_non_zero) + row_ptrs = np.arange(0, n_non_zero + n_src_values_per_result_value, + n_src_values_per_result_value) + + corners = itertools.product(*[[(i, 1 - n), (i + 1, n)] + for i, n in zip(indices, + norm_distances)]) + shape = self.values.shape[:ndim] + + for i, corner in enumerate(corners): + corner_indices = [ci for ci, cw in corner] + n_indices = np.ravel_multi_index(corner_indices, shape, + mode='wrap') + col_indices[i::n_src_values_per_result_value] = n_indices + for ci, cw in corner: + weights[i::n_src_values_per_result_value] *= cw + + n_src_values = np.prod(list(map(len, self.grid))) + sparse_matrix = csr_matrix((weights, col_indices, row_ptrs), + shape=(n_result_values, n_src_values)) + + prepared = (xi_shape, method, sparse_matrix, None, out_of_bounds) + + return prepared + + def interp_using_pre_computed_weights(self, computed_weights): + """ + Perform the interpolation using pre-computed interpolation weights. + + .. note:: + This interface provides the ability to reuse weights on multiple + data sources, such as in the case of regridding. For normal + interpolation, simply call the interpolator with the sample points, + rather using this decomposed interface. + + Parameters + ---------- + computed_weights : *intentionally undefined interface* + The pre-computed interpolation weights which come from calling + :meth:`compute_interp_weights`. + + """ + [xi_shape, method, indices, norm_distances, + out_of_bounds] = computed_weights + + method = self.method if method is None else method + if method not in ["linear", "nearest"]: + raise ValueError("Method '%s' is not defined" % method) + + ndim = len(self.grid) + + if method == "linear": + result = self._evaluate_linear_sparse(indices) + elif method == "nearest": + result = self._evaluate_nearest( + indices, norm_distances, out_of_bounds) + if not self.bounds_error and self.fill_value is not None: + result[out_of_bounds] = self.fill_value + + return result.reshape(xi_shape[:-1] + self.values.shape[ndim:]) + + def _evaluate_linear_sparse(self, sparse_matrix): + ndim = len(self.grid) + if ndim == self.values.ndim: + result = sparse_matrix * self.values.reshape(-1) + else: + shape = (sparse_matrix.shape[1], -1) + result = sparse_matrix * self.values.reshape(shape) + + return result + + def _evaluate_nearest(self, indices, norm_distances, out_of_bounds): + idx_res = [] + for i, yi in zip(indices, norm_distances): + idx_res.append(np.where(yi <= .5, i, i + 1)) + return self.values[idx_res] + + def _find_indices(self, xi): + # find relevant edges between which xi are situated + indices = [] + # compute distance to lower edge in unity units + norm_distances = [] + # check for out of bounds xi + out_of_bounds = np.zeros((xi.shape[1]), dtype=bool) + # iterate through dimensions + for x, grid in zip(xi, self.grid): + i = np.searchsorted(grid, x) - 1 + i[i < 0] = 0 + i[i > grid.size - 2] = grid.size - 2 + indices.append(i) + # TODO: Add this to scipy's version. + if grid.size == 1: + norm_distances.append(x - grid[i]) + else: + norm_distances.append((x - grid[i]) / + (grid[i + 1] - grid[i])) + if not self.bounds_error: + out_of_bounds += x < grid[0] + out_of_bounds += x > grid[-1] + return indices, norm_distances, out_of_bounds + +# ============================================================================ +# | END SciPy copyright | +# ============================================================================ diff --git a/lib/iris/analysis/calculus.py b/lib/iris/analysis/calculus.py index 2d04018241..c816d733ec 100644 --- a/lib/iris/analysis/calculus.py +++ b/lib/iris/analysis/calculus.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -21,18 +21,23 @@ """ -from __future__ import division +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + import re -import warnings +import cf_units import numpy as np +from iris._deprecation import warn_deprecated import iris.cube import iris.coords import iris.coord_systems import iris.analysis import iris.analysis.maths -import iris.analysis.cartography +from iris.analysis.cartography import (DEFAULT_SPHERICAL_EARTH_RADIUS, + DEFAULT_SPHERICAL_EARTH_RADIUS_UNIT) from iris.util import delta @@ -41,8 +46,9 @@ def _construct_delta_coord(coord): """ - Return a coordinate of deltas between the given coordinate's points. If the original coordinate has length n - and is circular then the result will be a coordinate of length n, otherwise the result will be + Return a coordinate of deltas between the given coordinate's points. + If the original coordinate has length n and is circular then the + result will be a coordinate of length n, otherwise the result will be of length n-1. """ @@ -50,7 +56,8 @@ def _construct_delta_coord(coord): raise iris.exceptions.CoordinateMultiDimError(coord) circular = getattr(coord, 'circular', False) if coord.shape == (1,) and not circular: - raise ValueError('Cannot take interval differences of a single valued coordinate.') + raise ValueError('Cannot take interval differences of a single ' + 'valued coordinate.') if circular: circular_kwd = coord.units.modulus or True @@ -71,25 +78,30 @@ def _construct_delta_coord(coord): def _construct_midpoint_coord(coord, circular=None): """ - Return a coordinate of mid-points from the given coordinate. If the given coordinate has length n - and the circular flag set then the result will be a coordinate of length n, otherwise the result will be + Return a coordinate of mid-points from the given coordinate. If the + given coordinate has length n and the circular flag set then the + result will be a coordinate of length n, otherwise the result will be of length n-1. """ if circular and not hasattr(coord, 'circular'): - raise ValueError("Cannot produce circular midpoint from a coord without the circular attribute ") + raise ValueError('Cannot produce circular midpoint from a coord ' + 'without the circular attribute') if circular is None: circular = getattr(coord, 'circular', False) elif circular != getattr(coord, 'circular', False): - warnings.warn("circular flag and Coord.circular attribute do not match") + warn_deprecated('circular flag and Coord.circular attribute do ' + 'not match') if coord.ndim != 1: raise iris.exceptions.CoordinateMultiDimError(coord) if coord.shape == (1,) and not circular: - raise ValueError('Cannot take the midpoints of a single valued coordinate.') + raise ValueError('Cannot take the midpoints of a single valued ' + 'coordinate.') - # Calculate the delta of the coordinate (this deals with circularity nicely) + # Calculate the delta of the coordinate + # (this deals with circularity nicely). mid_point_coord = _construct_delta_coord(coord) # if the coord is circular then include the last one, else, just take 0:-1 @@ -107,34 +119,41 @@ def _construct_midpoint_coord(coord, circular=None): # if the coord is circular then include the last one, else, just take 0:-1 mid_point_points = axis_delta * 0.5 + coord.points[circular_slice] - try: # try creating a coordinate of the same type as before, otherwise, make an AuxCoord - mid_point_coord = coord.from_coord(coord).copy(mid_point_points, mid_point_bounds) + # Try creating a coordinate of the same type as before, otherwise, + # make an AuxCoord. + try: + mid_point_coord = coord.from_coord(coord).copy(mid_point_points, + mid_point_bounds) except ValueError: - mid_point_coord = iris.coords.AuxCoord.from_coord(coord).copy(mid_point_points, mid_point_bounds) + mid_point_coord = iris.coords.AuxCoord.from_coord(coord).copy( + mid_point_points, mid_point_bounds) return mid_point_coord def cube_delta(cube, coord): """ - Given a cube calculate the difference between each value in the given coord's direction. + Given a cube calculate the difference between each value in the + given coord's direction. Args: * coord either a Coord instance or the unique name of a coordinate in the cube. - If a Coord instance is provided, it does not necessarily have to exist in the cube. + If a Coord instance is provided, it does not necessarily have to + exist in the cube. Example usage:: - change_in_temperature_wrt_pressure = cube_delta(temperature_cube, 'pressure') + change_in_temperature_wrt_pressure = \ +cube_delta(temperature_cube, 'pressure') .. note:: Missing data support not yet implemented. """ # handle the case where a user passes a coordinate name - if isinstance(coord, basestring): + if isinstance(coord, six.string_types): coord = cube.coord(coord) if coord.ndim != 1: @@ -142,41 +161,52 @@ def cube_delta(cube, coord): # Try and get a coord dim delta_dims = cube.coord_dims(coord.name()) - if (coord.shape[0] == 1 and not getattr(coord, 'circular', False)) or not delta_dims: - raise ValueError('Cannot calculate delta over "%s" as it has length of 1.' % coord.name()) + if ((coord.shape[0] == 1 and not getattr(coord, 'circular', False)) or + not delta_dims): + raise ValueError('Cannot calculate delta over {!r} as it has ' + 'length of 1.'.format(coord.name())) delta_dim = delta_dims[0] - # Calculate the actual delta, taking into account whether the given coordinate is circular - delta_cube_data = delta(cube.data, delta_dim, circular=getattr(coord, 'circular', False)) + # Calculate the actual delta, taking into account whether the given + # coordinate is circular. + delta_cube_data = delta(cube.data, delta_dim, + circular=getattr(coord, 'circular', False)) # If the coord/dim is circular there is no change in cube shape if getattr(coord, 'circular', False): delta_cube = cube.copy(data=delta_cube_data) else: - # Subset the cube to the appropriate new shape by knocking off the last row of the delta dimension - subset_slice = [slice(None,None)] * cube.ndim + # Subset the cube to the appropriate new shape by knocking off + # the last row of the delta dimension. + subset_slice = [slice(None, None)] * cube.ndim subset_slice[delta_dim] = slice(None, -1) delta_cube = cube[tuple(subset_slice)] delta_cube.data = delta_cube_data - # Replace the delta_dim coords with midpoints (no shape change if circular). + # Replace the delta_dim coords with midpoints + # (no shape change if circular). for cube_coord in cube.coords(dimensions=delta_dim): - delta_cube.replace_coord(_construct_midpoint_coord(cube_coord, circular=getattr(coord, 'circular', False))) + delta_cube.replace_coord(_construct_midpoint_coord( + cube_coord, circular=getattr(coord, 'circular', False))) - delta_cube.rename('change_in_%s_wrt_%s' % (delta_cube.name(), coord.name())) + delta_cube.rename('change_in_{}_wrt_{}'.format(delta_cube.name(), + coord.name())) return delta_cube def differentiate(cube, coord_to_differentiate): r""" - Calculate the differential of a given cube with respect to the coord_to_differentiate. + Calculate the differential of a given cube with respect to the + coord_to_differentiate. Args: * coord_to_differentiate: - Either a Coord instance or the unique name of a coordinate which exists in the cube. - If a Coord instance is provided, it does not necessarily have to exist on the cube. + Either a Coord instance or the unique name of a coordinate which + exists in the cube. + If a Coord instance is provided, it does not necessarily have to + exist on the cube. Example usage:: @@ -188,13 +218,32 @@ def differentiate(cube, coord_to_differentiate): d_i = \frac{v_{i+1}-v_i}{c_{i+1}-c_i} - Where ``d`` is the differential, ``v`` is the data value, ``c`` is the coordinate value and ``i`` is the index in the differential - direction. Hence, in a normal situation if a cube has a shape (x: n; y: m) differentiating with respect to x will result in a cube - of shape (x: n-1; y: m) and differentiating with respect to y will result in (x: n; y: m-1). If the coordinate to differentiate is - :attr:`circular ` then the resultant shape will be the same as the input cube. - - - .. note:: Difference method used is the same as :func:`cube_delta` and therefore has the same limitations. + Where ``d`` is the differential, ``v`` is the data value, ``c`` is + the coordinate value and ``i`` is the index in the differential + direction. Hence, in a normal situation if a cube has a shape + (x: n; y: m) differentiating with respect to x will result in a cube + of shape (x: n-1; y: m) and differentiating with respect to y will + result in (x: n; y: m-1). If the coordinate to differentiate is + :attr:`circular ` then the resultant + shape will be the same as the input cube. + + In the returned cube the `coord_to_differentiate` object is + redefined such that the output coordinate values are set to the + averages of the original coordinate values (i.e. the mid-points). + Similarly, the output lower bounds values are set to the averages of + the original lower bounds values and the output upper bounds values + are set to the averages of the original upper bounds values. In more + formal terms: + + * `C[i] = (c[i] + c[i+1]) / 2` + * `B[i, 0] = (b[i, 0] + b[i+1, 0]) / 2` + * `B[i, 1] = (b[i, 1] + b[i+1, 1]) / 2` + + where `c` and `b` represent the input coordinate values and bounds, + and `C` and `B` the output coordinate values and bounds. + + .. note:: Difference method used is the same as :func:`cube_delta` + and therefore has the same limitations. .. note:: Spherical differentiation does not occur in this routine. @@ -203,7 +252,7 @@ def differentiate(cube, coord_to_differentiate): # This operation results in a copy of the original cube. delta_cube = cube_delta(cube, coord_to_differentiate) - if isinstance(coord_to_differentiate, basestring): + if isinstance(coord_to_differentiate, six.string_types): coord = cube.coord(coord_to_differentiate) else: coord = coord_to_differentiate @@ -215,23 +264,27 @@ def differentiate(cube, coord_to_differentiate): delta_cube = iris.analysis.maths.divide(delta_cube, delta_coord, delta_dim) # Update the standard name - delta_cube.rename(('derivative_of_%s_wrt_%s' % (cube.name(), coord.name())) ) + delta_cube.rename('derivative_of_{}_wrt_{}'.format(cube.name(), + coord.name())) return delta_cube def _curl_subtract(a, b): """ - Simple wrapper to :func:`iris.analysis.maths.subtract` to subtract two cubes, which deals with None in a way that makes sense in the context of curl. + Simple wrapper to :func:`iris.analysis.maths.subtract` to subtract + two cubes, which deals with None in a way that makes sense in the + context of curl. """ - # We are definitely dealing with cubes or None - otherwise we have a programmer error... + # We are definitely dealing with cubes or None - otherwise we have a + # programmer error... assert isinstance(a, iris.cube.Cube) or a is None assert isinstance(b, iris.cube.Cube) or b is None if a is None and b is None: return None elif a is None: - c = b.copy(data = 0 - b.data) + c = b.copy(data=0 - b.data) return c elif b is None: return a.copy() @@ -241,10 +294,12 @@ def _curl_subtract(a, b): def _curl_differentiate(cube, coord): """ - Simple wrapper to :func:`differentiate` to differentiate a cube and deal with None in a way that makes sense in the context of curl. + Simple wrapper to :func:`differentiate` to differentiate a cube and + deal with None in a way that makes sense in the context of curl. """ - # We are definitely dealing with cubes/coords or None - otherwise we have a programmer error... + # We are definitely dealing with cubes/coords or None - otherwise we + # have a programmer error... assert isinstance(cube, iris.cube.Cube) or cube is None assert isinstance(coord, iris.coords.Coord) or coord is None @@ -260,17 +315,20 @@ def _curl_differentiate(cube, coord): def _curl_regrid(cube, prototype): """ - Simple wrapper to :ref`iris.cube.Cube.regridded` to deal with None in a way that makes sense in the context of curl. + Simple wrapper to :ref`iris.cube.Cube.regridded` to deal with None + in a way that makes sense in the context of curl. """ - # We are definitely dealing with cubes or None - otherwise we have a programmer error... + # We are definitely dealing with cubes or None - otherwise we have a + # programmer error... assert isinstance(cube, iris.cube.Cube) or cube is None assert isinstance(prototype, iris.cube.Cube) if cube is None: - return None - # #301 use of resample would be better here. - return cube.regridded(prototype) + result = None + else: + result = cube.regrid(prototype, iris.analysis.Linear()) + return result def _copy_cube_transformed(src_cube, data, coord_func): @@ -286,6 +344,7 @@ def _copy_cube_transformed(src_cube, data, coord_func): # Start with just the metadata and the data... new_cube = iris.cube.Cube(data) new_cube.metadata = src_cube.metadata + new_cube.metadata = src_cube.metadata # ... and then create all the coordinates. @@ -319,12 +378,14 @@ def _curl_change_z(src_cube, z_coord, prototype_diff): # new cube using the prototype z_coord. local_z_coord = src_cube.coord(z_coord) new_local_z_coord = prototype_diff.coord(z_coord).copy() + def coord_func(coord): if coord is local_z_coord: new_coord = new_local_z_coord else: new_coord = coord.copy() return new_coord + result = _copy_cube_transformed(src_cube, new_data, coord_func) return result @@ -382,9 +443,14 @@ def _trig_method(coord, trig_function): return trig_coord -def curl(i_cube, j_cube, k_cube=None, ignore=None): - r''' - Calculate the 3d curl of the given vector of cubes. +def curl(i_cube, j_cube, k_cube=None): + r""" + Calculate the 2-dimensional or 3-dimensional spherical or cartesian + curl of the given vector of cubes. + + As well as the standard x and y coordinates, this function requires each + cube to possess a vertical or z-like coordinate (representing some form + of height or pressure). This can be a scalar or dimension coordinate. Args: @@ -400,36 +466,64 @@ def curl(i_cube, j_cube, k_cube=None, ignore=None): Return (i_cmpt_curl_cube, j_cmpt_curl_cube, k_cmpt_curl_cube) - The calculation of curl is dependent on the type of :func:`iris.coord_systems.CoordSystem` in the cube: + If the k-cube is not passed in then the 2-dimensional curl will + be calculated, yielding the result: [None, None, k_cube]. + If the k-cube is passed in, the 3-dimensional curl will + be calculated, returning 3 component cubes. + + All cubes passed in must have the same data units, and those units + must be spatially-derived (e.g. 'm/s' or 'km/h'). + + The calculation of curl is dependent on the type of + :func:`~iris.coord_systems.CoordSystem` in the cube. + If the :func:`~iris.coord_systems.CoordSystem` is either + GeogCS or RotatedGeogCS, the spherical curl will be calculated; otherwise + the cartesian curl will be calculated: Cartesian curl + When cartesian calculus is used, i_cube is the u component, + j_cube is the v component and k_cube is the w component. + The Cartesian curl is defined as: .. math:: - \nabla\times \vec u = (\frac{\delta w}{\delta y} - \frac{\delta v}{\delta z}) \vec a_i - (\frac{\delta w}{\delta x} - \frac{\delta u}{\delta z})\vec a_j + (\frac{\delta v}{\delta x} - \frac{\delta u}{\delta y})\vec a_k + \nabla\times \vec u = + (\frac{\delta w}{\delta y} - \frac{\delta v}{\delta z})\vec a_i + - + (\frac{\delta w}{\delta x} - \frac{\delta u}{\delta z})\vec a_j + + + (\frac{\delta v}{\delta x} - \frac{\delta u}{\delta y})\vec a_k Spherical curl - When spherical calculus is used, i_cube is the phi vector component (e.g. eastward), j_cube is the theta component + When spherical calculus is used, i_cube is the :math:`\phi` vector + component (e.g. eastward), j_cube is the :math:`\theta` component (e.g. northward) and k_cube is the radial component. The spherical curl is defined as: .. math:: - \nabla\times \vec A = \frac{1}{r cos \theta}(\frac{\delta}{\delta \theta}(\vec A_\phi cos \theta) - \frac{\delta \vec A_\theta}{\delta \phi}) \vec r + \frac{1}{r}(\frac{1}{cos \theta} \frac{\delta \vec A_r}{\delta \phi} - \frac{\delta}{\delta r} (r \vec A_\phi))\vec \theta + \frac{1}{r}(\frac{\delta}{\delta r}(r \vec A_\theta) - \frac{\delta \vec A_r}{\delta \theta}) \vec \phi + \nabla\times \vec A = \frac{1}{r cos \theta} + (\frac{\delta}{\delta \theta} + (\vec A_\phi cos \theta) - + \frac{\delta \vec A_\theta}{\delta \phi}) \vec r + + \frac{1}{r}(\frac{1}{cos \theta} + \frac{\delta \vec A_r}{\delta \phi} - + \frac{\delta}{\delta r} (r \vec A_\phi))\vec \theta + + \frac{1}{r} + (\frac{\delta}{\delta r}(r \vec A_\theta) - + \frac{\delta \vec A_r}{\delta \theta}) \vec \phi where phi is longitude, theta is latitude. - ''' - if ignore is not None: - ignore = None - warnings.warn('The ignore keyword to iris.analysis.calculus.curl is deprecated, ignoring is now done automatically.') - - # Get the vector quantity names (i.e. ['easterly', 'northerly', 'vertical']) - vector_quantity_names, phenomenon_name = spatial_vectors_with_phenom_name(i_cube, j_cube, k_cube) + """ + # Get the vector quantity names. + # (i.e. ['easterly', 'northerly', 'vertical']) + vector_quantity_names, phenomenon_name = \ + spatial_vectors_with_phenom_name(i_cube, j_cube, k_cube) cubes = filter(None, [i_cube, j_cube, k_cube]) @@ -438,16 +532,21 @@ def curl(i_cube, j_cube, k_cube=None, ignore=None): bad_coords = coord_comparison['ungroupable_and_dimensioned'] if bad_coords: - raise ValueError("Coordinates found in one cube that describe a data dimension which weren't in the other " - "cube (%s), try removing this coordinate." % ', '.join([group.name() for group in bad_coords])) + raise ValueError("Coordinates found in one cube that describe " + "a data dimension which weren't in the other " + "cube ({}), try removing this coordinate.".format( + ', '.join(group.name() for group in bad_coords))) bad_coords = coord_comparison['resamplable'] if bad_coords: - raise ValueError('Some coordinates are different (%s), consider resampling.' % ', '.join([group.name() for group in bad_coords])) + raise ValueError('Some coordinates are different ({}), consider ' + 'resampling.'.format( + ', '.join(group.name() for group in bad_coords))) ignore_string = '' if coord_comparison['ignorable']: - ignore_string = ' (ignoring %s)' % ', '.join([group.name() for group in bad_coords]) + ignore_string = ' (ignoring {})'.format( + ', '.join(group.name() for group in bad_coords)) # Get the dim_coord, or None if none exist, for the xyz dimensions x_coord = i_cube.coord(axis='X') @@ -458,9 +557,10 @@ def curl(i_cube, j_cube, k_cube=None, ignore=None): horiz_cs = i_cube.coord_system('CoordSystem') - # Planar (non spherical) coords? - ellipsoidal = isinstance(horiz_cs, (iris.coord_systems.GeogCS, iris.coord_systems.RotatedGeogCS)) - if not ellipsoidal: + # Non-spherical coords? + spherical_coords = isinstance(horiz_cs, (iris.coord_systems.GeogCS, + iris.coord_systems.RotatedGeogCS)) + if not spherical_coords: # TODO Implement some mechanism for conforming to a common grid dj_dx = _curl_differentiate(j_cube, x_coord) @@ -472,7 +572,8 @@ def curl(i_cube, j_cube, k_cube=None, ignore=None): dj_dz = _curl_differentiate(j_cube, z_coord) dj_dz = _curl_regrid(dj_dz, prototype_diff) - # TODO Implement resampling in the vertical (which regridding does not support). + # TODO Implement resampling in the vertical (which regridding + # does not support). if dj_dz is not None and dj_dz.data.shape != prototype_diff.data.shape: dj_dz = _curl_change_z(dj_dz, z_coord, prototype_diff) @@ -483,7 +584,8 @@ def curl(i_cube, j_cube, k_cube=None, ignore=None): di_dz = _curl_differentiate(i_cube, z_coord) di_dz = _curl_regrid(di_dz, prototype_diff) - # TODO Implement resampling in the vertical (which regridding does not support). + # TODO Implement resampling in the vertical (which regridding + # does not support). if di_dz is not None and di_dz.data.shape != prototype_diff.data.shape: di_dz = _curl_change_z(di_dz, z_coord, prototype_diff) @@ -507,11 +609,14 @@ def curl(i_cube, j_cube, k_cube=None, ignore=None): else: # A_\phi = i ; A_\theta = j ; A_\r = k # theta = lat ; phi = long ; - # r_cmpt = 1/ ( r * cos(lat) ) * ( d/dtheta ( i_cube * sin( lat ) ) - d_j_cube_dphi ) + # r_cmpt = 1 / (r * cos(lat)) * + # (d/dtheta (i_cube * sin(lat)) - d_j_cube_dphi) # phi_cmpt = 1/r * ( d/dr (r * j_cube) - d_k_cube_dtheta) # theta_cmpt = 1/r * ( 1/cos(lat) * d_k_cube_dphi - d/dr (r * i_cube) - if y_coord.name() != 'latitude' or x_coord.name() != 'longitude': - raise ValueError('Expecting latitude as the y coord and longitude as the x coord for spherical curl.') + if y_coord.name() not in ['latitude', 'grid_latitude'] \ + or x_coord.name() not in ['longitude', 'grid_longitude']: + raise ValueError('Expecting latitude as the y coord and ' + 'longitude as the x coord for spherical curl.') # Get the radius of the earth - and check for sphericity ellipsoid = horiz_cs @@ -520,15 +625,16 @@ def curl(i_cube, j_cube, k_cube=None, ignore=None): if ellipsoid: # TODO: Add a test for this r = ellipsoid.semi_major_axis - r_unit = iris.unit.Unit("m") + r_unit = cf_units.Unit("m") spherical = (ellipsoid.inverse_flattening == 0.0) else: - r = iris.analysis.cartography.DEFAULT_SPHERICAL_EARTH_RADIUS - r_unit = iris.analysis.cartography.DEFAULT_SPHERICAL_EARTH_RADIUS_UNIT + r = DEFAULT_SPHERICAL_EARTH_RADIUS + r_unit = DEFAULT_SPHERICAL_EARTH_RADIUS_UNIT spherical = True if not spherical: - raise ValueError("Cannot take the curl over a non-spherical ellipsoid.") + raise ValueError('Cannot take the curl over a non-spherical ' + 'ellipsoid.') lon_coord = x_coord.copy() lat_coord = y_coord.copy() @@ -541,14 +647,17 @@ def curl(i_cube, j_cube, k_cube=None, ignore=None): dicos_dtheta = _curl_differentiate(temp, lat_coord) prototype_diff = dicos_dtheta - # r curl component: 1/ ( r * cos(lat) ) * ( dicos_dtheta - d_j_cube_dphi ) - # Since prototype_diff == dicos_dtheta we don't need to recalculate dicos_dtheta + # r curl component: 1 / (r * cos(lat)) * (d_j_cube_dphi - dicos_dtheta) + # Since prototype_diff == dicos_dtheta we don't need to + # recalculate dicos_dtheta. d_j_cube_dphi = _curl_differentiate(j_cube, lon_coord) d_j_cube_dphi = _curl_regrid(d_j_cube_dphi, prototype_diff) - new_lat_coord = d_j_cube_dphi.coord('latitude') + new_lat_coord = d_j_cube_dphi.coord(axis='Y') new_lat_cos_coord = _coord_cos(new_lat_coord) lat_dim = d_j_cube_dphi.coord_dims(new_lat_coord)[0] - r_cmpt = iris.analysis.maths.divide(_curl_subtract(dicos_dtheta, d_j_cube_dphi), r * new_lat_cos_coord, dim=lat_dim) + r_cmpt = iris.analysis.maths.divide(_curl_subtract(d_j_cube_dphi, + dicos_dtheta), + r * new_lat_cos_coord, dim=lat_dim) r_cmpt.units = r_cmpt.units / r_unit d_j_cube_dphi = dicos_dtheta = None @@ -571,7 +680,8 @@ def curl(i_cube, j_cube, k_cube=None, ignore=None): d_k_cube_dphi = _curl_differentiate(k_cube, lon_coord) d_k_cube_dphi = _curl_regrid(d_k_cube_dphi, prototype_diff) if d_k_cube_dphi is not None: - d_k_cube_dphi = iris.analysis.maths.divide(d_k_cube_dphi, lat_cos_coord) + d_k_cube_dphi = iris.analysis.maths.divide(d_k_cube_dphi, + lat_cos_coord) dri_dr = _curl_differentiate(r * i_cube, z_coord) if dri_dr is not None: dri_dr.units = dri_dr.units * r_unit @@ -594,48 +704,64 @@ def curl(i_cube, j_cube, k_cube=None, ignore=None): def spatial_vectors_with_phenom_name(i_cube, j_cube, k_cube=None): """ - Given 2 or 3 spatially dependent cubes, return a list of the spatial coordinate names with appropriate phenomenon name. + Given 2 or 3 spatially dependent cubes, return a list of the spatial + coordinate names with appropriate phenomenon name. - This routine is designed to identify the vector quantites which each of the cubes provided represent - and return a list of their 3d spatial dimension names and associated phenomenon. - For example, given a cube of "u wind" and "v wind" the return value would be (['u', 'v', 'w'], 'wind'):: + This routine is designed to identify the vector quantites which each + of the cubes provided represent and return a list of their 3d + spatial dimension names and associated phenomenon. + For example, given a cube of "u wind" and "v wind" the return value + would be (['u', 'v', 'w'], 'wind'):: - >>> spatial_vectors_with_phenom_name(u_wind_cube, v_wind_cube) #doctest: +SKIP + >>> spatial_vectors_with_phenom_name(u_wind_cube, v_wind_cube) \ +#doctest: +SKIP (['u', 'v', 'w'], 'wind') """ directional_names = (('u', 'v', 'w'), ('x', 'y', 'z'), ('i', 'j', 'k'), ('eastward', 'northward', 'upward'), - ('easterly', 'northerly', 'vertical'), ('easterly', 'northerly', 'radial')) + ('easterly', 'northerly', 'vertical'), + ('easterly', 'northerly', 'radial')) - # Create a list of the standard_names of our incoming cubes (excluding the k_cube if it is None) - cube_standard_names = [cube.name() for cube in (i_cube, j_cube, k_cube) if cube is not None] + # Create a list of the standard_names of our incoming cubes + # (excluding the k_cube if it is None). + cube_standard_names = [cube.name() for cube in (i_cube, j_cube, k_cube) + if cube is not None] - # Define a regular expr which represents (direction, phenomenon) from the standard name of a cube + # Define a regular expr which represents (direction, phenomenon) + # from the standard name of a cube. # e.g from "w wind" -> ("w", "wind") vector_qty = re.compile(r'([^\W_]+)[\W_]+(.*)') # Make a dictionary of {direction: phenomenon quantity} - cube_directions, cube_phenomena = zip( *[re.match(vector_qty, std_name).groups() for std_name in cube_standard_names] ) + cube_directions, cube_phenomena = zip( + *[re.match(vector_qty, std_name).groups() + for std_name in cube_standard_names]) # Check that there is only one distinct phenomenon if len(set(cube_phenomena)) != 1: - raise ValueError('Vector phenomenon name not consistent between vector cubes. Got ' - 'cube phenomena: %s; from standard names: %s.' % \ - (', '.join(cube_phenomena), ', '.join(cube_standard_names)) - ) - - # Get the appropriate direction list from the cube_directions we have got from the standard name + raise ValueError('Vector phenomenon name not consistent between ' + 'vector cubes. Got cube phenomena: {}; from ' + 'standard names: {}.'.format( + ', '.join(cube_phenomena), + ', '.join(cube_standard_names))) + + # Get the appropriate direction list from the cube_directions we + # have got from the standard name. direction = None for possible_direction in directional_names: - # if this possible direction (minus the k_cube if it is none) matches direction from the given cubes use it. + # If this possible direction (minus the k_cube if it is none) + # matches direction from the given cubes use it. if possible_direction[0:len(cube_directions)] == cube_directions: direction = possible_direction # If we didn't get a match, raise an Exception if direction is None: - direction_string = '; '.join((', '.join(possible_direction) for possible_direction in directional_names)) - raise ValueError('%s are not recognised vector cube_directions. Possible cube_directions are: %s.' % \ - (cube_directions, direction_string) ) + direction_string = '; '.join(', '.join(possible_direction) + for possible_direction + in directional_names) + raise ValueError('{} are not recognised vector cube_directions. ' + 'Possible cube_directions are: {}.'.format( + cube_directions, direction_string)) return (direction, cube_phenomena[0]) diff --git a/lib/iris/analysis/cartography.py b/lib/iris/analysis/cartography.py index dc707be577..a778f5f846 100644 --- a/lib/iris/analysis/cartography.py +++ b/lib/iris/analysis/cartography.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -18,11 +18,15 @@ Various utilities and numeric transformations relevant to cartography. """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +from collections import namedtuple import copy -import itertools -import math import warnings +import cf_units import numpy as np import numpy.ma as ma @@ -32,13 +36,34 @@ import iris.coords import iris.coord_systems import iris.exceptions -import iris.unit - +from iris.util import _meshgrid +from ._grid_angles import gridcell_angles, rotate_grid_vectors + +# List of contents to control Sphinx autodocs. +# Unfortunately essential to get docs for the grid_angles functions. +__all__ = [ + 'area_weights', + 'cosine_latitude_weights', + 'get_xy_contiguous_bounded_grids', + 'get_xy_grids', + 'gridcell_angles', + 'project', + 'rotate_grid_vectors', + 'rotate_pole', + 'rotate_winds', + 'unrotate_pole', + 'wrap_lons', + 'DistanceDifferential', + 'PartialDifferential'] # This value is used as a fall-back if the cube does not define the earth DEFAULT_SPHERICAL_EARTH_RADIUS = 6367470 # TODO: This should not be necessary, as CF is always in meters -DEFAULT_SPHERICAL_EARTH_RADIUS_UNIT = iris.unit.Unit('m') +DEFAULT_SPHERICAL_EARTH_RADIUS_UNIT = cf_units.Unit('m') +# Distance differentials for coordinate systems at specified locations +DistanceDifferential = namedtuple('DistanceDifferential', 'dx1 dy1 dx2 dy2') +# Partial differentials between coordinate systems +PartialDifferential = namedtuple('PartialDifferential', 'dx1 dy1') def wrap_lons(lons, base, period): @@ -51,23 +76,50 @@ def wrap_lons(lons, base, period): from iris.analysis.cartography import wrap_lons For example: - >>> print wrap_lons(np.array([185, 30, -200, 75]), -180, 360) - [-175 30 160 75] + >>> print(wrap_lons(np.array([185, 30, -200, 75]), -180, 360)) + [-175. 30. 160. 75.] """ + # It is important to use 64bit floating precision when changing a floats + # numbers range. + lons = lons.astype(np.float64) return ((lons - base + period * 2) % period) + base def unrotate_pole(rotated_lons, rotated_lats, pole_lon, pole_lat): """ - Convert rotated-pole lons and lats to unrotated ones. + Convert arrays of rotated-pole longitudes and latitudes to unrotated + arrays of longitudes and latitudes. The values of ``pole_lon`` and + ``pole_lat`` should describe the location of the rotated pole that + describes the arrays of rotated-pole longitudes and latitudes. + + As the arrays of rotated-pole longitudes and latitudes must describe a + rectilinear grid, the arrays of rotated-pole longitudes and latitudes must + be of the same shape as each other. Example:: - lons, lats = unrotate_pole(grid_lons, grid_lats, pole_lon, pole_lat) + lons, lats = unrotate_pole(rotated_lons, rotated_lats, \ + pole_lon, pole_lat) .. note:: Uses proj.4 to perform the conversion. + Args: + + * rotated_lons: + An array of rotated-pole longitude values. + * rotated_lats: + An array of rotated-pole latitude values. + * pole_lon: + The longitude of the rotated pole that describes the arrays of + rotated-pole longitudes and latitudes. + * pole_lat: + The latitude of the rotated pole that describes the arrays of + rotated-pole longitudes and latitudes. + + Returns: + An array of unrotated longitudes and an array of unrotated latitudes. + """ src_proj = ccrs.RotatedGeodetic(pole_longitude=pole_lon, pole_latitude=pole_lat) @@ -82,14 +134,39 @@ def unrotate_pole(rotated_lons, rotated_lats, pole_lon, pole_lat): def rotate_pole(lons, lats, pole_lon, pole_lat): """ - Convert arrays of lons and lats to ones on a rotated pole. + Convert arrays of longitudes and latitudes to arrays of rotated-pole + longitudes and latitudes. The values of ``pole_lon`` and ``pole_lat`` + should describe the rotated pole that the arrays of longitudes and + latitudes are to be rotated onto. + + As the arrays of longitudes and latitudes must describe a rectilinear grid, + the arrays of rotated-pole longitudes and latitudes must be of the same + shape as each other. Example:: - grid_lons, grid_lats = rotate_pole(lons, lats, pole_lon, pole_lat) + rotated_lons, rotated_lats = rotate_pole(lons, lats,\ + pole_lon, pole_lat) .. note:: Uses proj.4 to perform the conversion. + Args: + + * lons: + An array of longitude values. + * lats: + An array of latitude values. + * pole_lon: + The longitude of the rotated pole that the arrays of longitudes and + latitudes are to be rotated onto. + * pole_lat: + The latitude of the rotated pole that the arrays of longitudes and + latitudes are to be rotated onto. + + Returns: + An array of rotated-pole longitudes and an array of rotated-pole + latitudes. + """ src_proj = ccrs.Geodetic() target_proj = ccrs.RotatedGeodetic(pole_longitude=pole_lon, @@ -102,18 +179,18 @@ def rotate_pole(lons, lats, pole_lon, pole_lat): return rotated_lon, rotated_lat -def _get_lat_lon_coords(cube): - lat_coords = filter(lambda coord: "latitude" in coord.name(), - cube.coords()) - lon_coords = filter(lambda coord: "longitude" in coord.name(), - cube.coords()) +def _get_lon_lat_coords(cube): + lat_coords = [coord for coord in cube.coords() + if "latitude" in coord.name()] + lon_coords = [coord for coord in cube.coords() + if "longitude" in coord.name()] if len(lat_coords) > 1 or len(lon_coords) > 1: raise ValueError( - "Calling _get_lat_lon_coords() with multiple lat or lon coords" + "Calling `_get_lon_lat_coords` with multiple lat or lon coords" " is currently disallowed") lat_coord = lat_coords[0] lon_coord = lon_coords[0] - return (lat_coord, lon_coord) + return (lon_coord, lat_coord) def _xy_range(cube, mode=None): @@ -142,7 +219,7 @@ def _xy_range(cube, mode=None): x_coord, y_coord = cube.coord(axis="X"), cube.coord(axis="Y") cs = cube.coord_system('CoordSystem') - if x_coord.has_bounds() != x_coord.has_bounds(): + if x_coord.has_bounds() != y_coord.has_bounds(): raise ValueError( 'Cannot get the range of the x and y coordinates if they do ' 'not have the same presence of bounds.') @@ -200,7 +277,7 @@ def get_xy_grids(cube): if x.ndim == y.ndim == 1: # Convert to 2D. - x, y = np.meshgrid(x, y) + x, y = _meshgrid(x, y) elif x.ndim == y.ndim == 2: # They are already in the correct shape. pass @@ -225,53 +302,54 @@ def get_xy_contiguous_bounded_grids(cube): x = x_coord.contiguous_bounds() y = y_coord.contiguous_bounds() - x, y = np.meshgrid(x, y) + x, y = _meshgrid(x, y) return (x, y) -def _quadrant_area(radian_colat_bounds, radian_lon_bounds, radius_of_earth): +def _quadrant_area(radian_lat_bounds, radian_lon_bounds, radius_of_earth): """Calculate spherical segment areas. - - radian_colat_bounds -- [n,2] array of colatitude bounds (radians) - - radian_lon_bounds -- [n,2] array of longitude bounds (radians) - - radius_of_earth -- radius of the earth - (currently assumed spherical) + - radian_lat_bounds -- [n,2] array of latitude bounds (radians) + - radian_lon_bounds -- [n,2] array of longitude bounds (radians) + - radius_of_earth -- radius of the earth + (currently assumed spherical) Area weights are calculated for each lat/lon cell as: .. math:: - r^2 (lon_1 - lon_0) ( cos(colat_0) - cos(colat_1)) + r^2 (lon_1 - lon_0) ( sin(lat_1) - sin(lat_0)) The resulting array will have a shape of - *(radian_colat_bounds.shape[0], radian_lon_bounds.shape[0])* + *(radian_lat_bounds.shape[0], radian_lon_bounds.shape[0])* + + The calculations are done at 64 bit precision and the returned array + will be of type numpy.float64. """ - #ensure pairs of bounds - if (radian_colat_bounds.shape[-1] != 2 or + # ensure pairs of bounds + if (radian_lat_bounds.shape[-1] != 2 or radian_lon_bounds.shape[-1] != 2 or - radian_colat_bounds.ndim != 2 or + radian_lat_bounds.ndim != 2 or radian_lon_bounds.ndim != 2): raise ValueError("Bounds must be [n,2] array") - #fill in a new array of areas + # fill in a new array of areas radius_sqr = radius_of_earth ** 2 - areas = np.ndarray((radian_colat_bounds.shape[0], - radian_lon_bounds.shape[0])) - # we use abs because backwards bounds (min > max) give negative areas. - for j in range(radian_colat_bounds.shape[0]): - areas[j, :] = [(radius_sqr * math.cos(radian_colat_bounds[j, 0]) * - (radian_lon_bounds[i, 1] - radian_lon_bounds[i, 0])) - - (radius_sqr * math.cos(radian_colat_bounds[j, 1]) * - (radian_lon_bounds[i, 1] - radian_lon_bounds[i, 0])) - for i in range(radian_lon_bounds.shape[0])] + radian_lat_64 = radian_lat_bounds.astype(np.float64) + radian_lon_64 = radian_lon_bounds.astype(np.float64) + + ylen = np.sin(radian_lat_64[:, 1]) - np.sin(radian_lat_64[:, 0]) + xlen = radian_lon_64[:, 1] - radian_lon_64[:, 0] + areas = radius_sqr * np.outer(ylen, xlen) + # we use abs because backwards bounds (min > max) give negative areas. return np.abs(areas) def area_weights(cube, normalize=False): - """ + r""" Returns an array of area weights, with the same dimensions as the cube. This is a 2D lat/lon area weights array, repeated over the non lat/lon @@ -294,7 +372,7 @@ def area_weights(cube, normalize=False): .. math:: - r^2 cos(lat_0) (lon_1 - lon_0) - r^2 cos(lat_1) (lon_1 - lon_0) + r^2 (lon_1 - lon_0) (\sin(lat_1) - \sin(lat_0)) Currently, only supports a spherical datum. Uses earth radius from the cube, if present and spherical. @@ -318,7 +396,7 @@ def area_weights(cube, normalize=False): # Get the lon and lat coords and axes try: - lat, lon = _get_lat_lon_coords(cube) + lon, lat = _get_lon_lat_coords(cube) except IndexError: raise ValueError('Cannot get latitude/longitude ' 'coordinates from cube {!r}.'.format(cube.name())) @@ -335,20 +413,27 @@ def area_weights(cube, normalize=False): lon_dim = lon_dim[0] if lon_dim else None if not (lat.has_bounds() and lon.has_bounds()): - msg = "Coordinates {!r} and {!r} must have bounds to determine " \ - "the area weights.".format(lat.name(), lon.name()) + msg = ("Coordinates {!r} and {!r} must have bounds to determine " + "the area weights.".format(lat.name(), lon.name())) raise ValueError(msg) # Convert from degrees to radians lat = lat.copy() - lat.convert_units('radians') lon = lon.copy() - lon.convert_units('radians') + + for coord in (lat, lon): + if coord.units in (cf_units.Unit('degrees'), + cf_units.Unit('radians')): + coord.convert_units('radians') + else: + msg = ("Units of degrees or radians required, coordinate " + "{!r} has units: {!r}".format(coord.name(), + coord.units.name)) + raise ValueError(msg) # Create 2D weights from bounds. # Use the geographical area as the weight for each cell - # Convert latitudes to co-latitude. I.e from -90 --> +90 to 0 --> pi - ll_weights = _quadrant_area(lat.bounds + np.pi / 2., + ll_weights = _quadrant_area(lat.bounds, lon.bounds, radius_of_earth) # Normalize the weights if necessary. @@ -358,7 +443,7 @@ def area_weights(cube, normalize=False): # Now we create an array of weights for each cell. This process will # handle adding the required extra dimensions and also take care of # the order of dimensions. - broadcast_dims = filter(lambda x: x is not None, (lat_dim, lon_dim)) + broadcast_dims = [x for x in (lat_dim, lon_dim) if x is not None] wshape = [] for idim, dim in zip((0, 1), (lat_dim, lon_dim)): if dim is not None: @@ -372,7 +457,7 @@ def area_weights(cube, normalize=False): def cosine_latitude_weights(cube): - """ + r""" Returns an array of latitude weights, with the same dimensions as the cube. The weights are the cosine of latitude. @@ -407,8 +492,8 @@ def cosine_latitude_weights(cube): """ # Find all latitude coordinates, we want one and only one. - lat_coords = filter(lambda coord: "latitude" in coord.name(), - cube.coords()) + lat_coords = [coord for coord in cube.coords() + if "latitude" in coord.name()] if len(lat_coords) > 1: raise ValueError("Multiple latitude coords are currently disallowed.") try: @@ -441,7 +526,7 @@ def cosine_latitude_weights(cube): # Create weights for each grid point. This operation handles adding extra # dimensions and also the order of the dimensions. - broadcast_dims = filter(lambda x: x is not None, lat_dims) + broadcast_dims = [x for x in lat_dims if x is not None] wshape = [] for idim, dim in enumerate(lat_dims): if dim is not None: @@ -507,7 +592,7 @@ def project(cube, target_proj, nx=None, ny=None): """ try: - lat_coord, lon_coord = _get_lat_lon_coords(cube) + lon_coord, lat_coord = _get_lon_lat_coords(cube) except IndexError: raise ValueError('Cannot get latitude/longitude ' 'coordinates from cube {!r}.'.format(cube.name())) @@ -541,7 +626,7 @@ def project(cube, target_proj, nx=None, ny=None): source_x = lon_coord.points source_y = lat_coord.points if source_x.ndim != 2 or source_y.ndim != 2: - source_x, source_y = np.meshgrid(source_x, source_y) + source_x, source_y = _meshgrid(source_x, source_y) # Calculate target grid target_cs = None @@ -602,32 +687,32 @@ def project(cube, target_proj, nx=None, ny=None): 'to have 1 or 2 dimensions, got {} and ' '{}.'.format(lat_coord.ndim, lon_coord.ndim)) - ## Mask out points outside of extent in source_cs - disabled until - ## a way to specify global/limited extent is agreed upon and code - ## is generalised to handle -180 to +180, 0 to 360 and >360 longitudes. - #source_desired_xy = source_cs.transform_points(target_proj, - # target_x.flatten(), - # target_y.flatten()) - #if np.any(source_x < 0.0) and np.any(source_x > 180.0): - # raise ValueError('Unable to handle range of longitude.') - ## This does not work in all cases e.g. lon > 360 - #if np.any(source_x > 180.0): - # source_desired_x = (source_desired_xy[:, 0].reshape(ny, nx) + - # 360.0) % 360.0 - #else: - # source_desired_x = source_desired_xy[:, 0].reshape(ny, nx) - #source_desired_y = source_desired_xy[:, 1].reshape(ny, nx) - #outof_extent_points = ((source_desired_x < source_x.min()) | - # (source_desired_x > source_x.max()) | - # (source_desired_y < source_y.min()) | - # (source_desired_y > source_y.max())) - ## Make array a mask by default (rather than a single bool) to allow mask - ## to be assigned to slices. - #new_data.mask = np.zeros(new_shape) +# # Mask out points outside of extent in source_cs - disabled until +# # a way to specify global/limited extent is agreed upon and code +# # is generalised to handle -180 to +180, 0 to 360 and >360 longitudes. +# source_desired_xy = source_cs.transform_points(target_proj, +# target_x.flatten(), +# target_y.flatten()) +# if np.any(source_x < 0.0) and np.any(source_x > 180.0): +# raise ValueError('Unable to handle range of longitude.') +# # This does not work in all cases e.g. lon > 360 +# if np.any(source_x > 180.0): +# source_desired_x = (source_desired_xy[:, 0].reshape(ny, nx) + +# 360.0) % 360.0 +# else: +# source_desired_x = source_desired_xy[:, 0].reshape(ny, nx) +# source_desired_y = source_desired_xy[:, 1].reshape(ny, nx) +# outof_extent_points = ((source_desired_x < source_x.min()) | +# (source_desired_x > source_x.max()) | +# (source_desired_y < source_y.min()) | +# (source_desired_y > source_y.max())) +# # Make array a mask by default (rather than a single bool) to allow mask +# # to be assigned to slices. +# new_data.mask = np.zeros(new_shape) # Step through cube data, regrid onto desired projection and insert results # in new_data array - for index, ll_slice in itertools.izip(index_it, slice_it): + for index, ll_slice in zip(index_it, slice_it): # Regrid source data onto target grid index = list(index) index[xdim] = slice(None, None) @@ -638,8 +723,8 @@ def project(cube, target_proj, nx=None, ny=None): target_proj, target_x, target_y) - ## Mask out points beyond extent - #new_data[index].mask[outof_extent_points] = True +# # Mask out points beyond extent +# new_data[index].mask[outof_extent_points] = True # Remove mask if it is unnecessary if not np.any(new_data.mask): @@ -649,12 +734,12 @@ def project(cube, target_proj, nx=None, ny=None): new_cube = iris.cube.Cube(new_data) # Add new grid coords - x_coord = iris.coords.DimCoord( - target_x[0, :], 'projection_x_coordinate', - coord_system=copy.copy(target_cs)) - y_coord = iris.coords.DimCoord( - target_y[:, 0], 'projection_y_coordinate', - coord_system=copy.copy(target_cs)) + x_coord = iris.coords.DimCoord(target_x[0, :], 'projection_x_coordinate', + units='m', + coord_system=copy.copy(target_cs)) + y_coord = iris.coords.DimCoord(target_y[:, 0], 'projection_y_coordinate', + units='m', + coord_system=copy.copy(target_cs)) new_cube.add_dim_coord(x_coord, xdim) new_cube.add_dim_coord(y_coord, ydim) @@ -699,3 +784,395 @@ def project(cube, target_proj, nx=None, ny=None): new_cube.metadata = cube.metadata return new_cube, extent + + +def _transform_xy(crs_from, x, y, crs_to): + """ + Shorthand function to transform 2d points between coordinate + reference systems. + + Args: + + * crs_from, crs_to (:class:`cartopy.crs.Projection`): + The coordinate reference systems. + * x, y (arrays): + point locations defined in 'crs_from'. + + Returns: + x, y : Arrays of locations defined in 'crs_to'. + + """ + pts = crs_to.transform_points(crs_from, x, y) + return pts[..., 0], pts[..., 1] + + +def _inter_crs_differentials(crs1, x, y, crs2): + """ + Calculate coordinate partial differentials from crs1 to crs2. + + Returns dx2/dx1, dy2/dx1, dx2/dy1 and dy2/dy1, at given locations. + + Args: + + * crs1, crs2 (`cartopy.crs.Projection`): + The coordinate systems, "from" and "to". + * x, y (array): + Point locations defined in 'crs1'. + + Returns: + (dx2/dx1, dy2/dx1, dx2/dy1, dy2/dy1) at given locations. Each + element of this tuple will be the same shape as the 'x' and 'y' + arrays and will be the partial differentials between the two systems. + + """ + # Get locations in target crs. + crs2_x, crs2_y = _transform_xy(crs1, x, y, crs2) + + # Define small x-deltas in the source crs. + VECTOR_DELTAS_FACTOR = 360000.0 # Empirical factor to obtain small delta. + delta_x = (crs1.x_limits[1] - crs1.x_limits[0]) / VECTOR_DELTAS_FACTOR + delta_x = delta_x * np.ones(x.shape) + eps = 1e-9 + # Reverse deltas where we would otherwise step outside the valid range. + invalid_dx = x + delta_x > crs1.x_limits[1] - eps + delta_x[invalid_dx] = -delta_x[invalid_dx] + # Calculate the transformed point with x = x + dx. + crs2_x2, crs2_y2 = _transform_xy(crs1, x + delta_x, y, crs2) + # Form differentials wrt dx. + dx2_dx = (crs2_x2 - crs2_x) / delta_x + dy2_dx = (crs2_y2 - crs2_y) / delta_x + + # Define small y-deltas in the source crs. + delta_y = (crs1.y_limits[1] - crs1.y_limits[0]) / VECTOR_DELTAS_FACTOR + delta_y = delta_y * np.ones(y.shape) + # Reverse deltas where we would otherwise step outside the valid range. + invalid_dy = y + delta_y > crs1.y_limits[1] - eps + delta_y[invalid_dy] = -delta_y[invalid_dy] + # Calculate the transformed point with y = y + dy. + crs2_x2, crs2_y2 = _transform_xy(crs1, x, y + delta_y, crs2) + # Form differentials wrt dy. + dx2_dy = (crs2_x2 - crs2_x) / delta_y + dy2_dy = (crs2_y2 - crs2_y) / delta_y + + return dx2_dx, dy2_dx, dx2_dy, dy2_dy + + +def _crs_distance_differentials(crs, x, y): + """ + Calculate d(distance) / d(x) and ... / d(y) for a coordinate + reference system at specified locations. + + Args: + + * crs (:class:`cartopy.crs.Projection`): + The coordinate reference system. + * x, y (array): + Locations at which to calculate the differentials, + defined in 'crs' coordinate reference system. + + Returns: + (abs(ds/dx), abs(ds/dy)). + Numerically approximated partial differentials, + i.e. scaling factors between changes in distance and changes in + coordinate values. + + """ + # Make a true-latlon coordinate system for distance calculations. + crs_latlon = ccrs.Geodetic(globe=ccrs.Globe(ellipse='sphere')) + # Transform points to true-latlon (just to get the true latitudes). + _, true_lat = _transform_xy(crs, x, y, crs_latlon) + # Get coordinate differentials w.r.t. true-latlon. + dlon_dx, dlat_dx, dlon_dy, dlat_dy = \ + _inter_crs_differentials(crs, x, y, crs_latlon) + # Calculate effective scalings of X and Y coordinates. + lat_factor = np.cos(np.deg2rad(true_lat))**2 + ds_dx = np.sqrt(dlat_dx * dlat_dx + dlon_dx * dlon_dx * lat_factor) + ds_dy = np.sqrt(dlat_dy * dlat_dy + dlon_dy * dlon_dy * lat_factor) + return ds_dx, ds_dy + + +def _transform_distance_vectors(u_dist, v_dist, ds, dx2, dy2): + """ + Transform distance vectors from one coordinate reference system to + another, preserving magnitude and physical direction. + + Args: + + * u_dist, v_dist (array): + Components of each vector along the x and y directions of the source + crs at each location. + * ds (`DistanceDifferential`): + Distance differentials for the source and the target crs at specified + locations. + * dx2, dy2 (`PartialDifferential`): + Partial differentials from the source to the target crs. + + Returns: + (ut_dist, vt_dist): Tuple of arrays containing the vector components + along the x and y directions of the target crs at each location. + + """ + + # Scale input distance vectors --> source-coordinate differentials. + u1, v1 = u_dist / ds.dx1, v_dist / ds.dy1 + # Transform vectors into the target system. + u2 = dx2.dx1 * u1 + dx2.dy1 * v1 + v2 = dy2.dx1 * u1 + dy2.dy1 * v1 + # Rescale output coordinate vectors --> target distance vectors. + u2_dist, v2_dist = u2 * ds.dx2, v2 * ds.dy2 + + return u2_dist, v2_dist + + +def _transform_distance_vectors_tolerance_mask(src_crs, x, y, tgt_crs, + ds, dx2, dy2): + """ + Return a mask that can be applied to data array to mask elements + where the magnitude of vectors are not preserved due to numerical + errors introduced by the tranformation between coordinate systems. + + Args: + * src_crs (`cartopy.crs.Projection`): + The source coordinate reference systems. + * x, y (array): + Locations of each vector defined in 'src_crs'. + * tgt_crs (`cartopy.crs.Projection`): + The target coordinate reference systems. + * ds (`DistanceDifferential`): + Distance differentials for src_crs and tgt_crs at specified locations + * dx2, dy2 (`PartialDifferential`): + Partial differentials from src_crs to tgt_crs. + + Returns: + 2d boolean array that is the same shape as x and y. + + """ + if x.shape != y.shape: + raise ValueError('Arrays do not have matching shapes. ' + 'x.shape is {}, y.shape is {}.'.format(x.shape, + y.shape)) + ones = np.ones(x.shape) + zeros = np.zeros(x.shape) + u_one_t, v_zero_t = _transform_distance_vectors(ones, zeros, ds, dx2, dy2) + u_zero_t, v_one_t = _transform_distance_vectors(zeros, ones, ds, dx2, dy2) + # Squared magnitudes should be equal to one within acceptable tolerance. + # A value of atol=2e-3 is used, which corresponds to a change in magnitude + # of approximately 0.1%. + sqmag_1_0 = u_one_t**2 + v_zero_t**2 + sqmag_0_1 = u_zero_t**2 + v_one_t**2 + mask = np.logical_not( + np.logical_and(np.isclose(sqmag_1_0, ones, atol=2e-3), + np.isclose(sqmag_0_1, ones, atol=2e-3))) + return mask + + +def rotate_winds(u_cube, v_cube, target_cs): + r""" + Transform wind vectors to a different coordinate system. + + The input cubes contain U and V components parallel to the local X and Y + directions of the input grid at each point. + + The output cubes contain the same winds, at the same locations, but + relative to the grid directions of a different coordinate system. + Thus in vector terms, the magnitudes will always be the same, but the + angles can be different. + + The outputs retain the original horizontal dimension coordinates, but + also have two 2-dimensional auxiliary coordinates containing the X and + Y locations in the target coordinate system. + + Args: + + * u_cube + An instance of :class:`iris.cube.Cube` that contains the x-component + of the vector. + * v_cube + An instance of :class:`iris.cube.Cube` that contains the y-component + of the vector. + * target_cs + An instance of :class:`iris.coord_systems.CoordSystem` that specifies + the new grid directions. + + Returns: + A (u', v') tuple of :class:`iris.cube.Cube` instances that are the u + and v components in the requested target coordinate system. + The units are the same as the inputs. + + .. note:: + + The U and V values relate to distance, with units such as 'm s-1'. + These are not the same as coordinate vectors, which transform in a + different manner. + + .. note:: + + The names of the output cubes are those of the inputs, prefixed with + 'transformed\_' (e.g. 'transformed_x_wind'). + + .. warning:: + + Conversion between rotated-pole and non-rotated systems can be + expressed analytically. However, this function always uses a numerical + approach. In locations where this numerical approach does not preserve + magnitude to an accuracy of 0.1%, the corresponding elements of the + returned cubes will be masked. + + """ + # Check u_cube and v_cube have the same shape. We iterate through + # the u and v cube slices which relies on the shapes matching. + if u_cube.shape != v_cube.shape: + msg = 'Expected u and v cubes to have the same shape. ' \ + 'u cube has shape {}, v cube has shape {}.' + raise ValueError(msg.format(u_cube.shape, v_cube.shape)) + + # Check the u_cube and v_cube have the same x and y coords. + msg = 'Coordinates differ between u and v cubes. Coordinate {!r} from ' \ + 'u cube does not equal coordinate {!r} from v cube.' + if u_cube.coord(axis='x') != v_cube.coord(axis='x'): + raise ValueError(msg.format(u_cube.coord(axis='x').name(), + v_cube.coord(axis='x').name())) + if u_cube.coord(axis='y') != v_cube.coord(axis='y'): + raise ValueError(msg.format(u_cube.coord(axis='y').name(), + v_cube.coord(axis='y').name())) + + # Check x and y coords have the same coordinate system. + x_coord = u_cube.coord(axis='x') + y_coord = u_cube.coord(axis='y') + if x_coord.coord_system != y_coord.coord_system: + msg = "Coordinate systems of x and y coordinates differ. " \ + "Coordinate {!r} has a coord system of {!r}, but coordinate " \ + "{!r} has a coord system of {!r}." + raise ValueError(msg.format(x_coord.name(), x_coord.coord_system, + y_coord.name(), y_coord.coord_system)) + + # Convert from iris coord systems to cartopy CRSs to access + # transform functionality. Use projection as cartopy + # transform_vectors relies on x_limits and y_limits. + if x_coord.coord_system is not None: + src_crs = x_coord.coord_system.as_cartopy_projection() + else: + # Default to Geodetic (but actually use PlateCarree as a + # projection is needed). + src_crs = ccrs.PlateCarree() + target_crs = target_cs.as_cartopy_projection() + + # Check the number of dimensions of the x and y coords is the same. + # Subsequent logic assumes either both 1d or both 2d. + x = x_coord.points + y = y_coord.points + if x.ndim != y.ndim or x.ndim > 2 or y.ndim > 2: + msg = 'x and y coordinates must have the same number of dimensions ' \ + 'and be either 1D or 2D. The number of dimensions are {} and ' \ + '{}, respectively.'.format(x.ndim, y.ndim) + raise ValueError(msg) + + # Check the dimension mappings match between u_cube and v_cube. + if u_cube.coord_dims(x_coord) != v_cube.coord_dims(x_coord): + raise ValueError('Dimension mapping of x coordinate differs ' + 'between u and v cubes.') + if u_cube.coord_dims(y_coord) != v_cube.coord_dims(y_coord): + raise ValueError('Dimension mapping of y coordinate differs ' + 'between u and v cubes.') + x_dims = u_cube.coord_dims(x_coord) + y_dims = u_cube.coord_dims(y_coord) + + # Convert points to 2D, if not already, and determine dims. + if x.ndim == y.ndim == 1: + x, y = _meshgrid(x, y) + dims = (y_dims[0], x_dims[0]) + else: + dims = x_dims + + # Transpose x, y 2d arrays to match the order in cube's data + # array so that x, y and the sliced data all line up. + if dims[0] > dims[1]: + x = x.transpose() + y = y.transpose() + + # Create resulting cubes. + ut_cube = u_cube.copy() + vt_cube = v_cube.copy() + ut_cube.rename('transformed_{}'.format(u_cube.name())) + vt_cube.rename('transformed_{}'.format(v_cube.name())) + + # Get distance scalings for source crs. + ds_dx1, ds_dy1 = _crs_distance_differentials(src_crs, x, y) + + # Get distance scalings for target crs. + x2, y2 = _transform_xy(src_crs, x, y, target_crs) + ds_dx2, ds_dy2 = _crs_distance_differentials(target_crs, x2, y2) + + ds = DistanceDifferential(ds_dx1, ds_dy1, ds_dx2, ds_dy2) + + # Calculate coordinate partial differentials from source crs to target crs. + dx2_dx1, dy2_dx1, dx2_dy1, dy2_dy1 = _inter_crs_differentials(src_crs, + x, y, + target_crs) + + dx2 = PartialDifferential(dx2_dx1, dx2_dy1) + dy2 = PartialDifferential(dy2_dx1, dy2_dy1) + + # Calculate mask based on preservation of magnitude. + mask = _transform_distance_vectors_tolerance_mask(src_crs, x, y, + target_crs, + ds, dx2, dy2) + apply_mask = mask.any() + if apply_mask: + # Make masked arrays to accept masking. + ut_cube.data = ma.asanyarray(ut_cube.data) + vt_cube.data = ma.asanyarray(vt_cube.data) + + # Project vectors with u, v components one horiz slice at a time and + # insert into the resulting cubes. + shape = list(u_cube.shape) + for dim in dims: + shape[dim] = 1 + ndindex = np.ndindex(*shape) + for index in ndindex: + index = list(index) + for dim in dims: + index[dim] = slice(None, None) + index = tuple(index) + u = u_cube.data[index] + v = v_cube.data[index] + ut, vt = _transform_distance_vectors(u, v, ds, dx2, dy2) + if apply_mask: + ut = ma.asanyarray(ut) + ut[mask] = ma.masked + vt = ma.asanyarray(vt) + vt[mask] = ma.masked + ut_cube.data[index] = ut + vt_cube.data[index] = vt + + # Calculate new coords of locations in target coordinate system. + xyz_tran = target_crs.transform_points(src_crs, x, y) + xt = xyz_tran[..., 0].reshape(x.shape) + yt = xyz_tran[..., 1].reshape(y.shape) + + # Transpose xt, yt 2d arrays to match the dim order + # of the original x an y arrays - i.e. undo the earlier + # transpose (if applied). + if dims[0] > dims[1]: + xt = xt.transpose() + yt = yt.transpose() + + xt_coord = iris.coords.AuxCoord(xt, + standard_name='projection_x_coordinate', + coord_system=target_cs) + yt_coord = iris.coords.AuxCoord(yt, + standard_name='projection_y_coordinate', + coord_system=target_cs) + # Set units based on coord_system. + if isinstance(target_cs, (iris.coord_systems.GeogCS, + iris.coord_systems.RotatedGeogCS)): + xt_coord.units = yt_coord.units = 'degrees' + else: + xt_coord.units = yt_coord.units = 'm' + + ut_cube.add_aux_coord(xt_coord, dims) + ut_cube.add_aux_coord(yt_coord, dims) + vt_cube.add_aux_coord(xt_coord.copy(), dims) + vt_cube.add_aux_coord(yt_coord.copy(), dims) + + return ut_cube, vt_cube diff --git a/lib/iris/analysis/geometry.py b/lib/iris/analysis/geometry.py index e530b06509..cca5d836ec 100644 --- a/lib/iris/analysis/geometry.py +++ b/lib/iris/analysis/geometry.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -22,6 +22,11 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import warnings + from shapely.geometry import Polygon import numpy as np @@ -29,29 +34,17 @@ import iris.exceptions -def geometry_area_weights(cube, geometry): +def _extract_relevant_cube_slice(cube, geometry): """ - Returns the array of weights corresponding to the area of overlap between - the cells of cube's horizontal grid, and the given shapely geometry. + Given a shapely geometry object, this helper method returns + the tuple + (subcube, x_coord_of_subcube, y_coord_of_subcube, + (min_x_index, min_y_index, max_x_index, max_y_index)) - The returned array is suitable for use with :const:`iris.analysis.MEAN`. - - The cube must have bounded horizontal coordinates. - - .. note:: - This routine works in Euclidean space. Area calculations do not - account for the curvature of the Earth. And care must be taken to - ensure any longitude values are expressed over a suitable interval. - - Args: - - * cube (:class:`iris.cube.Cube`): - A Cube containing a bounded, horizontal grid definition. - * geometry (a shapely geometry instance): - The geometry of interest. To produce meaningful results this geometry - must have a non-zero area. Typically a Polygon or MultiPolygon. + If cube and geometry don't overlap, returns None. """ + # Validate the input parameters if not cube.coords(axis='x') or not cube.coords(axis='y'): raise ValueError('The cube must contain x and y axes.') @@ -59,7 +52,8 @@ def geometry_area_weights(cube, geometry): x_coords = cube.coords(axis='x') y_coords = cube.coords(axis='y') if len(x_coords) != 1 or len(y_coords) != 1: - raise ValueError('The cube must contain one, and only one, coordinate for each of the x and y axes.') + raise ValueError('The cube must contain one, and only one, coordinate ' + 'for each of the x and y axes.') x_coord = x_coords[0] y_coord = y_coords[0] @@ -71,24 +65,165 @@ def geometry_area_weights(cube, geometry): if y_coord.ndim != 1: raise iris.exceptions.CoordinateMultiDimError(y_coord) - # Figure out the shape of the horizontal dimensions - shape = [1] * len(cube.shape) - x_dim = cube.coord_dims(x_coord)[0] - y_dim = cube.coord_dims(y_coord)[0] - shape[x_dim] = x_coord.shape[0] - shape[y_dim] = y_coord.shape[0] - weights = np.empty(shape, np.float32) - - # Calculate the area weights + # bounds of cube dimensions x_bounds = x_coord.bounds y_bounds = y_coord.bounds - for nd_index in np.ndindex(weights.shape): + + # identify ascending/descending coordinate dimensions + x_ascending = x_coord.points[1] - x_coord.points[0] > 0. + y_ascending = y_coord.points[1] - y_coord.points[0] > 0. + + # identify upper/lower bounds of coordinate dimensions + x_bounds_lower = x_bounds[:, 0] if x_ascending else x_bounds[:, 1] + y_bounds_lower = y_bounds[:, 0] if y_ascending else y_bounds[:, 1] + x_bounds_upper = x_bounds[:, 1] if x_ascending else x_bounds[:, 0] + y_bounds_upper = y_bounds[:, 1] if y_ascending else y_bounds[:, 0] + + # find indices of coordinate bounds to fully cover geometry + x_min_geom, y_min_geom, x_max_geom, y_max_geom = geometry.bounds + try: + x_min_ix = np.where(x_bounds_lower <= x_min_geom)[0] + x_min_ix = x_min_ix[np.argmax(x_bounds_lower[x_min_ix])] + except ValueError: + warnings.warn("The geometry exceeds the cube's x dimension at the " + "lower end.", UserWarning) + x_min_ix = 0 if x_ascending else x_coord.points.size - 1 + + try: + x_max_ix = np.where(x_bounds_upper >= x_max_geom)[0] + x_max_ix = x_max_ix[np.argmin(x_bounds_upper[x_max_ix])] + except ValueError: + warnings.warn("The geometry exceeds the cube's x dimension at the " + "upper end.", UserWarning) + x_max_ix = x_coord.points.size - 1 if x_ascending else 0 + + try: + y_min_ix = np.where(y_bounds_lower <= y_min_geom)[0] + y_min_ix = y_min_ix[np.argmax(y_bounds_lower[y_min_ix])] + except ValueError: + warnings.warn("The geometry exceeds the cube's y dimension at the " + "lower end.", UserWarning) + y_min_ix = 0 if y_ascending else y_coord.points.size - 1 + + try: + y_max_ix = np.where(y_bounds_upper >= y_max_geom)[0] + y_max_ix = y_max_ix[np.argmin(y_bounds_upper[y_max_ix])] + except ValueError: + warnings.warn("The geometry exceeds the cube's y dimension at the " + "upper end.", UserWarning) + y_max_ix = y_coord.points.size - 1 if y_ascending else 0 + + # extract coordinate values at these indices + x_min = x_bounds_lower[x_min_ix] + x_max = x_bounds_upper[x_max_ix] + y_min = y_bounds_lower[y_min_ix] + y_max = y_bounds_upper[y_max_ix] + + # switch min and max if necessary, to create slice objects later on + if x_min_ix > x_max_ix: + x_min_ix, x_max_ix = x_max_ix, x_min_ix + if y_min_ix > y_max_ix: + y_min_ix, y_max_ix = y_max_ix, y_min_ix + bnds_ix = x_min_ix, y_min_ix, x_max_ix, y_max_ix + + # cut the relevant part from the original cube + coord_constr = {x_coord.name(): lambda x: x_min <= x.point <= x_max, + y_coord.name(): lambda y: y_min <= y.point <= y_max} + constraint = iris.Constraint(coord_values=coord_constr) + subcube = cube.extract(constraint) + + if subcube is None: + return None + else: + x_coord = subcube.coord(axis='x') + y_coord = subcube.coord(axis='y') + return subcube, x_coord, y_coord, bnds_ix + + +def geometry_area_weights(cube, geometry, normalize=False): + """ + Returns the array of weights corresponding to the area of overlap between + the cells of cube's horizontal grid, and the given shapely geometry. + + The returned array is suitable for use with :const:`iris.analysis.MEAN`. + + The cube must have bounded horizontal coordinates. + + .. note:: + This routine works in Euclidean space. Area calculations do not + account for the curvature of the Earth. And care must be taken to + ensure any longitude values are expressed over a suitable interval. + + .. note:: + This routine currently does not handle all out-of-bounds cases + correctly. In cases where both the coordinate bounds and the + geometry's bounds lie outside the physically realistic range + (i.e., abs(latitude) > 90., as it is commonly the case when + bounds are constructed via guess_bounds()), the weights + calculation might be wrong. In this case, a UserWarning will + be issued. + + Args: + + * cube (:class:`iris.cube.Cube`): + A Cube containing a bounded, horizontal grid definition. + * geometry (a shapely geometry instance): + The geometry of interest. To produce meaningful results this geometry + must have a non-zero area. Typically a Polygon or MultiPolygon. + + Kwargs: + + * normalize: + Calculate each individual cell weight as the cell area overlap between + the cell and the given shapely geometry divided by the total cell area. + Default is False. + + """ + + # extract smallest subcube containing geometry + shape = cube.shape + extraction_results = _extract_relevant_cube_slice(cube, geometry) + + # test if there is overlap between cube and geometry + if extraction_results is None: + return np.zeros(shape) + + subcube, subx_coord, suby_coord, bnds_ix = extraction_results + x_min_ix, y_min_ix, x_max_ix, y_max_ix = bnds_ix + + # prepare the weights array + subshape = list(cube.shape) + x_dim = cube.coord_dims(subx_coord)[0] + y_dim = cube.coord_dims(suby_coord)[0] + subshape[x_dim] = subx_coord.shape[0] + subshape[y_dim] = suby_coord.shape[0] + subx_bounds = subx_coord.bounds + suby_bounds = suby_coord.bounds + subweights = np.empty(subshape, np.float32) + + # calculate the area weights + for nd_index in np.ndindex(subweights.shape): xi = nd_index[x_dim] yi = nd_index[y_dim] - x0, x1 = x_bounds[xi] - y0, y1 = y_bounds[yi] + x0, x1 = subx_bounds[xi] + y0, y1 = suby_bounds[yi] polygon = Polygon([(x0, y0), (x0, y1), (x1, y1), (x1, y0)]) - weights[nd_index] = polygon.intersection(geometry).area + subweights[nd_index] = polygon.intersection(geometry).area + if normalize: + subweights[nd_index] /= polygon.area + + # pad the calculated weights with zeros to match original cube shape + weights = np.zeros(shape, np.float32) + slices = [] + for i in range(weights.ndim): + if i == x_dim: + slices.append(slice(x_min_ix, x_max_ix + 1)) + elif i == y_dim: + slices.append(slice(y_min_ix, y_max_ix + 1)) + else: + slices.append(slice(None)) + + weights[tuple(slices)] = subweights # Fix for the limitation of iris.analysis.MEAN weights handling. # Broadcast the array to the full shape of the cube diff --git a/lib/iris/analysis/interpolate.py b/lib/iris/analysis/interpolate.py deleted file mode 100644 index 38c24c8c65..0000000000 --- a/lib/iris/analysis/interpolate.py +++ /dev/null @@ -1,999 +0,0 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -""" -Interpolation and re-gridding routines. - -See also: :mod:`NumPy `, and :ref:`SciPy `. - -""" -import collections -import warnings - -import numpy as np -import numpy.ma as ma -import scipy -import scipy.spatial -from scipy.interpolate.interpolate import interp1d - -import iris.cube -import iris.coord_systems -import iris.coords -import iris.exceptions - - -def _ll_to_cart(lon, lat): - # Based on cartopy.img_transform.ll_to_cart() - x = np.sin(np.deg2rad(90 - lat)) * np.cos(np.deg2rad(lon)) - y = np.sin(np.deg2rad(90 - lat)) * np.sin(np.deg2rad(lon)) - z = np.cos(np.deg2rad(90 - lat)) - return (x, y, z) - -def _cartesian_sample_points(sample_points, sample_point_coord_names): - # Replace geographic latlon with cartesian xyz. - # Generates coords suitable for nearest point calculations with scipy.spatial.cKDTree. - # - # Input: - # sample_points[coord][datum] : list of sample_positions for each datum, formatted for fast use of _ll_to_cart() - # sample_point_coord_names[coord] : list of n coord names - # - # Output: - # list of [x,y,z,t,etc] positions, formatted for kdtree - - # Find lat and lon coord indices - i_lat = i_lon = None - i_non_latlon = range(len(sample_point_coord_names)) - for i, name in enumerate(sample_point_coord_names): - if "latitude" in name: - i_lat = i - i_non_latlon.remove(i_lat) - if "longitude" in name: - i_lon = i - i_non_latlon.remove(i_lon) - - if i_lat is None or i_lon is None: - return sample_points.transpose() - - num_points = len(sample_points[0]) - cartesian_points = [None] * num_points - - # Get the point coordinates without the latlon - for p in range(num_points): - cartesian_points[p] = [sample_points[c][p] for c in i_non_latlon] - - # Add cartesian xyz coordinates from latlon - x, y, z = _ll_to_cart(sample_points[i_lon], sample_points[i_lat]) - for p in range(num_points): - cartesian_point = cartesian_points[p] - cartesian_point.append(x[p]) - cartesian_point.append(y[p]) - cartesian_point.append(z[p]) - - return cartesian_points - - -def nearest_neighbour_indices(cube, sample_points): - """ - Returns the indices to select the data value(s) closest to the given coordinate point values. - - The sample_points mapping does not have to include coordinate values corresponding to all data - dimensions. Any dimensions unspecified will default to a full slice. - - For example: - - >>> cube = iris.load_cube(iris.sample_data_path('ostia_monthly.nc')) - >>> iris.analysis.interpolate.nearest_neighbour_indices(cube, [('latitude', 0), ('longitude', 10)]) - (slice(None, None, None), 9, 12) - >>> iris.analysis.interpolate.nearest_neighbour_indices(cube, [('latitude', 0)]) - (slice(None, None, None), 9, slice(None, None, None)) - - Args: - - * cube: - An :class:`iris.cube.Cube`. - * sample_points - A list of tuple pairs mapping coordinate instances or unique coordinate names in the cube to point values. - - Returns: - The tuple of indices which will select the point in the cube closest to the supplied coordinate values. - - .. note:: - - Nearest neighbour interpolation of multidimensional coordinates is not - yet supported. - - """ - if isinstance(sample_points, dict): - warnings.warn('Providing a dictionary to specify points is deprecated. Please provide a list of (coordinate, values) pairs.') - sample_points = sample_points.items() - - if sample_points: - try: - coord, values = sample_points[0] - except ValueError: - raise ValueError('Sample points must be a list of (coordinate, value) pairs. Got %r.' % sample_points) - - points = [] - for coord, values in sample_points: - if isinstance(coord, basestring): - coord = cube.coord(coord) - else: - coord = cube.coord(coord) - points.append((coord, values)) - sample_points = points - - # Build up a list of indices to span the cube. - indices = [slice(None, None)] * cube.ndim - - # Build up a dictionary which maps the cube's data dimensions to a list (which will later - # be populated by coordinates in the sample points list) - dim_to_coord_map = {} - for i in range(cube.ndim): - dim_to_coord_map[i] = [] - - # Iterate over all of the specifications provided by sample_points - for coord, point in sample_points: - data_dim = cube.coord_dims(coord) - - # If no data dimension then we don't need to make any modifications to indices. - if not data_dim: - continue - elif len(data_dim) > 1: - raise iris.exceptions.CoordinateMultiDimError("Nearest neighbour interpolation of multidimensional " - "coordinates is not supported.") - data_dim = data_dim[0] - - dim_to_coord_map[data_dim].append(coord) - - #calculate the nearest neighbour - min_index = coord.nearest_neighbour_index(point) - - if getattr(coord, 'circular', False): - warnings.warn("Nearest neighbour on a circular coordinate may not be picking the nearest point.", DeprecationWarning) - - # If the dimension has already been interpolated then assert that the index from this coordinate - # agrees with the index already calculated, otherwise we have a contradicting specification - if indices[data_dim] != slice(None, None) and min_index != indices[data_dim]: - raise ValueError('The coordinates provided (%s) over specify dimension %s.' % - (', '.join([coord.name() for coord in dim_to_coord_map[data_dim]]), data_dim)) - - indices[data_dim] = min_index - - return tuple(indices) - - -def _nearest_neighbour_indices_ndcoords(cube, sample_point, cache=None): - """ - See documentation for :func:`iris.analysis.interpolate.nearest_neighbour_indices`. - - This function is adapted for points sampling a multi-dimensional coord, - and can currently only do nearest neighbour interpolation. - - Because this function can be slow for multidimensional coordinates, - a 'cache' dictionary can be provided by the calling code. - - """ - - # Developer notes: - # A "sample space cube" is made which only has the coords and dims we are sampling on. - # We get the nearest neighbour using this sample space cube. - - if isinstance(sample_point, dict): - warnings.warn('Providing a dictionary to specify points is deprecated. Please provide a list of (coordinate, values) pairs.') - sample_point = sample_point.items() - - if sample_point: - try: - coord, value = sample_point[0] - except ValueError: - raise ValueError('Sample points must be a list of (coordinate, value) pairs. Got %r.' % sample_point) - - # Convert names to coords in sample_point - point = [] - ok_coord_ids = set(map(id, cube.dim_coords + cube.aux_coords)) - for coord, value in sample_point: - if isinstance(coord, basestring): - coord = cube.coord(coord) - else: - coord = cube.coord(coord) - if id(coord) not in ok_coord_ids: - msg = ('Invalid sample coordinate {!r}: derived coordinates are' - ' not allowed.'.format(coord.name())) - raise ValueError(msg) - point.append((coord, value)) - - # Reformat sample_point for use in _cartesian_sample_points(), below. - sample_point = np.array([[value] for coord, value in point]) - sample_point_coords = [coord for coord, value in point] - sample_point_coord_names = [coord.name() for coord, value in point] - - # Which dims are we sampling? - sample_dims = set() - for coord in sample_point_coords: - for dim in cube.coord_dims(coord): - sample_dims.add(dim) - sample_dims = sorted(list(sample_dims)) - - # Extract a sub cube that lives in just the sampling space. - sample_space_slice = [0] * cube.ndim - for sample_dim in sample_dims: - sample_space_slice[sample_dim] = slice(None, None) - sample_space_slice = tuple(sample_space_slice) - sample_space_cube = cube[sample_space_slice] - - #...with just the sampling coords - for coord in sample_space_cube.coords(): - if not coord.name() in sample_point_coord_names: - sample_space_cube.remove_coord(coord) - - # Order the sample point coords according to the sample space cube coords - sample_space_coord_names = [coord.name() for coord in sample_space_cube.coords()] - new_order = [sample_space_coord_names.index(name) for name in sample_point_coord_names] - sample_point = np.array([sample_point[i] for i in new_order]) - sample_point_coord_names = [sample_point_coord_names[i] for i in new_order] - - # Convert the sample point to cartesian coords. - # If there is no latlon within the coordinate there will be no change. - # Otherwise, geographic latlon is replaced with cartesian xyz. - cartesian_sample_point = _cartesian_sample_points(sample_point, sample_point_coord_names)[0] - - sample_space_coords = sample_space_cube.dim_coords + sample_space_cube.aux_coords - sample_space_coords_and_dims = [(coord, sample_space_cube.coord_dims(coord)) for coord in sample_space_coords] - - if cache is not None and cube in cache: - kdtree = cache[cube] - else: - # Create a "sample space position" for each datum: sample_space_data_positions[coord_index][datum_index] - sample_space_data_positions = np.empty((len(sample_space_coords_and_dims), sample_space_cube.data.size), dtype=float) - for d, ndi in enumerate(np.ndindex(sample_space_cube.data.shape)): - for c, (coord, coord_dims) in enumerate(sample_space_coords_and_dims): - # Index of this datum along this coordinate (could be nD). - keys = tuple(ndi[ind] for ind in coord_dims) if coord_dims else slice(None, None) - # Position of this datum along this coordinate. - sample_space_data_positions[c][d] = coord.points[keys] - - # Convert to cartesian coordinates. Flatten for kdtree compatibility. - cartesian_space_data_coords = _cartesian_sample_points(sample_space_data_positions, sample_point_coord_names) - - # Get the nearest datum index to the sample point. This is the goal of the function. - kdtree = scipy.spatial.cKDTree(cartesian_space_data_coords) - - cartesian_distance, datum_index = kdtree.query(cartesian_sample_point) - sample_space_ndi = np.unravel_index(datum_index, sample_space_cube.data.shape) - - # Turn sample_space_ndi into a main cube slice. - # Map sample cube to main cube dims and leave the rest as a full slice. - main_cube_slice = [slice(None, None)] * cube.ndim - for sample_coord, sample_coord_dims in sample_space_coords_and_dims: - # Find the coord in the main cube - main_coord = cube.coord(sample_coord.name()) - main_coord_dims = cube.coord_dims(main_coord) - # Mark the nearest data index/indices with respect to this coord - for sample_i, main_i in zip(sample_coord_dims, main_coord_dims): - main_cube_slice[main_i] = sample_space_ndi[sample_i] - - - # Update cache - if cache is not None: - cache[cube] = kdtree - - return tuple(main_cube_slice) - - -def extract_nearest_neighbour(cube, sample_points): - """ - Returns a new cube using data value(s) closest to the given coordinate point values. - - The sample_points mapping does not have to include coordinate values corresponding to all data - dimensions. Any dimensions unspecified will default to a full slice. - - For example: - - >>> cube = iris.load_cube(iris.sample_data_path('ostia_monthly.nc')) - >>> iris.analysis.interpolate.extract_nearest_neighbour(cube, [('latitude', 0), ('longitude', 10)]) - - >>> iris.analysis.interpolate.extract_nearest_neighbour(cube, [('latitude', 0)]) - - - Args: - - * cube: - An :class:`iris.cube.Cube`. - * sample_points - A list of tuple pairs mapping coordinate instances or unique coordinate names in the cube to point values. - - Returns: - A cube that represents uninterpolated data as near to the given points as possible. - - """ - return cube[nearest_neighbour_indices(cube, sample_points)] - - -def nearest_neighbour_data_value(cube, sample_points): - """ - Returns the data value closest to the given coordinate point values. - - The sample_points mapping must include coordinate values corresponding to all data - dimensions. - - For example: - - >>> cube = iris.load_cube(iris.sample_data_path('air_temp.pp')) - >>> iris.analysis.interpolate.nearest_neighbour_data_value(cube, [('latitude', 0), ('longitude', 10)]) - 299.21564 - >>> iris.analysis.interpolate.nearest_neighbour_data_value(cube, [('latitude', 0)]) - Traceback (most recent call last): - ... - ValueError: The sample points [('latitude', 0)] was not specific enough to return a single value from the cube. - - - Args: - - * cube: - An :class:`iris.cube.Cube`. - * sample_points - A list of tuple pairs mapping coordinate instances or unique coordinate names in the cube to point values. - - Returns: - The data value at the point in the cube closest to the supplied coordinate values. - - """ - indices = nearest_neighbour_indices(cube, sample_points) - for ind in indices: - if isinstance(ind, slice): - raise ValueError('The sample points given (%s) were not specific enough to return a ' - 'single value from the cube.' % sample_points) - - return cube.data[indices] - - -def regrid(source_cube, grid_cube, mode='bilinear', **kwargs): - """ - Returns a new cube with values derived from the source_cube on the horizontal grid specified - by the grid_cube. - - Fundamental input requirements: - 1) Both cubes must have a CoordSystem. - 2) The source 'x' and 'y' coordinates must not share data dimensions with any other coordinates. - - In addition, the algorithm currently used requires: - 3) Both CS instances must be compatible: - i.e. of the same type, with the same attribute values, and with compatible coordinates. - 4) No new data dimensions can be created. - 5) Source cube coordinates to map to a single dimension. - - Args: - - * source_cube: - An instance of :class:`iris.cube.Cube` which supplies the source data and metadata. - * grid_cube: - An instance of :class:`iris.cube.Cube` which supplies the horizontal grid definition. - - Kwargs: - - * mode (string): - Regridding interpolation algorithm to be applied, which may be one of the following: - - * 'bilinear' for bi-linear interpolation (default), see :func:`iris.analysis.interpolate.linear`. - * 'nearest' for nearest neighbour interpolation. - - Returns: - A new :class:`iris.cube.Cube` instance. - - .. note:: - - The masked status of values are currently ignored. See :func:\ -`~iris.experimental.regrid.regrid_bilinear_rectilinear_src_and_grid` - for regrid support with mask awareness. - - """ - # Condition 1 - source_cs = source_cube.coord_system(iris.coord_systems.CoordSystem) - grid_cs = grid_cube.coord_system(iris.coord_systems.CoordSystem) - if (source_cs is None) != (grid_cs is None): - raise ValueError("The source and grid cubes must both have a CoordSystem or both have None.") - - # Condition 2: We can only have one x coordinate and one y coordinate with the source CoordSystem, and those coordinates - # must be the only ones occupying their respective dimension - source_x = source_cube.coord(axis='x', coord_system=source_cs) - source_y = source_cube.coord(axis='y', coord_system=source_cs) - - source_x_dims = source_cube.coord_dims(source_x) - source_y_dims = source_cube.coord_dims(source_y) - - source_x_dim = None - if source_x_dims: - if len(source_x_dims) > 1: - raise ValueError('The source x coordinate may not describe more than one data dimension.') - source_x_dim = source_x_dims[0] - dim_sharers = ', '.join([coord.name() for coord in source_cube.coords(contains_dimension=source_x_dim) if coord is not source_x]) - if dim_sharers: - raise ValueError('No coordinates may share a dimension (dimension %s) with the x ' - 'coordinate, but (%s) do.' % (source_x_dim, dim_sharers)) - - source_y_dim = None - if source_y_dims: - if len(source_y_dims) > 1: - raise ValueError('The source y coordinate may not describe more than one data dimension.') - source_y_dim = source_y_dims[0] - dim_sharers = ', '.join([coord.name() for coord in source_cube.coords(contains_dimension=source_y_dim) if coord is not source_y]) - if dim_sharers: - raise ValueError('No coordinates may share a dimension (dimension %s) with the y ' - 'coordinate, but (%s) do.' % (source_y_dim, dim_sharers)) - - if source_x_dim is not None and source_y_dim == source_x_dim: - raise ValueError('The source x and y coords may not describe the same data dimension.') - - - # Condition 3 - # Check for compatible horizontal CSs. Currently that means they're exactly the same except for the coordinate - # values. - # The same kind of CS ... - compatible = (source_cs == grid_cs) - if compatible: - grid_x = grid_cube.coord(axis='x', coord_system=grid_cs) - grid_y = grid_cube.coord(axis='y', coord_system=grid_cs) - compatible = source_x.is_compatible(grid_x) and \ - source_y.is_compatible(grid_y) - if not compatible: - raise ValueError("The new grid must be defined on the same coordinate system, and have the same coordinate " - "metadata, as the source.") - - # Condition 4 - if grid_cube.coord_dims(grid_x) and not source_x_dims or \ - grid_cube.coord_dims(grid_y) and not source_y_dims: - raise ValueError("The new grid must not require additional data dimensions.") - - x_coord = grid_x.copy() - y_coord = grid_y.copy() - - - # - # Adjust the data array to match the new grid. - # - - # get the new shape of the data - new_shape = list(source_cube.shape) - if source_x_dims: - new_shape[source_x_dims[0]] = grid_x.shape[0] - if source_y_dims: - new_shape[source_y_dims[0]] = grid_y.shape[0] - - new_data = np.empty(new_shape, dtype=source_cube.data.dtype) - - # Prepare the index pattern which will be used to insert a single "column" of data. - # NB. A "column" is a slice constrained to a single XY point, which therefore extends over *all* the other axes. - # For an XYZ cube this means a column only extends over Z and corresponds to the normal definition of "column". - indices = [slice(None, None)] * new_data.ndim - - if mode == 'bilinear': - # Perform bilinear interpolation, passing through any keywords. - points_dict = [(source_x, list(x_coord.points)), (source_y, list(y_coord.points))] - new_data = linear(source_cube, points_dict, **kwargs).data - else: - # Perform nearest neighbour interpolation on each column in turn. - for iy, y in enumerate(y_coord.points): - for ix, x in enumerate(x_coord.points): - column_pos = [(source_x, x), (source_y, y)] - column_data = extract_nearest_neighbour(source_cube, column_pos).data - if source_y_dim is not None: - indices[source_y_dim] = iy - if source_x_dim is not None: - indices[source_x_dim] = ix - new_data[tuple(indices)] = column_data - - # Special case to make 0-dimensional results take the same form as NumPy - if new_data.shape == (): - new_data = new_data.flat[0] - - # Start with just the metadata and the re-sampled data... - new_cube = iris.cube.Cube(new_data) - new_cube.metadata = source_cube.metadata - - # ... and then copy across all the unaffected coordinates. - - # Record a mapping from old coordinate IDs to new coordinates, - # for subsequent use in creating updated aux_factories. - coord_mapping = {} - - def copy_coords(source_coords, add_method): - for coord in source_coords: - if coord is source_x or coord is source_y: - continue - dims = source_cube.coord_dims(coord) - new_coord = coord.copy() - add_method(new_coord, dims) - coord_mapping[id(coord)] = new_coord - - copy_coords(source_cube.dim_coords, new_cube.add_dim_coord) - copy_coords(source_cube.aux_coords, new_cube.add_aux_coord) - - for factory in source_cube.aux_factories: - new_cube.add_aux_factory(factory.updated(coord_mapping)) - - # Add the new coords - if source_x in source_cube.dim_coords: - new_cube.add_dim_coord(x_coord, source_x_dim) - else: - new_cube.add_aux_coord(x_coord, source_x_dims) - - if source_y in source_cube.dim_coords: - new_cube.add_dim_coord(y_coord, source_y_dim) - else: - new_cube.add_aux_coord(y_coord, source_y_dims) - - return new_cube - - -def regrid_to_max_resolution(cubes, **kwargs): - """ - Returns all the cubes re-gridded to the highest horizontal resolution. - - Horizontal resolution is defined by the number of grid points/cells covering the horizontal plane. - See :func:`iris.analysis.interpolation.regrid` regarding mode of interpolation. - - Args: - - * cubes: - An iterable of :class:`iris.cube.Cube` instances. - - Returns: - A list of new :class:`iris.cube.Cube` instances. - - """ - # TODO: This could be significantly improved for readability and functionality. - resolution = lambda cube_: (cube_.shape[cube_.coord_dims(cube_.coord(axis="x"))[0]]) * (cube_.shape[cube_.coord_dims(cube_.coord(axis="y"))[0]]) - grid_cube = max(cubes, key=resolution) - return [cube.regridded(grid_cube, **kwargs) for cube in cubes] - - -def linear(cube, sample_points, extrapolation_mode='linear'): - """ - Return a cube of the linearly interpolated points given the desired - sample points. - - Given a list of tuple pairs mapping coordinates (or coordinate names) - to their desired values, return a cube with linearly interpolated values. - If more than one coordinate is specified, the linear interpolation will be - carried out in sequence, thus providing n-linear interpolation - (bi-linear, tri-linear, etc.). - - If the input cube's data is masked, the result cube will have a data - mask interpolated to the new sample points - - .. testsetup:: - - import numpy as np - - For example: - - >>> cube = iris.load_cube(iris.sample_data_path('air_temp.pp')) - >>> sample_points = [('latitude', np.linspace(-90, 90, 10)), - ... ('longitude', np.linspace(-180, 180, 20))] - >>> iris.analysis.interpolate.linear(cube, sample_points) - - - .. note:: - - By definition, linear interpolation requires all coordinates to - be 1-dimensional. - - .. note:: - - If a specified coordinate is single valued its value will be - extrapolated to the desired sample points by assuming a gradient of - zero. - - Args: - - * cube - The cube to be interpolated. - - * sample_points - List of one or more tuple pairs mapping coordinate to desired - points to interpolate. Points may be a scalar or a numpy array - of values. Multi-dimensional coordinates are not supported. - - Kwargs: - - * extrapolation_mode - string - one of 'linear', 'nan' or 'error' - - * If 'linear' the point will be calculated by extending the - gradient of closest two points. - * If 'nan' the extrapolation point will be put as a NAN. - * If 'error' a value error will be raised notifying of the - attempted extrapolation. - - .. note:: - - If the source cube's data, or any of its resampled coordinates, - have an integer data type they will be promoted to a floating - point data type in the result. - - """ - if not isinstance(cube, iris.cube.Cube): - raise ValueError('Expecting a cube instance, got %s' % type(cube)) - - if isinstance(sample_points, dict): - warnings.warn('Providing a dictionary to specify points is deprecated. Please provide a list of (coordinate, values) pairs.') - sample_points = sample_points.items() - - # catch the case where a user passes a single (coord/name, value) pair rather than a list of pairs - if sample_points and not (isinstance(sample_points[0], collections.Container) and not isinstance(sample_points[0], basestring)): - raise TypeError('Expecting the sample points to be a list of tuple pairs representing (coord, points), got a list of %s.' % type(sample_points[0])) - - points = [] - for (coord, values) in sample_points: - if isinstance(coord, basestring): - coord = cube.coord(coord) - else: - coord = cube.coord(coord) - points.append((coord, values)) - sample_points = points - - if len(sample_points) == 0: - raise ValueError('Expecting a non-empty list of coord value pairs, got %r.' % sample_points) - - if cube.data.dtype.kind == 'i': - raise ValueError("Cannot linearly interpolate a cube which has integer type data. Consider casting the " - "cube's data to floating points in order to continue.") - - bounds_error = (extrapolation_mode == 'error') - - # Handle an over-specified points_dict or a specification which does not describe a data dimension - data_dimensions_requested = [] - for coord, values in sample_points: - if coord.ndim > 1: - raise ValueError('Cannot linearly interpolate over {!r} as it is' - ' multi-dimensional.'.format(coord.name())) - data_dim = cube.coord_dims(coord) - if not data_dim: - raise ValueError('Requested a point over a coordinate which does' - ' not describe a dimension: {!r}.'.format( - coord.name())) - else: - data_dim = data_dim[0] - if data_dim in data_dimensions_requested: - raise ValueError('Requested a point which over specifies a' - ' dimension: {!r}. '.format(coord.name())) - data_dimensions_requested.append(data_dim) - - # Iterate over all of the requested keys in the given points_dict calling this routine repeatedly. - if len(sample_points) > 1: - result = cube - for coord, cells in sample_points: - result = linear(result, [(coord, cells)], extrapolation_mode=extrapolation_mode) - return result - - else: - # Now we must be down to a single sample coordinate and its - # values. - src_coord, requested_points = sample_points[0] - sample_values = np.array(requested_points) - - # 1) Define the interpolation characteristics. - - # Get the sample dimension (which we have already tested is not None) - sample_dim = cube.coord_dims(src_coord)[0] - - # Construct source data & source coordinate values suitable for - # SciPy's interp1d. - if getattr(src_coord, 'circular', False): - coord_slice_in_cube = [slice(None, None)] * cube.ndim - coord_slice_in_cube[sample_dim] = slice(0, 1) - modulus = np.array(src_coord.units.modulus or 0, - dtype=src_coord.dtype) - src_points = np.append(src_coord.points, - src_coord.points[0] + modulus) - - # TODO: Restore this code after resolution of the following issue: - # https://github.com/numpy/numpy/issues/478 -# data = np.append(cube.data, -# cube.data[tuple(coord_slice_in_cube)], -# axis=sample_dim) - # This is the alternative, temporary workaround. - # It doesn't use append on an nD mask. - if (not isinstance(cube.data, ma.MaskedArray) or - not isinstance(cube.data.mask, np.ndarray) or - len(cube.data.mask.shape) == 0): - data = np.append(cube.data, - cube.data[tuple(coord_slice_in_cube)], - axis=sample_dim) - else: - new_data = np.append(cube.data.data, - cube.data.data[tuple(coord_slice_in_cube)], - axis=sample_dim) - new_mask = np.append(cube.data.mask, - cube.data.mask[tuple(coord_slice_in_cube)], - axis=sample_dim) - data = ma.array(new_data, mask=new_mask) - else: - src_points = src_coord.points - data = cube.data - - # Map all the requested values into the range of the source - # data (centered over the centre of the source data to allow - # extrapolation where required). - src_axis = iris.util.guess_coord_axis(src_coord) - if src_axis == 'X' and src_coord.units.modulus: - modulus = src_coord.units.modulus - offset = (src_points.max() + src_points.min() - modulus) * 0.5 - sample_values = ((sample_values - offset) % modulus) + offset - - if len(src_points) == 1: - if extrapolation_mode == 'error' and \ - np.any(sample_values != src_points): - raise ValueError('Attempting to extrapolate from a single ' - 'point with extrapolation mode set ' - 'to {!r}.'.format(extrapolation_mode)) - direction = 0 - - def interpolate(fx, new_x, axis=None, **kwargs): - # All kwargs other than axis are ignored. - if axis is None: - axis = -1 - new_x = np.array(new_x) - new_shape = list(fx.shape) - new_shape[axis] = new_x.size - fx = np.broadcast_arrays(fx, np.empty(new_shape))[0].copy() - if extrapolation_mode == 'nan': - indices = [slice(None)] * fx.ndim - indices[axis] = new_x != src_points - fx[tuple(indices)] = np.nan - # If new_x is a scalar, then remove the dimension from fx. - if not new_x.shape: - del new_shape[axis] - fx.shape = new_shape - return fx - else: - monotonic, direction = iris.util.monotonic(src_points, - return_direction=True) - if not monotonic: - raise ValueError('Unable to linearly interpolate this ' - 'cube as the coordinate {!r} is not ' - 'monotonic'.format(src_coord.name())) - - # SciPy's interp1d requires monotonic increasing coord values. - if direction == -1: - src_points = iris.util.reverse(src_points, axes=0) - data = iris.util.reverse(data, axes=sample_dim) - - # Wrap it all up in a function which makes the right kind of - # interpolator/extrapolator. - # NB. This uses a closure to capture the values of src_points, - # bounds_error, and extrapolation_mode. - def interpolate(fx, new_x, **kwargs): - # SciPy's interp1d needs float values, so if we're given - # integer values, convert them to the smallest possible - # float dtype that can accurately preserve the values. - if fx.dtype.kind == 'i': - fx = fx.astype(np.promote_types(fx.dtype, np.float16)) - x = src_points.astype(fx.dtype) - interpolator = interp1d(x, fx, kind='linear', - bounds_error=bounds_error, **kwargs) - if extrapolation_mode == 'linear': - interpolator = Linear1dExtrapolator(interpolator) - new_fx = interpolator(np.array(new_x, dtype=fx.dtype)) - return new_fx - - # 2) Interpolate the data and produce our new Cube. - if isinstance(data, ma.MaskedArray): - # interpolate data, ignoring the mask - new_data = interpolate(data.data, sample_values, axis=sample_dim, - copy=False) - # Mask out any results which contain a non-zero contribution - # from a masked value when interpolated from mask cast as 1,0. - mask_dataset = ma.getmaskarray(data).astype(float) - new_mask = interpolate(mask_dataset, sample_values, - axis=sample_dim, copy=False) > 0 - # create new_data masked array - new_data = ma.MaskedArray(new_data, mask=new_mask) - else: - new_data = interpolate(data, sample_values, axis=sample_dim, - copy=False) - new_cube = iris.cube.Cube(new_data) - new_cube.metadata = cube.metadata - - # If requested_points is an array scalar then `new_cube` will - # have one less dimension than `cube`. (The `sample_dim` - # dimension will vanish.) In which case we build a mapping from - # `cube` dimensions to `new_cube` dimensions. - dim_mapping = None - if new_cube.ndim != cube.ndim: - dim_mapping = {i: i for i in range(sample_dim)} - dim_mapping[sample_dim] = None - for i in range(sample_dim + 1, cube.ndim): - dim_mapping[i] = i - 1 - - # 2) Copy/interpolate the coordinates. - for dim_coord in cube.dim_coords: - dims = cube.coord_dims(dim_coord) - if sample_dim in dims: - new_coord = _resample_coord(dim_coord, src_coord, direction, - requested_points, interpolate) - else: - new_coord = dim_coord.copy() - if dim_mapping: - dims = [dim_mapping[dim] for dim in dims - if dim_mapping[dim] is not None] - if isinstance(new_coord, iris.coords.DimCoord) and dims: - new_cube.add_dim_coord(new_coord, dims) - else: - new_cube.add_aux_coord(new_coord, dims) - - for coord in cube.aux_coords: - dims = cube.coord_dims(coord) - if sample_dim in dims: - new_coord = _resample_coord(coord, src_coord, direction, - requested_points, interpolate) - else: - new_coord = coord.copy() - if dim_mapping: - dims = [dim_mapping[dim] for dim in dims - if dim_mapping[dim] is not None] - new_cube.add_aux_coord(new_coord, dims) - - return new_cube - - -def _resample_coord(coord, src_coord, direction, target_points, interpolate): - if coord.ndim != 1: - raise iris.exceptions.NotYetImplementedError( - 'Linear interpolation of multi-dimensional coordinates.') - coord_points = coord.points - if coord is src_coord: - dtype = coord_points.dtype - if dtype.kind == 'i': - dtype = np.promote_types(dtype, np.float16) - new_points = np.array(target_points, dtype=dtype) - else: - if getattr(src_coord, 'circular', False): - coord_points = np.append(coord_points, coord_points[0]) - - # If the source coordinate was monotonic decreasing, we need to - # flip this coordinate's values. - if direction == -1: - coord_points = iris.util.reverse(coord_points, axes=0) - - new_points = interpolate(coord_points, target_points) - - # Watch out for DimCoord instances that are no longer monotonic - # after the resampling. - try: - new_coord = coord.copy(new_points) - except ValueError: - new_coord = iris.coords.AuxCoord.from_coord(coord).copy(new_points) - return new_coord - - -def _interp1d_rolls_y(): - """ - Determines if :class:`scipy.interpolate.interp1d` rolls its array `y` by - comparing the shape of y passed into interp1d to the shape of its internal - representation of y. - - SciPy v0.13.x+ no longer rolls the axis of its internal representation - of y so we test for this occurring to prevent us subsequently - extrapolating along the wrong axis. - - For further information on this change see, for example: - * https://github.com/scipy/scipy/commit/0d906d0fc54388464603c63119b9e35c9a9c4601 - (the commit that introduced the change in behaviour). - * https://github.com/scipy/scipy/issues/2621 - (a discussion on the change - note the issue is not resolved - at time of writing). - - """ - y = np.arange(12).reshape(3, 4) - f = interp1d(np.arange(3), y, axis=0) - # If the initial shape of y and the shape internal to interp1d are *not* - # the same then scipy.interp1d rolls y. - return y.shape != f.y.shape - - -class Linear1dExtrapolator(object): - """ - Extension class to :class:`scipy.interpolate.interp1d` to provide linear extrapolation. - - See also: :mod:`scipy.interpolate`. - - """ - roll_y = _interp1d_rolls_y() - - def __init__(self, interpolator): - """ - Given an already created :class:`scipy.interpolate.interp1d` instance, return a callable object - which supports linear extrapolation. - - """ - self._interpolator = interpolator - self.x = interpolator.x - # Store the y values given to the interpolator. - self.y = interpolator.y - """ - The y values given to the interpolator object. - - .. note:: These are stored with the interpolator.axis last. - - """ - # Roll interpolator.axis to the end if scipy no longer does it for us. - if not self.roll_y: - self.y = np.rollaxis(self.y, self._interpolator.axis, self.y.ndim) - - def all_points_in_range(self, requested_x): - """Given the x points, do all of the points sit inside the interpolation range.""" - test = (requested_x >= self.x[0]) & (requested_x <= self.x[-1]) - if isinstance(test, np.ndarray): - test = test.all() - return test - - def __call__(self, requested_x): - if not self.all_points_in_range(requested_x): - # cast requested_x to a numpy array if it is not already. - if not isinstance(requested_x, np.ndarray): - requested_x = np.array(requested_x) - - # we need to catch the special case of providing a single value... - remember_that_i_was_0d = requested_x.ndim == 0 - - requested_x = requested_x.flatten() - - gt = np.where(requested_x > self.x[-1])[0] - lt = np.where(requested_x < self.x[0])[0] - ok = np.where( (requested_x >= self.x[0]) & (requested_x <= self.x[-1]) )[0] - - data_shape = list(self.y.shape) - data_shape[-1] = len(requested_x) - result = np.empty(data_shape, dtype=self._interpolator(self.x[0]).dtype) - - # Make a variable to represent the slice into the resultant data. (This will be updated in each of gt, lt & ok) - interpolator_result_index = [slice(None, None)] * self.y.ndim - - if len(ok) != 0: - interpolator_result_index[-1] = ok - - r = self._interpolator(requested_x[ok]) - # Reshape the properly formed array to put the interpolator.axis last i.e. dims 0, 1, 2 -> 0, 2, 1 if axis = 1 - axes = range(r.ndim) - del axes[self._interpolator.axis] - axes.append(self._interpolator.axis) - - result[interpolator_result_index] = r.transpose(axes) - - if len(lt) != 0: - interpolator_result_index[-1] = lt - - grad = (self.y[..., 1:2] - self.y[..., 0:1]) / (self.x[1] - self.x[0]) - result[interpolator_result_index] = self.y[..., 0:1] + (requested_x[lt] - self.x[0]) * grad - - if len(gt) != 0: - interpolator_result_index[-1] = gt - - grad = (self.y[..., -1:] - self.y[..., -2:-1]) / (self.x[-1] - self.x[-2]) - result[interpolator_result_index] = self.y[..., -1:] + (requested_x[gt] - self.x[-1]) * grad - - axes = range(len(interpolator_result_index)) - axes.insert(self._interpolator.axis, axes.pop(axes[-1])) - result = result.transpose(axes) - - if remember_that_i_was_0d: - new_shape = list(result.shape) - del new_shape[self._interpolator.axis] - result = result.reshape(new_shape) - - return result - else: - return self._interpolator(requested_x) diff --git a/lib/iris/analysis/maths.py b/lib/iris/analysis/maths.py index c5396273e9..abd6e3a633 100644 --- a/lib/iris/analysis/maths.py +++ b/lib/iris/analysis/maths.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -18,16 +18,96 @@ Basic mathematical and statistical operations. """ -from __future__ import division + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + import warnings import math +import operator +import inspect +import cf_units import numpy as np +from numpy import ma import iris.analysis import iris.coords import iris.cube import iris.exceptions +import iris.util + +import dask.array as da +from dask.array.core import broadcast_shapes + + +_output_dtype_cache = {} + + +def _output_dtype(op, first_dtype, second_dtype=None, in_place=False): + """ + Get the numpy dtype corresponding to the result of applying a unary or + binary operation to arguments of specified dtype. + + Args: + + * op: + A unary or binary operator which can be applied to array-like objects. + * first_dtype: + The dtype of the first or only argument to the operator. + + Kwargs: + + * second_dtype: + The dtype of the second argument to the operator. + + * in_place: + Whether the operation is to be performed in place. + + Returns: + An instance of :class:`numpy.dtype` + + .. note:: + + The function always returns the dtype which would result if the + operation were successful, even if the operation could fail due to + casting restrictions for in place operations. + + """ + if in_place: + # Always return the first dtype, even if the operation would fail due + # to failure to cast the result. + result = first_dtype + else: + operand_dtypes = (first_dtype, second_dtype) \ + if second_dtype is not None \ + else (first_dtype,) + key = (op, operand_dtypes) + result = _output_dtype_cache.get(key, None) + if result is None: + arrays = [np.array([1], dtype=dtype) for dtype in operand_dtypes] + result = op(*arrays).dtype + _output_dtype_cache[key] = result + return result + + +def _get_dtype(operand): + """ + Get the numpy dtype corresponding to the numeric data in the object + provided. + + Args: + + * operand: + An instance of :class:`iris.cube.Cube` or :class:`iris.coords.Coord`, + or a number or :class:`numpy.ndarray`. + + Returns: + An instance of :class:`numpy.dtype` + + """ + return np.min_scalar_type(operand) if np.isscalar(operand) \ + else operand.dtype def abs(cube, in_place=False): @@ -48,7 +128,10 @@ def abs(cube, in_place=False): An instance of :class:`iris.cube.Cube`. """ - return _math_op_common(cube, np.abs, cube.units, in_place=in_place) + _assert_is_cube(cube) + new_dtype = _output_dtype(np.abs, cube.dtype, in_place=in_place) + op = da.absolute if cube.has_lazy_data() else np.abs + return _math_op_common(cube, op, cube.units, new_dtype, in_place=in_place) def intersection_of_cubes(cube, other_cube): @@ -70,11 +153,13 @@ def intersection_of_cubes(cube, other_cube): to the original cubes restricted to their intersection. """ - # Take references of the original cubes (which will be copied when slicing later) + # Take references of the original cubes (which will be copied when + # slicing later). new_cube_self = cube new_cube_other = other_cube - # This routine has not been written to cope with multi-dimensional coordinates. + # This routine has not been written to cope with multi-dimensional + # coordinates. for coord in cube.coords() + other_cube.coords(): if coord.ndim != 1: raise iris.exceptions.CoordinateMultiDimError(coord) @@ -82,13 +167,15 @@ def intersection_of_cubes(cube, other_cube): coord_comp = iris.analysis.coord_comparison(cube, other_cube) if coord_comp['ungroupable_and_dimensioned']: - raise ValueError('Cubes do not share all coordinates in common, cannot intersect.') + raise ValueError('Cubes do not share all coordinates in common, ' + 'cannot intersect.') # cubes must have matching coordinates for coord in cube.coords(): other_coord = other_cube.coord(coord) - # Only intersect coordinates which are different, single values coordinates may differ. + # Only intersect coordinates which are different, single values + # coordinates may differ. if coord.shape[0] > 1 and coord != other_coord: intersected_coord = coord.intersect(other_coord) new_cube_self = new_cube_self.subset(intersected_coord) @@ -104,43 +191,49 @@ def _assert_is_cube(cube): def _assert_compatible(cube, other): - """Checks to see if cube.data and another array can be broadcast to the same shape using ``numpy.broadcast_arrays``.""" - # This code previously returned broadcasted versions of the cube data and the other array. - # As numpy.broadcast_arrays does not work with masked arrays (it returns them as ndarrays) operations - # involving masked arrays would be broken. + """ + Checks to see if cube.data and another array can be broadcast to + the same shape. + """ try: - data_view, other_view = np.broadcast_arrays(cube.data, other) - except ValueError, err: + new_shape = broadcast_shapes(cube.shape, other.shape) + except ValueError as err: # re-raise - raise ValueError("The array was not broadcastable to the cube's data shape. The error message from numpy when broadcasting:\n%s\n" - "The cube's shape was %s and the array's shape was %s" % (err, cube.shape, other.shape)) + raise ValueError("The array was not broadcastable to the cube's data " + "shape. The error message when " + "broadcasting:\n{}\nThe cube's shape was {} and the " + "array's shape was {}".format(err, cube.shape, + other.shape)) - if cube.shape != data_view.shape: - raise ValueError("The array operation would increase the dimensionality of the cube. The new cubes data would " - "have had to become: %s" % (data_view.shape, )) + if cube.shape != new_shape: + raise ValueError("The array operation would increase the size or " + "dimensionality of the cube. The new cube's data " + "would have had to become: {}".format( + new_shape)) -def _assert_matching_units(cube, other, operation_noun): +def _assert_matching_units(cube, other, operation_name): """ Check that the units of the cube and the other item are the same, or if the other does not have a unit, skip this test """ if cube.units != getattr(other, 'units', cube.units): - raise iris.exceptions.NotYetImplementedError( - 'Differing units (%s & %s) %s not implemented' % - (cube.units, other.units, operation_noun)) + msg = 'Cannot use {!r} with differing units ({} & {})'.format( + operation_name, cube.units, other.units) + raise iris.exceptions.NotYetImplementedError(msg) -def add(cube, other, dim=None, ignore=True, in_place=False): +def add(cube, other, dim=None, in_place=False): """ - Calculate the sum of two cubes, or the sum of a cube and a coordinate or scalar - value. + Calculate the sum of two cubes, or the sum of a cube and a + coordinate or scalar value. - When summing two cubes, they must both have the same coordinate systems & data resolution. + When summing two cubes, they must both have the same coordinate + systems & data resolution. - When adding a coordinate to a cube, they must both share the same number of elements - along a shared axis. + When adding a coordinate to a cube, they must both share the same + number of elements along a shared axis. Args: @@ -153,7 +246,8 @@ def add(cube, other, dim=None, ignore=True, in_place=False): Kwargs: * dim: - If supplying a coord with no match on the cube, you must supply the dimension to process. + If supplying a coord with no match on the cube, you must supply + the dimension to process. * in_place: Whether to create a new Cube, or alter the given "cube". @@ -161,19 +255,28 @@ def add(cube, other, dim=None, ignore=True, in_place=False): An instance of :class:`iris.cube.Cube`. """ - return _add_subtract_common(np.add, 'addition', 'added', cube, other, - dim=dim, ignore=ignore, in_place=in_place) + _assert_is_cube(cube) + new_dtype = _output_dtype(operator.add, cube.dtype, _get_dtype(other), + in_place=in_place) + if in_place: + _inplace_common_checks(cube, other, 'addition') + op = operator.iadd + else: + op = operator.add + return _add_subtract_common(op, 'add', cube, other, new_dtype, dim=dim, + in_place=in_place) -def subtract(cube, other, dim=None, ignore=True, in_place=False): +def subtract(cube, other, dim=None, in_place=False): """ Calculate the difference between two cubes, or the difference between a cube and a coordinate or scalar value. - When subtracting two cubes, they must both have the same coordinate systems & data resolution. + When subtracting two cubes, they must both have the same coordinate + systems & data resolution. - When subtracting a coordinate to a cube, they must both share the same number of elements - along a shared axis. + When subtracting a coordinate to a cube, they must both share the + same number of elements along a shared axis. Args: @@ -186,7 +289,8 @@ def subtract(cube, other, dim=None, ignore=True, in_place=False): Kwargs: * dim: - If supplying a coord with no match on the cube, you must supply the dimension to process. + If supplying a coord with no match on the cube, you must supply + the dimension to process. * in_place: Whether to create a new Cube, or alter the given "cube". @@ -194,59 +298,49 @@ def subtract(cube, other, dim=None, ignore=True, in_place=False): An instance of :class:`iris.cube.Cube`. """ - return _add_subtract_common(np.subtract, 'subtraction', 'subtracted', cube, - other, dim=dim, ignore=ignore, - in_place=in_place) + _assert_is_cube(cube) + new_dtype = _output_dtype(operator.sub, cube.dtype, _get_dtype(other), + in_place=in_place) + if in_place: + _inplace_common_checks(cube, other, 'subtraction') + op = operator.isub + else: + op = operator.sub + return _add_subtract_common(op, 'subtract', cube, other, new_dtype, + dim=dim, in_place=in_place) -def _add_subtract_common(operation_function, operation_noun, - operation_past_tense, cube, other, dim=None, - ignore=True, in_place=False): +def _add_subtract_common(operation_function, operation_name, cube, other, + new_dtype, dim=None, in_place=False): """ - Function which shares common code between addition and subtraction of cubes. + Function which shares common code between addition and subtraction + of cubes. - operation_function - function which does the operation (e.g. numpy.subtract) - operation_symbol - the textual symbol of the operation (e.g. '-') - operation_noun - the noun of the operation (e.g. 'subtraction') - operation_past_tense - the past tense of the operation (e.g. 'subtracted') + operation_function - function which does the operation + (e.g. numpy.subtract) + operation_name - the public name of the operation (e.g. 'divide') + cube - the cube whose data is used as the first argument + to `operation_function` + other - the cube, coord, ndarray or number whose data is + used as the second argument + new_dtype - the expected dtype of the output. Used in the + case of scalar masked arrays + dim - dimension along which to apply `other` if it's a + coordinate that is not found in `cube` + in_place - whether or not to apply the operation in place to + `cube` and `cube.data` """ _assert_is_cube(cube) - _assert_matching_units(cube, other, operation_noun) + _assert_matching_units(cube, other, operation_name) if isinstance(other, iris.cube.Cube): # get a coordinate comparison of this cube and the cube to do the # operation with coord_comp = iris.analysis.coord_comparison(cube, other) - if coord_comp['transposable']: - # User does not need to transpose their cubes if numpy - # array broadcasting will make the dimensions match - broadcast_padding = cube.ndim - other.ndim - coord_dims_equal = True - for coord_group in coord_comp['transposable']: - cube_coord, other_coord = coord_group.coords - cube_coord_dims = cube.coord_dims(cube_coord) - other_coord_dims = other.coord_dims(other_coord) - other_coord_dims_broadcasted = tuple( - [dim + broadcast_padding for dim in other_coord_dims]) - if cube_coord_dims != other_coord_dims_broadcasted: - coord_dims_equal = False - - if not coord_dims_equal: - raise ValueError('Cubes cannot be %s, differing axes. ' - 'cube.transpose() may be required to ' - 're-order the axes.' % operation_past_tense) - - # provide a deprecation warning if the ignore keyword has been set - if ignore is not True: - warnings.warn('The "ignore" keyword has been deprecated in ' - 'add/subtract. This functionality is now automatic. ' - 'The provided value to "ignore" has been ignored, ' - 'and has been automatically calculated.') - - bad_coord_grps = (coord_comp['ungroupable_and_dimensioned'] - + coord_comp['resamplable']) + bad_coord_grps = (coord_comp['ungroupable_and_dimensioned'] + + coord_comp['resamplable']) if bad_coord_grps: raise ValueError('This operation cannot be performed as there are ' 'differing coordinates (%s) remaining ' @@ -256,8 +350,9 @@ def _add_subtract_common(operation_function, operation_noun, else: coord_comp = None - new_cube = _binary_op_common(operation_function, operation_noun, cube, - other, cube.units, dim, in_place) + new_cube = _binary_op_common(operation_function, operation_name, cube, + other, cube.units, new_dtype=new_dtype, + dim=dim, in_place=in_place) if coord_comp: # If a coordinate is to be ignored - remove it @@ -284,17 +379,67 @@ def multiply(cube, other, dim=None, in_place=False): Kwargs: * dim: - If supplying a coord with no match on the cube, you must supply the dimension to process. + If supplying a coord with no match on the cube, you must supply + the dimension to process. Returns: An instance of :class:`iris.cube.Cube`. """ _assert_is_cube(cube) + new_dtype = _output_dtype(operator.mul, cube.dtype, _get_dtype(other), + in_place=in_place) other_unit = getattr(other, 'units', '1') new_unit = cube.units * other_unit - return _binary_op_common(np.multiply, 'multiplication', cube, other, - new_unit, dim, in_place) + if in_place: + _inplace_common_checks(cube, other, 'multiplication') + op = operator.imul + else: + op = operator.mul + + if isinstance(other, iris.cube.Cube): + # get a coordinate comparison of this cube and the cube to do the + # operation with + coord_comp = iris.analysis.coord_comparison(cube, other) + bad_coord_grps = (coord_comp['ungroupable_and_dimensioned'] + + coord_comp['resamplable']) + if bad_coord_grps: + raise ValueError('This operation cannot be performed as there are ' + 'differing coordinates (%s) remaining ' + 'which cannot be ignored.' + % ', '.join({coord_grp.name() for coord_grp + in bad_coord_grps})) + else: + coord_comp = None + + new_cube = _binary_op_common(op, 'multiply', cube, other, new_unit, + new_dtype=new_dtype, dim=dim, + in_place=in_place) + + if coord_comp: + # If a coordinate is to be ignored - remove it + ignore = filter(None, [coord_grp[0] for coord_grp + in coord_comp['ignorable']]) + for coord in ignore: + new_cube.remove_coord(coord) + + return new_cube + + +def _inplace_common_checks(cube, other, math_op): + """ + Check whether an inplace math operation can take place between `cube` and + `other`. It cannot if `cube` has integer data and `other` has float data + as the operation will always produce float data that cannot be 'safely' + cast back to the integer data of `cube`. + + """ + other_dtype = _get_dtype(other) + if not np.can_cast(other_dtype, cube.dtype, 'same_kind'): + aemsg = ('Cannot perform inplace {} between {!r} ' + 'with {} data and {!r} with {} data.') + raise ArithmeticError( + aemsg.format(math_op, cube, cube.dtype, other, other_dtype)) def divide(cube, other, dim=None, in_place=False): @@ -312,17 +457,55 @@ def divide(cube, other, dim=None, in_place=False): Kwargs: * dim: - If supplying a coord with no match on the cube, you must supply the dimension to process. + If supplying a coord with no match on the cube, you must supply + the dimension to process. Returns: An instance of :class:`iris.cube.Cube`. """ _assert_is_cube(cube) + new_dtype = _output_dtype(operator.truediv, + cube.dtype, _get_dtype(other), in_place=in_place) other_unit = getattr(other, 'units', '1') new_unit = cube.units / other_unit - return _binary_op_common(np.divide, 'divison', cube, other, new_unit, dim, - in_place) + if in_place: + if cube.dtype.kind in 'iu': + # Cannot coerce float result from inplace division back to int. + aemsg = ('Cannot perform inplace division of cube {!r} ' + 'with integer data.') + raise ArithmeticError(aemsg) + op = operator.itruediv + else: + op = operator.truediv + + if isinstance(other, iris.cube.Cube): + # get a coordinate comparison of this cube and the cube to do the + # operation with + coord_comp = iris.analysis.coord_comparison(cube, other) + bad_coord_grps = (coord_comp['ungroupable_and_dimensioned'] + + coord_comp['resamplable']) + if bad_coord_grps: + raise ValueError('This operation cannot be performed as there are ' + 'differing coordinates (%s) remaining ' + 'which cannot be ignored.' + % ', '.join({coord_grp.name() for coord_grp + in bad_coord_grps})) + else: + coord_comp = None + + new_cube = _binary_op_common(op, 'divide', cube, other, new_unit, + new_dtype=new_dtype, dim=dim, + in_place=in_place) + + if coord_comp: + # If a coordinate is to be ignored - remove it + ignore = filter(None, [coord_grp[0] for coord_grp + in coord_comp['ignorable']]) + for coord in ignore: + new_cube.remove_coord(coord) + + return new_cube def exponentiate(cube, exponent, in_place=False): @@ -336,8 +519,9 @@ def exponentiate(cube, exponent, in_place=False): * exponent: The integer or floating point exponent. - .. note:: When applied to the cube's unit, the exponent must result in a unit - that can be described using only integer powers of the basic units. + .. note:: When applied to the cube's unit, the exponent must + result in a unit that can be described using only integer + powers of the basic units. e.g. Unit('meter^-2 kilogram second^-1') @@ -351,9 +535,16 @@ def exponentiate(cube, exponent, in_place=False): """ _assert_is_cube(cube) - def power(data, out=None): - return np.power(data, exponent, out) - return _math_op_common(cube, power, cube.units ** exponent, + new_dtype = _output_dtype(operator.pow, cube.dtype, _get_dtype(exponent), + in_place=in_place) + if cube.has_lazy_data(): + def power(data): + return operator.pow(data, exponent) + else: + def power(data, out=None): + return np.power(data, exponent, out) + + return _math_op_common(cube, power, cube.units ** exponent, new_dtype, in_place=in_place) @@ -379,7 +570,10 @@ def exp(cube, in_place=False): An instance of :class:`iris.cube.Cube`. """ - return _math_op_common(cube, np.exp, iris.unit.Unit('1'), + _assert_is_cube(cube) + new_dtype = _output_dtype(np.exp, cube.dtype, in_place=in_place) + op = da.exp if cube.has_lazy_data() else np.exp + return _math_op_common(cube, op, cf_units.Unit('1'), new_dtype, in_place=in_place) @@ -401,7 +595,10 @@ def log(cube, in_place=False): An instance of :class:`iris.cube.Cube`. """ - return _math_op_common(cube, np.log, cube.units.log(math.e), + _assert_is_cube(cube) + new_dtype = _output_dtype(np.log, cube.dtype, in_place=in_place) + op = da.log if cube.has_lazy_data() else np.log + return _math_op_common(cube, op, cube.units.log(math.e), new_dtype, in_place=in_place) @@ -414,7 +611,7 @@ def log2(cube, in_place=False): * cube: An instance of :class:`iris.cube.Cube`. - Kwargs: + Kwargs:lib/iris/tests/unit/analysis/maths/test_subtract.py * in_place: Whether to create a new Cube, or alter the given "cube". @@ -423,7 +620,10 @@ def log2(cube, in_place=False): An instance of :class:`iris.cube.Cube`. """ - return _math_op_common(cube, np.log2, cube.units.log(2), + _assert_is_cube(cube) + new_dtype = _output_dtype(np.log2, cube.dtype, in_place=in_place) + op = da.log2 if cube.has_lazy_data() else np.log2 + return _math_op_common(cube, op, cube.units.log(2), new_dtype, in_place=in_place) @@ -445,21 +645,112 @@ def log10(cube, in_place=False): An instance of :class:`iris.cube.Cube`. """ - return _math_op_common(cube, np.log10, cube.units.log(10), + _assert_is_cube(cube) + new_dtype = _output_dtype(np.log10, cube.dtype, in_place=in_place) + op = da.log10 if cube.has_lazy_data() else np.log10 + return _math_op_common(cube, op, cube.units.log(10), new_dtype, in_place=in_place) -def _binary_op_common(operation_function, operation_noun, cube, other, - new_unit, dim=None, in_place=False): +def apply_ufunc(ufunc, cube, other_cube=None, new_unit=None, new_name=None, + in_place=False): + """ + Apply a `numpy universal function + `_ to a cube + or pair of cubes. + + .. note:: Many of the numpy.ufunc have been implemented explicitly in Iris + e.g. :func:`numpy.abs`, :func:`numpy.add` are implemented in + :func:`iris.analysis.maths.abs`, :func:`iris.analysis.maths.add`. + It is usually preferable to use these functions rather than + :func:`iris.analysis.maths.apply_ufunc` where possible. + + Args: + + * ufunc: + An instance of :func:`numpy.ufunc` e.g. :func:`numpy.sin`, + :func:`numpy.mod`. + + * cube: + An instance of :class:`iris.cube.Cube`. + + Kwargs: + + * other_cube: + An instance of :class:`iris.cube.Cube` to be given as the second + argument to :func:`numpy.ufunc`. + + * new_unit: + Unit for the resulting Cube. + + * new_name: + Name for the resulting Cube. + + * in_place: + Whether to create a new Cube, or alter the given "cube". + + Returns: + An instance of :class:`iris.cube.Cube`. + + Example:: + + cube = apply_ufunc(numpy.sin, cube, in_place=True) + + """ + + if not isinstance(ufunc, np.ufunc): + name = getattr(ufunc, '__name__', 'function passed to apply_ufunc') + + raise TypeError('{} is not recognised (it is not an instance of ' + 'numpy.ufunc)'.format(name)) + + if ufunc.nout != 1: + raise ValueError('{} returns {} objects, apply_ufunc currently ' + 'only supports ufunc functions returning a single ' + 'object.'.format(ufunc.__name__, ufunc.nout)) + + if ufunc.nin == 2: + if other_cube is None: + raise ValueError('{} requires two arguments, so other_cube ' + 'must also be passed to apply_ufunc'.format( + ufunc.__name__)) + + _assert_is_cube(other_cube) + new_dtype = _output_dtype(ufunc, cube.dtype, other_cube.dtype, + in_place=in_place) + + new_cube = _binary_op_common(ufunc, ufunc.__name__, cube, other_cube, + new_unit, new_dtype=new_dtype, + in_place=in_place) + + elif ufunc.nin == 1: + new_dtype = _output_dtype(ufunc, cube.dtype, in_place=in_place) + + new_cube = _math_op_common(cube, ufunc, new_unit, new_dtype, + in_place=in_place) + + else: + raise ValueError(ufunc.__name__ + ".nin should be 1 or 2.") + + new_cube.rename(new_name) + + return new_cube + + +def _binary_op_common(operation_function, operation_name, cube, other, + new_unit, new_dtype=None, dim=None, in_place=False): """ Function which shares common code between binary operations. - operation_function - function which does the operation (e.g. numpy.divide) - operation_noun - the noun of the operation (e.g. 'division') + operation_function - function which does the operation + (e.g. numpy.divide) + operation_name - the public name of the operation (e.g. 'divide') cube - the cube whose data is used as the first argument to `operation_function` other - the cube, coord, ndarray or number whose data is used as the second argument + new_dtype - the expected dtype of the output. Used in the + case of scalar masked arrays new_unit - unit for the resulting quantity dim - dimension along which to apply `other` if it's a coordinate that is not found in `cube` @@ -467,20 +758,24 @@ def _binary_op_common(operation_function, operation_noun, cube, other, `cube` and `cube.data` """ _assert_is_cube(cube) - if isinstance(other, iris.coords.Coord): - other = _broadcast_cube_coord_data(cube, other, operation_noun, dim) + other = _broadcast_cube_coord_data(cube, other, operation_name, dim) elif isinstance(other, iris.cube.Cube): - # TODO: add intelligent broadcasting along coordinate dimensions for - # all binary operators, not just + and - - other = other.data - # don't worry about checking for other data types (such as scalers or + try: + broadcast_shapes(cube.shape, other.shape) + except ValueError: + other = iris.util.as_compatible_shape(other, cube) + other = other.core_data() + else: + other = np.asanyarray(other) + + # don't worry about checking for other data types (such as scalars or # np.ndarrays) because _assert_compatible validates that they are broadcast # compatible with cube.data _assert_compatible(cube, other) - def unary_func(x, out=None): - ret = operation_function(x, other, out) + def unary_func(x): + ret = operation_function(x, other) if ret is NotImplemented: # explicitly raise the TypeError, so it gets raised even if, for # example, `iris.analysis.maths.multiply(cube, other)` is called @@ -489,10 +784,10 @@ def unary_func(x, out=None): (operation_function.__name__, type(x).__name__, type(other).__name__)) return ret - return _math_op_common(cube, unary_func, new_unit, in_place) + return _math_op_common(cube, unary_func, new_unit, new_dtype, in_place) -def _broadcast_cube_coord_data(cube, other, operation_noun, dim=None): +def _broadcast_cube_coord_data(cube, other, operation_name, dim=None): # What dimension are we processing? data_dimension = None if dim is not None: @@ -509,14 +804,14 @@ def _broadcast_cube_coord_data(cube, other, operation_noun, dim=None): except iris.exceptions.CoordinateNotFoundError: raise ValueError("Could not determine dimension for %s. " "Use %s(cube, coord, dim=dim)" - % (operation_noun, operation_noun)) + % (operation_name, operation_name)) if other.ndim != 1: raise iris.exceptions.CoordinateMultiDimError(other) if other.has_bounds(): - warnings.warn('%s by a bounded coordinate not well defined, ignoring ' - 'bounds.' % operation_noun) + warnings.warn('Using {!r} with a bounded coordinate is not well ' + 'defined; ignoring bounds.'.format(operation_name)) points = other.points @@ -530,13 +825,195 @@ def _broadcast_cube_coord_data(cube, other, operation_noun, dim=None): return points -def _math_op_common(cube, operation_function, new_unit, in_place=False): +def _math_op_common(cube, operation_function, new_unit, new_dtype=None, + in_place=False): _assert_is_cube(cube) + if in_place: new_cube = cube - operation_function(new_cube.data, out=new_cube.data) + if cube.has_lazy_data(): + new_cube.data = operation_function(cube.lazy_data()) + else: + try: + operation_function(cube.data, out=cube.data) + except TypeError: + # Non ufunc function + operation_function(cube.data) else: - new_cube = cube.copy(data=operation_function(cube.data)) + new_cube = cube.copy(data=operation_function(cube.core_data())) + + # If the result of the operation is scalar and masked, we need to fix up + # the dtype + if new_dtype is not None \ + and not new_cube.has_lazy_data() \ + and new_cube.data.shape == () \ + and ma.is_masked(new_cube.data): + new_cube.data = ma.masked_array(0, 1, dtype=new_dtype) + iris.analysis.clear_phenomenon_identity(new_cube) new_cube.units = new_unit return new_cube + + +class IFunc(object): + """ + :class:`IFunc` class for functions that can be applied to an iris cube. + """ + def __init__(self, data_func, units_func): + """ + Create an ifunc from a data function and units function. + + Args: + + * data_func: + + Function to be applied to one or two data arrays, which + are given as positional arguments. Should return another + data array, with the same shape as the first array. + + Can also have keyword arguments. + + * units_func: + + Function to calculate the unit of the resulting cube. + Should take the cube(s) as input and return + an instance of :class:`cf_units.Unit`. + + Returns: + An ifunc. + + **Example usage 1** Using an existing numpy ufunc, such as numpy.sin + for the data function and a simple lambda function for the units + function:: + + sine_ifunc = iris.analysis.maths.IFunc( + numpy.sin, lambda cube: cf_units.Unit('1')) + sine_cube = sine_ifunc(cube) + + **Example usage 2** Define a function for the data arrays of two cubes + and define a units function that checks the units of the cubes + for consistency, before giving the resulting cube the same units + as the first cube:: + + def ws_data_func(u_data, v_data): + return numpy.sqrt( u_data**2 + v_data**2 ) + + def ws_units_func(u_cube, v_cube): + if u_cube.units != getattr(v_cube, 'units', u_cube.units): + raise ValueError("units do not match") + return u_cube.units + + ws_ifunc = iris.analysis.maths.IFunc(ws_data_func, ws_units_func) + ws_cube = ws_ifunc(u_cube, v_cube, new_name='wind speed') + + **Example usage 3** Using a data function that allows a keyword + argument:: + + cs_ifunc = iris.analysis.maths.IFunc(numpy.cumsum, + lambda a: a.units) + cs_cube = cs_ifunc(cube, axis=1) + """ + + if hasattr(data_func, 'nin'): + self.nin = data_func.nin + else: + (args, varargs, keywords, defaults) = inspect.getargspec(data_func) + self.nin = len(args) - ( + len(defaults) if defaults is not None else 0) + + if self.nin not in [1, 2]: + msg = ('{} requires {} input data arrays, the IFunc class ' + 'currently only supports functions requiring 1 or two ' + 'data arrays as input.') + raise ValueError(msg.format(data_func.__name__, self.nin)) + + if hasattr(data_func, 'nout'): + if data_func.nout != 1: + msg = ('{} returns {} objects, the IFunc class currently ' + 'only supports functions returning a single object.') + raise ValueError(msg.format(data_func.__name__, + data_func.nout)) + + self.data_func = data_func + + self.units_func = units_func + + def __repr__(self): + return 'iris.analysis.maths.IFunc({}, {})'.format( + self.data_func.__name__, self.units_func.__name__) + + def __str__(self): + return ('IFunc constructed from the data function {} ' + 'and the units function {}'.format( + self.data_func.__name__, self.units_func.__name__)) + + def __call__(self, cube, other=None, dim=None, in_place=False, + new_name=None, **kwargs_data_func): + """ + Applies the ifunc to the cube(s). + + Args: + + * cube + An instance of :class:`iris.cube.Cube`, whose data is used + as the first argument to the data function. + + Kwargs: + + * other + A cube, coord, ndarray or number whose data is used as the + second argument to the data function. + + * new_name: + Name for the resulting Cube. + + * in_place: + Whether to create a new Cube, or alter the given "cube". + + * dim: + Dimension along which to apply `other` if it's a coordinate that is + not found in `cube` + + * **kwargs_data_func: + Keyword arguments that get passed on to the data_func. + + Returns: + An instance of :class:`iris.cube.Cube`. + + """ + _assert_is_cube(cube) + + def wrap_data_func(*args, **kwargs): + kwargs_combined = dict(kwargs_data_func, **kwargs) + + return self.data_func(*args, **kwargs_combined) + + if self.nin == 2: + if other is None: + raise ValueError(self.data_func.__name__ + + ' requires two arguments') + + new_unit = self.units_func(cube, other) + + new_cube = _binary_op_common(wrap_data_func, + self.data_func.__name__, cube, other, + new_unit, dim=dim, + in_place=in_place) + + elif self.nin == 1: + if other is not None: + raise ValueError(self.data_func.__name__ + + ' requires one argument') + + new_unit = self.units_func(cube) + + new_cube = _math_op_common(cube, wrap_data_func, new_unit, + in_place=in_place) + + else: + raise ValueError('self.nin should be 1 or 2.') + + if new_name is not None: + new_cube.rename(new_name) + + return new_cube diff --git a/lib/iris/analysis/stats.py b/lib/iris/analysis/stats.py index a1c9e81234..9654cdea0f 100644 --- a/lib/iris/analysis/stats.py +++ b/lib/iris/analysis/stats.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -19,138 +19,148 @@ """ -import numpy as np +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import numpy as np +import numpy.ma as ma import iris +from iris.util import broadcast_to_shape -def _get_calc_view(cube_a, cube_b, corr_coords): +def _ones_like(cube): """ - This function takes two cubes and returns cubes which are - flattened so that efficient comparisons can be performed - between the two. - - Args: - - * cube_a: - First cube of data - * cube_b: - Second cube of data, compatible with cube_a - * corr_coords: - Names of the dimension coordinates over which - to calculate correlations. - - Returns: - - * reshaped_a/reshaped_b: - The data arrays of cube_a/cube_b reshaped - so that the dimensions to be compared are - flattened into the 0th dimension of the - return array and other dimensions are - preserved. - * res_ind: - The indices of the dimensions that we - are not comparing, in terms of cube_a/cube_b - + Return a copy of cube with the same mask, but all data values set to 1. """ + ones_cube = cube.copy() + ones_cube.data = np.ones_like(cube.data) + ones_cube.rename('unknown') + ones_cube.units = 1 + return ones_cube - # Following lists to be filled with: - # indices of dimension we are not comparing - res_ind = [] - # indices of dimensions we are comparing - slice_ind = [] - for i, c in enumerate(cube_a.dim_coords): - if not c.name() in corr_coords: - res_ind.append(i) - else: - slice_ind.append(i) - # sanitise input - dim_coord_names = [c.name() for c in cube_a.dim_coords] - if corr_coords is None: - corr_coords = dim_coord_names - - if ([c.name() for c in cube_a.dim_coords] != - [c.name() for c in cube_b.dim_coords]): - raise ValueError("Cubes are incompatible.") - - for c in corr_coords: - if c not in dim_coord_names: - raise ValueError("%s coord " - "does not exist in cube." % c) - - # Reshape data to be data to correlate in 0th dim and - # other grid points in 1st dim. - # Transpose to group the correlation data dims before the - # grid point dims. - data_a = cube_a.data.view() - data_b = cube_b.data.view() - dim_i_len = np.prod(np.array(cube_a.shape)[slice_ind]) - dim_j_len = np.prod(np.array(cube_a.shape)[res_ind]) - reshaped_a = data_a.transpose(slice_ind+res_ind)\ - .reshape(dim_i_len, dim_j_len) - reshaped_b = data_b.transpose(slice_ind+res_ind)\ - .reshape(dim_i_len, dim_j_len) - - return reshaped_a, reshaped_b, res_ind - - -def pearsonr(cube_a, cube_b, corr_coords=None): +def pearsonr(cube_a, cube_b, corr_coords=None, weights=None, mdtol=1., + common_mask=False): """ - Calculates the n-D Pearson's r correlation - cube over the dimensions associated with the - given coordinates. - - Returns a cube of the correlation between the two - cubes along the dimensions of the given - coordinates, at each point in the remaining - dimensions of the cubes. - - For example providing two time/altitude/latitude/longitude - cubes and corr_coords of 'latitude' and 'longitude' will result - in a time/altitude cube describing the latitude/longitude - (i.e. pattern) correlation at each time/altitude point. + Calculate the Pearson's r correlation coefficient over specified + dimensions. Args: * cube_a, cube_b (cubes): - Between which the correlation field will be calculated. - Cubes should be the same shape and have the - same dimension coordinates. - * corr_coords (list of str): - The cube coordinate names over which to calculate - correlations. If no names are provided then - correlation will be calculated over all cube - dimensions. + Cubes between which the correlation will be calculated. The cubes + should either be the same shape and have the same dimension coordinates + or one cube should be broadcastable to the other. + * corr_coords (str or list of str): + The cube coordinate name(s) over which to calculate correlations. If no + names are provided then correlation will be calculated over all common + cube dimensions. + * weights (numpy.ndarray, optional): + Weights array of same shape as (the smaller of) cube_a and cube_b. Note + that latitude/longitude area weights can be calculated using + :func:`iris.analysis.cartography.area_weights`. + * mdtol (float, optional): + Tolerance of missing data. The missing data fraction is calculated + based on the number of grid cells masked in both cube_a and cube_b. If + this fraction exceed mdtol, the returned value in the corresponding + cell is masked. mdtol=0 means no missing data is tolerated while + mdtol=1 means the resulting element will be masked if and only if all + contributing elements are masked in cube_a or cube_b. Defaults to 1. + * common_mask (bool): + If True, applies a common mask to cube_a and cube_b so only cells which + are unmasked in both cubes contribute to the calculation. If False, the + variance for each cube is calculated from all available cells. Defaults + to False. Returns: - Cube of correlations. + A cube of the correlation between the two input cubes along the + specified dimensions, at each point in the remaining dimensions of the + cubes. + + For example providing two time/altitude/latitude/longitude cubes and + corr_coords of 'latitude' and 'longitude' will result in a + time/altitude cube describing the latitude/longitude (i.e. pattern) + correlation at each time/altitude point. Reference: http://www.statsoft.com/textbook/glosp.html#Pearson%20Correlation """ - # If no coords passed then set to all coords of cube. + # Assign larger cube to cube_1 + if cube_b.ndim > cube_a.ndim: + cube_1 = cube_b + cube_2 = cube_a + else: + cube_1 = cube_a + cube_2 = cube_b + + dim_coords_1 = [coord.name() for coord in cube_1.dim_coords] + dim_coords_2 = [coord.name() for coord in cube_2.dim_coords] + common_dim_coords = list(set(dim_coords_1) & set(dim_coords_2)) + # If no coords passed then set to all common dimcoords of cubes. if corr_coords is None: - corr_coords = [c.name() for c in cube_a.dim_coords] - - vec_a, vec_b, res_ind = _get_calc_view(cube_a, - cube_b, - corr_coords) + corr_coords = common_dim_coords - sa = vec_a - np.mean(vec_a, 0) - sb = vec_b - np.mean(vec_b, 0) - flat_corrs = np.sum((sa*sb), 0)/np.sqrt(np.sum(sa**2, 0)*np.sum(sb**2, 0)) + smaller_shape = cube_2.shape - corrs = flat_corrs.reshape([cube_a.shape[i] for i in res_ind]) - - # Construct cube to hold correlation results. - corrs_cube = iris.cube.Cube(corrs) - corrs_cube.long_name = "Pearson's r" - corrs_cube.units = "1" - for i, dim in enumerate(res_ind): - c = cube_a.dim_coords[dim] - corrs_cube.add_dim_coord(c, i) - - return corrs_cube + # Match up data masks if required. + if common_mask: + # Create a cube of 1's with a common mask. + if ma.is_masked(cube_2.data): + mask_cube = _ones_like(cube_2) + else: + mask_cube = 1. + if ma.is_masked(cube_1.data): + # Take a slice to avoid unnecessary broadcasting of cube_2. + slice_coords = [dim_coords_1[i] for i in range(cube_1.ndim) if + dim_coords_1[i] not in common_dim_coords and + np.array_equal(cube_1.data.mask.any(axis=i), + cube_1.data.mask.all(axis=i))] + cube_1_slice = next(cube_1.slices_over(slice_coords)) + mask_cube = _ones_like(cube_1_slice) * mask_cube + # Apply common mask to data. + if isinstance(mask_cube, iris.cube.Cube): + cube_1 = cube_1 * mask_cube + cube_2 = mask_cube * cube_2 + dim_coords_2 = [coord.name() for coord in cube_2.dim_coords] + + # Broadcast weights to shape of cubes if necessary. + if weights is None or cube_1.shape == smaller_shape: + weights_1 = weights + weights_2 = weights + else: + if weights.shape != smaller_shape: + raise ValueError("weights array should have dimensions {}". + format(smaller_shape)) + + dims_1_common = [i for i in range(cube_1.ndim) if + dim_coords_1[i] in common_dim_coords] + weights_1 = broadcast_to_shape(weights, cube_1.shape, dims_1_common) + if cube_2.shape != smaller_shape: + dims_2_common = [i for i in range(cube_2.ndim) if + dim_coords_2[i] in common_dim_coords] + weights_2 = broadcast_to_shape(weights, cube_2.shape, + dims_2_common) + else: + weights_2 = weights + + # Calculate correlations. + s1 = cube_1 - cube_1.collapsed(corr_coords, iris.analysis.MEAN, + weights=weights_1) + s2 = cube_2 - cube_2.collapsed(corr_coords, iris.analysis.MEAN, + weights=weights_2) + + covar = (s1*s2).collapsed(corr_coords, iris.analysis.SUM, + weights=weights_1, mdtol=mdtol) + var_1 = (s1**2).collapsed(corr_coords, iris.analysis.SUM, + weights=weights_1) + var_2 = (s2**2).collapsed(corr_coords, iris.analysis.SUM, + weights=weights_2) + + denom = iris.analysis.maths.apply_ufunc(np.sqrt, var_1*var_2, + new_unit=covar.units) + corr_cube = covar / denom + corr_cube.rename("Pearson's r") + + return corr_cube diff --git a/lib/iris/analysis/trajectory.py b/lib/iris/analysis/trajectory.py index e81602f194..878a07e68a 100644 --- a/lib/iris/analysis/trajectory.py +++ b/lib/iris/analysis/trajectory.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -15,29 +15,40 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """ -Defines a Trajectory class, and a routine to extract a sub-cube along a trajectory. +Defines a Trajectory class, and a routine to extract a sub-cube along a +trajectory. """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + import math import numpy as np +from scipy.spatial import cKDTree +import iris.analysis import iris.coord_systems import iris.coords -import iris.analysis + +from iris.analysis import Linear +from iris.analysis._interpolation import snapshot_grid +from iris.util import _meshgrid class _Segment(object): - """A single trajectory line segment: Two points, as described in the Trajectory class.""" + """A single trajectory line segment: Two points, as described in the + Trajectory class.""" def __init__(self, p0, p1): - #check keys + # check keys if sorted(p0.keys()) != sorted(p1.keys()): raise ValueError("keys do not match") self.pts = [p0, p1] - #calculate our length + # calculate our length squares = 0 for key in self.pts[0].keys(): delta = self.pts[1][key] - self.pts[0][key] @@ -54,10 +65,12 @@ def __init__(self, waypoints, sample_count=10): For example:: - waypoints = [{'latitude': 45, 'longitude': -60}, {'latitude': 45, 'longitude': 0}] + waypoints = [{'latitude': 45, 'longitude': -60}, + {'latitude': 45, 'longitude': 0}] Trajectory(waypoints) - .. note:: All the waypoint dictionaries must contain the same coordinate names. + .. note:: All the waypoint dictionaries must contain the same + coordinate names. Args: @@ -74,16 +87,18 @@ def __init__(self, waypoints, sample_count=10): self.sample_count = sample_count # create line segments from the waypoints - segments = [_Segment(self.waypoints[i], self.waypoints[i+1]) for i in range(len(self.waypoints) - 1)] + segments = [_Segment(self.waypoints[i], self.waypoints[i+1]) + for i in range(len(self.waypoints) - 1)] # calculate our total length self.length = sum([seg.length for seg in segments]) # generate our sampled points + #: The trajectory points, as dictionaries of {coord_name: value}. self.sampled_points = [] sample_step = self.length / (self.sample_count - 1) - #start with the first segment + # start with the first segment cur_seg_i = 0 cur_seg = segments[cur_seg_i] len_accum = cur_seg.length @@ -93,7 +108,7 @@ def __init__(self, waypoints, sample_count=10): sample_at_len = p * sample_step # skip forward to the containing segment - while(len_accum < sample_at_len and cur_seg_i < len(segments)): + while len_accum < sample_at_len and cur_seg_i < len(segments): cur_seg_i += 1 cur_seg = segments[cur_seg_i] len_accum += cur_seg.length @@ -102,17 +117,87 @@ def __init__(self, waypoints, sample_count=10): seg_start_len = len_accum - cur_seg.length seg_frac = (sample_at_len-seg_start_len) / cur_seg.length - # sample each coordinate in this segment, to create a new sampled point + # sample each coordinate in this segment, to create a new + # sampled point new_sampled_point = {} for key in cur_seg.pts[0].keys(): seg_coord_delta = cur_seg.pts[1][key] - cur_seg.pts[0][key] - new_sampled_point.update({key: cur_seg.pts[0][key] + seg_frac*seg_coord_delta}) + new_sampled_point.update({key: cur_seg.pts[0][key] + + seg_frac*seg_coord_delta}) # add this new sampled point self.sampled_points.append(new_sampled_point) def __repr__(self): - return 'Trajectory(%s, sample_count=%s)' % (self.waypoints, self.sample_count) + return 'Trajectory(%s, sample_count=%s)' % (self.waypoints, + self.sample_count) + + def _get_interp_points(self): + """ + Translate `self.sampled_points` to the format expected by the + interpolator. + + Returns: + `self.sampled points` in the format required by + `:func:`~iris.analysis.trajectory.interpolate`. + + """ + points = {k: [point_dict[k] for point_dict in self.sampled_points] + for k in self.sampled_points[0].keys()} + return [(k, v) for k, v in points.items()] + + def _src_cube_anon_dims(self, cube): + """ + A helper method to locate the index of anonymous dimensions on the + interpolation target, ``cube``. + + Returns: + The index of any anonymous dimensions in ``cube``. + + """ + named_dims = [cube.coord_dims(c)[0] for c in cube.dim_coords] + return list(set(range(cube.ndim)) - set(named_dims)) + + def interpolate(self, cube, method=None): + """ + Calls :func:`~iris.analysis.trajectory.interpolate` to interpolate + ``cube`` on the defined trajectory. + + Assumes that the coordinate names supplied in the waypoints + dictionaries match to coordinate names in `cube`, and that points are + supplied in the same coord_system as in `cube`, where appropriate (i.e. + for horizontal coordinate points). + + Args: + + * cube + The source Cube to interpolate. + + Kwargs: + + * method: + The interpolation method to use; "linear" (default) or "nearest". + Only nearest is available when specifying multi-dimensional + coordinates. + + """ + sample_points = self._get_interp_points() + interpolated_cube = interpolate(cube, sample_points, method=method) + # Add an "index" coord to name the anonymous dimension produced by + # the interpolation, if present. + if len(interpolated_cube.dim_coords) < interpolated_cube.ndim: + # Add a new coord `index` to describe the new dimension created by + # interpolating. + index_coord = iris.coords.DimCoord(range(self.sample_count), + long_name='index') + # Make sure anonymous dims in `cube` do not mistakenly get labelled + # as the new `index` dimension created by interpolating. + src_anon_dims = self._src_cube_anon_dims(cube) + interp_anon_dims = self._src_cube_anon_dims(interpolated_cube) + anon_dim_index, = list(set(interp_anon_dims) - set(src_anon_dims)) + # Add the new coord to the interpolated cube. + interpolated_cube.add_dim_coord(index_coord, anon_dim_index) + return interpolated_cube def interpolate(cube, sample_points, method=None): @@ -131,12 +216,14 @@ def interpolate(cube, sample_points, method=None): * method Request "linear" interpolation (default) or "nearest" neighbour. - Only nearest neighbour is available when specifying multi-dimensional coordinates. + Only nearest neighbour is available when specifying multi-dimensional + coordinates. For example:: - - sample_points = [('latitude', [45, 45, 45]), ('longitude', [-60, -50, -40])] + + sample_points = [('latitude', [45, 45, 45]), + ('longitude', [-60, -50, -40])] interpolated_cube = interpolate(cube, sample_points) """ @@ -146,7 +233,7 @@ def interpolate(cube, sample_points, method=None): # Convert any coordinate names to coords points = [] for coord, values in sample_points: - if isinstance(coord, basestring): + if isinstance(coord, six.string_types): coord = cube.coord(coord) points.append((coord, values)) sample_points = points @@ -165,13 +252,16 @@ def interpolate(cube, sample_points, method=None): for dim in dims: squish_my_dims.add(dim) - # Derive the new cube's shape by filtering out all the dimensions we're about to sample, + # Derive the new cube's shape by filtering out all the dimensions we're + # about to sample, # and then adding a new dimension to accommodate all the sample points. - remaining = [(dim, size) for dim, size in enumerate(cube.shape) if dim not in squish_my_dims] + remaining = [(dim, size) for dim, size in enumerate(cube.shape) if dim + not in squish_my_dims] new_data_shape = [size for dim, size in remaining] new_data_shape.append(trajectory_size) - # Start with empty data and then fill in the "column" of values for each trajectory point. + # Start with empty data and then fill in the "column" of values for each + # trajectory point. new_cube = iris.cube.Cube(np.empty(new_data_shape)) new_cube.metadata = cube.metadata @@ -223,30 +313,539 @@ def interpolate(cube, sample_points, method=None): for coord, values in sample_points: if coord.ndim > 1: if method == "linear": - raise iris.exceptions.CoordinateMultiDimError("Cannot currently perform linear interpolation for multi-dimensional coordinates.") + msg = "Cannot currently perform linear interpolation for " \ + "multi-dimensional coordinates." + raise iris.exceptions.CoordinateMultiDimError(msg) method = "nearest" break - # Use a cache with _nearest_neighbour_indices_ndcoords() - cache = {} - - for i in range(trajectory_size): - point = [(coord, values[i]) for coord, values in sample_points] - - if method in ["linear", None]: - column = iris.analysis.interpolate.linear(cube, point) - new_cube.data[..., i] = column.data - elif method == "nearest": - column_index = iris.analysis.interpolate._nearest_neighbour_indices_ndcoords(cube, point, cache=cache) - column = cube[column_index] + if method in ["linear", None]: + for i in range(trajectory_size): + point = [(coord, values[i]) for coord, values in sample_points] + column = cube.interpolate(point, Linear()) new_cube.data[..., i] = column.data + # Fill in the empty squashed (non derived) coords. + for column_coord in column.dim_coords + column.aux_coords: + src_dims = cube.coord_dims(column_coord) + if not squish_my_dims.isdisjoint(src_dims): + if len(column_coord.points) != 1: + msg = "Expected to find exactly one point. Found {}." + raise Exception(msg.format(column_coord.points)) + new_cube.coord(column_coord.name()).points[i] = \ + column_coord.points[0] + + elif method == "nearest": + # Use a cache with _nearest_neighbour_indices_ndcoords() + cache = {} + column_indexes = _nearest_neighbour_indices_ndcoords( + cube, sample_points, cache=cache) + + # Construct "fancy" indexes, so we can create the result data array in + # a single numpy indexing operation. + # ALSO: capture the index range in each dimension, so that we can fetch + # only a required (square) sub-region of the source data. + fancy_source_indices = [] + region_slices = [] + n_index_length = len(column_indexes[0]) + dims_reduced = [False] * n_index_length + for i_ind in range(n_index_length): + contents = [column_index[i_ind] + for column_index in column_indexes] + each_used = [content != slice(None) for content in contents] + if np.all(each_used): + # This dimension is addressed : use a list of indices. + dims_reduced[i_ind] = True + # Select the region by min+max indices. + start_ind = np.min(contents) + stop_ind = 1 + np.max(contents) + region_slice = slice(start_ind, stop_ind) + # Record point indices with start subtracted from all of them. + fancy_index = list(np.array(contents) - start_ind) + elif not np.any(each_used): + # This dimension is not addressed by the operation. + # Use a ":" as the index. + fancy_index = slice(None) + # No sub-region selection for this dimension. + region_slice = slice(None) + else: + # Should really never happen, if _ndcoords is right. + msg = ('Internal error in trajectory interpolation : point ' + 'selection indices should all have the same form.') + raise ValueError(msg) + + fancy_source_indices.append(fancy_index) + region_slices.append(region_slice) + + # Fetch the required (square-section) region of the source data. + # NOTE: This is not quite as good as only fetching the individual + # points used, but it avoids creating a sub-cube for each point, + # which is very slow, especially when points are re-used a lot ... + source_area_indices = tuple(region_slices) + source_data = cube[source_area_indices].data + + # Transpose source data before indexing it to get the final result. + # Because.. the fancy indexing will replace the indexed (horizontal) + # dimensions with a new single dimension over trajectory points. + # Move those dimensions to the end *first* : this ensures that the new + # dimension also appears at the end, which is where we want it. + # Make a list of dims with the reduced ones last. + dims_reduced = np.array(dims_reduced) + dims_order = np.arange(n_index_length) + dims_order = np.concatenate((dims_order[~dims_reduced], + dims_order[dims_reduced])) + # Rearrange the data dimensions and the fancy indices into that order. + source_data = source_data.transpose(dims_order) + fancy_source_indices = [fancy_source_indices[i_dim] + for i_dim in dims_order] + + # Apply the fancy indexing to get all the result data points. + source_data = source_data[fancy_source_indices] + + # "Fix" problems with missing datapoints producing odd values + # when copied from a masked into an unmasked array. + # TODO: proper masked data handling. + if np.ma.isMaskedArray(source_data): + # This is **not** proper mask handling, because we cannot produce a + # masked result, but it ensures we use a "filled" version of the + # input in this case. + source_data = source_data.filled() + new_cube.data[:] = source_data + # NOTE: we assign to "new_cube.data[:]" and *not* just "new_cube.data", + # because the existing code produces a default dtype from 'np.empty' + # instead of preserving the input dtype. + # TODO: maybe this should be fixed -- i.e. to preserve input dtype ?? # Fill in the empty squashed (non derived) coords. - for column_coord in column.dim_coords + column.aux_coords: - src_dims = cube.coord_dims(column_coord) - if not squish_my_dims.isdisjoint(src_dims): - if len(column_coord.points) != 1: - raise Exception("Expected to find exactly one point. Found %d" % len(column_coord.points)) - new_cube.coord(column_coord.name()).points[i] = column_coord.points[0] + column_coords = [coord + for coord in cube.dim_coords + cube.aux_coords + if not squish_my_dims.isdisjoint( + cube.coord_dims(coord))] + new_cube_coords = [new_cube.coord(column_coord.name()) + for column_coord in column_coords] + all_point_indices = np.array(column_indexes) + single_point_test_cube = cube[column_indexes[0]] + for new_cube_coord, src_coord in zip(new_cube_coords, column_coords): + # Check structure of the indexed coord (at one selected point). + point_coord = single_point_test_cube.coord(src_coord) + if len(point_coord.points) != 1: + msg = ('Coord {} at one x-y position has the shape {}, ' + 'instead of being a single point. ') + raise ValueError(msg.format(src_coord.name(), src_coord.shape)) + + # Work out which indices apply to the input coord. + # NOTE: we know how to index the source cube to get a cube with a + # single point for each coord, but this is very inefficient. + # So here, we translate cube indexes into *coord* indexes. + src_coord_dims = cube.coord_dims(src_coord) + fancy_coord_index_arrays = [list(all_point_indices[:, src_dim]) + for src_dim in src_coord_dims] + + # Fill the new coord with all the correct points from the old one. + new_cube_coord.points = src_coord.points[fancy_coord_index_arrays] + # NOTE: the new coords do *not* have bounds. return new_cube + + +def _ll_to_cart(lon, lat): + # Based on cartopy.img_transform.ll_to_cart(). + x = np.sin(np.deg2rad(90 - lat)) * np.cos(np.deg2rad(lon)) + y = np.sin(np.deg2rad(90 - lat)) * np.sin(np.deg2rad(lon)) + z = np.cos(np.deg2rad(90 - lat)) + return (x, y, z) + + +def _cartesian_sample_points(sample_points, sample_point_coord_names): + """ + Replace geographic lat/lon with cartesian xyz. + Generates coords suitable for nearest point calculations with + `scipy.spatial.cKDTree`. + + Args: + + * sample_points[coord][datum]: + list of sample_positions for each datum, formatted for fast use of + :func:`_ll_to_cart()`. + + * sample_point_coord_names[coord]: + list of n coord names + + Returns: + list of [x,y,z,t,etc] positions, formatted for kdtree. + + """ + # Find lat and lon coord indices + i_lat = i_lon = None + i_non_latlon = list(range(len(sample_point_coord_names))) + for i, name in enumerate(sample_point_coord_names): + if "latitude" in name: + i_lat = i + i_non_latlon.remove(i_lat) + if "longitude" in name: + i_lon = i + i_non_latlon.remove(i_lon) + + if i_lat is None or i_lon is None: + return sample_points.transpose() + + num_points = len(sample_points[0]) + cartesian_points = [None] * num_points + + # Get the point coordinates without the latlon + for p in range(num_points): + cartesian_points[p] = [sample_points[c][p] for c in i_non_latlon] + + # Add cartesian xyz coordinates from latlon + x, y, z = _ll_to_cart(sample_points[i_lon], sample_points[i_lat]) + for p in range(num_points): + cartesian_point = cartesian_points[p] + cartesian_point.append(x[p]) + cartesian_point.append(y[p]) + cartesian_point.append(z[p]) + + return cartesian_points + + +def _nearest_neighbour_indices_ndcoords(cube, sample_points, cache=None): + """ + Returns the indices to select the data value(s) closest to the given + coordinate point values. + + 'sample_points' is of the form [[coord-or-coord-name, point-value(s)]*]. + The lengths of all the point-values sequences must be equal. + + This function is adapted for points sampling a multi-dimensional coord, + and can currently only do nearest neighbour interpolation. + + Because this function can be slow for multidimensional coordinates, + a 'cache' dictionary can be provided by the calling code. + + .. Note:: + + If the points are longitudes/latitudes, these are handled correctly as + points on the sphere, but the values must be in 'degrees'. + + Developer notes: + A "sample space cube" is made which only has the coords and dims we are + sampling on. + We get the nearest neighbour using this sample space cube. + + """ + if sample_points: + try: + coord, value = sample_points[0] + except (KeyError, ValueError): + emsg = ('Sample points must be a list of ' + '(coordinate, value) pairs, got {!r}.') + raise TypeError(emsg.format(sample_points)) + + # Convert names to coords in sample_point and reformat sample point values + # for use in `_cartesian_sample_points()`. + coord_values = [] + sample_point_coords = [] + sample_point_coord_names = [] + ok_coord_ids = set(map(id, cube.dim_coords + cube.aux_coords)) + for coord, value in sample_points: + coord = cube.coord(coord) + if id(coord) not in ok_coord_ids: + msg = ('Invalid sample coordinate {!r}: derived coordinates are' + ' not allowed.'.format(coord.name())) + raise ValueError(msg) + sample_point_coords.append(coord) + sample_point_coord_names.append(coord.name()) + value = np.array(value, ndmin=1) + coord_values.append(value) + + coord_point_lens = np.array([len(value) for value in coord_values]) + if not np.all(coord_point_lens == coord_point_lens[0]): + msg = 'All coordinates must have the same number of sample points.' + raise ValueError(msg) + + coord_values = np.array(coord_values) + + # Which dims are we sampling? + sample_dims = set() + for coord in sample_point_coords: + for dim in cube.coord_dims(coord): + sample_dims.add(dim) + sample_dims = sorted(list(sample_dims)) + + # Extract a sub cube that lives in just the sampling space. + sample_space_slice = [0] * cube.ndim + for sample_dim in sample_dims: + sample_space_slice[sample_dim] = slice(None, None) + sample_space_slice = tuple(sample_space_slice) + sample_space_cube = cube[sample_space_slice] + + # Just the sampling coords. + for coord in sample_space_cube.coords(): + if not coord.name() in sample_point_coord_names: + sample_space_cube.remove_coord(coord) + + # Order the sample point coords according to the sample space cube coords. + sample_space_coord_names = \ + [coord.name() for coord in sample_space_cube.coords()] + new_order = [sample_space_coord_names.index(name) + for name in sample_point_coord_names] + coord_values = np.array([coord_values[i] for i in new_order]) + sample_point_coord_names = [sample_point_coord_names[i] for i in new_order] + + sample_space_coords = \ + sample_space_cube.dim_coords + sample_space_cube.aux_coords + sample_space_coords_and_dims = \ + [(coord, sample_space_cube.coord_dims(coord)) + for coord in sample_space_coords] + + if cache is not None and cube in cache: + kdtree = cache[cube] + else: + # Create a "sample space position" for each + # `datum.sample_space_data_positions[coord_index][datum_index]`. + sample_space_data_positions = \ + np.empty((len(sample_space_coords_and_dims), + sample_space_cube.data.size), + dtype=float) + for d, ndi in enumerate(np.ndindex(sample_space_cube.data.shape)): + for c, (coord, coord_dims) in \ + enumerate(sample_space_coords_and_dims): + # Index of this datum along this coordinate (could be nD). + if coord_dims: + keys = tuple(ndi[ind] for ind in coord_dims) + else: + keys = slice(None, None) + # Position of this datum along this coordinate. + sample_space_data_positions[c][d] = coord.points[keys] + + # Convert to cartesian coordinates. Flatten for kdtree compatibility. + cartesian_space_data_coords = \ + _cartesian_sample_points(sample_space_data_positions, + sample_point_coord_names) + + # Create a kdtree for the nearest-distance lookup to these 3d points. + kdtree = cKDTree(cartesian_space_data_coords) + # This can find the nearest datum point to any given target point, + # which is the goal of this function. + + # Update cache. + if cache is not None: + cache[cube] = kdtree + + # Convert the sample points to cartesian (3d) coords. + # If there is no latlon within the coordinate there will be no change. + # Otherwise, geographic latlon is replaced with cartesian xyz. + cartesian_sample_points = _cartesian_sample_points( + coord_values, sample_point_coord_names) + + # Use kdtree to get the nearest sourcepoint index for each target point. + _, datum_index_lists = kdtree.query(cartesian_sample_points) + + # Convert flat indices back into multidimensional sample-space indices. + sample_space_dimension_indices = np.unravel_index( + datum_index_lists, sample_space_cube.data.shape) + # Convert this from "pointwise list of index arrays for each dimension", + # to "list of cube indices for each point". + sample_space_ndis = np.array(sample_space_dimension_indices).transpose() + + # For the returned result, we must convert these indices into the source + # (sample-space) cube, to equivalent indices into the target 'cube'. + + # Make a result array: (cube.ndim * ), per sample point. + n_points = coord_values.shape[-1] + main_cube_slices = np.empty((n_points, cube.ndim), dtype=object) + # Initialise so all unused indices are ":". + main_cube_slices[:] = slice(None) + + # Move result indices according to the source (sample) and target (cube) + # dimension mappings. + for sample_coord, sample_coord_dims in sample_space_coords_and_dims: + # Find the coord in the main cube + main_coord = cube.coord(sample_coord.name()) + main_coord_dims = cube.coord_dims(main_coord) + # Fill nearest-point data indices for each coord dimension. + for sample_i, main_i in zip(sample_coord_dims, main_coord_dims): + main_cube_slices[:, main_i] = sample_space_ndis[:, sample_i] + + # Return as a list of **tuples** : required for correct indexing usage. + result = [tuple(inds) for inds in main_cube_slices] + return result + + +class UnstructuredNearestNeigbourRegridder(object): + """ + Encapsulate the operation of :meth:`iris.analysis.trajectory.interpolate` + with given source and target grids. + + This is the type used by the :class:`~iris.analysis.UnstructuredNearest` + regridding scheme. + + """ + # TODO: cache the necessary bits of the operation so re-use can actually + # be more efficient. + def __init__(self, src_cube, target_grid_cube): + """ + A nearest-neighbour regridder to perform regridding from the source + grid to the target grid. + + This can then be applied to any source data with the same structure as + the original 'src_cube'. + + Args: + + * src_cube: + The :class:`~iris.cube.Cube` defining the source grid. + The X and Y coordinates can have any shape, but must be mapped over + the same cube dimensions. + + * target_grid_cube: + A :class:`~iris.cube.Cube`, whose X and Y coordinates specify a + desired target grid. + The X and Y coordinates must be one-dimensional dimension + coordinates, mapped to different dimensions. + All other cube components are ignored. + + Returns: + regridder : (object) + + A callable object with the interface: + `result_cube = regridder(data)` + + where `data` is a cube with the same grid as the original + `src_cube`, that is to be regridded to the `target_grid_cube`. + + .. Note:: + + For latitude-longitude coordinates, the nearest-neighbour distances + are computed on the sphere, otherwise flat Euclidean distances are + used. + + The source and target X and Y coordinates must all have the same + coordinate system, which may also be None. + If any X and Y coordinates are latitudes or longitudes, they *all* + must be. Otherwise, the corresponding X and Y coordinates must + have the same units in the source and grid cubes. + + """ + # Make a copy of the source cube, so we can convert coordinate units. + src_cube = src_cube.copy() + + # Snapshot the target grid and check it is a "normal" grid. + tgt_x_coord, tgt_y_coord = snapshot_grid(target_grid_cube) + + # Check that the source has unique X and Y coords over common dims. + if (not src_cube.coords(axis='x') or not src_cube.coords(axis='y')): + msg = 'Source cube must have X- and Y-axis coordinates.' + raise ValueError(msg) + src_x_coord = src_cube.coord(axis='x') + src_y_coord = src_cube.coord(axis='y') + if (src_cube.coord_dims(src_x_coord) != + src_cube.coord_dims(src_y_coord)): + msg = ('Source cube X and Y coordinates must have the same ' + 'cube dimensions.') + raise ValueError(msg) + + # Record *copies* of the original grid coords, in the desired + # dimension order. + # This lets us convert the actual ones in use to units of "degrees". + self.src_grid_coords = [src_y_coord.copy(), src_x_coord.copy()] + self.tgt_grid_coords = [tgt_y_coord.copy(), tgt_x_coord.copy()] + + # Check that all XY coords have suitable coordinate systems and units. + coords_all = [src_x_coord, src_y_coord, tgt_x_coord, tgt_y_coord] + cs = coords_all[0].coord_system + if not all(coord.coord_system == cs for coord in coords_all): + msg = ('Source and target cube X and Y coordinates must all have ' + 'the same coordinate system.') + raise ValueError(msg) + + # Check *all* X and Y coords are lats+lons, if any are. + latlons = ['latitude' in coord.name() or 'longitude' in coord.name() + for coord in coords_all] + if any(latlons) and not all(latlons): + msg = ('If any X and Y coordinates are latitudes/longitudes, ' + 'then they all must be.') + raise ValueError(msg) + + self.grid_is_latlon = any(latlons) + if self.grid_is_latlon: + # Convert all XY coordinates to units of "degrees". + # N.B. already copied the target grid, so the result matches that. + for coord in coords_all: + try: + coord.convert_units('degrees') + except ValueError: + msg = ('Coordinate {!r} has units of {!r}, which does not ' + 'convert to "degrees".') + raise ValueError(msg.format(coord.name(), + str(coord.units))) + else: + # Check that source and target have the same X and Y units. + if (src_x_coord.units != tgt_x_coord.units or + src_y_coord.units != tgt_y_coord.units): + msg = ('Source and target cube X and Y coordinates must ' + 'have the same units.') + raise ValueError(msg) + + # Record the resulting grid shape. + self.tgt_grid_shape = tgt_y_coord.shape + tgt_x_coord.shape + + # Calculate sample points as 2d arrays, like broadcast (NY,1)*(1,NX). + x_2d, y_2d = _meshgrid(tgt_x_coord.points, tgt_y_coord.points) + # Cast as a "trajectory", to suit the method used. + self.trajectory = ((tgt_x_coord.name(), x_2d.flatten()), + (tgt_y_coord.name(), y_2d.flatten())) + + def __call__(self, src_cube): + # Check the source cube X and Y coords match the original. + # Note: for now, this is sufficient to ensure a valid trajectory + # interpolation, but if in future we save + re-use the cache context + # for the 'interpolate' call, we may need more checks here. + + # Check the given cube against the original. + x_cos = src_cube.coords(axis='x') + y_cos = src_cube.coords(axis='y') + if (not x_cos or not y_cos or + y_cos != [self.src_grid_coords[0]] or + x_cos != [self.src_grid_coords[1]]): + msg = ('The given cube is not defined on the same source ' + 'grid as this regridder.') + raise ValueError(msg) + + # Convert source XY coordinates to degrees if required. + if self.grid_is_latlon: + src_cube = src_cube.copy() + src_cube.coord(axis='x').convert_units('degrees') + src_cube.coord(axis='y').convert_units('degrees') + + # Get the basic interpolated results. + result_trajectory_cube = interpolate(src_cube, self.trajectory, + method='nearest') + + # Reconstruct this as a cube "like" the source data. + # TODO: handle all aux-coords, cell measures ?? + + # The shape is that of the basic result, minus the trajectory (last) + # dimension, plus the target grid dimensions. + target_shape = result_trajectory_cube.shape[:-1] + self.tgt_grid_shape + data_2d_x_and_y = result_trajectory_cube.data.reshape(target_shape) + + # Make a new result cube with the reshaped data. + result_cube = iris.cube.Cube(data_2d_x_and_y) + result_cube.metadata = src_cube.metadata + + # Copy all the coords from the trajectory result. + i_trajectory_dim = result_trajectory_cube.ndim - 1 + for coord in result_trajectory_cube.dim_coords: + dims = result_trajectory_cube.coord_dims(coord) + if i_trajectory_dim not in dims: + result_cube.add_dim_coord(coord.copy(), dims) + for coord in result_trajectory_cube.aux_coords: + dims = result_trajectory_cube.coord_dims(coord) + if i_trajectory_dim not in dims: + result_cube.add_aux_coord(coord.copy(), dims) + + # Add the X+Y grid coords from the grid cube, mapped to the new Y and X + # dimensions, i.e. the last 2. + for i_dim, coord in enumerate(self.tgt_grid_coords): + result_cube.add_dim_coord(coord.copy(), i_dim + i_trajectory_dim) + + return result_cube diff --git a/lib/iris/aux_factory.py b/lib/iris/aux_factory.py index 8a17ef1641..d58c488afc 100644 --- a/lib/iris/aux_factory.py +++ b/lib/iris/aux_factory.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -19,81 +19,21 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + from abc import ABCMeta, abstractmethod, abstractproperty import warnings -import zlib +import dask.array as da import numpy as np from iris._cube_coord_common import CFVariableMixin import iris.coords -import iris.util - - -class LazyArray(object): - """ - Represents a simplified NumPy array which is only computed on demand. - It provides the :meth:`view()` and :meth:`reshape()` methods so it - can be used in place of a standard NumPy array under some - circumstances. - - The first use of either of these methods causes the array to be - computed and cached for any subsequent access. - """ - - def __init__(self, shape, func): - """ - Args: - - * shape (tuple): - The shape of the array which will be created. - * func: - The function which will be called to supply the real array. - - """ - self.shape = tuple(shape) - self._func = func - self._array = None - - def __repr__(self): - return ''.format(self.shape) - - def _cached_array(self): - if self._array is None: - self._array = self._func() - del self._func - return self._array - - def reshape(self, *args, **kwargs): - """ - Returns a view of this array with the given shape. - - See :meth:`numpy.ndarray.reshape()` for argument details. - - """ - return self._cached_array().reshape(*args, **kwargs) - - def to_xml_attr(self): - """ - Returns a string describing this array, suitable for use in CML. - - """ - crc = zlib.crc32(np.array(self._cached_array(), order='C')) - return 'LazyArray(shape={}, checksum={})'.format(self.shape, crc) - - def view(self, *args, **kwargs): - """ - Returns a view of this array. - - See :meth:`numpy.ndarray.view()` for argument details. - - """ - return self._cached_array().view(*args, **kwargs) - - -class AuxCoordFactory(CFVariableMixin): +class AuxCoordFactory(six.with_metaclass(ABCMeta, CFVariableMixin)): """ Represents a "factory" which can manufacture an additional auxiliary coordinate on demand, by combining the values of other coordinates. @@ -106,13 +46,12 @@ class AuxCoordFactory(CFVariableMixin): properties of the resulting auxiliary coordinates. """ - __metaclass__ = ABCMeta def __init__(self): #: Descriptive name of the coordinate made by the factory self.long_name = None - #: CF variable name of the coordinate made by the factory + #: netCDF variable name for the coordinate made by the factory self.var_name = None #: Coordinate system (if any) of the coordinate made by the factory @@ -157,7 +96,7 @@ def update(self, old_coord, new_coord=None): * old_coord: The dependency coordinate to be removed/replaced. * new_coord: - If None, the dependency using old_coord is removed, othewise + If None, the dependency using old_coord is removed, otherwise the dependency is updated to use new_coord. """ @@ -166,14 +105,13 @@ def __repr__(self): def arg_text(item): key, coord = item return '{}={}'.format(key, str(coord and repr(coord.name()))) - items = self.dependencies.items() - items.sort(key=lambda item: item[0]) + items = sorted(self.dependencies.items(), key=lambda item: item[0]) args = map(arg_text, items) return '<{}({})>'.format(type(self).__name__, ', '.join(args)) def derived_dims(self, coord_dims_func): """ - Returns the virtual dim-mapping for the derived coordinate. + Returns the cube dimensions for the derived coordinate. Args: @@ -182,11 +120,15 @@ def derived_dims(self, coord_dims_func): to a given coordinate. See :meth:`iris.cube.Cube.coord_dims()`. + Returns: + + A sorted list of cube dimension numbers. + """ # Which dimensions are relevant? # e.g. If sigma -> [1] and orog -> [2, 3] then result = [1, 2, 3] derived_dims = set() - for coord in self.dependencies.itervalues(): + for coord in six.itervalues(self.dependencies): if coord: derived_dims.update(coord_dims_func(coord)) @@ -209,7 +151,7 @@ def updated(self, new_coord_mapping): """ new_dependencies = {} - for key, coord in self.dependencies.iteritems(): + for key, coord in six.iteritems(self.dependencies): if coord: coord = new_coord_mapping[id(coord)] new_dependencies[key] = coord @@ -221,22 +163,30 @@ def xml_element(self, doc): """ element = doc.createElement('coordFactory') - for key, coord in self.dependencies.iteritems(): + for key, coord in six.iteritems(self.dependencies): element.setAttribute(key, coord._xml_id()) element.appendChild(self.make_coord().xml_element(doc)) return element def _dependency_dims(self, coord_dims_func): dependency_dims = {} - for key, coord in self.dependencies.iteritems(): + for key, coord in six.iteritems(self.dependencies): if coord: dependency_dims[key] = coord_dims_func(coord) return dependency_dims - def _nd_bounds(self, coord, dims, ndim): + @staticmethod + def _nd_bounds(coord, dims, ndim): """ - Returns the coord's bounds in Cube-orientation and - broadcastable to N dimensions. + Return a lazy bounds array for a dependency coordinate, 'coord'. + + The result is aligned to the first 'ndim' cube dimensions, and + expanded to the full ('ndim'+1)-dimensional shape. + + The value of 'ndim' must be >= the highest cube dimension of the + dependency coordinate. + + The extra final result dimension ('ndim'-th) is the bounds dimension. Example: coord.shape == (70,) @@ -250,21 +200,27 @@ def _nd_bounds(self, coord, dims, ndim): # Transpose to be consistent with the Cube. sorted_pairs = sorted(enumerate(dims), key=lambda pair: pair[1]) transpose_order = [pair[0] for pair in sorted_pairs] + [len(dims)] - bounds = coord.bounds - if dims: + bounds = coord.lazy_bounds() + if dims and transpose_order != list(range(len(dims))): bounds = bounds.transpose(transpose_order) # Figure out the n-dimensional shape. nd_shape = [1] * ndim + [coord.nbounds] for dim, size in zip(dims, coord.shape): nd_shape[dim] = size - bounds.shape = tuple(nd_shape) + bounds = bounds.reshape(nd_shape) return bounds - def _nd_points(self, coord, dims, ndim): + @staticmethod + def _nd_points(coord, dims, ndim): """ - Returns the coord's points in Cube-orientation and - broadcastable to N dimensions. + Return a lazy points array for a dependency coordinate, 'coord'. + + The result is aligned to the first 'ndim' cube dimensions, and + expanded to the full 'ndim'-dimensional shape. + + The value of 'ndim' must be >= the highest cube dimension of the + dependency coordinate. Example: coord.shape == (4, 3) @@ -277,25 +233,42 @@ def _nd_points(self, coord, dims, ndim): # Transpose to be consistent with the Cube. sorted_pairs = sorted(enumerate(dims), key=lambda pair: pair[1]) transpose_order = [pair[0] for pair in sorted_pairs] - points = coord.points - if dims: + points = coord.lazy_points() + if dims and transpose_order != list(range(len(dims))): points = points.transpose(transpose_order) - # Figure out the n-dimensional shape. - nd_shape = [1] * ndim - for dim, size in zip(dims, coord.shape): - nd_shape[dim] = size - points.shape = tuple(nd_shape) + # Expand dimensionality to be consistent with the Cube. + if dims: + keys = [None] * ndim + for dim, size in zip(dims, coord.shape): + keys[dim] = slice(None) + points = points[tuple(keys)] + else: + # Scalar coordinates have one dimensional points despite + # mapping to zero dimensions, so we only need to add N-1 + # new dimensions. + keys = (None,) * (ndim - 1) + points = points[keys] return points def _remap(self, dependency_dims, derived_dims): + """ + Return a mapping from dependency names to coordinate points arrays. + + For dependencies that are present, the values are all expanded and + aligned to the same dimensions, which is the full set of all the + dependency dimensions. + These non-missing values are all lazy arrays. + Missing dependencies, however, are assigned a scalar value of 0.0. + + """ if derived_dims: ndim = max(derived_dims) + 1 else: ndim = 1 nd_points_by_key = {} - for key, coord in self.dependencies.iteritems(): + for key, coord in six.iteritems(self.dependencies): if coord: # Get the points as consistent with the Cube. nd_points = self._nd_points(coord, dependency_dims[key], ndim) @@ -303,14 +276,10 @@ def _remap(self, dependency_dims, derived_dims): # Restrict to just the dimensions relevant to the # derived coord. NB. These are always in Cube-order, so # no transpose is needed. - shape = [] - for dim in derived_dims: - shape.append(nd_points.shape[dim]) - # Ensure the array always has at least one dimension to be - # compatible with normal coordinates. - if not derived_dims: - shape.append(1) - nd_points.shape = shape + if derived_dims: + keys = tuple(slice(None) if dim in derived_dims else 0 for + dim in range(ndim)) + nd_points = nd_points[keys] else: # If no coord, treat value as zero. # Use a float16 to provide `shape` attribute and avoid @@ -321,13 +290,27 @@ def _remap(self, dependency_dims, derived_dims): return nd_points_by_key def _remap_with_bounds(self, dependency_dims, derived_dims): + """ + Return a mapping from dependency names to coordinate bounds arrays. + + For dependencies that are present, the values are all expanded and + aligned to the same dimensions, which is the full set of all the + dependency dimensions, plus an extra bounds dimension. + These non-missing values are all lazy arrays. + Missing dependencies, however, are assigned a scalar value of 0.0. + + Where a dependency coordinate has no bounds, then the associated value + is taken from its points array, but reshaped to have an extra bounds + dimension of length 1. + + """ if derived_dims: ndim = max(derived_dims) + 1 else: ndim = 1 nd_values_by_key = {} - for key, coord in self.dependencies.iteritems(): + for key, coord in six.iteritems(self.dependencies): if coord: # Get the bounds or points as consistent with the Cube. if coord.nbounds: @@ -355,7 +338,7 @@ def _remap_with_bounds(self, dependency_dims, derived_dims): # extra dimension to make the shape compatible, so # we just add an extra 1. shape.append(1) - nd_values.shape = shape + nd_values = nd_values.reshape(shape) else: # If no coord, treat value as zero. # Use a float16 to provide `shape` attribute and avoid @@ -365,23 +348,6 @@ def _remap_with_bounds(self, dependency_dims, derived_dims): nd_values_by_key[key] = nd_values return nd_values_by_key - def _shape(self, nd_values_by_key): - nd_values = sorted(nd_values_by_key.values(), - key=lambda value: value.ndim) - shape = list(nd_values.pop().shape) - for array in nd_values: - for i, size in enumerate(array.shape): - if size > 1: - # NB. If there's an inconsistency it can only come - # from a mismatch in the number of bounds (the Cube - # ensures the other dimensions must match). - # But we can't afford to raise an error now - it'd - # break Cube.derived_coords. Instead, we let the - # error happen when the derived coordinate's bounds - # are accessed. - shape[i] = size - return shape - class HybridHeightFactory(AuxCoordFactory): """ @@ -389,7 +355,6 @@ class HybridHeightFactory(AuxCoordFactory): z = a + b * orog """ - def __init__(self, delta=None, sigma=None, orography=None): """ Creates a hybrid-height coordinate factory with the formula: @@ -448,8 +413,7 @@ def dependencies(self): 'orography': self.orography} def _derive(self, delta, sigma, orography): - temp = delta + sigma * orography - return temp + return delta + sigma * orography def make_coord(self, coord_dims_func): """ @@ -466,48 +430,37 @@ def make_coord(self, coord_dims_func): """ # Which dimensions are relevant? derived_dims = self.derived_dims(coord_dims_func) - dependency_dims = self._dependency_dims(coord_dims_func) - # Build a "lazy" points array. + # Build the points array. nd_points_by_key = self._remap(dependency_dims, derived_dims) - - # Define the function here to obtain a closure. - def calc_points(): - return self._derive(nd_points_by_key['delta'], - nd_points_by_key['sigma'], - nd_points_by_key['orography']) - shape = self._shape(nd_points_by_key) - points = LazyArray(shape, calc_points) + points = self._derive(nd_points_by_key['delta'], + nd_points_by_key['sigma'], + nd_points_by_key['orography']) bounds = None if ((self.delta and self.delta.nbounds) or (self.sigma and self.sigma.nbounds)): - # Build a "lazy" bounds array. + # Build the bounds array. nd_values_by_key = self._remap_with_bounds(dependency_dims, derived_dims) - - # Define the function here to obtain a closure. - def calc_bounds(): - delta = nd_values_by_key['delta'] - sigma = nd_values_by_key['sigma'] - orography = nd_values_by_key['orography'] - ok_bound_shapes = [(), (1,), (2,)] - if delta.shape[-1:] not in ok_bound_shapes: - raise ValueError('Invalid delta coordinate bounds.') - if sigma.shape[-1:] not in ok_bound_shapes: - raise ValueError('Invalid sigma coordinate bounds.') - if orography.shape[-1:] not in [(), (1,)]: - warnings.warn('Orography coordinate has bounds. ' - 'These are being disregarded.', - UserWarning, stacklevel=2) - orography_pts = nd_points_by_key['orography'] - orography_pts_shape = list(orography_pts.shape) - orography = orography_pts.reshape( - orography_pts_shape.append(1)) - return self._derive(delta, sigma, orography) - b_shape = self._shape(nd_values_by_key) - bounds = LazyArray(b_shape, calc_bounds) + delta = nd_values_by_key['delta'] + sigma = nd_values_by_key['sigma'] + orography = nd_values_by_key['orography'] + ok_bound_shapes = [(), (1,), (2,)] + if delta.shape[-1:] not in ok_bound_shapes: + raise ValueError('Invalid delta coordinate bounds.') + if sigma.shape[-1:] not in ok_bound_shapes: + raise ValueError('Invalid sigma coordinate bounds.') + if orography.shape[-1:] not in [(), (1,)]: + warnings.warn('Orography coordinate has bounds. ' + 'These are being disregarded.', + UserWarning, stacklevel=2) + orography_pts = nd_points_by_key['orography'] + bds_shape = list(orography_pts.shape) + [1] + orography = orography_pts.reshape(bds_shape) + + bounds = self._derive(delta, sigma, orography) hybrid_height = iris.coords.AuxCoord(points, standard_name=self.standard_name, @@ -529,7 +482,7 @@ def update(self, old_coord, new_coord=None): * old_coord: The coordinate to be removed/replaced. * new_coord: - If None, any dependency using old_coord is removed, othewise + If None, any dependency using old_coord is removed, otherwise any dependency using old_coord is updated to use new_coord. """ @@ -557,7 +510,6 @@ class HybridPressureFactory(AuxCoordFactory): p = ap + b * ps """ - def __init__(self, delta=None, sigma=None, surface_air_pressure=None): """ Creates a hybrid-height coordinate factory with the formula: @@ -647,8 +599,7 @@ def dependencies(self): 'surface_air_pressure': self.surface_air_pressure} def _derive(self, delta, sigma, surface_air_pressure): - temp = delta + sigma * surface_air_pressure - return temp + return delta + sigma * surface_air_pressure def make_coord(self, coord_dims_func): """ @@ -665,49 +616,38 @@ def make_coord(self, coord_dims_func): """ # Which dimensions are relevant? derived_dims = self.derived_dims(coord_dims_func) - dependency_dims = self._dependency_dims(coord_dims_func) - # Build a "lazy" points array. + # Build the points array. nd_points_by_key = self._remap(dependency_dims, derived_dims) - - # Define the function here to obtain a closure. - def calc_points(): - return self._derive(nd_points_by_key['delta'], - nd_points_by_key['sigma'], - nd_points_by_key['surface_air_pressure']) - shape = self._shape(nd_points_by_key) - points = LazyArray(shape, calc_points) + points = self._derive(nd_points_by_key['delta'], + nd_points_by_key['sigma'], + nd_points_by_key['surface_air_pressure']) bounds = None if ((self.delta and self.delta.nbounds) or (self.sigma and self.sigma.nbounds)): - # Build a "lazy" bounds array. + # Build the bounds array. nd_values_by_key = self._remap_with_bounds(dependency_dims, derived_dims) - - # Define the function here to obtain a closure. - def calc_bounds(): - delta = nd_values_by_key['delta'] - sigma = nd_values_by_key['sigma'] - surface_air_pressure = nd_values_by_key['surface_air_pressure'] - ok_bound_shapes = [(), (1,), (2,)] - if delta.shape[-1:] not in ok_bound_shapes: - raise ValueError('Invalid delta coordinate bounds.') - if sigma.shape[-1:] not in ok_bound_shapes: - raise ValueError('Invalid sigma coordinate bounds.') - if surface_air_pressure.shape[-1:] not in [(), (1,)]: - warnings.warn('Surface pressure coordinate has bounds. ' - 'These are being disregarded.') - surface_air_pressure_pts = nd_points_by_key[ - 'surface_air_pressure'] - surface_air_pressure_pts_shape = list( - surface_air_pressure_pts.shape) - surface_air_pressure = surface_air_pressure_pts.reshape( - surface_air_pressure_pts_shape.append(1)) - return self._derive(delta, sigma, surface_air_pressure) - b_shape = self._shape(nd_values_by_key) - bounds = LazyArray(b_shape, calc_bounds) + delta = nd_values_by_key['delta'] + sigma = nd_values_by_key['sigma'] + surface_air_pressure = nd_values_by_key['surface_air_pressure'] + ok_bound_shapes = [(), (1,), (2,)] + if delta.shape[-1:] not in ok_bound_shapes: + raise ValueError('Invalid delta coordinate bounds.') + if sigma.shape[-1:] not in ok_bound_shapes: + raise ValueError('Invalid sigma coordinate bounds.') + if surface_air_pressure.shape[-1:] not in [(), (1,)]: + warnings.warn('Surface pressure coordinate has bounds. ' + 'These are being disregarded.') + surface_air_pressure_pts = nd_points_by_key[ + 'surface_air_pressure'] + bds_shape = list(surface_air_pressure_pts.shape) + [1] + surface_air_pressure = surface_air_pressure_pts.reshape( + bds_shape) + + bounds = self._derive(delta, sigma, surface_air_pressure) hybrid_pressure = iris.coords.AuxCoord( points, standard_name=self.standard_name, long_name=self.long_name, @@ -725,7 +665,995 @@ def update(self, old_coord, new_coord=None): * old_coord: The coordinate to be removed/replaced. * new_coord: - If None, any dependency using old_coord is removed, othewise + If None, any dependency using old_coord is removed, otherwise + any dependency using old_coord is updated to use new_coord. + + """ + new_dependencies = self.dependencies + for name, coord in self.dependencies.items(): + if old_coord is coord: + new_dependencies[name] = new_coord + try: + self._check_dependencies(**new_dependencies) + except ValueError as e: + msg = 'Failed to update dependencies. ' + str(e) + raise ValueError(msg) + else: + setattr(self, name, new_coord) + break + + +class OceanSigmaZFactory(AuxCoordFactory): + """Defines an ocean sigma over z coordinate factory.""" + + def __init__(self, sigma=None, eta=None, depth=None, + depth_c=None, nsigma=None, zlev=None): + """ + Creates a ocean sigma over z coordinate factory with the formula: + + if k < nsigma: + z(n, k, j, i) = eta(n, j, i) + sigma(k) * + (min(depth_c, depth(j, i)) + eta(n, j, i)) + + if k >= nsigma: + z(n, k, j, i) = zlev(k) + + The `zlev` and 'nsigma' coordinates must be provided, and at least + either `eta`, or 'sigma' and `depth` and `depth_c` coordinates. + + """ + super(OceanSigmaZFactory, self).__init__() + + # Check that provided coordinates meet necessary conditions. + self._check_dependencies(sigma, eta, depth, depth_c, nsigma, zlev) + + self.sigma = sigma + self.eta = eta + self.depth = depth + self.depth_c = depth_c + self.nsigma = nsigma + self.zlev = zlev + + self.standard_name = 'sea_surface_height_above_reference_ellipsoid' + self.attributes = {'positive': 'up'} + + @property + def units(self): + return self.zlev.units + + @staticmethod + def _check_dependencies(sigma, eta, depth, depth_c, nsigma, zlev): + # Check for sufficient factory coordinates. + if zlev is None: + raise ValueError('Unable to determine units: ' + 'no zlev coordinate available.') + if nsigma is None: + raise ValueError('Missing nsigma coordinate.') + + if eta is None and (sigma is None or depth_c is None or + depth is None): + msg = 'Unable to construct ocean sigma over z coordinate ' \ + 'factory due to insufficient source coordinates.' + raise ValueError(msg) + + # Check bounds and shape. + for coord, term in ((sigma, 'sigma'), (zlev, 'zlev')): + if coord is not None and coord.nbounds not in (0, 2): + msg = 'Invalid {} coordinate {!r}: must have either ' \ + '0 or 2 bounds.'.format(term, coord.name()) + raise ValueError(msg) + + if sigma and sigma.nbounds != zlev.nbounds: + msg = 'The sigma coordinate {!r} and zlev coordinate {!r} ' \ + 'must be equally bounded.'.format(sigma.name(), zlev.name()) + raise ValueError(msg) + + coords = ((eta, 'eta'), (depth, 'depth'), + (depth_c, 'depth_c'), (nsigma, 'nsigma')) + for coord, term in coords: + if coord is not None and coord.nbounds: + msg = 'The {} coordinate {!r} has bounds. ' \ + 'These are being disregarded.'.format(term, coord.name()) + warnings.warn(msg, UserWarning, stacklevel=2) + + for coord, term in ((depth_c, 'depth_c'), (nsigma, 'nsigma')): + if coord is not None and coord.shape != (1,): + msg = 'Expected scalar {} coordinate {!r}: ' \ + 'got shape {!r}.'.format(term, coord.name(), coord.shape) + raise ValueError(msg) + + # Check units. + if not zlev.units.is_convertible('m'): + msg = 'Invalid units: zlev coordinate {!r} ' \ + 'must have units of distance.'.format(zlev.name()) + raise ValueError(msg) + + if sigma is not None and not sigma.units.is_dimensionless(): + msg = 'Invalid units: sigma coordinate {!r} ' \ + 'must be dimensionless.'.format(sigma.name()) + raise ValueError(msg) + + coords = ((eta, 'eta'), (depth_c, 'depth_c'), (depth, 'depth')) + for coord, term in coords: + if coord is not None and coord.units != zlev.units: + msg = 'Incompatible units: {} coordinate {!r} and zlev ' \ + 'coordinate {!r} must have ' \ + 'the same units.'.format(term, coord.name(), zlev.name()) + raise ValueError(msg) + + @property + def dependencies(self): + """ + Returns a dictionary mapping from constructor argument names to + the corresponding coordinates. + + """ + return dict(sigma=self.sigma, eta=self.eta, depth=self.depth, + depth_c=self.depth_c, nsigma=self.nsigma, zlev=self.zlev) + + def _derive(self, sigma, eta, depth, depth_c, + zlev, nsigma, coord_dims_func): + # Calculate the index of the 'z' dimension in the input arrays. + # First find the cube 'z' dimension ... + [cube_z_dim] = coord_dims_func(self.dependencies['zlev']) + # ... then calculate the corresponding dependency dimension. + derived_cubedims = self.derived_dims(coord_dims_func) + z_dim = derived_cubedims.index(cube_z_dim) + + # Calculate the result shape as a combination of all the inputs. + # Note: all the inputs have the same number of dimensions >= 1, except + # for any missing dependencies, which have scalar values. + allshapes = np.array( + [el.shape + for el in (sigma, eta, depth, depth_c, zlev) + if el.ndim > 0]) + result_shape = list(np.max(allshapes, axis=0)) + ndims = len(result_shape) + + # Make a slice tuple to index the first nsigma z-levels. + z_slices_nsigma = [slice(None)] * ndims + z_slices_nsigma[z_dim] = slice(0, int(nsigma)) + z_slices_nsigma = tuple(z_slices_nsigma) + # Make a slice tuple to index the remaining z-levels. + z_slices_rest = [slice(None)] * ndims + z_slices_rest[z_dim] = slice(int(nsigma), None) + z_slices_rest = tuple(z_slices_rest) + + # Perform the ocean sigma over z coordinate nsigma slice. + if eta.ndim: + eta = eta[z_slices_nsigma] + if sigma.ndim: + sigma = sigma[z_slices_nsigma] + if depth.ndim: + depth = depth[z_slices_nsigma] + # Note that, this performs a point-wise minimum. + nsigma_levs = eta + sigma * (da.minimum(depth_c, depth) + eta) + + # Make a result-shaped lazy "ones" array for expanding partial results. + # Note: for the 'chunks' arg, we try to use [1, 1, ... ny, nx]. + # This calculation could be assuming too much in some cases, as we + # don't actually check the dimensions of our dependencies anywhere. + result_chunks = result_shape + if len(result_shape) > 1: + result_chunks = [1] * len(result_shape) + result_chunks[-2:] = result_shape[-2:] + ones_full_result = da.ones(result_shape, chunks=result_chunks, + dtype=zlev.dtype) + + # Expand nsigma_levs to its full required shape : needed as the + # calculated result may have a fixed size of 1 in some dimensions. + result_nsigma_levs = nsigma_levs * ones_full_result[z_slices_nsigma] + + # Likewise, expand zlev to its full required shape. + result_rest_levs = (zlev[z_slices_rest] * + ones_full_result[z_slices_rest]) + + # Combine nsigma and 'rest' levels for the final result. + result = da.concatenate([result_nsigma_levs, result_rest_levs], + axis=z_dim) + return result + + def make_coord(self, coord_dims_func): + """ + Returns a new :class:`iris.coords.AuxCoord` as defined by this factory. + + Args: + + * coord_dims_func: + A callable which can return the list of dimesions relevant + to a given coordinate. See :meth:`iris.cube.Cube.coord_dims()`. + + """ + # Determine the relevant dimensions. + derived_dims = self.derived_dims(coord_dims_func) + dependency_dims = self._dependency_dims(coord_dims_func) + + # Build the points array. + nd_points_by_key = self._remap(dependency_dims, derived_dims) + + [nsigma] = nd_points_by_key['nsigma'] + points = self._derive(nd_points_by_key['sigma'], + nd_points_by_key['eta'], + nd_points_by_key['depth'], + nd_points_by_key['depth_c'], + nd_points_by_key['zlev'], + nsigma, + coord_dims_func) + + bounds = None + if self.zlev.nbounds or (self.sigma and self.sigma.nbounds): + # Build the bounds array. + nd_values_by_key = self._remap_with_bounds(dependency_dims, + derived_dims) + valid_shapes = [(), (1,), (2,)] + for key in ('sigma', 'zlev'): + if nd_values_by_key[key].shape[-1:] not in valid_shapes: + name = self.dependencies[key].name() + msg = 'Invalid bounds for {} ' \ + 'coordinate {!r}.'.format(key, name) + raise ValueError(msg) + valid_shapes.pop() + for key in ('eta', 'depth', 'depth_c', 'nsigma'): + if nd_values_by_key[key].shape[-1:] not in valid_shapes: + name = self.dependencies[key].name() + msg = 'The {} coordinate {!r} has bounds. ' \ + 'These are being disregarded.'.format(key, name) + warnings.warn(msg, UserWarning, stacklevel=2) + # Swap bounds with points. + bds_shape = list(nd_points_by_key[key].shape) + [1] + bounds = nd_points_by_key[key].reshape(bds_shape) + nd_values_by_key[key] = bounds + + bounds = self._derive(nd_values_by_key['sigma'], + nd_values_by_key['eta'], + nd_values_by_key['depth'], + nd_values_by_key['depth_c'], + nd_values_by_key['zlev'], + nsigma, + coord_dims_func) + + coord = iris.coords.AuxCoord(points, + standard_name=self.standard_name, + long_name=self.long_name, + var_name=self.var_name, + units=self.units, + bounds=bounds, + attributes=self.attributes, + coord_system=self.coord_system) + return coord + + def update(self, old_coord, new_coord=None): + """ + Notifies the factory of the removal/replacement of a coordinate + which might be a dependency. + + Args: + + * old_coord: + The coordinate to be removed/replaced. + * new_coord: + If None, any dependency using old_coord is removed, otherwise + any dependency using old_coord is updated to use new_coord. + + """ + new_dependencies = self.dependencies + for name, coord in self.dependencies.items(): + if old_coord is coord: + new_dependencies[name] = new_coord + try: + self._check_dependencies(**new_dependencies) + except ValueError as e: + msg = 'Failed to update dependencies. ' + str(e) + raise ValueError(msg) + else: + setattr(self, name, new_coord) + break + + +class OceanSigmaFactory(AuxCoordFactory): + """Defines an ocean sigma coordinate factory.""" + + def __init__(self, sigma=None, eta=None, depth=None): + """ + Creates an ocean sigma coordinate factory with the formula: + + z(n, k, j, i) = eta(n, j, i) + sigma(k) * + (depth(j, i) + eta(n, j, i)) + + """ + super(OceanSigmaFactory, self).__init__() + + # Check that provided coordinates meet necessary conditions. + self._check_dependencies(sigma, eta, depth) + + self.sigma = sigma + self.eta = eta + self.depth = depth + + self.standard_name = 'sea_surface_height_above_reference_ellipsoid' + self.attributes = {'positive': 'up'} + + @property + def units(self): + return self.depth.units + + @staticmethod + def _check_dependencies(sigma, eta, depth): + # Check for sufficient factory coordinates. + if eta is None or sigma is None or depth is None: + msg = 'Unable to construct ocean sigma coordinate ' \ + 'factory due to insufficient source coordinates.' + raise ValueError(msg) + + # Check bounds and shape. + coord, term = (sigma, 'sigma') + if coord is not None and coord.nbounds not in (0, 2): + msg = 'Invalid {} coordinate {!r}: must have either ' \ + '0 or 2 bounds.'.format(term, coord.name()) + raise ValueError(msg) + + coords = ((eta, 'eta'), (depth, 'depth')) + for coord, term in coords: + if coord is not None and coord.nbounds: + msg = 'The {} coordinate {!r} has bounds. ' \ + 'These are being disregarded.'.format(term, coord.name()) + warnings.warn(msg, UserWarning, stacklevel=2) + + # Check units. + if sigma is not None and not sigma.units.is_dimensionless(): + msg = 'Invalid units: sigma coordinate {!r} ' \ + 'must be dimensionless.'.format(sigma.name()) + raise ValueError(msg) + + coords = ((eta, 'eta'), (depth, 'depth')) + for coord, term in coords: + if coord is not None and coord.units != depth.units: + msg = 'Incompatible units: {} coordinate {!r} and depth ' \ + 'coordinate {!r} must have ' \ + 'the same units.'.format(term, coord.name(), depth.name()) + raise ValueError(msg) + + @property + def dependencies(self): + """ + Returns a dictionary mapping from constructor argument names to + the corresponding coordinates. + + """ + return dict(sigma=self.sigma, eta=self.eta, depth=self.depth) + + def _derive(self, sigma, eta, depth): + return eta + sigma * (depth + eta) + + def make_coord(self, coord_dims_func): + """ + Returns a new :class:`iris.coords.AuxCoord` as defined by this factory. + + Args: + + * coord_dims_func: + A callable which can return the list of dimensions relevant + to a given coordinate. See :meth:`iris.cube.Cube.coord_dims()`. + + """ + # Determine the relevant dimensions. + derived_dims = self.derived_dims(coord_dims_func) + dependency_dims = self._dependency_dims(coord_dims_func) + + # Build the points array. + nd_points_by_key = self._remap(dependency_dims, derived_dims) + points = self._derive(nd_points_by_key['sigma'], + nd_points_by_key['eta'], + nd_points_by_key['depth']) + + bounds = None + if self.sigma and self.sigma.nbounds: + # Build the bounds array. + nd_values_by_key = self._remap_with_bounds(dependency_dims, + derived_dims) + valid_shapes = [(), (1,), (2,)] + key = 'sigma' + if nd_values_by_key[key].shape[-1:] not in valid_shapes: + name = self.dependencies[key].name() + msg = 'Invalid bounds for {} ' \ + 'coordinate {!r}.'.format(key, name) + raise ValueError(msg) + valid_shapes.pop() + for key in ('eta', 'depth'): + if nd_values_by_key[key].shape[-1:] not in valid_shapes: + name = self.dependencies[key].name() + msg = 'The {} coordinate {!r} has bounds. ' \ + 'These are being disregarded.'.format(key, name) + warnings.warn(msg, UserWarning, stacklevel=2) + # Swap bounds with points. + bds_shape = list(nd_points_by_key[key].shape) + [1] + bounds = nd_points_by_key[key].reshape(bds_shape) + nd_values_by_key[key] = bounds + + bounds = self._derive(nd_values_by_key['sigma'], + nd_values_by_key['eta'], + nd_values_by_key['depth']) + + coord = iris.coords.AuxCoord(points, + standard_name=self.standard_name, + long_name=self.long_name, + var_name=self.var_name, + units=self.units, + bounds=bounds, + attributes=self.attributes, + coord_system=self.coord_system) + return coord + + def update(self, old_coord, new_coord=None): + """ + Notifies the factory of the removal/replacement of a coordinate + which might be a dependency. + + Args: + + * old_coord: + The coordinate to be removed/replaced. + * new_coord: + If None, any dependency using old_coord is removed, otherwise + any dependency using old_coord is updated to use new_coord. + + """ + new_dependencies = self.dependencies + for name, coord in self.dependencies.items(): + if old_coord is coord: + new_dependencies[name] = new_coord + try: + self._check_dependencies(**new_dependencies) + except ValueError as e: + msg = 'Failed to update dependencies. ' + str(e) + raise ValueError(msg) + else: + setattr(self, name, new_coord) + break + + +class OceanSg1Factory(AuxCoordFactory): + """Defines an Ocean s-coordinate, generic form 1 factory.""" + + def __init__(self, s=None, c=None, eta=None, depth=None, depth_c=None): + """ + Creates an Ocean s-coordinate, generic form 1 factory with the formula: + + z(n,k,j,i) = S(k,j,i) + eta(n,j,i) * (1 + S(k,j,i) / depth(j,i)) + + where: + S(k,j,i) = depth_c * s(k) + (depth(j,i) - depth_c) * C(k) + + """ + super(OceanSg1Factory, self).__init__() + + # Check that provided coordinates meet necessary conditions. + self._check_dependencies(s, c, eta, depth, depth_c) + + self.s = s + self.c = c + self.eta = eta + self.depth = depth + self.depth_c = depth_c + + self.standard_name = 'sea_surface_height_above_reference_ellipsoid' + self.attributes = {'positive': 'up'} + + @property + def units(self): + return self.depth.units + + @staticmethod + def _check_dependencies(s, c, eta, depth, depth_c): + # Check for sufficient factory coordinates. + if (eta is None or s is None or c is None or + depth is None or depth_c is None): + msg = 'Unable to construct Ocean s-coordinate, generic form 1 ' \ + 'factory due to insufficient source coordinates.' + raise ValueError(msg) + + # Check bounds and shape. + coords = ((s, 's'), (c, 'c')) + for coord, term in coords: + if coord is not None and coord.nbounds not in (0, 2): + msg = 'Invalid {} coordinate {!r}: must have either ' \ + '0 or 2 bounds.'.format(term, coord.name()) + raise ValueError(msg) + + if s and s.nbounds != c.nbounds: + msg = 'The s coordinate {!r} and c coordinate {!r} ' \ + 'must be equally bounded.'.format(s.name(), c.name()) + raise ValueError(msg) + + coords = ((eta, 'eta'), (depth, 'depth')) + for coord, term in coords: + if coord is not None and coord.nbounds: + msg = 'The {} coordinate {!r} has bounds. ' \ + 'These are being disregarded.'.format(term, coord.name()) + warnings.warn(msg, UserWarning, stacklevel=2) + + if depth_c is not None and depth_c.shape != (1,): + msg = 'Expected scalar {} coordinate {!r}: ' \ + 'got shape {!r}.'.format(term, coord.name(), coord.shape) + raise ValueError(msg) + + # Check units. + coords = ((s, 's'), (c, 'c')) + for coord, term in coords: + if coord is not None and not coord.units.is_dimensionless(): + msg = 'Invalid units: {} coordinate {!r} ' \ + 'must be dimensionless.'.format(term, coord.name()) + raise ValueError(msg) + + coords = ((eta, 'eta'), (depth, 'depth'), (depth_c, 'depth_c')) + for coord, term in coords: + if coord is not None and coord.units != depth.units: + msg = 'Incompatible units: {} coordinate {!r} and depth ' \ + 'coordinate {!r} must have ' \ + 'the same units.'.format(term, coord.name(), depth.name()) + raise ValueError(msg) + + @property + def dependencies(self): + """ + Returns a dictionary mapping from constructor argument names to + the corresponding coordinates. + + """ + return dict(s=self.s, c=self.c, eta=self.eta, depth=self.depth, + depth_c=self.depth_c) + + def _derive(self, s, c, eta, depth, depth_c): + S = depth_c * s + (depth - depth_c) * c + return S + eta * (1 + S / depth) + + def make_coord(self, coord_dims_func): + """ + Returns a new :class:`iris.coords.AuxCoord` as defined by this factory. + + Args: + + * coord_dims_func: + A callable which can return the list of dimensions relevant + to a given coordinate. See :meth:`iris.cube.Cube.coord_dims()`. + + """ + # Determine the relevant dimensions. + derived_dims = self.derived_dims(coord_dims_func) + dependency_dims = self._dependency_dims(coord_dims_func) + + # Build the points array. + nd_points_by_key = self._remap(dependency_dims, derived_dims) + points = self._derive(nd_points_by_key['s'], + nd_points_by_key['c'], + nd_points_by_key['eta'], + nd_points_by_key['depth'], + nd_points_by_key['depth_c']) + + bounds = None + if self.s.nbounds or (self.c and self.c.nbounds): + # Build the bounds array. + nd_values_by_key = self._remap_with_bounds(dependency_dims, + derived_dims) + valid_shapes = [(), (1,), (2,)] + key = 's' + if nd_values_by_key[key].shape[-1:] not in valid_shapes: + name = self.dependencies[key].name() + msg = 'Invalid bounds for {} ' \ + 'coordinate {!r}.'.format(key, name) + raise ValueError(msg) + valid_shapes.pop() + for key in ('eta', 'depth', 'depth_c'): + if nd_values_by_key[key].shape[-1:] not in valid_shapes: + name = self.dependencies[key].name() + msg = 'The {} coordinate {!r} has bounds. ' \ + 'These are being disregarded.'.format(key, name) + warnings.warn(msg, UserWarning, stacklevel=2) + # Swap bounds with points. + bds_shape = list(nd_points_by_key[key].shape) + [1] + bounds = nd_points_by_key[key].reshape(bds_shape) + nd_values_by_key[key] = bounds + + bounds = self._derive(nd_values_by_key['s'], + nd_values_by_key['c'], + nd_values_by_key['eta'], + nd_values_by_key['depth'], + nd_values_by_key['depth_c']) + + coord = iris.coords.AuxCoord(points, + standard_name=self.standard_name, + long_name=self.long_name, + var_name=self.var_name, + units=self.units, + bounds=bounds, + attributes=self.attributes, + coord_system=self.coord_system) + return coord + + def update(self, old_coord, new_coord=None): + """ + Notifies the factory of the removal/replacement of a coordinate + which might be a dependency. + + Args: + + * old_coord: + The coordinate to be removed/replaced. + * new_coord: + If None, any dependency using old_coord is removed, otherwise + any dependency using old_coord is updated to use new_coord. + + """ + new_dependencies = self.dependencies + for name, coord in self.dependencies.items(): + if old_coord is coord: + new_dependencies[name] = new_coord + try: + self._check_dependencies(**new_dependencies) + except ValueError as e: + msg = 'Failed to update dependencies. ' + str(e) + raise ValueError(msg) + else: + setattr(self, name, new_coord) + break + + +class OceanSFactory(AuxCoordFactory): + """Defines an Ocean s-coordinate factory.""" + + def __init__(self, s=None, eta=None, depth=None, a=None, b=None, + depth_c=None): + """ + Creates an Ocean s-coordinate factory with the formula: + + z(n,k,j,i) = eta(n,j,i)*(1+s(k)) + depth_c*s(k) + + (depth(j,i)-depth_c)*C(k) + + where: + C(k) = (1-b) * sinh(a*s(k)) / sinh(a) + + b * [tanh(a * (s(k) + 0.5)) / (2 * tanh(0.5*a)) - 0.5] + + """ + super(OceanSFactory, self).__init__() + + # Check that provided coordinates meet necessary conditions. + self._check_dependencies(s, eta, depth, a, b, depth_c) + + self.s = s + self.eta = eta + self.depth = depth + self.a = a + self.b = b + self.depth_c = depth_c + + self.standard_name = 'sea_surface_height_above_reference_ellipsoid' + self.attributes = {'positive': 'up'} + + @property + def units(self): + return self.depth.units + + @staticmethod + def _check_dependencies(s, eta, depth, a, b, depth_c): + # Check for sufficient factory coordinates. + if (eta is None or s is None or depth is None or + a is None or b is None or depth_c is None): + msg = 'Unable to construct Ocean s-coordinate ' \ + 'factory due to insufficient source coordinates.' + raise ValueError(msg) + + # Check bounds and shape. + if s is not None and s.nbounds not in (0, 2): + msg = 'Invalid s coordinate {!r}: must have either ' \ + '0 or 2 bounds.'.format(s.name()) + raise ValueError(msg) + + coords = ((eta, 'eta'), (depth, 'depth')) + for coord, term in coords: + if coord is not None and coord.nbounds: + msg = 'The {} coordinate {!r} has bounds. ' \ + 'These are being disregarded.'.format(term, coord.name()) + warnings.warn(msg, UserWarning, stacklevel=2) + + coords = ((a, 'a'), (b, 'b'), (depth_c, 'depth_c')) + for coord, term in coords: + if coord is not None and coord.shape != (1,): + msg = 'Expected scalar {} coordinate {!r}: ' \ + 'got shape {!r}.'.format(term, coord.name(), coord.shape) + raise ValueError(msg) + + # Check units. + if s is not None and not s.units.is_dimensionless(): + msg = 'Invalid units: s coordinate {!r} ' \ + 'must be dimensionless.'.format(s.name()) + raise ValueError(msg) + + coords = ((eta, 'eta'), (depth, 'depth'), (depth_c, 'depth_c')) + for coord, term in coords: + if coord is not None and coord.units != depth.units: + msg = 'Incompatible units: {} coordinate {!r} and depth ' \ + 'coordinate {!r} must have ' \ + 'the same units.'.format(term, coord.name(), depth.name()) + raise ValueError(msg) + + @property + def dependencies(self): + """ + Returns a dictionary mapping from constructor argument names to + the corresponding coordinates. + + """ + return dict(s=self.s, eta=self.eta, depth=self.depth, a=self.a, + b=self.b, depth_c=self.depth_c) + + def _derive(self, s, eta, depth, a, b, depth_c): + c = ((1 - b) * da.sinh(a * s) / da.sinh(a) + b * + (da.tanh(a * (s + 0.5)) / (2 * da.tanh(0.5 * a)) - 0.5)) + return eta * (1 + s) + depth_c * s + (depth - depth_c) * c + + def make_coord(self, coord_dims_func): + """ + Returns a new :class:`iris.coords.AuxCoord` as defined by this factory. + + Args: + + * coord_dims_func: + A callable which can return the list of dimensions relevant + to a given coordinate. See :meth:`iris.cube.Cube.coord_dims()`. + + """ + # Determine the relevant dimensions. + derived_dims = self.derived_dims(coord_dims_func) + dependency_dims = self._dependency_dims(coord_dims_func) + + # Build the points array. + nd_points_by_key = self._remap(dependency_dims, derived_dims) + points = self._derive(nd_points_by_key['s'], + nd_points_by_key['eta'], + nd_points_by_key['depth'], + nd_points_by_key['a'], + nd_points_by_key['b'], + nd_points_by_key['depth_c']) + + bounds = None + if self.s.nbounds: + # Build the bounds array. + nd_values_by_key = self._remap_with_bounds(dependency_dims, + derived_dims) + valid_shapes = [(), (1,), (2,)] + key = 's' + if nd_values_by_key[key].shape[-1:] not in valid_shapes: + name = self.dependencies[key].name() + msg = 'Invalid bounds for {} ' \ + 'coordinate {!r}.'.format(key, name) + raise ValueError(msg) + valid_shapes.pop() + for key in ('eta', 'depth', 'a', 'b', 'depth_c'): + if nd_values_by_key[key].shape[-1:] not in valid_shapes: + name = self.dependencies[key].name() + msg = 'The {} coordinate {!r} has bounds. ' \ + 'These are being disregarded.'.format(key, name) + warnings.warn(msg, UserWarning, stacklevel=2) + # Swap bounds with points. + bds_shape = list(nd_points_by_key[key].shape) + [1] + bounds = nd_points_by_key[key].reshape(bds_shape) + nd_values_by_key[key] = bounds + + bounds = self._derive(nd_values_by_key['s'], + nd_values_by_key['eta'], + nd_values_by_key['depth'], + nd_values_by_key['a'], + nd_values_by_key['b'], + nd_values_by_key['depth_c']) + + coord = iris.coords.AuxCoord(points, + standard_name=self.standard_name, + long_name=self.long_name, + var_name=self.var_name, + units=self.units, + bounds=bounds, + attributes=self.attributes, + coord_system=self.coord_system) + return coord + + def update(self, old_coord, new_coord=None): + """ + Notifies the factory of the removal/replacement of a coordinate + which might be a dependency. + + Args: + + * old_coord: + The coordinate to be removed/replaced. + * new_coord: + If None, any dependency using old_coord is removed, otherwise + any dependency using old_coord is updated to use new_coord. + + """ + new_dependencies = self.dependencies + for name, coord in self.dependencies.items(): + if old_coord is coord: + new_dependencies[name] = new_coord + try: + self._check_dependencies(**new_dependencies) + except ValueError as e: + msg = 'Failed to update dependencies. ' + str(e) + raise ValueError(msg) + else: + setattr(self, name, new_coord) + break + + +class OceanSg2Factory(AuxCoordFactory): + """Defines an Ocean s-coordinate, generic form 2 factory.""" + + def __init__(self, s=None, c=None, eta=None, depth=None, depth_c=None): + """ + Creates an Ocean s-coordinate, generic form 2 factory with the formula: + + z(n,k,j,i) = eta(n,j,i) + (eta(n,j,i) + depth(j,i)) * S(k,j,i) + + where: + S(k,j,i) = (depth_c * s(k) + depth(j,i) * C(k)) / + (depth_c + depth(j,i)) + + """ + super(OceanSg2Factory, self).__init__() + + # Check that provided coordinates meet necessary conditions. + self._check_dependencies(s, c, eta, depth, depth_c) + + self.s = s + self.c = c + self.eta = eta + self.depth = depth + self.depth_c = depth_c + + self.standard_name = 'sea_surface_height_above_reference_ellipsoid' + self.attributes = {'positive': 'up'} + + @property + def units(self): + return self.depth.units + + @staticmethod + def _check_dependencies(s, c, eta, depth, depth_c): + # Check for sufficient factory coordinates. + if (eta is None or s is None or c is None or + depth is None or depth_c is None): + msg = 'Unable to construct Ocean s-coordinate, generic form 2 ' \ + 'factory due to insufficient source coordinates.' + raise ValueError(msg) + + # Check bounds and shape. + coords = ((s, 's'), (c, 'c')) + for coord, term in coords: + if coord is not None and coord.nbounds not in (0, 2): + msg = 'Invalid {} coordinate {!r}: must have either ' \ + '0 or 2 bounds.'.format(term, coord.name()) + raise ValueError(msg) + + if s and s.nbounds != c.nbounds: + msg = 'The s coordinate {!r} and c coordinate {!r} ' \ + 'must be equally bounded.'.format(s.name(), c.name()) + raise ValueError(msg) + + coords = ((eta, 'eta'), (depth, 'depth')) + for coord, term in coords: + if coord is not None and coord.nbounds: + msg = 'The {} coordinate {!r} has bounds. ' \ + 'These are being disregarded.'.format(term, coord.name()) + warnings.warn(msg, UserWarning, stacklevel=2) + + if depth_c is not None and depth_c.shape != (1,): + msg = 'Expected scalar depth_c coordinate {!r}: ' \ + 'got shape {!r}.'.format(depth_c.name(), depth_c.shape) + raise ValueError(msg) + + # Check units. + coords = ((s, 's'), (c, 'c')) + for coord, term in coords: + if coord is not None and not coord.units.is_dimensionless(): + msg = 'Invalid units: {} coordinate {!r} ' \ + 'must be dimensionless.'.format(term, coord.name()) + raise ValueError(msg) + + coords = ((eta, 'eta'), (depth, 'depth'), (depth_c, 'depth_c')) + for coord, term in coords: + if coord is not None and coord.units != depth.units: + msg = 'Incompatible units: {} coordinate {!r} and depth ' \ + 'coordinate {!r} must have ' \ + 'the same units.'.format(term, coord.name(), depth.name()) + raise ValueError(msg) + + @property + def dependencies(self): + """ + Returns a dictionary mapping from constructor argument names to + the corresponding coordinates. + + """ + return dict(s=self.s, c=self.c, eta=self.eta, depth=self.depth, + depth_c=self.depth_c) + + def _derive(self, s, c, eta, depth, depth_c): + S = (depth_c * s + depth * c) / (depth_c + depth) + return eta + (eta + depth) * S + + def make_coord(self, coord_dims_func): + """ + Returns a new :class:`iris.coords.AuxCoord` as defined by this factory. + + Args: + + * coord_dims_func: + A callable which can return the list of dimensions relevant + to a given coordinate. See :meth:`iris.cube.Cube.coord_dims()`. + + """ + # Determine the relevant dimensions. + derived_dims = self.derived_dims(coord_dims_func) + dependency_dims = self._dependency_dims(coord_dims_func) + + # Build the points array. + nd_points_by_key = self._remap(dependency_dims, derived_dims) + points = self._derive(nd_points_by_key['s'], + nd_points_by_key['c'], + nd_points_by_key['eta'], + nd_points_by_key['depth'], + nd_points_by_key['depth_c']) + + bounds = None + if self.s.nbounds or (self.c and self.c.nbounds): + # Build the bounds array. + nd_values_by_key = self._remap_with_bounds(dependency_dims, + derived_dims) + valid_shapes = [(), (1,), (2,)] + key = 's' + if nd_values_by_key[key].shape[-1:] not in valid_shapes: + name = self.dependencies[key].name() + msg = 'Invalid bounds for {} ' \ + 'coordinate {!r}.'.format(key, name) + raise ValueError(msg) + valid_shapes.pop() + for key in ('eta', 'depth', 'depth_c'): + if nd_values_by_key[key].shape[-1:] not in valid_shapes: + name = self.dependencies[key].name() + msg = 'The {} coordinate {!r} has bounds. ' \ + 'These are being disregarded.'.format(key, name) + warnings.warn(msg, UserWarning, stacklevel=2) + # Swap bounds with points. + bds_shape = list(nd_points_by_key[key].shape) + [1] + bounds = nd_points_by_key[key].reshape(bds_shape) + nd_values_by_key[key] = bounds + + bounds = self._derive(nd_values_by_key['s'], + nd_values_by_key['c'], + nd_values_by_key['eta'], + nd_values_by_key['depth'], + nd_values_by_key['depth_c']) + + coord = iris.coords.AuxCoord(points, + standard_name=self.standard_name, + long_name=self.long_name, + var_name=self.var_name, + units=self.units, + bounds=bounds, + attributes=self.attributes, + coord_system=self.coord_system) + return coord + + def update(self, old_coord, new_coord=None): + """ + Notifies the factory of the removal/replacement of a coordinate + which might be a dependency. + + Args: + + * old_coord: + The coordinate to be removed/replaced. + * new_coord: + If None, any dependency using old_coord is removed, otherwise any dependency using old_coord is updated to use new_coord. """ @@ -736,7 +1664,8 @@ def update(self, old_coord, new_coord=None): try: self._check_dependencies(**new_dependencies) except ValueError as e: - msg = 'Failed to update dependencies. ' + e.message + msg = 'Failed to update dependencies. ' + str(e) raise ValueError(msg) else: setattr(self, name, new_coord) + break diff --git a/lib/iris/config.py b/lib/iris/config.py index 909239fc2a..f375128a14 100644 --- a/lib/iris/config.py +++ b/lib/iris/config.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -23,13 +23,6 @@ ---------- -.. py:data:: iris.config.SAMPLE_DATA_DIR - - Local directory where sample data exists. Defaults to "sample_data" - sub-directory of the Iris package install directory. The sample data - directory supports the Iris gallery. Directory contents accessed via - :func:`iris.sample_data_path`. - .. py:data:: iris.config.TEST_DATA_DIR Local directory where test data exists. Defaults to "test_data" @@ -41,16 +34,6 @@ The full path to the Iris palette configuration directory -.. py:data:: iris.config.RULE_LOG_DIR - - The [optional] full path to the rule logging directory used by - :func:`iris.fileformats.pp.load()` and - :func:`iris.fileformats.pp.save()`. - -.. py:data:: iris.config.RULE_LOG_IGNORE - - The [optional] list of users to ignore when logging rules. - .. py:data:: iris.config.IMPORT_LOGGER The [optional] name of the logger to notify when first imported. @@ -58,8 +41,14 @@ ---------- """ -import ConfigParser +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six +from six.moves import configparser + +import contextlib import os.path +import sys import warnings @@ -103,7 +92,10 @@ def get_dir_option(section, option, default=None): CONFIG_PATH = os.path.join(ROOT_PATH, 'etc') # Load the optional "site.cfg" file if it exists. -config = ConfigParser.SafeConfigParser() +if sys.version_info >= (3, 2): + config = configparser.ConfigParser() +else: + config = configparser.SafeConfigParser() config.read([os.path.join(CONFIG_PATH, 'site.cfg')]) @@ -112,10 +104,6 @@ def get_dir_option(section, option, default=None): _RESOURCE_SECTION = 'Resources' -SAMPLE_DATA_DIR = get_dir_option( - _RESOURCE_SECTION, 'sample_data_dir', - default=os.path.join(os.path.dirname(__file__), 'sample_data')) - TEST_DATA_DIR = get_dir_option(_RESOURCE_SECTION, 'test_data_dir', default=os.path.join(os.path.dirname(__file__), 'test_data')) @@ -123,22 +111,113 @@ def get_dir_option(section, option, default=None): # Override the data repository if the appropriate environment variable # has been set. This is used in setup.py in the TestRunner command to # enable us to simulate the absence of external data. -if os.environ.get("override_test_data_repository"): +override = os.environ.get("OVERRIDE_TEST_DATA_REPOSITORY") +if override: TEST_DATA_DIR = None + if os.path.isdir(os.path.expanduser(override)): + TEST_DATA_DIR = os.path.abspath(override) PALETTE_PATH = get_dir_option(_RESOURCE_SECTION, 'palette_path', os.path.join(CONFIG_PATH, 'palette')) - -################# -# Logging options -_LOGGING_SECTION = 'Logging' - - -RULE_LOG_DIR = get_dir_option(_LOGGING_SECTION, 'rule_dir') - - -RULE_LOG_IGNORE = get_option(_LOGGING_SECTION, 'rule_ignore') - - -IMPORT_LOGGER = get_option(_LOGGING_SECTION, 'import_logger') +# Runtime options + + +class NetCDF(object): + """Control Iris NetCDF options.""" + + def __init__(self, conventions_override=None): + """ + Set up NetCDF processing options for Iris. + + Currently accepted kwargs: + + * conventions_override (bool): + Define whether the CF Conventions version (e.g. `CF-1.6`) set when + saving a cube to a NetCDF file should be defined by + Iris (the default) or the cube being saved. + + If `False` (the default), specifies that Iris should set the + CF Conventions version when saving cubes as NetCDF files. + If `True`, specifies that the cubes being saved to NetCDF should + set the CF Conventions version for the saved NetCDF files. + + Example usages: + + * Specify, for the lifetime of the session, that we want all cubes + written to NetCDF to define their own CF Conventions versions:: + + iris.config.netcdf.conventions_override = True + iris.save('my_cube', 'my_dataset.nc') + iris.save('my_second_cube', 'my_second_dataset.nc') + + * Specify, with a context manager, that we want a cube written to + NetCDF to define its own CF Conventions version:: + + with iris.config.netcdf.context(conventions_override=True): + iris.save('my_cube', 'my_dataset.nc') + + """ + # Define allowed `__dict__` keys first. + self.__dict__['conventions_override'] = None + + # Now set specific values. + setattr(self, 'conventions_override', conventions_override) + + def __repr__(self): + msg = 'NetCDF options: {}.' + # Automatically populate with all currently accepted kwargs. + options = ['{}={}'.format(k, v) + for k, v in six.iteritems(self.__dict__)] + joined = ', '.join(options) + return msg.format(joined) + + def __setattr__(self, name, value): + if name not in self.__dict__: + # Can't add new names. + msg = 'Cannot set option {!r} for {} configuration.' + raise AttributeError(msg.format(name, self.__class__.__name__)) + if value is None: + # Set an unset value to the name's default. + value = self._defaults_dict[name]['default'] + if self._defaults_dict[name]['options'] is not None: + # Replace a bad value with a good one if there is a defined set of + # specified good values. If there isn't, we can assume that + # anything goes. + if value not in self._defaults_dict[name]['options']: + good_value = self._defaults_dict[name]['default'] + wmsg = ('Attempting to set invalid value {!r} for ' + 'attribute {!r}. Defaulting to {!r}.') + warnings.warn(wmsg.format(value, name, good_value)) + value = good_value + self.__dict__[name] = value + + @property + def _defaults_dict(self): + # Set this as a property so that it isn't added to `self.__dict__`. + return {'conventions_override': {'default': False, + 'options': [True, False]}, + } + + @contextlib.contextmanager + def context(self, **kwargs): + """ + Allow temporary modification of the options via a context manager. + Accepted kwargs are the same as can be supplied to the Option. + + """ + # Snapshot the starting state for restoration at the end of the + # contextmanager block. + starting_state = self.__dict__.copy() + # Update the state to reflect the requested changes. + for name, value in six.iteritems(kwargs): + setattr(self, name, value) + try: + yield + finally: + # Return the state to the starting state. + self.__dict__.clear() + self.__dict__.update(starting_state) + + +netcdf = NetCDF() diff --git a/lib/iris/coord_categorisation.py b/lib/iris/coord_categorisation.py index 85f78db03e..3c3303441d 100644 --- a/lib/iris/coord_categorisation.py +++ b/lib/iris/coord_categorisation.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -27,6 +27,10 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + import calendar import collections @@ -61,7 +65,7 @@ def add_categorised_coord(cube, name, from_coord, category_function, units of the category value, typically 'no_unit' or '1'. """ # Interpret coord, if given as a name - if isinstance(from_coord, basestring): + if isinstance(from_coord, six.string_types): from_coord = cube.coord(from_coord) if len(cube.coords(name)) > 0: @@ -73,9 +77,14 @@ def add_categorised_coord(cube, name, from_coord, category_function, # Test whether the result contains strings. If it does we must manually # force the dtype because of a numpy bug (see numpy #3270 on GitHub). result = category_function(from_coord, from_coord.points.ravel()[0]) - if isinstance(result, basestring): + if isinstance(result, six.string_types): str_vectorised_fn = np.vectorize(category_function, otypes=[object]) - vectorised_fn = lambda *args: str_vectorised_fn(*args).astype('|S64') + # Use a common type for string arrays (N.B. limited to 64 chars) + all_cases_string_type = '|S64' if six.PY2 else '|U64' + + def vectorised_fn(*args): + return str_vectorised_fn(*args).astype(all_cases_string_type) + else: vectorised_fn = np.vectorize(category_function) new_coord = iris.coords.AuxCoord(vectorised_fn(from_coord, @@ -88,7 +97,7 @@ def add_categorised_coord(cube, name, from_coord, category_function, cube.add_aux_coord(new_coord, cube.coord_dims(from_coord)) -#====================================== +# ====================================== # Specific functions for particular purposes # # NOTE: all the existing ones are calendar operations, so are for 'Time' @@ -118,7 +127,7 @@ def _pt_date(coord, time): return coord.units.num2date(time) -#-------------------------------------------- +# -------------------------------------------- # Time categorisations : calendar date components def add_year(cube, coord, name='year'): @@ -164,12 +173,16 @@ def add_day_of_year(cube, coord, name='day_of_year'): (1..366 in leap years). """ + # Note: cftime.datetime objects return a normal tuple from timetuple(), + # unlike datetime.datetime objects that return a namedtuple. + # Index the time tuple (element 7 is day of year) instead of using named + # element tm_yday. add_categorised_coord( cube, name, coord, - lambda coord, x: _pt_date(coord, x).timetuple().tm_yday) + lambda coord, x: _pt_date(coord, x).timetuple()[7]) -#-------------------------------------------- +# -------------------------------------------- # Time categorisations : days of the week def add_weekday_number(cube, coord, name='weekday_number'): @@ -195,7 +208,17 @@ def add_weekday(cube, coord, name='weekday'): units='no_unit') -#---------------------------------------------- +# -------------------------------------------- +# Time categorisations : hour of the day + +def add_hour(cube, coord, name='hour'): + """Add a categorical hour coordinate, values 0..23.""" + add_categorised_coord( + cube, name, coord, + lambda coord, x: _pt_date(coord, x).hour) + + +# ---------------------------------------------- # Time categorisations : meteorological seasons def _months_in_season(season): @@ -210,7 +233,7 @@ def _months_in_season(season): # Can't match the season, raise an error. raise ValueError('unrecognised season: {!s}'.format(season)) m1 = m0 + len(season) - return map(lambda month: (month % 12) + 1, range(m0, m1)) + return [(month % 12) + 1 for month in range(m0, m1)] def _validate_seasons(seasons): @@ -227,13 +250,13 @@ def _validate_seasons(seasons): for season in seasons: c.update(_months_in_season(season)) # Make a list of months that are not present... - not_present = [calendar.month_abbr[month] for month in xrange(1, 13) - if month not in c.keys()] + not_present = [calendar.month_abbr[month] for month in range(1, 13) + if month not in c] if not_present: raise ValueError('some months do not appear in any season: ' '{!s}'.format(', '.join(not_present))) # Make a list of months that appear multiple times... - multi_present = [calendar.month_abbr[month] for month in xrange(1, 13) + multi_present = [calendar.month_abbr[month] for month in range(1, 13) if c[month] > 1] if multi_present: raise ValueError('some months appear in more than one season: ' @@ -252,8 +275,9 @@ def _month_year_adjusts(seasons): month_year_adjusts = [None, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] for season in seasons: months = _months_in_season(season) - for month in filter(lambda m: m > months[-1], months): - month_year_adjusts[month] = 1 + for month in months: + if month > months[-1]: + month_year_adjusts[month] = 1 return month_year_adjusts diff --git a/lib/iris/coord_systems.py b/lib/iris/coord_systems.py index 15e104a9de..e02ae7dc8c 100644 --- a/lib/iris/coord_systems.py +++ b/lib/iris/coord_systems.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -19,19 +19,23 @@ """ -from __future__ import division +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + from abc import ABCMeta, abstractmethod import warnings -import cartopy.crs +import numpy as np +import cartopy +import cartopy.crs as ccrs -class CoordSystem(object): +class CoordSystem(six.with_metaclass(ABCMeta, object)): """ Abstract base class for coordinate systems. """ - __metaclass__ = ABCMeta grid_mapping_name = None @@ -59,10 +63,16 @@ def xml_element(self, doc, attrs=None): if attrs is None: attrs = self.__dict__.items() - attrs.sort(key=lambda attr: attr[0]) + attrs = sorted(attrs, key=lambda attr: attr[0]) for name, value in attrs: - coord_system_xml_element.setAttribute(name, str(value)) + if isinstance(value, float): + value_str = '{:.16}'.format(value) + elif isinstance(value, np.float32): + value_str = '{:.8}'.format(value) + else: + value_str = '{}'.format(value) + coord_system_xml_element.setAttribute(name, value_str) return coord_system_xml_element @@ -208,10 +218,17 @@ def __str__(self): attrs = self._pretty_attrs() # Special case for 1 pretty attr if len(attrs) == 1 and attrs[0][0] == "semi_major_axis": - return "GeogCS(%s)" % self.semi_major_axis + return 'GeogCS({:.16})'.format(self.semi_major_axis) else: - return "GeogCS(%s)" % ", ".join( - ["%s=%s" % (k, v) for k, v in attrs]) + text_attrs = [] + for k, v in attrs: + if isinstance(v, float): + text_attrs.append('{}={:.16}'.format(k, v)) + elif isinstance(v, np.float32): + text_attrs.append('{}={:.8}'.format(k, v)) + else: + text_attrs.append('{}={}'.format(k, v)) + return 'GeogCS({})'.format(', '.join(text_attrs)) def xml_element(self, doc): # Special output for spheres @@ -222,17 +239,17 @@ def xml_element(self, doc): return CoordSystem.xml_element(self, doc, attrs) def as_cartopy_crs(self): - return cartopy.crs.Geodetic(self.as_cartopy_globe()) + return ccrs.Geodetic(self.as_cartopy_globe()) def as_cartopy_projection(self): - return cartopy.crs.PlateCarree() + return ccrs.PlateCarree() def as_cartopy_globe(self): # Explicitly set `ellipse` to None as a workaround for # Cartopy setting WGS84 as the default. - return cartopy.crs.Globe(semimajor_axis=self.semi_major_axis, - semiminor_axis=self.semi_minor_axis, - ellipse=None) + return ccrs.Globe(semimajor_axis=self.semi_major_axis, + semiminor_axis=self.semi_minor_axis, + ellipse=None) class RotatedGeogCS(CoordSystem): @@ -303,8 +320,15 @@ def __repr__(self): def __str__(self): attrs = self._pretty_attrs() - result = "RotatedGeogCS(%s)" % ", ".join( - ["%s=%s" % (k, v) for k, v in attrs]) + text_attrs = [] + for k, v in attrs: + if isinstance(v, float): + text_attrs.append('{}={:.16}'.format(k, v)) + elif isinstance(v, np.float32): + text_attrs.append('{}={:.8}'.format(k, v)) + else: + text_attrs.append('{}={}'.format(k, v)) + result = 'RotatedGeogCS({})'.format(', '.join(text_attrs)) # Extra prettiness result = result.replace("grid_north_pole_latitude=", "") result = result.replace("grid_north_pole_longitude=", "") @@ -313,13 +337,30 @@ def __str__(self): def xml_element(self, doc): return CoordSystem.xml_element(self, doc, self._pretty_attrs()) + def _ccrs_kwargs(self): + globe = None + if self.ellipsoid is not None: + globe = self.ellipsoid.as_cartopy_globe() + # Cartopy v0.12 provided the new arg north_pole_grid_longitude + cartopy_kwargs = {'pole_longitude': self.grid_north_pole_longitude, + 'pole_latitude': self.grid_north_pole_latitude, + 'globe': globe} + + if cartopy.__version__ < '0.12': + warnings.warn('"central_rotated_longitude" is not supported by ' + 'cartopy{} and has been ignored in the ' + 'creation of the cartopy ' + 'projection/crs.'.format(cartopy.__version__)) + else: + crl = 'central_rotated_longitude' + cartopy_kwargs[crl] = self.north_pole_grid_longitude + return cartopy_kwargs + def as_cartopy_crs(self): - return cartopy.crs.RotatedGeodetic(self.grid_north_pole_longitude, - self.grid_north_pole_latitude) + return ccrs.RotatedGeodetic(**self._ccrs_kwargs()) def as_cartopy_projection(self): - return cartopy.crs.RotatedPole(self.grid_north_pole_longitude, - self.grid_north_pole_latitude) + return ccrs.RotatedPole(**self._ccrs_kwargs()) class TransverseMercator(CoordSystem): @@ -405,7 +446,7 @@ def as_cartopy_crs(self): else: globe = None - return cartopy.crs.TransverseMercator( + return ccrs.TransverseMercator( central_longitude=self.longitude_of_central_meridian, central_latitude=self.latitude_of_projection_origin, false_easting=self.false_easting, @@ -425,10 +466,183 @@ def __init__(self): GeogCS(6377563.396, 6356256.909)) def as_cartopy_crs(self): - return cartopy.crs.OSGB() + return ccrs.OSGB() + + def as_cartopy_projection(self): + return ccrs.OSGB() + + +class Orthographic(CoordSystem): + """ + An orthographic map projection. + + """ + + grid_mapping_name = 'orthographic' + + def __init__(self, latitude_of_projection_origin, + longitude_of_projection_origin, false_easting=0.0, + false_northing=0.0, ellipsoid=None): + """ + Constructs an Orthographic coord system. + + Args: + + * latitude_of_projection_origin: + True latitude of planar origin in degrees. + + * longitude_of_projection_origin: + True longitude of planar origin in degrees. + + Kwargs: + + * false_easting + X offset from planar origin in metres. Defaults to 0. + + * false_northing + Y offset from planar origin in metres. Defaults to 0. + + * ellipsoid + :class:`GeogCS` defining the ellipsoid. + + """ + #: True latitude of planar origin in degrees. + self.latitude_of_projection_origin = float( + latitude_of_projection_origin) + + #: True longitude of planar origin in degrees. + self.longitude_of_projection_origin = float( + longitude_of_projection_origin) + + #: X offset from planar origin in metres. + self.false_easting = float(false_easting) + + #: Y offset from planar origin in metres. + self.false_northing = float(false_northing) + + #: Ellipsoid definition. + self.ellipsoid = ellipsoid + + def __repr__(self): + return "Orthographic(latitude_of_projection_origin={!r}, "\ + "longitude_of_projection_origin={!r}, "\ + "false_easting={!r}, false_northing={!r}, "\ + "ellipsoid={!r})".format(self.latitude_of_projection_origin, + self.longitude_of_projection_origin, + self.false_easting, + self.false_northing, + self.ellipsoid) + + def as_cartopy_crs(self): + if self.ellipsoid is not None: + globe = self.ellipsoid.as_cartopy_globe() + else: + globe = ccrs.Globe() + + warnings.warn('Discarding false_easting and false_northing that are ' + 'not used by Cartopy.') + + return ccrs.Orthographic( + central_longitude=self.longitude_of_projection_origin, + central_latitude=self.latitude_of_projection_origin, + globe=globe) + + def as_cartopy_projection(self): + return self.as_cartopy_crs() + + +class VerticalPerspective(CoordSystem): + """ + An geostationary satellite image map projection. + + """ + + grid_mapping_name = 'vertical_perspective' + + def __init__(self, latitude_of_projection_origin, + longitude_of_projection_origin, perspective_point_height, + false_easting=0, false_northing=0, ellipsoid=None): + """ + Constructs an Vertical Perspective Geostationary coord system. + + Args: + + * latitude_of_projection_origin: + True latitude of planar origin in degrees. + + * longitude_of_projection_origin: + True longitude of planar origin in degrees. + + * perspective_point_height: + Altitude of satellite in metres above the surface of the + ellipsoid. + + Kwargs: + + * false_easting + X offset from planar origin in metres. Defaults to 0. + + * false_northing + Y offset from planar origin in metres. Defaults to 0. + + * ellipsoid + :class:`GeogCS` defining the ellipsoid. + + """ + #: True latitude of planar origin in degrees. + self.latitude_of_projection_origin = float( + latitude_of_projection_origin) + if self.latitude_of_projection_origin != 0.0: + raise ValueError('Non-zero latitude of projection currently not' + ' supported by Cartopy.') + + #: True longitude of planar origin in degrees. + self.longitude_of_projection_origin = float( + longitude_of_projection_origin) + + #: Altitude of satellite in metres. + # test if perspective_point_height may be cast to float for proj.4 + test_pph = float(perspective_point_height) + self.perspective_point_height = perspective_point_height + + #: X offset from planar origin in metres. + test_fe = float(false_easting) + self.false_easting = false_easting + + #: Y offset from planar origin in metres. + test_fn = float(false_northing) + self.false_northing = false_northing + + #: Ellipsoid definition. + self.ellipsoid = ellipsoid + + def __repr__(self): + return "Vertical Perspective(latitude_of_projection_origin={!r}, "\ + "longitude_of_projection_origin={!r}, "\ + "perspective_point_height = {!r}, "\ + "false_easting={!r}, false_northing={!r}, "\ + "ellipsoid={!r})".format(self.latitude_of_projection_origin, + self.longitude_of_projection_origin, + self.perspective_point_height, + self.false_easting, + self.false_northing, + self.ellipsoid) + + def as_cartopy_crs(self): + if self.ellipsoid is not None: + globe = self.ellipsoid.as_cartopy_globe() + else: + globe = ccrs.Globe() + + return ccrs.Geostationary( + central_longitude=self.longitude_of_projection_origin, + satellite_height=self.perspective_point_height, + false_easting=self.false_easting, + false_northing=self.false_northing, + globe=globe) def as_cartopy_projection(self): - return cartopy.crs.OSGB() + return self.as_cartopy_crs() class Stereographic(CoordSystem): @@ -453,14 +667,14 @@ def __init__(self, central_lat, central_lon, * central_lon The central longitude, which aligns with the y axis. + Kwargs: + * false_easting X offset from planar origin in metres. Defaults to 0. * false_northing Y offset from planar origin in metres. Defaults to 0. - Kwargs: - * true_scale_lat Latitude of true scale. @@ -501,11 +715,11 @@ def as_cartopy_crs(self): if self.ellipsoid is not None: globe = self.ellipsoid.as_cartopy_globe() else: - globe = cartopy.crs.Globe() - return cartopy.crs.Stereographic( + globe = ccrs.Globe() + return ccrs.Stereographic( self.central_lat, self.central_lon, self.false_easting, self.false_northing, - self.true_scale_lat, globe) + self.true_scale_lat, globe=globe) def as_cartopy_projection(self): return self.as_cartopy_crs() @@ -517,7 +731,7 @@ class LambertConformal(CoordSystem): """ - grid_mapping_name = "lambert_conformal" + grid_mapping_name = "lambert_conformal_conic" def __init__(self, central_lat=39.0, central_lon=-96.0, false_easting=0.0, false_northing=0.0, @@ -525,7 +739,7 @@ def __init__(self, central_lat=39.0, central_lon=-96.0, """ Constructs a LambertConformal coord system. - Args: + Kwargs: * central_lat The latitude of "unitary scale". @@ -539,8 +753,6 @@ def __init__(self, central_lat=39.0, central_lon=-96.0, * false_northing Y offset from planar origin in metres. - Kwargs: - * secant_latitudes Latitudes of secant intersection. @@ -564,8 +776,11 @@ def __init__(self, central_lat=39.0, central_lon=-96.0, self.false_easting = false_easting #: Y offset from planar origin in metres. self.false_northing = false_northing - #: Latitudes of secant intersection. - self.secant_latitudes = secant_latitudes + #: The two standard parallels of the cone. + try: + self.secant_latitudes = tuple(secant_latitudes) + except TypeError: + self.secant_latitudes = (secant_latitudes,) #: Ellipsoid definition. self.ellipsoid = ellipsoid @@ -589,12 +804,222 @@ def as_cartopy_crs(self): if self.ellipsoid is not None: globe = self.ellipsoid.as_cartopy_globe() else: - globe = cartopy.crs.Globe() + globe = ccrs.Globe() - return cartopy.crs.LambertConformal( - self.central_lon, self.central_lat, - self.false_easting, self.false_northing, - self.secant_latitudes, globe, cutoff) + # Cartopy v0.12 deprecated the use of secant_latitudes. + if cartopy.__version__ < '0.12': + conic_position = dict(secant_latitudes=self.secant_latitudes) + else: + conic_position = dict(standard_parallels=self.secant_latitudes) + + return ccrs.LambertConformal( + central_longitude=self.central_lon, + central_latitude=self.central_lat, + false_easting=self.false_easting, + false_northing=self.false_northing, + globe=globe, cutoff=cutoff, **conic_position) + + def as_cartopy_projection(self): + return self.as_cartopy_crs() + + +class Mercator(CoordSystem): + """ + A coordinate system in the Mercator projection. + + """ + + grid_mapping_name = "mercator" + + def __init__(self, longitude_of_projection_origin=0.0, ellipsoid=None, + standard_parallel=0.0): + """ + Constructs a Mercator coord system. + + Kwargs: + * longitude_of_projection_origin + True longitude of planar origin in degrees. + * ellipsoid + :class:`GeogCS` defining the ellipsoid. + * standard_parallel + the latitude where the scale is 1. Defaults to 0 degrees. + + """ + #: True longitude of planar origin in degrees. + self.longitude_of_projection_origin = longitude_of_projection_origin + #: Ellipsoid definition. + self.ellipsoid = ellipsoid + #: The latitude where the scale is 1 (defaults to 0 degrees). + self.standard_parallel = standard_parallel + + def __repr__(self): + res = ("Mercator(longitude_of_projection_origin=" + "{self.longitude_of_projection_origin!r}, " + "ellipsoid={self.ellipsoid!r}, " + "standard_parallel={self.standard_parallel!r})") + return res.format(self=self) + + def as_cartopy_crs(self): + if self.ellipsoid is not None: + globe = self.ellipsoid.as_cartopy_globe() + else: + globe = ccrs.Globe() + + return ccrs.Mercator( + central_longitude=self.longitude_of_projection_origin, + globe=globe, + latitude_true_scale=self.standard_parallel) + + def as_cartopy_projection(self): + return self.as_cartopy_crs() + + +class LambertAzimuthalEqualArea(CoordSystem): + """ + A coordinate system in the Lambert Azimuthal Equal Area projection. + + """ + + grid_mapping_name = "lambert_azimuthal_equal_area" + + def __init__(self, latitude_of_projection_origin=0.0, + longitude_of_projection_origin=0.0, + false_easting=0.0, false_northing=0.0, + ellipsoid=None): + """ + Constructs a Lambert Azimuthal Equal Area coord system. + + Kwargs: + + * latitude_of_projection_origin + True latitude of planar origin in degrees. Defaults to 0. + + * longitude_of_projection_origin + True longitude of planar origin in degrees. Defaults to 0. + + * false_easting + X offset from planar origin in metres. Defaults to 0. + + * false_northing + Y offset from planar origin in metres. Defaults to 0. + + * ellipsoid + :class:`GeogCS` defining the ellipsoid. + + """ + #: True latitude of planar origin in degrees. + self.latitude_of_projection_origin = latitude_of_projection_origin + #: True longitude of planar origin in degrees. + self.longitude_of_projection_origin = longitude_of_projection_origin + #: X offset from planar origin in metres. + self.false_easting = false_easting + #: Y offset from planar origin in metres. + self.false_northing = false_northing + #: Ellipsoid definition. + self.ellipsoid = ellipsoid + + def __repr__(self): + return ("LambertAzimuthalEqualArea(latitude_of_projection_origin={!r}," + " longitude_of_projection_origin={!r}, false_easting={!r}," + " false_northing={!r}, ellipsoid={!r})").format( + self.latitude_of_projection_origin, + self.longitude_of_projection_origin, + self.false_easting, + self.false_northing, + self.ellipsoid) + + def as_cartopy_crs(self): + if self.ellipsoid is not None: + globe = self.ellipsoid.as_cartopy_globe() + else: + globe = ccrs.Globe() + return ccrs.LambertAzimuthalEqualArea( + central_longitude=self.longitude_of_projection_origin, + central_latitude=self.latitude_of_projection_origin, + false_easting=self.false_easting, + false_northing=self.false_northing, + globe=globe) + + def as_cartopy_projection(self): + return self.as_cartopy_crs() + + +class AlbersEqualArea(CoordSystem): + """ + A coordinate system in the Albers Conical Equal Area projection. + + """ + + grid_mapping_name = "albers_conical_equal_area" + + def __init__(self, latitude_of_projection_origin=0.0, + longitude_of_central_meridian=0.0, + false_easting=0.0, false_northing=0.0, + standard_parallels=(20.0, 50.0), + ellipsoid=None): + """ + Constructs a Albers Conical Equal Area coord system. + + Kwargs: + + * latitude_of_projection_origin + True latitude of planar origin in degrees. + Defaults to 0. + + * longitude_of_central_meridian + True longitude of planar central meridian in degrees. + Defaults to 0. + + * false_easting + X offset from planar origin in metres. Defaults to 0. + + * false_northing + Y offset from planar origin in metres. Defaults to 0. + + * standard_parallels + The one or two latitudes of correct scale. + Defaults to (20,50). + * ellipsoid + :class:`GeogCS` defining the ellipsoid. + + """ + #: True latitude of planar origin in degrees. + self.latitude_of_projection_origin = latitude_of_projection_origin + #: True longitude of planar central meridian in degrees. + self.longitude_of_central_meridian = longitude_of_central_meridian + #: X offset from planar origin in metres. + self.false_easting = false_easting + #: Y offset from planar origin in metres. + self.false_northing = false_northing + #: The one or two latitudes of correct scale. + self.standard_parallels = standard_parallels + #: Ellipsoid definition. + self.ellipsoid = ellipsoid + + def __repr__(self): + return ("AlbersEqualArea(latitude_of_projection_origin={!r}," + " longitude_of_central_meridian={!r}, false_easting={!r}," + " false_northing={!r}, standard_parallels={!r}," + " ellipsoid={!r})").format( + self.latitude_of_projection_origin, + self.longitude_of_central_meridian, + self.false_easting, + self.false_northing, + self.standard_parallels, + self.ellipsoid) + + def as_cartopy_crs(self): + if self.ellipsoid is not None: + globe = self.ellipsoid.as_cartopy_globe() + else: + globe = ccrs.Globe() + return ccrs.AlbersEqualArea( + central_longitude=self.longitude_of_central_meridian, + central_latitude=self.latitude_of_projection_origin, + false_easting=self.false_easting, + false_northing=self.false_northing, + standard_parallels=self.standard_parallels, + globe=globe) def as_cartopy_projection(self): return self.as_cartopy_crs() diff --git a/lib/iris/coords.py b/lib/iris/coords.py index af78c5b5f3..5519630c5d 100644 --- a/lib/iris/coords.py +++ b/lib/iris/coords.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -18,25 +18,34 @@ Definitions of coordinates. """ -from __future__ import division + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six from abc import ABCMeta, abstractproperty import collections import copy -from itertools import chain, izip_longest +from itertools import chain +from six.moves import zip_longest import operator import warnings import zlib +import cftime import numpy as np +import numpy.ma as ma +from iris._data_manager import DataManager +from iris._deprecation import warn_deprecated +import iris._lazy_data as _lazy import iris.aux_factory import iris.exceptions -import iris.unit +import iris.time import iris.util from iris._cube_coord_common import CFVariableMixin -from iris.util import is_regular +from iris.util import points_step class CoordDefn(collections.namedtuple('CoordDefn', @@ -48,6 +57,9 @@ class CoordDefn(collections.namedtuple('CoordDefn', :class:`AuxCoord` based on its metadata. """ + + __slots__ = () + def name(self, default='unknown'): """ Returns a human-readable name. @@ -59,6 +71,63 @@ def name(self, default='unknown'): """ return self.standard_name or self.long_name or self.var_name or default + def __lt__(self, other): + if not isinstance(other, CoordDefn): + return NotImplemented + + def _sort_key(defn): + # Emulate Python 2 behaviour with None + return (defn.standard_name is not None, defn.standard_name, + defn.long_name is not None, defn.long_name, + defn.var_name is not None, defn.var_name, + defn.units is not None, defn.units, + defn.coord_system is not None, defn.coord_system) + + return _sort_key(self) < _sort_key(other) + + +class CoordExtent(collections.namedtuple('_CoordExtent', ['name_or_coord', + 'minimum', + 'maximum', + 'min_inclusive', + 'max_inclusive'])): + """Defines a range of values for a coordinate.""" + + def __new__(cls, name_or_coord, minimum, maximum, + min_inclusive=True, max_inclusive=True): + """ + Create a CoordExtent for the specified coordinate and range of + values. + + Args: + + * name_or_coord + Either a coordinate name or a coordinate, as defined in + :meth:`iris.cube.Cube.coords()`. + + * minimum + The minimum value of the range to select. + + * maximum + The maximum value of the range to select. + + Kwargs: + + * min_inclusive + If True, coordinate values equal to `minimum` will be included + in the selection. Default is True. + + * max_inclusive + If True, coordinate values equal to `maximum` will be included + in the selection. Default is True. + + """ + return super(CoordExtent, cls).__new__(cls, name_or_coord, minimum, + maximum, min_inclusive, + max_inclusive) + + __slots__ = () + # Coordinate cell styles. Used in plot and cartography. POINT_MODE = 0 @@ -74,6 +143,47 @@ def name(self, default='unknown'): 'groupby_point, groupby_slice') +def _get_2d_coord_bound_grid(bounds): + """ + Creates a grid using the bounds of a 2D coordinate with 4 sided cells. + + Assumes that the four vertices of the cells are in an anti-clockwise order + (bottom-left, bottom-right, top-right, top-left). + + Selects the zeroth vertex of each cell. A final column is added, which + contains the first vertex of the cells in the final column. A final row + is added, which contains the third vertex of all the cells in the final + row, except for in the final column where it uses the second vertex. + e.g. + # 0-0-0-0-1 + # 0-0-0-0-1 + # 3-3-3-3-2 + + Args: + * bounds: (array) + Coordinate bounds array of shape (Y, X, 4) + + Returns: + * grid: (array) + Grid of shape (Y+1, X+1) + + """ + # Check bds has the shape (ny, nx, 4) + if not (bounds.ndim == 3 and bounds.shape[-1] == 4): + raise ValueError('Bounds for 2D coordinates must be 3-dimensional and ' + 'have 4 bounds per point.') + + bounds_shape = bounds.shape + result = np.zeros((bounds_shape[0] + 1, bounds_shape[1] + 1)) + + result[:-1, :-1] = bounds[:, :, 0] + result[:-1, -1] = bounds[:, -1, 1] + result[-1, :-1] = bounds[-1, :, 3] + result[-1, -1] = bounds[-1, -1, 2] + + return result + + class Cell(collections.namedtuple('Cell', ['point', 'bound'])): """ An immutable representation of a single cell of a coordinate, including the @@ -108,6 +218,9 @@ class Cell(collections.namedtuple('Cell', ['point', 'bound'])): # This subclass adds no attributes. __slots__ = () + # Make this class's comparison operators override those of numpy + __array_priority__ = 100 + def __new__(cls, point=None, bound=None): """ Construct a Cell from point or point-and-bound information. @@ -148,6 +261,9 @@ def __add__(self, mod): bound = tuple([val + mod for val in bound]) return Cell(point, bound) + def __hash__(self): + return super(Cell, self).__hash__() + def __eq__(self, other): """ Compares Cell equality depending on the type of the object to be @@ -162,8 +278,8 @@ def __eq__(self, other): return self.point == other elif isinstance(other, Cell): return (self.point == other.point) and (self.bound == other.bound) - elif (isinstance(other, basestring) and self.bound is None and - isinstance(self.point, basestring)): + elif (isinstance(other, six.string_types) and self.bound is None and + isinstance(self.point, six.string_types)): return self.point == other else: return NotImplemented @@ -186,12 +302,20 @@ def __common_cmp__(self, other, operator_method): """ if not (isinstance(other, (int, float, np.number, Cell)) or hasattr(other, 'timetuple')): - raise ValueError("Unexpected type of other " - "{}.".format(type(other))) + raise TypeError("Unexpected type of other " + "{}.".format(type(other))) if operator_method not in (operator.gt, operator.lt, operator.ge, operator.le): raise ValueError("Unexpected operator_method") + # Prevent silent errors resulting from missing cftime + # behaviour. + if (isinstance(other, cftime.datetime) or + (isinstance(self.point, cftime.datetime) and + not isinstance(other, iris.time.PartialDateTime))): + raise TypeError('Cannot determine the order of ' + 'cftime.datetime objects') + if isinstance(other, Cell): # Cell vs Cell comparison for providing a strict sort order if self.bound is None: @@ -235,20 +359,35 @@ def __common_cmp__(self, other, operator_method): else: result = operator_method(self.bound[0], other.bound[0]) else: - # Cell vs number (or string) for providing Constraint - # behaviour. + # Cell vs number (or string, or datetime-like) for providing + # Constraint behaviour. if self.bound is None: # Point vs number # - Simple matching me = self.point else: + if hasattr(other, 'timetuple'): + raise TypeError('Cannot determine whether a point lies ' + 'within a bounded region for ' + 'datetime-like objects.') # Point-and-bound vs number # - Match if "within" the Cell if operator_method in [operator.gt, operator.le]: me = min(self.bound) else: me = max(self.bound) - result = operator_method(me, other) + + # Work around to handle cftime.datetime comparison, which + # doesn't return NotImplemented on failure in some versions of the + # library + try: + result = operator_method(me, other) + except TypeError: + rop = {operator.lt: operator.gt, + operator.gt: operator.lt, + operator.le: operator.ge, + operator.ge: operator.le}[operator_method] + result = rop(other, me) return result @@ -281,16 +420,19 @@ def contains_point(self, point): """ if self.bound is None: raise ValueError('Point cannot exist inside an unbounded cell.') + if hasattr(point, 'timetuple') or np.any([hasattr(val, 'timetuple') for + val in self.bound]): + raise TypeError('Cannot determine whether a point lies within ' + 'a bounded region for datetime-like objects.') return np.min(self.bound) <= point <= np.max(self.bound) -class Coord(CFVariableMixin): +class Coord(six.with_metaclass(ABCMeta, CFVariableMixin)): """ Abstract superclass for coordinates. """ - __metaclass__ = ABCMeta _MODE_ADD = 1 _MODE_SUB = 2 @@ -317,13 +459,13 @@ def __init__(self, points, standard_name=None, long_name=None, Kwargs: * standard_name: - CF standard name of coordinate + CF standard name of the coordinate. * long_name: - Descriptive name of coordinate + Descriptive name of the coordinate. * var_name: - CF variable name of coordinate + The netCDF variable name for the coordinate. * units - The :class:`~iris.unit.Unit` of the coordinate's values. + The :class:`~cf_units.Unit` of the coordinate's values. Can be a string, which will be converted to a Unit object. * bounds An array of values describing the bounds of each cell. Given n @@ -331,11 +473,11 @@ def __init__(self, points, standard_name=None, long_name=None, points.shape + (n,). For example, a 1d coordinate with 100 points and two bounds per cell would have a bounds array of shape (100, 2) - * attributes A dictionary containing other cf and user-defined attributes. * coord_system - A :class:`~iris.coord_systems.CoordSystem`, + A :class:`~iris.coord_systems.CoordSystem` representing the + coordinate system of the coordinate, e.g. a :class:`~iris.coord_systems.GeogCS` for a longitude Coord. """ @@ -345,7 +487,7 @@ def __init__(self, points, standard_name=None, long_name=None, #: Descriptive name of the coordinate. self.long_name = long_name - #: The CF variable name for the coordinate. + #: The netCDF variable name for the coordinate. self.var_name = var_name #: Unit of the quantity that the coordinate represents. @@ -355,13 +497,16 @@ def __init__(self, points, standard_name=None, long_name=None, #: have no meaning to Iris. self.attributes = attributes - #: Relevant CoordSystem (if any). + #: Relevant coordinate system (if any). self.coord_system = coord_system + # Set up DataManager attributes and points and bounds values. + self._points_dm = None + self._bounds_dm = None self.points = points self.bounds = bounds - def __getitem__(self, key): + def __getitem__(self, keys): """ Returns a new Coord whose values are obtained by conventional array indexing. @@ -373,36 +518,27 @@ def __getitem__(self, key): indexing. """ - # Turn the key(s) into a full slice spec - i.e. one entry for - # each dimension of the coord. - full_slice = iris.util._build_full_slice_given_keys(key, self.ndim) - - # If it's a "null" indexing operation (e.g. coord[:, :]) then - # we can preserve deferred loading by avoiding promoting _points - # and _bounds to full ndarray instances. - def is_full_slice(s): - return isinstance(s, slice) and s == slice(None, None) - if all(is_full_slice(s) for s in full_slice): - points = self._points - bounds = self._bounds + # Fetch the points and bounds. + points = self._points_dm.core_data() + if self.has_bounds(): + bounds = self._bounds_dm.core_data() else: - points = self.points - bounds = self.bounds + bounds = None - # Make indexing on the cube column based by using the - # column_slices_generator (potentially requires slicing the - # data multiple times). - _, slice_gen = iris.util.column_slices_generator(full_slice, - self.ndim) - for keys in slice_gen: - if points is not None: - points = points[keys] - if points.shape and min(points.shape) == 0: - raise IndexError('Cannot index with zero length ' - 'slice.') - if bounds is not None: - bounds = bounds[keys + (Ellipsis, )] + # Index both points and bounds with the keys. + _, points = iris.util._slice_data_with_keys( + points, keys) + if bounds is not None: + _, bounds = iris.util._slice_data_with_keys( + bounds, keys) + # Copy data after indexing, to avoid making coords that are + # views on other coords. This will not realise lazy data. + points = points.copy() + if bounds is not None: + bounds = bounds.copy() + + # The new coordinate is a copy of the old one with replaced content. new_coord = self.copy(points=points, bounds=bounds) return new_coord @@ -426,17 +562,13 @@ def copy(self, points=None, bounds=None): resulting coordinate will have no bounds. """ - if points is None and bounds is not None: raise ValueError('If bounds are specified, points must also be ' 'specified') new_coord = copy.deepcopy(self) if points is not None: - # Explicitly not using the points property as we don't want the - # shape the new points to be constrained by the shape of - # self.points - new_coord._points = None + new_coord._points_dm = None new_coord.points = points # Regardless of whether bounds are provided as an argument, new # points will result in new bounds, discarding those copied from @@ -445,13 +577,176 @@ def copy(self, points=None, bounds=None): return new_coord - @abstractproperty - def points(self): - """Property containing the points values as a numpy array""" + @classmethod + def from_coord(cls, coord): + """Create a new Coord of this type, from the given coordinate.""" + kwargs = {'points': coord.core_points(), + 'bounds': coord.core_bounds(), + 'standard_name': coord.standard_name, + 'long_name': coord.long_name, + 'var_name': coord.var_name, + 'units': coord.units, + 'attributes': coord.attributes, + 'coord_system': copy.deepcopy(coord.coord_system)} + if issubclass(cls, DimCoord): + # DimCoord introduces an extra constructor keyword. + kwargs['circular'] = getattr(coord, 'circular', False) + return cls(**kwargs) + + def _sanitise_array(self, src, ndmin): + if _lazy.is_lazy_data(src): + # Lazy data : just ensure ndmin requirement. + ndims_missing = ndmin - src.ndim + if ndims_missing <= 0: + result = src + else: + extended_shape = tuple([1] * ndims_missing + list(src.shape)) + result = src.reshape(extended_shape) + else: + # Real data : a few more things to do in this case. + # Ensure the array is writeable. + # NB. Returns the *same object* if src is already writeable. + result = np.require(src, requirements='W') + # Ensure the array has enough dimensions. + # NB. Returns the *same object* if result.ndim >= ndmin + result = np.array(result, ndmin=ndmin, copy=False) + # We don't need to copy the data, but we do need to have our + # own view so we can control the shape, etc. + result = result.view() + return result + + def _points_getter(self): + """The coordinate points values as a NumPy array.""" + return self._points_dm.data.view() + + def _points_setter(self, points): + # Set the points to a new array - as long as it's the same shape. + + # Ensure points has an ndmin of 1 and is either a numpy or lazy array. + # This will avoid Scalar coords with points of shape () rather + # than the desired (1,). + points = self._sanitise_array(points, 1) + + # Set or update DataManager. + if self._points_dm is None: + self._points_dm = DataManager(points) + else: + self._points_dm.data = points + + points = property(_points_getter, _points_setter) + + def _bounds_getter(self): + """ + The coordinate bounds values, as a NumPy array, + or None if no bound values are defined. + + .. note:: The shape of the bound array should be: ``points.shape + + (n_bounds, )``. + + """ + bounds = None + if self.has_bounds(): + bounds = self._bounds_dm.data.view() + return bounds - @abstractproperty - def bounds(self): - """Property containing the bound values as a numpy array""" + def _bounds_setter(self, bounds): + # Ensure the bounds are a compatible shape. + if bounds is None: + self._bounds_dm = None + else: + bounds = self._sanitise_array(bounds, 2) + if self.shape != bounds.shape[:-1]: + raise ValueError("Bounds shape must be compatible with points " + "shape.") + if not self.has_bounds() \ + or self.core_bounds().shape != bounds.shape: + # Construct a new bounds DataManager. + self._bounds_dm = DataManager(bounds) + else: + self._bounds_dm.data = bounds + + bounds = property(_bounds_getter, _bounds_setter) + + def lazy_points(self): + """ + Return a lazy array representing the coord points. + + Accessing this method will never cause the points values to be loaded. + Similarly, calling methods on, or indexing, the returned Array + will not cause the coord to have loaded points. + + If the data have already been loaded for the coord, the returned + Array will be a new lazy array wrapper. + + Returns: + A lazy array, representing the coord points array. + + """ + return self._points_dm.lazy_data() + + def lazy_bounds(self): + """ + Return a lazy array representing the coord bounds. + + Accessing this method will never cause the bounds values to be loaded. + Similarly, calling methods on, or indexing, the returned Array + will not cause the coord to have loaded bounds. + + If the data have already been loaded for the coord, the returned + Array will be a new lazy array wrapper. + + Returns: + A lazy array representing the coord bounds array or `None` if the + coord does not have bounds. + + """ + lazy_bounds = None + if self.has_bounds(): + lazy_bounds = self._bounds_dm.lazy_data() + return lazy_bounds + + def core_points(self): + """ + The points array at the core of this coord, which may be a NumPy array + or a dask array. + + """ + result = self._points_dm.core_data() + if not _lazy.is_lazy_data(result): + result = result.view() + return result + + def core_bounds(self): + """ + The points array at the core of this coord, which may be a NumPy array + or a dask array. + + """ + result = None + if self.has_bounds(): + result = self._bounds_dm.core_data() + if not _lazy.is_lazy_data(result): + result = result.view() + return result + + def has_lazy_points(self): + """ + Return a boolean indicating whether the coord's points array is a + lazy dask array or not. + + """ + return self._points_dm.has_lazy_data() + + def has_lazy_bounds(self): + """ + Return a boolean indicating whether the coord's bounds array is a + lazy dask array or not. + + """ + result = False + if self.has_bounds(): + result = self._bounds_dm.has_lazy_data() + return result def _repr_other_metadata(self): fmt = '' @@ -469,25 +764,29 @@ def _repr_other_metadata(self): def _str_dates(self, dates_as_numbers): date_obj_array = self.units.num2date(dates_as_numbers) kwargs = {'separator': ', ', 'prefix': ' '} - try: - # With NumPy 1.7 we need to ask for 'str' formatting. - result = np.core.arrayprint.array2string( - date_obj_array, formatter={'numpystr': str}, **kwargs) - except TypeError: - # But in 1.6 we don't need to ask, and the option doesn't - # even exist! - result = np.core.arrayprint.array2string(date_obj_array, **kwargs) - return result + return np.core.arrayprint.array2string(date_obj_array, + formatter={'all': str}, + **kwargs) def __str__(self): if self.units.is_time_reference(): fmt = '{cls}({points}{bounds}' \ ', standard_name={self.standard_name!r}' \ ', calendar={self.units.calendar!r}{other_metadata})' - points = self._str_dates(self.points) + if self.units.is_long_time_interval(): + # A time unit with a long time interval ("months" or "years") + # cannot be converted to a date using `num2date` so gracefully + # fall back to printing points as numbers, not datetimes. + points = self.points + else: + points = self._str_dates(self.points) bounds = '' - if self.bounds is not None: - bounds = ', bounds=' + self._str_dates(self.bounds) + if self.has_bounds(): + if self.units.is_long_time_interval(): + bounds_vals = self.bounds + else: + bounds_vals = self._str_dates(self.bounds) + bounds = ', bounds={vals}'.format(vals=bounds_vals) result = fmt.format(self=self, cls=type(self).__name__, points=points, bounds=bounds, other_metadata=self._repr_other_metadata()) @@ -500,7 +799,7 @@ def __repr__(self): ', standard_name={self.standard_name!r}, units={self.units!r}' \ '{other_metadata})' bounds = '' - if self.bounds is not None: + if self.has_bounds(): bounds = ', bounds=' + repr(self.bounds) result = fmt.format(self=self, cls=type(self).__name__, bounds=bounds, @@ -521,14 +820,13 @@ def __eq__(self, other): eq = iris.util.array_equal(self.points, other.points) # bounds comparison if eq: - if self.bounds is not None and other.bounds is not None: + if self.has_bounds() and other.has_bounds(): eq = iris.util.array_equal(self.bounds, other.bounds) else: eq = self.bounds is None and other.bounds is None return eq - # Must supply __ne__, Python does not defer to __eq__ for negative equality def __ne__(self, other): result = self.__eq__(other) if result is not NotImplemented: @@ -540,9 +838,18 @@ def _as_defn(self): self.units, self.attributes, self.coord_system) return defn + # Must supply __hash__ as Python 3 does not enable it if __eq__ is defined. + # NOTE: Violates "objects which compare equal must have the same hash". + # We ought to remove this, as equality of two coords can *change*, so they + # really should not be hashable. + # However, current code needs it, e.g. so we can put them in sets. + # Fixing it will require changing those uses. See #962 and #1772. + def __hash__(self): + return hash(id(self)) + def __binary_operator__(self, other, mode_constant): """ - Common code which is called by add, sub, mult and div + Common code which is called by add, sub, mul and div Mode constant is one of ADD, SUB, MUL, DIV, RDIV @@ -557,37 +864,42 @@ def __binary_operator__(self, other, mode_constant): """ if isinstance(other, Coord): - raise iris.exceptions.NotYetImplementedError( - 'coord %s coord' % Coord._MODE_SYMBOL[mode_constant]) + emsg = 'coord {} coord'.format(Coord._MODE_SYMBOL[mode_constant]) + raise iris.exceptions.NotYetImplementedError(emsg) elif isinstance(other, (int, float, np.number)): + points = self._points_dm.core_data() if mode_constant == Coord._MODE_ADD: - points = self.points + other + new_points = points + other elif mode_constant == Coord._MODE_SUB: - points = self.points - other + new_points = points - other elif mode_constant == Coord._MODE_MUL: - points = self.points * other + new_points = points * other elif mode_constant == Coord._MODE_DIV: - points = self.points / other + new_points = points / other elif mode_constant == Coord._MODE_RDIV: - points = other / self.points + new_points = other / points + + if self.has_bounds(): + bounds = self._bounds_dm.core_data() - if self.bounds is not None: if mode_constant == Coord._MODE_ADD: - bounds = self.bounds + other + new_bounds = bounds + other elif mode_constant == Coord._MODE_SUB: - bounds = self.bounds - other + new_bounds = bounds - other elif mode_constant == Coord._MODE_MUL: - bounds = self.bounds * other + new_bounds = bounds * other elif mode_constant == Coord._MODE_DIV: - bounds = self.bounds / other + new_bounds = bounds / other elif mode_constant == Coord._MODE_RDIV: - bounds = other / self.bounds + new_bounds = other / bounds + else: - bounds = None - new_coord = self.copy(points, bounds) + new_bounds = None + new_coord = self.copy(new_points, new_bounds) return new_coord + else: return NotImplemented @@ -622,8 +934,8 @@ def __rmul__(self, other): return self * other def __neg__(self): - return self.copy(-self.points, -self.bounds if self.bounds is not - None else None) + return self.copy(-self.core_points(), + -self.core_bounds() if self.has_bounds() else None) def convert_units(self, unit): """ @@ -643,10 +955,32 @@ def convert_units(self, unit): """ # If the coord has units convert the values in points (and bounds if # present). - if not self.units.is_unknown(): - self.points = self.units.convert(self.points, unit) - if self.bounds is not None: - self.bounds = self.units.convert(self.bounds, unit) + if self.units.is_unknown(): + raise iris.exceptions.UnitConversionError( + 'Cannot convert from unknown units. ' + 'The "coord.units" attribute may be set directly.') + if self.has_lazy_points() or self.has_lazy_bounds(): + # Make fixed copies of old + new units for a delayed conversion. + old_unit = self.units + new_unit = unit + + # Define a delayed conversion operation (i.e. a callback). + def pointwise_convert(values): + return old_unit.convert(values, new_unit) + + if self.has_lazy_points(): + new_points = _lazy.lazy_elementwise(self.lazy_points(), + pointwise_convert) + else: + new_points = self.units.convert(self.points, unit) + self.points = new_points + if self.has_bounds(): + if self.has_lazy_bounds(): + new_bounds = _lazy.lazy_elementwise(self.lazy_bounds(), + pointwise_convert) + else: + new_bounds = self.units.convert(self.bounds, unit) + self.bounds = new_bounds self.units = unit def cells(self): @@ -661,22 +995,106 @@ def cells(self): """ return _CellIterator(self) - def _sanity_check_contiguous(self): - if self.ndim != 1: - raise iris.exceptions.CoordinateMultiDimError( - 'Invalid operation for {!r}. Contiguous bounds are not defined' - ' for multi-dimensional coordinates.'.format(self.name())) - if self.nbounds != 2: - raise ValueError( - 'Invalid operation for {!r}, with {} bounds. Contiguous bounds' - ' are only defined for coordinates with 2 bounds.'.format( - self.name(), self.nbounds)) + def _sanity_check_bounds(self): + if self.ndim == 1: + if self.nbounds != 2: + raise ValueError('Invalid operation for {!r}, with {} ' + 'bound(s). Contiguous bounds are only ' + 'defined for 1D coordinates with 2 ' + 'bounds.'.format(self.name(), self.nbounds)) + elif self.ndim == 2: + if self.nbounds != 4: + raise ValueError('Invalid operation for {!r}, with {} ' + 'bound(s). Contiguous bounds are only ' + 'defined for 2D coordinates with 4 ' + 'bounds.'.format(self.name(), self.nbounds)) + else: + raise ValueError('Invalid operation for {!r}. Contiguous bounds ' + 'are not defined for coordinates with more than ' + '2 dimensions.'.format(self.name())) + + def _discontiguity_in_bounds(self, rtol=1e-5, atol=1e-8): + """ + Checks that the bounds of the coordinate are contiguous. + + Kwargs: + * rtol: (float) + Relative tolerance that is used when checking contiguity. Defaults + to 1e-5. + * atol: (float) + Absolute tolerance that is used when checking contiguity. Defaults + to 1e-8. + + Returns: + * contiguous: (boolean) + True if there are no discontiguities. + * diffs: (array or tuple of arrays) + The diffs along the bounds of the coordinate. If self is a 2D + coord of shape (Y, X), a tuple of arrays is returned, where the + first is an array of differences along the x-axis, of the shape + (Y, X-1) and the second is an array of differences along the + y-axis, of the shape (Y-1, X). + + """ + self._sanity_check_bounds() + + if self.ndim == 1: + contiguous = np.allclose(self.bounds[1:, 0], + self.bounds[:-1, 1], + rtol=rtol, atol=atol) + diffs = np.abs(self.bounds[:-1, 1] - self.bounds[1:, 0]) + + elif self.ndim == 2: + def mod360_adjust(compare_axis): + bounds = self.bounds.copy() + + if compare_axis == 'x': + upper_bounds = bounds[:, :-1, 1] + lower_bounds = bounds[:, 1:, 0] + elif compare_axis == 'y': + upper_bounds = bounds[:-1, :, 3] + lower_bounds = bounds[1:, :, 0] + + if self.name() in ['longitude', 'grid_longitude']: + # If longitude, adjust for longitude wrapping + diffs = upper_bounds - lower_bounds + index = diffs > 180 + if index.any(): + sign = np.sign(diffs) + modification = (index.astype(int) * 360) * sign + upper_bounds -= modification + + diffs_between_cells = np.abs(upper_bounds - lower_bounds) + cell_size = lower_bounds - upper_bounds + diffs_along_axis = diffs_between_cells > (atol + + rtol * cell_size) + + points_close_enough = diffs_along_axis <= (atol + + rtol * cell_size) + contiguous_along_axis = np.all(points_close_enough) + return diffs_along_axis, contiguous_along_axis + + diffs_along_x, match_cell_x1 = mod360_adjust(compare_axis='x') + diffs_along_y, match_cell_y1 = mod360_adjust(compare_axis='y') + + contiguous = match_cell_x1 and match_cell_y1 + diffs = (diffs_along_x, diffs_along_y) + + return contiguous, diffs def is_contiguous(self, rtol=1e-05, atol=1e-08): """ Return True if, and only if, this Coord is bounded with contiguous bounds to within the specified relative and absolute tolerances. + 1D coords are contiguous if the upper bound of a cell aligns, + within a tolerance, to the lower bound of the next cell along. + + 2D coords, with 4 bounds, are contiguous if the lower right corner of + each cell aligns with the lower left corner of the cell to the right of + it, and the upper left corner of each cell aligns with the lower left + corner of the cell above it. + Args: * rtol: @@ -688,34 +1106,50 @@ def is_contiguous(self, rtol=1e-05, atol=1e-08): Boolean. """ - if self.bounds is not None: - self._sanity_check_contiguous() - return np.allclose(self.bounds[1:, 0], self.bounds[:-1, 1], - rtol=rtol, atol=atol) + if self.has_bounds(): + contiguous, _ = self._discontiguity_in_bounds(rtol=rtol, atol=atol) else: - return False + contiguous = False + return contiguous def contiguous_bounds(self): """ - Returns the N+1 bound values for a contiguous bounded coordinate - of length N. + Returns the N+1 bound values for a contiguous bounded 1D coordinate + of length N, or the (N+1, M+1) bound values for a contiguous bounded 2D + coordinate of shape (N, M). + + Only 1D or 2D coordinates are supported. .. note:: - If the coordinate is does not have bounds, this method will + If the coordinate has bounds, this method assumes they are + contiguous. + + If the coordinate is 1D and does not have bounds, this method will return bounds positioned halfway between the coordinate's points. + If the coordinate is 2D and does not have bounds, an error will be + raised. + """ - if self.bounds is None: - warnings.warn('Coordinate {!r} is not bounded, guessing ' - 'contiguous bounds.'.format(self.name())) - bounds = self._guess_bounds() + if not self.has_bounds(): + if self.ndim == 1: + warnings.warn('Coordinate {!r} is not bounded, guessing ' + 'contiguous bounds.'.format(self.name())) + bounds = self._guess_bounds() + elif self.ndim == 2: + raise ValueError('2D coordinate {!r} is not bounded. Guessing ' + 'bounds of 2D coords is not currently ' + 'supported.'.format(self.name())) else: - self._sanity_check_contiguous() + self._sanity_check_bounds() bounds = self.bounds - c_bounds = np.resize(bounds[:, 0], bounds.shape[0] + 1) - c_bounds[-1] = bounds[-1, 1] + if self.ndim == 1: + c_bounds = np.resize(bounds[:, 0], bounds.shape[0] + 1) + c_bounds[-1] = bounds[-1, 1] + elif self.ndim == 2: + c_bounds = _get_2d_coord_bound_grid(bounds) return c_bounds def is_monotonic(self): @@ -731,8 +1165,8 @@ def is_monotonic(self): if not iris.util.monotonic(self.points, strict=True): return False - if self.bounds is not None: - for b_index in xrange(self.nbounds): + if self.has_bounds(): + for b_index in range(self.nbounds): if not iris.util.monotonic(self.bounds[..., b_index], strict=True): return False @@ -769,7 +1203,7 @@ def is_compatible(self, other, ignore=None): if compatible: common_keys = set(self.attributes).intersection(other.attributes) if ignore is not None: - if isinstance(ignore, basestring): + if isinstance(ignore, six.string_types): ignore = (ignore,) common_keys = common_keys.difference(ignore) for key in common_keys: @@ -782,10 +1216,22 @@ def is_compatible(self, other, ignore=None): @property def dtype(self): """ - Abstract property which returns the Numpy data type of the Coordinate. + The NumPy dtype of the coord, as specified by its points. """ - return self.points.dtype + return self._points_dm.dtype + + @property + def bounds_dtype(self): + """ + The NumPy dtype of the coord's bounds. Will be `None` if the coord + does not have bounds. + + """ + result = None + if self.has_bounds(): + result = self._bounds_dm.dtype + return result @property def ndim(self): @@ -794,7 +1240,7 @@ def ndim(self): bounded dimension). """ - return len(self.shape) + return self._points_dm.ndim @property def nbounds(self): @@ -803,19 +1249,18 @@ def nbounds(self): """ nbounds = 0 - if self.bounds is not None: - nbounds = self.bounds.shape[-1] + if self.has_bounds(): + nbounds = self._bounds_dm.shape[-1] return nbounds def has_bounds(self): - return self.bounds is not None + """Return a boolean indicating whether the coord has a bounds array.""" + return self._bounds_dm is not None @property def shape(self): """The fundamental shape of the Coord, expressed as a tuple.""" - # Access the underlying _points attribute to avoid triggering - # a deferred load unnecessarily. - return self._points.shape + return self._points_dm.shape def cell(self, index): """ @@ -827,7 +1272,14 @@ def cell(self, index): If `iris.FUTURE.cell_datetime_objects` is True, then this method will return Cell objects whose `points` and `bounds` attributes contain either datetime.datetime instances or - netcdftime.datetime instances (depending on the calendar). + cftime.datetime instances (depending on the calendar). + + .. deprecated:: 2.0.0 + + The option `iris.FUTURE.cell_datetime_objects` is deprecated and + will be removed in a future release; it is now set to True by + default. Please update your code to support using cells as + datetime objects. """ index = iris.util._build_full_slice_given_keys(index, self.ndim) @@ -838,7 +1290,7 @@ def cell(self, index): 'point to create a cell with.' % (index, )) bound = None - if self.bounds is not None: + if self.has_bounds(): bound = tuple(np.array(self.bounds[index], ndmin=1).flatten()) if iris.FUTURE.cell_datetime_objects: @@ -846,40 +1298,48 @@ def cell(self, index): point = self.units.num2date(point) if bound is not None: bound = self.units.num2date(bound) + else: + wmsg = ("disabling cells as datetime objects is deprecated " + "behaviour. " + "Please update your code to support using cells as " + "datetime objects." + "See the userguide section 2.2.1 for examples of this.") + warn_deprecated(wmsg) return Cell(point, bound) def collapsed(self, dims_to_collapse=None): """ - Returns a copy of this coordinate which has been collapsed along + Returns a copy of this coordinate, which has been collapsed along the specified dimensions. Replaces the points & bounds with a simple bounded region. - """ + import dask.array as da + # Ensure dims_to_collapse is a tuple to be able to pass + # through to numpy if isinstance(dims_to_collapse, (int, np.integer)): - dims_to_collapse = [dims_to_collapse] + dims_to_collapse = (dims_to_collapse, ) + if isinstance(dims_to_collapse, list): + dims_to_collapse = tuple(dims_to_collapse) - if dims_to_collapse is not None and \ - set(range(self.ndim)) != set(dims_to_collapse): - raise ValueError('Cannot partially collapse a coordinate (%s).' - % self.name()) - - if np.issubdtype(self.dtype, np.str): + if np.issubdtype(self.dtype, np.str_): # Collapse the coordinate by serializing the points and # bounds as strings. - serialize = lambda x: '|'.join([str(i) for i in x.flatten()]) + def serialize(x): + return '|'.join([str(i) for i in x.flatten()]) bounds = None - if self.bounds is not None: - shape = self.bounds.shape[1:] + string_type_fmt = 'S{}' if six.PY2 else 'U{}' + if self.has_bounds(): + shape = self._bounds_dm.shape[1:] bounds = [] for index in np.ndindex(shape): index_slice = (slice(None),) + tuple(index) bounds.append(serialize(self.bounds[index_slice])) - dtype = np.dtype('S{}'.format(max(map(len, bounds)))) + dtype = np.dtype(string_type_fmt.format(max(map(len, bounds)))) bounds = np.array(bounds, dtype=dtype).reshape((1,) + shape) points = serialize(self.points) - dtype = np.dtype('S{}'.format(len(points))) + dtype = np.dtype(string_type_fmt.format(len(points))) # Create the new collapsed coordinate. coord = self.copy(points=np.array(points, dtype=dtype), bounds=bounds) @@ -894,18 +1354,20 @@ def collapsed(self, dims_to_collapse=None): 'Metadata may not be fully descriptive for {!r}.' warnings.warn(msg.format(self.name())) - # Create bounds for the new collapsed coordinate. - item = self.bounds if self.bounds is not None else self.points - lower, upper = np.min(item), np.max(item) - bounds_dtype = item.dtype - bounds = [lower, upper] - # Create points for the new collapsed coordinate. - points_dtype = self.points.dtype - points = [(lower + upper) * 0.5] + # Determine the array library for stacking + al = da if self.has_bounds() \ + and _lazy.is_lazy_data(self.core_bounds()) else np + + item = al.concatenate(self.core_bounds()) if self.has_bounds() \ + else self.core_points() + + # Calculate the bounds and points along the right dims + bounds = al.stack([item.min(axis=dims_to_collapse), + item.max(axis=dims_to_collapse)]).T + points = al.array(bounds.sum(axis=-1) * 0.5, dtype=self.dtype) # Create the new collapsed coordinate. - coord = self.copy(points=np.array(points, dtype=points_dtype), - bounds=np.array(bounds, dtype=bounds_dtype)) + coord = self.copy(points=points, bounds=bounds) return coord def _guess_bounds(self, bound_position=0.5): @@ -914,8 +1376,9 @@ def _guess_bounds(self, bound_position=0.5): Kwargs: - * bound_position - The desired position of the bounds relative to the - position of the points. + * bound_position: + The desired position of the bounds relative to the position + of the points. Returns: A numpy array of shape (len(self.points), 2). @@ -924,6 +1387,22 @@ def _guess_bounds(self, bound_position=0.5): This method only works for coordinates with ``coord.ndim == 1``. + .. note:: + + If `iris.FUTURE.clip_latitudes` is True, then this method + will clip the coordinate bounds to the range [-90, 90] when: + + - it is a `latitude` or `grid_latitude` coordinate, + - the units are degrees, + - all the points are in the range [-90, 90]. + + .. deprecated:: 2.0.0 + + The `iris.FUTURE.clip_latitudes` option is now deprecated + and is set to True by default. Please remove code which + relies on coordinate bounds being outside the range + [-90, 90]. + """ # XXX Consider moving into DimCoord # ensure we have monotonic points @@ -938,20 +1417,40 @@ def _guess_bounds(self, bound_position=0.5): raise ValueError('Cannot guess bounds for a coordinate of length ' '1.') - if self.bounds is not None: + if self.has_bounds(): raise ValueError('Coord already has bounds. Remove the bounds ' 'before guessing new ones.') - diffs = np.diff(self.points) - - diffs = np.insert(diffs, 0, diffs[0]) - diffs = np.append(diffs, diffs[-1]) + if getattr(self, 'circular', False): + points = np.empty(self.shape[0] + 2) + points[1:-1] = self.points + direction = 1 if self.points[-1] > self.points[0] else -1 + points[0] = self.points[-1] - (self.units.modulus * direction) + points[-1] = self.points[0] + (self.units.modulus * direction) + diffs = np.diff(points) + else: + diffs = np.diff(self.points) + diffs = np.insert(diffs, 0, diffs[0]) + diffs = np.append(diffs, diffs[-1]) min_bounds = self.points - diffs[:-1] * bound_position max_bounds = self.points + diffs[1:] * (1 - bound_position) bounds = np.array([min_bounds, max_bounds]).transpose() + if iris.FUTURE.clip_latitudes: + if (self.name() in ('latitude', 'grid_latitude') and + self.units == 'degree'): + points = self.points + if (points >= -90).all() and (points <= 90).all(): + np.clip(bounds, -90, 90, out=bounds) + else: + wmsg = ("guessing latitude bounds outside of [-90, 90] is " + "deprecated behaviour. " + "All latitude points will be clipped to the range " + "[-90, 90].") + warn_deprecated(wmsg) + return bounds def guess_bounds(self, bound_position=0.5): @@ -969,8 +1468,9 @@ def guess_bounds(self, bound_position=0.5): Kwargs: - * bound_position - The desired position of the bounds relative to the - position of the points. + * bound_position: + The desired position of the bounds relative to the position + of the points. .. note:: @@ -983,6 +1483,22 @@ def guess_bounds(self, bound_position=0.5): produce unexpected results : In such cases you should assign suitable values directly to the bounds property, instead. + .. note:: + + If `iris.FUTURE.clip_latitudes` is True, then this method + will clip the coordinate bounds to the range [-90, 90] when: + + - it is a `latitude` or `grid_latitude` coordinate, + - the units are degrees, + - all the points are in the range [-90, 90]. + + .. deprecated:: 2.0.0 + + The `iris.FUTURE.clip_latitudes` option is now deprecated + and is set to True by default. Please remove code which + relies on coordinate bounds being outside the range + [-90, 90]. + """ self.bounds = self._guess_bounds(bound_position) @@ -1037,6 +1553,14 @@ def nearest_neighbour_index(self, point): Only works for one-dimensional coordinates. + For example: + + >>> cube = iris.load_cube(iris.sample_data_path('ostia_monthly.nc')) + >>> cube.coord('latitude').nearest_neighbour_index(0) + 9 + >>> cube.coord('longitude').nearest_neighbour_index(10) + 12 + .. note:: If the coordinate contains bounds, these will be used to determine the nearest neighbour instead of the point values. @@ -1066,14 +1590,21 @@ def nearest_neighbour_index(self, point): # or if two are equally close, return the lowest index if self.has_bounds(): # make bounds ranges complete+separate, so point is in at least one + increasing = self.bounds[0, 1] > self.bounds[0, 0] bounds = bounds.copy() # sort the bounds cells by their centre values sort_inds = np.argsort(np.mean(bounds, axis=1)) bounds = bounds[sort_inds] # replace all adjacent bounds with their averages - mid_bounds = 0.5 * (bounds[:-1, 1] + bounds[1:, 0]) - bounds[:-1, 1] = mid_bounds - bounds[1:, 0] = mid_bounds + if increasing: + mid_bounds = 0.5 * (bounds[:-1, 1] + bounds[1:, 0]) + bounds[:-1, 1] = mid_bounds + bounds[1:, 0] = mid_bounds + else: + mid_bounds = 0.5 * (bounds[:-1, 0] + bounds[1:, 1]) + bounds[:-1, 0] = mid_bounds + bounds[1:, 1] = mid_bounds + # if point lies beyond either end, fix the end cell to include it bounds[0, 0] = min(point, bounds[0, 0]) bounds[-1, 1] = max(point, bounds[-1, 1]) @@ -1126,7 +1657,7 @@ def xml_element(self, doc): if self.attributes: attributes_element = doc.createElement('attributes') - for name in sorted(self.attributes.iterkeys()): + for name in sorted(six.iterkeys(self.attributes)): attribute_element = doc.createElement('attribute') attribute_element.setAttribute('name', name) attribute_element.setAttribute('value', @@ -1146,7 +1677,7 @@ def xml_element(self, doc): else: element.setAttribute('points', iris.util.format_array(self.points)) - if self.bounds is not None: + if self.has_bounds(): if hasattr(self.bounds, 'to_xml_attr'): element.setAttribute('bounds', self.bounds.to_xml_attr()) else: @@ -1157,13 +1688,20 @@ def xml_element(self, doc): def _xml_id(self): # Returns a consistent, unique string identifier for this coordinate. - unique_value = (self.standard_name, self.long_name, self.units, - tuple(sorted(self.attributes.items())), - self.coord_system) + unique_value = b'' + if self.standard_name: + unique_value += self.standard_name.encode('utf-8') + unique_value += b'\0' + if self.long_name: + unique_value += self.long_name.encode('utf-8') + unique_value += b'\0' + unique_value += str(self.units).encode('utf-8') + b'\0' + for k, v in sorted(self.attributes.items()): + unique_value += (str(k) + ':' + str(v)).encode('utf-8') + b'\0' + unique_value += str(self.coord_system).encode('utf-8') + b'\0' # Mask to ensure consistency across Python versions & platforms. - crc = zlib.crc32(str(unique_value)) & 0xffffffff - # 'L' added by 32-bit systems. - return hex(crc).lstrip('0x').rstrip('L') + crc = zlib.crc32(unique_value) & 0xffffffff + return '%08x' % (crc, ) def _value_type_name(self): """ @@ -1171,12 +1709,23 @@ def _value_type_name(self): values. """ - values = self.points - value_type_name = values.dtype.name - if self.points.dtype.kind == 'S': + dtype = self.core_points().dtype + kind = dtype.kind + if kind in 'SU': + # Establish the basic type name for 'string' type data. + # N.B. this means "unicode" in Python3, and "str" in Python2. value_type_name = 'string' - elif self.points.dtype.kind == 'U': - value_type_name = 'unicode' + + # Override this if not the 'native' string type. + if six.PY3: + if kind == 'S': + value_type_name = 'bytes' + else: + if kind == 'U': + value_type_name = 'unicode' + else: + value_type_name = dtype.name + return value_type_name @@ -1185,16 +1734,6 @@ class DimCoord(Coord): A coordinate that is 1D, numeric, and strictly monotonic. """ - @staticmethod - def from_coord(coord): - """Create a new DimCoord from the given coordinate.""" - return DimCoord(coord.points, standard_name=coord.standard_name, - long_name=coord.long_name, var_name=coord.var_name, - units=coord.units, bounds=coord.bounds, - attributes=coord.attributes, - coord_system=copy.deepcopy(coord.coord_system), - circular=getattr(coord, 'circular', False)) - @classmethod def from_regular(cls, zeroth, step, count, standard_name=None, long_name=None, var_name=None, units='1', attributes=None, @@ -1223,33 +1762,24 @@ def from_regular(cls, zeroth, step, count, standard_name=None, bounds values will be defined. Defaults to False. """ - coord = DimCoord.__new__(cls) - - coord.standard_name = standard_name - coord.long_name = long_name - coord.var_name = var_name - coord.units = units - coord.attributes = attributes - coord.coord_system = coord_system - coord.circular = circular - - points = (zeroth+step) + step*np.arange(count, dtype=np.float32) + points = (zeroth + step) + step * np.arange(count, dtype=np.float32) + _, regular = points_step(points) + if not regular: + points = (zeroth + step) + step * np.arange(count, + dtype=np.float64) points.flags.writeable = False - coord._points = points - if not is_regular(coord) and count > 1: - points = (zeroth+step) + step*np.arange(count, dtype=np.float64) - points.flags.writeable = False - coord._points = points if with_bounds: delta = 0.5 * step bounds = np.concatenate([[points - delta], [points + delta]]).T bounds.flags.writeable = False - coord._bounds = bounds else: - coord._bounds = None + bounds = None - return coord + return cls(points, standard_name=standard_name, + long_name=long_name, var_name=var_name, units=units, + bounds=bounds, attributes=attributes, + coord_system=coord_system, circular=circular) def __init__(self, points, standard_name=None, long_name=None, var_name=None, units='1', bounds=None, attributes=None, @@ -1259,14 +1789,37 @@ def __init__(self, points, standard_name=None, long_name=None, read-only points and bounds. """ - Coord.__init__(self, points, standard_name=standard_name, - long_name=long_name, var_name=var_name, - units=units, bounds=bounds, attributes=attributes, - coord_system=coord_system) + super(DimCoord, self).__init__(points, standard_name=standard_name, + long_name=long_name, var_name=var_name, + units=units, bounds=bounds, + attributes=attributes, + coord_system=coord_system) #: Whether the coordinate wraps by ``coord.units.modulus``. self.circular = bool(circular) + def __deepcopy__(self, memo): + """ + coord.__deepcopy__() -> Deep copy of coordinate. + + Used if copy.deepcopy is called on a coordinate. + + """ + new_coord = copy.deepcopy(super(DimCoord, self), memo) + # Ensure points and bounds arrays are read-only. + new_coord._points_dm.data.flags.writeable = False + if new_coord._bounds_dm is not None: + new_coord._bounds_dm.data.flags.writeable = False + return new_coord + + def copy(self, points=None, bounds=None): + new_coord = super(DimCoord, self).copy(points=points, bounds=bounds) + # Make the arrays read-only. + new_coord._points_dm.data.flags.writeable = False + if bounds is not None: + new_coord._bounds_dm.data.flags.writeable = False + return new_coord + def __eq__(self, other): # TODO investigate equality of AuxCoord and DimCoord if circular is # False. @@ -1278,6 +1831,14 @@ def __eq__(self, other): # The __ne__ operator from Coord implements the not __eq__ method. + # For Python 3, we must explicitly re-implement the '__hash__' method, as + # defining an '__eq__' has blocked its inheritance. See ... + # https://docs.python.org/3.1/reference/datamodel.html#object.__hash__ + # "If a class that overrides __eq__() needs to retain the + # implementation of __hash__() from a parent class, the interpreter + # must be told this explicitly". + __hash__ = Coord.__hash__ + def __getitem__(self, key): coord = super(DimCoord, self).__getitem__(key) coord.circular = self.circular and coord.shape == self.shape @@ -1301,65 +1862,72 @@ def _repr_other_metadata(self): result += ', circular=%r' % self.circular return result - @property - def points(self): - """The local points values as a read-only NumPy array.""" - points = self._points.view() - return points - - @points.setter - def points(self, points): - points = np.array(points, ndmin=1) - # If points are already defined for this coordinate, - if hasattr(self, '_points') and self._points is not None: - # Check that setting these points wouldn't change self.shape - if points.shape != self.shape: - raise ValueError("New points shape must match existing points " - "shape.") + def _new_points_requirements(self, points): + """ + Confirm that a new set of coord points adheres to the requirements for + :class:`~iris.coords.DimCoord` points, being: + * points are scalar or 1D, + * points are numeric, and + * points are monotonic. - # Checks for 1d, numeric, monotonic - if points.ndim != 1: - raise ValueError('The points array must be 1-dimensional.') + """ + if points.ndim not in (0, 1): + raise ValueError( + 'The points array must be scalar or 1-dimensional.') if not np.issubdtype(points.dtype, np.number): raise ValueError('The points array must be numeric.') - if len(points) > 1 and not iris.util.monotonic(points, strict=True): + if points.size > 1 and not iris.util.monotonic(points, strict=True): raise ValueError('The points array must be strictly monotonic.') - # Make the array read-only. - points.flags.writeable = False - self._points = points + def _points_setter(self, points): + # DimCoord always realises the points, to allow monotonicity checks. + # Ensure it is an actual array, and also make our own copy so that we + # can make it read-only. + points = _lazy.as_concrete_data(points) + points = np.array(points) - @property - def bounds(self): - """ - The bounds values as a read-only NumPy array, or None if no - bounds have been set. + # Check validity requirements for dimension-coordinate points. + self._new_points_requirements(points) + + # Invoke the generic points setter. + super(DimCoord, self)._points_setter(points) + + if self._points_dm is not None: + # Re-fetch the core array, as the super call may replace it. + points = self._points_dm.core_data() + # N.B. always a *real* array, as we realised 'points' at the start. + + # Make the array read-only. + points.flags.writeable = False + + points = property(Coord._points_getter, _points_setter) + def _new_bounds_requirements(self, bounds): """ - bounds = None - if self._bounds is not None: - bounds = self._bounds.view() - return bounds + Confirm that a new set of coord bounds adheres to the requirements for + :class:`~iris.coords.DimCoord` bounds, being: + * bounds are compatible in shape with the points + * bounds are numeric, and + * bounds are monotonic in the first dimension. - @bounds.setter - def bounds(self, bounds): - if bounds is not None: - # Ensure the bounds are a compatible shape. - bounds = np.array(bounds, ndmin=2) - if self.shape != bounds.shape[:-1]: - raise ValueError( - "The shape of the bounds array should be " - "points.shape + (n_bounds,)") - # Checks for numeric and monotonic - if not np.issubdtype(bounds.dtype, np.number): - raise ValueError('The bounds array must be numeric.') + """ + # Ensure the bounds are a compatible shape. + if self.shape != bounds.shape[:-1] and \ + not (self.shape == (1,) and bounds.ndim == 1): + raise ValueError( + "The shape of the bounds array should be " + "points.shape + (n_bounds,)") + # Checks for numeric and monotonic. + if not np.issubdtype(bounds.dtype, np.number): + raise ValueError('The bounds array must be numeric.') + if bounds.ndim > 1: n_bounds = bounds.shape[-1] n_points = bounds.shape[0] if n_points > 1: directions = set() - for b_index in xrange(n_bounds): + for b_index in range(n_bounds): monotonic, direction = iris.util.monotonic( bounds[:, b_index], strict=True, return_direction=True) if not monotonic: @@ -1371,10 +1939,27 @@ def bounds(self, bounds): raise ValueError('The direction of monotonicity must be ' 'consistent across all bounds') + def _bounds_setter(self, bounds): + if bounds is not None: + # Ensure we have a realised array of new bounds values. + bounds = _lazy.as_concrete_data(bounds) + bounds = np.array(bounds) + + # Check validity requirements for dimension-coordinate bounds. + self._new_bounds_requirements(bounds) + + # Invoke the generic bounds setter. + super(DimCoord, self)._bounds_setter(bounds) + + if self._bounds_dm is not None: + # Re-fetch the core array, as the super call may replace it. + bounds = self._bounds_dm.core_data() + # N.B. always a *real* array, as we realised 'bounds' at the start. + # Ensure the array is read-only. bounds.flags.writeable = False - self._bounds = bounds + bounds = property(Coord._bounds_getter, _bounds_setter) def is_monotonic(self): return True @@ -1388,84 +1973,218 @@ def xml_element(self, doc): class AuxCoord(Coord): - """A CF auxiliary coordinate.""" - @staticmethod - def from_coord(coord): - """Create a new AuxCoord from the given coordinate.""" - new_coord = AuxCoord(coord.points, standard_name=coord.standard_name, - long_name=coord.long_name, - var_name=coord.var_name, - units=coord.units, bounds=coord.bounds, - attributes=coord.attributes, - coord_system=copy.deepcopy(coord.coord_system)) + """ + A CF auxiliary coordinate. - return new_coord + .. note:: - def _sanitise_array(self, src, ndmin): - # Ensure the array is writeable. - # NB. Returns the *same object* if src is already writeable. - result = np.require(src, requirements='W') - # Ensure the array has enough dimensions. - # NB. Returns the *same object* if result.ndim >= ndmin - result = np.array(result, ndmin=ndmin, copy=False) - # We don't need to copy the data, but we do need to have our - # own view so we can control the shape, etc. - result = result.view() - return result + There are currently no specific properties of :class:`AuxCoord`, + everything is inherited from :class:`Coord`. - @property - def points(self): - """Property containing the points values as a numpy array""" - return self._points.view() + """ + # Logically, :class:`Coord` is an abstract class and all actual coords must + # be members of some concrete subclass, i.e. an :class:`AuxCoord` or + # a :class:`DimCoord`. + # So we retain :class:`AuxCoord` as a distinct concrete subclass. + # This provides clarity, backwards compatibility, and so we can add + # AuxCoord-specific code if needed in future. - @points.setter - def points(self, points): - # Set the points to a new array - as long as it's the same shape. - # With the exception of LazyArrays ensure points is a numpy array with - # ndmin of 1. - # This will avoid Scalar coords with points of shape () rather than the - # desired (1,) - # ... could change to: points = lazy.array(points, ndmin=1) - if not isinstance(points, iris.aux_factory.LazyArray): - points = self._sanitise_array(points, 1) - # If points are already defined for this coordinate, - if hasattr(self, '_points') and self._points is not None: - # Check that setting these points wouldn't change self.shape - if points.shape != self.shape: - raise ValueError("New points shape must match existing points " +class CellMeasure(six.with_metaclass(ABCMeta, CFVariableMixin)): + """ + A CF Cell Measure, providing area or volume properties of a cell + where these cannot be inferred from the Coordinates and + Coordinate Reference System. + + """ + + def __init__(self, data, standard_name=None, long_name=None, + var_name=None, units='1', attributes=None, measure=None): + + """ + Constructs a single cell measure. + + Args: + + * data: + The values of the measure for each cell. + Either a 'real' array (:class:`numpy.ndarray`) or a 'lazy' array + (:class:`dask.array.Array`). + + Kwargs: + + * standard_name: + CF standard name of the coordinate. + * long_name: + Descriptive name of the coordinate. + * var_name: + The netCDF variable name for the coordinate. + * units + The :class:`~cf_units.Unit` of the coordinate's values. + Can be a string, which will be converted to a Unit object. + * attributes + A dictionary containing other CF and user-defined attributes. + * measure + A string describing the type of measure. 'area' and 'volume' + are the only valid entries. + + """ + #: CF standard name of the quantity that the coordinate represents. + self.standard_name = standard_name + + #: Descriptive name of the coordinate. + self.long_name = long_name + + #: The netCDF variable name for the coordinate. + self.var_name = var_name + + #: Unit of the quantity that the coordinate represents. + self.units = units + + #: Other attributes, including user specified attributes that + #: have no meaning to Iris. + self.attributes = attributes + + #: String naming the measure type. + self.measure = measure + + # Initialise data via the data setter code, which applies standard + # checks and ajustments. + self.data = data + + @property + def measure(self): + return self._measure + + @property + def data(self): + """Property containing the data values as a numpy array""" + return self._data_manager.data + + @data.setter + def data(self, data): + # Set the data to a new array - as long as it's the same shape. + # If data are already defined for this CellMeasure, + if data is None: + raise ValueError('The data payload of a CellMeasure may not be ' + 'None; it must be a numpy array or equivalent.') + if _lazy.is_lazy_data(data) and data.dtype.kind in 'biu': + # Non-floating cell measures are not valid up to CF v1.7 + msg = ('Cannot create cell measure with lazy data of type {}, as ' + 'integer types are not currently supported.') + raise ValueError(msg.format(data.dtype)) + if data.shape == (): + # If we have a scalar value, promote the shape from () to (1,). + # NOTE: this way also *realises* it. Don't think that matters. + data = np.array(data, ndmin=1) + if hasattr(self, '_data_manager') and self._data_manager is not None: + # Check that setting these data wouldn't change self.shape + if data.shape != self.shape: + raise ValueError("New data shape must match existing data " "shape.") - self._points = points + self._data_manager = DataManager(data) @property - def bounds(self): + def shape(self): + """Returns the shape of the Cell Measure, expressed as a tuple.""" + return self._data_manager.shape + + @property + def ndim(self): + """Returns the number of dimensions of the cell measure.""" + return self._data_manager.ndim + + @measure.setter + def measure(self, measure): + if measure not in ['area', 'volume']: + raise ValueError("measure must be 'area' or 'volume', " + "not {}".format(measure)) + self._measure = measure + + def __getitem__(self, keys): """ - Property containing the bound values, as a numpy array, - or None if no bound values are defined. + Returns a new CellMeasure whose values are obtained by + conventional array indexing. - .. note:: The shape of the bound array should be: ``points.shape + - (n_bounds, )``. + """ + # Get the data, all or part of which will become the new data. + data = self._data_manager.core_data() + + # Index data with the keys. + # Note: does not copy data unless it has to. + _, data = iris.util._slice_data_with_keys(data, keys) + + # Always copy data, to avoid making the new measure a view onto the old + # one. + data = data.copy() + # The result is a copy with replacement data. + return self.copy(data=data) + + def copy(self, data=None): """ - if self._bounds is not None: - bounds = self._bounds.view() - else: - bounds = None + Returns a copy of this CellMeasure. - return bounds + Kwargs: - @bounds.setter - def bounds(self, bounds): - # Ensure the bounds are a compatible shape. - if bounds is not None: - if not isinstance(bounds, iris.aux_factory.LazyArray): - bounds = self._sanitise_array(bounds, 2) - # NB. Use _points to avoid triggering any lazy array. - if self._points.shape != bounds.shape[:-1]: - raise ValueError("Bounds shape must be compatible with points " - "shape.") - self._bounds = bounds + * data: A data array for the new cell_measure. + This may be a different shape to the data of the + cell_measure being copied. + + """ + new_cell_measure = copy.deepcopy(self) + if data is not None: + # Remove the existing data manager, to prevent the data setter + # checking against existing content. + new_cell_measure._data_manager = None + # Set new data via the data setter code, which applies standard + # checks and ajustments. + new_cell_measure.data = data + + return new_cell_measure + + def _repr_other_metadata(self): + fmt = '' + if self.long_name: + fmt = ', long_name={self.long_name!r}' + if self.var_name: + fmt += ', var_name={self.var_name!r}' + if len(self.attributes) > 0: + fmt += ', attributes={self.attributes}' + result = fmt.format(self=self) + return result + + def __str__(self): + result = repr(self) + return result + + def __repr__(self): + fmt = ('{cls}({self.data!r}' + ', measure={self.measure}, standard_name={self.standard_name!r}' + ', units={self.units!r}{other_metadata})') + result = fmt.format(self=self, cls=type(self).__name__, + other_metadata=self._repr_other_metadata()) + return result + + def _as_defn(self): + defn = (self.standard_name, self.long_name, self.var_name, + self.units, self.attributes, self.measure) + return defn + + def __eq__(self, other): + eq = NotImplemented + if isinstance(other, CellMeasure): + eq = self._as_defn() == other._as_defn() + if eq: + eq = (self.data == other.data).all() + return eq + + def __ne__(self, other): + result = self.__eq__(other) + if result is not NotImplemented: + result = not result + return result class CellMethod(iris.util._OrderedHashable): @@ -1512,7 +2231,7 @@ def __init__(self, method, coords=None, intervals=None, comments=None): comments. """ - if not isinstance(method, basestring): + if not isinstance(method, six.string_types): raise TypeError("'method' must be a string - got a '%s'" % type(method)) @@ -1521,7 +2240,7 @@ def __init__(self, method, coords=None, intervals=None, comments=None): pass elif isinstance(coords, Coord): _coords.append(coords.name()) - elif isinstance(coords, basestring): + elif isinstance(coords, six.string_types): _coords.append(coords) else: normalise = (lambda coord: coord.name() if @@ -1531,7 +2250,7 @@ def __init__(self, method, coords=None, intervals=None, comments=None): _intervals = [] if intervals is None: pass - elif isinstance(intervals, basestring): + elif isinstance(intervals, six.string_types): _intervals = [intervals] else: _intervals.extend(intervals) @@ -1539,7 +2258,7 @@ def __init__(self, method, coords=None, intervals=None, comments=None): _comments = [] if comments is None: pass - elif isinstance(comments, basestring): + elif isinstance(comments, six.string_types): _comments = [comments] else: _comments.extend(comments) @@ -1549,8 +2268,8 @@ def __init__(self, method, coords=None, intervals=None, comments=None): def __str__(self): """Return a custom string representation of CellMethod""" # Group related coord names intervals and comments together - cell_components = izip_longest(self.coord_names, self.intervals, - self.comments, fillvalue="") + cell_components = zip_longest(self.coord_names, self.intervals, + self.comments, fillvalue="") collection_summaries = [] cm_summary = "%s: " % self.method @@ -1578,9 +2297,9 @@ def xml_element(self, doc): cellMethod_xml_element = doc.createElement('cellMethod') cellMethod_xml_element.setAttribute('method', self.method) - for coord_name, interval, comment in map(None, self.coord_names, - self.intervals, - self.comments): + for coord_name, interval, comment in zip_longest(self.coord_names, + self.intervals, + self.comments): coord_xml_element = doc.createElement('coord') if coord_name is not None: coord_xml_element.setAttribute('name', coord_name) @@ -1599,13 +2318,15 @@ def __init__(self, coord): self._coord = coord if coord.ndim != 1: raise iris.exceptions.CoordinateMultiDimError(coord) - self._indices = iter(xrange(coord.shape[0])) + self._indices = iter(range(coord.shape[0])) - def next(self): + def __next__(self): # NB. When self._indices runs out it will raise StopIteration for us. - i = self._indices.next() + i = next(self._indices) return self._coord.cell(i) + next = __next__ + # See ExplicitCoord._group() for the description/context. class _GroupIterator(collections.Iterator): @@ -1613,7 +2334,7 @@ def __init__(self, points): self._points = points self._start = 0 - def next(self): + def __next__(self): num_points = len(self._points) if self._start >= num_points: raise StopIteration @@ -1626,3 +2347,5 @@ def next(self): group = _GroupbyItem(m, slice(self._start, stop)) self._start = stop return group + + next = __next__ diff --git a/lib/iris/cube.py b/lib/iris/cube.py index c04518f886..4fb7e85668 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -14,39 +14,46 @@ # # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . + """ Classes for representing multi-dimensional data with metadata. """ -from xml.dom.minidom import Document +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + import collections import copy +from copy import deepcopy import datetime +from functools import reduce import operator -import re -import UserDict import warnings +from xml.dom.minidom import Document import zlib -import biggus +import dask.array as da import numpy as np import numpy.ma as ma +from iris._cube_coord_common import CFVariableMixin +import iris._concatenate +import iris._constraints +from iris._data_manager import DataManager +import iris._lazy_data as _lazy + +import iris._merge import iris.analysis +from iris.analysis.cartography import wrap_lons import iris.analysis.maths -import iris.analysis.interpolate import iris.aux_factory import iris.coord_systems import iris.coords -import iris._concatenate -import iris._constraints -import iris._merge import iris.exceptions import iris.util -from iris._cube_coord_common import CFVariableMixin - __all__ = ['Cube', 'CubeList', 'CubeMetadata'] @@ -62,6 +69,9 @@ class CubeMetadata(collections.namedtuple('CubeMetadata', Represents the phenomenon metadata for a single :class:`Cube`. """ + + __slots__ = () + def name(self, default='unknown'): """ Returns a human-readable name. @@ -231,7 +241,7 @@ def __getslice__(self, start, stop): result = CubeList(result) return result - def xml(self, checksum=False, order=True): + def xml(self, checksum=False, order=True, byteorder=True): """Return a string of the XML that this list of cubes represents.""" doc = Document() cubes_xml_element = doc.createElement("cubes") @@ -239,7 +249,8 @@ def xml(self, checksum=False, order=True): for cube_obj in self: cubes_xml_element.appendChild( - cube_obj._xml_element(doc, checksum=checksum, order=order)) + cube_obj._xml_element( + doc, checksum=checksum, order=order, byteorder=byteorder)) doc.appendChild(cubes_xml_element) @@ -277,13 +288,13 @@ def _extract_and_merge(cubes, constraints, strict, merge_unique=False): constraint_groups = dict([(constraint, CubeList()) for constraint in constraints]) for cube in cubes: - for constraint, cube_list in constraint_groups.iteritems(): + for constraint, cube_list in six.iteritems(constraint_groups): sub_cube = constraint.extract(cube) if sub_cube is not None: cube_list.append(sub_cube) if merge_unique is not None: - for constraint, cubelist in constraint_groups.iteritems(): + for constraint, cubelist in six.iteritems(constraint_groups): constraint_groups[constraint] = cubelist.merge(merge_unique) result = CubeList() @@ -307,6 +318,33 @@ def extract_strict(self, constraints): """ return self.extract(constraints, strict=True) + def extract_overlapping(self, coord_names): + """ + Returns a :class:`CubeList` of cubes extracted over regions + where the coordinates overlap, for the coordinates + in coord_names. + + Args: + + * coord_names: + A string or list of strings of the names of the coordinates + over which to perform the extraction. + + """ + if isinstance(coord_names, six.string_types): + coord_names = [coord_names] + + def make_overlap_fn(coord_name): + def overlap_fn(cell): + return all(cell in cube.coord(coord_name).cells() + for cube in self) + return overlap_fn + + coord_values = {coord_name: make_overlap_fn(coord_name) + for coord_name in coord_names} + + return self.extract(iris.Constraint(coord_values=coord_values)) + def merge_cube(self): """ Return the merged contents of the :class:`CubeList` as a single @@ -370,13 +408,13 @@ def merge(self, unique=True): For example:: - >>> print c1 + >>> print(c1) some_parameter / (unknown) (x_vals: 3) Dimension coordinates: x_vals x Scalar coordinates: y_vals: 100 - >>> print c2 + >>> print(c2) some_parameter / (unknown) (x_vals: 3) Dimension coordinates: x_vals x @@ -384,18 +422,25 @@ def merge(self, unique=True): y_vals: 200 >>> cube_list = iris.cube.CubeList([c1, c2]) >>> new_cube = cube_list.merge()[0] - >>> print new_cube + >>> print(new_cube) some_parameter / (unknown) (y_vals: 2; x_vals: 3) Dimension coordinates: y_vals x - x_vals - x - >>> print new_cube.coord('y_vals').points + >>> print(new_cube.coord('y_vals').points) [100 200] >>> Contrast this with :meth:`iris.cube.CubeList.concatenate`, which joins cubes along an existing dimension. + .. note:: + + If time coordinates in the list of cubes have differing epochs then + the cubes will not be able to be merged. If this occurs, use + :func:`iris.util.unify_time_units` to normalise the epochs of the + time coordinates so that the cubes can be merged. + """ # Register each of our cubes with its appropriate ProtoCube. proto_cubes_by_name = {} @@ -413,18 +458,74 @@ def merge(self, unique=True): proto_cube = iris._merge.ProtoCube(cube) proto_cubes.append(proto_cube) + # Emulate Python 2 behaviour. + def _none_sort(item): + return (item is not None, item) + # Extract all the merged cubes from the ProtoCubes. merged_cubes = CubeList() - for name in sorted(proto_cubes_by_name): + for name in sorted(proto_cubes_by_name, key=_none_sort): for proto_cube in proto_cubes_by_name[name]: merged_cubes.extend(proto_cube.merge(unique=unique)) return merged_cubes - def concatenate(self): + def concatenate_cube(self, check_aux_coords=True): + """ + Return the concatenated contents of the :class:`CubeList` as a single + :class:`Cube`. + + If it is not possible to concatenate the `CubeList` into a single + `Cube`, a :class:`~iris.exceptions.ConcatenateError` will be raised + describing the reason for the failure. + + Kwargs: + + * check_aux_coords + Checks the auxilliary coordinates of the cubes match. This check + is not applied to auxilliary coordinates that span the dimension + the concatenation is occuring along. Defaults to True. + + .. note:: + + Concatenation cannot occur along an anonymous dimension. + + """ + if not self: + raise ValueError("can't concatenate an empty CubeList") + + names = [cube.metadata.name() for cube in self] + unique_names = list(collections.OrderedDict.fromkeys(names)) + if len(unique_names) == 1: + res = iris._concatenate.concatenate( + self, error_on_mismatch=True, + check_aux_coords=check_aux_coords) + n_res_cubes = len(res) + if n_res_cubes == 1: + return res[0] + else: + msgs = [] + msgs.append('An unexpected problem prevented concatenation.') + msgs.append('Expected only a single cube, ' + 'found {}.'.format(n_res_cubes)) + raise iris.exceptions.ConcatenateError(msgs) + else: + msgs = [] + msgs.append('Cube names differ: {} != {}'.format(names[0], + names[1])) + raise iris.exceptions.ConcatenateError(msgs) + + def concatenate(self, check_aux_coords=True): """ Concatenate the cubes over their common dimensions. + Kwargs: + + * check_aux_coords + Checks the auxilliary coordinates of the cubes match. This check + is not applied to auxilliary coordinates that span the dimension + the concatenation is occuring along. Defaults to True. + Returns: A new :class:`iris.cube.CubeList` of concatenated :class:`iris.cube.Cube` instances. @@ -449,40 +550,86 @@ def concatenate(self): For example:: - >>> print c1 + >>> print(c1) some_parameter / (unknown) (y_vals: 2; x_vals: 4) Dimension coordinates: y_vals x - x_vals - x - >>> print c1.coord('y_vals').points + >>> print(c1.coord('y_vals').points) [4 5] - >>> print c2 + >>> print(c2) some_parameter / (unknown) (y_vals: 3; x_vals: 4) Dimension coordinates: y_vals x - x_vals - x - >>> print c2.coord('y_vals').points + >>> print(c2.coord('y_vals').points) [ 7 9 10] >>> cube_list = iris.cube.CubeList([c1, c2]) >>> new_cube = cube_list.concatenate()[0] - >>> print new_cube + >>> print(new_cube) some_parameter / (unknown) (y_vals: 5; x_vals: 4) Dimension coordinates: y_vals x - x_vals - x - >>> print new_cube.coord('y_vals').points + >>> print(new_cube.coord('y_vals').points) [ 4 5 7 9 10] >>> Contrast this with :meth:`iris.cube.CubeList.merge`, which makes a new dimension from values of an auxiliary scalar coordinate. - .. warning:: + .. note:: - This routine will load your data payload! + If time coordinates in the list of cubes have differing epochs then + the cubes will not be able to be concatenated. If this occurs, use + :func:`iris.util.unify_time_units` to normalise the epochs of the + time coordinates so that the cubes can be concatenated. + + .. note:: + + Concatenation cannot occur along an anonymous dimension. """ - return iris._concatenate.concatenate(self) + return iris._concatenate.concatenate(self, + check_aux_coords=check_aux_coords) + + def realise_data(self): + """ + Fetch 'real' data for all cubes, in a shared calculation. + + This computes any lazy data, equivalent to accessing each `cube.data`. + However, lazy calculations and data fetches can be shared between the + computations, improving performance. + + For example:: + + # Form stats. + a_std = cube_a.collapsed(['x', 'y'], iris.analysis.STD_DEV) + b_std = cube_b.collapsed(['x', 'y'], iris.analysis.STD_DEV) + ab_mean_diff = (cube_b - cube_a).collapsed(['x', 'y'], + iris.analysis.MEAN) + std_err = (a_std * a_std + b_std * b_std) ** 0.5 + + # Compute these stats together (avoiding multiple data passes). + CubeList([a_std, b_std, ab_mean_diff, std_err]).realise_data() + + .. Note:: + + Cubes with non-lazy data are not affected. + + """ + _lazy.co_realise_cubes(*self) + + +def _is_single_item(testee): + """ + Return whether this is a single item, rather than an iterable. + + We count string types as 'single', also. + + """ + return (isinstance(testee, six.string_types) or + not isinstance(testee, collections.Iterable)) class Cube(CFVariableMixin): @@ -495,13 +642,13 @@ class Cube(CFVariableMixin): For example: >>> cube = iris.load_cube(iris.sample_data_path('air_temp.pp')) - >>> print cube + >>> print(cube) air_temperature / (K) (latitude: 73; longitude: 96) Dimension coordinates: latitude x - longitude - x Scalar coordinates: - forecast_period: 6477 hours + forecast_period: 6477 hours, bound=(-28083.0, 6477.0) hours forecast_reference_time: 1998-03-01 03:00:00 pressure: 1000.0 hPa time: 1998-12-01 00:00:00, \ @@ -510,16 +657,25 @@ class Cube(CFVariableMixin): STASH: m01s16i203 source: Data from Met Office Unified Model Cell methods: - mean: time + mean within years: time + mean over years: time See the :doc:`user guide` for more information. """ + + #: Indicates to client code that the object supports + #: "orthogonal indexing", which means that slices that are 1d arrays + #: or lists slice along each dimension independently. This behavior + #: is similar to Fortran or Matlab, but different than numpy. + __orthogonal_indexing__ = True + def __init__(self, data, standard_name=None, long_name=None, var_name=None, units=None, attributes=None, cell_methods=None, dim_coords_and_dims=None, - aux_coords_and_dims=None, aux_factories=None): + aux_coords_and_dims=None, aux_factories=None, + cell_measures_and_dims=None): """ Creates a cube with data and optional metadata. @@ -532,9 +688,9 @@ def __init__(self, data, standard_name=None, long_name=None, This object defines the shape of the cube and the phenomenon value in each cell. - It can be a biggus array, a numpy array, a numpy array - subclass (such as :class:`numpy.ma.MaskedArray`), or an - *array_like* as described in :func:`numpy.asarray`. + ``data`` can be a dask array, a NumPy array, a NumPy array + subclass (such as :class:`numpy.ma.MaskedArray`), or + array_like (as described in :func:`numpy.asarray`). See :attr:`Cube.data`. @@ -545,7 +701,7 @@ def __init__(self, data, standard_name=None, long_name=None, * long_name An unconstrained description of the cube. * var_name - The CF variable name for the cube. + The netCDF variable name for the cube. * units The unit of the cube, e.g. ``"m s-1"`` or ``"kelvin"``. * attributes @@ -564,35 +720,40 @@ def __init__(self, data, standard_name=None, long_name=None, * aux_factories A list of auxiliary coordinate factories. See :mod:`iris.aux_factory`. + * cell_measures_and_dims + A list of CellMeasures with dimension mappings. For example:: - - latitude = DimCoord(range(-85, 105, 10), standard_name='latitude', - units='degrees') - longitude = DimCoord(range(0, 360, 10), standard_name='longitude', - units='degrees') - cube = Cube(np.zeros((18, 36), np.float32), - dim_coords_and_dims=[(latitude, 0), (longitude, 1)]) + >>> from iris.coords import DimCoord + >>> from iris.cube import Cube + >>> latitude = DimCoord(np.linspace(-90, 90, 4), + ... standard_name='latitude', + ... units='degrees') + >>> longitude = DimCoord(np.linspace(45, 360, 8), + ... standard_name='longitude', + ... units='degrees') + >>> cube = Cube(np.zeros((4, 8), np.float32), + ... dim_coords_and_dims=[(latitude, 0), + ... (longitude, 1)]) """ # Temporary error while we transition the API. - if isinstance(data, basestring): + if isinstance(data, six.string_types): raise TypeError('Invalid data type: {!r}.'.format(data)) - if not isinstance(data, (biggus.Array, ma.MaskedArray)): - data = np.asarray(data) - self._my_data = data + # Initialise the cube data manager. + self._data_manager = DataManager(data) #: The "standard name" for the Cube's phenomenon. self.standard_name = standard_name - #: An instance of :class:`iris.unit.Unit` describing the Cube's data. + #: An instance of :class:`cf_units.Unit` describing the Cube's data. self.units = units #: The "long name" for the Cube's phenomenon. self.long_name = long_name - #: The CF variable name for the Cube. + #: The netCDF variable name for the Cube. self.var_name = var_name self.cell_methods = cell_methods @@ -606,6 +767,9 @@ def __init__(self, data, standard_name=None, long_name=None, self._aux_coords_and_dims = [] self._aux_factories = [] + # Cell Measures + self._cell_measures_and_dims = [] + identities = set() if dim_coords_and_dims: dims = set() @@ -631,6 +795,10 @@ def __init__(self, data, standard_name=None, long_name=None, for factory in aux_factories: self.add_aux_factory(factory) + if cell_measures_and_dims: + for cell_measure, dims in cell_measures_and_dims: + self.add_cell_measure(cell_measure, dims) + @property def metadata(self): """ @@ -654,8 +822,8 @@ def metadata(self, value): try: value = CubeMetadata(*value) except TypeError: - attr_check = lambda name: not hasattr(value, name) - missing_attrs = filter(attr_check, CubeMetadata._fields) + missing_attrs = [field for field in CubeMetadata._fields + if not hasattr(value, field)] if missing_attrs: raise TypeError('Invalid/incomplete metadata') for name in CubeMetadata._fields: @@ -701,7 +869,7 @@ def is_compatible(self, other, ignore=None): if compatible: common_keys = set(self.attributes).intersection(other.attributes) if ignore is not None: - if isinstance(ignore, basestring): + if isinstance(ignore, six.string_types): ignore = (ignore,) common_keys = common_keys.difference(ignore) for key in common_keys: @@ -730,12 +898,28 @@ def convert_units(self, unit): """ # If the cube has units convert the data. - if not self.units.is_unknown(): - self.data = self.units.convert(self.data, unit) + if self.units.is_unknown(): + raise iris.exceptions.UnitConversionError( + 'Cannot convert from unknown units. ' + 'The "cube.units" attribute may be set directly.') + if self.has_lazy_data(): + # Make fixed copies of old + new units for a delayed conversion. + old_unit = self.units + new_unit = unit + + # Define a delayed conversion operation (i.e. a callback). + def pointwise_convert(values): + return old_unit.convert(values, new_unit) + + new_data = _lazy.lazy_elementwise(self.lazy_data(), + pointwise_convert) + else: + new_data = self.units.convert(self.data, unit) + self.data = new_data self.units = unit def add_cell_method(self, cell_method): - """Add a CellMethod to the Cube.""" + """Add a :class:`~iris.coords.CellMethod` to the Cube.""" self.cell_methods += (cell_method, ) def add_aux_coord(self, coord, data_dims=None): @@ -764,7 +948,7 @@ def add_aux_coord(self, coord, data_dims=None): raise ValueError('Duplicate coordinates are not permitted.') self._add_unique_aux_coord(coord, data_dims) - def _add_unique_aux_coord(self, coord, data_dims): + def _check_multi_dim_metadata(self, metadata, data_dims): # Convert to a tuple of integers if data_dims is None: data_dims = tuple() @@ -774,22 +958,27 @@ def _add_unique_aux_coord(self, coord, data_dims): data_dims = (int(data_dims),) if data_dims: - if len(data_dims) != coord.ndim: + if len(data_dims) != metadata.ndim: msg = 'Invalid data dimensions: {} given, {} expected for ' \ - '{!r}.'.format(len(data_dims), coord.ndim, coord.name()) + '{!r}.'.format(len(data_dims), metadata.ndim, + metadata.name()) raise ValueError(msg) # Check compatibility with the shape of the data for i, dim in enumerate(data_dims): - if coord.shape[i] != self.shape[dim]: + if metadata.shape[i] != self.shape[dim]: msg = 'Unequal lengths. Cube dimension {} => {};' \ - ' coord {!r} dimension {} => {}.' + ' metadata {!r} dimension {} => {}.' raise ValueError(msg.format(dim, self.shape[dim], - coord.name(), i, - coord.shape[i])) - elif coord.shape != (1,): - raise ValueError('Missing data dimensions for multi-valued' - ' coordinate {!r}'.format(coord.name())) + metadata.name(), i, + metadata.shape[i])) + elif metadata.shape != (1,): + msg = 'Missing data dimensions for multi-valued {} {!r}' + msg = msg.format(metadata.__class__.__name__, metadata.name()) + raise ValueError(msg) + return data_dims + def _add_unique_aux_coord(self, coord, data_dims): + data_dims = self._check_multi_dim_metadata(coord, data_dims) self._aux_coords_and_dims.append([coord, data_dims]) def add_aux_factory(self, aux_factory): @@ -805,8 +994,44 @@ def add_aux_factory(self, aux_factory): if not isinstance(aux_factory, iris.aux_factory.AuxCoordFactory): raise TypeError('Factory must be a subclass of ' 'iris.aux_factory.AuxCoordFactory.') + cube_coords = self.coords() + for dependency in aux_factory.dependencies: + ref_coord = aux_factory.dependencies[dependency] + if ref_coord is not None and ref_coord not in cube_coords: + msg = "{} coordinate for factory is not present on cube {}" + raise ValueError(msg.format(ref_coord.name(), self.name())) self._aux_factories.append(aux_factory) + def add_cell_measure(self, cell_measure, data_dims=None): + """ + Adds a CF cell measure to the cube. + + Args: + + * cell_measure + The :class:`iris.coords.CellMeasure` + instance to add to the cube. + + Kwargs: + + * data_dims + Integer or iterable of integers giving the data dimensions spanned + by the coordinate. + + Raises a ValueError if a cell_measure with identical metadata already + exists on the cube. + + See also + :meth:`Cube.remove_cell_measure()`. + + """ + if self.cell_measures(cell_measure): + raise ValueError('Duplicate cell_measures are not permitted.') + data_dims = self._check_multi_dim_metadata(cell_measure, data_dims) + self._cell_measures_and_dims.append([cell_measure, data_dims]) + self._cell_measures_and_dims.sort(key=lambda cm_dims: + (cm_dims[0]._as_defn(), cm_dims[1])) + def add_dim_coord(self, dim_coord, data_dim): """ Add a CF coordinate to the cube. @@ -882,7 +1107,8 @@ def remove_coord(self, coord): * coord (string or coord) The (name of the) coordinate to remove from the cube. - See also :meth:`Cube.add_coord()`. + See also :meth:`Cube.add_dim_coord()` + and :meth:`Cube.add_aux_coord()`. """ coord = self.coord(coord) @@ -891,6 +1117,23 @@ def remove_coord(self, coord): for factory in self.aux_factories: factory.update(coord) + def remove_cell_measure(self, cell_measure): + """ + Removes a cell measure from the cube. + + Args: + + * cell_measure (CellMeasure) + The CellMeasure to remove from the cube. + + See also + :meth:`Cube.add_cell_measure()` + + """ + self._cell_measures_and_dims = [[cell_measure_, dim] for cell_measure_, + dim in self._cell_measures_and_dims + if cell_measure_ is not cell_measure] + def replace_coord(self, new_coord): """ Replace the coordinate whose metadata matches the given coordinate. @@ -938,25 +1181,33 @@ def coord_dims(self, coord): # Search derived aux coords target_defn = coord._as_defn() if not matches: - match = lambda factory: factory._as_defn() == target_defn + def match(factory): + return factory._as_defn() == target_defn factories = filter(match, self._aux_factories) matches = [factory.derived_dims(self.coord_dims) for factory in factories] - # Deprecate name based searching - ### Search by coord name, if have no match - # XXX Where did this come from? And why isn't it reflected in the - # docstring? if not matches: - warnings.warn('name based coord matching is deprecated and will ' - 'be removed in a future release.', - stacklevel=2) - matches = [(dim,) for coord_, dim in self._dim_coords_and_dims if - coord_.name() == coord.name()] - # Finish deprecate name based searching + raise iris.exceptions.CoordinateNotFoundError(coord.name()) + + return matches[0] + + def cell_measure_dims(self, cell_measure): + """ + Returns a tuple of the data dimensions relevant to the given + CellMeasure. + + * cell_measure + The CellMeasure to look for. + + """ + # Search for existing cell measure (object) on the cube, faster lookup + # than equality - makes no functional difference. + matches = [dims for cm_, dims in self._cell_measures_and_dims if + cm_ is cell_measure] if not matches: - raise iris.exceptions.CoordinateNotFoundError(coord.name()) + raise iris.exceptions.CellMeasureNotFoundError(cell_measure.name()) return matches[0] @@ -977,7 +1228,7 @@ def aux_factory(self, name=None, standard_name=None, long_name=None, An unconstrained description of the coordinate factory. If None, does not check for long_name. * var_name - The CF variable name of the desired coordinate factory. + The netCDF variable name of the desired coordinate factory. If None, does not check for var_name. .. note:: @@ -1020,8 +1271,8 @@ def aux_factory(self, name=None, standard_name=None, long_name=None, def coords(self, name_or_coord=None, standard_name=None, long_name=None, var_name=None, attributes=None, axis=None, - contains_dimension=None, dimensions=None, coord=None, - coord_system=None, dim_coords=None, name=None): + contains_dimension=None, dimensions=None, coord_system=None, + dim_coords=None): """ Return a list of coordinates in this cube fitting the given criteria. @@ -1040,8 +1291,6 @@ def coords(self, name_or_coord=None, standard_name=None, :class:`iris.coords.DimCoord`, :class:`iris.coords.AuxCoord`, :class:`iris.aux_factory.AuxCoordFactory` or :class:`iris.coords.CoordDefn`. - * name - .. deprecated:: 1.6. Please use the name_or_coord kwarg. * standard_name The CF standard name of the desired coordinate. If None, does not check for standard name. @@ -1049,8 +1298,8 @@ def coords(self, name_or_coord=None, standard_name=None, An unconstrained description of the coordinate. If None, does not check for long_name. * var_name - The CF variable name of the desired coordinate. If None, does not - check for var_name. + The netCDF variable name of the desired coordinate. If None, does + not check for var_name. * attributes A dictionary of attributes desired on the coordinates. If None, does not check for attributes. @@ -1065,8 +1314,6 @@ def coords(self, name_or_coord=None, standard_name=None, The exact data dimensions of the desired coordinate. Coordinates with no data dimension can be found with an empty tuple or list (i.e. ``()`` or ``[]``). If None, does not check for dimensions. - * coord - .. deprecated:: 1.6. Please use the name_or_coord kwarg. * coord_system Whether the desired coordinates have coordinate systems equal to the given coordinate system. If None, no check is done. @@ -1079,27 +1326,10 @@ def coords(self, name_or_coord=None, standard_name=None, See also :meth:`Cube.coord()`. """ - # Handle deprecated kwargs - if name is not None: - name_or_coord = name - warnings.warn('the name kwarg is deprecated and will be removed ' - 'in a future release. Consider converting ' - 'existing code to use the name_or_coord ' - 'kwarg as a replacement.', - stacklevel=2) - if coord is not None: - name_or_coord = coord - warnings.warn('the coord kwarg is deprecated and will be removed ' - 'in a future release. Consider converting ' - 'existing code to use the name_or_coord ' - 'kwarg as a replacement.', - stacklevel=2) - # Finish handling deprecated kwargs - name = None coord = None - if isinstance(name_or_coord, basestring): + if isinstance(name_or_coord, six.string_types): name = name_or_coord else: coord = name_or_coord @@ -1140,9 +1370,11 @@ def coords(self, name_or_coord=None, standard_name=None, msg = 'The attributes keyword was expecting a dictionary ' \ 'type, but got a %s instead.' % type(attributes) raise ValueError(msg) - attr_filter = lambda coord_: all(k in coord_.attributes and - coord_.attributes[k] == v for - k, v in attributes.iteritems()) + + def attr_filter(coord_): + return all(k in coord_.attributes and coord_.attributes[k] == v + for k, v in six.iteritems(attributes)) + coords_and_factories = [coord_ for coord_ in coords_and_factories if attr_filter(coord_)] @@ -1189,8 +1421,8 @@ def extract_coord(coord_or_factory): def coord(self, name_or_coord=None, standard_name=None, long_name=None, var_name=None, attributes=None, axis=None, - contains_dimension=None, dimensions=None, coord=None, - coord_system=None, dim_coords=None, name=None): + contains_dimension=None, dimensions=None, coord_system=None, + dim_coords=None): """ Return a single coord given the same arguments as :meth:`Cube.coords`. @@ -1206,23 +1438,6 @@ def coord(self, name_or_coord=None, standard_name=None, documentation. """ - # Handle deprecated kwargs - if name is not None: - name_or_coord = name - warnings.warn('the name kwarg is deprecated and will be removed ' - 'in a future release. Consider converting ' - 'existing code to use the name_or_coord ' - 'kwarg as a replacement.', - stacklevel=2) - if coord is not None: - name_or_coord = coord - warnings.warn('the coord kwarg is deprecated and will be removed ' - 'in a future release. Consider converting ' - 'existing code to use the name_or_coord ' - 'kwarg as a replacement.', - stacklevel=2) - # Finish handling deprecated kwargs - coords = self.coords(name_or_coord=name_or_coord, standard_name=standard_name, long_name=long_name, var_name=var_name, @@ -1238,8 +1453,11 @@ def coord(self, name_or_coord=None, standard_name=None, coord in coords)) raise iris.exceptions.CoordinateNotFoundError(msg) elif len(coords) == 0: - bad_name = name or standard_name or long_name or \ - (coord and coord.name()) or '' + _name = name_or_coord + if name_or_coord is not None: + if not isinstance(name_or_coord, six.string_types): + _name = name_or_coord.name() + bad_name = _name or standard_name or long_name or '' msg = 'Expected to find exactly 1 %s coordinate, but found ' \ 'none.' % bad_name raise iris.exceptions.CoordinateNotFoundError(msg) @@ -1272,7 +1490,7 @@ def coord_system(self, spec=None): The :class:`iris.coord_systems.CoordSystem` or None. """ - if isinstance(spec, basestring) or spec is None: + if isinstance(spec, six.string_types) or spec is None: spec_name = spec else: msg = "type %s is not a subclass of CoordSystem" % spec @@ -1287,7 +1505,8 @@ def coord_system(self, spec=None): result = None if spec_name is None: - for key in sorted(coord_systems.keys()): + for key in sorted(coord_systems.keys(), + key=lambda class_: class_.__name__): result = coord_systems[key] break else: @@ -1295,6 +1514,81 @@ def coord_system(self, spec=None): return result + def cell_measures(self, name_or_cell_measure=None): + """ + Return a list of cell measures in this cube fitting the given criteria. + + Kwargs: + + * name_or_cell_measure + Either + + (a) a :attr:`standard_name`, :attr:`long_name`, or + :attr:`var_name`. Defaults to value of `default` + (which itself defaults to `unknown`) as defined in + :class:`iris._cube_coord_common.CFVariableMixin`. + + (b) a cell_measure instance with metadata equal to that of + the desired cell_measures. + + See also :meth:`Cube.cell_measure()`. + + """ + name = None + + if isinstance(name_or_cell_measure, six.string_types): + name = name_or_cell_measure + else: + cell_measure = name_or_cell_measure + cell_measures = [] + for cm, _ in self._cell_measures_and_dims: + if name is not None: + if cm.name() == name: + cell_measures.append(cm) + elif cell_measure is not None: + if cm == cell_measure: + cell_measures.append(cm) + else: + cell_measures.append(cm) + return cell_measures + + def cell_measure(self, name_or_cell_measure=None): + """ + Return a single cell_measure given the same arguments as + :meth:`Cube.cell_measures`. + + .. note:: + + If the arguments given do not result in precisely 1 cell_measure + being matched, an :class:`iris.exceptions.CellMeasureNotFoundError` + is raised. + + .. seealso:: + + :meth:`Cube.cell_measures()` + for full keyword documentation. + + """ + cell_measures = self.cell_measures(name_or_cell_measure) + + if len(cell_measures) > 1: + msg = ('Expected to find exactly 1 cell_measure, but found {}. ' + 'They were: {}.') + msg = msg.format(len(cell_measures), + ', '.join(cm.name() for cm in cell_measures)) + raise iris.exceptions.CellMeasureNotFoundError(msg) + elif len(cell_measures) == 0: + if isinstance(name_or_cell_measure, six.string_types): + bad_name = name_or_cell_measure + else: + bad_name = (name_or_cell_measure and + name_or_cell_measure.name()) or '' + msg = 'Expected to find exactly 1 %s cell_measure, but found ' \ + 'none.' % bad_name + raise iris.exceptions.CellMeasureNotFoundError(msg) + + return cell_measures[0] + @property def cell_methods(self): """ @@ -1308,59 +1602,59 @@ def cell_methods(self): def cell_methods(self, cell_methods): self._cell_methods = tuple(cell_methods) if cell_methods else tuple() + def core_data(self): + """ + Retrieve the data array of this :class:`~iris.cube.Cube` in its + current state, which will either be real or lazy. + + If this :class:`~iris.cube.Cube` has lazy data, accessing its data + array via this method **will not** realise the data array. This means + you can perform operations using this method that work equivalently + on real or lazy data, and will maintain lazy data if present. + + """ + return self._data_manager.core_data() + @property def shape(self): """The shape of the data of this cube.""" - shape = self.lazy_data().shape - return shape + return self._data_manager.shape + + @property + def dtype(self): + """ + The data type of the values in the data array of this + :class:`~iris.cube.Cube`. + + """ + return self._data_manager.dtype @property def ndim(self): """The number of dimensions in the data of this cube.""" - return len(self.shape) + return self._data_manager.ndim - def lazy_data(self, array=None): + def lazy_data(self): """ - Return a :class:`biggus.Array` representing the - multi-dimensional data of the Cube, and optionally provide a - new array of values. + Return a "lazy array" representing the Cube data. A lazy array + describes an array whose data values have not been loaded into memory + from disk. - Accessing this method will never cause the data to be loaded. + Accessing this method will never cause the Cube data to be loaded. Similarly, calling methods on, or indexing, the returned Array - will not cause the Cube to have loaded data. + will not cause the Cube data to be loaded. - If the data have already been loaded for the Cube, the returned - Array will be a :class:`biggus.NumpyArrayAdapter` which wraps - the numpy array from `self.data`. - - Kwargs: - - * array (:class:`biggus.Array` or None): - When this is not None it sets the multi-dimensional data of - the cube to the given value. + If the Cube data have already been loaded (for example by calling + :meth:`~iris.cube.Cube.data`), the returned Array will be a view of the + loaded cube data represented as a lazy array object. Note that this + does _not_ make the Cube data lazy again; the Cube data remains loaded + in memory. Returns: - A :class:`biggus.Array` representing the multi-dimensional - data of the Cube. - - """ - if array is not None: - if not isinstance(array, biggus.Array): - raise TypeError('new values must be a biggus.Array') - if self.shape != array.shape: - # The _ONLY_ data reshape permitted is converting a - # 0-dimensional array into a 1-dimensional array of - # length one. - # i.e. self.shape = () and array.shape == (1,) - if self.shape or array.shape != (1,): - raise ValueError('Require cube data with shape %r, got ' - '%r.' % (self.shape, array.shape)) - self._my_data = array - else: - array = self._my_data - if not isinstance(array, biggus.Array): - array = biggus.NumpyArrayAdapter(array) - return array + A lazy array, representing the Cube data. + + """ + return self._data_manager.lazy_data() @property def data(self): @@ -1378,54 +1672,38 @@ def data(self): Example:: >>> fname = iris.sample_data_path('air_temp.pp') - >>> cube = iris.load_cube(fname, 'air_temperature') \ -# cube.data does not yet have a value. - >>> print cube.shape \ -# cube.data still does not have a value. + >>> cube = iris.load_cube(fname, 'air_temperature') + >>> # cube.data does not yet have a value. + ... + >>> print(cube.shape) (73, 96) - >>> cube = cube[:10, :20] \ -# cube.data still does not have a value. - >>> data = cube.data \ -# Only now is the data loaded. - >>> print data.shape + >>> # cube.data still does not have a value. + ... + >>> cube = cube[:10, :20] + >>> # cube.data still does not have a value. + ... + >>> data = cube.data + >>> # Only now is the data loaded. + ... + >>> print(data.shape) (10, 20) """ - data = self._my_data - if not isinstance(data, np.ndarray): - try: - data = data.masked_array() - except MemoryError: - msg = "Failed to create the cube's data as there was not" \ - " enough memory available.\n" \ - "The array shape would have been {0!r} and the data" \ - " type {1}.\n" \ - "Consider freeing up variables or indexing the cube" \ - " before getting its data." - msg = msg.format(self.shape, data.dtype) - raise MemoryError(msg) - # Unmask the array only if it is filled. - if ma.count_masked(data) == 0: - data = data.data - self._my_data = data - return data + return self._data_manager.data @data.setter - def data(self, value): - data = np.asanyarray(value) + def data(self, data): + self._data_manager.data = data - if self.shape != data.shape: - # The _ONLY_ data reshape permitted is converting a 0-dimensional - # array i.e. self.shape == () into a 1-dimensional array of length - # one i.e. data.shape == (1,) - if self.shape or data.shape != (1,): - raise ValueError('Require cube data with shape %r, got ' - '%r.' % (self.shape, data.shape)) + def has_lazy_data(self): + """ + Details whether this :class:`~iris.cube.Cube` has lazy data. - self._my_data = data + Returns: + Boolean. - def has_lazy_data(self): - return isinstance(self._my_data, biggus.Array) + """ + return self._data_manager.has_lazy_data() @property def dim_coords(self): @@ -1444,7 +1722,7 @@ def dim_coords(self): """ return tuple((coord for coord, dim in sorted(self._dim_coords_and_dims, - key=lambda (coord, dim): (dim, coord.name())))) + key=lambda co_di: (co_di[1], co_di[0].name())))) @property def aux_coords(self): @@ -1455,7 +1733,7 @@ def aux_coords(self): """ return tuple((coord for coord, dims in sorted(self._aux_coords_and_dims, - key=lambda (coord, dims): (dims, coord.name())))) + key=lambda co_di: (co_di[1], co_di[0].name())))) @property def derived_coords(self): @@ -1482,7 +1760,7 @@ def _summary_coord_extra(self, coord, indent): # Find all the attribute keys keys = set() for similar_coord in similar_coords: - keys.update(similar_coord.attributes.iterkeys()) + keys.update(six.iterkeys(similar_coord.attributes)) # Look for any attributes that vary vary = set() attributes = {} @@ -1495,7 +1773,7 @@ def _summary_coord_extra(self, coord, indent): if attributes.setdefault(key, value) != value: vary.add(key) break - keys = sorted(vary & coord.attributes.viewkeys()) + keys = sorted(vary & set(coord.attributes.keys())) bits = ['{}={!r}'.format(key, coord.attributes[key]) for key in keys] if bits: @@ -1520,11 +1798,11 @@ def summary(self, shorten=False, name_padding=35): """ # Create a set to contain the axis names for each data dimension. - dim_names = [set() for dim in xrange(len(self.shape))] + dim_names = [set() for dim in range(len(self.shape))] # Add the dim_coord names that participate in the associated data # dimensions. - for dim in xrange(len(self.shape)): + for dim in range(len(self.shape)): dim_coords = self.coords(contains_dimension=dim, dim_coords=True) if dim_coords: dim_names[dim].add(dim_coords[0].name()) @@ -1576,6 +1854,10 @@ def summary(self, shorten=False, name_padding=35): vector_derived_coords = [coord for coord in derived_coords if id(coord) not in scalar_coord_ids] + # cell measures + vector_cell_measures = [cm for cm in self.cell_measures() + if cm.shape != (1,)] + # Determine the cube coordinates that don't describe the cube and # are most likely erroneous. vector_coords = vector_dim_coords + vector_aux_coords + \ @@ -1599,7 +1881,8 @@ def summary(self, shorten=False, name_padding=35): # # Generate textual summary of cube vector coordinates. # - def vector_summary(vector_coords, cube_header, max_line_offset): + def vector_summary(vector_coords, cube_header, max_line_offset, + cell_measures=None): """ Generates a list of suitably aligned strings containing coord names and dimensions indicated by one or more 'x' symbols. @@ -1610,45 +1893,65 @@ def vector_summary(vector_coords, cube_header, max_line_offset): returned with the list of strings. """ + if cell_measures is None: + cell_measures = [] vector_summary = [] - if vector_coords: - # Identify offsets for each dimension text marker. - alignment = np.array([index for index, value in - enumerate(cube_header) if - value == ':']) - - # Generate basic textual summary for each vector coordinate - # - WITHOUT dimension markers. - for coord in vector_coords: - vector_summary.append('%*s%s' % ( - indent, ' ', iris.util.clip_string(coord.name()))) - min_alignment = min(alignment) - - # Determine whether the cube header requires realignment - # due to one or more longer vector coordinate summaries. - if max_line_offset >= min_alignment: - delta = max_line_offset - min_alignment + 5 - cube_header = '%-*s (%s)' % (int(name_padding + delta), - self.name() or 'unknown', - dimension_header) - alignment += delta + vectors = [] + + # Identify offsets for each dimension text marker. + alignment = np.array([index for index, value in + enumerate(cube_header) if + value == ':']) + + # Generate basic textual summary for each vector coordinate + # - WITHOUT dimension markers. + for coord in vector_coords + cell_measures: + vector_summary.append('%*s%s' % ( + indent, ' ', iris.util.clip_string(coord.name()))) + min_alignment = min(alignment) + + # Determine whether the cube header requires realignment + # due to one or more longer vector coordinate summaries. + if max_line_offset >= min_alignment: + delta = max_line_offset - min_alignment + 5 + cube_header = '%-*s (%s)' % (int(name_padding + delta), + self.name() or 'unknown', + dimension_header) + alignment += delta + if vector_coords: # Generate full textual summary for each vector coordinate # - WITH dimension markers. for index, coord in enumerate(vector_coords): dims = self.coord_dims(coord) - for dim in xrange(len(self.shape)): + + for dim in range(len(self.shape)): + width = alignment[dim] - len(vector_summary[index]) + char = 'x' if dim in dims else '-' + line = '{pad:{width}}{char}'.format(pad=' ', + width=width, + char=char) + vector_summary[index] += line + vectors = vectors + vector_coords + if cell_measures: + # Generate full textual summary for each vector coordinate + # - WITH dimension markers. + for index, coord in enumerate(cell_measures): + dims = self.cell_measure_dims(coord) + + for dim in range(len(self.shape)): width = alignment[dim] - len(vector_summary[index]) char = 'x' if dim in dims else '-' line = '{pad:{width}}{char}'.format(pad=' ', width=width, char=char) vector_summary[index] += line - # Interleave any extra lines that are needed to distinguish - # the coordinates. - vector_summary = self._summary_extra(vector_coords, - vector_summary, - extra_indent) + vectors = vectors + cell_measures + # Interleave any extra lines that are needed to distinguish + # the coordinates. + vector_summary = self._summary_extra(vectors, + vector_summary, + extra_indent) return vector_summary, cube_header @@ -1676,6 +1979,16 @@ def vector_summary(vector_coords, cube_header, max_line_offset): summary += '\n Derived coordinates:\n' + \ '\n'.join(derived_coord_summary) + # + # Generate summary of cube cell measures attribute + # + if vector_cell_measures: + cell_measure_summary, cube_header = vector_summary( + [], cube_header, max_line_offset, + cell_measures=vector_cell_measures) + summary += '\n Cell Measures:\n' + summary += '\n'.join(cell_measure_summary) + # # Generate textual summary of cube scalar coordinates. # @@ -1690,10 +2003,9 @@ def vector_summary(vector_coords, cube_header, max_line_offset): unit = ' {!s}'.format(coord.units) # Format cell depending on type of point and whether it - # has a bound - with iris.FUTURE.context(cell_datetime_objects=False): - coord_cell = coord.cell(0) - if isinstance(coord_cell.point, basestring): + # has a bound. + coord_cell = coord.cell(0) + if isinstance(coord_cell.point, six.string_types): # Indent string type coordinates coord_cell_split = [iris.util.clip_string(str(item)) for item in @@ -1702,20 +2014,12 @@ def vector_summary(vector_coords, cube_header, max_line_offset): pad=' ', width=indent + len(coord.name()) + 2) coord_cell_str = line_sep.join(coord_cell_split) + unit else: - # Human readable times - if coord.units.is_time_reference(): - coord_cell_cpoint = coord.units.num2date( - coord_cell.point) - if coord_cell.bound is not None: - coord_cell_cbound = coord.units.num2date( - coord_cell.bound) - else: - coord_cell_cpoint = coord_cell.point - coord_cell_cbound = coord_cell.bound + coord_cell_cpoint = coord_cell.point + coord_cell_cbound = coord_cell.bound coord_cell_str = '{!s}{}'.format(coord_cell_cpoint, unit) - if coord_cell.bound is not None: + if coord_cell_cbound is not None: bound = '({})'.format(', '.join(str(val) for val in coord_cell_cbound)) coord_cell_str += ', bound={}{}'.format(bound, @@ -1752,13 +2056,22 @@ def vector_summary(vector_coords, cube_header, max_line_offset): summary += '\n Invalid coordinates:\n' + \ '\n'.join(invalid_summary) + # cell measures + scalar_cell_measures = [cm for cm in self.cell_measures() + if cm.shape == (1,)] + if scalar_cell_measures: + summary += '\n Scalar cell measures:\n' + scalar_cms = [' {}'.format(cm.name()) + for cm in scalar_cell_measures] + summary += '\n'.join(scalar_cms) + # # Generate summary of cube attributes. # if self.attributes: attribute_lines = [] - for name, value in sorted(self.attributes.iteritems()): - value = iris.util.clip_string(unicode(value)) + for name, value in sorted(six.iteritems(self.attributes)): + value = iris.util.clip_string(six.text_type(value)) line = u'{pad:{width}}{name}: {value}'.format(pad=' ', width=indent, name=name, @@ -1782,13 +2095,12 @@ def vector_summary(vector_coords, cube_header, max_line_offset): return summary - def assert_valid(self): - """Raise an exception if the cube is invalid; otherwise return None.""" - - warnings.warn('Cube.assert_valid() has been deprecated.') - def __str__(self): - return self.summary().encode(errors='replace') + # six has a decorator for this bit, but it doesn't do errors='replace'. + if six.PY3: + return self.summary() + else: + return self.summary().encode(errors='replace') def __unicode__(self): return self.summary() @@ -1797,6 +2109,11 @@ def __repr__(self): return "" % self.summary(shorten=True, name_padding=1) + def _repr_html_(self): + from iris.experimental.representation import CubeRepresentation + representer = CubeRepresentation(self) + return representer.repr_html() + def __iter__(self): raise TypeError('Cube is not iterable') @@ -1810,44 +2127,39 @@ def __getitem__(self, keys): """ # turn the keys into a full slice spec (all dims) - full_slice = iris.util._build_full_slice_given_keys(keys, - len(self.shape)) - - # make indexing on the cube column based by using the - # column_slices_generator (potentially requires slicing the data - # multiple times) - dimension_mapping, slice_gen = iris.util.column_slices_generator( - full_slice, len(self.shape)) - new_coord_dims = lambda coord_: [dimension_mapping[d] for d in - self.coord_dims(coord_) if - dimension_mapping[d] is not None] + full_slice = iris.util._build_full_slice_given_keys(keys, self.ndim) - try: - first_slice = slice_gen.next() - except StopIteration: - first_slice = None + def new_coord_dims(coord_): + return [dimension_mapping[d] + for d in self.coord_dims(coord_) + if dimension_mapping[d] is not None] - if first_slice is not None: - data = self._my_data[first_slice] - else: - data = copy.deepcopy(self._my_data) + def new_cell_measure_dims(cm_): + return [dimension_mapping[d] + for d in self.cell_measure_dims(cm_) + if dimension_mapping[d] is not None] + + # Fetch the data as a generic array-like object. + cube_data = self._data_manager.core_data() - for other_slice in slice_gen: - data = data[other_slice] + # Index with the keys, using orthogonal slicing. + dimension_mapping, data = iris.util._slice_data_with_keys( + cube_data, keys) - # We don't want a view of the data, so take a copy of it if it's - # not already our own. - if isinstance(data, biggus.Array) or not data.flags['OWNDATA']: - data = copy.deepcopy(data) + # We don't want a view of the data, so take a copy of it. + data = deepcopy(data) - # We can turn a masked array into a normal array if it's full. - if isinstance(data, ma.core.MaskedArray): - if ma.count_masked(data) == 0: - data = data.filled() + # XXX: Slicing a single item from a masked array that is masked, + # results in numpy (v1.11.1) *always* returning a MaskedConstant + # with a dtype of float64, regardless of the original masked + # array dtype! + if isinstance(data, ma.core.MaskedConstant) and \ + data.dtype != cube_data.dtype: + data = ma.array(data.data, mask=data.mask, dtype=cube_data.dtype) # Make the new cube slice cube = Cube(data) - cube.metadata = copy.deepcopy(self.metadata) + cube.metadata = deepcopy(self.metadata) # Record a mapping from old coordinate IDs to new coordinates, # for subsequent use in creating updated aux_factories. @@ -1890,11 +2202,21 @@ def __getitem__(self, keys): for factory in self.aux_factories: cube.add_aux_factory(factory.updated(coord_mapping)) + # slice the cell measures and add them to the cube + for cellmeasure in self.cell_measures(): + dims = self.cell_measure_dims(cellmeasure) + cm_keys = tuple([full_slice[dim] for dim in dims]) + new_cm = cellmeasure[cm_keys] + cube.add_cell_measure(new_cm, + new_cell_measure_dims(cellmeasure)) + return cube def subset(self, coord): """ - Get a subset of the cube by providing the desired resultant coordinate. + Get a subset of the cube by providing the desired resultant + coordinate. If the coordinate provided applies to the whole cube; the + whole cube is returned. As such, the operation is not strict. """ if not isinstance(coord, iris.coords.Coord): @@ -1902,24 +2224,42 @@ def subset(self, coord): # Get the coord to extract from the cube coord_to_extract = self.coord(coord) - if len(self.coord_dims(coord_to_extract)) > 1: - msg = "Currently, only 1D coords can be used to subset a cube" - raise iris.exceptions.CoordinateMultiDimError(msg) - # Identify the dimension of the cube which this coordinate references - coord_to_extract_dim = self.coord_dims(coord_to_extract)[0] - - # Identify the indices which intersect the requested coord and - # coord_to_extract - coordinate_indices = coord_to_extract.intersect(coord, - return_indices=True) - - # Build up a slice which spans the whole of the cube - full_slice = [slice(None, None)] * len(self.shape) - # Update the full slice to only extract specific indices which were - # identified above - full_slice[coord_to_extract_dim] = coordinate_indices - full_slice = tuple(full_slice) - return self[full_slice] + + # If scalar, return the whole cube. Not possible to subset 1 point. + if coord_to_extract in self.aux_coords and\ + len(coord_to_extract.points) == 1: + + # Default to returning None + result = None + + indices = coord_to_extract.intersect(coord, return_indices=True) + + # If there is an intersect between the two scalar coordinates; + # return the whole cube. Else, return None. + if len(indices): + result = self + + else: + if len(self.coord_dims(coord_to_extract)) > 1: + msg = "Currently, only 1D coords can be used to subset a cube" + raise iris.exceptions.CoordinateMultiDimError(msg) + # Identify the dimension of the cube which this coordinate + # references + coord_to_extract_dim = self.coord_dims(coord_to_extract)[0] + + # Identify the indices which intersect the requested coord and + # coord_to_extract + coord_indices = coord_to_extract.intersect(coord, + return_indices=True) + + # Build up a slice which spans the whole of the cube + full_slice = [slice(None, None)] * len(self.shape) + # Update the full slice to only extract specific indices which + # were identified above + full_slice[coord_to_extract_dim] = coord_indices + full_slice = tuple(full_slice) + result = self[full_slice] + return result def extract(self, constraint): """ @@ -1931,27 +2271,411 @@ def extract(self, constraint): constraint = iris._constraints.as_constraint(constraint) return constraint.extract(self) + def intersection(self, *args, **kwargs): + """ + Return the intersection of the cube with specified coordinate + ranges. + + Coordinate ranges can be specified as: + + (a) instances of :class:`iris.coords.CoordExtent`. + + (b) keyword arguments, where the keyword name specifies the name + of the coordinate (as defined in :meth:`iris.cube.Cube.coords()`) + and the value defines the corresponding range of coordinate + values as a tuple. The tuple must contain two, three, or four + items corresponding to: (minimum, maximum, min_inclusive, + max_inclusive). Where the items are defined as: + + * minimum + The minimum value of the range to select. + + * maximum + The maximum value of the range to select. + + * min_inclusive + If True, coordinate values equal to `minimum` will be included + in the selection. Default is True. + + * max_inclusive + If True, coordinate values equal to `maximum` will be included + in the selection. Default is True. + + To perform an intersection that ignores any bounds on the coordinates, + set the optional keyword argument *ignore_bounds* to True. Defaults to + False. + + .. note:: + + For ranges defined over "circular" coordinates (i.e. those + where the `units` attribute has a modulus defined) the cube + will be "rolled" to fit where neccesary. + + .. warning:: + + Currently this routine only works with "circular" + coordinates (as defined in the previous note.) + + For example:: + + >>> import iris + >>> cube = iris.load_cube(iris.sample_data_path('air_temp.pp')) + >>> print(cube.coord('longitude').points[::10]) + [ 0. 37.49999237 74.99998474 112.49996948 \ +149.99996948 + 187.49995422 224.99993896 262.49993896 299.99993896 \ +337.49990845] + >>> subset = cube.intersection(longitude=(30, 50)) + >>> print(subset.coord('longitude').points) + [ 33.74999237 37.49999237 41.24998856 44.99998856 48.74998856] + >>> subset = cube.intersection(longitude=(-10, 10)) + >>> print(subset.coord('longitude').points) + [-7.50012207 -3.75012207 0. 3.75 7.5 ] + + Returns: + A new :class:`~iris.cube.Cube` giving the subset of the cube + which intersects with the requested coordinate intervals. + + """ + result = self + ignore_bounds = kwargs.pop('ignore_bounds', False) + for arg in args: + result = result._intersect(*arg, ignore_bounds=ignore_bounds) + for name, value in six.iteritems(kwargs): + result = result._intersect(name, *value, + ignore_bounds=ignore_bounds) + return result + + def _intersect(self, name_or_coord, minimum, maximum, + min_inclusive=True, max_inclusive=True, + ignore_bounds=False): + coord = self.coord(name_or_coord) + if coord.ndim != 1: + raise iris.exceptions.CoordinateMultiDimError(coord) + if coord.nbounds not in (0, 2): + raise ValueError('expected 0 or 2 bound values per cell') + if minimum > maximum: + raise ValueError('minimum greater than maximum') + modulus = coord.units.modulus + if modulus is None: + raise ValueError('coordinate units with no modulus are not yet' + ' supported') + subsets, points, bounds = self._intersect_modulus(coord, + minimum, maximum, + min_inclusive, + max_inclusive, + ignore_bounds) + + # By this point we have either one or two subsets along the relevant + # dimension. If it's just one subset (which might be a slice or an + # unordered collection of indices) we can simply index the cube + # and we're done. If it's two subsets we need to stitch the two + # pieces together. + # subsets provides a way of slicing the coordinates to ensure that + # they remain contiguous. In doing so, this can mean + # transforming the data (this stitching together of two separate + # pieces). + def make_chunk(key): + chunk = self[key_tuple_prefix + (key,)] + chunk_coord = chunk.coord(coord) + chunk_coord.points = points[(key,)] + if chunk_coord.has_bounds(): + chunk_coord.bounds = bounds[(key,)] + return chunk + + dim, = self.coord_dims(coord) + key_tuple_prefix = (slice(None),) * dim + chunks = [make_chunk(key) for key in subsets] + if len(chunks) == 1: + result = chunks[0] + else: + chunk_data = [chunk.core_data() for chunk in chunks] + if self.has_lazy_data(): + func = da.concatenate + else: + module = ma if ma.isMaskedArray(self.data) else np + func = module.concatenate + data = func(chunk_data, dim) + result = iris.cube.Cube(data) + result.metadata = deepcopy(self.metadata) + + # Record a mapping from old coordinate IDs to new coordinates, + # for subsequent use in creating updated aux_factories. + coord_mapping = {} + + def create_coords(src_coords, add_coord): + # Add copies of the source coordinates, selecting + # the appropriate subsets out of coordinates which + # share the intersection dimension. + preserve_circular = (min_inclusive and max_inclusive and + abs(maximum - minimum) == modulus) + for src_coord in src_coords: + dims = self.coord_dims(src_coord) + if dim in dims: + dim_within_coord = dims.index(dim) + points = np.concatenate([chunk.coord(src_coord).points + for chunk in chunks], + dim_within_coord) + if src_coord.has_bounds(): + bounds = np.concatenate( + [chunk.coord(src_coord).bounds + for chunk in chunks], + dim_within_coord) + else: + bounds = None + result_coord = src_coord.copy(points=points, + bounds=bounds) + + circular = getattr(result_coord, 'circular', False) + if circular and not preserve_circular: + result_coord.circular = False + else: + result_coord = src_coord.copy() + add_coord(result_coord, dims) + coord_mapping[id(src_coord)] = result_coord + + create_coords(self.dim_coords, result.add_dim_coord) + create_coords(self.aux_coords, result.add_aux_coord) + for factory in self.aux_factories: + result.add_aux_factory(factory.updated(coord_mapping)) + return result + + def _intersect_derive_subset(self, coord, points, bounds, inside_indices): + # Return the subsets, i.e. the means to allow the slicing of + # coordinates to ensure that they remain contiguous. + modulus = coord.units.modulus + delta = coord.points[inside_indices] - points[inside_indices] + step = np.rint(np.diff(delta) / modulus) + non_zero_step_indices = np.nonzero(step)[0] + + def dim_coord_subset(): + """ + Derive the subset for dimension coordinates. + + Ensure that we do not wrap if blocks are at the very edge. That + is, if the very edge is wrapped and corresponds to base + period, + stop this unnecessary wraparound. + + """ + # A contiguous block at the start and another at the end. + # (NB. We can't have more than two blocks because we've already + # restricted the coordinate's range to its modulus). + end_of_first_chunk = non_zero_step_indices[0] + index_of_second_chunk = inside_indices[end_of_first_chunk + 1] + final_index = points.size - 1 + + # Condition1: The two blocks don't themselves wrap + # (inside_indices is contiguous). + # Condition2: Are we chunked at either extreme edge. + edge_wrap = ((index_of_second_chunk == + inside_indices[end_of_first_chunk] + 1) and + index_of_second_chunk in (final_index, 1)) + subsets = None + if edge_wrap: + # Increasing coord + if coord.points[-1] > coord.points[0]: + index_end = -1 + index_start = 0 + # Decreasing coord + else: + index_end = 0 + index_start = -1 + + # Unwrap points and bounds (if present and equal base + period) + if bounds is not None: + edge_equal_base_period = ( + np.isclose(coord.bounds[index_end, index_end], + coord.bounds[index_start, index_start] + + modulus)) + if edge_equal_base_period: + bounds[index_end, :] = coord.bounds[index_end, :] + else: + edge_equal_base_period = ( + np.isclose(coord.points[index_end], + coord.points[index_start] + + modulus)) + if edge_equal_base_period: + points[index_end] = coord.points[index_end] + subsets = [slice(inside_indices[0], + inside_indices[-1] + 1)] + + # Either no edge wrap or edge wrap != base + period + # i.e. derive subset without alteration + if subsets is None: + subsets = [ + slice(index_of_second_chunk, None), + slice(None, inside_indices[end_of_first_chunk] + 1) + ] + + return subsets + + if isinstance(coord, iris.coords.DimCoord): + if non_zero_step_indices.size: + subsets = dim_coord_subset() + else: + # A single, contiguous block. + subsets = [slice(inside_indices[0], inside_indices[-1] + 1)] + else: + # An AuxCoord could have its values in an arbitrary + # order, and hence a range of values can select an + # arbitrary subset. Also, we want to preserve the order + # from the original AuxCoord. So we just use the indices + # directly. + subsets = [inside_indices] + return subsets + + def _intersect_modulus(self, coord, minimum, maximum, min_inclusive, + max_inclusive, ignore_bounds): + modulus = coord.units.modulus + if maximum > minimum + modulus: + raise ValueError("requested range greater than coordinate's" + " unit's modulus") + if coord.has_bounds(): + values = coord.bounds + else: + values = coord.points + if values.max() > values.min() + modulus: + raise ValueError("coordinate's range greater than coordinate's" + " unit's modulus") + min_comp = np.less_equal if min_inclusive else np.less + max_comp = np.less_equal if max_inclusive else np.less + + if coord.has_bounds(): + bounds = wrap_lons(coord.bounds, minimum, modulus) + if ignore_bounds: + points = wrap_lons(coord.points, minimum, modulus) + inside_indices, = np.where( + np.logical_and(min_comp(minimum, points), + max_comp(points, maximum))) + else: + inside = np.logical_and(min_comp(minimum, bounds), + max_comp(bounds, maximum)) + inside_indices, = np.where(np.any(inside, axis=1)) + + # To ensure that bounds (and points) of matching cells aren't + # "scrambled" by the wrap operation we detect split cells that + # straddle the wrap point and choose a new wrap point which avoids + # split cells. + # For example: the cell [349.875, 350.4375] wrapped at -10 would + # become [349.875, -9.5625] which is no longer valid. The lower + # cell bound value (and possibly associated point) are + # recalculated so that they are consistent with the extended + # wrapping scheme which moves the wrap point to the correct lower + # bound value (-10.125) thus resulting in the cell no longer + # being split. For bounds which may extend exactly the length of + # the modulus, we simply preserve the point to bound difference, + # and call the new bounds = the new points + the difference. + pre_wrap_delta = np.diff(coord.bounds[inside_indices]) + post_wrap_delta = np.diff(bounds[inside_indices]) + close_enough = np.allclose(pre_wrap_delta, post_wrap_delta) + if not close_enough: + split_cell_indices, _ = np.where(pre_wrap_delta != + post_wrap_delta) + + # Recalculate the extended minimum. + indices = inside_indices[split_cell_indices] + cells = bounds[indices] + cells_delta = np.diff(coord.bounds[indices]) + + # Watch out for ascending/descending bounds + if cells_delta[0, 0] > 0: + cells[:, 0] = cells[:, 1] - cells_delta[:, 0] + minimum = np.min(cells[:, 0]) + else: + cells[:, 1] = cells[:, 0] + cells_delta[:, 0] + minimum = np.min(cells[:, 1]) + + points = wrap_lons(coord.points, minimum, modulus) + + bound_diffs = coord.points[:, np.newaxis] - coord.bounds + bounds = points[:, np.newaxis] - bound_diffs + else: + points = wrap_lons(coord.points, minimum, modulus) + bounds = None + inside_indices, = np.where( + np.logical_and(min_comp(minimum, points), + max_comp(points, maximum))) + + # Determine the subsets + subsets = self._intersect_derive_subset(coord, points, bounds, + inside_indices) + return subsets, points, bounds + def _as_list_of_coords(self, names_or_coords): """ Convert a name, coord, or list of names/coords to a list of coords. """ # If not iterable, convert to list of a single item - if not hasattr(names_or_coords, '__iter__'): + if _is_single_item(names_or_coords): names_or_coords = [names_or_coords] coords = [] for name_or_coord in names_or_coords: - if (isinstance(name_or_coord, basestring) or + if (isinstance(name_or_coord, six.string_types) or isinstance(name_or_coord, iris.coords.Coord)): coords.append(self.coord(name_or_coord)) else: # Don't know how to handle this type - msg = "Don't know how to handle coordinate of type %s. " \ - "Ensure all coordinates are of type basestring or " \ - "iris.coords.Coord." % type(name_or_coord) + msg = ("Don't know how to handle coordinate of type %s. " + "Ensure all coordinates are of type six.string_types " + "or iris.coords.Coord.") % (type(name_or_coord), ) raise TypeError(msg) return coords + def slices_over(self, ref_to_slice): + """ + Return an iterator of all subcubes along a given coordinate or + dimension index, or multiple of these. + + Args: + + * ref_to_slice (string, coord, dimension index or a list of these): + Determines which dimensions will be iterated along (i.e. the + dimensions that are not returned in the subcubes). + A mix of input types can also be provided. + + Returns: + An iterator of subcubes. + + For example, to get all subcubes along the time dimension:: + + for sub_cube in cube.slices_over('time'): + print(sub_cube) + + .. seealso:: :meth:`iris.cube.Cube.slices`. + + .. note:: + + The order of dimension references to slice along does not affect + the order of returned items in the iterator; instead the ordering + is based on the fastest-changing dimension. + + """ + # Required to handle a mix between types. + if _is_single_item(ref_to_slice): + ref_to_slice = [ref_to_slice] + + slice_dims = set() + for ref in ref_to_slice: + try: + coord, = self._as_list_of_coords(ref) + except TypeError: + dim = int(ref) + if dim < 0 or dim > self.ndim: + msg = ('Requested an iterator over a dimension ({}) ' + 'which does not exist.'.format(dim)) + raise ValueError(msg) + # Convert coord index to a single-element list to prevent a + # TypeError when `slice_dims.update` is called with it. + dims = [dim] + else: + dims = self.coord_dims(coord) + slice_dims.update(dims) + + all_dims = set(range(self.ndim)) + opposite_dims = list(all_dims - slice_dims) + return self.slices(opposite_dims, ordered=False) + def slices(self, ref_to_slice, ordered=True): """ Return an iterator of all subcubes given the coordinates or dimension @@ -1979,14 +2703,16 @@ def slices(self, ref_to_slice, ordered=True): multi-dimensional cube:: for sub_cube in cube.slices(['longitude', 'latitude']): - print sub_cube + print(sub_cube) + + .. seealso:: :meth:`iris.cube.Cube.slices_over`. """ if not isinstance(ordered, bool): raise TypeError("'ordered' argument to slices must be boolean.") # Required to handle a mix between types - if not hasattr(ref_to_slice, '__iter__'): + if _is_single_item(ref_to_slice): ref_to_slice = [ref_to_slice] dim_to_slice = [] @@ -2028,32 +2754,6 @@ def slices(self, ref_to_slice, ordered=True): return _SliceIterator(self, dims_index, dim_to_slice, ordered) - # TODO: This is not used anywhere. Remove. - @property - def title(self): - title = '%s with ' % self.name().replace('_', ' ').capitalize() - attribute_str_list = [] - for coord in self.coords(): - if coord.shape == (1,): - cell = coord.cell(0) - if coord.has_points(): - attribute_str_list.append( - '%s: %s' % (coord.name(), cell.point)) - elif coord.has_bounds(): - attribute_str_list.append('%s: between %s & %s' % ( - coord.name(), cell.bound[0], cell.bound[1])) - - current_len = len(title) - for i, line in enumerate(attribute_str_list): - if (current_len + len(line)) > 90: - attribute_str_list[i] = '\n' + line - current_len = len(line) - else: - current_len += len(line) - - title = title + ', '.join(attribute_str_list) - return title - def transpose(self, new_order=None): """ Re-order the data dimensions of the cube in-place. @@ -2067,34 +2767,42 @@ def transpose(self, new_order=None): Example usage:: # put the second dimension first, followed by the third dimension, - and finally put the first dimension third cube.transpose([1, 2, 0]) + and finally put the first dimension third:: + + >>> cube.transpose([1, 2, 0]) """ if new_order is None: - new_order = np.arange(self.data.ndim)[::-1] - elif len(new_order) != self.data.ndim: + new_order = np.arange(self.ndim)[::-1] + + # `new_order` must be an iterable for checking with `self.ndim`. + # Dask transpose only supports lists, so ensure `new_order` is + # always a list. + new_order = list(new_order) + + if len(new_order) != self.ndim: raise ValueError('Incorrect number of dimensions.') - # The data needs to be copied, otherwise this view of the transposed - # data will not be contiguous. Ensure not to assign via the cube.data - # setter property since we are reshaping the cube payload in-place. - self._my_data = np.transpose(self.data, new_order).copy() + # Transpose the data payload. + dm = self._data_manager + data = dm.core_data().transpose(new_order) + self._data_manager = DataManager(data) dim_mapping = {src: dest for dest, src in enumerate(new_order)} def remap_dim_coord(coord_and_dim): coord, dim = coord_and_dim return coord, dim_mapping[dim] - self._dim_coords_and_dims = map(remap_dim_coord, - self._dim_coords_and_dims) + self._dim_coords_and_dims = list(map(remap_dim_coord, + self._dim_coords_and_dims)) def remap_aux_coord(coord_and_dims): coord, dims = coord_and_dims return coord, tuple(dim_mapping[dim] for dim in dims) - self._aux_coords_and_dims = map(remap_aux_coord, - self._aux_coords_and_dims) + self._aux_coords_and_dims = list(map(remap_aux_coord, + self._aux_coords_and_dims)) - def xml(self, checksum=False, order=True): + def xml(self, checksum=False, order=True, byteorder=True): """ Returns a fully valid CubeML string representation of the Cube. @@ -2102,14 +2810,15 @@ def xml(self, checksum=False, order=True): doc = Document() cube_xml_element = self._xml_element(doc, checksum=checksum, - order=order) + order=order, + byteorder=byteorder) cube_xml_element.setAttribute("xmlns", XML_NAMESPACE_URI) doc.appendChild(cube_xml_element) # Print our newly created XML return doc.toprettyxml(indent=" ") - def _xml_element(self, doc, checksum=False, order=True): + def _xml_element(self, doc, checksum=False, order=True, byteorder=True): cube_xml_element = doc.createElement("cube") if self.standard_name: @@ -2119,15 +2828,28 @@ def _xml_element(self, doc, checksum=False, order=True): if self.var_name: cube_xml_element.setAttribute('var_name', self.var_name) cube_xml_element.setAttribute('units', str(self.units)) + cube_xml_element.setAttribute('dtype', self.dtype.name) if self.attributes: attributes_element = doc.createElement('attributes') - for name in sorted(self.attributes.iterkeys()): + for name in sorted(six.iterkeys(self.attributes)): attribute_element = doc.createElement('attribute') attribute_element.setAttribute('name', name) - value = str(self.attributes[name]) + + value = self.attributes[name] + # Strict check because we don't want namedtuples. + if type(value) in (list, tuple): + delimiter = '[]' if isinstance(value, list) else '()' + value = ', '.join(("'%s'" + if isinstance(item, six.string_types) + else '%s') % (item, ) for item in value) + value = delimiter[0] + value + delimiter[1] + else: + value = str(value) + attribute_element.setAttribute('value', value) attributes_element.appendChild(attribute_element) + cube_xml_element.appendChild(attributes_element) coords_xml_element = doc.createElement("coords") @@ -2171,22 +2893,22 @@ def normalise(data): data.dtype = data.dtype.newbyteorder('<') return data - if isinstance(data, ma.MaskedArray): + if ma.isMaskedArray(data): # Fill in masked values to avoid the checksum being # sensitive to unused numbers. Use a fixed value so # a change in fill_value doesn't affect the # checksum. - crc = hex(zlib.crc32(normalise(data.filled(0)))) + crc = '0x%08x' % ( + zlib.crc32(normalise(data.filled(0))) & 0xffffffff, ) data_xml_element.setAttribute("checksum", crc) if ma.is_masked(data): - crc = hex(zlib.crc32(normalise(data.mask))) + crc = '0x%08x' % ( + zlib.crc32(normalise(data.mask)) & 0xffffffff, ) else: crc = 'no-masked-elements' data_xml_element.setAttribute("mask_checksum", crc) - data_xml_element.setAttribute('fill_value', - str(data.fill_value)) else: - crc = hex(zlib.crc32(normalise(data))) + crc = '0x%08x' % (zlib.crc32(normalise(data)) & 0xffffffff, ) data_xml_element.setAttribute("checksum", crc) elif self.has_lazy_data(): data_xml_element.setAttribute("state", "deferred") @@ -2212,11 +2934,12 @@ def _order(array): # NB. dtype.byteorder can return '=', which is bad for # cross-platform consistency - so we use dtype.str # instead. - byte_order = {'>': 'big', '<': 'little'}.get(dtype.str[0]) - if byte_order: - data_xml_element.setAttribute('byteorder', byte_order) + if byteorder: + array_byteorder = {'>': 'big', '<': 'little'}.get(dtype.str[0]) + if array_byteorder is not None: + data_xml_element.setAttribute('byteorder', array_byteorder) - if order and isinstance(data, ma.core.MaskedArray): + if order and ma.isMaskedArray(data): data_xml_element.setAttribute('mask_order', _order(data.mask)) else: @@ -2240,7 +2963,9 @@ def copy(self, data=None): A copy instance of the :class:`Cube`. """ - return self._deepcopy({}, data) + memo = {} + cube = self._deepcopy(memo, data=data) + return cube def __copy__(self): """Shallow copying is disallowed for Cubes.""" @@ -2251,43 +2976,28 @@ def __deepcopy__(self, memo): return self._deepcopy(memo) def _deepcopy(self, memo, data=None): - if data is None: - if not self.has_lazy_data() and self.ndim == 0: - # Cope with NumPy's asymmetric (aka. "annoying!") behaviour - # of deepcopy on 0-d arrays. - new_cube_data = np.asanyarray(self.data) - else: - new_cube_data = copy.copy(self._my_data) - else: - if not isinstance(data, biggus.Array): - data = np.asanyarray(data) - - if data.shape != self.shape: - msg = 'Cannot copy cube with new data of a different shape ' \ - '(slice or subset the cube first).' - raise ValueError(msg) + dm = self._data_manager.copy(data=data) - new_cube_data = data - - new_dim_coords_and_dims = copy.deepcopy(self._dim_coords_and_dims, - memo) - new_aux_coords_and_dims = copy.deepcopy(self._aux_coords_and_dims, - memo) + new_dim_coords_and_dims = deepcopy(self._dim_coords_and_dims, memo) + new_aux_coords_and_dims = deepcopy(self._aux_coords_and_dims, memo) # Record a mapping from old coordinate IDs to new coordinates, # for subsequent use in creating updated aux_factories. coord_mapping = {} + for old_pair, new_pair in zip(self._dim_coords_and_dims, new_dim_coords_and_dims): coord_mapping[id(old_pair[0])] = new_pair[0] + for old_pair, new_pair in zip(self._aux_coords_and_dims, new_aux_coords_and_dims): coord_mapping[id(old_pair[0])] = new_pair[0] - new_cube = Cube(new_cube_data, + new_cube = Cube(dm.core_data(), dim_coords_and_dims=new_dim_coords_and_dims, aux_coords_and_dims=new_aux_coords_and_dims) - new_cube.metadata = copy.deepcopy(self.metadata, memo) + + new_cube.metadata = deepcopy(self.metadata, memo) for factory in self.aux_factories: new_cube.add_aux_factory(factory.updated(coord_mapping)) @@ -2322,56 +3032,49 @@ def __ne__(self, other): result = not result return result + # Must supply __hash__ as Python 3 does not enable it if __eq__ is defined. + # NOTE: Violates "objects which compare equal must have the same hash". + # We ought to remove this, as equality of two cube can *change*, so they + # really should not be hashable. + # However, current code needs it, e.g. so we can put them in sets. + # Fixing it will require changing those uses. See #962 and #1772. + def __hash__(self): + return hash(id(self)) + def __add__(self, other): - return iris.analysis.maths.add(self, other, ignore=True) + return iris.analysis.maths.add(self, other) + + def __iadd__(self, other): + return iris.analysis.maths.add(self, other, in_place=True) + __radd__ = __add__ def __sub__(self, other): - return iris.analysis.maths.subtract(self, other, ignore=True) + return iris.analysis.maths.subtract(self, other) + + def __isub__(self, other): + return iris.analysis.maths.subtract(self, other, in_place=True) __mul__ = iris.analysis.maths.multiply __rmul__ = iris.analysis.maths.multiply - __div__ = iris.analysis.maths.divide - __truediv__ = iris.analysis.maths.divide - __pow__ = iris.analysis.maths.exponentiate - # END OPERATOR OVERLOADS - def add_history(self, string): - """ - Add the given string to the cube's history. - If the history coordinate does not exist, then one will be created. - - .. deprecated:: 1.6 - Add/modify history metadata within - attr:`~iris.cube.Cube.attributes` as needed. - - """ - warnings.warn("Cube.add_history() has been deprecated - " - "please modify/create cube.attributes['history'] " - "as needed.") + def __imul__(self, other): + return iris.analysis.maths.multiply(self, other, in_place=True) - timestamp = datetime.datetime.now().strftime("%d/%m/%y %H:%M:%S") - string = '%s Iris: %s' % (timestamp, string) - - try: - history = self.attributes['history'] - self.attributes['history'] = '%s\n%s' % (history, string) - except KeyError: - self.attributes['history'] = string + __div__ = iris.analysis.maths.divide - # START ANALYSIS ROUTINES + def __idiv__(self, other): + return iris.analysis.maths.divide(self, other, in_place=True) - regridded = iris.util._wrap_function_for_method( - iris.analysis.interpolate.regrid, - """ - Returns a new cube with values derived from this cube on the - horizontal grid specified by the grid_cube. + __truediv__ = iris.analysis.maths.divide - """) + def __itruediv__(self, other): + return iris.analysis.maths.divide(self, other, in_place=True) - # END ANALYSIS ROUTINES + __pow__ = iris.analysis.maths.exponentiate + # END OPERATOR OVERLOADS - def collapsed(self, coords, aggregator, lazy=False, **kwargs): + def collapsed(self, coords, aggregator, **kwargs): """ Collapse one or more dimensions over the cube given the coordinate/s and an aggregation. @@ -2388,6 +3091,13 @@ def collapsed(self, coords, aggregator, lazy=False, **kwargs): matches the cube. Values for latitude-longitude area weights may be calculated using :func:`iris.analysis.cartography.area_weights`. + Some Iris aggregators support "lazy" evaluation, meaning that + cubes resulting from this method may represent data arrays which are + not computed until the data is requested (e.g. via ``cube.data`` or + ``iris.save``). If lazy evaluation exists for the given aggregator + it will be used wherever possible when this cube's data is itself + a deferred array. + Args: * coords (string, coord or a list of strings/coords): @@ -2399,17 +3109,6 @@ def collapsed(self, coords, aggregator, lazy=False, **kwargs): Kwargs: - * lazy (bool): - When set, the operation expects and will return a cube with a lazy - data array. This is only supported for certain operations using - certain types of aggregator -- see documentation of - :class:`iris.analysis.Aggregator`. - - .. warning:: - - This keyword may in future be replaced by a different method of - controlling the lazy/concrete operations. - * kwargs: Aggregation function keyword arguments. @@ -2423,7 +3122,7 @@ def collapsed(self, coords, aggregator, lazy=False, **kwargs): >>> path = iris.sample_data_path('ostia_monthly.nc') >>> cube = iris.load_cube(path) >>> new_cube = cube.collapsed('longitude', iris.analysis.MEAN) - >>> print new_cube + >>> print(new_cube) surface_temperature / (K) (time: 54; latitude: 18) Dimension coordinates: time x - @@ -2467,7 +3166,6 @@ def collapsed(self, coords, aggregator, lazy=False, **kwargs): cube.collapsed(['latitude', 'longitude'], iris.analysis.VARIANCE) - """ # Convert any coordinate names to coordinates coords = self._as_list_of_coords(coords) @@ -2475,8 +3173,8 @@ def collapsed(self, coords, aggregator, lazy=False, **kwargs): if (isinstance(aggregator, iris.analysis.WeightedAggregator) and not aggregator.uses_weighting(**kwargs)): msg = "Collapsing spatial coordinate {!r} without weighting" - lat_match = filter(lambda coord: 'latitude' in coord.name(), - coords) + lat_match = [coord for coord in coords + if 'latitude' in coord.name()] if lat_match: for coord in lat_match: warnings.warn(msg.format(coord.name())) @@ -2523,17 +3221,11 @@ def collapsed(self, coords, aggregator, lazy=False, **kwargs): # Record the axis(s) argument passed to 'aggregation', so the same is # passed to the 'update_metadata' function. collapse_axis = -1 + + data_result = None + # Perform the actual aggregation. - if lazy: - # Use a lazy operation separately defined by the aggregator, based - # on the cube lazy array. - # NOTE: do not reform the data in this case, as 'lazy_aggregate' - # accepts multiple axes (unlike 'aggregate'). - collapse_axis = dims_to_collapse - data_result = aggregator.lazy_aggregate(self._my_data, - collapse_axis, - **kwargs) - elif aggregator.cell_method == 'peak': + if aggregator.cell_method == 'peak': # The PEAK aggregator must collapse each coordinate separately. untouched_shape = [self.shape[d] for d in untouched_dims] collapsed_shape = [self.shape[d] for d in dims_to_collapse] @@ -2548,8 +3240,27 @@ def collapsed(self, coords, aggregator, lazy=False, **kwargs): axis=-1, **kwargs) data_result = unrolled_data - else: - # Perform the aggregation over the cube data + + # Perform the aggregation in lazy form if possible. + elif (aggregator.lazy_func is not None and self.has_lazy_data()): + # Use a lazy operation separately defined by the aggregator, based + # on the cube lazy array. + # NOTE: do not reform the data in this case, as 'lazy_aggregate' + # accepts multiple axes (unlike 'aggregate'). + collapse_axis = list(dims_to_collapse) + try: + data_result = aggregator.lazy_aggregate(self.lazy_data(), + axis=collapse_axis, + **kwargs) + except TypeError: + # TypeError - when unexpected keywords passed through (such as + # weights to mean) + pass + + # If we weren't able to complete a lazy aggregation, compute it + # directly now. + if data_result is None: + # Perform the (non-lazy) aggregation over the cube data # First reshape the data so that the dimensions being aggregated # over are grouped 'at the end' (i.e. axis=-1). dims_to_collapse = sorted(dims_to_collapse) @@ -2570,10 +3281,10 @@ def collapsed(self, coords, aggregator, lazy=False, **kwargs): data_result = aggregator.aggregate(unrolled_data, axis=-1, **kwargs) - aggregator.update_metadata(collapsed_cube, coords, axis=collapse_axis, **kwargs) - result = aggregator.post_process(collapsed_cube, data_result, **kwargs) + result = aggregator.post_process(collapsed_cube, data_result, coords, + **kwargs) return result def aggregated_by(self, coords, aggregator, **kwargs): @@ -2583,8 +3294,7 @@ def aggregated_by(self, coords, aggregator, **kwargs): A "group coordinate" is a coordinate where repeating values represent a single group, such as a month coordinate on a daily time slice. - TODO: It is not clear if repeating values must be consecutive to form a - group. + Repeated values will form a group even if they are not consecutive. The group coordinates must all be over the same cube dimension. Each common value group identified over all the group-by coordinates is @@ -2606,6 +3316,10 @@ def aggregated_by(self, coords, aggregator, **kwargs): Returns: :class:`iris.cube.Cube`. + .. note:: + + This operation does not yet have support for lazy evaluation. + For example: >>> import iris @@ -2615,7 +3329,7 @@ def aggregated_by(self, coords, aggregator, **kwargs): >>> cube = iris.load_cube(fname, 'surface_temperature') >>> cat.add_year(cube, 'time', name='year') >>> new_cube = cube.aggregated_by('year', iris.analysis.MEAN) - >>> print new_cube + >>> print(new_cube) surface_temperature / (K) \ (time: 5; latitude: 18; longitude: 432) Dimension coordinates: @@ -2646,11 +3360,11 @@ def aggregated_by(self, coords, aggregator, **kwargs): # We can't handle weights if isinstance(aggregator, iris.analysis.WeightedAggregator) and \ aggregator.uses_weighting(**kwargs): - raise ValueError('Invalid Aggregation, aggergated_by() cannot use' + raise ValueError('Invalid Aggregation, aggregated_by() cannot use' ' weights.') - for coord in sorted(self._as_list_of_coords(coords), - key=lambda coord: coord._as_defn()): + coords = self._as_list_of_coords(coords) + for coord in sorted(coords, key=lambda coord: coord._as_defn()): if coord.ndim > 1: msg = 'Cannot aggregate_by coord %s as it is ' \ 'multidimensional.' % coord.name() @@ -2669,14 +3383,15 @@ def aggregated_by(self, coords, aggregator, **kwargs): # Determine the other coordinates that share the same group-by # coordinate dimension. - shared_coords = filter(lambda coord_: coord_ not in groupby_coords, - self.coords(dimensions=dimension_to_groupby)) + shared_coords = list(filter( + lambda coord_: coord_ not in groupby_coords, + self.coords(dimensions=dimension_to_groupby))) # Create the aggregation group-by instance. groupby = iris.analysis._Groupby(groupby_coords, shared_coords) # Create the resulting aggregate-by cube and remove the original - # coordinates which are going to be groupedby. + # coordinates that are going to be groupedby. key = [slice(None, None)] * self.ndim # Generate unique index tuple key to maintain monotonicity. key[dimension_to_groupby] = tuple(range(len(groupby))) @@ -2686,7 +3401,7 @@ def aggregated_by(self, coords, aggregator, **kwargs): aggregateby_cube.remove_coord(coord) # Determine the group-by cube data shape. - data_shape = list(self.shape) + data_shape = list(self.shape + aggregator.aggregate_shape(**kwargs)) data_shape[dimension_to_groupby] = len(groupby) # Aggregate the group-by data. @@ -2707,7 +3422,7 @@ def aggregated_by(self, coords, aggregator, **kwargs): # Determine aggregation result data type for the aggregate-by cube # data on first pass. if i == 0: - if isinstance(self.data, ma.MaskedArray): + if ma.isMaskedArray(self.data): aggregateby_data = ma.zeros(data_shape, dtype=result.dtype) else: aggregateby_data = np.zeros(data_shape, dtype=result.dtype) @@ -2730,8 +3445,11 @@ def aggregated_by(self, coords, aggregator, **kwargs): else: aggregateby_cube.add_aux_coord(coord.copy(), dimension_to_groupby) - # Attatch the aggregate-by data into the aggregate-by cube. - aggregateby_cube.data = aggregateby_data + + # Attach the aggregate-by data into the aggregate-by cube. + aggregateby_cube = aggregator.post_process(aggregateby_cube, + aggregateby_data, + coords, **kwargs) return aggregateby_cube @@ -2760,12 +3478,16 @@ def rolling_window(self, coord, aggregator, window, **kwargs): Returns: :class:`iris.cube.Cube`. + .. note:: + + This operation does not yet have support for lazy evaluation. + For example: >>> import iris, iris.analysis >>> fname = iris.sample_data_path('GloSea4', 'ensemble_010.pp') >>> air_press = iris.load_cube(fname, 'surface_temperature') - >>> print air_press + >>> print(air_press) surface_temperature / (K) \ (time: 6; latitude: 145; longitude: 192) Dimension coordinates: @@ -2783,12 +3505,13 @@ def rolling_window(self, coord, aggregator, window, **kwargs): realization: 10 Attributes: STASH: m01s00i024 - source: Data from Met Office Unified Model 7.06 + source: Data from Met Office Unified Model + um_version: 7.6 Cell methods: mean: time (1 hour) - >>> print air_press.rolling_window('time', iris.analysis.MEAN, 3) + >>> print(air_press.rolling_window('time', iris.analysis.MEAN, 3)) surface_temperature / (K) \ (time: 4; latitude: 145; longitude: 192) Dimension coordinates: @@ -2806,7 +3529,8 @@ def rolling_window(self, coord, aggregator, window, **kwargs): realization: 10 Attributes: STASH: m01s00i024 - source: Data from Met Office Unified Model 7.06 + source: Data from Met Office Unified Model + um_version: 7.6 Cell methods: mean: time (1 hour) mean: time @@ -2866,10 +3590,20 @@ def rolling_window(self, coord, aggregator, window, **kwargs): new_bounds = iris.util.rolling_window(coord_.points, window) - # Take the first and last element of the rolled window (i.e. the - # bounds) - new_bounds = new_bounds[:, (0, -1)] - new_points = np.mean(new_bounds, axis=-1) + if np.issubdtype(new_bounds.dtype, np.str_): + # Handle case where the AuxCoord contains string. The points + # are the serialized form of the points contributing to each + # window and the bounds are the first and last points in the + # window as with numeric coordinates. + new_points = np.apply_along_axis(lambda x: '|'.join(x), -1, + new_bounds) + new_bounds = new_bounds[:, (0, -1)] + else: + # Take the first and last element of the rolled window (i.e. + # the bounds) and the new points are the midpoints of these + # bounds. + new_bounds = new_bounds[:, (0, -1)] + new_points = np.mean(new_bounds, axis=-1) # wipe the coords points and set the bounds new_coord = new_cube.coord(coord_) @@ -2883,25 +3617,135 @@ def rolling_window(self, coord, aggregator, window, **kwargs): **kwargs) # and perform the data transformation, generating weights first if # needed - newkwargs = {} if isinstance(aggregator, iris.analysis.WeightedAggregator) and \ aggregator.uses_weighting(**kwargs): - if 'weights' in kwargs.keys(): + if 'weights' in kwargs: weights = kwargs['weights'] if weights.ndim > 1 or weights.shape[0] != window: raise ValueError('Weights for rolling window aggregation ' 'must be a 1d array with the same length ' 'as the window.') - newkwargs['weights'] = iris.util.broadcast_to_shape( + kwargs = dict(kwargs) + kwargs['weights'] = iris.util.broadcast_to_shape( weights, rolling_window_data.shape, (dimension + 1,)) - new_cube.data = aggregator.aggregate(rolling_window_data, - axis=dimension + 1, - **newkwargs) + data_result = aggregator.aggregate(rolling_window_data, + axis=dimension + 1, + **kwargs) + result = aggregator.post_process(new_cube, data_result, [coord], + **kwargs) + return result - return new_cube + def interpolate(self, sample_points, scheme, collapse_scalar=True): + """ + Interpolate from this :class:`~iris.cube.Cube` to the given + sample points using the given interpolation scheme. + + Args: + + * sample_points: + A sequence of (coordinate, points) pairs over which to + interpolate. The values for coordinates that correspond to + dates or times may optionally be supplied as datetime.datetime or + cftime.datetime instances. + * scheme: + The type of interpolation to use to interpolate from this + :class:`~iris.cube.Cube` to the given sample points. The + interpolation schemes currently available in Iris are: + + * :class:`iris.analysis.Linear`, and + * :class:`iris.analysis.Nearest`. + + Kwargs: + + * collapse_scalar: + Whether to collapse the dimension of scalar sample points + in the resulting cube. Default is True. + + Returns: + A cube interpolated at the given sample points. + If `collapse_scalar` is True then the dimensionality of the cube + will be the number of original cube dimensions minus + the number of scalar coordinates. + For example: + + >>> import datetime + >>> import iris + >>> path = iris.sample_data_path('uk_hires.pp') + >>> cube = iris.load_cube(path, 'air_potential_temperature') + >>> print(cube.summary(shorten=True)) + air_potential_temperature / (K) \ +(time: 3; model_level_number: 7; grid_latitude: 204; grid_longitude: 187) + >>> print(cube.coord('time')) + DimCoord([2009-11-19 10:00:00, 2009-11-19 11:00:00, \ +2009-11-19 12:00:00], standard_name='time', calendar='gregorian') + >>> print(cube.coord('time').points) + [349618. 349619. 349620.] + >>> samples = [('time', 349618.5)] + >>> result = cube.interpolate(samples, iris.analysis.Linear()) + >>> print(result.summary(shorten=True)) + air_potential_temperature / (K) \ +(model_level_number: 7; grid_latitude: 204; grid_longitude: 187) + >>> print(result.coord('time')) + DimCoord([2009-11-19 10:30:00], standard_name='time', \ +calendar='gregorian') + >>> print(result.coord('time').points) + [349618.5] + >>> # For datetime-like coordinates, we can also use + >>> # datetime-like objects. + >>> samples = [('time', datetime.datetime(2009, 11, 19, 10, 30))] + >>> result2 = cube.interpolate(samples, iris.analysis.Linear()) + >>> print(result2.summary(shorten=True)) + air_potential_temperature / (K) \ +(model_level_number: 7; grid_latitude: 204; grid_longitude: 187) + >>> print(result2.coord('time')) + DimCoord([2009-11-19 10:30:00], standard_name='time', \ +calendar='gregorian') + >>> print(result2.coord('time').points) + [349618.5] + >>> print(result == result2) + True + + """ + coords, points = zip(*sample_points) + interp = scheme.interpolator(self, coords) + return interp(points, collapse_scalar=collapse_scalar) + + def regrid(self, grid, scheme): + """ + Regrid this :class:`~iris.cube.Cube` on to the given target `grid` + using the given regridding `scheme`. + + Args: + + * grid: + A :class:`~iris.cube.Cube` that defines the target grid. + * scheme: + The type of regridding to use to regrid this cube onto the + target grid. The regridding schemes currently available + in Iris are: + + * :class:`iris.analysis.Linear`, + * :class:`iris.analysis.Nearest`, and + * :class:`iris.analysis.AreaWeighted`. + + Returns: + A cube defined with the horizontal dimensions of the target grid + and the other dimensions from this cube. The data values of + this cube will be converted to values on the new grid + according to the given regridding scheme. -class ClassDict(object, UserDict.DictMixin): + .. note:: + + Both the source and target cubes must have a CoordSystem, otherwise + this function is not applicable. + + """ + regridder = scheme.regridder(self, grid) + return regridder(self) + + +class ClassDict(collections.MutableMapping, object): """ A mapping that stores objects keyed on their superclasses and their names. @@ -2951,14 +3795,24 @@ def __getitem__(self, class_): except KeyError: raise KeyError('Coordinate system %r does not exist.' % class_) + def __setitem__(self, key, value): + raise NotImplementedError('You must call the add method instead.') + def __delitem__(self, class_): cs = self[class_] - keys = [k for k, v in self._retrieval_map.iteritems() if v == cs] + keys = [k for k, v in six.iteritems(self._retrieval_map) if v == cs] for key in keys: del self._retrieval_map[key] del self._basic_map[type(cs)] return cs + def __len__(self): + return len(self._basic_map) + + def __iter__(self): + for item in self._basic_map: + yield item + def keys(self): '''Return the keys of the dictionary mapping.''' return self._basic_map.keys() @@ -2992,9 +3846,9 @@ def __init__(self, cube, dims_index, requested_dims, ordered): self._mod_requested_dims = np.argsort(requested_dims) self._ordered = ordered - def next(self): + def __next__(self): # NB. When self._ndindex runs out it will raise StopIteration for us. - index_tuple = self._ndindex.next() + index_tuple = next(self._ndindex) # Turn the given tuple into a list so that we can do something with it index_list = list(index_tuple) @@ -3008,7 +3862,12 @@ def next(self): cube = self._cube[tuple(index_list)] if self._ordered: - if any(self._mod_requested_dims != range(len(cube.shape))): - cube.transpose(self._mod_requested_dims) + if any(self._mod_requested_dims != list(range(len(cube.shape)))): + n = len(self._mod_requested_dims) + sliced_dims = np.empty(n, dtype=int) + sliced_dims[self._mod_requested_dims] = np.arange(n) + cube.transpose(sliced_dims) return cube + + next = __next__ diff --git a/lib/iris/etc/mosig_codes.txt b/lib/iris/etc/mosig_codes.txt deleted file mode 100644 index acce018dfc..0000000000 --- a/lib/iris/etc/mosig_codes.txt +++ /dev/null @@ -1,1468 +0,0 @@ -# (C) British Crown Copyright 2010 - 2012, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . - -# MOSIG rule #216 -IF -f.lbuser[6] == 06 -f.lbuser[3] == 103 -THEN -CMAttribute("standard_name", "upward_eastward_momentum_flux_in_air_due_to_nonorographic_westward_gravity_waves") -CMAttribute("units", "Pa") - -# MOSIG rule #217 -IF -f.lbuser[6] == 06 -f.lbuser[3] == 201 -THEN -CMAttribute("standard_name", "upward_eastward_momentum_flux_in_air_due_to_orographic_gravity_waves") -CMAttribute("units", "Pa") - -# MOSIG rule #214 -IF -f.lbuser[6] == 03 -f.lbuser[3] == 394 -THEN -CMAttribute("standard_name", "surface_downward_eastward_stress") -CMAttribute("units", "Pa") - -# MOSIG rule #215 -IF -f.lbuser[6] == 06 -f.lbuser[3] == 101 -THEN -CMAttribute("standard_name", "upward_eastward_momentum_flux_in_air_due_to_nonorographic_eastward_gravity_waves") -CMAttribute("units", "Pa") - -# MOSIG rule #212 -IF -f.lbuser[6] == 03 -f.lbuser[3] == 337 -THEN -CMAttribute("standard_name", "downward_heat_flux_in_soil") -CMAttribute("units", "W m-2") - -# MOSIG rule #213 -IF -f.lbuser[6] == 03 -f.lbuser[3] == 392 -THEN -CMAttribute("standard_name", "surface_downward_eastward_stress") -CMAttribute("units", "Pa") - -# MOSIG rule #210 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 1435 -THEN -CMAttribute("standard_name", "surface_downwelling_shortwave_flux_in_air") -CMAttribute("units", "W m-2") - -# MOSIG rule #211 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3334 -THEN -CMAttribute("standard_name", "water_potential_evaporation_flux") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #165 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 102 -THEN -CMAttribute("standard_name", "sea_water_salinity") -CMAttribute("units", "1") - -# MOSIG rule #218 -IF -f.lbuser[6] == 06 -f.lbuser[3] == 207 -THEN -CMAttribute("standard_name", "tendency_of_eastward_wind_due_to_orographic_gravity_wave_drag") -CMAttribute("units", "m s-2") - -# MOSIG rule #219 -IF -f.lbuser[6] == 15 -f.lbuser[3] == 243 -THEN -CMAttribute("standard_name", "eastward_wind") -CMAttribute("units", "m s-1") - -# MOSIG rule #133 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 15220 -THEN -CMAttribute("standard_name", "square_of_eastward_wind") -CMAttribute("units", "???") - -# MOSIG rule #132 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 15219 -THEN -CMAttribute("standard_name", "square_of_air_temperature") -CMAttribute("units", "???") - -# MOSIG rule #131 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 15214 -THEN -CMAttribute("standard_name", "ertel_potential_vorticity") -CMAttribute("units", "???") - -# MOSIG rule #137 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 15224 -THEN -CMAttribute("standard_name", "product_of_eastward_wind_and_omega") -CMAttribute("units", "???") - -# MOSIG rule #136 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 15223 -THEN -CMAttribute("standard_name", "product_of_omega_and_air_temperature") -CMAttribute("units", "???") - -# MOSIG rule #135 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 15222 -THEN -CMAttribute("standard_name", "lagrangian_tendency_of_air_pressure") -CMAttribute("units", "Pa s-1") - -# MOSIG rule #134 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 15221 -THEN -CMAttribute("standard_name", "square_of_northward_wind") -CMAttribute("units", "???") - -# MOSIG rule #139 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 15226 -THEN -CMAttribute("standard_name", "specific_humidity") -CMAttribute("units", "???") - -# MOSIG rule #138 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 15225 -THEN -CMAttribute("standard_name", "product_of_northward_wind_and_omega") -CMAttribute("units", "???") - -# MOSIG rule #27 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 1201 -THEN -CMAttribute("standard_name", "surface_net_downward_shortwave_flux") -CMAttribute("units", "W m-2") - -# MOSIG rule #20 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 205 -THEN -CMAttribute("standard_name", "land_area_fraction") -CMAttribute("units", "%") - -# MOSIG rule #160 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 30406 -THEN -# TODO: Is there a CF standard name for this? -CMAttribute("long_name", "atmosphere_cloud_ice_content") -CMAttribute("units", "kg m-2") - -# MOSIG rule #29 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 1203 -THEN -CMAttribute("standard_name", "surface_net_downward_shortwave_flux_where_open_sea") -CMAttribute("units", "???") - -# MOSIG rule #161 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 30417 -THEN -CMAttribute("standard_name", "surface_air_pressure") -CMAttribute("units", "Pa") - -# MOSIG rule #4 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 4 -THEN -CMAttribute("standard_name", "air_potential_temperature") -CMAttribute("units", "K") - -# MOSIG rule #8 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 13 -THEN -CMAttribute("standard_name", "convective_cloud_area_fraction") -CMAttribute("units", "???") - -# MOSIG rule #119 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 8231 -THEN -CMAttribute("standard_name", "surface_snow_melt_flux_where_land") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #120 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 8234 -THEN -CMAttribute("standard_name", "surface_runoff_flux") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #122 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 8235 -THEN -CMAttribute("standard_name", "subsurface_runoff_flux") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #123 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 9201 -THEN -CMAttribute("standard_name", "large_scale_cloud_area_fraction_of_atmosphere_layer") -CMAttribute("units", "???") - -# MOSIG rule #126 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 12201 -THEN -CMAttribute("standard_name", "lagrangian_tendency_of_air_pressure") -CMAttribute("units", "Pa s-1") - -# MOSIG rule #127 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 15201 -THEN -CMAttribute("standard_name", "eastward_wind") -CMAttribute("units", "m s-1") - -# MOSIG rule #129 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 15202 -THEN -CMAttribute("standard_name", "northward_wind") -CMAttribute("units", "m s-1") - -# MOSIG rule #167 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 121 -THEN -CMAttribute("standard_name", "baroclinic_eastward_sea_water_velocity") -CMAttribute("units", "cm s-1") - -# MOSIG rule #59 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 2238 -THEN -CMAttribute("standard_name", "tropopause_downwelling_longwave_flux") -CMAttribute("units", "???") - -# MOSIG rule #55 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 2232 -THEN -CMAttribute("standard_name", "tendency_of_air_temperature_due_to_longwave_heating") -CMAttribute("units", "???") - -# MOSIG rule #54 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 2208 -THEN -CMAttribute("standard_name", "surface_downwelling_longwave_flux_in_air_assuming_clear_sky") -CMAttribute("units", "W m-2") - -# MOSIG rule #57 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 2237 -THEN -CMAttribute("standard_name", "tropopause_net_downward_longwave_flux") -CMAttribute("units", "???") - -# MOSIG rule #56 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 2233 -THEN -CMAttribute("standard_name", "tendency_of_air_temperature_due_to_longwave_heating_assuming_clear_sky") -CMAttribute("units", "???") - -# MOSIG rule #51 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 2205 -THEN -CMAttribute("standard_name", "toa_outgoing_longwave_flux") -CMAttribute("units", "W m-2") - -# MOSIG rule #53 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 2207 -THEN -CMAttribute("standard_name", "surface_downwelling_longwave_flux_in_air") -CMAttribute("units", "W m-2") - -# MOSIG rule #52 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 2206 -THEN -CMAttribute("standard_name", "toa_outgoing_longwave_flux_assuming_clear_sky") -CMAttribute("units", "W m-2") - -# MOSIG rule #259 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 146 -THEN -CMAttribute("standard_name", "sea_ice_area_fraction") -CMAttribute("units", "%") - -# MOSIG rule #201 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 32211 -THEN -CMAttribute("standard_name", "tendency_of_sea_ice_area_fraction_due_to_thermodynamics") -CMAttribute("units", "???") - -# MOSIG rule #199 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 32209 -THEN -CMAttribute("standard_name", "eastward_sea_ice_velocity") -CMAttribute("units", "m s-1") - -# MOSIG rule #198 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 32202 -THEN -CMAttribute("standard_name", "tendency_of_sea_ice_thickness_due_to_dynamics") -CMAttribute("units", "???") - -# MOSIG rule #200 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 32210 -THEN -CMAttribute("standard_name", "northward_sea_ice_velocity") -CMAttribute("units", "m s-1") - -# MOSIG rule #195 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 30321 -THEN -CMAttribute("standard_name", "northward_sea_water_velocity") -CMAttribute("units", "m s-1") - -# MOSIG rule #197 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 32201 -THEN -CMAttribute("standard_name", "tendency_of_sea_ice_area_fraction_due_to_dynamics") -CMAttribute("units", "???") - -# MOSIG rule #178 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 148 -THEN -CMAttribute("standard_name", "eastward_sea_ice_velocity") -CMAttribute("units", "m s-1") - -# MOSIG rule #190 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 30201 -THEN -CMAttribute("standard_name", "upward_sea_water_velocity") -CMAttribute("units", "m s-1") - -# MOSIG rule #193 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 30320 -THEN -CMAttribute("standard_name", "eastward_sea_water_velocity") -CMAttribute("units", "m s-1") - -# MOSIG rule #192 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 30211 -THEN -CMAttribute("standard_name", "northward_ocean_heat_transport") -CMAttribute("units", "PW") - -# MOSIG rule #115 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 8225 -THEN -CMAttribute("standard_name", "soil_temperature") -CMAttribute("units", "???") - -# MOSIG rule #252 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 8223 -THEN -CMAttribute("standard_name", "soil_moisture_content") -CMAttribute("units", "kg m-2") - -# MOSIG rule #89 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 4204 -THEN -# TODO: Is there a CF standard name for this? -CMAttribute("long_name", "large_scale_snowfall_flux") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #111 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 8209 -THEN -CMAttribute("standard_name", "canopy_water_amount") -CMAttribute("units", "???") - -# MOSIG rule #110 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 8208 -THEN -CMAttribute("standard_name", "soil_moisture_content") -CMAttribute("units", "???") - -# MOSIG rule #82 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3261 -THEN -CMAttribute("standard_name", "gross_primary_productivity_of_carbon") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #83 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3262 -THEN -CMAttribute("standard_name", "net_primary_productivity_of_carbon") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #80 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3249 -THEN -CMAttribute("standard_name", "wind_speed") -CMAttribute("units", "m s-1") - -# MOSIG rule #81 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3258 -THEN -CMAttribute("standard_name", "surface_snow_melt_heat_flux") -CMAttribute("units", "W m-2") - -# MOSIG rule #86 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3332 -THEN -CMAttribute("standard_name", "toa_outgoing_longwave_flux") -CMAttribute("units", "W m-2") - -# MOSIG rule #87 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 4203 -THEN -# TODO: Is there a CF standard name for this? -CMAttribute("long_name", "large_scale_rainfall_rate") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #84 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3295 -THEN -CMAttribute("standard_name", "surface_snow_area_fraction_where_land") -CMAttribute("units", "%") - -# MOSIG rule #85 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3298 -THEN -CMAttribute("standard_name", "water_sublimation_flux") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #207 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 408 -THEN -CMAttribute("standard_name", "air_pressure") -CMAttribute("units", "Pa") - -# MOSIG rule #206 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 31 -THEN -CMAttribute("standard_name", "sea_ice_thickness") -CMAttribute("units", "%") - -# MOSIG rule #226 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33001 -THEN -CMAttribute("standard_name", "mole_fraction_of_ozone_in_air") -CMAttribute("units", "mole mole-1") - -# MOSIG rule #3 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3 -THEN -CMAttribute("standard_name", "northward_wind") -CMAttribute("units", "???") - -# MOSIG rule #225 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 30314 -THEN -CMAttribute("standard_name", "tendency_of_eastward_wind_due_to_eliassen_palm_flux_divergence") -CMAttribute("units", "m s-2") - -# MOSIG rule #245 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33150 -THEN -CMAttribute("standard_name", "age_of_stratospheric_air") -CMAttribute("units", "Years") - -# MOSIG rule #244 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33058 -THEN -CMAttribute("standard_name", "mole_fraction_of_atomic_nitrogen_in_air") -CMAttribute("units", "mole mole-1") - -# MOSIG rule #108 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 8023 -THEN -CMAttribute("standard_name", "surface_snow_amount") -CMAttribute("units", "kg m-2") - -# MOSIG rule #109 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 8202 -THEN -CMAttribute("standard_name", "surface_snow_melt_flux_where_land") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #241 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33054 -THEN -CMAttribute("standard_name", "mole_fraction_of_chlorine_nitrate_in_air") -CMAttribute("units", "mole mole-1") - -# MOSIG rule #240 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33051 -THEN -CMAttribute("standard_name", "mole_fraction_of_hypochlorous_acid_in_air") -CMAttribute("units", "mole mole-1") - -# MOSIG rule #243 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33056 -THEN -CMAttribute("standard_name", "mole_fraction_of_cfc12_in_air") -CMAttribute("units", "mole mole-1") - -# MOSIG rule #242 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33055 -THEN -CMAttribute("standard_name", "mole_fraction_of_cfc11_in_air") -CMAttribute("units", "mole mole-1") - -# MOSIG rule #103 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 5214 -THEN -CMAttribute("standard_name", "rainfall_flux") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #101 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 5213 -THEN -CMAttribute("standard_name", "mass_fraction_of_convective_cloud_liquid_water_in_air") -CMAttribute("units", "1") - -# MOSIG rule #106 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 5233 -THEN -CMAttribute("standard_name", "mass_fraction_of_convective_cloud_liquid_water_in_air") -CMAttribute("units", "1") - -# MOSIG rule #104 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 5215 -THEN -CMAttribute("standard_name", "snowfall_flux") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #105 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 5216 -THEN -CMAttribute("standard_name", "precipitation_flux") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #39 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 1233 -THEN -CMAttribute("standard_name", "tendency_of_air_temperature_due_to_shortwave_heating_assuming_clear_sky") -CMAttribute("units", "???") - -# MOSIG rule #38 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 1232 -THEN -CMAttribute("standard_name", "tendency_of_air_temperature_due_to_shortwave_heating") -CMAttribute("units", "???") - -# MOSIG rule #30 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 1207 -THEN -CMAttribute("standard_name", "toa_incoming_shortwave_flux") -CMAttribute("units", "W m-2") - -# MOSIG rule #37 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 1211 -THEN -CMAttribute("standard_name", "surface_upwelling_shortwave_flux_in_air_assuming_clear_sky") -CMAttribute("units", "W m-2") - -# MOSIG rule #36 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 1210 -THEN -CMAttribute("standard_name", "surface_downwelling_shortwave_flux_in_air_assuming_clear_sky") -CMAttribute("units", "W m-2") - -# MOSIG rule #35 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 1209 -THEN -CMAttribute("standard_name", "toa_outgoing_shortwave_flux_assuming_clear_sky") -CMAttribute("units", "W m-2") - -# MOSIG rule #34 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 1208 -THEN -CMAttribute("standard_name", "toa_outgoing_shortwave_flux") -CMAttribute("units", "W m-2") - -# MOSIG rule #246 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33270 -THEN -CMAttribute("standard_name", "age_of_stratospheric_air") -CMAttribute("units", "Years") - -# MOSIG rule #205 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 43 -THEN -CMAttribute("standard_name", "soil_porosity") -CMAttribute("units", "1") - -# MOSIG rule #223 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 30312 -THEN -CMAttribute("standard_name", "northward_eliassen_palm_flux_in_air") -CMAttribute("units", "m3 s-2") - -# MOSIG rule #176 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 147 -THEN -CMAttribute("standard_name", "sea_ice_thickness") -CMAttribute("units", "m") - -# MOSIG rule #60 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3201 -THEN -CMAttribute("standard_name", "downward_heat_flux_in_sea_ice") -CMAttribute("units", "W m-2") - -# MOSIG rule #61 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3202 -THEN -CMAttribute("standard_name", "downward_heat_flux_in_soil") -CMAttribute("units", "???") - -# MOSIG rule #62 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3217 -THEN -CMAttribute("standard_name", "surface_upward_sensible_heat_flux") -CMAttribute("units", "W m-2") - -# MOSIG rule #63 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3219 -THEN -CMAttribute("standard_name", "surface_downward_eastward_stress") -CMAttribute("units", "Pa") - -# MOSIG rule #64 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3220 -THEN -CMAttribute("standard_name", "surface_downward_northward_stress") -CMAttribute("units", "Pa") - -# MOSIG rule #65 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3223 -THEN -CMAttribute("standard_name", "water_evaporation_flux") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #67 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3224 -THEN -CMAttribute("standard_name", "wind_mixing_energy_flux_into_ocean") -CMAttribute("units", "W m-2") - -# MOSIG rule #68 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3225 -THEN -CMAttribute("standard_name", "eastward_wind") -CMAttribute("units", "m s-1") - -# MOSIG rule #69 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3226 -THEN -CMAttribute("standard_name", "northward_wind") -CMAttribute("units", "m s-1") - -# MOSIG rule #173 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 143 -THEN -CMAttribute("standard_name", "upward_sea_ice_basal_heat_flux") -CMAttribute("units", "W m-2") - -# MOSIG rule #172 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 137 -THEN -CMAttribute("standard_name", "ocean_mixed_layer_thickness") -CMAttribute("units", "m") - -# MOSIG rule #170 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 132 -THEN -CMAttribute("standard_name", "tendency_of_ocean_barotropic_streamfunction") -CMAttribute("units", "???") - -# MOSIG rule #203 -IF -f.lbuser[6] == 03 -f.lbuser[3] == 177 -THEN -CMAttribute("standard_name", "prescribed_heat_flux_into_slab_ocean") -CMAttribute("units", "W m-2") - -# MOSIG rule #222 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 30311 -THEN -CMAttribute("standard_name", "northward_transformed_eulerian_mean_air_velocity") -CMAttribute("units", "m s-1") - -# MOSIG rule #181 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 150 -THEN -CMAttribute("standard_name", "surface_downward_eastward_stress") -CMAttribute("units", "Pa") - -# MOSIG rule #182 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 151 -THEN -CMAttribute("standard_name", "surface_downward_northward_stress") -CMAttribute("units", "Pa") - -# MOSIG rule #183 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 152 -THEN -CMAttribute("standard_name", "wind_mixing_energy_flux_into_ocean") -CMAttribute("units", "W m-2") - -# MOSIG rule #180 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 149 -THEN -CMAttribute("standard_name", "northward_sea_ice_velocity") -CMAttribute("units", "m s-1") - -# MOSIG rule #2 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 2 -THEN -CMAttribute("standard_name", "eastward_wind") -CMAttribute("units", "???") - -# MOSIG rule #187 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 186 -THEN -CMAttribute("standard_name", "water_flux_correction_where_ocean") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #220 -IF -f.lbuser[6] == 15 -f.lbuser[3] == 244 -THEN -CMAttribute("standard_name", "northward_wind") -CMAttribute("units", "m s-1") - -# MOSIG rule #186 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 171 -THEN -CMAttribute("standard_name", "snowfall_flux") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #188 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 190 -THEN -CMAttribute("standard_name", "surface_melt_heat_flux") -CMAttribute("units", "W m-2") - -# MOSIG rule #189 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 191 -THEN -CMAttribute("standard_name", "downward_heat_flux_in_sea_ice") -CMAttribute("units", "W m-2") - -# MOSIG rule #202 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 32212 -THEN -CMAttribute("standard_name", "tendency_of_sea_ice_thickness_due_to_thermodynamics") -CMAttribute("units", "???") - -# MOSIG rule #221 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 30310 -THEN -CMAttribute("standard_name", "northward_transformed_eulerian_mean_air_velocity") -CMAttribute("units", "m s-1") - -# MOSIG rule #185 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 166 -THEN -CMAttribute("standard_name", "water_flux_into_ocean_from_rivers") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #168 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 122 -THEN -CMAttribute("standard_name", "baroclinic_northward_sea_water_velocity") -CMAttribute("units", "cm s-1") - -# MOSIG rule #169 -IF -f.lbuser[6] == 02 -f.lbuser[3] == 130 -THEN -CMAttribute("standard_name", "ocean_barotropic_streamfunction") -CMAttribute("units", "m3 s-1") - -# MOSIG rule #229 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33006 -THEN -CMAttribute("standard_name", "mole_fraction_of_peroxynitric_acid_in_air") -CMAttribute("units", "mole mole-1") - -# MOSIG rule #228 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33005 -THEN -CMAttribute("standard_name", "mole_fraction_of_dinitrogen_pentoxide_in_air") -CMAttribute("units", "mole mole-1") - -# MOSIG rule #90 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 5205 -THEN -CMAttribute("standard_name", "convective_rainfall_rate") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #93 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 5209 -THEN -CMAttribute("standard_name", "air_temperature") -CMAttribute("units", "???") - -# MOSIG rule #92 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 5206 -THEN -CMAttribute("standard_name", "convective_snowfall_flux") -CMAttribute("units", "kg m-2 s-1") - -# MOSIG rule #94 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 5212 -THEN -CMAttribute("standard_name", "convective_cloud_area_fraction_of_atmosphere_layer") -CMAttribute("units", "???") - -# MOSIG rule #11 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 25 -THEN -CMAttribute("standard_name", "atmosphere_boundary_layer_thickness") -CMAttribute("units", "???") - -# MOSIG rule #10 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 24 -THEN -CMAttribute("standard_name", "surface_temperature") -CMAttribute("units", "K") - -# MOSIG rule #13 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 29 -THEN -CMAttribute("standard_name", "northward_sea_water_velocity") -CMAttribute("units", "???") - -# MOSIG rule #12 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 28 -THEN -CMAttribute("standard_name", "eastward_sea_water_velocity") -CMAttribute("units", "???") - -# MOSIG rule #14 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 30 -THEN -CMAttribute("standard_name", "land_area_fraction") -CMAttribute("units", "%") - -# MOSIG rule #17 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33 -THEN -CMAttribute("standard_name", "surface_altitude") -CMAttribute("units", "m") - -# MOSIG rule #16 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 32 -THEN -CMAttribute("standard_name", "sea_ice_thickness") -CMAttribute("units", "m") - -# MOSIG rule #19 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 60 -THEN -CMAttribute("standard_name", "mole_fraction_of_o3_in_air") -CMAttribute("units", "1e-9") - -# MOSIG rule #117 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 8230 -THEN -CMAttribute("standard_name", "mass_fraction_of_frozen_water_in_soil_moisture") -CMAttribute("units", "???") - -# MOSIG rule #116 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 8229 -THEN -CMAttribute("standard_name", "mass_fraction_of_unfrozen_water_in_soil_moisture") -CMAttribute("units", "???") - -# MOSIG rule #204 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 40 -THEN -CMAttribute("standard_name", "volume_fraction_of_water_in_soil_at_wilting_point") -CMAttribute("units", "1") - -# MOSIG rule #151 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 16224 -THEN -CMAttribute("standard_name", "square_of_height") -CMAttribute("units", "???") - -# MOSIG rule #150 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 16222 -THEN -CMAttribute("standard_name", "air_pressure_at_sea_level") -CMAttribute("units", "Pa") - -# MOSIG rule #238 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33048 -THEN -CMAttribute("standard_name", "mole_fraction_of_bromine_nitrate_in_air") -CMAttribute("units", "mole mole-1") - -# MOSIG rule #239 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33049 -THEN -CMAttribute("standard_name", "mole_fraction_of_nitrous_oxide_in_air") -CMAttribute("units", "mole mole-1") - -# MOSIG rule #234 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33042 -THEN -CMAttribute("standard_name", "mole_fraction_of_chlorine_monoxide_in_air") -CMAttribute("units", "mole mole-1") - -# MOSIG rule #235 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33043 -THEN -CMAttribute("standard_name", "mole_fraction_of_dichlorine_peroxide_in_air") -CMAttribute("units", "mole mole-1") - -# MOSIG rule #236 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33044 -THEN -CMAttribute("standard_name", "mole_fraction_of_chlorine_dioxide_in_air") -CMAttribute("units", "mole mole-1") - -# MOSIG rule #237 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33047 -THEN -CMAttribute("standard_name", "mole_fraction_of_bromine_chloride_in_air") -CMAttribute("units", "mole mole-1") - -# MOSIG rule #230 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33007 -THEN -CMAttribute("standard_name", "mole_fraction_of_chlorine_nitrate_in_air") -CMAttribute("units", "mole mole-1") - -# MOSIG rule #231 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33009 -THEN -CMAttribute("standard_name", "mole_fraction_of_methane_in_air") -CMAttribute("units", "mole mole-1") - -# MOSIG rule #233 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33041 -THEN -CMAttribute("standard_name", "mole_fraction_of_atomic_chlorine_in_air") -CMAttribute("units", "mole mole-1") - -# MOSIG rule #224 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 30313 -THEN -CMAttribute("standard_name", "upward_eliassen_palm_flux_in_air") -CMAttribute("units", "m3 s-2") - -# MOSIG rule #48 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 2203 -THEN -CMAttribute("standard_name", "surface_net_downward_longwave_flux_where_open_sea") -CMAttribute("units", "???") - -# MOSIG rule #44 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 1242 -THEN -CMAttribute("standard_name", "large_scale_cloud_liquid_water_content_of_atmosphere_layer") -CMAttribute("units", "???") - -# MOSIG rule #45 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 2201 -THEN -CMAttribute("standard_name", "surface_net_downward_longwave_flux") -CMAttribute("units", "W m-2") - -# MOSIG rule #42 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 1237 -THEN -CMAttribute("standard_name", "net_downward_shortwave_flux_in_air") -CMAttribute("units", "W m-2") - -# MOSIG rule #43 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 1238 -THEN -CMAttribute("standard_name", "tropopause_upwelling_shortwave_flux") -CMAttribute("units", "???") - -# MOSIG rule #40 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 1235 -THEN -CMAttribute("standard_name", "surface_downwelling_shortwave_flux_in_air") -CMAttribute("units", "W m-2") - -# MOSIG rule #1 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 1 -THEN -CMAttribute("standard_name", "surface_air_pressure") -CMAttribute("units", "Pa") - -# MOSIG rule #5 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 10 -THEN -CMAttribute("standard_name", "specific_humidity") -CMAttribute("units", "1") - -# MOSIG rule #9 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 23 -THEN -CMAttribute("standard_name", "surface_snow_amount") -CMAttribute("units", "kg m-2") - -# MOSIG rule #146 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 16202 -THEN -CMAttribute("standard_name", "geopotential_height") -CMAttribute("units", "m") - -# MOSIG rule #147 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 16203 -THEN -CMAttribute("standard_name", "air_temperature") -CMAttribute("units", "K") - -# MOSIG rule #144 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 15239 -THEN -CMAttribute("standard_name", "product_of_eastward_wind_and_geopotential_height") -CMAttribute("units", "???") - -# MOSIG rule #145 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 15240 -THEN -CMAttribute("standard_name", "product_of_northward_wind_and_geopotential_height") -CMAttribute("units", "???") - -# MOSIG rule #142 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 15235 -THEN -CMAttribute("standard_name", "product_of_omega_and_specific_humidity") -CMAttribute("units", "???") - -# MOSIG rule #143 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 15238 -THEN -CMAttribute("standard_name", "geopotential_height") -CMAttribute("units", "???") - -# MOSIG rule #140 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 15227 -THEN -CMAttribute("standard_name", "product_of_eastward_wind_and_specific_humidity") -CMAttribute("units", "???") - -# MOSIG rule #141 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 15228 -THEN -CMAttribute("standard_name", "product_of_northward_wind_and_specific_humidity") -CMAttribute("units", "???") - -# MOSIG rule #209 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 1410 -THEN -CMAttribute("standard_name", "surface_downwelling_shortwave_flux_in_air_assuming_clear_sky") -CMAttribute("units", "W m-2") - -# MOSIG rule #208 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 409 -THEN -CMAttribute("standard_name", "surface_air_pressure") -CMAttribute("units", "Pa") - -# MOSIG rule #149 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 16204 -THEN -CMAttribute("standard_name", "relative_humidity") -CMAttribute("units", "%") - -# MOSIG rule #77 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3237 -THEN -CMAttribute("standard_name", "specific_humidity") -CMAttribute("units", "1") - -# MOSIG rule #76 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3236 -THEN -CMAttribute("standard_name", "air_temperature") -CMAttribute("units", "K") - -# MOSIG rule #72 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3234 -THEN -CMAttribute("standard_name", "surface_upward_latent_heat_flux") -CMAttribute("units", "W m-2") - -# MOSIG rule #71 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3227 -THEN -CMAttribute("standard_name", "wind_speed") -CMAttribute("units", "m s-1") - -# MOSIG rule #79 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3245 -THEN -CMAttribute("standard_name", "relative_humidity") -CMAttribute("units", "???") - -# MOSIG rule #78 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 3238 -THEN -CMAttribute("standard_name", "soil_temperature") -CMAttribute("units", "???") - -# MOSIG rule #227 -IF -f.lbuser[6] == 1 -f.lbuser[3] == 33004 -THEN -CMAttribute("standard_name", "mole_fraction_of_nitrogen_trioxide_in_air") -CMAttribute("units", "mole mole-1") - diff --git a/lib/iris/etc/pp_save_rules.txt b/lib/iris/etc/pp_save_rules.txt deleted file mode 100644 index bb9ff57296..0000000000 --- a/lib/iris/etc/pp_save_rules.txt +++ /dev/null @@ -1,718 +0,0 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . - -################################################################ -### stuff that's missing from the default pp, or always true ### -################################################################ - -IF - True -THEN - pp.lbproc = 0 # Processing. Start at 0. - -IF - cm.coord_system("GeogCS") is not None or cm.coord_system(None) is None -THEN - pp.bplat = 90 - pp.bplon = 0 - -IF - cm.coord_system("RotatedGeogCS") is not None -THEN - pp.bplat = cm.coord_system("RotatedGeogCS").grid_north_pole_latitude - pp.bplon = cm.coord_system("RotatedGeogCS").grid_north_pole_longitude - - -#UM - no version number -IF - 'source' in cm.attributes - len(cm.attributes['source'].rsplit("Data from Met Office Unified Model", 1)) > 1 - len(cm.attributes['source'].rsplit("Data from Met Office Unified Model", 1)[1]) == 0 -THEN - pp.lbsrce = 1111 - -#UM - with version number -IF - 'source' in cm.attributes - len(cm.attributes['source'].rsplit("Data from Met Office Unified Model", 1)) > 1 - len(cm.attributes['source'].rsplit("Data from Met Office Unified Model", 1)[1]) > 0 -THEN - pp.lbsrce = int(float(cm.attributes['source'].rsplit("Data from Met Office Unified Model", 1)[1]) * 1000000) + 1111 # UM version - -IF - 'STASH' in cm.attributes - isinstance(cm.attributes['STASH'], iris.fileformats.pp.STASH) -THEN - pp.lbuser[3] = 1000 * (cm.attributes['STASH'].section or 0) + (cm.attributes['STASH'].item or 0) - pp.lbuser[6] = (cm.attributes['STASH'].model or 0) - - -############################################ -# Fallback to derive LBFC from the standard_name -# NOTE: The following rules are suspect, as units are not specified, once -# specific units are identified, these rules can be migrated to CF_TO_LBFC. - -IF - pp.lbfc == 0 - cm.name() in ['geopotential_height'] -THEN - pp.lbfc = 1 - -IF - pp.lbfc == 0 - cm.name() in ['temperature', 'air_temperature'] -THEN - pp.lbfc = 16 - -IF - pp.lbfc == 0 - cm.name() in ['sea_surface_elevation'] -THEN - pp.lbfc = 608 - -IF - cm.name() in ['wind_gust'] -THEN - pp.lbfc = 1694 - -IF - cm.name() in ['wind_speed'] -THEN - pp.lbfc = 50 - -IF - cm.name() in ['large_scale_rainfall_rate'] -THEN - pp.lbfc = 99 - -IF - cm.name() in ['eastward_wind'] -THEN - pp.lbfc = 56 - -IF - cm.name() in ['northward_wind'] -THEN - pp.lbfc = 57 - - -###################################################### -### time - lbtim, t1, t2 and lbft (but not lbproc) ### -###################################################### - -#no forecast -IF - scalar_coord(cm, 'time') is not None - scalar_coord(cm, 'forecast_period') is None - scalar_coord(cm, 'forecast_reference_time') is None -THEN - pp.lbtim.ia = 0 - pp.lbtim.ib = 0 - pp.t1 = scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').points[0]) - pp.t2 = netcdftime.datetime(0, 0, 0) - - -#forecast -IF - scalar_coord(cm, 'time') is not None - not scalar_coord(cm, 'time').has_bounds() - scalar_coord(cm, 'forecast_period') is not None -THEN - pp.lbtim.ia = 0 - pp.lbtim.ib = 1 - pp.t1 = scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').points[0]) - pp.t2 = scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').points[0] - scalar_coord(cm, 'forecast_period').points[0]) - pp.lbft = scalar_coord(cm, 'forecast_period').points[0] - - -#time mean (non-climatological) -# XXX This only works when we have a single timestep -IF - # XXX How do we know *which* time to use if there are more than - # one? *Can* there be more than one? - scalar_coord(cm, 'time') is not None - scalar_coord(cm, 'time').has_bounds() - scalar_coord(cm, 'clim_season') is None - scalar_coord(cm, 'forecast_period') is not None -THEN - pp.lbtim.ib = 2 - pp.t1 = scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,0]) - pp.t2 = scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,1]) - pp.lbft = pp.bounds_adjusted_lbft(cm) - -IF - # Handle missing forecast period using time and forecast reference time. - scalar_coord(cm, 'time') is not None - scalar_coord(cm, 'time').has_bounds() - scalar_coord(cm, 'clim_season') is None - scalar_coord(cm, 'forecast_period') is None - scalar_coord(cm, 'forecast_reference_time') is not None -THEN - pp.lbtim.ib = 2 - pp.t1 = scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,0]) - pp.t2 = scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,1]) - pp.lbft = calculate_forecast_period(scalar_coord(cm, 'time'), scalar_coord(cm, 'forecast_reference_time')) - -IF - # XXX Note the repetition of the previous rule's constraints - # This can be addressed through REQUIRES/PROVIDES extensions - scalar_coord(cm, 'time') is not None - scalar_coord(cm, 'time').has_bounds() - scalar_coord(cm, 'clim_season') is None - scalar_coord(cm, 'forecast_period') is not None or scalar_coord(cm, 'forecast_reference_time') is not None - scalar_cell_method(cm, 'mean', 'time') is not None - scalar_cell_method(cm, 'mean', 'time').intervals != () - scalar_cell_method(cm, 'mean', 'time').intervals[0].endswith('hour') -THEN - pp.lbtim.ia = int(scalar_cell_method(cm, 'mean', 'time').intervals[0][:-5]) - -IF - # XXX Note the repetition of the previous rule's constraints - scalar_coord(cm, 'time') is not None - scalar_coord(cm, 'time').has_bounds() - scalar_coord(cm, 'clim_season') is None - scalar_coord(cm, 'forecast_period') is not None or scalar_coord(cm, 'forecast_reference_time') is not None - scalar_cell_method(cm, 'mean', 'time') is None or scalar_cell_method(cm, 'mean', 'time').intervals == () or not scalar_cell_method(cm, 'mean', 'time').intervals[0].endswith('hour') -THEN - pp.lbtim.ia = 0 - - -#climatiological time mean - single year -IF - scalar_coord(cm, 'time') is not None - scalar_coord(cm, 'time').has_bounds() - scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,0]).year == scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,1]).year - scalar_coord(cm, 'forecast_period') is not None - scalar_coord(cm, 'clim_season') is not None - 'clim_season' in cm.cell_methods[-1].coord_names -THEN - pp.lbtim.ia = 0 - pp.lbtim.ib = 2 - pp.t1 = scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0, 0]) - pp.t2 = scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0, 1]) - pp.lbft = pp.bounds_adjusted_lbft(cm) - - -#climatiological time mean - spanning years - djf -IF - scalar_coord(cm, 'time') is not None - scalar_coord(cm, 'time').has_bounds() - scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,0]).year != scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,1]).year - scalar_coord(cm, 'forecast_period') is not None - scalar_coord(cm, 'clim_season') is not None - 'clim_season' in cm.cell_methods[-1].coord_names - scalar_coord(cm, 'clim_season').points[0] == 'djf' -THEN - pp.lbtim.ia = 0 - pp.lbtim.ib = 3 - - pp.t1 = scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,0]) - pp.t2 = scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,1]) - - pp.t1 = netcdftime.datetime( pp.t1.year if pp.t1.month==12 else pp.t1.year-1, 12, 1, 0, 0, 0 ) - pp.t2 = netcdftime.datetime( pp.t2.year, 3, 1, 0, 0, 0 ) - - self.conditional_warning(scalar_coord(cm, 'time').bounds[0,0] != scalar_coord(cm, 'time').units.date2num(pp.t1), "modified t1 for climatological seasonal mean") - self.conditional_warning(scalar_coord(cm, 'time').bounds[0,1] != scalar_coord(cm, 'time').units.date2num(pp.t2), "modified t2 for climatological seasonal mean") - - pp.lbft = pp.bounds_adjusted_lbft(cm) - -#climatiological time mean - spanning years - mam -IF - scalar_coord(cm, 'time') is not None - scalar_coord(cm, 'time').has_bounds() - scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,0]).year != scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,1]).year - scalar_coord(cm, 'forecast_period') is not None - scalar_coord(cm, 'clim_season') is not None - 'clim_season' in cm.cell_methods[-1].coord_names - scalar_coord(cm, 'clim_season').points[0] == 'mam' -THEN - pp.lbtim.ia = 0 - pp.lbtim.ib = 3 - - pp.t1 = scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,0]) - pp.t2 = scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,1]) - - pp.t1 = netcdftime.datetime( pp.t1.year, 3, 1, 0, 0, 0 ) - pp.t2 = netcdftime.datetime( pp.t2.year, 6, 1, 0, 0, 0 ) - - self.conditional_warning(scalar_coord(cm, 'time').bounds[0,0] != scalar_coord(cm, 'time').units.date2num(pp.t1), "modified t1 for climatological seasonal mean") - self.conditional_warning(scalar_coord(cm, 'time').bounds[0,1] != scalar_coord(cm, 'time').units.date2num(pp.t2), "modified t2 for climatological seasonal mean") - - pp.lbft = pp.bounds_adjusted_lbft(cm) - -#climatiological time mean - spanning years - jja -IF - scalar_coord(cm, 'time') is not None - scalar_coord(cm, 'time').has_bounds() - scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,0]).year != scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,1]).year - scalar_coord(cm, 'forecast_period') is not None - scalar_coord(cm, 'clim_season') is not None - 'clim_season' in cm.cell_methods[-1].coord_names - scalar_coord(cm, 'clim_season').points[0] == 'jja' -THEN - pp.lbtim.ia = 0 - pp.lbtim.ib = 3 - - pp.t1 = scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,0]) - pp.t2 = scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,1]) - - pp.t1 = netcdftime.datetime( pp.t1.year, 6, 1, 0, 0, 0 ) - pp.t2 = netcdftime.datetime( pp.t2.year, 9, 1, 0, 0, 0 ) - - self.conditional_warning(scalar_coord(cm, 'time').bounds[0,0] != scalar_coord(cm, 'time').units.date2num(pp.t1), "modified t1 for climatological seasonal mean") - self.conditional_warning(scalar_coord(cm, 'time').bounds[0,1] != scalar_coord(cm, 'time').units.date2num(pp.t2), "modified t2 for climatological seasonal mean") - - pp.lbft = pp.bounds_adjusted_lbft(cm) - -#climatiological time mean - spanning years - son -IF - scalar_coord(cm, 'time') is not None - scalar_coord(cm, 'time').has_bounds() - scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,0]).year != scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,1]).year - scalar_coord(cm, 'forecast_period') is not None - scalar_coord(cm, 'clim_season') is not None - 'clim_season' in cm.cell_methods[-1].coord_names - scalar_coord(cm, 'clim_season').points[0] == 'son' -THEN - pp.lbtim.ia = 0 - pp.lbtim.ib = 3 - - pp.t1 = scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,0]) - pp.t2 = scalar_coord(cm, 'time').units.num2date(scalar_coord(cm, 'time').bounds[0,1]) - - pp.t1 = netcdftime.datetime( pp.t1.year, 9, 1, 0, 0, 0 ) - pp.t2 = netcdftime.datetime( pp.t2.year, 12, 1, 0, 0, 0 ) - - self.conditional_warning(scalar_coord(cm, 'time').bounds[0,0] != scalar_coord(cm, 'time').units.date2num(pp.t1), "modified t1 for climatological seasonal mean") - self.conditional_warning(scalar_coord(cm, 'time').bounds[0,1] != scalar_coord(cm, 'time').units.date2num(pp.t2), "modified t2 for climatological seasonal mean") - - pp.lbft = pp.bounds_adjusted_lbft(cm) - -#360 day calendar -IF - scalar_coord(cm, 'time') is not None - scalar_coord(cm, 'time').units.calendar == '360_day' -THEN - pp.lbtim.ic = 2 - - -#gregorian calendar -IF - scalar_coord(cm, 'time') is not None - scalar_coord(cm, 'time').units.calendar == 'gregorian' -THEN - pp.lbtim.ic = 1 - - -#365 day calendar -IF - scalar_coord(cm, 'time') is not None - scalar_coord(cm, 'time').units.calendar == '365_day' -THEN - pp.lbtim.ic = 4 - -##################### -### grid and pole ### -##################### - -IF - vector_coord(cm, 'longitude') and not is_regular(vector_coord(cm, 'longitude')) -THEN - pp.bzx = 0 - pp.bdx = 0 - pp.lbnpt = vector_coord(cm, 'longitude').shape[0] - pp.x = vector_coord(cm, 'longitude').points - -IF - vector_coord(cm, 'grid_longitude') and not is_regular(vector_coord(cm, 'grid_longitude')) -THEN - pp.bzx = 0 - pp.bdx = 0 - pp.lbnpt = vector_coord(cm, 'grid_longitude').shape[0] - pp.x = vector_coord(cm, 'grid_longitude').points - -IF - vector_coord(cm, 'latitude') and not is_regular(vector_coord(cm, 'latitude')) -THEN - pp.bzy = 0 - pp.bdy = 0 - pp.lbrow = vector_coord(cm, 'latitude').shape[0] - pp.y = vector_coord(cm, 'latitude').points - -IF - vector_coord(cm, 'grid_latitude') and not is_regular(vector_coord(cm, 'grid_latitude')) -THEN - pp.bzy = 0 - pp.bdy = 0 - pp.lbrow = vector_coord(cm, 'grid_latitude').shape[0] - pp.y = vector_coord(cm, 'grid_latitude').points - -IF - vector_coord(cm, 'longitude') and is_regular(vector_coord(cm, 'longitude')) -THEN - pp.bzx = vector_coord(cm, 'longitude').points[0] - regular_step(vector_coord(cm, 'longitude')) - pp.bdx = regular_step(vector_coord(cm, 'longitude')) - pp.lbnpt = len(vector_coord(cm, 'longitude').points) - -IF - vector_coord(cm, 'grid_longitude') and is_regular(vector_coord(cm, 'grid_longitude')) -THEN - pp.bzx = vector_coord(cm, 'grid_longitude').points[0] - regular_step(vector_coord(cm, 'grid_longitude')) - pp.bdx = regular_step(vector_coord(cm, 'grid_longitude')) - pp.lbnpt = len(vector_coord(cm, 'grid_longitude').points) - -IF - vector_coord(cm, 'latitude') and is_regular(vector_coord(cm, 'latitude')) -THEN - pp.bzy = vector_coord(cm, 'latitude').points[0] - regular_step(vector_coord(cm, 'latitude')) - pp.bdy = regular_step(vector_coord(cm, 'latitude')) - pp.lbrow = len(vector_coord(cm, 'latitude').points) - -IF - vector_coord(cm, 'grid_latitude') and is_regular(vector_coord(cm, 'grid_latitude')) -THEN - pp.bzy = vector_coord(cm, 'grid_latitude').points[0] - regular_step(vector_coord(cm, 'grid_latitude')) - pp.bdy = regular_step(vector_coord(cm, 'grid_latitude')) - pp.lbrow = len(vector_coord(cm, 'grid_latitude').points) - - -#rotated? -IF -# iris.fileformats.pp.is_cross_section(cm) == False - cm.coord_system("RotatedGeogCS") is not None -THEN - pp.lbcode = int(pp.lbcode) + 100 - - -#lon global -IF - vector_coord(cm, 'longitude') is not None - vector_coord(cm, 'longitude').circular -THEN - pp.lbhem = 0 - -IF - vector_coord(cm, 'grid_longitude') is not None - vector_coord(cm, 'grid_longitude').circular -THEN - pp.lbhem = 0 - -#lon not global -IF - vector_coord(cm, 'longitude') is not None - not vector_coord(cm, 'longitude').circular -THEN - pp.lbhem = 3 - -IF - vector_coord(cm, 'grid_longitude') is not None - not vector_coord(cm, 'grid_longitude').circular -THEN - pp.lbhem = 3 - - - -##################################################### -############ non-standard cross-sections ############ -##################################################### - -# Ticket #1037, x=latitude, y=air_pressure - non-standard cross-section with bounds -IF - vector_coord(cm, 'air_pressure') is not None - not vector_coord(cm, 'air_pressure').circular - vector_coord(cm, 'air_pressure').has_bounds() - vector_coord(cm, 'latitude') is not None - not vector_coord(cm, 'latitude').circular - vector_coord(cm, 'latitude').has_bounds() -THEN - pp.lbcode = 10000 + int(100*10) + 1 - pp.bgor = 0 - pp.y = vector_coord(cm, 'air_pressure').points - pp.y_lower_bound = vector_coord(cm, 'air_pressure').bounds[:,0] - pp.y_upper_bound = vector_coord(cm, 'air_pressure').bounds[:,1] - pp.x = vector_coord(cm, 'latitude').points - pp.x_lower_bound = vector_coord(cm, 'latitude').bounds[:,0] - pp.x_upper_bound = vector_coord(cm, 'latitude').bounds[:,1] - pp.lbrow = vector_coord(cm, 'air_pressure').shape[0] - pp.lbnpt = vector_coord(cm, 'latitude').shape[0] - pp.bzx = pp.bzy = pp.bdx = pp.bdy = 0 - -# Ticket #1037, x=latitude, y=depth - non-standard cross-section with bounds -IF - vector_coord(cm, 'depth') is not None - not vector_coord(cm, 'depth').circular - vector_coord(cm, 'depth').has_bounds() - vector_coord(cm, 'latitude') is not None - not vector_coord(cm, 'latitude').circular - vector_coord(cm, 'latitude').has_bounds() -THEN - pp.lbcode = 10000 + int(100*10) + 4 - pp.bgor = 0 - pp.y = vector_coord(cm, 'depth').points - pp.y_lower_bound = vector_coord(cm, 'depth').bounds[:,0] - pp.y_upper_bound = vector_coord(cm, 'depth').bounds[:,1] - pp.x = vector_coord(cm, 'latitude').points - pp.x_lower_bound = vector_coord(cm, 'latitude').bounds[:,0] - pp.x_upper_bound = vector_coord(cm, 'latitude').bounds[:,1] - pp.lbrow = vector_coord(cm, 'depth').shape[0] - pp.lbnpt = vector_coord(cm, 'latitude').shape[0] - pp.bzx = pp.bzy = pp.bdx = pp.bdy = 0 - -# Ticket #1037, x=latitude, y=ETA - non-standard cross-section with bounds -IF - vector_coord(cm, 'eta') is not None - not vector_coord(cm, 'eta').circular - vector_coord(cm, 'eta').has_bounds() - vector_coord(cm, 'latitude') is not None - not vector_coord(cm, 'latitude').circular - vector_coord(cm, 'latitude').has_bounds() -THEN - pp.lbcode = 10000 + int(100*10) + 3 - pp.bgor = 0 - pp.y = vector_coord(cm, 'eta').points - pp.y_lower_bound = vector_coord(cm, 'eta').bounds[:,0] - pp.y_upper_bound = vector_coord(cm, 'eta').bounds[:,1] - pp.x = vector_coord(cm, 'latitude').points - pp.x_lower_bound = vector_coord(cm, 'latitude').bounds[:,0] - pp.x_upper_bound = vector_coord(cm, 'latitude').bounds[:,1] - pp.lbrow = vector_coord(cm, 'eta').shape[0] - pp.lbnpt = vector_coord(cm, 'latitude').shape[0] - pp.bzx = pp.bzy = pp.bdx = pp.bdy = 0 - -# Ticket #1037, x=days (360 calendar), y=depth - non-standard cross-section with bounds -IF - vector_coord(cm, 'depth') is not None - not vector_coord(cm, 'depth').circular - vector_coord(cm, 'depth').has_bounds() - vector_coord(cm, 'time') is not None - not vector_coord(cm, 'time').circular - vector_coord(cm, 'time').has_bounds() -THEN - pp.lbcode = 10000 + int(100*23) + 4 - pp.bgor = 0 - pp.y = vector_coord(cm, 'depth').points - pp.y_lower_bound = vector_coord(cm, 'depth').bounds[:,0] - pp.y_upper_bound = vector_coord(cm, 'depth').bounds[:,1] - pp.x = vector_coord(cm, 'time').points - pp.x_lower_bound = vector_coord(cm, 'time').bounds[:,0] - pp.x_upper_bound = vector_coord(cm, 'time').bounds[:,1] - pp.lbrow = vector_coord(cm, 'depth').shape[0] - pp.lbnpt = vector_coord(cm, 'time').shape[0] - pp.bzx = pp.bzy = pp.bdx = pp.bdy = 0 - - -# Ticket #1037, x=days (360 calendar), y=air_pressure - non-standard cross-section with bounds -IF - vector_coord(cm, 'air_pressure') is not None - not vector_coord(cm, 'air_pressure').circular - vector_coord(cm, 'air_pressure').has_bounds() - vector_coord(cm, 'time') is not None - not vector_coord(cm, 'time').circular - vector_coord(cm, 'time').has_bounds() -THEN - pp.lbcode = 10000 + int(100*23) + 1 - pp.bgor = 0 - pp.y = vector_coord(cm, 'air_pressure').points - pp.y_lower_bound = vector_coord(cm, 'air_pressure').bounds[:,0] - pp.y_upper_bound = vector_coord(cm, 'air_pressure').bounds[:,1] - pp.x = vector_coord(cm, 'time').points - pp.x_lower_bound = vector_coord(cm, 'time').bounds[:,0] - pp.x_upper_bound = vector_coord(cm, 'time').bounds[:,1] - pp.lbrow = vector_coord(cm, 'air_pressure').shape[0] - pp.lbnpt = vector_coord(cm, 'time').shape[0] - pp.bzx = pp.bzy = pp.bdx = pp.bdy = 0 - - - - - -##################################################### -### lbproc (must start at 0 before rules are run) ### -##################################################### - -IF - cm.attributes.get("ukmo__process_flags", None) -THEN - pp.lbproc += sum([iris.fileformats.pp.lbproc_map[name] for name in cm.attributes["ukmo__process_flags"]]) - -#time-mean -IF - # Look for a CellMethod which is a "mean" over "time". - scalar_cell_method(cm, 'mean', 'time') is not None -THEN - pp.lbproc += 128 - -#time-maximum -IF - # Look for a CellMethod which is a "maximum" over "time". - scalar_cell_method(cm, 'maximum', 'time') is not None -THEN - pp.lbproc += 8192 - -################################ -### vertical - lbvc and blev ### -################################ - -#single height level -IF - scalar_coord(cm, 'height') is not None - not scalar_coord(cm, 'height').bounds - scalar_coord(cm, 'height').points[0] == 1.5 - cm.name() == 'air_temperature' -THEN - pp.lbvc = 129 - pp.blev = -1 - -IF - pp.lbvc == 0 - scalar_coord(cm, 'height') is not None - not scalar_coord(cm, 'height').bounds -THEN - pp.lbvc = 1 - pp.blev = cm.coord('height').points[0] - - -#single air_pressure level -IF - scalar_coord(cm, 'air_pressure') is not None - not scalar_coord(cm, 'air_pressure').bounds -THEN - pp.lbvc = 8 - pp.blev = scalar_coord(cm, 'air_pressure').points[0] - -#single "pressure" level -#TODO: "pressure" is in the PP load rules awaiting more info -IF - scalar_coord(cm, 'pressure') is not None - not scalar_coord(cm, 'pressure').bounds -THEN - pp.lbvc = 8 - pp.blev = scalar_coord(cm, 'pressure').points[0] - - -# single depth level (non cross section) -IF - scalar_coord(cm, 'model_level_number') is not None - not scalar_coord(cm, 'model_level_number').bounds - scalar_coord(cm, 'depth') is not None - not scalar_coord(cm, 'depth').bounds -THEN - pp.lbvc = 2 - pp.lblev = scalar_coord(cm, 'model_level_number').points[0] - pp.blev = scalar_coord(cm, 'depth').points[0] - -# single depth level (Non-dimensional soil model level) -IF - scalar_coord(cm, 'soil_model_level_number') is not None - not scalar_coord(cm, 'soil_model_level_number').bounds - # The following `is None` checks ensure this rule does not get run - # if any of the previous LBVC setting rules have run. It gives these - # rules something of an IF-THEN-ELSE structure. - scalar_coord(cm, 'air_pressure') is None - scalar_coord(cm, 'depth') is None - scalar_coord(cm, 'height') is None - scalar_coord(cm, 'pressure') is None - cm.standard_name is not None - 'soil' in cm.standard_name -THEN - pp.lbvc = 6 - pp.lblev = scalar_coord(cm, 'soil_model_level_number').points[0] - pp.blev = pp.lblev - -# single potential-temperature level -IF - scalar_coord(cm, 'air_potential_temperature') is not None - not scalar_coord(cm, 'air_potential_temperature').bounds - # The following `is None` checks ensure this rule does not get run - # if any of the previous LBVC setting rules have run. It gives these - # rules something of an IF-THEN-ELSE structure. - scalar_coord(cm, 'air_pressure') is None - scalar_coord(cm, 'depth') is None - scalar_coord(cm, 'height') is None - scalar_coord(cm, 'pressure') is None - scalar_coord(cm, 'model_level_number') is None -THEN - pp.lbvc = 19 - pp.lblev = scalar_coord(cm, 'air_potential_temperature').points[0] - pp.blev = scalar_coord(cm, 'air_potential_temperature').points[0] - -# single hybrid_height level -IF - has_aux_factory(cm, iris.aux_factory.HybridHeightFactory) - scalar_coord(cm, 'model_level_number') is not None - scalar_coord(cm, 'model_level_number').bounds is None - aux_factory(cm, iris.aux_factory.HybridHeightFactory).dependencies['delta'] is not None - aux_factory(cm, iris.aux_factory.HybridHeightFactory).dependencies['delta'].bounds is not None - aux_factory(cm, iris.aux_factory.HybridHeightFactory).dependencies['sigma'] is not None - aux_factory(cm, iris.aux_factory.HybridHeightFactory).dependencies['sigma'].bounds is not None -THEN - pp.lbvc = 65 - pp.lblev = scalar_coord(cm, 'model_level_number').points[0] - pp.blev = aux_factory(cm, iris.aux_factory.HybridHeightFactory).dependencies['delta'].points[0] - pp.brlev = aux_factory(cm, iris.aux_factory.HybridHeightFactory).dependencies['delta'].bounds[0, 0] - pp.brsvd[0] = aux_factory(cm, iris.aux_factory.HybridHeightFactory).dependencies['delta'].bounds[0, 1] - pp.bhlev = aux_factory(cm, iris.aux_factory.HybridHeightFactory).dependencies['sigma'].points[0] - pp.bhrlev = aux_factory(cm, iris.aux_factory.HybridHeightFactory).dependencies['sigma'].bounds[0, 0] - pp.brsvd[1] = aux_factory(cm, iris.aux_factory.HybridHeightFactory).dependencies['sigma'].bounds[0, 1] - -# single hybrid pressure level -IF - has_aux_factory(cm, iris.aux_factory.HybridPressureFactory) - scalar_coord(cm, 'model_level_number') is not None - scalar_coord(cm, 'model_level_number').bounds is None - aux_factory(cm, iris.aux_factory.HybridPressureFactory).dependencies['delta'] is not None - aux_factory(cm, iris.aux_factory.HybridPressureFactory).dependencies['delta'].bounds is not None - aux_factory(cm, iris.aux_factory.HybridPressureFactory).dependencies['sigma'] is not None - aux_factory(cm, iris.aux_factory.HybridPressureFactory).dependencies['sigma'].bounds is not None -THEN - pp.lbvc = 9 - pp.lblev = scalar_coord(cm, 'model_level_number').points[0] - - # Note that sigma and delta are swapped around from the hybrid height rules above. - pp.blev = aux_factory(cm, iris.aux_factory.HybridPressureFactory).dependencies['sigma'].points[0] - pp.brlev = aux_factory(cm, iris.aux_factory.HybridPressureFactory).dependencies['sigma'].bounds[0, 0] - pp.brsvd[0] = aux_factory(cm, iris.aux_factory.HybridPressureFactory).dependencies['sigma'].bounds[0, 1] - - pp.bhlev = aux_factory(cm, iris.aux_factory.HybridPressureFactory).dependencies['delta'].points[0] - pp.bhrlev = aux_factory(cm, iris.aux_factory.HybridPressureFactory).dependencies['delta'].bounds[0, 0] - pp.brsvd[1] = aux_factory(cm, iris.aux_factory.HybridPressureFactory).dependencies['delta'].bounds[0, 1] - - -#MDI -IF - isinstance(cm.data, ma.core.MaskedArray) -THEN - pp.bmdi = cm.data.fill_value - -IF - not isinstance(cm.data, ma.core.MaskedArray) -THEN - pp.bmdi = -1e30 - - -# CFname mega rule -IF - (cm.name(),cm.units) in iris.fileformats.um_cf_map.CF_TO_LBFC -THEN - pp.lbfc = iris.fileformats.um_cf_map.CF_TO_LBFC[(cm.name(),cm.units)] - -IF - 'STASH' in cm.attributes - str(cm.attributes['STASH']) in iris.fileformats._ff_cross_references.STASH_TRANS -THEN - pp.lbfc = iris.fileformats._ff_cross_references.STASH_TRANS[str(cm.attributes['STASH'])].field_code diff --git a/lib/iris/etc/site.cfg.template b/lib/iris/etc/site.cfg.template index b78e9c4b97..ef5459cc92 100644 --- a/lib/iris/etc/site.cfg.template +++ b/lib/iris/etc/site.cfg.template @@ -6,5 +6,3 @@ dot_path = /path/to/dot # see iris.fileformats.dot sample_data_dir = /path/to/iris/resources/sample_data test_data_dir = /path/to/iris/resources/test_data -[Logging] -import_logger = logger_name diff --git a/lib/iris/exceptions.py b/lib/iris/exceptions.py index b3a01fa21e..dbc3f523d2 100644 --- a/lib/iris/exceptions.py +++ b/lib/iris/exceptions.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -18,7 +18,9 @@ Exceptions specific to the Iris package. """ -import iris.coords + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa class IrisError(Exception): @@ -36,9 +38,16 @@ class CoordinateNotFoundError(KeyError): pass +class CellMeasureNotFoundError(KeyError): + """Raised when a search yields no cell measures.""" + pass + + class CoordinateMultiDimError(ValueError): """Raised when a routine doesn't support multi-dimensional coordinates.""" def __init__(self, msg): + # N.B. deferred import to avoid a circular import dependency. + import iris.coords if isinstance(msg, iris.coords.Coord): fmt = "Multi-dimensional coordinate not supported: '%s'" msg = fmt % msg.name() @@ -87,6 +96,30 @@ class IgnoreCubeException(IrisError): pass +class ConcatenateError(IrisError): + """ + Raised when concatenate is expected to produce a single cube, but fails to + do so. + + """ + def __init__(self, differences): + """ + Creates a ConcatenateError with a list of textual descriptions of + the differences which prevented a concatenate. + + Args: + + * differences: + The list of strings which describe the differences. + + """ + self.differences = differences + + def __str__(self): + return '\n '.join(['failed to concatenate into a single cube.'] + + list(self.differences)) + + class MergeError(IrisError): """ Raised when merge is expected to produce a single cube, but fails to @@ -119,3 +152,8 @@ def __init__(self, msg): class LazyAggregatorError(Exception): pass + + +class UnitConversionError(IrisError): + """Raised when Iris is unable to convert a unit.""" + pass diff --git a/lib/iris/experimental/__init__.py b/lib/iris/experimental/__init__.py index 4e7588d8d6..eb29818f80 100644 --- a/lib/iris/experimental/__init__.py +++ b/lib/iris/experimental/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -21,3 +21,6 @@ codebase. The code is expected to graduate, eventually, to "full status". """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/experimental/animate.py b/lib/iris/experimental/animate.py index 9d02672394..ac60400ba7 100644 --- a/lib/iris/experimental/animate.py +++ b/lib/iris/experimental/animate.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -19,6 +19,9 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + import warnings import matplotlib.pyplot as plt @@ -37,8 +40,12 @@ def animate(cube_iterator, plot_func, fig=None, **kwargs): Each animation frame corresponds to each :class:`iris.cube.Cube` object. See :meth:`iris.cube.Cube.slices`. - * plot_func (:mod:`~iris.plot` or :mod:`~iris.quickplot` plot): - Plotting function used to animate. + * plot_func (:mod:`iris.plot` or :mod:`iris.quickplot` plotting function): + Plotting function used to animate. Must accept the signature + ``plot_func(cube, vmin=vmin, vmax=vmax, coords=coords)``. + :func:`~iris.plot.contourf`, :func:`~iris.plot.contour`, + :func:`~iris.plot.pcolor` and :func:`~iris.plot.pcolormesh` + all conform to this signature. Kwargs: @@ -117,7 +124,7 @@ def update_animation_iris(i, cubes, vmin, vmax, coords): vmax = kwargs.pop('vmax', max([cc.data.max() for cc in cubes])) update = update_animation_iris - frames = xrange(len(cubes)) + frames = range(len(cubes)) return animation.FuncAnimation(fig, update, frames=frames, diff --git a/lib/iris/experimental/concatenate.py b/lib/iris/experimental/concatenate.py index b9a8d27543..dcf3fcdd22 100644 --- a/lib/iris/experimental/concatenate.py +++ b/lib/iris/experimental/concatenate.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -24,6 +24,9 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + def concatenate(cubes): """ diff --git a/lib/iris/experimental/equalise_cubes.py b/lib/iris/experimental/equalise_cubes.py index 4136b35c90..8a85cded97 100644 --- a/lib/iris/experimental/equalise_cubes.py +++ b/lib/iris/experimental/equalise_cubes.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2016, Met Office # # This file is part of Iris. # @@ -19,6 +19,9 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + import numpy as np @@ -37,16 +40,16 @@ def equalise_attributes(cubes): """ # Work out which attributes are identical across all the cubes. - common_keys = cubes[0].attributes.keys() + common_keys = list(cubes[0].attributes.keys()) for cube in cubes[1:]: - cube_keys = cube.attributes.keys() + cube_keys = list(cube.attributes.keys()) common_keys = [ key for key in common_keys - if key in cube_keys - and np.all(cube.attributes[key] == cubes[0].attributes[key])] + if (key in cube_keys and + np.all(cube.attributes[key] == cubes[0].attributes[key]))] # Remove all the other attributes. for cube in cubes: - for key in cube.attributes.keys(): + for key in list(cube.attributes.keys()): if key not in common_keys: del cube.attributes[key] diff --git a/lib/iris/experimental/fileformats/__init__.py b/lib/iris/experimental/fileformats/__init__.py deleted file mode 100644 index c65058d712..0000000000 --- a/lib/iris/experimental/fileformats/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -""" -Experimental code for converting cubes to and from specific file formats. - -""" diff --git a/lib/iris/experimental/raster.py b/lib/iris/experimental/raster.py index b99791fe34..aca3fdadca 100644 --- a/lib/iris/experimental/raster.py +++ b/lib/iris/experimental/raster.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -24,12 +24,18 @@ dependency should be added to INSTALL """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + import numpy as np +import numpy.ma as ma from osgeo import gdal, osr +import cf_units + import iris import iris.coord_systems -import iris.unit _GDAL_DATATYPES = { @@ -92,7 +98,7 @@ def _gdal_write_array(x_min, x_step, y_max, y_step, coord_system, data, fname, gdal_dataset.SetGeoTransform(padf_transform) band = gdal_dataset.GetRasterBand(1) - if isinstance(data, np.ma.core.MaskedArray): + if ma.isMaskedArray(data): data = data.copy() data[data.mask] = data.fill_value band.SetNoDataValue(float(data.fill_value)) @@ -138,7 +144,7 @@ def export_geotiff(cube, fname): msg = 'Coordinate {!r} must have two bounds ' \ 'per point.'.format(name) raise ValueError(msg) - if not (coord.units == iris.unit.Unit('degrees') or + if not (coord.units == cf_units.Unit('degrees') or coord.units.is_convertible('meters')): raise ValueError('Coordinate {!r} units must be either degrees or ' 'convertible to meters.'.format(name)) diff --git a/lib/iris/experimental/regrid.py b/lib/iris/experimental/regrid.py index 87ad52a42b..91e48af61a 100644 --- a/lib/iris/experimental/regrid.py +++ b/lib/iris/experimental/regrid.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2018, Met Office # # This file is part of Iris. # @@ -18,57 +18,35 @@ Regridding functions. """ -import collections +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +from collections import namedtuple import copy +import functools import warnings +import cartopy.crs as ccrs +import cf_units import numpy as np import numpy.ma as ma -from scipy.sparse import csc_matrix +import scipy.interpolate +from scipy.sparse import csc_matrix, diags as sparse_diags +import six import iris.analysis.cartography -import iris.coords +from iris.analysis._interpolation import (get_xy_dim_coords, get_xy_coords, + snapshot_grid) +from iris.analysis._regrid import RectilinearRegridder import iris.coord_systems import iris.cube -import iris.unit - - -def _get_xy_dim_coords(cube): - """ - Return the x and y dimension coordinates from a cube. - - This function raises a ValueError if the cube does not contain one and - only one set of x and y dimension coordinates. It also raises a ValueError - if the identified x and y coordinates do not have coordinate systems that - are equal. - - Args: - - * cube: - An instance of :class:`iris.cube.Cube`. - - Returns: - A tuple containing the cube's x and y dimension coordinates. - - """ - x_coords = cube.coords(axis='x', dim_coords=True) - if len(x_coords) != 1: - raise ValueError('Cube {!r} must contain a single 1D x ' - 'coordinate.'.format(cube.name())) - x_coord = x_coords[0] +from iris.util import _meshgrid, promote_aux_coord_to_dim_coord - y_coords = cube.coords(axis='y', dim_coords=True) - if len(y_coords) != 1: - raise ValueError('Cube {!r} must contain a single 1D y ' - 'coordinate.'.format(cube.name())) - y_coord = y_coords[0] - if x_coord.coord_system != y_coord.coord_system: - raise ValueError("The cube's x ({!r}) and y ({!r}) " - "coordinates must have the same coordinate " - "system.".format(x_coord.name(), y_coord.name())) - - return x_coord, y_coord +_Version = namedtuple('Version', ('major', 'minor', 'micro')) +_NP_VERSION = _Version(*(int(val) for val in + np.version.version.split('.') if val.isdigit())) def _get_xy_coords(cube): @@ -143,372 +121,48 @@ def _get_xy_coords(cube): return x_coord, y_coord -def _sample_grid(src_coord_system, grid_x_coord, grid_y_coord): +def _within_bounds(src_bounds, tgt_bounds, orderswap=False): """ - Convert the rectilinear grid coordinates to a curvilinear grid in - the source coordinate system. - - The `grid_x_coord` and `grid_y_coord` must share a common coordinate - system. + Determine which target bounds lie within the extremes of the source bounds. Args: - * src_coord_system: - The :class:`iris.coord_system.CoordSystem` for the grid of the - source Cube. - * grid_x_coord: - The :class:`iris.coords.DimCoord` for the X coordinate. - * grid_y_coord: - The :class:`iris.coords.DimCoord` for the Y coordinate. - - Returns: - A tuple of the X and Y coordinate values as 2-dimensional - arrays. - - """ - src_crs = src_coord_system.as_cartopy_crs() - grid_crs = grid_x_coord.coord_system.as_cartopy_crs() - grid_x, grid_y = np.meshgrid(grid_x_coord.points, grid_y_coord.points) - # Skip the CRS transform if we can to avoid precision problems. - if src_crs == grid_crs: - sample_grid_x = grid_x - sample_grid_y = grid_y - else: - sample_xyz = src_crs.transform_points(grid_crs, grid_x, grid_y) - sample_grid_x = sample_xyz[..., 0] - sample_grid_y = sample_xyz[..., 1] - return sample_grid_x, sample_grid_y - - -def _regrid_bilinear_array(src_data, x_dim, y_dim, src_x_coord, src_y_coord, - sample_grid_x, sample_grid_y): - """ - Regrid the given data from the src grid to the sample grid. - - Args: - - * src_data: - An N-dimensional NumPy array. - * x_dim: - The X dimension within `src_data`. - * y_dim: - The Y dimension within `src_data`. - * src_x_coord: - The X :class:`iris.coords.DimCoord`. - * src_y_coord: - The Y :class:`iris.coords.DimCoord`. - * sample_grid_x: - A 2-dimensional array of sample X values. - * sample_grid_y: - A 2-dimensional array of sample Y values. - - Returns: - The regridded data as an N-dimensional NumPy array. The lengths - of the X and Y dimensions will now match those of the sample - grid. + * src_bounds (ndarray): + An (n, 2) shaped array of monotonic contiguous source bounds. + * tgt_bounds (ndarray): + An (n, 2) shaped array corresponding to the target bounds. - """ - if sample_grid_x.shape != sample_grid_y.shape: - raise ValueError('Inconsistent sample grid shapes.') - if sample_grid_x.ndim != 2: - raise ValueError('Sample grid must be 2-dimensional.') - - # Prepare the result data array - shape = list(src_data.shape) - shape[y_dim] = sample_grid_x.shape[0] - shape[x_dim] = sample_grid_x.shape[1] - # If we're given integer values, convert them to the smallest - # possible float dtype that can accurately preserve the values. - dtype = src_data.dtype - if dtype.kind == 'i': - dtype = np.promote_types(dtype, np.float16) - data = np.empty(shape, dtype=dtype) - - # TODO: Replace ... see later comment. - # A crummy, temporary hack using iris.analysis.interpolate.linear() - # The faults include, but are not limited to: - # 1) It uses a nested `for` loop. - # 2) It is doing lots of unncessary metadata faffing. - # 3) It ends up performing two linear interpolations for each - # column of results, and the first linear interpolation does a lot - # more work than we'd ideally do, as most of the interpolated data - # is irrelevant to the second interpolation. - src = iris.cube.Cube(src_data) - src.add_dim_coord(src_x_coord, x_dim) - src.add_dim_coord(src_y_coord, y_dim) - - indices = [slice(None)] * data.ndim - linear = iris.analysis.interpolate.linear - for yx_index in np.ndindex(sample_grid_x.shape): - x = sample_grid_x[yx_index] - y = sample_grid_y[yx_index] - column_pos = [(src_x_coord, x), (src_y_coord, y)] - column_data = linear(src, column_pos, 'nan').data - indices[y_dim] = yx_index[0] - indices[x_dim] = yx_index[1] - data[tuple(indices)] = column_data - - # TODO: - # Altenative: - # Locate the four pairs of src x and y indices relevant to each grid - # location: - # => x_indices.shape == (4, ny, nx); y_indices.shape == (4, ny, nx) - # Calculate the relative weight of each corner: - # => weights.shape == (4, ny, nx) - # Extract the src data relevant to the grid locations: - # => raw_data = src.data[..., y_indices, x_indices] - # NB. Can't rely on this index order in general. - # => raw_data.shape == (..., 4, ny, nx) - # Weight it: - # => Reshape `weights` to broadcast against `raw_data`. - # => weighted_data = raw_data * weights - # => weighted_data.shape == (..., 4, ny, nx) - # Sum over the `4` dimension: - # => data = weighted_data.sum(axis=sample_axis) - # => data.shape == (..., ny, nx) - # Should be able to re-use the weights to calculate the interpolated - # values for auxiliary coordinates as well. - - return data - - -def _regrid_reference_surface(src_surface_coord, surface_dims, x_dim, y_dim, - src_x_coord, src_y_coord, - sample_grid_x, sample_grid_y, regrid_callback): - """ - Return a new reference surface coordinate appropriate to the sample - grid. + Kwargs: - Args: - - * src_surface_coord: - The :class:`iris.coords.Coord` containing the source reference - surface. - * surface_dims: - The tuple of the data dimensions relevant to the source - reference surface coordinate. - * x_dim: - The X dimension within the source Cube. - * y_dim: - The Y dimension within the source Cube. - * src_x_coord: - The X :class:`iris.coords.DimCoord`. - * src_y_coord: - The Y :class:`iris.coords.DimCoord`. - * sample_grid_x: - A 2-dimensional array of sample X values. - * sample_grid_y: - A 2-dimensional array of sample Y values. - * regrid_callback: - The routine that will be used to calculate the interpolated - values for the new reference surface. + * orderswap (bool): + A Boolean indicating whether the target bounds are in descending order + (True). Defaults to False. Returns: - The new reference surface coordinate. + Boolean ndarray, indicating whether each target bound is within the + extremes of the source bounds. """ - # Determine which of the reference surface's dimensions span the X - # and Y dimensions of the source cube. - surface_x_dim = surface_dims.index(x_dim) - surface_y_dim = surface_dims.index(y_dim) - surface = regrid_callback(src_surface_coord.points, - surface_x_dim, surface_y_dim, - src_x_coord, src_y_coord, - sample_grid_x, sample_grid_y) - surface_coord = src_surface_coord.copy(surface) - return surface_coord - - -def _create_cube(data, src, x_dim, y_dim, src_x_coord, src_y_coord, - grid_x_coord, grid_y_coord, sample_grid_x, sample_grid_y, - regrid_callback): - """ - Return a new Cube for the result of regridding the source Cube onto - the new grid. - - All the metadata and coordinates of the result Cube are copied from - the source Cube, with two exceptions: - - Grid dimension coordinates are copied from the grid Cube. - - Auxiliary coordinates which span the grid dimensions are - ignored, except where they provide a reference surface for an - :class:`iris.aux_factory.AuxCoordFactory`. + min_bound = np.min(src_bounds) - 1e-14 + max_bound = np.max(src_bounds) + 1e-14 - Args: - - * data: - The regridded data as an N-dimensional NumPy array. - * src: - The source Cube. - * x_dim: - The X dimension within the source Cube. - * y_dim: - The Y dimension within the source Cube. - * src_x_coord: - The X :class:`iris.coords.DimCoord`. - * src_y_coord: - The Y :class:`iris.coords.DimCoord`. - * grid_x_coord: - The :class:`iris.coords.DimCoord` for the new grid's X - coordinate. - * grid_y_coord: - The :class:`iris.coords.DimCoord` for the new grid's Y - coordinate. - * sample_grid_x: - A 2-dimensional array of sample X values. - * sample_grid_y: - A 2-dimensional array of sample Y values. - * regrid_callback: - The routine that will be used to calculate the interpolated - values of any reference surfaces. - - Returns: - The new, regridded Cube. - - """ - # Create a result cube with the appropriate metadata - result = iris.cube.Cube(data) - result.metadata = copy.deepcopy(src.metadata) - - # Copy across all the coordinates which don't span the grid. - # Record a mapping from old coordinate IDs to new coordinates, - # for subsequent use in creating updated aux_factories. - coord_mapping = {} - - def copy_coords(src_coords, add_method): - for coord in src_coords: - dims = src.coord_dims(coord) - if coord is src_x_coord: - coord = grid_x_coord - elif coord is src_y_coord: - coord = grid_y_coord - elif x_dim in dims or y_dim in dims: - continue - result_coord = coord.copy() - add_method(result_coord, dims) - coord_mapping[id(coord)] = result_coord - - copy_coords(src.dim_coords, result.add_dim_coord) - copy_coords(src.aux_coords, result.add_aux_coord) - - # Copy across any AuxFactory instances, and regrid their reference - # surfaces where required. - for factory in src.aux_factories: - for coord in factory.dependencies.itervalues(): - if coord is None: - continue - dims = src.coord_dims(coord) - if x_dim in dims and y_dim in dims: - result_coord = _regrid_reference_surface( - coord, dims, x_dim, y_dim, src_x_coord, src_y_coord, - sample_grid_x, sample_grid_y, regrid_callback) - result.add_aux_coord(result_coord, dims) - coord_mapping[id(coord)] = result_coord - try: - result.add_aux_factory(factory.updated(coord_mapping)) - except KeyError: - msg = 'Cannot update aux_factory {!r} because of dropped' \ - ' coordinates.'.format(factory.name()) - warnings.warn(msg) - return result - - -def regrid_bilinear_rectilinear_src_and_grid(src, grid): - """ - Return a new Cube that is the result of regridding the source Cube - onto the grid of the grid Cube using bilinear interpolation. - - Both the source and grid Cubes must be defined on rectilinear grids. - - Auxiliary coordinates which span the grid dimensions are ignored, - except where they provide a reference surface for an - :class:`iris.aux_factory.AuxCoordFactory`. - - Args: - - * src: - The source :class:`iris.cube.Cube` providing the data. - * grid: - The :class:`iris.cube.Cube` which defines the new grid. - - Returns: - The :class:`iris.cube.Cube` resulting from regridding the source - data onto the grid defined by the grid Cube. - - """ - # Validity checks - if not isinstance(src, iris.cube.Cube): - raise TypeError("'src' must be a Cube") - if not isinstance(grid, iris.cube.Cube): - raise TypeError("'grid' must be a Cube") - src_x_coord, src_y_coord = _get_xy_dim_coords(src) - grid_x_coord, grid_y_coord = _get_xy_dim_coords(grid) - src_cs = src_x_coord.coord_system - grid_cs = grid_x_coord.coord_system - if src_cs is None or grid_cs is None: - raise ValueError("Both 'src' and 'grid' Cubes must have a" - " coordinate system for their rectilinear grid" - " coordinates.") - - def _valid_units(coord): - if isinstance(coord.coord_system, (iris.coord_systems.GeogCS, - iris.coord_systems.RotatedGeogCS)): - valid_units = 'degrees' - else: - valid_units = 'm' - return coord.units == valid_units - if not all(_valid_units(coord) for coord in (src_x_coord, src_y_coord, - grid_x_coord, grid_y_coord)): - raise ValueError("Unsupported units: must be 'degrees' or 'm'.") - - # Convert the grid to a 2D sample grid in the src CRS. - sample_grid_x, sample_grid_y = _sample_grid(src_cs, - grid_x_coord, grid_y_coord) - - # Compute the interpolated data values. - x_dim = src.coord_dims(src_x_coord)[0] - y_dim = src.coord_dims(src_y_coord)[0] - src_data = src.data - fill_value = None - if np.ma.isMaskedArray(src_data): - # Since we're using iris.analysis.interpolate.linear which - # doesn't respect the mask, we replace masked values with NaN. - fill_value = src_data.fill_value - src_data = src_data.filled(np.nan) - data = _regrid_bilinear_array(src_data, x_dim, y_dim, - src_x_coord, src_y_coord, - sample_grid_x, sample_grid_y) - # Convert NaN based results to masked array where appropriate. - mask = np.isnan(data) - if np.any(mask): - data = np.ma.MaskedArray(data, mask, fill_value=fill_value) - - # Wrap up the data as a Cube. - result = _create_cube(data, src, x_dim, y_dim, src_x_coord, src_y_coord, - grid_x_coord, grid_y_coord, - sample_grid_x, sample_grid_y, - _regrid_bilinear_array) - return result - - -def _within_bounds(bounds, lower, upper): - """ - Return whether both lower and upper lie within the extremes - of bounds. - - """ - min_bound = np.min(bounds) - max_bound = np.max(bounds) + # Swap upper-lower is necessary. + if orderswap is True: + upper, lower = tgt_bounds.T + else: + lower, upper = tgt_bounds.T - return (min_bound <= lower <= max_bound) and \ - (min_bound <= upper <= max_bound) + return (((lower <= max_bound) * (lower >= min_bound)) * + ((upper <= max_bound) * (upper >= min_bound))) def _cropped_bounds(bounds, lower, upper): """ - Return a new bounds array and corresponding slice object (or indices) - that result from cropping the provided bounds between the specified lower - and upper values. The bounds at the extremities will be truncated so that - they start and end with lower and upper. + Return a new bounds array and corresponding slice object (or indices) of + the original data array, resulting from cropping the provided bounds + between the specified lower and upper values. The bounds at the + extremities will be truncated so that they start and end with lower and + upper. This function will return an empty NumPy array and slice if there is no overlap between the region covered by bounds and the region from lower to @@ -685,7 +339,7 @@ def _spherical_area(y_bounds, x_bounds, radius=1.0): """ return iris.analysis.cartography._quadrant_area( - y_bounds + np.pi / 2.0, x_bounds, radius) + y_bounds, x_bounds, radius) def _get_bounds_in_units(coord, units, dtype): @@ -695,15 +349,74 @@ def _get_bounds_in_units(coord, units, dtype): return coord.units.convert(coord.bounds.astype(dtype), units).astype(dtype) +def _weighted_mean_with_mdtol(data, weights, axis=None, mdtol=0): + """ + Return the weighted mean of an array over the specified axis + using the provided weights (if any) and a permitted fraction of + masked data. + + Args: + + * data (array-like): + Data to be averaged. + + * weights (array-like): + An array of the same shape as the data that specifies the contribution + of each corresponding data element to the calculated mean. + + Kwargs: + + * axis (int or tuple of ints): + Axis along which the mean is computed. The default is to compute + the mean of the flattened array. + + * mdtol (float): + Tolerance of missing data. The value returned in each element of the + returned array will be masked if the fraction of masked data exceeds + mdtol. This fraction is weighted by the `weights` array if one is + provided. mdtol=0 means no missing data is tolerated + while mdtol=1 will mean the resulting element will be masked if and + only if all the contributing elements of data are masked. + Defaults to 0. + + Returns: + Numpy array (possibly masked) or scalar. + + """ + if ma.is_masked(data): + res, unmasked_weights_sum = ma.average(data, weights=weights, + axis=axis, returned=True) + if mdtol < 1: + weights_sum = weights.sum(axis=axis) + frac_masked = 1 - np.true_divide(unmasked_weights_sum, weights_sum) + mask_pt = frac_masked > mdtol + if np.any(mask_pt) and not isinstance(res, ma.core.MaskedConstant): + if np.isscalar(res): + res = ma.masked + elif ma.isMaskedArray(res): + res.mask |= mask_pt + else: + res = ma.masked_array(res, mask=mask_pt) + else: + res = np.average(data, weights=weights, axis=axis) + return res + + def _regrid_area_weighted_array(src_data, x_dim, y_dim, src_x_bounds, src_y_bounds, grid_x_bounds, grid_y_bounds, grid_x_decreasing, grid_y_decreasing, - area_func, circular=False): + area_func, circular=False, mdtol=0): """ Regrid the given data from its source grid to a new grid using an area weighted mean to determine the resulting data values. + .. note:: + + Elements in the returned array that lie either partially + or entirely outside of the extent of the source grid will + be masked irrespective of the value of mdtol. + Args: * src_data: @@ -729,10 +442,22 @@ def _regrid_area_weighted_array(src_data, x_dim, y_dim, * area_func: A function that returns an (p, q) array of weights given an (p, 2) shaped array of Y bounds and an (q, 2) shaped array of X bounds. + + Kwargs: + * circular: A boolean indicating whether the `src_x_bounds` are periodic. Default is False. + * mdtol: + Tolerance of missing data. The value returned in each element of the + returned array will be masked if the fraction of missing data exceeds + mdtol. This fraction is calculated based on the area of masked cells + within each target cell. mdtol=0 means no missing data is tolerated + while mdtol=1 will mean the resulting element will be masked if and + only if all the overlapping elements of the source grid are masked. + Defaults to 0. + Returns: The regridded data as an N-dimensional NumPy array. The lengths of the X and Y dimensions will now match those of the target @@ -748,17 +473,39 @@ def _regrid_area_weighted_array(src_data, x_dim, y_dim, if y_dim is not None: new_shape[y_dim] = grid_y_bounds.shape[0] + # Use input cube dtype or convert values to the smallest possible float + # dtype when necessary. + dtype = np.promote_types(src_data.dtype, np.float16) + # Flag to indicate whether the original data was a masked array. src_masked = ma.isMaskedArray(src_data) if src_masked: - new_data = ma.zeros(new_shape, fill_value=src_data.fill_value) + new_data = ma.zeros(new_shape, fill_value=src_data.fill_value, + dtype=dtype) else: - new_data = ma.zeros(new_shape) + new_data = ma.zeros(new_shape, dtype=dtype) # Assign to mask to explode it, allowing indexed assignment. new_data.mask = False - # Simple for loop approach. indices = [slice(None)] * new_data.ndim + + # Determine which grid bounds are within src extent. + y_within_bounds = _within_bounds(src_y_bounds, grid_y_bounds, + grid_y_decreasing) + x_within_bounds = _within_bounds(src_x_bounds, grid_x_bounds, + grid_x_decreasing) + + # Cache which src_bounds are within grid bounds + cached_x_bounds = [] + cached_x_indices = [] + for (x_0, x_1) in grid_x_bounds: + if grid_x_decreasing: + x_0, x_1 = x_1, x_0 + x_bounds, x_indices = _cropped_bounds(src_x_bounds, x_0, x_1) + cached_x_bounds.append(x_bounds) + cached_x_indices.append(x_indices) + + # Simple for loop approach. for j, (y_0, y_1) in enumerate(grid_y_bounds): # Reverse lower and upper if dest grid is decreasing. if grid_y_decreasing: @@ -768,7 +515,8 @@ def _regrid_area_weighted_array(src_data, x_dim, y_dim, # Reverse lower and upper if dest grid is decreasing. if grid_x_decreasing: x_0, x_1 = x_1, x_0 - x_bounds, x_indices = _cropped_bounds(src_x_bounds, x_0, x_1) + x_bounds = cached_x_bounds[i] + x_indices = cached_x_indices[i] # Determine whether to mask element i, j based on overlap with # src. @@ -777,8 +525,8 @@ def _regrid_area_weighted_array(src_data, x_dim, y_dim, # (i.e. circular) this new cell would include a region outside of # the extent of the src grid and should therefore be masked. outside_extent = x_0 > x_1 and not circular - if (outside_extent or not _within_bounds(src_y_bounds, y_0, y_1) or - not _within_bounds(src_x_bounds, x_0, x_1)): + if (outside_extent or not y_within_bounds[j] or not + x_within_bounds[i]): # Mask out element(s) in new_data if x_dim is not None: indices[x_dim] = i @@ -805,11 +553,7 @@ def _regrid_area_weighted_array(src_data, x_dim, y_dim, # Numpy 1.7 allows the axis keyword arg to be a tuple. # If the version of NumPy is less than 1.7 manipulate the axes # of the data so the x and y dimensions can be flattened. - Version = collections.namedtuple('Version', - ('major', 'minor', 'micro')) - np_version = Version(*(int(val) for val in - np.version.version.split('.'))) - if np_version.minor < 7: + if _NP_VERSION.minor < 7: if y_dim is not None and x_dim is not None: flattened_shape = list(data.shape) if y_dim > x_dim: @@ -837,10 +581,8 @@ def _regrid_area_weighted_array(src_data, x_dim, y_dim, flattened_shape.append(-1) data = data.swapaxes(x_dim, -1).reshape( *flattened_shape) - # Axes of data over which the weighted mean is calculated. + weights = weights.ravel() axis = -1 - new_data_pt = ma.average(data, weights=weights.ravel(), - axis=axis) else: # Transpose weights to match dim ordering in data. weights_shape_y = weights.shape[0] @@ -861,21 +603,13 @@ def _regrid_area_weighted_array(src_data, x_dim, y_dim, # Assign new shape to raise error on copy. weights.shape = weights_padded_shape # Broadcast weights to match shape of data. - _, broadcasted_weights = np.broadcast_arrays(data, weights) + _, weights = np.broadcast_arrays(data, weights) # Axes of data over which the weighted mean is calculated. axis = tuple(axes) - # Calculate weighted mean taking into account missing data. - new_data_pt = ma.average(data, weights=broadcasted_weights, - axis=axis) - - # Determine suitable mask for data associated with cell. - # Could use all() here. - if src_masked: - # data.mask may be a bool, if not collapse via any(). - if data.mask.ndim: - new_data_pt_mask = data.mask.any(axis=axis) - else: - new_data_pt_mask = data.mask + + # Calculate weighted mean taking into account missing data. + new_data_pt = _weighted_mean_with_mdtol( + data, weights=weights, axis=axis, mdtol=mdtol) # Insert data (and mask) values into new array. if x_dim is not None: @@ -883,8 +617,6 @@ def _regrid_area_weighted_array(src_data, x_dim, y_dim, if y_dim is not None: indices[y_dim] = j new_data[tuple(indices)] = new_data_pt - if src_masked: - new_data.mask[tuple(indices)] = new_data_pt_mask # Remove new mask if original data was not masked # and no values in the new array are masked. @@ -894,7 +626,8 @@ def _regrid_area_weighted_array(src_data, x_dim, y_dim, return new_data -def regrid_area_weighted_rectilinear_src_and_grid(src_cube, grid_cube): +def regrid_area_weighted_rectilinear_src_and_grid(src_cube, grid_cube, + mdtol=0): """ Return a new cube with data values calculated using the area weighted mean of data values from src_grid regridded onto the horizontal grid of @@ -906,6 +639,12 @@ def regrid_area_weighted_rectilinear_src_and_grid(src_cube, grid_cube): also requires that the coordinates describing the horizontal grids all have bounds. + .. note:: + + Elements in data array of the returned cube that lie either partially + or entirely outside of the horizontal extent of the src_cube will + be masked irrespective of the value of mdtol. + Args: * src_cube: @@ -915,6 +654,17 @@ def regrid_area_weighted_rectilinear_src_and_grid(src_cube, grid_cube): An instance of :class:`iris.cube.Cube` that supplies the desired horizontal grid definition. + Kwargs: + + * mdtol: + Tolerance of missing data. The value returned in each element of the + returned cube's data array will be masked if the fraction of masked + data in the overlapping cells of the source cube exceeds mdtol. This + fraction is calculated based on the area of masked cells within each + target cell. mdtol=0 means no missing data is tolerated while mdtol=1 + will mean the resulting element will be masked if and only if all the + overlapping cells of the source cube are masked. Defaults to 0. + Returns: A new :class:`iris.cube.Cube` instance. @@ -961,8 +711,8 @@ def regrid_area_weighted_rectilinear_src_and_grid(src_cube, grid_cube): src_x.units == 'degrees' or src_x.units == 'radians') # Get src and grid bounds in the same units. - x_units = iris.unit.Unit('radians') if spherical else src_x.units - y_units = iris.unit.Unit('radians') if spherical else src_y.units + x_units = cf_units.Unit('radians') if spherical else src_x.units + y_units = cf_units.Unit('radians') if spherical else src_y.units # Operate in highest precision. src_dtype = np.promote_types(src_x.bounds.dtype, src_y.bounds.dtype) @@ -1006,15 +756,17 @@ def regrid_area_weighted_rectilinear_src_and_grid(src_cube, grid_cube): grid_x_bounds, grid_y_bounds, grid_x_decreasing, grid_y_decreasing, - area_func, circular) + area_func, circular, mdtol) # Wrap up the data as a Cube. # Create 2d meshgrids as required by _create_cube func. - meshgrid_x, meshgrid_y = np.meshgrid(grid_x.points, grid_y.points) - new_cube = _create_cube(new_data, src_cube, src_x_dim, src_y_dim, - src_x, src_y, grid_x, grid_y, - meshgrid_x, meshgrid_y, - _regrid_bilinear_array) + meshgrid_x, meshgrid_y = _meshgrid(grid_x.points, grid_y.points) + regrid_callback = RectilinearRegridder._regrid + new_cube = RectilinearRegridder._create_cube(new_data, src_cube, + src_x_dim, src_y_dim, + src_x, src_y, grid_x, grid_y, + meshgrid_x, meshgrid_y, + regrid_callback) # Slice out any length 1 dimensions. indices = [slice(None, None)] * new_data.ndim @@ -1028,14 +780,39 @@ def regrid_area_weighted_rectilinear_src_and_grid(src_cube, grid_cube): return new_cube +def _transform_xy_arrays(crs_from, x, y, crs_to): + """ + Transform 2d points between cartopy coordinate reference systems. + + NOTE: copied private function from iris.analysis.cartography. + + Args: + + * crs_from, crs_to (:class:`cartopy.crs.Projection`): + The coordinate reference systems. + * x, y (arrays): + point locations defined in 'crs_from'. + + Returns: + x, y : Arrays of locations defined in 'crs_to'. + + """ + pts = crs_to.transform_points(crs_from, x, y) + return pts[..., 0], pts[..., 1] + + def regrid_weighted_curvilinear_to_rectilinear(src_cube, weights, grid_cube): """ Return a new cube with the data values calculated using the weighted mean of data values from :data:`src_cube` and the weights from :data:`weights` regridded onto the horizontal grid of :data:`grid_cube`. - This function requires that the :data:`src_cube` has a curvilinear - horizontal grid and the target :data:`grid_cube` is rectilinear + This function requires that the :data:`src_cube` has a horizontal grid + defined by a pair of X- and Y-axis coordinates which are mapped over the + same cube dimensions, thus each point has an individually defined X and + Y coordinate value. The actual dimensions of these coordinates are of + no significance. + The :data:`src_cube` grid cube must have a normal horizontal grid, i.e. expressed in terms of two orthogonal 1D horizontal coordinates. Both grids must be in the same coordinate system, and the :data:`grid_cube` must have horizontal coordinates that are both bounded and contiguous. @@ -1051,21 +828,18 @@ def regrid_weighted_curvilinear_to_rectilinear(src_cube, weights, grid_cube): .. warning:: - * Only 2D cubes are supported. * All coordinates that span the :data:`src_cube` that don't define the horizontal curvilinear grid will be ignored. - * The :class:`iris.unit.Unit` of the horizontal grid coordinates - must be either :data:`degrees` or :data:`radians`. Args: * src_cube: A :class:`iris.cube.Cube` instance that defines the source variable grid to be regridded. - * weights: + * weights (array or None): A :class:`numpy.ndarray` instance that defines the weights for the source variable grid cells. Must have the same shape - as the :data:`src_cube.data`. + as the X and Y coordinates. If weights is None, all-ones will be used. * grid_cube: A :class:`iris.cube.Cube` instance that defines the target rectilinear grid. @@ -1074,14 +848,23 @@ def regrid_weighted_curvilinear_to_rectilinear(src_cube, weights, grid_cube): A :class:`iris.cube.Cube` instance. """ - if src_cube.shape != weights.shape: - msg = 'The source cube and weights require the same data shape.' - raise ValueError(msg) + regrid_info = \ + _regrid_weighted_curvilinear_to_rectilinear__prepare( + src_cube, weights, grid_cube) + result = _regrid_weighted_curvilinear_to_rectilinear__perform( + src_cube, regrid_info) + return result - if src_cube.ndim != 2 or grid_cube.ndim != 2: - msg = 'The source cube and target grid cube must reference 2D data.' - raise ValueError(msg) +def _regrid_weighted_curvilinear_to_rectilinear__prepare( + src_cube, weights, grid_cube): + """ + First (setup) part of 'regrid_weighted_curvilinear_to_rectilinear'. + + Check inputs and calculate the sparse regrid matrix and related info. + The 'regrid info' returned can be re-used over many 2d slices. + + """ if src_cube.aux_factories: msg = 'All source cube derived coordinates will be ignored.' warnings.warn(msg) @@ -1089,33 +872,16 @@ def regrid_weighted_curvilinear_to_rectilinear(src_cube, weights, grid_cube): # Get the source cube x and y 2D auxiliary coordinates. sx, sy = src_cube.coord(axis='x'), src_cube.coord(axis='y') # Get the target grid cube x and y dimension coordinates. - tx, ty = _get_xy_dim_coords(grid_cube) - - if sx.units.modulus is None or sy.units.modulus is None or \ - sx.units != sy.units: - msg = 'The source cube x ({!r}) and y ({!r}) coordinates must ' \ - 'have units of degrees or radians.' - raise ValueError(msg.format(sx.name(), sy.name())) - - if tx.units.modulus is None or ty.units.modulus is None or \ - tx.units != ty.units: - msg = 'The target grid cube x ({!r}) and y ({!r}) coordinates must ' \ - 'have units of degrees or radians.' - raise ValueError(msg.format(tx.name(), ty.name())) + tx, ty = get_xy_dim_coords(grid_cube) - if sx.units != tx.units: - msg = 'The source cube and target grid cube must have x and y ' \ - 'coordinates with the same units.' - raise ValueError(msg) - - if sx.ndim != sy.ndim: + if sx.units != sy.units: msg = 'The source cube x ({!r}) and y ({!r}) coordinates must ' \ - 'have the same dimensionality.' + 'have the same units.' raise ValueError(msg.format(sx.name(), sy.name())) - if sx.ndim != 2: + if src_cube.coord_dims(sx) != src_cube.coord_dims(sy): msg = 'The source cube x ({!r}) and y ({!r}) coordinates must ' \ - 'be 2D auxiliary coordinates.' + 'map onto the same cube dimensions.' raise ValueError(msg.format(sx.name(), sy.name())) if sx.coord_system != sy.coord_system: @@ -1123,11 +889,31 @@ def regrid_weighted_curvilinear_to_rectilinear(src_cube, weights, grid_cube): 'have the same coordinate system.' raise ValueError(msg.format(sx.name(), sy.name())) - if sx.coord_system != tx.coord_system and \ - sx.coord_system is not None and \ - tx.coord_system is not None: - msg = 'The source cube and target grid cube must have the same ' \ - 'coordinate system.' + if sx.coord_system is None: + msg = ('The source X and Y coordinates must have a defined ' + 'coordinate system.') + raise ValueError(msg) + + if tx.units != ty.units: + msg = 'The target grid cube x ({!r}) and y ({!r}) coordinates must ' \ + 'have the same units.' + raise ValueError(msg.format(tx.name(), ty.name())) + + if tx.coord_system is None: + msg = ('The target X and Y coordinates must have a defined ' + 'coordinate system.') + raise ValueError(msg) + + if tx.coord_system != ty.coord_system: + msg = 'The target grid cube x ({!r}) and y ({!r}) coordinates must ' \ + 'have the same coordinate system.' + raise ValueError(msg.format(tx.name(), ty.name())) + + if weights is None: + weights = np.ones(sx.shape) + if weights.shape != sx.shape: + msg = ('Provided weights must have the same shape as the X and Y ' + 'coordinates.') raise ValueError(msg) if not tx.has_bounds() or not tx.is_contiguous(): @@ -1143,29 +929,52 @@ def regrid_weighted_curvilinear_to_rectilinear(src_cube, weights, grid_cube): def _src_align_and_flatten(coord): # Return a flattened, unmasked copy of a coordinate's points array that # will align with a flattened version of the source cube's data. + # + # PP-TODO: Should work with any cube dimensions for X and Y coords. + # Probably needs fixing anyway? + # points = coord.points if src_cube.coord_dims(coord) == (1, 0): points = points.T if points.shape != src_cube.shape: - msg = 'The shape of the points array of !r is not compatible ' \ - 'with the shape of !r.'.format(coord.name(), src_cube.name()) - raise ValueError(msg) + msg = 'The shape of the points array of {!r} is not compatible ' \ + 'with the shape of {!r}.' + raise ValueError(msg.format(coord.name(), src_cube.name())) return np.asarray(points.flatten()) # Align and flatten the coordinate points of the source space. sx_points = _src_align_and_flatten(sx) sy_points = _src_align_and_flatten(sy) - # Match the source cube x coordinate range to the target grid - # cube x coordinate range. - min_sx, min_tx = np.min(sx.points), np.min(tx.points) + # Transform source X and Y points into the target coord-system, if needed. + if sx.coord_system != tx.coord_system: + src_crs = sx.coord_system.as_cartopy_projection() + tgt_crs = tx.coord_system.as_cartopy_projection() + sx_points, sy_points = _transform_xy_arrays( + src_crs, sx_points, sy_points, tgt_crs) + # + # TODO: how does this work with scaled units ?? + # e.g. if crs is latlon, units could be degrees OR radians ? + # + + # Wrap modular values (e.g. longitudes) if required. modulus = sx.units.modulus - if min_sx < 0 and min_tx >= 0: - indices = np.where(sx_points < 0) - sx_points[indices] += modulus - elif min_sx >= 0 and min_tx < 0: - indices = np.where(sx_points > (modulus / 2)) - sx_points[indices] -= modulus + if modulus is not None: + # Match the source cube x coordinate range to the target grid + # cube x coordinate range. + min_sx, min_tx = np.min(sx.points), np.min(tx.points) + if min_sx < 0 and min_tx >= 0: + indices = np.where(sx_points < 0) + # Ensure += doesn't raise a TypeError + if not np.can_cast(modulus, sx_points.dtype): + sx_points = sx_points.astype(type(modulus), casting='safe') + sx_points[indices] += modulus + elif min_sx >= 0 and min_tx < 0: + indices = np.where(sx_points > (modulus / 2)) + # Ensure -= doesn't raise a TypeError + if not np.can_cast(modulus, sx_points.dtype): + sx_points = sx_points.astype(type(modulus), casting='safe') + sx_points[indices] -= modulus # Create target grid cube x and y cell boundaries. tx_depth, ty_depth = tx.points.size, ty.points.size @@ -1222,16 +1031,9 @@ def _regrid_indices(cells, depth, points): # target cube cell. # Determine the valid indices and their offsets in M x N space. - if ma.isMaskedArray(src_cube.data): - # Calculate the valid M offsets, accounting for the source cube mask. - mask = ~src_cube.data.mask.flatten() - cols = np.where((y_indices >= 0) & (y_indices < ty_depth) & - (x_indices >= 0) & (x_indices < tx_depth) & - mask)[0] - else: - # Calculate the valid M offsets. - cols = np.where((y_indices >= 0) & (y_indices < ty_depth) & - (x_indices >= 0) & (x_indices < tx_depth))[0] + # Calculate the valid M offsets. + cols = np.where((y_indices >= 0) & (y_indices < ty_depth) & + (x_indices >= 0) & (x_indices < tx_depth))[0] # Reduce the indices to only those that are valid. x_indices = x_indices[cols] @@ -1258,15 +1060,79 @@ def _regrid_indices(cells, depth, points): # contribution from one or more source points. rows = np.nonzero(sum_weights) - # Calculate the numerator of the weighted mean (M, 1). - numerator = sparse_matrix * src_cube.data.reshape(-1, 1) + # NOTE: when source points are masked, this 'sum_weights' is possibly + # incorrect and needs re-calculating. Likewise 'rows' may cover target + # cells which happen to get no data. This is dealt with by adjusting as + # required in the '__perform' function, below. + + regrid_info = (sparse_matrix, sum_weights, rows, grid_cube) + return regrid_info + + +def _regrid_weighted_curvilinear_to_rectilinear__perform( + src_cube, regrid_info): + """ + Second (regrid) part of 'regrid_weighted_curvilinear_to_rectilinear'. + + Perform the prepared regrid calculation on a single 2d cube. + + """ + sparse_matrix, sum_weights, rows, grid_cube = regrid_info - # Calculate the weighted mean payload. + # Calculate the numerator of the weighted mean (M, 1). + is_masked = ma.isMaskedArray(src_cube.data) + if not is_masked: + data = src_cube.data + else: + # Use raw data array + data = src_cube.data.data + # Check if there are any masked source points to take account of. + is_masked = np.ma.is_masked(src_cube.data) + if is_masked: + # Zero any masked source points so they add nothing in output sums. + mask = src_cube.data.mask + data[mask] = 0.0 + # Calculate a new 'sum_weights' to allow for missing source points. + # N.B. it is more efficient to use the original once-calculated + # sparse matrix, but in this case we can't. + # Hopefully, this post-multiplying by the validities is less costly + # than repeating the whole sparse calculation. + valid_src_cells = ~mask.flat[:] + src_cell_validity_factors = sparse_diags( + np.array(valid_src_cells, dtype=int), + 0) + valid_weights = sparse_matrix * src_cell_validity_factors + sum_weights = valid_weights.sum(axis=1).getA() + # Work out where output cells are missing all contributions. + # This allows for where 'rows' contains output cells that have no + # data because of missing input points. + zero_sums = sum_weights == 0.0 + # Make sure we can still divide by sum_weights[rows]. + sum_weights[zero_sums] = 1.0 + + # Calculate sum in each target cell, over contributions from each source + # cell. + numerator = sparse_matrix * data.reshape(-1, 1) + + # Create a template for the weighted mean result. weighted_mean = ma.masked_all(numerator.shape, dtype=numerator.dtype) + + # Calculate final results in all relevant places. weighted_mean[rows] = numerator[rows] / sum_weights[rows] + if is_masked: + # Ensure masked points where relevant source cells were all missing. + if np.any(zero_sums): + # Make masked if it wasn't. + weighted_mean = np.ma.asarray(weighted_mean) + # Mask where contributing sums were zero. + weighted_mean[zero_sums] = np.ma.masked # Construct the final regridded weighted mean cube. - dim_coords_and_dims = zip((ty.copy(), tx.copy()), (ty_dim, tx_dim)) + tx = grid_cube.coord(axis='x', dim_coords=True) + ty = grid_cube.coord(axis='y', dim_coords=True) + tx_dim, = grid_cube.coord_dims(tx) + ty_dim, = grid_cube.coord_dims(ty) + dim_coords_and_dims = list(zip((ty.copy(), tx.copy()), (ty_dim, tx_dim))) cube = iris.cube.Cube(weighted_mean.reshape(grid_cube.shape), dim_coords_and_dims=dim_coords_and_dims) cube.metadata = copy.deepcopy(src_cube.metadata) @@ -1275,3 +1141,611 @@ def _regrid_indices(cells, depth, points): cube.add_aux_coord(coord.copy()) return cube + + +class _CurvilinearRegridder(object): + """ + This class provides support for performing point-in-cell regridding + between a curvilinear source grid and a rectilinear target grid. + + """ + def __init__(self, src_grid_cube, target_grid_cube, weights=None): + """ + Create a regridder for conversions between the source + and target grids. + + Args: + + * src_grid_cube: + The :class:`~iris.cube.Cube` providing the source grid. + * tgt_grid_cube: + The :class:`~iris.cube.Cube` providing the target grid. + + Optional Args: + + * weights: + A :class:`numpy.ndarray` instance that defines the weights + for the grid cells of the source grid. Must have the same shape + as the data of the source grid. + If unspecified, equal weighting is assumed. + + """ + # Validity checks. + if not isinstance(src_grid_cube, iris.cube.Cube): + raise TypeError("'src_grid_cube' must be a Cube") + if not isinstance(target_grid_cube, iris.cube.Cube): + raise TypeError("'target_grid_cube' must be a Cube") + # Snapshot the state of the cubes to ensure that the regridder + # is impervious to external changes to the original source cubes. + self._src_cube = src_grid_cube.copy() + self._target_cube = target_grid_cube.copy() + self.weights = weights + self._regrid_info = None + + @staticmethod + def _get_horizontal_coord(cube, axis): + """ + Gets the horizontal coordinate on the supplied cube along the + specified axis. + + Args: + + * cube: + An instance of :class:`iris.cube.Cube`. + * axis: + Locate coordinates on `cube` along this axis. + + Returns: + The horizontal coordinate on the specified axis of the supplied + cube. + + """ + coords = cube.coords(axis=axis, dim_coords=False) + if len(coords) != 1: + raise ValueError('Cube {!r} must contain a single 1D {} ' + 'coordinate.'.format(cube.name()), axis) + return coords[0] + + def __call__(self, src): + """ + Regrid the supplied :class:`~iris.cube.Cube` on to the target grid of + this :class:`_CurvilinearRegridder`. + + The given cube must be defined with the same grid as the source + grid used to create this :class:`_CurvilinearRegridder`. + + Args: + + * src: + A :class:`~iris.cube.Cube` to be regridded. + + Returns: + A cube defined with the horizontal dimensions of the target + and the other dimensions from this cube. The data values of + this cube will be converted to values on the new grid using + point-in-cell regridding. + + """ + # Validity checks. + if not isinstance(src, iris.cube.Cube): + raise TypeError("'src' must be a Cube") + + gx = self._get_horizontal_coord(self._src_cube, 'x') + gy = self._get_horizontal_coord(self._src_cube, 'y') + src_grid = (gx.copy(), gy.copy()) + sx = self._get_horizontal_coord(src, 'x') + sy = self._get_horizontal_coord(src, 'y') + if (sx, sy) != src_grid: + raise ValueError('The given cube is not defined on the same ' + 'source grid as this regridder.') + + # Call the regridder function. + # This includes repeating over any non-XY dimensions, because the + # underlying routine does not support this. + # FOR NOW: we will use cube.slices and merge to achieve this, + # though that is not a terribly efficient method ... + # TODO: create a template result cube and paste data slices into it, + # which would be more efficient. + result_slices = iris.cube.CubeList([]) + for slice_cube in src.slices(sx): + if self._regrid_info is None: + # Calculate the basic regrid info just once. + self._regrid_info = \ + _regrid_weighted_curvilinear_to_rectilinear__prepare( + slice_cube, self.weights, self._target_cube) + slice_result = \ + _regrid_weighted_curvilinear_to_rectilinear__perform( + slice_cube, self._regrid_info) + result_slices.append(slice_result) + result = result_slices.merge_cube() + return result + + +class PointInCell(object): + """ + This class describes the point-in-cell regridding scheme for use + typically with :meth:`iris.cube.Cube.regrid()`. + + The PointInCell regridder can regrid data from a source grid of any + dimensionality and in any coordinate system. + The location of each source point is specified by X and Y coordinates + mapped over the same cube dimensions, aka "grid dimensions" : the grid may + have any dimensionality. The X and Y coordinates must also have the same, + defined coord_system. + The weights, if specified, must have the same shape as the X and Y + coordinates. + The output grid can be any 'normal' XY grid, specified by *separate* X + and Y coordinates : That is, X and Y have two different cube dimensions. + The output X and Y coordinates must also have a common, specified + coord_system. + + """ + def __init__(self, weights=None): + """ + Point-in-cell regridding scheme suitable for regridding over one + or more orthogonal coordinates. + + Optional Args: + + * weights: + A :class:`numpy.ndarray` instance that defines the weights + for the grid cells of the source grid. Must have the same shape + as the data of the source grid. + If unspecified, equal weighting is assumed. + + """ + self.weights = weights + + def regridder(self, src_grid, target_grid): + """ + Creates a point-in-cell regridder to perform regridding from the + source grid to the target grid. + + Typically you should use :meth:`iris.cube.Cube.regrid` for + regridding a cube. There are, however, some situations when + constructing your own regridder is preferable. These are detailed in + the :ref:`user guide `. + + Args: + + * src_grid: + The :class:`~iris.cube.Cube` defining the source grid. + * target_grid: + The :class:`~iris.cube.Cube` defining the target grid. + + Returns: + A callable with the interface: + + `callable(cube)` + + where `cube` is a cube with the same grid as `src_grid` + that is to be regridded to the `target_grid`. + + """ + return _CurvilinearRegridder(src_grid, target_grid, self.weights) + + +class _ProjectedUnstructuredRegridder(object): + """ + This class provides regridding that uses scipy.interpolate.griddata. + + """ + def __init__(self, src_cube, tgt_grid_cube, method, + projection=None): + """ + Create a regridder for conversions between the source + and target grids. + + Args: + + * src_cube: + The :class:`~iris.cube.Cube` providing the source points. + * tgt_grid_cube: + The :class:`~iris.cube.Cube` providing the target grid. + * method: + Either 'linear' or 'nearest'. + * projection: + The projection in which the interpolation is performed. If None, a + PlateCarree projection is used. Defaults to None. + + """ + # Validity checks. + if not isinstance(src_cube, iris.cube.Cube): + raise TypeError("'src_cube' must be a Cube") + if not isinstance(tgt_grid_cube, iris.cube.Cube): + raise TypeError("'tgt_grid_cube' must be a Cube") + + # Snapshot the state of the target cube to ensure that the regridder + # is impervious to external changes to the original source cubes. + self._tgt_grid = snapshot_grid(tgt_grid_cube) + + # Check the target grid units. + for coord in self._tgt_grid: + self._check_units(coord) + + # Whether to use linear or nearest-neighbour interpolation. + if method not in ('linear', 'nearest'): + msg = 'Regridding method {!r} not supported.'.format(method) + raise ValueError(msg) + self._method = method + + src_x_coord, src_y_coord = get_xy_coords(src_cube) + if src_x_coord.coord_system != src_y_coord.coord_system: + raise ValueError("'src_cube' lateral geographic coordinates have " + "differing coordinate sytems.") + if src_x_coord.coord_system is None: + raise ValueError("'src_cube' lateral geographic coordinates have " + "no coordinate sytem.") + tgt_x_coord, tgt_y_coord = get_xy_dim_coords(tgt_grid_cube) + if tgt_x_coord.coord_system != tgt_y_coord.coord_system: + raise ValueError("'tgt_grid_cube' lateral geographic coordinates " + "have differing coordinate sytems.") + if tgt_x_coord.coord_system is None: + raise ValueError("'tgt_grid_cube' lateral geographic coordinates " + "have no coordinate sytem.") + + if projection is None: + globe = src_x_coord.coord_system.as_cartopy_globe() + projection = ccrs.Sinusoidal(globe=globe) + self._projection = projection + + def _check_units(self, coord): + if coord.coord_system is None: + # No restriction on units. + pass + elif isinstance(coord.coord_system, + (iris.coord_systems.GeogCS, + iris.coord_systems.RotatedGeogCS)): + # Units for lat-lon or rotated pole must be 'degrees'. Note + # that 'degrees_east' etc. are equal to 'degrees'. + if coord.units != 'degrees': + msg = "Unsupported units for coordinate system. " \ + "Expected 'degrees' got {!r}.".format(coord.units) + raise ValueError(msg) + else: + # Units for other coord systems must be equal to metres. + if coord.units != 'm': + msg = "Unsupported units for coordinate system. " \ + "Expected 'metres' got {!r}.".format(coord.units) + raise ValueError(msg) + + @staticmethod + def _regrid(src_data, xy_dim, src_x_coord, src_y_coord, + tgt_x_coord, tgt_y_coord, + projection, method): + """ + Regrids input data from the source to the target. Calculation is. + + """ + # Transform coordinates into the projection the interpolation will be + # performed in. + src_projection = src_x_coord.coord_system.as_cartopy_projection() + projected_src_points = projection.transform_points( + src_projection, src_x_coord.points, src_y_coord.points) + + tgt_projection = tgt_x_coord.coord_system.as_cartopy_projection() + tgt_x, tgt_y = _meshgrid(tgt_x_coord.points, tgt_y_coord.points) + projected_tgt_grid = projection.transform_points( + tgt_projection, tgt_x, tgt_y) + + # Prepare the result data array. + # XXX TODO: Deal with masked src_data + tgt_y_shape, = tgt_y_coord.shape + tgt_x_shape, = tgt_x_coord.shape + tgt_shape = src_data.shape[:xy_dim] + (tgt_y_shape,) + (tgt_x_shape,) \ + + src_data.shape[xy_dim+1:] + data = np.empty(tgt_shape, dtype=src_data.dtype) + + iter_shape = list(src_data.shape) + iter_shape[xy_dim] = 1 + + for index in np.ndindex(tuple(iter_shape)): + src_index = list(index) + src_index[xy_dim] = slice(None) + src_subset = src_data[tuple(src_index)] + tgt_index = index[:xy_dim] + (slice(None), slice(None)) \ + + index[xy_dim+1:] + data[tgt_index] = scipy.interpolate.griddata( + projected_src_points[..., :2], src_subset, + (projected_tgt_grid[..., 0], projected_tgt_grid[..., 1]), + method=method) + data = np.ma.array(data, mask=np.isnan(data)) + return data + + def _create_cube(self, data, src, src_xy_dim, src_x_coord, src_y_coord, + grid_x_coord, grid_y_coord, + regrid_callback): + """ + Return a new Cube for the result of regridding the source Cube onto + the new grid. + + All the metadata and coordinates of the result Cube are copied from + the source Cube, with two exceptions: + - Grid dimension coordinates are copied from the grid Cube. + - Auxiliary coordinates which span the grid dimensions are + ignored, except where they provide a reference surface for an + :class:`iris.aux_factory.AuxCoordFactory`. + + Args: + + * data: + The regridded data as an N-dimensional NumPy array. + * src: + The source Cube. + * src_xy_dim: + The dimension the X and Y coord span within the source Cube. + * src_x_coord: + The X coordinate (either :class:`iris.coords.AuxCoord` or + :class:`iris.coords.DimCoord`). + * src_y_coord: + The Y coordinate (either :class:`iris.coords.AuxCoord` or + :class:`iris.coords.DimCoord`). + * grid_x_coord: + The :class:`iris.coords.DimCoord` for the new grid's X + coordinate. + * grid_y_coord: + The :class:`iris.coords.DimCoord` for the new grid's Y + coordinate. + * regrid_callback: + The routine that will be used to calculate the interpolated + values of any reference surfaces. + + Returns: + The new, regridded Cube. + + """ + # Create a result cube with the appropriate metadata + result = iris.cube.Cube(data) + result.metadata = copy.deepcopy(src.metadata) + + # Copy across all the coordinates which don't span the grid. + # Record a mapping from old coordinate IDs to new coordinates, + # for subsequent use in creating updated aux_factories. + coord_mapping = {} + + def copy_coords(src_coords, add_method): + for coord in src_coords: + dims = src.coord_dims(coord) + if coord is src_x_coord: + coord = grid_x_coord + # Increase dimensionality to account for 1D coord being + # regridded onto 2D grid + dims = list(dims) + dims[0] += 1 + dims = tuple(dims) + add_method = result.add_dim_coord + elif coord is src_y_coord: + coord = grid_y_coord + add_method = result.add_dim_coord + elif src_xy_dim in dims: + continue + result_coord = coord.copy() + add_method(result_coord, dims) + coord_mapping[id(coord)] = result_coord + + copy_coords(src.dim_coords, result.add_dim_coord) + copy_coords(src.aux_coords, result.add_aux_coord) + + def regrid_reference_surface(src_surface_coord, surface_dims, + src_xy_dim, src_x_coord, src_y_coord, + grid_x_coord, grid_y_coord, + regrid_callback): + # Determine which of the reference surface's dimensions span the X + # and Y dimensions of the source cube. + surface_xy_dim = surface_dims.index(src_xy_dim) + surface = regrid_callback(src_surface_coord.points, surface_xy_dim, + src_x_coord, src_y_coord, + grid_x_coord, grid_y_coord) + surface_coord = src_surface_coord.copy(surface) + return surface_coord + + # Copy across any AuxFactory instances, and regrid their reference + # surfaces where required. + for factory in src.aux_factories: + for coord in six.itervalues(factory.dependencies): + if coord is None: + continue + dims = src.coord_dims(coord) + if src_xy_dim in dims: + result_coord = regrid_reference_surface(coord, dims, + src_xy_dim, + src_x_coord, + src_y_coord, + grid_x_coord, + grid_y_coord, + regrid_callback) + result.add_aux_coord(result_coord, (dims[0], dims[0]+1)) + coord_mapping[id(coord)] = result_coord + try: + result.add_aux_factory(factory.updated(coord_mapping)) + except KeyError: + msg = 'Cannot update aux_factory {!r} because of dropped' \ + ' coordinates.'.format(factory.name()) + warnings.warn(msg) + return result + + def __call__(self, src_cube): + """ + Regrid this :class:`~iris.cube.Cube` on to the target grid of + this :class:`UnstructuredProjectedRegridder`. + + The given cube must be defined with the same grid as the source + grid used to create this :class:`UnstructuredProjectedRegridder`. + + Args: + + * src_cube: + A :class:`~iris.cube.Cube` to be regridded. + + Returns: + A cube defined with the horizontal dimensions of the target + and the other dimensions from this cube. The data values of + this cube will be converted to values on the new grid using + either nearest-neighbour or linear interpolation. + + """ + # Validity checks. + if not isinstance(src_cube, iris.cube.Cube): + raise TypeError("'src' must be a Cube") + + src_x_coord, src_y_coord = get_xy_coords(src_cube) + tgt_x_coord, tgt_y_coord = self._tgt_grid + src_cs = src_x_coord.coord_system + tgt_cs = tgt_x_coord.coord_system + + if src_x_coord.coord_system != src_y_coord.coord_system: + raise ValueError("'src' lateral geographic coordinates have " + "differing coordinate sytems.") + if src_cs is None: + raise ValueError("'src' lateral geographic coordinates have " + "no coordinate sytem.") + + # Check the source grid units. + for coord in (src_x_coord, src_y_coord): + self._check_units(coord) + + src_x_dim, = src_cube.coord_dims(src_x_coord) + src_y_dim, = src_cube.coord_dims(src_y_coord) + + if src_x_dim != src_y_dim: + raise ValueError("'src' lateral geographic coordinates should map " + "the same dimension.") + src_xy_dim = src_x_dim + + # Compute the interpolated data values. + data = self._regrid(src_cube.data, src_xy_dim, + src_x_coord, src_y_coord, + tgt_x_coord, tgt_y_coord, + self._projection, method=self._method) + + # Wrap up the data as a Cube. + regrid_callback = functools.partial(self._regrid, + method=self._method, + projection=self._projection) + + new_cube = self._create_cube(data, src_cube, src_xy_dim, + src_x_coord, src_y_coord, + tgt_x_coord, tgt_y_coord, + regrid_callback) + + return new_cube + + +class ProjectedUnstructuredLinear(object): + """ + This class describes the linear regridding scheme which uses the + scipy.interpolate.griddata to regrid unstructured data on to a grid. + + The source cube and the target cube will be projected into a common + projection for the scipy calculation to be performed. + + """ + def __init__(self, projection=None): + """ + Linear regridding scheme that uses scipy.interpolate.griddata on + projected unstructured data. + + Optional Args: + + * projection: `cartopy.crs instance` + The projection that the scipy calculation is performed in. + If None is given, a PlateCarree projection is used. Defaults to + None. + + """ + self.projection = projection + + def regridder(self, src_cube, target_grid): + """ + Creates a linear regridder to perform regridding, using + scipy.interpolate.griddata from unstructured source points to the + target grid. The regridding calculation is performed in the given + projection. + + Typically you should use :meth:`iris.cube.Cube.regrid` for + regridding a cube. There are, however, some situations when + constructing your own regridder is preferable. These are detailed in + the :ref:`user guide `. + + Args: + + * src_cube: + The :class:`~iris.cube.Cube` defining the unstructured source + points. + * target_grid: + The :class:`~iris.cube.Cube` defining the target grid. + + Returns: + A callable with the interface: + + `callable(cube)` + + where `cube` is a cube with the same grid as `src_cube` + that is to be regridded to the `target_grid`. + + """ + return _ProjectedUnstructuredRegridder(src_cube, target_grid, + 'linear', self.projection) + + +class ProjectedUnstructuredNearest(object): + """ + This class describes the nearest regridding scheme which uses the + scipy.interpolate.griddata to regrid unstructured data on to a grid. + + The source cube and the target cube will be projected into a common + projection for the scipy calculation to be performed. + + .. Note:: + The :class:`iris.analysis.UnstructuredNearest` scheme performs + essentially the same job. That calculation is more rigorously + correct and may be applied to larger data regions (including global). + This one however, where applicable, is substantially faster. + + """ + def __init__(self, projection=None): + """ + Nearest regridding scheme that uses scipy.interpolate.griddata on + projected unstructured data. + + Optional Args: + + * projection: `cartopy.crs instance` + The projection that the scipy calculation is performed in. + If None is given, a PlateCarree projection is used. Defaults to + None. + + """ + self.projection = projection + + def regridder(self, src_cube, target_grid): + """ + Creates a nearest-neighbour regridder to perform regridding, using + scipy.interpolate.griddata from unstructured source points to the + target grid. The regridding calculation is performed in the given + projection. + + Typically you should use :meth:`iris.cube.Cube.regrid` for + regridding a cube. There are, however, some situations when + constructing your own regridder is preferable. These are detailed in + the :ref:`user guide `. + + Args: + + * src_cube: + The :class:`~iris.cube.Cube` defining the unstructured source + points. + * target_grid: + The :class:`~iris.cube.Cube` defining the target grid. + + Returns: + A callable with the interface: + + `callable(cube)` + + where `cube` is a cube with the same grid as `src_cube` + that is to be regridded to the `target_grid`. + + """ + return _ProjectedUnstructuredRegridder(src_cube, target_grid, + 'nearest', self.projection) diff --git a/lib/iris/experimental/regrid_conservative.py b/lib/iris/experimental/regrid_conservative.py index 336714105d..d8dc2219a0 100644 --- a/lib/iris/experimental/regrid_conservative.py +++ b/lib/iris/experimental/regrid_conservative.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -19,14 +19,16 @@ """ -import numpy as np -# Import ESMF via iris.proxy, just so we can build the docs with no ESMF. -import iris.proxy -iris.proxy.apply_proxy('ESMF', globals()) +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa import cartopy.crs as ccrs +import numpy as np + import iris -import iris.experimental.regrid as i_regrid +from iris.analysis._interpolation import get_xy_dim_coords +from iris.analysis._regrid import RectilinearRegridder +from iris.util import _meshgrid #: A static Cartopy Geodetic() instance for transforming to true-lat-lons. @@ -71,19 +73,22 @@ def _make_esmpy_field(x_coord, y_coord, ref_name='field', Add a mask item to the grid, assigning it 0/1 where mask=False/True. """ + # Lazy import so we can build the docs with no ESMF. + import ESMF + # Create a Grid object describing the coordinate cells. dims = [len(coord.points) for coord in (x_coord, y_coord)] dims = np.array(dims, dtype=np.int32) # specific type required by ESMF. grid = ESMF.Grid(dims) # Get all cell corner coordinates as true-lat-lons - x_bounds, y_bounds = np.meshgrid(x_coord.contiguous_bounds(), - y_coord.contiguous_bounds()) + x_bounds, y_bounds = _meshgrid(x_coord.contiguous_bounds(), + y_coord.contiguous_bounds()) grid_crs = x_coord.coord_system.as_cartopy_crs() lon_bounds, lat_bounds = _convert_latlons(grid_crs, x_bounds, y_bounds) # Add grid 'coord' element for corners, and fill with corner values. - grid.add_coords(staggerlocs=[ESMF.StaggerLoc.CORNER]) + grid.add_coords(staggerloc=ESMF.StaggerLoc.CORNER) grid_corners_x = grid.get_coords(0, ESMF.StaggerLoc.CORNER) grid_corners_x[:] = lon_bounds.T grid_corners_y = grid.get_coords(1, ESMF.StaggerLoc.CORNER) @@ -109,11 +114,11 @@ def _make_esmpy_field(x_coord, y_coord, ref_name='field', x_centres = 0.5 * (x_centres[:-1] + x_centres[1:]) y_centres = y_coord.contiguous_bounds() y_centres = 0.5 * (y_centres[:-1] + y_centres[1:]) - x_points, y_points = np.meshgrid(x_centres, y_centres) + x_points, y_points = _meshgrid(x_centres, y_centres) lon_points, lat_points = _convert_latlons(grid_crs, x_points, y_points) # Add grid 'coord' element for centres + fill with centre-points values. - grid.add_coords(staggerlocs=[ESMF.StaggerLoc.CENTER]) + grid.add_coords(staggerloc=ESMF.StaggerLoc.CENTER) grid_centers_x = grid.get_coords(0, ESMF.StaggerLoc.CENTER) grid_centers_x[:] = lon_points.T grid_centers_y = grid.get_coords(1, ESMF.StaggerLoc.CENTER) @@ -178,9 +183,12 @@ def regrid_conservative_via_esmpy(source_cube, grid_cube): To alter this, make a prior call to ESMF.Manager(). """ + # Lazy import so we can build the docs with no ESMF. + import ESMF + # Get source + target XY coordinate pairs and check they are suitable. - src_coords = i_regrid._get_xy_dim_coords(source_cube) - dst_coords = i_regrid._get_xy_dim_coords(grid_cube) + src_coords = get_xy_dim_coords(source_cube) + dst_coords = get_xy_dim_coords(grid_cube) src_cs = src_coords[0].coord_system grid_cs = dst_coords[0].coord_system if src_cs is None or grid_cs is None: @@ -215,8 +223,8 @@ def _valid_units(coord): fullcube_data = np.ma.zeros(dst_shape) # Iterate 2d slices over all possible indices of the 'other' dimensions - all_other_dims = filter(lambda i_dim: i_dim not in src_dims_xy, - xrange(source_cube.ndim)) + all_other_dims = [i_dim for i_dim in range(source_cube.ndim) + if i_dim not in src_dims_xy] all_combinations_of_other_inds = np.ndindex(*dst_shape[all_other_dims]) for other_indices in all_combinations_of_other_inds: # Construct a tuple of slices to address the 2d xy field @@ -251,7 +259,7 @@ def _valid_units(coord): unmapped_action=ESMF.UnmappedAction.IGNORE, dst_frac_field=coverage_field) regrid_method(src_field, dst_field) - data = dst_field.data + data = np.ma.masked_array(dst_field.data) # Convert destination 'coverage fraction' into a missing-data mask. # Set = wherever part of cell goes outside source grid, or overlaps a @@ -274,13 +282,12 @@ def _valid_units(coord): # NOTE: as seen in "regrid_bilinear_rectilinear_src_and_grid" # TODO: can this not also be wound into the _create_cube method ? src_cs = src_coords[0].coord_system - sample_grid_x, sample_grid_y = i_regrid._sample_grid(src_cs, - dst_coords[0], - dst_coords[1]) + sample_grid_x, sample_grid_y = RectilinearRegridder._sample_grid( + src_cs, dst_coords[0], dst_coords[1]) # Return result as a new cube based on the source. # TODO: please tidy this interface !!! - return i_regrid._create_cube( + return RectilinearRegridder._create_cube( fullcube_data, src=source_cube, x_dim=src_dims_xy[0], @@ -291,4 +298,4 @@ def _valid_units(coord): grid_y_coord=dst_coords[1], sample_grid_x=sample_grid_x, sample_grid_y=sample_grid_y, - regrid_callback=i_regrid._regrid_bilinear_array) + regrid_callback=RectilinearRegridder._regrid) diff --git a/lib/iris/experimental/representation.py b/lib/iris/experimental/representation.py new file mode 100644 index 0000000000..5adef1f06e --- /dev/null +++ b/lib/iris/experimental/representation.py @@ -0,0 +1,308 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +""" +Definitions of how Iris objects should be represented. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import re + + +class CubeRepresentation(object): + """ + Produce representations of a :class:`~iris.cube.Cube`. + + This includes: + + * ``_html_repr_``: a representation of the cube as an html object, + available in Jupyter notebooks. Specifically, this is presented as an + html table. + + """ + + _template = """ + + + {header} + {shape} + {content} +
    + """ + + def __init__(self, cube): + self.cube = cube + self.cube_id = id(self.cube) + self.cube_str = str(self.cube) + + self.str_headings = { + 'Dimension coordinates:': None, + 'Auxiliary coordinates:': None, + 'Derived coordinates:': None, + 'Scalar coordinates:': None, + 'Attributes:': None, + 'Cell methods:': None, + } + self.dim_desc_coords = ['Dimension coordinates:', + 'Auxiliary coordinates:', + 'Derived coordinates:'] + + # Important content that summarises a cube is defined here. + self.shapes = self.cube.shape + self.scalar_cube = self.shapes == () + self.ndims = self.cube.ndim + + self.name = self.cube.name().title().replace('_', ' ') + self.names = self._dim_names() + self.units = self.cube.units + + def _get_dim_names(self): + """ + Get dimension-describing coordinate names, or '--' if no coordinate] + describes the dimension. + + Note: borrows from `cube.summary`. + + """ + # Create a set to contain the axis names for each data dimension. + dim_names = list(range(len(self.cube.shape))) + + # Add the dim_coord names that participate in the associated data + # dimensions. + for dim in range(len(self.cube.shape)): + dim_coords = self.cube.coords(contains_dimension=dim, + dim_coords=True) + if dim_coords: + dim_names[dim] = dim_coords[0].name() + else: + dim_names[dim] = '--' + return dim_names + + def _dim_names(self): + if self.scalar_cube: + dim_names = ['(scalar cube)'] + else: + dim_names = self._get_dim_names() + return dim_names + + def _get_lines(self): + return self.cube_str.split('\n') + + def _get_bits(self, bits): + """ + Parse the body content (`bits`) of the cube string in preparation for + being converted into table rows. + + """ + left_indent = re.split(r'\w+', bits[1])[0] + + # Get heading indices within the printout. + start_inds = [] + for hdg in self.str_headings.keys(): + heading = '{}{}'.format(left_indent, hdg) + try: + start_ind = bits.index(heading) + except ValueError: + continue + else: + start_inds.append(start_ind) + # Mark the end of the file. + start_inds.append(0) + + # Retrieve info for each heading from the printout. + for i0, i1 in zip(start_inds[:-1], start_inds[1:]): + str_heading_name = bits[i0].strip() + if i1 != 0: + content = bits[i0 + 1: i1] + else: + content = bits[i0 + 1:] + self.str_headings[str_heading_name] = content + + def _make_header(self): + """ + Make the table header. This is similar to the summary of the cube, + but does not include dim shapes. These are included on the next table + row down, and produced with `make_shapes_row`. + + """ + # Header row. + tlc_template = \ + '{self.name} ({self.units})' + top_left_cell = tlc_template.format(self=self) + cells = ['', top_left_cell] + for dim_name in self.names: + cells.append( + '{}'.format(dim_name)) + cells.append('') + return '\n'.join(cell for cell in cells) + + def _make_shapes_row(self): + """Add a row to show data / dimensions shape.""" + title_cell = \ + 'Shape' + cells = ['', title_cell] + for shape in self.shapes: + cells.append( + '{}'.format(shape)) + cells.append('') + return '\n'.join(cell for cell in cells) + + def _make_row(self, title, body=None, col_span=0): + """ + Produce one row for the table body; i.e. + Coord namex-... + + `body` contains the content for each cell not in the left-most (title) + column. + If None, indicates this row is a title row (see below). + `title` contains the row heading. If `body` is None, indicates + that the row contains a sub-heading; + e.g. 'Dimension coordinates:'. + `col_span` indicates how many columns the string should span. + + """ + row = [''] + template = ' {content}' + if body is None: + # This is a title row. + # Strip off the trailing ':' from the title string. + title = title.strip()[:-1] + row.append( + template.format(html_cls=' class="iris-title iris-word-cell"', + content=title)) + # Add blank cells for the rest of the rows. + for _ in range(self.ndims): + row.append(template.format(html_cls=' class="iris-title"', + content='')) + else: + # This is not a title row. + # Deal with name of coord/attr etc. first. + sub_title = '\t{}'.format(title) + row.append(template.format( + html_cls=' class="iris-word-cell iris-subheading-cell"', + content=sub_title)) + # One further item or more than that? + if col_span != 0: + html_cls = ' class="{}" colspan="{}"'.format('iris-word-cell', + col_span) + row.append(template.format(html_cls=html_cls, content=body)) + else: + # "Inclusion" - `x` or `-`. + for itm in body: + row.append(template.format( + html_cls=' class="iris-inclusion-cell"', + content=itm)) + row.append('') + return row + + def _make_content(self): + elements = [] + for k, v in self.str_headings.items(): + if v is not None: + # Add the sub-heading title. + elements.extend(self._make_row(k)) + for line in v: + # Add every other row in the sub-heading. + if k in self.dim_desc_coords: + body = re.findall(r'[\w-]+', line) + title = body.pop(0) + colspan = 0 + else: + split_point = line.index(':') + title = line[:split_point].strip() + body = line[split_point + 2:].strip() + colspan = self.ndims + elements.extend( + self._make_row(title, body=body, col_span=colspan)) + return '\n'.join(element for element in elements) + + def repr_html(self): + """The `repr` interface for Jupyter.""" + # Deal with the header first. + header = self._make_header() + + # Check if we have a scalar cube. + if self.scalar_cube: + shape = '' + # We still need a single content column! + self.ndims = 1 + else: + shape = self._make_shapes_row() + + # Now deal with the rest of the content. + lines = self._get_lines() + # If we only have a single line `cube_str` we have no coords / attrs! + # We need to handle this case specially. + if len(lines) == 1: + content = '' + else: + self._get_bits(lines) + content = self._make_content() + + return self._template.format(header=header, + id=self.cube_id, + shape=shape, + content=content) diff --git a/lib/iris/experimental/stratify.py b/lib/iris/experimental/stratify.py new file mode 100644 index 0000000000..cc4e30fc71 --- /dev/null +++ b/lib/iris/experimental/stratify.py @@ -0,0 +1,205 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Routines for putting data on new strata (aka. isosurfaces), often in the +Z direction. + +""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +from functools import partial +import six + +import numpy as np +import stratify + +from iris.coords import Coord, AuxCoord, DimCoord +from iris.cube import Cube + + +def _copy_coords_without_z_dim(src, tgt, z_dim): + """ + Helper function to copy across non z-dimenson coordinates between cubes. + + Parameters + ---------- + src : :class:`~iris.cube.Cube` + Incoming cube containing the coordinates to be copied from. + + tgt : :class:`~iris.cube.Cube` + Outgoing cube for the coordinates to be copied to. + + z_dim : int + Dimension within the `src` cube that is the z-dimension. + This dimension will not be copied. For example, the incoming + z-dimension cube has model level_height, whilst the outgoing + z-dimension cube has pressure. + + """ + # Copy across non z-dimension coordinates. + for coord in src.dim_coords: + [dim] = src.coord_dims(coord) + if dim != z_dim: + tgt.add_dim_coord(coord.copy(), dim) + + for coord in src.aux_coords: + dims = src.coord_dims(coord) + if z_dim not in dims: + tgt.add_aux_coord(coord.copy(), dims) + + for coord in src.derived_coords: + dims = src.coord_dims(coord) + if z_dim not in dims: + tgt.add_aux_coord(coord.copy(), dims) + + +def relevel(cube, src_levels, tgt_levels, axis=None, interpolator=None): + """ + Interpolate the cube onto the specified target levels, given the + source levels of the cube. + + For example, suppose we have two datasets `P(i,j,k)` and `H(i,j,k)` + and we want `P(i,j,H)`. We call :func:`relevel` with `cube=P`, + `src_levels=H` and `tgt_levels` being an array of the values of `H` + we would like. + + This routine is especially useful for computing isosurfaces of phenomenon + that are generally monotonic in the direction of interpolation, such as + height/pressure or salinity/depth. + + Parameters + ---------- + cube : :class:`~iris.cube.Cube` + The phenomenon data to be re-levelled. + + src_levels : :class:`~iris.cube.Cube`, :class:`~iris.coord.Coord` or string + Describes the source levels of the `cube` that will be interpolated + over. The `src_levels` must be in the same system as the `tgt_levels`. + The dimensions of `src_levels` must be broadcastable to the dimensions + of the `cube`. + Note that, the coordinate name containing the source levels in the + `cube` may be provided. + + tgt_levels : array-like + Describes the target levels of the `cube` to be interpolated to. The + `tgt_levels` must be in the same system as the `src_levels`. The + dimensions of the `tgt_levels` must be broadcastable to the dimensions + of the `cube`, except in the nominated axis of interpolation. + + axis : int, :class:`~iris.coords.Coord` or string + The axis of interpolation. Defaults to the first dimension of the + `cube`, which is typically the z-dimension. Note that, the coordinate + name specifying the z-dimension of the `cube` may be provided. + + interpolator : callable or None + The interpolator to use when computing the interpolation. The function + will be passed the following positional arguments:: + + (tgt-data, src-data, cube-data, axis-of-interpolation) + + If the interpolator is None, :func:`stratify.interpolate` will be used + with linear interpolation and NaN extrapolation. + + An example of constructing an alternative interpolation scheme:: + + from functools import partial + interpolator = partial(stratify.interpolate, + interpolation=stratify.INTERPOLATE_NEAREST, + extrapolation=stratify.EXTRAPOLATE_LINEAR) + + """ + # Identify the z-coordinate within the phenomenon cube. + if axis is None: + axis = 0 + + if isinstance(axis, (six.string_types, Coord)): + [axis] = cube.coord_dims(axis) + + # Get the source level data. + if isinstance(src_levels, six.string_types): + src_data = cube.coord(src_levels).points + elif isinstance(src_levels, Coord): + src_data = src_levels.points + else: + src_data = src_levels.data + + # The dimensions of cube and src_data must be broadcastable. + try: + cube_data, src_data = np.broadcast_arrays(cube.data, src_data) + except ValueError: + emsg = ('Cannot broadcast the cube and src_levels with ' + 'shapes {} and {}.') + raise ValueError(emsg.format(cube.shape, src_data.shape)) + + tgt_levels = np.asarray(tgt_levels) + tgt_aux_dims = axis + if tgt_levels.ndim != 1: + # The dimensions of tgt_levels must be broadcastable to cube + # in everything but the interpolation axis - otherwise raise + # an exception. + dim_delta = cube_data.ndim - tgt_levels.ndim + # The axis is relative to the cube. Calculate the axis of + # interplation relative to the tgt_levels. + tgt_axis = axis - dim_delta + # Calculate the cube shape without the axis of interpolation. + data_shape = list(cube_data.shape) + data_shape.pop(axis) + # Calculate the tgt_levels shape without the axis of interpolation. + target_shape = list(tgt_levels.shape) + target_shape.pop(tgt_axis) + # Now ensure that the shapes are broadcastable. + try: + np.broadcast_arrays(np.empty(data_shape), np.empty(target_shape)) + except ValueError: + emsg = ('Cannot broadcast the cube and tgt_levels with ' + 'shapes {} and {}, whilst ignoring axis of interpolation.') + raise ValueError(emsg.format(cube_data.shape, tgt_levels.shape)) + # Calculate the dimensions over the cube that the tgt_levels span. + tgt_aux_dims = list(range(cube_data.ndim))[dim_delta:] + + if interpolator is None: + # Use the default stratify interpolator. + interpolator = partial(stratify.interpolate, + interpolation='linear', extrapolation='nan') + + # Now perform the interpolation. + new_data = interpolator(tgt_levels, src_data, cube_data, axis=axis) + + # Create a result cube with the correct shape and metadata. + result = Cube(new_data, **cube.copy().metadata._asdict()) + + # Copy across non z-dimension coordinates from the source cube + # to the result cube. + _copy_coords_without_z_dim(cube, result, axis) + + kwargs = dict(standard_name=src_levels.standard_name, + long_name=src_levels.long_name, + var_name=src_levels.var_name, + units=src_levels.units, + attributes=src_levels.attributes) + + # Add our new interpolated coordinate to the result cube. + try: + coord = DimCoord(tgt_levels, **kwargs) + result.add_dim_coord(coord, axis) + except ValueError: + # Attach the data to the trailing dimensions. + coord = AuxCoord(tgt_levels, **kwargs) + result.add_aux_coord(coord, tgt_aux_dims) + + return result diff --git a/lib/iris/experimental/ugrid.py b/lib/iris/experimental/ugrid.py new file mode 100644 index 0000000000..ca1dfbe09b --- /dev/null +++ b/lib/iris/experimental/ugrid.py @@ -0,0 +1,60 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +""" +Ugrid functions. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import iris + + +def ugrid(location, name): + """ + Create a cube from an unstructured grid. + + Args: + + * location: + A string whose value represents the path to a file or + URL to an OpenDAP resource conforming to the + Unstructured Grid Metadata Conventions for Scientific Datasets + https://github.com/ugrid-conventions/ugrid-conventions + + * name: + A string whose value represents a cube loading constraint of + first the standard name if found, then the long name if found, + then the variable name if found, before falling back to + the value of the default which itself defaults to "unknown" + + Returns: + An instance of :class:`iris.cube.Cube` decorated with + an instance of :class:`pyugrid.ugrid.Ugrid` + bound to an attribute of the cube called "mesh" + + """ + # Lazy import so we can build the docs with no pyugrid. + import pyugrid + + cube = iris.load_cube(location, name) + ug = pyugrid.ugrid.UGrid.from_ncfile(location) + cube.mesh = ug + cube.mesh_dimension = 1 # {0:time, 1:node} + return cube diff --git a/lib/iris/fileformats/__init__.py b/lib/iris/fileformats/__init__.py index 2462bae726..c869fe07bd 100644 --- a/lib/iris/fileformats/__init__.py +++ b/lib/iris/fileformats/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -19,27 +19,23 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + from iris.io.format_picker import (FileExtension, FormatAgent, FormatSpecification, MagicNumber, UriProtocol, LeadingLine) -import abf -import ff -import grib -import name -import netcdf -import nimrod -import pp +from . import abf +from . import um +from . import name +from . import netcdf +from . import nimrod +from . import pp __all__ = ['FORMAT_AGENT'] -def _pp_little_endian(filename, *args, **kwargs): - msg = 'PP file {!r} contains little-endian data, ' \ - 'please convert to big-endian with command line utility "bigend".' - raise ValueError(msg.format(filename)) - - FORMAT_AGENT = FormatAgent() FORMAT_AGENT.__doc__ = "The FORMAT_AGENT is responsible for identifying the " \ "format of a given URI. New formats can be added " \ @@ -53,26 +49,38 @@ def _pp_little_endian(filename, *args, **kwargs): MagicNumber(4), 0x00000100, pp.load_cubes, - priority=5)) + priority=5, + constraint_aware_handler=True)) FORMAT_AGENT.add_spec( FormatSpecification('UM Post Processing file (PP) little-endian', MagicNumber(4), 0x00010000, - _pp_little_endian, - priority=3)) + pp.load_cubes_little_endian, + priority=3, + constraint_aware_handler=True)) # # GRIB files. # +def _load_grib(*args, **kwargs): + try: + from iris_grib import load_cubes + except ImportError: + raise RuntimeError('Unable to load GRIB file - ' + '"iris_grib" package is not installed.') + + return load_cubes(*args, **kwargs) + + # NB. Because this is such a "fuzzy" check, we give this a very low # priority to avoid collateral damage from false positives. FORMAT_AGENT.add_spec( FormatSpecification('GRIB', MagicNumber(100), - lambda header_bytes: 'GRIB' in header_bytes, - grib.load_cubes, priority=1)) + lambda header_bytes: b'GRIB' in header_bytes, + _load_grib, priority=1)) # @@ -114,38 +122,43 @@ def _pp_little_endian(filename, *args, **kwargs): FORMAT_AGENT.add_spec(FormatSpecification('UM Fieldsfile (FF) pre v3.1', MagicNumber(8), 0x000000000000000F, - ff.load_cubes, - priority=3)) + um.load_cubes, + priority=3, + constraint_aware_handler=True)) FORMAT_AGENT.add_spec(FormatSpecification('UM Fieldsfile (FF) post v5.2', MagicNumber(8), 0x0000000000000014, - ff.load_cubes, - priority=4)) + um.load_cubes, + priority=4, + constraint_aware_handler=True)) FORMAT_AGENT.add_spec(FormatSpecification('UM Fieldsfile (FF) ancillary', MagicNumber(8), 0xFFFFFFFFFFFF8000, - ff.load_cubes, - priority=3)) + um.load_cubes, + priority=3, + constraint_aware_handler=True)) FORMAT_AGENT.add_spec(FormatSpecification('UM Fieldsfile (FF) converted ' 'with ieee to 32 bit', MagicNumber(4), 0x00000014, - ff.load_cubes_32bit_ieee, - priority=3)) + um.load_cubes_32bit_ieee, + priority=3, + constraint_aware_handler=True)) FORMAT_AGENT.add_spec(FormatSpecification('UM Fieldsfile (FF) ancillary ' 'converted with ieee to 32 bit', MagicNumber(4), 0xFFFF8000, - ff.load_cubes_32bit_ieee, - priority=3)) + um.load_cubes_32bit_ieee, + priority=3, + constraint_aware_handler=True)) # @@ -163,7 +176,7 @@ def _pp_little_endian(filename, *args, **kwargs): FORMAT_AGENT.add_spec( FormatSpecification('NAME III', LeadingLine(), - lambda line: line.lstrip().startswith("NAME III"), + lambda line: line.lstrip().startswith(b"NAME III"), name.load_cubes, priority=5)) diff --git a/lib/iris/fileformats/_ff.py b/lib/iris/fileformats/_ff.py new file mode 100644 index 0000000000..d2b04c88f6 --- /dev/null +++ b/lib/iris/fileformats/_ff.py @@ -0,0 +1,813 @@ +# (C) British Crown Copyright 2010 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Provides UK Met Office Fields File (FF) format specific capabilities. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import os +import warnings + +import numpy as np + +from iris.exceptions import NotYetImplementedError +from iris.fileformats._ff_cross_references import STASH_TRANS +from . import pp + + +IMDI = -32768 + +FF_HEADER_DEPTH = 256 # In words (64-bit). +DEFAULT_FF_WORD_DEPTH = 8 # In bytes. + +# UM marker to signify empty lookup table entry. +_FF_LOOKUP_TABLE_TERMINATE = -99 + +# UM FieldsFile fixed length header names and positions. +UM_FIXED_LENGTH_HEADER = [ + ('data_set_format_version', (1, )), + ('sub_model', (2, )), + ('vert_coord_type', (3, )), + ('horiz_grid_type', (4, )), + ('dataset_type', (5, )), + ('run_identifier', (6, )), + ('experiment_number', (7, )), + ('calendar', (8, )), + ('grid_staggering', (9, )), + ('time_type', (10, )), + ('projection_number', (11, )), + ('model_version', (12, )), + ('obs_file_type', (14, )), + ('last_fieldop_type', (15, )), + ('first_validity_time', (21, 22, 23, 24, 25, 26, 27, )), + ('last_validity_time', (28, 29, 30, 31, 32, 33, 34, )), + ('misc_validity_time', (35, 36, 37, 38, 39, 40, 41, )), + ('integer_constants', (100, 101, )), + ('real_constants', (105, 106, )), + ('level_dependent_constants', (110, 111, 112, )), + ('row_dependent_constants', (115, 116, 117, )), + ('column_dependent_constants', (120, 121, 122, )), + ('fields_of_constants', (125, 126, 127, )), + ('extra_constants', (130, 131, )), + ('temp_historyfile', (135, 136, )), + ('compressed_field_index1', (140, 141, )), + ('compressed_field_index2', (142, 143, )), + ('compressed_field_index3', (144, 145, )), + ('lookup_table', (150, 151, 152, )), + ('total_prognostic_fields', (153, )), + ('data', (160, 161, 162, )), ] + +# Offset value to convert from UM_FIXED_LENGTH_HEADER positions to +# FF_HEADER offsets. +UM_TO_FF_HEADER_OFFSET = 1 +# Offset the UM_FIXED_LENGTH_HEADER positions to FF_HEADER offsets. +FF_HEADER = [ + (name, tuple(position - UM_TO_FF_HEADER_OFFSET for position in positions)) + for name, positions in UM_FIXED_LENGTH_HEADER] + +# UM FieldsFile fixed length header pointer names. +_FF_HEADER_POINTERS = [ + 'integer_constants', + 'real_constants', + 'level_dependent_constants', + 'row_dependent_constants', + 'column_dependent_constants', + 'fields_of_constants', + 'extra_constants', + 'temp_historyfile', + 'compressed_field_index1', + 'compressed_field_index2', + 'compressed_field_index3', + 'lookup_table', + 'data', ] + +_LBUSER_DTYPE_LOOKUP = {1: '>f{word_depth}', + 2: '>i{word_depth}', + 3: '>i{word_depth}', + 'default': '>f{word_depth}', } + +#: Codes used in STASH_GRID which indicate the x coordinate is on the +#: edge of the cell. +X_COORD_U_GRID = (11, 18, 27) + +#: Codes used in STASH_GRID which indicate the y coordinate is on the +#: edge of the cell. +Y_COORD_V_GRID = (11, 19, 28) + +#: Grid codes found in the STASH master which are currently known to be +#: handled correctly. A warning is issued if a grid is found which is not +#: handled. +HANDLED_GRIDS = (1, 2, 3, 4, 5, 21, 26, 29) + X_COORD_U_GRID + Y_COORD_V_GRID + +# REAL constants header names as described by UM documentation paper F3. +# NB. These are zero-based indices as opposed to the one-based indices +# used in F3. +REAL_EW_SPACING = 0 +REAL_NS_SPACING = 1 +REAL_FIRST_LAT = 2 +REAL_FIRST_LON = 3 +REAL_POLE_LAT = 4 +REAL_POLE_LON = 5 + + +class Grid(object): + """ + An abstract class representing the default/file-level grid + definition for a FieldsFile. + + """ + def __init__(self, column_dependent_constants, row_dependent_constants, + real_constants, horiz_grid_type): + """ + Create a Grid from the relevant sections of the FFHeader. + + Args: + + * column_dependent_constants (numpy.ndarray): + The `column_dependent_constants` from a FFHeader. + + * row_dependent_constants (numpy.ndarray): + The `row_dependent_constants` from a FFHeader. + + * real_constants (numpy.ndarray): + The `real_constants` from a FFHeader. + + * horiz_grid_type (integer): + `horiz_grid_type` from a FFHeader. + + """ + self.column_dependent_constants = column_dependent_constants + self.row_dependent_constants = row_dependent_constants + self.ew_spacing = real_constants[REAL_EW_SPACING] + self.ns_spacing = real_constants[REAL_NS_SPACING] + self.first_lat = real_constants[REAL_FIRST_LAT] + self.first_lon = real_constants[REAL_FIRST_LON] + self.pole_lat = real_constants[REAL_POLE_LAT] + self.pole_lon = real_constants[REAL_POLE_LON] + self.horiz_grid_type = horiz_grid_type + + def _x_vectors(self, subgrid): + # Abstract method to return the X vector for the given sub-grid. + raise NotImplementedError() + + def _y_vectors(self, subgrid): + # Abstract method to return the X vector for the given sub-grid. + raise NotImplementedError() + + def regular_x(self, subgrid): + # Abstract method to return BZX, BDX for the given sub-grid. + raise NotImplementedError() + + def regular_y(self, subgrid): + # Abstract method to return BZY, BDY for the given sub-grid. + raise NotImplementedError() + + def vectors(self, subgrid): + """ + Return the X and Y coordinate vectors for the given sub-grid of + this grid. + + Args: + + * subgrid (integer): + A "grid type code" as described in UM documentation paper C4. + + Returns: + A 2-tuple of X-vector, Y-vector. + + """ + x_p, x_u = self._x_vectors() + y_p, y_v = self._y_vectors() + x = x_p + y = y_p + if subgrid in X_COORD_U_GRID: + x = x_u + if subgrid in Y_COORD_V_GRID: + y = y_v + return x, y + + +class ArakawaC(Grid): + """ + An abstract class representing an Arakawa C-grid. + + """ + def _x_vectors(self): + x_p, x_u = None, None + if self.column_dependent_constants is not None: + x_p = self.column_dependent_constants[:, 0] + if self.column_dependent_constants.shape[1] == 2: + # Wrap around for global field + if self.horiz_grid_type == 0: + x_u = self.column_dependent_constants[:-1, 1] + else: + x_u = self.column_dependent_constants[:, 1] + return x_p, x_u + + def regular_x(self, subgrid): + """ + Return the "zeroth" value and step for the X coordinate on the + given sub-grid of this grid. + + Args: + + * subgrid (integer): + A "grid type code" as described in UM documentation paper C4. + + Returns: + A 2-tuple of BZX, BDX. + + """ + bdx = self.ew_spacing + bzx = self.first_lon - bdx + if subgrid in X_COORD_U_GRID: + bzx += 0.5 * bdx + return bzx, bdx + + def regular_y(self, subgrid): + """ + Return the "zeroth" value and step for the Y coordinate on the + given sub-grid of this grid. + + Args: + + * subgrid (integer): + A "grid type code" as described in UM documentation paper C4. + + Returns: + A 2-tuple of BZY, BDY. + + """ + bdy = self.ns_spacing + bzy = self.first_lat - bdy + if subgrid in Y_COORD_V_GRID: + bzy += self._v_offset * bdy + return bzy, bdy + + +class NewDynamics(ArakawaC): + """ + An Arakawa C-grid as used by UM New Dynamics. + + The theta and u points are at the poles. + + """ + + _v_offset = 0.5 + + def _y_vectors(self): + y_p, y_v = None, None + if self.row_dependent_constants is not None: + y_p = self.row_dependent_constants[:, 0] + if self.row_dependent_constants.shape[1] == 2: + y_v = self.row_dependent_constants[:-1, 1] + return y_p, y_v + + +class ENDGame(ArakawaC): + """ + An Arakawa C-grid as used by UM ENDGame. + + The v points are at the poles. + + """ + + _v_offset = -0.5 + + def _y_vectors(self): + y_p, y_v = None, None + if self.row_dependent_constants is not None: + y_p = self.row_dependent_constants[:-1, 0] + if self.row_dependent_constants.shape[1] == 2: + y_v = self.row_dependent_constants[:, 1] + return y_p, y_v + + +class FFHeader(object): + """ + A class to represent the FIXED_LENGTH_HEADER section of a FieldsFile. + + """ + + GRID_STAGGERING_CLASS = {3: NewDynamics, 6: ENDGame} + + def __init__(self, filename, word_depth=DEFAULT_FF_WORD_DEPTH): + """ + Create a FieldsFile header instance by reading the + FIXED_LENGTH_HEADER section of the FieldsFile, making the names + defined in FF_HEADER available as attributes of a FFHeader instance. + + Args: + + * filename (string): + Specify the name of the FieldsFile. + + Returns: + FFHeader object. + + """ + + #: File name of the FieldsFile. + self.ff_filename = filename + self._word_depth = word_depth + + # Read the FF header data + with open(filename, 'rb') as ff_file: + # typically 64-bit words (aka. int64 or ">i8") + header_data = np.fromfile(ff_file, + dtype='>i{0}'.format(word_depth), + count=FF_HEADER_DEPTH) + header_data = tuple(header_data) + # Create FF instance attributes + for name, offsets in FF_HEADER: + if len(offsets) == 1: + value = header_data[offsets[0]] + else: + value = header_data[offsets[0]:offsets[-1] + 1] + setattr(self, name, value) + + # Turn the pointer values into real arrays. + for elem in _FF_HEADER_POINTERS: + if elem not in ['data', 'lookup_table']: + if self._attribute_is_pointer_and_needs_addressing(elem): + addr = getattr(self, elem) + ff_file.seek((addr[0] - 1) * word_depth, os.SEEK_SET) + if len(addr) == 2: + if elem == 'integer_constants': + res = np.fromfile( + ff_file, + dtype='>i{0}'.format(word_depth), + count=addr[1]) + else: + res = np.fromfile( + ff_file, + dtype='>f{0}'.format(word_depth), + count=addr[1]) + elif len(addr) == 3: + res = np.fromfile(ff_file, + dtype='>f{0}'.format(word_depth), + count=addr[1]*addr[2]) + res = res.reshape((addr[1], addr[2]), order='F') + else: + raise ValueError('ff header element {} is not' + 'handled correctly'.format(elem)) + else: + res = None + setattr(self, elem, res) + + def __str__(self): + attributes = [] + for name, _ in FF_HEADER: + attributes.append(' {}: {}'.format(name, getattr(self, name))) + return 'FF Header:\n' + '\n'.join(attributes) + + def __repr__(self): + return '{}({!r})'.format(type(self).__name__, self.ff_filename) + + def _attribute_is_pointer_and_needs_addressing(self, name): + if name in _FF_HEADER_POINTERS: + attr = getattr(self, name) + + # Check that we haven't already addressed this pointer, + # that the pointer is actually referenceable (i.e. >0) + # and that the attribute is not marked as missing. + is_referenceable = (isinstance(attr, tuple) and + attr[0] > 0 and attr[0] != IMDI) + else: + msg = '{!r} object does not have pointer attribute {!r}' + raise AttributeError(msg.format(self.__class__.__name__, name)) + return is_referenceable + + def shape(self, name): + """ + Return the dimension shape of the FieldsFile FIXED_LENGTH_HEADER + pointer attribute. + + Args: + + * name (string): + Specify the name of the FIXED_LENGTH_HEADER attribute. + + Returns: + Dimension tuple. + + """ + + if name in _FF_HEADER_POINTERS: + value = getattr(self, name)[1:] + else: + msg = '{!r} object does not have pointer address {!r}' + raise AttributeError(msg.format(self.__class_.__name__, name)) + return value + + def grid(self): + """Return the Grid definition for the FieldsFile.""" + grid_class = self.GRID_STAGGERING_CLASS.get(self.grid_staggering) + if grid_class is None: + grid_class = NewDynamics + warnings.warn( + 'Staggered grid type: {} not currently interpreted, assuming ' + 'standard C-grid'.format(self.grid_staggering)) + grid = grid_class(self.column_dependent_constants, + self.row_dependent_constants, + self.real_constants, self.horiz_grid_type) + return grid + + +class FF2PP(object): + """ + A class to extract the individual PPFields from within a FieldsFile. + + """ + + def __init__(self, filename, read_data=False, + word_depth=DEFAULT_FF_WORD_DEPTH): + """ + Create a FieldsFile to Post Process instance that returns a generator + of PPFields contained within the FieldsFile. + + Args: + + * filename (string): + Specify the name of the FieldsFile. + + Kwargs: + + * read_data (boolean): + Specify whether to read the associated PPField data within + the FieldsFile. Default value is False. + + Returns: + PPField generator. + + For example:: + + >>> for field in ff.FF2PP(filename): + ... print(field) + + """ + + self._ff_header = FFHeader(filename, word_depth=word_depth) + self._word_depth = word_depth + self._filename = filename + self._read_data = read_data + + def _payload(self, field): + """Calculate the payload data depth (in bytes) and type.""" + lbpack_n1 = field.raw_lbpack % 10 + if lbpack_n1 == 0: + word_depth = self._word_depth + # Data payload is not packed. + data_words = field.lblrec - field.lbext + # Determine PP field 64-bit payload datatype. + lookup = _LBUSER_DTYPE_LOOKUP + dtype_template = lookup.get(field.lbuser[0], lookup['default']) + dtype_name = dtype_template.format(word_depth=self._word_depth) + data_type = np.dtype(dtype_name) + else: + word_depth = pp.PP_WORD_DEPTH + # Data payload is packed. + if lbpack_n1 == 1: + # Data packed using WGDOS archive method. + data_words = field.lbnrec * 2 + elif lbpack_n1 == 2: + # Data packed using CRAY 32-bit method. + data_words = field.lblrec - field.lbext + else: + msg = 'PP fields with LBPACK of {} are not supported.' + raise NotYetImplementedError(msg.format(field.raw_lbpack)) + + # Determine PP field payload datatype. + lookup = pp.LBUSER_DTYPE_LOOKUP + data_type = lookup.get(field.lbuser[0], lookup['default']) + + if field.boundary_packing is not None: + if lbpack_n1 not in (0, 2): + # Can't handle the usual packing methods with LBC data. + raise ValueError( + 'LBC data has LBPACK = {:d}, but packed LBC data is not ' + 'supported.'.format(field.raw_lbpack)) + # Adjust to packed data size, for LBC data. + # NOTE: logic duplicates that in pp._data_bytes_to_shaped_array. + pack_dims = field.boundary_packing + boundary_height = pack_dims.y_halo + pack_dims.rim_width + boundary_width = pack_dims.x_halo + pack_dims.rim_width + y_height, x_width = field.lbrow, field.lbnpt + mid_height = y_height - 2 * boundary_height + data_words = (boundary_height * x_width * 2 + + boundary_width * mid_height * 2) + + data_depth = data_words * word_depth + return data_depth, data_type + + def _det_border(self, field_dim, halo_dim): + # Update field coordinates for a variable resolution LBC file where + # the resolution of the very edge (within the rim width) is assumed to + # be same as the halo. + def range_order(range1, range2, resolution): + # Handles whether increasing/decreasing ranges. + if np.sign(resolution) > 0: + lower = range1 + upper = range2 + else: + upper = range1 + lower = range2 + return lower, upper + + # Ensure that the resolution is the same on both edges. + res_low = field_dim[1] - field_dim[0] + res_high = field_dim[-1] - field_dim[-2] + if not np.allclose(res_low, res_high): + msg = ('The x or y coordinates of your boundary condition field ' + 'may be incorrect, not having taken into account the ' + 'boundary size.') + warnings.warn(msg) + else: + range2 = field_dim[0] - res_low + range1 = field_dim[0] - halo_dim * res_low + lower, upper = range_order(range1, range2, res_low) + extra_before = np.linspace(lower, upper, halo_dim) + + range1 = field_dim[-1] + res_high + range2 = field_dim[-1] + halo_dim * res_high + lower, upper = range_order(range1, range2, res_high) + extra_after = np.linspace(lower, upper, halo_dim) + + field_dim = np.concatenate([extra_before, field_dim, extra_after]) + return field_dim + + def _adjust_field_for_lbc(self, field): + """ + Make an LBC field look like a 'normal' field for rules processing. + + """ + # Set LBTIM to indicate the specific time encoding for LBCs, + # i.e. t1=forecast, t2=reference + lbtim_default = 11 + if field.lbtim not in (0, lbtim_default): + raise ValueError('LBC field has LBTIM of {:d}, expected only ' + '0 or {:d}.'.format(field.lbtim, lbtim_default)) + field.lbtim = lbtim_default + + # Set LBVC to indicate the specific height encoding for LBCs, + # i.e. hybrid height layers. + lbvc_default = 65 + if field.lbvc not in (0, lbvc_default): + raise ValueError('LBC field has LBVC of {:d}, expected only ' + '0 or {:d}.'.format(field.lbvc, lbvc_default)) + field.lbvc = lbvc_default + # Specifying a vertical encoding scheme means a usable vertical + # coordinate can be produced, because we also record the level + # number in each result field: Thus they are located, and can + # be stacked, in a vertical dimension. + # See per-layer loop (below). + + # Calculate field packing details. + name_mapping = dict(rim_width=slice(4, 6), y_halo=slice(2, 4), + x_halo=slice(0, 2)) + boundary_packing = pp.SplittableInt(field.lbuser[2], name_mapping) + # Store packing on the field, which affects how it gets the data. + field.boundary_packing = boundary_packing + # Fix the lbrow and lbnpt to be the actual size of the data + # array, since the field is no longer a "boundary" fields file + # field. + # Note: The documentation states that lbrow (y) doesn't + # contain the halo rows, but no such comment exists at UM v8.5 + # for lbnpt (x). Experimentation has shown that lbnpt also + # excludes the halo size. + field.lbrow += 2 * boundary_packing.y_halo + field.lbnpt += 2 * boundary_packing.x_halo + + # Update the x and y coordinates for this field. Note: it may + # be that this needs to update x and y also, but that is yet + # to be confirmed. + if (field.bdx in (0, field.bmdi) or + field.bdy in (0, field.bmdi)): + field.x = self._det_border(field.x, boundary_packing.x_halo) + field.y = self._det_border(field.y, boundary_packing.y_halo) + else: + if field.bdy < 0: + warnings.warn('The LBC has a bdy less than 0. No ' + 'case has previously been seen of ' + 'this, and the decompression may be ' + 'erroneous.') + field.bzx -= field.bdx * boundary_packing.x_halo + field.bzy -= field.bdy * boundary_packing.y_halo + + def _fields_over_all_levels(self, field): + """ + Replicate the field over all model levels, setting LBLEV for each. + + This is appropriate for LBC data. + Yields an iterator producing a sequence of distinct field objects. + + """ + n_all_levels = self._ff_header.level_dependent_constants.shape[0] + levels_count = field.lbhem - 100 + if levels_count < 1: + raise ValueError( + 'LBC field has LBHEM of {:d}, but this should be (100 ' + '+ levels-per-field-type), hence >= 101.'.format(field.lbhem)) + if levels_count > n_all_levels: + raise ValueError( + 'LBC field has LBHEM of (100 + levels-per-field-type) ' + '= {:d}, but this is more than the total number of levels ' + 'in the file = {:d}).'.format(field.lbhem, n_all_levels)) + + for i_model_level in range(levels_count): + # Make subsequent fields alike, but distinct. + if i_model_level > 0: + field = field.copy() + # Provide the correct "model level" value. + field.lblev = i_model_level + # TODO: as LBC lookup headers cover multiple layers, they + # contain no per-layer height values, which are all 0. + # So the field's "height" coordinate will be useless. + # It should be possible to fix this here, by calculating + # per-layer Z and C values from the file header, and + # setting blev/brlev/brsvd1 and bhlev/bhrlev/brsvd2 here, + # but we don't yet do this. + + yield field + + def _extract_field(self): + # FF table pointer initialisation based on FF LOOKUP table + # configuration. + + lookup_table = self._ff_header.lookup_table + table_index, table_entry_depth, table_count = lookup_table + table_offset = (table_index - 1) * self._word_depth # in bytes + table_entry_depth = table_entry_depth * self._word_depth # in bytes + # Open the FF for processing. + with open(self._ff_header.ff_filename, 'rb') as ff_file: + ff_file_seek = ff_file.seek + + is_boundary_packed = self._ff_header.dataset_type == 5 + + grid = self._ff_header.grid() + + # Process each FF LOOKUP table entry. + while table_count: + table_count -= 1 + # Move file pointer to the start of the current FF LOOKUP + # table entry. + ff_file_seek(table_offset, os.SEEK_SET) + + # Read the current PP header entry from the FF LOOKUP table. + header_longs = np.fromfile( + ff_file, dtype='>i{0}'.format(self._word_depth), + count=pp.NUM_LONG_HEADERS) + # Check whether the current FF LOOKUP table entry is valid. + if header_longs[0] == _FF_LOOKUP_TABLE_TERMINATE: + # There are no more FF LOOKUP table entries to read. + break + header_floats = np.fromfile( + ff_file, dtype='>f{0}'.format(self._word_depth), + count=pp.NUM_FLOAT_HEADERS) + header = tuple(header_longs) + tuple(header_floats) + + # Calculate next FF LOOKUP table entry. + table_offset += table_entry_depth + + # Construct a PPField object and populate using the header_data + # read from the current FF LOOKUP table. + # (The PPField sub-class will depend on the header release + # number.) + # (Some Fields File fields are UM specific scratch spaces, with + # no header release number, these will throw an exception from + # the PP module and are skipped to enable reading of the file. + try: + field = pp.make_pp_field(header) + + # Fast stash look-up. + stash_s = field.lbuser[3] // 1000 + stash_i = field.lbuser[3] % 1000 + stash = 'm{:02}s{:02}i{:03}'.format(field.lbuser[6], + stash_s, stash_i) + stash_entry = STASH_TRANS.get(stash, None) + if stash_entry is None: + subgrid = None + else: + subgrid = stash_entry.grid_code + if subgrid not in HANDLED_GRIDS: + warnings.warn('The stash code {} is on a grid {} ' + 'which has not been explicitly ' + 'handled by the fieldsfile loader.' + ' Assuming the data is on a P grid' + '.'.format(stash, subgrid)) + + field.x, field.y = grid.vectors(subgrid) + + # Use the per-file grid if no per-field metadata is + # available. + no_x = field.bzx in (0, field.bmdi) and field.x is None + no_y = field.bzy in (0, field.bmdi) and field.y is None + if no_x and no_y: + if subgrid is None: + msg = ('The STASH code {0} was not found in the ' + 'STASH to grid type mapping. Picking the P ' + 'position as the cell type'.format(stash)) + warnings.warn(msg) + field.bzx, field.bdx = grid.regular_x(subgrid) + field.bzy, field.bdy = grid.regular_y(subgrid) + field.bplat = grid.pole_lat + field.bplon = grid.pole_lon + elif no_x or no_y: + warnings.warn( + 'Partially missing X or Y coordinate values.') + + # Check for LBC fields. + is_boundary_packed = self._ff_header.dataset_type == 5 + if is_boundary_packed: + # Apply adjustments specific to LBC data. + self._adjust_field_for_lbc(field) + + # Calculate start address of the associated PP header data. + data_offset = field.lbegin * self._word_depth + # Determine PP field payload depth and type. + data_depth, data_type = self._payload(field) + + # Produce (yield) output fields. + if is_boundary_packed: + fields = self._fields_over_all_levels(field) + else: + fields = [field] + for result_field in fields: + # Add a field data element. + if self._read_data: + # Read the actual bytes. This can then be converted + # to a numpy array at a higher level. + ff_file_seek(data_offset, os.SEEK_SET) + result_field.data = pp.LoadedArrayBytes( + ff_file.read(data_depth), data_type) + else: + # Provide enough context to read the data bytes + # later. + result_field.data = (self._filename, data_offset, + data_depth, data_type) + + data_offset += data_depth + + yield result_field + except ValueError as valerr: + msg = ('Input field skipped as PPField creation failed :' + ' error = {!r}') + warnings.warn(msg.format(str(valerr))) + + def __iter__(self): + return pp._interpret_fields(self._extract_field()) + + +def load_cubes(filenames, callback, constraints=None): + """ + Loads cubes from a list of fields files filenames. + + Args: + + * filenames - list of fields files filenames to load + + Kwargs: + + * callback - a function which can be passed on to + :func:`iris.io.run_callback` + + .. note:: + + The resultant cubes may not be in the order that they are in the + file (order is not preserved when there is a field with + orography references). + + """ + return pp._load_cubes_variable_loader(filenames, callback, FF2PP, + constraints=constraints) + + +def load_cubes_32bit_ieee(filenames, callback, constraints=None): + """ + Loads cubes from a list of 32bit ieee converted fieldsfiles filenames. + + .. seealso:: + + :func:`load_cubes` for keyword details + + """ + return pp._load_cubes_variable_loader(filenames, callback, FF2PP, + {'word_depth': 4}, + constraints=constraints) diff --git a/lib/iris/fileformats/_ff_cross_references.py b/lib/iris/fileformats/_ff_cross_references.py index 9080df4653..dd451a97b9 100644 --- a/lib/iris/fileformats/_ff_cross_references.py +++ b/lib/iris/fileformats/_ff_cross_references.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -17,5155 +17,5481 @@ # # DO NOT EDIT: AUTO-GENERATED """ -Auto-generated from SciTools/iris-code-generators:tools/gen_stash_refs.py +Auto-generated from iris/tools/gen_stash_refs.py Relates grid code and field code to the stash code. """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + from collections import namedtuple -Stash = namedtuple('Stash', 'grid_code field_code') +Stash = namedtuple('Stash', 'grid_code field_code pseudo_level_type') STASH_TRANS = { - "m01s00i001": Stash(1, 8), - "m01s00i002": Stash(18, 56), - "m01s00i003": Stash(19, 57), - "m01s00i004": Stash(1, 19), - "m01s00i005": Stash(21, 0), - "m01s00i006": Stash(21, 0), - "m01s00i007": Stash(1, 1), - "m01s00i008": Stash(21, 2011), - "m01s00i009": Stash(21, 122), - "m01s00i010": Stash(1, 95), - "m01s00i011": Stash(1, 95), - "m01s00i012": Stash(1, 78), - "m01s00i013": Stash(1, 34), - "m01s00i014": Stash(1, 222), - "m01s00i015": Stash(1, 223), - "m01s00i016": Stash(1, 219), - "m01s00i017": Stash(21, 174), - "m01s00i018": Stash(21, 175), - "m01s00i020": Stash(21, 23), - "m01s00i021": Stash(1, 1100), - "m01s00i022": Stash(21, 271), - "m01s00i023": Stash(1, 93), - "m01s00i024": Stash(1, 16), - "m01s00i025": Stash(1, 5), - "m01s00i026": Stash(1, 324), - "m01s00i027": Stash(3, 0), - "m01s00i028": Stash(18, 701), - "m01s00i029": Stash(19, 702), - "m01s00i030": Stash(1, 395), - "m01s00i031": Stash(3, 37), - "m01s00i032": Stash(3, 687), - "m01s00i033": Stash(1, 1), - "m01s00i034": Stash(21, 150), - "m01s00i035": Stash(21, 152), - "m01s00i036": Stash(21, 153), - "m01s00i037": Stash(21, 154), - "m01s00i038": Stash(3, 0), - "m01s00i039": Stash(1, 0), - "m01s00i040": Stash(21, 329), - "m01s00i041": Stash(21, 330), - "m01s00i042": Stash(21, 331), - "m01s00i043": Stash(21, 332), - "m01s00i044": Stash(21, 333), - "m01s00i045": Stash(21, 334), - "m01s00i046": Stash(21, 335), - "m01s00i047": Stash(21, 336), - "m01s00i048": Stash(21, 342), - "m01s00i049": Stash(3, 209), - "m01s00i050": Stash(21, 326), - "m01s00i051": Stash(21, 321), - "m01s00i052": Stash(21, 322), - "m01s00i053": Stash(21, 328), - "m01s00i054": Stash(21, 323), - "m01s00i055": Stash(21, 325), - "m01s00i056": Stash(21, 327), - "m01s00i057": Stash(1, 287), - "m01s00i058": Stash(1, 569), - "m01s00i059": Stash(1, 570), - "m01s00i060": Stash(22, 453), - "m01s00i061": Stash(1, 501), - "m01s00i062": Stash(1, 502), - "m01s00i063": Stash(1, 503), - "m01s00i064": Stash(1, 504), - "m01s00i065": Stash(1, 505), - "m01s00i066": Stash(1, 506), - "m01s00i067": Stash(1, 507), - "m01s00i068": Stash(1, 508), - "m01s00i069": Stash(1, 509), - "m01s00i070": Stash(1, 2038), - "m01s00i071": Stash(1, 2039), - "m01s00i072": Stash(1, 2040), - "m01s00i073": Stash(1, 2041), - "m01s00i074": Stash(1, 2056), - "m01s00i075": Stash(1, 515), - "m01s00i076": Stash(1, 516), - "m01s00i077": Stash(1, 517), - "m01s00i078": Stash(1, 518), - "m01s00i079": Stash(1, 519), - "m01s00i080": Stash(1, 520), - "m01s00i081": Stash(1, 521), - "m01s00i082": Stash(1, 522), - "m01s00i083": Stash(1, 523), - "m01s00i084": Stash(1, 524), - "m01s00i085": Stash(1, 525), - "m01s00i086": Stash(1, 526), - "m01s00i087": Stash(1, 527), - "m01s00i088": Stash(1, 528), - "m01s00i089": Stash(1, 529), - "m01s00i090": Stash(1, 286), - "m01s00i093": Stash(21, 0), - "m01s00i095": Stash(3, 93), - "m01s00i096": Stash(25, 0), - "m01s00i097": Stash(25, 0), - "m01s00i098": Stash(1, 0), - "m01s00i099": Stash(1, 1709), - "m01s00i100": Stash(1, 1711), - "m01s00i101": Stash(1, 1374), - "m01s00i102": Stash(1, 1373), - "m01s00i103": Stash(1, 1370), - "m01s00i104": Stash(1, 1371), - "m01s00i105": Stash(1, 1372), - "m01s00i106": Stash(1, 581), - "m01s00i107": Stash(1, 1379), - "m01s00i108": Stash(1, 1491), - "m01s00i109": Stash(1, 1492), - "m01s00i110": Stash(1, 1493), - "m01s00i111": Stash(1, 1683), - "m01s00i112": Stash(1, 1684), - "m01s00i113": Stash(1, 1685), - "m01s00i114": Stash(1, 1491), - "m01s00i115": Stash(1, 1491), - "m01s00i116": Stash(1, 1491), - "m01s00i117": Stash(1, 1491), - "m01s00i118": Stash(1, 1491), - "m01s00i121": Stash(1, 569), - "m01s00i122": Stash(1, 580), - "m01s00i123": Stash(1, 600), - "m01s00i124": Stash(1, 581), - "m01s00i125": Stash(1, 60), - "m01s00i126": Stash(1, 569), - "m01s00i127": Stash(1, 572), - "m01s00i128": Stash(1, 573), - "m01s00i129": Stash(1, 573), - "m01s00i130": Stash(1, 574), - "m01s00i131": Stash(1, 574), - "m01s00i132": Stash(1, 575), - "m01s00i133": Stash(1, 1558), - "m01s00i134": Stash(1, 573), - "m01s00i135": Stash(1, 573), - "m01s00i150": Stash(1, 42), - "m01s00i151": Stash(23, 1905), - "m01s00i152": Stash(23, 1906), - "m01s00i153": Stash(23, 1902), - "m01s00i154": Stash(19, 57), - "m01s00i155": Stash(21, 1907), - "m01s00i156": Stash(21, 1908), - "m01s00i157": Stash(1, 1909), - "m01s00i160": Stash(1, 1910), - "m01s00i161": Stash(1, 1911), - "m01s00i162": Stash(1, 1912), - "m01s00i163": Stash(1, 1913), - "m01s00i164": Stash(1, 1914), - "m01s00i165": Stash(1, 1915), - "m01s00i166": Stash(1, 1916), - "m01s00i167": Stash(1, 1917), - "m01s00i168": Stash(1, 1918), - "m01s00i169": Stash(1, 1919), - "m01s00i171": Stash(1, 186), - "m01s00i172": Stash(1, 186), - "m01s00i173": Stash(1, 187), - "m01s00i174": Stash(1, 187), - "m01s00i176": Stash(18, 61), - "m01s00i177": Stash(19, 62), - "m01s00i178": Stash(1, 182), - "m01s00i179": Stash(1, 178), - "m01s00i180": Stash(1, 107), - "m01s00i181": Stash(1, 285), - "m01s00i184": Stash(1, 1414), - "m01s00i185": Stash(1, 1415), - "m01s00i186": Stash(1, 99), - "m01s00i187": Stash(1, 118), - "m01s00i188": Stash(1, 98), - "m01s00i189": Stash(1, 119), - "m01s00i192": Stash(1, 112), - "m01s00i201": Stash(1, 8), - "m01s00i202": Stash(18, 56), - "m01s00i203": Stash(19, 57), - "m01s00i204": Stash(1, 19), - "m01s00i205": Stash(1, 36), - "m01s00i207": Stash(21, 1381), - "m01s00i208": Stash(21, 1382), - "m01s00i209": Stash(21, 1383), - "m01s00i211": Stash(1, 218), - "m01s00i212": Stash(1, 1101), - "m01s00i213": Stash(21, 1384), - "m01s00i214": Stash(21, 1385), - "m01s00i215": Stash(21, 1386), - "m01s00i216": Stash(21, 1391), - "m01s00i217": Stash(21, 1392), - "m01s00i218": Stash(21, 1393), - "m01s00i219": Stash(21, 1394), - "m01s00i220": Stash(21, 1395), - "m01s00i221": Stash(1, 1396), - "m01s00i222": Stash(1, 259), - "m01s00i223": Stash(21, 1397), - "m01s00i224": Stash(21, 1398), - "m01s00i225": Stash(21, 1500), - "m01s00i226": Stash(21, 1501), - "m01s00i227": Stash(21, 1502), - "m01s00i228": Stash(21, 1503), - "m01s00i229": Stash(21, 1504), - "m01s00i230": Stash(21, 1505), - "m01s00i231": Stash(21, 1507), - "m01s00i232": Stash(21, 1508), - "m01s00i233": Stash(21, 1510), - "m01s00i234": Stash(21, 1511), - "m01s00i235": Stash(1, 113), - "m01s00i236": Stash(21, 1579), - "m01s00i237": Stash(21, 1580), - "m01s00i238": Stash(1, 1581), - "m01s00i239": Stash(1, 1582), - "m01s00i240": Stash(21, 1583), - "m01s00i241": Stash(21, 93), - "m01s00i242": Stash(21, 93), - "m01s00i250": Stash(1, 1560), - "m01s00i251": Stash(1, 1561), - "m01s00i252": Stash(1, 1564), - "m01s00i253": Stash(1, 0), - "m01s00i254": Stash(1, 79), - "m01s00i255": Stash(1, 7), - "m01s00i256": Stash(18, 56), - "m01s00i257": Stash(19, 57), - "m01s00i258": Stash(1, 42), - "m01s00i259": Stash(1, 0), - "m01s00i260": Stash(1, 0), - "m01s00i261": Stash(1, 0), - "m01s00i262": Stash(1, 0), - "m01s00i263": Stash(1, 0), - "m01s00i264": Stash(1, 0), - "m01s00i265": Stash(1, 1729), - "m01s00i266": Stash(1, 220), - "m01s00i267": Stash(1, 1425), - "m01s00i268": Stash(1, 1426), - "m01s00i269": Stash(1, 701), - "m01s00i270": Stash(1, 702), - "m01s00i271": Stash(1, 1689), - "m01s00i272": Stash(1, 1681), - "m01s00i273": Stash(1, 1921), - "m01s00i274": Stash(21, 900), - "m01s00i275": Stash(21, 900), - "m01s00i276": Stash(21, 900), - "m01s00i277": Stash(21, 900), - "m01s00i278": Stash(21, 900), - "m01s00i279": Stash(21, 900), - "m01s00i280": Stash(21, 900), - "m01s00i281": Stash(21, 900), - "m01s00i282": Stash(21, 900), - "m01s00i283": Stash(21, 900), - "m01s00i284": Stash(21, 900), - "m01s00i285": Stash(21, 900), - "m01s00i286": Stash(21, 1394), - "m01s00i287": Stash(21, 1513), - "m01s00i288": Stash(21, 1513), - "m01s00i289": Stash(21, 1513), - "m01s00i290": Stash(1, 1907), - "m01s00i291": Stash(21, 0), - "m01s00i292": Stash(21, 0), - "m01s00i293": Stash(21, 0), - "m01s00i294": Stash(21, 0), - "m01s00i295": Stash(21, 0), - "m01s00i296": Stash(21, 0), - "m01s00i297": Stash(21, 0), - "m01s00i298": Stash(21, 0), - "m01s00i301": Stash(1, 0), - "m01s00i302": Stash(1, 0), - "m01s00i303": Stash(1, 0), - "m01s00i304": Stash(1, 0), - "m01s00i305": Stash(1, 0), - "m01s00i306": Stash(1, 0), - "m01s00i307": Stash(1, 0), - "m01s00i308": Stash(1, 0), - "m01s00i321": Stash(1, 573), - "m01s00i340": Stash(1, 520), - "m01s00i341": Stash(22, 453), - "m01s00i342": Stash(1, 0), - "m01s00i343": Stash(1, 2001), - "m01s00i344": Stash(1, 2002), - "m01s00i351": Stash(1, 385), - "m01s00i352": Stash(1, 386), - "m01s00i353": Stash(1, 387), - "m01s00i354": Stash(1, 388), - "m01s00i355": Stash(1, 389), - "m01s00i356": Stash(1, 390), - "m01s00i357": Stash(1, 391), - "m01s00i358": Stash(1, 392), - "m01s00i359": Stash(1, 393), - "m01s00i360": Stash(1, 394), - "m01s00i361": Stash(1, 395), - "m01s00i362": Stash(1, 396), - "m01s00i363": Stash(1, 397), - "m01s00i364": Stash(1, 398), - "m01s00i365": Stash(1, 399), - "m01s00i366": Stash(1, 400), - "m01s00i367": Stash(1, 401), - "m01s00i368": Stash(1, 402), - "m01s00i369": Stash(1, 403), - "m01s00i370": Stash(1, 404), - "m01s00i371": Stash(1, 405), - "m01s00i376": Stash(21, 0), - "m01s00i377": Stash(21, 0), - "m01s00i378": Stash(21, 0), - "m01s00i379": Stash(21, 0), - "m01s00i380": Stash(21, 0), - "m01s00i381": Stash(21, 0), - "m01s00i382": Stash(21, 0), - "m01s00i383": Stash(21, 0), - "m01s00i384": Stash(21, 0), - "m01s00i385": Stash(21, 0), - "m01s00i386": Stash(21, 0), - "m01s00i401": Stash(1, 7), - "m01s00i402": Stash(1, 79), - "m01s00i403": Stash(1, 78), - "m01s00i404": Stash(1, 1731), - "m01s00i405": Stash(21, 106), - "m01s00i406": Stash(1, 7), - "m01s00i407": Stash(1, 8), - "m01s00i408": Stash(1, 8), - "m01s00i409": Stash(1, 8), - "m01s00i410": Stash(1, 0), - "m01s00i411": Stash(1, 0), - "m01s00i412": Stash(1, 0), - "m01s00i413": Stash(1, 1411), - "m01s00i414": Stash(1, 1410), - "m01s00i415": Stash(1, 1413), - "m01s00i416": Stash(1, 1412), - "m01s00i418": Stash(1, 1630), - "m01s00i419": Stash(1, 1631), - "m01s00i420": Stash(1, 1632), - "m01s00i421": Stash(1, 1633), - "m01s00i422": Stash(1, 1633), - "m01s00i423": Stash(1, 1633), - "m01s00i424": Stash(1, 1633), - "m01s00i425": Stash(1, 1633), - "m01s00i426": Stash(1, 1633), - "m01s00i431": Stash(1, 1634), - "m01s00i432": Stash(1, 1634), - "m01s00i433": Stash(1, 1634), - "m01s00i434": Stash(1, 1634), - "m01s00i435": Stash(1, 1634), - "m01s00i436": Stash(1, 1634), - "m01s00i460": Stash(1, 902), - "m01s00i466": Stash(21, 1397), - "m01s00i467": Stash(21, 1397), - "m01s00i468": Stash(21, 1397), - "m01s00i469": Stash(21, 1397), - "m01s00i470": Stash(21, 1503), - "m01s00i471": Stash(21, 1503), - "m01s00i472": Stash(21, 1503), - "m01s00i473": Stash(21, 1503), - "m01s00i480": Stash(1, 1080), - "m01s00i481": Stash(22, 1081), - "m01s00i482": Stash(22, 1082), - "m01s00i483": Stash(22, 1083), - "m01s00i484": Stash(22, 1084), - "m01s00i485": Stash(22, 1085), - "m01s00i486": Stash(22, 1086), - "m01s00i487": Stash(22, 1087), - "m01s00i490": Stash(21, 1137), - "m01s00i491": Stash(1, 1138), - "m01s00i492": Stash(1, 1139), - "m01s00i493": Stash(1, 40), - "m01s00i494": Stash(21, 0), - "m01s00i495": Stash(21, 0), - "m01s00i496": Stash(21, 0), - "m01s00i497": Stash(21, 0), - "m01s00i498": Stash(21, 0), - "m01s00i499": Stash(21, 0), - "m01s00i500": Stash(21, 0), - "m01s00i501": Stash(21, 0), - "m01s00i502": Stash(21, 0), - "m01s00i505": Stash(21, 395), - "m01s00i506": Stash(1, 16), - "m01s00i507": Stash(1, 16), - "m01s00i508": Stash(1, 16), - "m01s00i509": Stash(1, 322), - "m01s00i510": Stash(1, 322), - "m01s00i511": Stash(21, 1907), - "m01s01i004": Stash(1, 16), - "m01s01i101": Stash(1, 0), - "m01s01i102": Stash(1, 0), - "m01s01i103": Stash(1, 0), - "m01s01i104": Stash(1, 0), - "m01s01i105": Stash(1, 0), - "m01s01i106": Stash(1, 0), - "m01s01i107": Stash(1, 0), - "m01s01i108": Stash(1, 0), - "m01s01i109": Stash(1, 0), - "m01s01i110": Stash(1, 0), - "m01s01i111": Stash(1, 0), - "m01s01i112": Stash(1, 0), - "m01s01i113": Stash(1, 0), - "m01s01i114": Stash(1, 0), - "m01s01i115": Stash(1, 0), - "m01s01i116": Stash(1, 0), - "m01s01i161": Stash(1, 0), - "m01s01i181": Stash(1, 0), - "m01s01i182": Stash(1, 0), - "m01s01i183": Stash(1, 0), - "m01s01i192": Stash(1, 0), - "m01s01i193": Stash(1, 0), - "m01s01i194": Stash(1, 0), - "m01s01i195": Stash(1, 0), - "m01s01i198": Stash(1, 0), - "m01s01i199": Stash(1, 0), - "m01s01i201": Stash(1, 186), - "m01s01i202": Stash(1, 186), - "m01s01i203": Stash(1, 186), - "m01s01i204": Stash(1, 186), - "m01s01i205": Stash(1, 201), - "m01s01i206": Stash(1, 328), - "m01s01i207": Stash(1, 200), - "m01s01i208": Stash(1, 201), - "m01s01i209": Stash(1, 207), - "m01s01i210": Stash(1, 208), - "m01s01i211": Stash(1, 207), - "m01s01i212": Stash(1, 1027), - "m01s01i213": Stash(1, 1028), - "m01s01i214": Stash(1, 1029), - "m01s01i215": Stash(1, 186), - "m01s01i216": Stash(1, 186), - "m01s01i217": Stash(1, 201), - "m01s01i218": Stash(1, 203), - "m01s01i219": Stash(1, 207), - "m01s01i220": Stash(1, 208), - "m01s01i221": Stash(1, 164), - "m01s01i222": Stash(1, 165), - "m01s01i223": Stash(1, 166), - "m01s01i224": Stash(1, 167), - "m01s01i225": Stash(1, 163), - "m01s01i226": Stash(1, 165), - "m01s01i230": Stash(1, 0), - "m01s01i231": Stash(1, 0), - "m01s01i232": Stash(1, 251), - "m01s01i233": Stash(1, 252), - "m01s01i234": Stash(1, 1376), - "m01s01i235": Stash(1, 203), - "m01s01i236": Stash(1, 1377), - "m01s01i237": Stash(1, 186), - "m01s01i238": Stash(1, 201), - "m01s01i241": Stash(1, 1464), - "m01s01i242": Stash(1, 1465), - "m01s01i243": Stash(1, 1466), - "m01s01i244": Stash(1, 1467), - "m01s01i245": Stash(1, 1468), - "m01s01i246": Stash(1, 1469), - "m01s01i247": Stash(1, 1470), - "m01s01i248": Stash(1, 1471), - "m01s01i254": Stash(1, 1805), - "m01s01i255": Stash(1, 1806), - "m01s01i257": Stash(1, 186), - "m01s01i258": Stash(1, 186), - "m01s01i259": Stash(1, 186), - "m01s01i260": Stash(1, 186), - "m01s01i262": Stash(1, 1714), - "m01s01i263": Stash(1, 1715), - "m01s01i264": Stash(1, 1721), - "m01s01i265": Stash(1, 1722), - "m01s01i266": Stash(1, 1723), - "m01s01i267": Stash(1, 1724), - "m01s01i280": Stash(1, 1807), - "m01s01i281": Stash(1, 1808), - "m01s01i290": Stash(1, 1891), - "m01s01i291": Stash(1, 1892), - "m01s01i292": Stash(1, 1030), - "m01s01i293": Stash(1, 1031), - "m01s01i294": Stash(1, 1032), - "m01s01i295": Stash(1, 1033), - "m01s01i296": Stash(1, 1034), - "m01s01i408": Stash(1, 201), - "m01s01i409": Stash(1, 207), - "m01s01i410": Stash(1, 208), - "m01s01i411": Stash(1, 207), - "m01s01i417": Stash(1, 201), - "m01s01i418": Stash(1, 203), - "m01s01i419": Stash(1, 207), - "m01s01i420": Stash(1, 208), - "m01s01i433": Stash(1, 252), - "m01s01i435": Stash(1, 203), - "m01s01i437": Stash(1, 186), - "m01s01i438": Stash(1, 201), - "m01s02i004": Stash(1, 16), - "m01s02i101": Stash(1, 0), - "m01s02i161": Stash(1, 0), - "m01s02i181": Stash(1, 0), - "m01s02i182": Stash(1, 0), - "m01s02i183": Stash(1, 0), - "m01s02i192": Stash(1, 0), - "m01s02i193": Stash(1, 0), - "m01s02i194": Stash(1, 0), - "m01s02i195": Stash(1, 0), - "m01s02i198": Stash(1, 0), - "m01s02i199": Stash(1, 0), - "m01s02i201": Stash(1, 187), - "m01s02i202": Stash(1, 187), - "m01s02i203": Stash(1, 187), - "m01s02i204": Stash(1, 30), - "m01s02i205": Stash(1, 206), - "m01s02i206": Stash(1, 210), - "m01s02i207": Stash(1, 205), - "m01s02i208": Stash(1, 211), - "m01s02i217": Stash(1, 206), - "m01s02i218": Stash(1, 205), - "m01s02i219": Stash(1, 210), - "m01s02i220": Stash(1, 211), - "m01s02i232": Stash(1, 253), - "m01s02i233": Stash(1, 254), - "m01s02i237": Stash(1, 187), - "m01s02i238": Stash(1, 205), - "m01s02i260": Stash(1, 453), - "m01s02i261": Stash(1, 1720), - "m01s02i262": Stash(1, 1718), - "m01s02i263": Stash(1, 1719), - "m01s02i264": Stash(1, 1725), - "m01s02i265": Stash(1, 1726), - "m01s02i266": Stash(1, 1727), - "m01s02i267": Stash(1, 1728), - "m01s02i269": Stash(1, 30), - "m01s02i270": Stash(1, 30), - "m01s02i271": Stash(1, 30), - "m01s02i272": Stash(1, 30), - "m01s02i273": Stash(1, 30), - "m01s02i274": Stash(1, 30), - "m01s02i275": Stash(1, 30), - "m01s02i276": Stash(1, 30), - "m01s02i277": Stash(1, 30), - "m01s02i280": Stash(1, 1930), - "m01s02i281": Stash(1, 1931), - "m01s02i282": Stash(1, 1932), - "m01s02i283": Stash(1, 1932), - "m01s02i284": Stash(1, 0), - "m01s02i285": Stash(1, 0), - "m01s02i286": Stash(1, 0), - "m01s02i287": Stash(1, 0), - "m01s02i288": Stash(1, 0), - "m01s02i289": Stash(1, 0), - "m01s02i290": Stash(1, 30), - "m01s02i291": Stash(1, 30), - "m01s02i292": Stash(1, 30), - "m01s02i293": Stash(1, 30), - "m01s02i295": Stash(1, 0), - "m01s02i296": Stash(1, 0), - "m01s02i297": Stash(1, 0), - "m01s02i298": Stash(1, 0), - "m01s02i299": Stash(1, 0), - "m01s02i300": Stash(1, 0), - "m01s02i301": Stash(1, 0), - "m01s02i302": Stash(1, 0), - "m01s02i303": Stash(1, 0), - "m01s02i304": Stash(1, 0), - "m01s02i305": Stash(1, 0), - "m01s02i308": Stash(1, 79), - "m01s02i309": Stash(1, 78), - "m01s02i310": Stash(1, 79), - "m01s02i311": Stash(1, 78), - "m01s02i312": Stash(1, 1425), - "m01s02i313": Stash(1, 1426), - "m01s02i314": Stash(1, 1425), - "m01s02i315": Stash(1, 1426), - "m01s02i320": Stash(1, 0), - "m01s02i321": Stash(1, 0), - "m01s02i322": Stash(1, 0), - "m01s02i323": Stash(1, 0), - "m01s02i324": Stash(1, 0), - "m01s02i325": Stash(1, 0), - "m01s02i330": Stash(1, 0), - "m01s02i331": Stash(1, 0), - "m01s02i332": Stash(1, 0), - "m01s02i333": Stash(1, 0), - "m01s02i334": Stash(1, 0), - "m01s02i335": Stash(1, 0), - "m01s02i336": Stash(1, 0), - "m01s02i337": Stash(1, 30), - "m01s02i340": Stash(1, 0), - "m01s02i341": Stash(1, 0), - "m01s02i342": Stash(1, 0), - "m01s02i343": Stash(1, 30), - "m01s02i344": Stash(1, 30), - "m01s02i345": Stash(1, 30), - "m01s02i346": Stash(1, 30), - "m01s02i347": Stash(1, 30), - "m01s02i348": Stash(1, 0), - "m01s02i349": Stash(1, 30), - "m01s02i350": Stash(1, 0), - "m01s02i351": Stash(1, 0), - "m01s02i352": Stash(1, 0), - "m01s02i353": Stash(1, 0), - "m01s02i354": Stash(1, 0), - "m01s02i355": Stash(1, 0), - "m01s02i356": Stash(1, 0), - "m01s02i360": Stash(1, 30), - "m01s02i370": Stash(1, 0), - "m01s02i371": Stash(1, 30), - "m01s02i372": Stash(1, 0), - "m01s02i373": Stash(1, 0), - "m01s02i374": Stash(1, 30), - "m01s02i375": Stash(1, 0), - "m01s02i376": Stash(1, 0), - "m01s02i377": Stash(1, 0), - "m01s02i378": Stash(1, 0), - "m01s02i380": Stash(1, 0), - "m01s02i381": Stash(1, 0), - "m01s02i382": Stash(1, 0), - "m01s02i383": Stash(1, 0), - "m01s02i384": Stash(1, 0), - "m01s02i385": Stash(1, 0), - "m01s02i386": Stash(1, 0), - "m01s02i387": Stash(1, 0), - "m01s02i388": Stash(1, 0), - "m01s02i389": Stash(1, 1697), - "m01s02i390": Stash(1, 1698), - "m01s02i406": Stash(1, 210), - "m01s02i407": Stash(1, 205), - "m01s02i408": Stash(1, 211), - "m01s02i417": Stash(1, 206), - "m01s02i418": Stash(1, 205), - "m01s02i419": Stash(1, 210), - "m01s02i420": Stash(1, 211), - "m01s02i421": Stash(1, 0), - "m01s02i422": Stash(1, 0), - "m01s02i423": Stash(1, 0), - "m01s02i424": Stash(1, 0), - "m01s02i425": Stash(1, 0), - "m01s02i426": Stash(1, 0), - "m01s02i427": Stash(1, 0), - "m01s02i433": Stash(1, 254), - "m01s02i437": Stash(1, 187), - "m01s02i438": Stash(1, 205), - "m01s03i002": Stash(18, 56), - "m01s03i003": Stash(19, 57), - "m01s03i004": Stash(1, 16), - "m01s03i010": Stash(1, 95), - "m01s03i024": Stash(1, 16), - "m01s03i025": Stash(1, 5), - "m01s03i026": Stash(1, 324), - "m01s03i027": Stash(1, 324), - "m01s03i028": Stash(1, 1075), - "m01s03i049": Stash(3, 209), - "m01s03i050": Stash(1, 0), - "m01s03i051": Stash(2, 0), - "m01s03i052": Stash(2, 0), - "m01s03i053": Stash(2, 0), - "m01s03i054": Stash(21, 1416), - "m01s03i055": Stash(2, 0), - "m01s03i060": Stash(1, 0), - "m01s03i061": Stash(1, 0), - "m01s03i062": Stash(1, 0), - "m01s03i063": Stash(1, 0), - "m01s03i064": Stash(1, 0), - "m01s03i065": Stash(1, 0), - "m01s03i066": Stash(1, 0), - "m01s03i067": Stash(1, 0), - "m01s03i068": Stash(1, 0), - "m01s03i069": Stash(1, 0), - "m01s03i070": Stash(1, 0), - "m01s03i071": Stash(1, 0), - "m01s03i072": Stash(1, 0), - "m01s03i073": Stash(1, 0), - "m01s03i074": Stash(1, 0), - "m01s03i075": Stash(1, 0), - "m01s03i076": Stash(1, 0), - "m01s03i077": Stash(1, 0), - "m01s03i078": Stash(1, 0), - "m01s03i079": Stash(1, 0), - "m01s03i100": Stash(1, 1301), - "m01s03i101": Stash(1, 1302), - "m01s03i102": Stash(1, 1303), - "m01s03i103": Stash(1, 1304), - "m01s03i104": Stash(1, 1305), - "m01s03i105": Stash(1, 1306), - "m01s03i106": Stash(1, 1307), - "m01s03i107": Stash(1, 1308), - "m01s03i108": Stash(1, 1309), - "m01s03i109": Stash(1, 1310), - "m01s03i110": Stash(1, 1311), - "m01s03i111": Stash(1, 1312), - "m01s03i112": Stash(1, 1313), - "m01s03i113": Stash(1, 1314), - "m01s03i114": Stash(1, 1315), - "m01s03i115": Stash(1, 1316), - "m01s03i116": Stash(1, 1317), - "m01s03i117": Stash(1, 1318), - "m01s03i118": Stash(1, 1319), - "m01s03i119": Stash(1, 1320), - "m01s03i120": Stash(1, 1321), - "m01s03i121": Stash(1, 1322), - "m01s03i122": Stash(1, 1323), - "m01s03i123": Stash(1, 1324), - "m01s03i124": Stash(1, 1325), - "m01s03i125": Stash(1, 1326), - "m01s03i126": Stash(1, 1327), - "m01s03i127": Stash(1, 1328), - "m01s03i128": Stash(1, 1329), - "m01s03i129": Stash(1, 1330), - "m01s03i130": Stash(1, 2042), - "m01s03i131": Stash(1, 2043), - "m01s03i132": Stash(1, 2044), - "m01s03i133": Stash(1, 2045), - "m01s03i134": Stash(1, 2046), - "m01s03i135": Stash(1, 2047), - "m01s03i136": Stash(1, 2048), - "m01s03i137": Stash(1, 2049), - "m01s03i138": Stash(1, 2050), - "m01s03i139": Stash(1, 2051), - "m01s03i140": Stash(1, 2052), - "m01s03i141": Stash(1, 2053), - "m01s03i142": Stash(1, 2054), - "m01s03i143": Stash(1, 2055), - "m01s03i170": Stash(1, 0), - "m01s03i171": Stash(1, 0), - "m01s03i172": Stash(1, 0), - "m01s03i173": Stash(1, 0), - "m01s03i176": Stash(1, 0), - "m01s03i177": Stash(1, 0), - "m01s03i178": Stash(1, 0), - "m01s03i179": Stash(1, 0), - "m01s03i181": Stash(1, 0), - "m01s03i182": Stash(1, 0), - "m01s03i183": Stash(1, 0), - "m01s03i184": Stash(1, 0), - "m01s03i185": Stash(18, 0), - "m01s03i186": Stash(19, 0), - "m01s03i188": Stash(1, 0), - "m01s03i189": Stash(1, 0), - "m01s03i190": Stash(1, 0), - "m01s03i192": Stash(1, 0), - "m01s03i193": Stash(1, 0), - "m01s03i194": Stash(1, 0), - "m01s03i201": Stash(1, 261), - "m01s03i202": Stash(2, 179), - "m01s03i203": Stash(1, 160), - "m01s03i204": Stash(1, 183), - "m01s03i205": Stash(1, 52), - "m01s03i206": Stash(11, 172), - "m01s03i207": Stash(1, 171), - "m01s03i208": Stash(1, 181), - "m01s03i209": Stash(18, 56), - "m01s03i210": Stash(19, 57), - "m01s03i216": Stash(1, 178), - "m01s03i217": Stash(1, 178), - "m01s03i219": Stash(18, 61), - "m01s03i220": Stash(19, 62), - "m01s03i221": Stash(11, 1900), - "m01s03i222": Stash(1, 184), - "m01s03i223": Stash(1, 184), - "m01s03i224": Stash(1, 182), - "m01s03i225": Stash(11, 56), - "m01s03i226": Stash(11, 57), - "m01s03i227": Stash(11, 50), - "m01s03i228": Stash(1, 178), - "m01s03i229": Stash(2, 115), - "m01s03i230": Stash(1, 183), - "m01s03i231": Stash(1, 107), - "m01s03i232": Stash(1, 285), - "m01s03i234": Stash(1, 180), - "m01s03i235": Stash(1, 260), - "m01s03i236": Stash(1, 16), - "m01s03i237": Stash(1, 95), - "m01s03i238": Stash(2, 23), - "m01s03i239": Stash(1, 79), - "m01s03i240": Stash(1, 78), - "m01s03i241": Stash(1, 184), - "m01s03i242": Stash(1, 220), - "m01s03i243": Stash(1, 79), - "m01s03i244": Stash(1, 78), - "m01s03i245": Stash(1, 88), - "m01s03i247": Stash(1, 25), - "m01s03i248": Stash(1, 220), - "m01s03i249": Stash(11, 50), - "m01s03i250": Stash(1, 17), - "m01s03i251": Stash(1, 174), - "m01s03i252": Stash(1, 175), - "m01s03i253": Stash(1, 173), - "m01s03i254": Stash(1, 19), - "m01s03i255": Stash(1, 95), - "m01s03i256": Stash(1, 1414), - "m01s03i257": Stash(1, 1415), - "m01s03i258": Stash(2, 141), - "m01s03i259": Stash(2, 1384), - "m01s03i260": Stash(2, 1387), - "m01s03i261": Stash(2, 1388), - "m01s03i262": Stash(2, 1389), - "m01s03i263": Stash(2, 1390), - "m01s03i264": Stash(2, 1382), - "m01s03i265": Stash(2, 1383), - "m01s03i270": Stash(1, 1400), - "m01s03i271": Stash(1, 1401), - "m01s03i272": Stash(1, 1402), - "m01s03i273": Stash(1, 1403), - "m01s03i274": Stash(1, 1542), - "m01s03i275": Stash(1, 1543), - "m01s03i276": Stash(1, 1406), - "m01s03i277": Stash(1, 1407), - "m01s03i278": Stash(1, 1408), - "m01s03i279": Stash(1, 1409), - "m01s03i280": Stash(1, 1410), - "m01s03i281": Stash(1, 25), - "m01s03i282": Stash(1, 220), - "m01s03i283": Stash(1, 173), - "m01s03i284": Stash(1, 25), - "m01s03i285": Stash(1, 25), - "m01s03i286": Stash(1, 1416), - "m01s03i287": Stash(2, 1517), - "m01s03i288": Stash(2, 1518), - "m01s03i289": Stash(2, 1519), - "m01s03i290": Stash(2, 1520), - "m01s03i291": Stash(2, 1521), - "m01s03i292": Stash(2, 1522), - "m01s03i293": Stash(2, 1523), - "m01s03i294": Stash(1, 1524), - "m01s03i295": Stash(2, 1525), - "m01s03i296": Stash(2, 1526), - "m01s03i297": Stash(2, 1527), - "m01s03i298": Stash(1, 1528), - "m01s03i299": Stash(2, 1529), - "m01s03i300": Stash(1, 1541), - "m01s03i301": Stash(1, 1542), - "m01s03i302": Stash(1, 1543), - "m01s03i303": Stash(1, 1544), - "m01s03i304": Stash(1, 1534), - "m01s03i305": Stash(1, 1535), - "m01s03i306": Stash(1, 1536), - "m01s03i307": Stash(1, 1537), - "m01s03i308": Stash(1, 1538), - "m01s03i309": Stash(1, 1539), - "m01s03i310": Stash(1, 1540), - "m01s03i311": Stash(2, 1557), - "m01s03i312": Stash(2, 1558), - "m01s03i313": Stash(2, 1559), - "m01s03i314": Stash(2, 202), - "m01s03i315": Stash(2, 1391), - "m01s03i316": Stash(2, 1510), - "m01s03i317": Stash(2, 1893), - "m01s03i318": Stash(2, 1894), - "m01s03i319": Stash(2, 1895), - "m01s03i320": Stash(2, 1397), - "m01s03i321": Stash(2, 1504), - "m01s03i322": Stash(2, 1505), - "m01s03i323": Stash(2, 1508), - "m01s03i324": Stash(2, 1511), - "m01s03i325": Stash(2, 1499), - "m01s03i326": Stash(2, 1562), - "m01s03i327": Stash(1, 1563), - "m01s03i328": Stash(2, 16), - "m01s03i329": Stash(2, 95), - "m01s03i330": Stash(2, 180), - "m01s03i331": Stash(2, 1564), - "m01s03i332": Stash(1, 206), - "m01s03i333": Stash(1, 202), - "m01s03i334": Stash(2, 115), - "m01s03i335": Stash(2, 1517), - "m01s03i337": Stash(2, 1564), - "m01s03i338": Stash(1, 1565), - "m01s03i339": Stash(1, 181), - "m01s03i340": Stash(1, 1628), - "m01s03i341": Stash(2, 115), - "m01s03i342": Stash(2, 115), - "m01s03i343": Stash(1, 285), - "m01s03i347": Stash(1, 285), - "m01s03i353": Stash(1, 1528), - "m01s03i356": Stash(1, 1800), - "m01s03i357": Stash(1, 1801), - "m01s03i358": Stash(1, 1802), - "m01s03i359": Stash(1, 1803), - "m01s03i360": Stash(1, 1091), - "m01s03i361": Stash(1, 1092), - "m01s03i362": Stash(1, 1093), - "m01s03i363": Stash(1, 1094), - "m01s03i381": Stash(1, 202), - "m01s03i389": Stash(1, 52), - "m01s03i390": Stash(1, 52), - "m01s03i391": Stash(18, 61), - "m01s03i392": Stash(18, 61), - "m01s03i393": Stash(19, 62), - "m01s03i394": Stash(19, 62), - "m01s03i395": Stash(1, 202), - "m01s03i396": Stash(1, 1686), - "m01s03i397": Stash(1, 1687), - "m01s03i398": Stash(1, 1688), - "m01s03i400": Stash(1, 1646), - "m01s03i401": Stash(1, 1635), - "m01s03i402": Stash(1, 1635), - "m01s03i403": Stash(1, 1635), - "m01s03i404": Stash(1, 1635), - "m01s03i405": Stash(1, 1635), - "m01s03i406": Stash(1, 1635), - "m01s03i407": Stash(1, 1542), - "m01s03i408": Stash(1, 1543), - "m01s03i409": Stash(1, 1544), - "m01s03i411": Stash(1, 1636), - "m01s03i412": Stash(1, 1636), - "m01s03i413": Stash(1, 1636), - "m01s03i414": Stash(1, 1636), - "m01s03i415": Stash(1, 1636), - "m01s03i416": Stash(1, 1636), - "m01s03i417": Stash(1, 1636), - "m01s03i418": Stash(1, 1636), - "m01s03i419": Stash(1, 1636), - "m01s03i421": Stash(1, 1637), - "m01s03i422": Stash(1, 1637), - "m01s03i423": Stash(1, 1637), - "m01s03i424": Stash(1, 1637), - "m01s03i425": Stash(1, 1637), - "m01s03i426": Stash(1, 1637), - "m01s03i427": Stash(1, 1637), - "m01s03i428": Stash(1, 1637), - "m01s03i429": Stash(1, 1637), - "m01s03i430": Stash(1, 1638), - "m01s03i441": Stash(1, 1639), - "m01s03i442": Stash(1, 1639), - "m01s03i443": Stash(1, 1639), - "m01s03i444": Stash(1, 1639), - "m01s03i445": Stash(1, 1639), - "m01s03i446": Stash(1, 1639), - "m01s03i451": Stash(1, 1640), - "m01s03i452": Stash(1, 1640), - "m01s03i453": Stash(1, 1640), - "m01s03i454": Stash(1, 1640), - "m01s03i455": Stash(1, 1640), - "m01s03i456": Stash(1, 1640), - "m01s03i460": Stash(18, 1025), - "m01s03i461": Stash(19, 1026), - "m01s03i462": Stash(1, 1896), - "m01s03i463": Stash(1, 1694), - "m01s03i464": Stash(1, 1695), - "m01s03i465": Stash(1, 1696), - "m01s03i466": Stash(1, 1015), - "m01s03i467": Stash(1, 1016), - "m01s03i468": Stash(1, 1017), - "m01s03i469": Stash(1, 1018), - "m01s03i470": Stash(1, 1019), - "m01s03i471": Stash(1, 1020), - "m01s03i472": Stash(1, 1021), - "m01s03i473": Stash(1, 1022), - "m01s03i474": Stash(18, 1023), - "m01s03i475": Stash(19, 1024), - "m01s03i476": Stash(1, 1036), - "m01s03i477": Stash(2, 1397), - "m01s03i478": Stash(2, 1397), - "m01s03i479": Stash(2, 1397), - "m01s03i480": Stash(2, 1397), - "m01s03i481": Stash(2, 1503), - "m01s03i482": Stash(2, 1503), - "m01s03i483": Stash(2, 1503), - "m01s03i484": Stash(2, 1503), - "m01s03i485": Stash(2, 1503), - "m01s03i486": Stash(2, 1503), - "m01s03i490": Stash(2, 2040), - "m01s03i491": Stash(2, 2041), - "m01s03i492": Stash(2, 2042), - "m01s03i493": Stash(2, 2043), - "m01s03i494": Stash(2, 2044), - "m01s03i501": Stash(1, 1400), - "m01s03i502": Stash(1, 1401), - "m01s03i503": Stash(1, 1402), - "m01s03i504": Stash(1, 1403), - "m01s03i505": Stash(1, 1404), - "m01s03i506": Stash(1, 1405), - "m01s03i507": Stash(1, 1406), - "m01s03i508": Stash(1, 1407), - "m01s04i004": Stash(1, 16), - "m01s04i010": Stash(1, 95), - "m01s04i130": Stash(1, 0), - "m01s04i131": Stash(1, 0), - "m01s04i132": Stash(1, 0), - "m01s04i133": Stash(1, 0), - "m01s04i136": Stash(1, 0), - "m01s04i137": Stash(1, 0), - "m01s04i138": Stash(1, 0), - "m01s04i139": Stash(1, 0), - "m01s04i141": Stash(1, 0), - "m01s04i142": Stash(1, 0), - "m01s04i143": Stash(1, 0), - "m01s04i144": Stash(1, 0), - "m01s04i152": Stash(1, 0), - "m01s04i153": Stash(1, 0), - "m01s04i154": Stash(1, 0), - "m01s04i170": Stash(1, 0), - "m01s04i171": Stash(1, 0), - "m01s04i172": Stash(1, 0), - "m01s04i173": Stash(1, 0), - "m01s04i176": Stash(1, 0), - "m01s04i177": Stash(1, 0), - "m01s04i178": Stash(1, 0), - "m01s04i179": Stash(1, 0), - "m01s04i181": Stash(1, 0), - "m01s04i182": Stash(1, 0), - "m01s04i183": Stash(1, 0), - "m01s04i184": Stash(1, 0), - "m01s04i189": Stash(1, 1681), - "m01s04i190": Stash(1, 1921), - "m01s04i191": Stash(1, 1689), - "m01s04i192": Stash(1, 0), - "m01s04i193": Stash(1, 0), - "m01s04i194": Stash(1, 0), - "m01s04i201": Stash(1, 102), - "m01s04i202": Stash(1, 116), - "m01s04i203": Stash(1, 99), - "m01s04i204": Stash(1, 118), - "m01s04i205": Stash(1, 79), - "m01s04i206": Stash(1, 78), - "m01s04i207": Stash(1, 88), - "m01s04i208": Stash(1, 25), - "m01s04i210": Stash(1, 0), - "m01s04i211": Stash(1, 0), - "m01s04i212": Stash(1, 1422), - "m01s04i213": Stash(1, 1546), - "m01s04i214": Stash(1, 1546), - "m01s04i215": Stash(1, 1545), - "m01s04i216": Stash(1, 1547), - "m01s04i217": Stash(1, 1548), - "m01s04i218": Stash(1, 1549), - "m01s04i219": Stash(1, 1550), - "m01s04i220": Stash(1, 1546), - "m01s04i221": Stash(1, 1546), - "m01s04i222": Stash(1, 99), - "m01s04i223": Stash(1, 118), - "m01s04i224": Stash(1, 1573), - "m01s04i225": Stash(1, 1574), - "m01s04i227": Stash(1, 1575), - "m01s04i228": Stash(1, 1546), - "m01s04i229": Stash(1, 1546), - "m01s04i231": Stash(1, 1641), - "m01s04i232": Stash(1, 1641), - "m01s04i233": Stash(1, 1641), - "m01s04i234": Stash(1, 1641), - "m01s04i235": Stash(1, 1641), - "m01s04i236": Stash(1, 1641), - "m01s04i237": Stash(1, 1691), - "m01s04i238": Stash(1, 1692), - "m01s04i240": Stash(1, 0), - "m01s04i241": Stash(1, 0), - "m01s04i242": Stash(1, 0), - "m01s04i243": Stash(1, 0), - "m01s04i244": Stash(1, 0), - "m01s04i245": Stash(1, 0), - "m01s04i246": Stash(1, 0), - "m01s04i247": Stash(1, 0), - "m01s04i248": Stash(1, 0), - "m01s04i249": Stash(1, 0), - "m01s04i250": Stash(1, 0), - "m01s04i251": Stash(1, 0), - "m01s04i252": Stash(1, 0), - "m01s04i253": Stash(1, 0), - "m01s04i254": Stash(1, 0), - "m01s04i255": Stash(1, 0), - "m01s04i256": Stash(1, 0), - "m01s04i257": Stash(1, 0), - "m01s04i258": Stash(1, 0), - "m01s04i259": Stash(1, 0), - "m01s04i260": Stash(1, 0), - "m01s04i261": Stash(1, 0), - "m01s04i262": Stash(1, 0), - "m01s04i263": Stash(1, 0), - "m01s04i264": Stash(1, 0), - "m01s04i265": Stash(1, 0), - "m01s04i266": Stash(1, 0), - "m01s04i267": Stash(1, 0), - "m01s04i268": Stash(1, 0), - "m01s04i269": Stash(1, 0), - "m01s04i270": Stash(1, 0), - "m01s04i271": Stash(1, 0), - "m01s04i281": Stash(1, 0), - "m01s04i282": Stash(1, 0), - "m01s04i283": Stash(1, 0), - "m01s04i292": Stash(1, 0), - "m01s04i293": Stash(1, 0), - "m01s05i004": Stash(1, 19), - "m01s05i010": Stash(1, 95), - "m01s05i013": Stash(1, 34), - "m01s05i140": Stash(1, 0), - "m01s05i141": Stash(1, 0), - "m01s05i142": Stash(1, 0), - "m01s05i143": Stash(1, 0), - "m01s05i146": Stash(1, 0), - "m01s05i147": Stash(1, 0), - "m01s05i148": Stash(1, 0), - "m01s05i149": Stash(1, 0), - "m01s05i150": Stash(1, 0), - "m01s05i151": Stash(1, 0), - "m01s05i152": Stash(1, 0), - "m01s05i156": Stash(1, 0), - "m01s05i157": Stash(1, 0), - "m01s05i158": Stash(1, 0), - "m01s05i163": Stash(1, 0), - "m01s05i164": Stash(1, 0), - "m01s05i172": Stash(1, 0), - "m01s05i173": Stash(1, 0), - "m01s05i174": Stash(1, 0), - "m01s05i181": Stash(1, 0), - "m01s05i182": Stash(1, 0), - "m01s05i183": Stash(1, 0), - "m01s05i184": Stash(1, 0), - "m01s05i185": Stash(18, 0), - "m01s05i186": Stash(19, 0), - "m01s05i187": Stash(1, 0), - "m01s05i188": Stash(1, 0), - "m01s05i192": Stash(1, 0), - "m01s05i193": Stash(1, 0), - "m01s05i194": Stash(1, 0), - "m01s05i201": Stash(1, 94), - "m01s05i202": Stash(1, 117), - "m01s05i203": Stash(1, 24), - "m01s05i204": Stash(1, 95), - "m01s05i205": Stash(1, 98), - "m01s05i206": Stash(1, 119), - "m01s05i207": Stash(1, 34), - "m01s05i208": Stash(1, 34), - "m01s05i209": Stash(1, 16), - "m01s05i210": Stash(1, 34), - "m01s05i211": Stash(1, 34), - "m01s05i212": Stash(1, 34), - "m01s05i213": Stash(1, 218), - "m01s05i214": Stash(1, 97), - "m01s05i215": Stash(1, 108), - "m01s05i216": Stash(1, 90), - "m01s05i217": Stash(1, 213), - "m01s05i218": Stash(1, 222), - "m01s05i219": Stash(1, 223), - "m01s05i220": Stash(1, 343), - "m01s05i221": Stash(1, 219), - "m01s05i222": Stash(1, 344), - "m01s05i223": Stash(1, 345), - "m01s05i224": Stash(1, 346), - "m01s05i225": Stash(1, 347), - "m01s05i226": Stash(1, 77), - "m01s05i227": Stash(1, 1697), - "m01s05i228": Stash(1, 1698), - "m01s05i229": Stash(1, 1419), - "m01s05i230": Stash(1, 1420), - "m01s05i231": Stash(1, 1134), - "m01s05i232": Stash(1, 1135), - "m01s05i233": Stash(1, 1482), - "m01s05i234": Stash(1, 1629), - "m01s05i235": Stash(18, 56), - "m01s05i236": Stash(19, 57), - "m01s05i237": Stash(1, 1551), - "m01s05i238": Stash(1, 1553), - "m01s05i239": Stash(1, 1554), - "m01s05i240": Stash(1, 1555), - "m01s05i241": Stash(1, 1556), - "m01s05i242": Stash(1, 1552), - "m01s05i243": Stash(1, 1693), - "m01s05i244": Stash(1, 1552), - "m01s05i246": Stash(1, 40), - "m01s05i247": Stash(1, 1552), - "m01s05i248": Stash(1, 1552), - "m01s05i249": Stash(1, 40), - "m01s05i250": Stash(1, 40), - "m01s05i251": Stash(1, 40), - "m01s05i252": Stash(1, 74), - "m01s05i253": Stash(1, 74), - "m01s05i254": Stash(1, 74), - "m01s05i255": Stash(1, 74), - "m01s05i256": Stash(1, 318), - "m01s05i257": Stash(1, 319), - "m01s05i258": Stash(1, 61), - "m01s05i259": Stash(1, 62), - "m01s05i260": Stash(1, 61), - "m01s05i261": Stash(1, 62), - "m01s05i262": Stash(1, 34), - "m01s05i263": Stash(1, 61), - "m01s05i264": Stash(1, 62), - "m01s05i267": Stash(1, 0), - "m01s05i268": Stash(1, 0), - "m01s05i269": Stash(1, 0), - "m01s05i270": Stash(1, 1598), - "m01s05i271": Stash(1, 1599), - "m01s05i272": Stash(1, 1934), - "m01s05i273": Stash(1, 1935), - "m01s05i274": Stash(1, 1936), - "m01s05i275": Stash(1, 132), - "m01s05i276": Stash(1, 1937), - "m01s05i277": Stash(1, 90), - "m01s05i278": Stash(1, 90), - "m01s05i279": Stash(1, 90), - "m01s05i280": Stash(1, 90), - "m01s05i281": Stash(1, 1642), - "m01s05i282": Stash(1, 1642), - "m01s05i283": Stash(1, 1642), - "m01s05i284": Stash(1, 1642), - "m01s05i285": Stash(1, 1642), - "m01s05i286": Stash(1, 1642), - "m01s05i290": Stash(1, 1001), - "m01s05i291": Stash(1, 1002), - "m01s05i292": Stash(1, 1003), - "m01s05i293": Stash(1, 1004), - "m01s05i300": Stash(1, 1005), - "m01s05i301": Stash(1, 1006), - "m01s05i302": Stash(1, 1007), - "m01s05i303": Stash(1, 1007), - "m01s05i304": Stash(1, 1001), - "m01s05i305": Stash(1, 1003), - "m01s05i306": Stash(1, 1001), - "m01s05i307": Stash(1, 1003), - "m01s05i308": Stash(1, 1011), - "m01s05i309": Stash(1, 1012), - "m01s05i310": Stash(1, 1008), - "m01s05i311": Stash(1, 1009), - "m01s05i312": Stash(1, 1010), - "m01s05i313": Stash(1, 1013), - "m01s05i314": Stash(1, 1014), - "m01s05i319": Stash(1, 0), - "m01s05i320": Stash(1, 40), - "m01s05i321": Stash(1, 40), - "m01s05i322": Stash(1, 40), - "m01s05i323": Stash(1, 40), - "m01s05i324": Stash(1, 0), - "m01s05i325": Stash(1, 0), - "m01s05i326": Stash(1, 0), - "m01s05i327": Stash(1, 0), - "m01s05i328": Stash(1, 0), - "m01s05i329": Stash(1, 0), - "m01s05i330": Stash(1, 0), - "m01s05i331": Stash(1, 0), - "m01s05i332": Stash(1, 318), - "m01s05i333": Stash(1, 318), - "m01s05i334": Stash(1, 318), - "m01s05i335": Stash(1, 318), - "m01s05i336": Stash(1, 319), - "m01s05i337": Stash(1, 319), - "m01s05i338": Stash(1, 319), - "m01s05i339": Stash(1, 319), - "m01s05i400": Stash(1, 0), - "m01s05i401": Stash(1, 0), - "m01s05i402": Stash(1, 0), - "m01s05i403": Stash(1, 0), - "m01s05i404": Stash(1, 0), - "m01s05i405": Stash(1, 0), - "m01s05i406": Stash(1, 0), - "m01s05i407": Stash(1, 0), - "m01s05i408": Stash(1, 0), - "m01s05i409": Stash(1, 0), - "m01s05i410": Stash(1, 0), - "m01s05i411": Stash(1, 0), - "m01s05i412": Stash(1, 0), - "m01s05i413": Stash(1, 0), - "m01s05i414": Stash(1, 0), - "m01s05i415": Stash(1, 0), - "m01s05i416": Stash(1, 0), - "m01s05i417": Stash(1, 40), - "m01s05i418": Stash(1, 40), - "m01s05i419": Stash(1, 40), - "m01s05i421": Stash(1, 0), - "m01s05i422": Stash(1, 0), - "m01s05i423": Stash(1, 0), - "m01s05i424": Stash(1, 0), - "m01s05i425": Stash(1, 0), - "m01s05i426": Stash(1, 0), - "m01s05i427": Stash(1, 0), - "m01s05i428": Stash(1, 0), - "m01s05i429": Stash(1, 0), - "m01s05i430": Stash(1, 0), - "m01s05i431": Stash(1, 0), - "m01s05i432": Stash(1, 0), - "m01s06i002": Stash(18, 56), - "m01s06i003": Stash(19, 57), - "m01s06i101": Stash(18, 420), - "m01s06i102": Stash(19, 421), - "m01s06i103": Stash(18, 422), - "m01s06i104": Stash(19, 423), - "m01s06i105": Stash(18, 424), - "m01s06i106": Stash(19, 425), - "m01s06i111": Stash(18, 1095), - "m01s06i113": Stash(18, 1096), - "m01s06i115": Stash(18, 1097), - "m01s06i185": Stash(18, 0), - "m01s06i186": Stash(19, 0), - "m01s06i201": Stash(18, 61), - "m01s06i202": Stash(19, 62), - "m01s06i203": Stash(1, 150), - "m01s06i204": Stash(1, 152), - "m01s06i205": Stash(1, 153), - "m01s06i206": Stash(1, 154), - "m01s06i207": Stash(18, 68), - "m01s06i208": Stash(19, 69), - "m01s06i209": Stash(18, 70), - "m01s06i210": Stash(19, 71), - "m01s06i211": Stash(18, 124), - "m01s06i212": Stash(19, 124), - "m01s06i213": Stash(11, 125), - "m01s06i214": Stash(1, 1579), - "m01s06i215": Stash(1, 1580), - "m01s06i216": Stash(1, 1581), - "m01s06i217": Stash(1, 1582), - "m01s06i218": Stash(1, 1583), - "m01s06i219": Stash(1, 1584), - "m01s06i220": Stash(1, 1585), - "m01s06i221": Stash(1, 1586), - "m01s06i222": Stash(1, 1587), - "m01s06i223": Stash(18, 1588), - "m01s06i224": Stash(19, 1589), - "m01s06i225": Stash(18, 1590), - "m01s06i226": Stash(19, 1591), - "m01s06i227": Stash(18, 1592), - "m01s06i228": Stash(19, 1593), - "m01s06i229": Stash(18, 1594), - "m01s06i230": Stash(19, 1595), - "m01s06i231": Stash(18, 1596), - "m01s06i232": Stash(19, 1597), - "m01s06i233": Stash(1, 0), - "m01s06i234": Stash(1, 0), - "m01s06i235": Stash(18, 61), - "m01s06i236": Stash(19, 62), - "m01s06i237": Stash(1, 0), - "m01s06i241": Stash(18, 1098), - "m01s06i247": Stash(18, 1099), - "m01s06i248": Stash(1, 0), - "m01s06i249": Stash(1, 0), - "m01s06i250": Stash(1, 0), - "m01s07i002": Stash(11, 56), - "m01s07i003": Stash(11, 57), - "m01s07i201": Stash(11, 195), - "m01s07i202": Stash(11, 196), - "m01s08i023": Stash(1, 93), - "m01s08i024": Stash(1, 16), - "m01s08i201": Stash(2, 110), - "m01s08i202": Stash(2, 197), - "m01s08i203": Stash(2, 274), - "m01s08i204": Stash(2, 111), - "m01s08i205": Stash(2, 112), - "m01s08i206": Stash(2, 337), - "m01s08i207": Stash(2, 338), - "m01s08i208": Stash(2, 106), - "m01s08i209": Stash(2, 271), - "m01s08i210": Stash(2, 329), - "m01s08i211": Stash(2, 330), - "m01s08i212": Stash(2, 331), - "m01s08i213": Stash(2, 332), - "m01s08i214": Stash(2, 333), - "m01s08i215": Stash(2, 334), - "m01s08i216": Stash(2, 335), - "m01s08i217": Stash(2, 336), - "m01s08i218": Stash(2, 326), - "m01s08i219": Stash(2, 321), - "m01s08i220": Stash(1, 323), - "m01s08i221": Stash(1, 325), - "m01s08i222": Stash(1, 327), - "m01s08i223": Stash(2, 122), - "m01s08i224": Stash(1, 342), - "m01s08i225": Stash(2, 23), - "m01s08i226": Stash(2, 141), - "m01s08i228": Stash(2, 1381), - "m01s08i229": Stash(2, 1385), - "m01s08i230": Stash(2, 1386), - "m01s08i231": Stash(2, 1530), - "m01s08i233": Stash(2, 1531), - "m01s08i234": Stash(2, 1532), - "m01s08i235": Stash(2, 1533), - "m01s08i236": Stash(2, 1566), - "m01s08i237": Stash(2, 1567), - "m01s08i238": Stash(2, 1568), - "m01s08i239": Stash(2, 1534), - "m01s08i240": Stash(2, 1535), - "m01s08i241": Stash(2, 1536), - "m01s08i242": Stash(2, 1537), - "m01s08i243": Stash(2, 1537), - "m01s08i244": Stash(2, 1537), - "m01s08i245": Stash(2, 1907), - "m01s08i246": Stash(2, 1537), - "m01s08i247": Stash(2, 1537), - "m01s08i248": Stash(2, 1537), - "m01s08i249": Stash(2, 1537), - "m01s08i250": Stash(2, 1537), - "m01s08i251": Stash(2, 1537), - "m01s08i252": Stash(2, 1534), - "m01s08i254": Stash(2, 1532), - "m01s08i255": Stash(2, 1533), - "m01s08i258": Stash(2, 1532), - "m01s08i259": Stash(2, 1533), - "m01s09i004": Stash(1, 16), - "m01s09i010": Stash(1, 95), - "m01s09i181": Stash(1, 0), - "m01s09i182": Stash(1, 0), - "m01s09i183": Stash(1, 0), - "m01s09i201": Stash(1, 220), - "m01s09i202": Stash(1, 1090), - "m01s09i203": Stash(1, 33), - "m01s09i204": Stash(1, 32), - "m01s09i205": Stash(1, 31), - "m01s09i206": Stash(1, 79), - "m01s09i207": Stash(1, 78), - "m01s09i208": Stash(1, 136), - "m01s09i209": Stash(1, 136), - "m01s09i210": Stash(1, 136), - "m01s09i211": Stash(1, 136), - "m01s09i212": Stash(1, 136), - "m01s09i213": Stash(1, 136), - "m01s09i214": Stash(1, 136), - "m01s09i215": Stash(1, 136), - "m01s09i216": Stash(1, 30), - "m01s09i217": Stash(1, 30), - "m01s09i218": Stash(1, 29), - "m01s09i219": Stash(1, 75), - "m01s09i220": Stash(1, 76), - "m01s09i221": Stash(1, 139), - "m01s09i222": Stash(1, 41), - "m01s09i223": Stash(1, 216), - "m01s09i224": Stash(1, 1425), - "m01s09i225": Stash(1, 1426), - "m01s09i226": Stash(1, 1729), - "m01s09i227": Stash(1, 1729), - "m01s09i228": Stash(1, 1730), - "m01s09i229": Stash(1, 88), - "m01s09i230": Stash(1, 25), - "m01s09i231": Stash(1, 0), - "m01s10i001": Stash(1, 8), - "m01s10i002": Stash(11, 56), - "m01s10i003": Stash(11, 57), - "m01s10i004": Stash(1, 19), - "m01s10i010": Stash(1, 95), - "m01s10i185": Stash(18, 56), - "m01s10i186": Stash(19, 57), - "m01s10i187": Stash(1, 42), - "m01s10i201": Stash(11, 224), - "m01s10i202": Stash(11, 225), - "m01s10i203": Stash(1, 151), - "m01s10i204": Stash(1, 43), - "m01s10i205": Stash(1, 28), - "m01s10i206": Stash(1, 3), - "m01s10i207": Stash(18, 229), - "m01s10i208": Stash(19, 230), - "m01s10i209": Stash(18, 231), - "m01s10i210": Stash(19, 232), - "m01s10i211": Stash(18, 233), - "m01s10i212": Stash(19, 234), - "m01s10i213": Stash(18, 235), - "m01s10i214": Stash(19, 236), - "m01s10i215": Stash(11, 263), - "m01s10i216": Stash(11, 264), - "m01s10i217": Stash(11, 265), - "m01s10i218": Stash(11, 266), - "m01s10i219": Stash(18, 267), - "m01s10i220": Stash(19, 268), - "m01s10i221": Stash(18, 269), - "m01s10i222": Stash(19, 270), - "m01s10i223": Stash(11, 56), - "m01s10i224": Stash(11, 57), - "m01s10i225": Stash(11, 88), - "m01s10i226": Stash(11, 56), - "m01s10i227": Stash(11, 57), - "m01s10i228": Stash(11, 88), - "m01s10i229": Stash(1, 79), - "m01s10i230": Stash(1, 78), - "m01s12i002": Stash(18, 0), - "m01s12i003": Stash(19, 0), - "m01s12i004": Stash(1, 0), - "m01s12i010": Stash(1, 0), - "m01s12i012": Stash(1, 0), - "m01s12i170": Stash(1, 0), - "m01s12i171": Stash(1, 0), - "m01s12i172": Stash(1, 0), - "m01s12i173": Stash(1, 0), - "m01s12i176": Stash(1, 0), - "m01s12i177": Stash(1, 0), - "m01s12i178": Stash(1, 0), - "m01s12i179": Stash(1, 0), - "m01s12i181": Stash(1, 0), - "m01s12i182": Stash(1, 0), - "m01s12i183": Stash(1, 0), - "m01s12i184": Stash(1, 0), - "m01s12i185": Stash(18, 0), - "m01s12i186": Stash(19, 0), - "m01s12i187": Stash(1, 0), - "m01s12i189": Stash(1, 1681), - "m01s12i190": Stash(1, 1921), - "m01s12i191": Stash(1, 1689), - "m01s12i192": Stash(1, 0), - "m01s12i193": Stash(1, 0), - "m01s12i194": Stash(1, 0), - "m01s12i201": Stash(11, 40), - "m01s12i202": Stash(11, 40), - "m01s12i203": Stash(1, 0), - "m01s12i204": Stash(1, 0), - "m01s12i205": Stash(1, 0), - "m01s12i254": Stash(1, 0), - "m01s13i002": Stash(11, 56), - "m01s13i003": Stash(11, 57), - "m01s13i004": Stash(1, 19), - "m01s13i010": Stash(1, 95), - "m01s13i181": Stash(1, 16), - "m01s13i182": Stash(1, 95), - "m01s13i185": Stash(18, 56), - "m01s13i186": Stash(19, 57), - "m01s13i190": Stash(1, 0), - "m01s13i191": Stash(1, 0), - "m01s13i192": Stash(1, 0), - "m01s13i193": Stash(1, 0), - "m01s13i194": Stash(1, 0), - "m01s13i195": Stash(1, 0), - "m01s13i196": Stash(1, 0), - "m01s13i197": Stash(1, 0), - "m01s13i201": Stash(1, 0), - "m01s13i381": Stash(1, 0), - "m01s13i385": Stash(18, 0), - "m01s13i386": Stash(19, 0), - "m01s13i387": Stash(1, 0), - "m01s13i388": Stash(1, 0), - "m01s13i481": Stash(1, 0), - "m01s13i485": Stash(18, 0), - "m01s13i486": Stash(19, 0), - "m01s13i487": Stash(1, 0), - "m01s14i181": Stash(1, 0), - "m01s14i201": Stash(1, 259), - "m01s15i002": Stash(11, 56), - "m01s15i003": Stash(11, 57), - "m01s15i101": Stash(1, 1), - "m01s15i102": Stash(1, 1), - "m01s15i108": Stash(1, 8), - "m01s15i119": Stash(1, 19), - "m01s15i127": Stash(1, 27), - "m01s15i142": Stash(1, 42), - "m01s15i143": Stash(18, 56), - "m01s15i144": Stash(19, 57), - "m01s15i181": Stash(1, 16), - "m01s15i182": Stash(1, 95), - "m01s15i183": Stash(1, 0), - "m01s15i201": Stash(11, 56), - "m01s15i202": Stash(11, 57), - "m01s15i203": Stash(11, 190), - "m01s15i204": Stash(11, 8), - "m01s15i205": Stash(11, 190), - "m01s15i206": Stash(11, 1), - "m01s15i207": Stash(11, 4), - "m01s15i208": Stash(11, 8), - "m01s15i209": Stash(11, 56), - "m01s15i210": Stash(11, 57), - "m01s15i211": Stash(11, 190), - "m01s15i212": Stash(11, 56), - "m01s15i213": Stash(11, 57), - "m01s15i214": Stash(11, 82), - "m01s15i215": Stash(11, 19), - "m01s15i216": Stash(11, 19), - "m01s15i217": Stash(11, 82), - "m01s15i218": Stash(1, 83), - "m01s15i219": Stash(11, 13), - "m01s15i220": Stash(11, 58), - "m01s15i221": Stash(11, 59), - "m01s15i222": Stash(11, 40), - "m01s15i223": Stash(11, 14), - "m01s15i224": Stash(11, 53), - "m01s15i225": Stash(11, 54), - "m01s15i226": Stash(11, 95), - "m01s15i227": Stash(11, 46), - "m01s15i228": Stash(11, 47), - "m01s15i229": Stash(11, 82), - "m01s15i230": Stash(1, 19), - "m01s15i231": Stash(19, 144), - "m01s15i232": Stash(1, 145), - "m01s15i233": Stash(1, 146), - "m01s15i234": Stash(1, 147), - "m01s15i235": Stash(11, 1334), - "m01s15i236": Stash(11, 1335), - "m01s15i237": Stash(11, 63), - "m01s15i238": Stash(11, 1), - "m01s15i239": Stash(11, 1334), - "m01s15i240": Stash(11, 1334), - "m01s15i241": Stash(11, 1399), - "m01s15i242": Stash(1, 42), - "m01s15i243": Stash(18, 56), - "m01s15i244": Stash(19, 57), - "m01s15i245": Stash(18, 56), - "m01s15i246": Stash(19, 57), - "m01s15i260": Stash(1, 0), - "m01s15i261": Stash(1, 0), - "m01s15i262": Stash(1, 0), - "m01s15i263": Stash(1, 0), - "m01s15i264": Stash(1, 0), - "m01s15i265": Stash(1, 0), - "m01s15i266": Stash(1, 0), - "m01s15i270": Stash(1, 0), - "m01s15i271": Stash(1, 0), - "m01s16i004": Stash(1, 16), - "m01s16i140": Stash(1, 0), - "m01s16i141": Stash(1, 0), - "m01s16i142": Stash(1, 0), - "m01s16i143": Stash(1, 0), - "m01s16i146": Stash(1, 0), - "m01s16i147": Stash(1, 0), - "m01s16i148": Stash(1, 0), - "m01s16i149": Stash(1, 0), - "m01s16i150": Stash(1, 0), - "m01s16i151": Stash(1, 0), - "m01s16i156": Stash(1, 0), - "m01s16i157": Stash(1, 0), - "m01s16i161": Stash(1, 0), - "m01s16i162": Stash(1, 0), - "m01s16i163": Stash(1, 0), - "m01s16i164": Stash(1, 0), - "m01s16i172": Stash(1, 0), - "m01s16i173": Stash(1, 0), - "m01s16i174": Stash(1, 0), - "m01s16i181": Stash(1, 0), - "m01s16i182": Stash(1, 0), - "m01s16i183": Stash(1, 0), - "m01s16i184": Stash(1, 0), - "m01s16i192": Stash(1, 0), - "m01s16i193": Stash(1, 0), - "m01s16i194": Stash(1, 0), - "m01s16i201": Stash(1, 1), - "m01s16i202": Stash(1, 1), - "m01s16i203": Stash(1, 16), - "m01s16i204": Stash(1, 88), - "m01s16i205": Stash(1, 22), - "m01s16i206": Stash(1, 299), - "m01s16i207": Stash(1, 1929), - "m01s16i208": Stash(1, 8), - "m01s16i209": Stash(1, 4), - "m01s16i210": Stash(1, 1), - "m01s16i211": Stash(1, 8), - "m01s16i212": Stash(1, 35), - "m01s16i213": Stash(1, 35), - "m01s16i214": Stash(1, 8), - "m01s16i215": Stash(1, 16), - "m01s16i216": Stash(1, 1), - "m01s16i217": Stash(1, 4), - "m01s16i218": Stash(1, 1), - "m01s16i219": Stash(1, 189), - "m01s16i220": Stash(1, 1), - "m01s16i221": Stash(1, 199), - "m01s16i222": Stash(1, 8), - "m01s16i223": Stash(1, 189), - "m01s16i224": Stash(1, 15), - "m01s16i225": Stash(1, 1), - "m01s16i226": Stash(1, 501), - "m01s16i227": Stash(1, 502), - "m01s16i228": Stash(1, 503), - "m01s16i229": Stash(1, 504), - "m01s16i230": Stash(1, 505), - "m01s16i231": Stash(1, 506), - "m01s16i232": Stash(1, 507), - "m01s16i233": Stash(1, 508), - "m01s16i234": Stash(1, 509), - "m01s16i235": Stash(1, 510), - "m01s16i236": Stash(1, 511), - "m01s16i237": Stash(1, 512), - "m01s16i238": Stash(1, 513), - "m01s16i239": Stash(1, 514), - "m01s16i240": Stash(1, 515), - "m01s16i241": Stash(1, 516), - "m01s16i242": Stash(1, 517), - "m01s16i243": Stash(1, 518), - "m01s16i244": Stash(1, 519), - "m01s16i245": Stash(1, 520), - "m01s16i246": Stash(1, 521), - "m01s16i247": Stash(1, 522), - "m01s16i248": Stash(1, 523), - "m01s16i249": Stash(1, 524), - "m01s16i250": Stash(1, 525), - "m01s16i251": Stash(1, 526), - "m01s16i252": Stash(1, 527), - "m01s16i253": Stash(1, 528), - "m01s16i254": Stash(1, 529), - "m01s16i255": Stash(1, 1), - "m01s16i256": Stash(1, 88), - "m01s17i201": Stash(1, 1494), - "m01s17i202": Stash(1, 1495), - "m01s17i203": Stash(1, 1496), - "m01s17i204": Stash(1, 1497), - "m01s17i205": Stash(1, 576), - "m01s17i206": Stash(1, 0), - "m01s17i207": Stash(1, 0), - "m01s17i208": Stash(1, 0), - "m01s17i209": Stash(1, 0), - "m01s17i210": Stash(1, 0), - "m01s17i211": Stash(1, 0), - "m01s17i212": Stash(1, 0), - "m01s17i213": Stash(1, 0), - "m01s17i214": Stash(1, 0), - "m01s17i215": Stash(1, 0), - "m01s17i216": Stash(1, 0), - "m01s17i217": Stash(1, 0), - "m01s17i218": Stash(1, 0), - "m01s17i219": Stash(1, 0), - "m01s17i220": Stash(1, 2020), - "m01s17i221": Stash(1, 2021), - "m01s17i222": Stash(1, 2022), - "m01s17i223": Stash(1, 2023), - "m01s17i224": Stash(1, 2024), - "m01s17i225": Stash(1, 2025), - "m01s17i226": Stash(1, 2026), - "m01s17i227": Stash(1, 2027), - "m01s17i228": Stash(1, 2028), - "m01s17i229": Stash(1, 2029), - "m01s17i230": Stash(1, 2030), - "m01s17i231": Stash(1, 2031), - "m01s17i232": Stash(1, 2032), - "m01s17i233": Stash(1, 2033), - "m01s17i234": Stash(1, 2034), - "m01s17i235": Stash(1, 2035), - "m01s17i236": Stash(1, 2036), - "m01s17i237": Stash(1, 2037), - "m01s17i240": Stash(1, 0), - "m01s17i241": Stash(1, 0), - "m01s17i242": Stash(1, 0), - "m01s17i257": Stash(1, 1645), - "m01s18i001": Stash(1, 1929), - "m01s18i002": Stash(11, 56), - "m01s18i003": Stash(11, 57), - "m01s18i004": Stash(1, 19), - "m01s18i010": Stash(1, 95), - "m01s18i201": Stash(1, 290), - "m01s18i202": Stash(1, 291), - "m01s18i203": Stash(11, 292), - "m01s18i204": Stash(1, 294), - "m01s18i205": Stash(1, 295), - "m01s18i209": Stash(1, 288), - "m01s18i211": Stash(1, 303), - "m01s18i212": Stash(1, 304), - "m01s18i213": Stash(11, 305), - "m01s18i214": Stash(1, 309), - "m01s18i215": Stash(1, 310), - "m01s18i219": Stash(1, 289), - "m01s18i223": Stash(11, 306), - "m01s18i231": Stash(1, 304), - "m01s18i241": Stash(11, 305), - "m01s18i242": Stash(11, 305), - "m01s18i251": Stash(11, 306), - "m01s18i252": Stash(11, 306), - "m01s18i261": Stash(1, 303), - "m01s18i262": Stash(1, 304), - "m01s18i271": Stash(1, 24), - "m01s18i272": Stash(1, 304), - "m01s19i001": Stash(2, 1512), - "m01s19i002": Stash(2, 1513), - "m01s19i003": Stash(2, 1514), - "m01s19i004": Stash(2, 1515), - "m01s19i005": Stash(2, 1516), - "m01s19i006": Stash(2, 1500), - "m01s19i007": Stash(2, 1392), - "m01s19i008": Stash(2, 1500), - "m01s19i009": Stash(2, 1398), - "m01s19i010": Stash(2, 1502), - "m01s19i011": Stash(2, 1503), - "m01s19i012": Stash(2, 1394), - "m01s19i013": Stash(2, 1391), - "m01s19i014": Stash(2, 1392), - "m01s19i015": Stash(2, 1393), - "m01s19i016": Stash(2, 1397), - "m01s19i017": Stash(2, 1503), - "m01s19i018": Stash(2, 1503), - "m01s19i019": Stash(2, 1503), - "m01s19i020": Stash(2, 1503), - "m01s19i021": Stash(2, 1397), - "m01s19i022": Stash(2, 1397), - "m01s19i023": Stash(2, 1397), - "m01s19i024": Stash(2, 1397), - "m01s19i025": Stash(2, 1512), - "m01s19i026": Stash(2, 1513), - "m01s19i027": Stash(2, 1512), - "m01s19i028": Stash(2, 1513), - "m01s19i029": Stash(2, 1512), - "m01s19i030": Stash(2, 1513), - "m01s19i031": Stash(2, 1394), - "m01s19i032": Stash(2, 1397), - "m01s19i033": Stash(2, 1397), - "m01s19i034": Stash(2, 1397), - "m01s19i035": Stash(2, 1515), - "m01s19i036": Stash(2, 1516), - "m01s19i037": Stash(2, 1516), - "m01s19i038": Stash(2, 1516), - "m01s19i039": Stash(2, 1516), - "m01s19i040": Stash(2, 1516), - "m01s19i041": Stash(2, 1516), - "m01s19i042": Stash(2, 1516), - "m01s20i001": Stash(1, 2), - "m01s20i002": Stash(1, 2), - "m01s20i003": Stash(1, 50), - "m01s20i004": Stash(1, 50), - "m01s20i005": Stash(1, 74), - "m01s20i006": Stash(1, 73), - "m01s20i007": Stash(1, 1578), - "m01s20i012": Stash(1, 34), - "m01s20i013": Stash(1, 1577), - "m01s20i014": Stash(1, 1564), - "m01s20i015": Stash(1, 1565), - "m01s20i016": Stash(1, 1690), - "m01s20i017": Stash(1, 1690), - "m01s20i018": Stash(1, 8), - "m01s20i020": Stash(18, 56), - "m01s20i021": Stash(19, 57), - "m01s20i022": Stash(1, 8), - "m01s20i023": Stash(1, 4), - "m01s20i024": Stash(1, 8), - "m01s20i025": Stash(1, 16), - "m01s20i026": Stash(1, 1), - "m01s20i027": Stash(1, 4), - "m01s20i028": Stash(1, 191), - "m01s20i029": Stash(1, 35), - "m01s20i030": Stash(1, 35), - "m01s20i031": Stash(1, 189), - "m01s20i032": Stash(1, 89), - "m01s20i033": Stash(1, 1), - "m01s20i034": Stash(1, 8), - "m01s20i035": Stash(1, 4), - "m01s20i036": Stash(1, 1), - "m01s20i037": Stash(1, 8), - "m01s20i038": Stash(1, 4), - "m01s20i039": Stash(1, 4), - "m01s20i040": Stash(1, 4), - "m01s20i041": Stash(11, 4), - "m01s20i042": Stash(11, 4), - "m01s20i043": Stash(11, 1981), - "m01s20i044": Stash(11, 1982), - "m01s20i045": Stash(11, 1983), - "m01s20i046": Stash(11, 1984), - "m01s20i047": Stash(11, 1985), - "m01s20i048": Stash(11, 1986), - "m01s20i049": Stash(11, 1987), - "m01s20i050": Stash(11, 1988), - "m01s20i051": Stash(11, 1989), - "m01s20i052": Stash(11, 1990), - "m01s20i053": Stash(11, 1991), - "m01s20i054": Stash(11, 1992), - "m01s20i055": Stash(11, 1993), - "m01s20i056": Stash(11, 1994), - "m01s20i057": Stash(11, 1995), - "m01s20i058": Stash(11, 1643), - "m01s20i059": Stash(11, 1644), - "m01s20i060": Stash(11, 1114), - "m01s20i061": Stash(1, 1), - "m01s20i062": Stash(1, 8), - "m01s20i063": Stash(1, 4), - "m01s20i064": Stash(1, 8), - "m01s20i065": Stash(1, 16), - "m01s20i066": Stash(1, 1), - "m01s20i067": Stash(1, 4), - "m01s20i068": Stash(1, 99), - "m01s20i069": Stash(1, 90), - "m01s20i070": Stash(11, 1649), - "m01s20i071": Stash(11, 1650), - "m01s21i001": Stash(1, 8), - "m01s21i002": Stash(11, 56), - "m01s21i003": Stash(11, 57), - "m01s21i004": Stash(1, 19), - "m01s21i010": Stash(1, 95), - "m01s21i013": Stash(1, 34), - "m01s21i014": Stash(1, 222), - "m01s21i015": Stash(1, 223), - "m01s21i016": Stash(1, 219), - "m01s21i023": Stash(1, 93), - "m01s21i024": Stash(1, 16), - "m01s21i025": Stash(1, 5), - "m01s21i026": Stash(1, 324), - "m01s21i028": Stash(3, 701), - "m01s21i029": Stash(3, 702), - "m01s21i031": Stash(3, 37), - "m01s21i032": Stash(3, 687), - "m01s21i061": Stash(1, 501), - "m01s21i062": Stash(1, 502), - "m01s21i063": Stash(1, 503), - "m01s21i064": Stash(1, 504), - "m01s21i065": Stash(1, 505), - "m01s21i066": Stash(1, 506), - "m01s21i067": Stash(1, 507), - "m01s21i068": Stash(1, 508), - "m01s21i069": Stash(1, 509), - "m01s21i070": Stash(1, 510), - "m01s21i071": Stash(1, 511), - "m01s21i072": Stash(1, 512), - "m01s21i073": Stash(1, 513), - "m01s21i074": Stash(1, 514), - "m01s21i075": Stash(1, 515), - "m01s21i076": Stash(1, 516), - "m01s21i077": Stash(1, 517), - "m01s21i078": Stash(1, 518), - "m01s21i079": Stash(1, 519), - "m01s21i080": Stash(1, 520), - "m01s21i081": Stash(1, 521), - "m01s21i082": Stash(1, 522), - "m01s21i083": Stash(1, 523), - "m01s21i084": Stash(1, 524), - "m01s21i085": Stash(1, 525), - "m01s21i086": Stash(1, 526), - "m01s21i087": Stash(1, 527), - "m01s21i088": Stash(1, 528), - "m01s21i089": Stash(1, 529), - "m01s21i201": Stash(11, 56), - "m01s21i202": Stash(11, 57), - "m01s21i203": Stash(11, 40), - "m01s21i205": Stash(11, 190), - "m01s21i206": Stash(11, 1), - "m01s21i207": Stash(11, 8), - "m01s21i208": Stash(11, 56), - "m01s21i209": Stash(11, 57), - "m01s21i210": Stash(1, 1), - "m01s21i211": Stash(1, 1), - "m01s21i212": Stash(1, 16), - "m01s21i213": Stash(1, 88), - "m01s21i214": Stash(1, 22), - "m01s21i215": Stash(1, 191), - "m01s21i216": Stash(1, 1), - "m01s21i217": Stash(1, 8), - "m01s21i218": Stash(1, 8), - "m01s21i219": Stash(1, 16), - "m01s21i220": Stash(1, 1), - "m01s21i221": Stash(1, 31), - "m01s21i222": Stash(1, 32), - "m01s21i223": Stash(1, 33), - "m01s21i224": Stash(1, 8), - "m01s22i001": Stash(1, 8), - "m01s22i002": Stash(11, 56), - "m01s22i003": Stash(11, 57), - "m01s22i004": Stash(1, 19), - "m01s22i010": Stash(1, 95), - "m01s22i013": Stash(1, 34), - "m01s22i014": Stash(1, 222), - "m01s22i015": Stash(1, 223), - "m01s22i016": Stash(1, 219), - "m01s22i023": Stash(1, 93), - "m01s22i024": Stash(1, 16), - "m01s22i025": Stash(1, 5), - "m01s22i026": Stash(1, 324), - "m01s22i028": Stash(3, 701), - "m01s22i029": Stash(3, 702), - "m01s22i031": Stash(3, 37), - "m01s22i032": Stash(3, 687), - "m01s22i061": Stash(1, 501), - "m01s22i062": Stash(1, 502), - "m01s22i063": Stash(1, 503), - "m01s22i064": Stash(1, 504), - "m01s22i065": Stash(1, 505), - "m01s22i066": Stash(1, 506), - "m01s22i067": Stash(1, 507), - "m01s22i068": Stash(1, 508), - "m01s22i069": Stash(1, 509), - "m01s22i070": Stash(1, 510), - "m01s22i071": Stash(1, 511), - "m01s22i072": Stash(1, 512), - "m01s22i073": Stash(1, 513), - "m01s22i074": Stash(1, 514), - "m01s22i075": Stash(1, 515), - "m01s22i076": Stash(1, 516), - "m01s22i077": Stash(1, 517), - "m01s22i078": Stash(1, 518), - "m01s22i079": Stash(1, 519), - "m01s22i080": Stash(1, 520), - "m01s22i081": Stash(1, 521), - "m01s22i082": Stash(1, 522), - "m01s22i083": Stash(1, 523), - "m01s22i084": Stash(1, 524), - "m01s22i085": Stash(1, 525), - "m01s22i086": Stash(1, 526), - "m01s22i087": Stash(1, 527), - "m01s22i088": Stash(1, 528), - "m01s22i089": Stash(1, 529), - "m01s22i201": Stash(11, 56), - "m01s22i202": Stash(11, 57), - "m01s22i203": Stash(11, 40), - "m01s22i205": Stash(11, 190), - "m01s22i206": Stash(11, 1), - "m01s22i207": Stash(11, 8), - "m01s22i208": Stash(11, 56), - "m01s22i209": Stash(11, 57), - "m01s22i210": Stash(1, 1), - "m01s22i211": Stash(1, 1), - "m01s22i212": Stash(1, 16), - "m01s22i213": Stash(1, 88), - "m01s22i214": Stash(1, 22), - "m01s22i215": Stash(1, 191), - "m01s22i216": Stash(1, 1), - "m01s22i217": Stash(1, 8), - "m01s22i218": Stash(1, 8), - "m01s22i219": Stash(1, 16), - "m01s22i220": Stash(1, 1), - "m01s22i221": Stash(1, 31), - "m01s22i222": Stash(1, 32), - "m01s22i223": Stash(1, 33), - "m01s22i224": Stash(1, 8), - "m01s23i001": Stash(1, 8), - "m01s23i002": Stash(11, 56), - "m01s23i003": Stash(11, 57), - "m01s23i004": Stash(1, 19), - "m01s23i010": Stash(1, 95), - "m01s23i013": Stash(1, 34), - "m01s23i014": Stash(1, 222), - "m01s23i015": Stash(1, 223), - "m01s23i016": Stash(1, 219), - "m01s23i023": Stash(1, 93), - "m01s23i024": Stash(1, 16), - "m01s23i025": Stash(1, 5), - "m01s23i026": Stash(1, 324), - "m01s23i028": Stash(3, 701), - "m01s23i029": Stash(3, 702), - "m01s23i031": Stash(3, 37), - "m01s23i032": Stash(3, 687), - "m01s23i061": Stash(1, 501), - "m01s23i062": Stash(1, 502), - "m01s23i063": Stash(1, 503), - "m01s23i064": Stash(1, 504), - "m01s23i065": Stash(1, 505), - "m01s23i066": Stash(1, 506), - "m01s23i067": Stash(1, 507), - "m01s23i068": Stash(1, 508), - "m01s23i069": Stash(1, 509), - "m01s23i070": Stash(1, 510), - "m01s23i071": Stash(1, 511), - "m01s23i072": Stash(1, 512), - "m01s23i073": Stash(1, 513), - "m01s23i074": Stash(1, 514), - "m01s23i075": Stash(1, 515), - "m01s23i076": Stash(1, 516), - "m01s23i077": Stash(1, 517), - "m01s23i078": Stash(1, 518), - "m01s23i079": Stash(1, 519), - "m01s23i080": Stash(1, 520), - "m01s23i081": Stash(1, 521), - "m01s23i082": Stash(1, 522), - "m01s23i083": Stash(1, 523), - "m01s23i084": Stash(1, 524), - "m01s23i085": Stash(1, 525), - "m01s23i086": Stash(1, 526), - "m01s23i087": Stash(1, 527), - "m01s23i088": Stash(1, 528), - "m01s23i089": Stash(1, 529), - "m01s23i201": Stash(11, 56), - "m01s23i202": Stash(11, 57), - "m01s23i203": Stash(11, 40), - "m01s23i205": Stash(11, 190), - "m01s23i206": Stash(11, 1), - "m01s23i207": Stash(11, 8), - "m01s23i208": Stash(11, 56), - "m01s23i209": Stash(11, 57), - "m01s23i210": Stash(1, 1), - "m01s23i211": Stash(1, 1), - "m01s23i212": Stash(1, 16), - "m01s23i213": Stash(1, 88), - "m01s23i214": Stash(1, 22), - "m01s23i215": Stash(1, 191), - "m01s23i216": Stash(1, 1), - "m01s23i217": Stash(1, 8), - "m01s23i218": Stash(1, 8), - "m01s23i219": Stash(1, 16), - "m01s23i220": Stash(1, 1), - "m01s23i221": Stash(1, 31), - "m01s23i222": Stash(1, 32), - "m01s23i223": Stash(1, 33), - "m01s23i224": Stash(1, 8), - "m01s24i001": Stash(1, 8), - "m01s24i002": Stash(11, 56), - "m01s24i003": Stash(11, 57), - "m01s24i004": Stash(1, 19), - "m01s24i010": Stash(1, 95), - "m01s24i013": Stash(1, 34), - "m01s24i014": Stash(1, 222), - "m01s24i015": Stash(1, 223), - "m01s24i016": Stash(1, 219), - "m01s24i023": Stash(1, 93), - "m01s24i024": Stash(1, 16), - "m01s24i025": Stash(1, 5), - "m01s24i026": Stash(1, 324), - "m01s24i028": Stash(3, 701), - "m01s24i029": Stash(3, 702), - "m01s24i031": Stash(3, 37), - "m01s24i032": Stash(3, 687), - "m01s24i061": Stash(1, 501), - "m01s24i062": Stash(1, 502), - "m01s24i063": Stash(1, 503), - "m01s24i064": Stash(1, 504), - "m01s24i065": Stash(1, 505), - "m01s24i066": Stash(1, 506), - "m01s24i067": Stash(1, 507), - "m01s24i068": Stash(1, 508), - "m01s24i069": Stash(1, 509), - "m01s24i070": Stash(1, 510), - "m01s24i071": Stash(1, 511), - "m01s24i072": Stash(1, 512), - "m01s24i073": Stash(1, 513), - "m01s24i074": Stash(1, 514), - "m01s24i075": Stash(1, 515), - "m01s24i076": Stash(1, 516), - "m01s24i077": Stash(1, 517), - "m01s24i078": Stash(1, 518), - "m01s24i079": Stash(1, 519), - "m01s24i080": Stash(1, 520), - "m01s24i081": Stash(1, 521), - "m01s24i082": Stash(1, 522), - "m01s24i083": Stash(1, 523), - "m01s24i084": Stash(1, 524), - "m01s24i085": Stash(1, 525), - "m01s24i086": Stash(1, 526), - "m01s24i087": Stash(1, 527), - "m01s24i088": Stash(1, 528), - "m01s24i089": Stash(1, 529), - "m01s24i201": Stash(11, 56), - "m01s24i202": Stash(11, 57), - "m01s24i203": Stash(11, 40), - "m01s24i205": Stash(11, 190), - "m01s24i206": Stash(11, 1), - "m01s24i207": Stash(11, 8), - "m01s24i208": Stash(11, 56), - "m01s24i209": Stash(11, 57), - "m01s24i210": Stash(1, 1), - "m01s24i211": Stash(1, 1), - "m01s24i212": Stash(1, 16), - "m01s24i213": Stash(1, 88), - "m01s24i214": Stash(1, 22), - "m01s24i215": Stash(1, 191), - "m01s24i216": Stash(1, 1), - "m01s24i217": Stash(1, 8), - "m01s24i218": Stash(1, 8), - "m01s24i219": Stash(1, 16), - "m01s24i220": Stash(1, 1), - "m01s24i221": Stash(1, 31), - "m01s24i222": Stash(1, 32), - "m01s24i223": Stash(1, 33), - "m01s24i224": Stash(1, 8), - "m01s26i001": Stash(23, 1902), - "m01s26i002": Stash(23, 1904), - "m01s26i003": Stash(23, 1903), - "m01s26i004": Stash(1, 1901), - "m01s26i006": Stash(23, 1906), - "m01s30i001": Stash(1, 56), - "m01s30i002": Stash(1, 57), - "m01s30i003": Stash(1, 42), - "m01s30i004": Stash(1, 16), - "m01s30i005": Stash(1, 95), - "m01s30i006": Stash(1, 1), - "m01s30i007": Stash(1, 60), - "m01s30i008": Stash(1, 40), - "m01s30i011": Stash(1, 0), - "m01s30i012": Stash(1, 0), - "m01s30i013": Stash(1, 0), - "m01s30i014": Stash(1, 0), - "m01s30i015": Stash(1, 0), - "m01s30i016": Stash(1, 0), - "m01s30i017": Stash(1, 0), - "m01s30i018": Stash(1, 0), - "m01s30i022": Stash(1, 0), - "m01s30i023": Stash(1, 0), - "m01s30i024": Stash(1, 0), - "m01s30i025": Stash(1, 0), - "m01s30i026": Stash(1, 0), - "m01s30i027": Stash(1, 0), - "m01s30i028": Stash(1, 0), - "m01s30i033": Stash(1, 0), - "m01s30i034": Stash(1, 0), - "m01s30i035": Stash(1, 0), - "m01s30i036": Stash(1, 0), - "m01s30i037": Stash(1, 0), - "m01s30i038": Stash(1, 0), - "m01s30i044": Stash(1, 0), - "m01s30i045": Stash(1, 0), - "m01s30i046": Stash(1, 0), - "m01s30i047": Stash(1, 0), - "m01s30i048": Stash(1, 0), - "m01s30i055": Stash(1, 0), - "m01s30i056": Stash(1, 0), - "m01s30i057": Stash(1, 0), - "m01s30i058": Stash(1, 0), - "m01s30i066": Stash(1, 0), - "m01s30i067": Stash(1, 0), - "m01s30i077": Stash(1, 0), - "m01s30i078": Stash(1, 0), - "m01s30i088": Stash(1, 0), - "m01s30i101": Stash(1, 56), - "m01s30i102": Stash(1, 57), - "m01s30i103": Stash(1, 42), - "m01s30i104": Stash(1, 16), - "m01s30i105": Stash(1, 95), - "m01s30i106": Stash(1, 1), - "m01s30i107": Stash(1, 95), - "m01s30i111": Stash(1, 16), - "m01s30i112": Stash(1, 42), - "m01s30i113": Stash(1, 88), - "m01s30i114": Stash(1, 42), - "m01s30i115": Stash(1, 0), - "m01s30i171": Stash(1, 16), - "m01s30i172": Stash(1, 95), - "m01s30i173": Stash(1, 79), - "m01s30i174": Stash(1, 78), - "m01s30i175": Stash(18, 56), - "m01s30i176": Stash(19, 57), - "m01s30i177": Stash(1, 42), - "m01s30i178": Stash(1, 7), - "m01s30i181": Stash(1, 16), - "m01s30i182": Stash(1, 95), - "m01s30i183": Stash(1, 79), - "m01s30i184": Stash(1, 78), - "m01s30i185": Stash(18, 56), - "m01s30i186": Stash(19, 57), - "m01s30i187": Stash(1, 42), - "m01s30i188": Stash(1, 7), - "m01s30i189": Stash(1, 1681), - "m01s30i190": Stash(1, 1921), - "m01s30i191": Stash(1, 1689), - "m01s30i201": Stash(11, 56), - "m01s30i202": Stash(11, 57), - "m01s30i203": Stash(11, 0), - "m01s30i204": Stash(11, 16), - "m01s30i205": Stash(11, 95), - "m01s30i206": Stash(11, 88), - "m01s30i207": Stash(11, 1), - "m01s30i208": Stash(11, 40), - "m01s30i211": Stash(11, 0), - "m01s30i212": Stash(11, 0), - "m01s30i213": Stash(11, 0), - "m01s30i214": Stash(11, 0), - "m01s30i215": Stash(11, 0), - "m01s30i217": Stash(11, 0), - "m01s30i218": Stash(11, 0), - "m01s30i222": Stash(11, 0), - "m01s30i223": Stash(11, 0), - "m01s30i224": Stash(11, 0), - "m01s30i225": Stash(11, 0), - "m01s30i227": Stash(11, 0), - "m01s30i228": Stash(11, 0), - "m01s30i233": Stash(11, 0), - "m01s30i234": Stash(11, 0), - "m01s30i235": Stash(11, 0), - "m01s30i237": Stash(11, 0), - "m01s30i238": Stash(11, 0), - "m01s30i244": Stash(11, 0), - "m01s30i245": Stash(11, 0), - "m01s30i247": Stash(11, 0), - "m01s30i248": Stash(11, 0), - "m01s30i255": Stash(11, 0), - "m01s30i257": Stash(11, 0), - "m01s30i258": Stash(11, 0), - "m01s30i277": Stash(11, 0), - "m01s30i278": Stash(11, 0), - "m01s30i288": Stash(11, 0), - "m01s30i301": Stash(11, 1335), - "m01s30i302": Stash(11, 16), - "m01s30i303": Stash(11, 16), - "m01s30i310": Stash(14, 1075), - "m01s30i311": Stash(14, 1076), - "m01s30i312": Stash(14, 1077), - "m01s30i313": Stash(14, 1078), - "m01s30i314": Stash(14, 1079), - "m01s30i315": Stash(14, 1080), - "m01s30i316": Stash(14, 1081), - "m01s30i401": Stash(1, 63), - "m01s30i402": Stash(1, 63), - "m01s30i403": Stash(1, 0), - "m01s30i404": Stash(1, 0), - "m01s30i405": Stash(1, 0), - "m01s30i406": Stash(1, 0), - "m01s30i407": Stash(1, 0), - "m01s30i408": Stash(1, 0), - "m01s30i409": Stash(1, 0), - "m01s30i410": Stash(18, 1399), - "m01s30i411": Stash(1, 56), - "m01s30i412": Stash(1, 57), - "m01s30i413": Stash(1, 0), - "m01s30i414": Stash(1, 56), - "m01s30i415": Stash(1, 57), - "m01s30i416": Stash(1, 0), - "m01s30i417": Stash(1, 8), - "m01s30i418": Stash(11, 8), - "m01s30i419": Stash(1, 259), - "m01s30i420": Stash(1, 0), - "m01s30i421": Stash(1, 0), - "m01s30i422": Stash(1, 0), - "m01s30i423": Stash(1, 0), - "m01s30i424": Stash(1, 0), - "m01s30i425": Stash(1, 0), - "m01s30i426": Stash(1, 0), - "m01s30i427": Stash(1, 0), - "m01s30i428": Stash(1, 0), - "m01s30i429": Stash(1, 0), - "m01s30i430": Stash(1, 0), - "m01s30i431": Stash(1, 0), - "m01s30i432": Stash(1, 0), - "m01s30i433": Stash(1, 0), - "m01s30i434": Stash(1, 0), - "m01s30i435": Stash(1, 0), - "m01s30i436": Stash(1, 0), - "m01s30i437": Stash(1, 0), - "m01s30i438": Stash(1, 0), - "m01s30i439": Stash(1, 0), - "m01s30i440": Stash(18, 0), - "m01s30i441": Stash(19, 0), - "m01s30i442": Stash(1, 0), - "m01s30i451": Stash(1, 8), - "m01s30i452": Stash(1, 16), - "m01s30i453": Stash(1, 1), - "m01s30i454": Stash(1, 4), - "m01s31i001": Stash(29, 0), - "m01s31i002": Stash(27, 0), - "m01s31i003": Stash(28, 0), - "m01s31i004": Stash(26, 0), - "m01s31i005": Stash(26, 0), - "m01s31i006": Stash(26, 0), - "m01s31i007": Stash(26, 0), - "m01s31i008": Stash(26, 0), - "m01s31i009": Stash(26, 0), - "m01s31i010": Stash(26, 0), - "m01s31i011": Stash(27, 0), - "m01s31i012": Stash(28, 0), - "m01s31i013": Stash(26, 0), - "m01s31i014": Stash(26, 0), - "m01s31i015": Stash(26, 0), - "m01s31i016": Stash(26, 0), - "m01s31i017": Stash(26, 0), - "m01s31i018": Stash(26, 0), - "m01s31i019": Stash(26, 0), - "m01s31i020": Stash(26, 0), - "m01s31i023": Stash(26, 0), - "m01s31i024": Stash(26, 0), - "m01s31i025": Stash(26, 0), - "m01s31i026": Stash(26, 0), - "m01s31i027": Stash(26, 0), - "m01s31i028": Stash(26, 0), - "m01s31i029": Stash(26, 0), - "m01s31i030": Stash(26, 0), - "m01s31i031": Stash(26, 0), - "m01s31i032": Stash(26, 0), - "m01s31i033": Stash(26, 0), - "m01s31i035": Stash(26, 0), - "m01s31i036": Stash(26, 0), - "m01s31i037": Stash(26, 0), - "m01s31i038": Stash(26, 0), - "m01s31i039": Stash(26, 0), - "m01s31i040": Stash(26, 0), - "m01s31i041": Stash(26, 0), - "m01s31i042": Stash(26, 0), - "m01s31i043": Stash(26, 0), - "m01s31i044": Stash(26, 0), - "m01s31i045": Stash(26, 0), - "m01s31i046": Stash(26, 0), - "m01s31i257": Stash(27, 0), - "m01s31i258": Stash(28, 0), - "m01s31i259": Stash(26, 0), - "m01s31i260": Stash(26, 0), - "m01s31i261": Stash(26, 0), - "m01s31i262": Stash(26, 0), - "m01s31i263": Stash(26, 0), - "m01s31i264": Stash(26, 0), - "m01s31i265": Stash(26, 0), - "m01s31i266": Stash(27, 0), - "m01s31i267": Stash(28, 0), - "m01s31i268": Stash(26, 0), - "m01s31i269": Stash(26, 0), - "m01s31i270": Stash(26, 0), - "m01s31i271": Stash(26, 0), - "m01s31i272": Stash(26, 0), - "m01s31i273": Stash(26, 0), - "m01s31i274": Stash(26, 0), - "m01s31i275": Stash(26, 0), - "m01s31i276": Stash(26, 0), - "m01s31i277": Stash(26, 0), - "m01s31i278": Stash(26, 0), - "m01s31i279": Stash(26, 0), - "m01s31i280": Stash(26, 0), - "m01s31i281": Stash(26, 0), - "m01s31i282": Stash(26, 0), - "m01s31i283": Stash(26, 0), - "m01s31i284": Stash(26, 0), - "m01s31i285": Stash(26, 0), - "m01s31i286": Stash(26, 0), - "m01s31i288": Stash(26, 0), - "m01s31i289": Stash(26, 0), - "m01s31i290": Stash(26, 0), - "m01s31i291": Stash(26, 0), - "m01s31i292": Stash(26, 0), - "m01s31i293": Stash(26, 0), - "m01s31i294": Stash(26, 0), - "m01s31i295": Stash(26, 0), - "m01s31i296": Stash(26, 0), - "m01s31i297": Stash(26, 0), - "m01s31i298": Stash(26, 0), - "m01s31i299": Stash(26, 0), - "m01s32i001": Stash(29, 0), - "m01s32i002": Stash(27, 0), - "m01s32i003": Stash(28, 0), - "m01s32i004": Stash(26, 0), - "m01s32i005": Stash(26, 0), - "m01s32i006": Stash(26, 0), - "m01s32i007": Stash(26, 0), - "m01s32i008": Stash(26, 0), - "m01s32i009": Stash(26, 0), - "m01s32i010": Stash(26, 0), - "m01s32i011": Stash(27, 0), - "m01s32i012": Stash(28, 0), - "m01s32i013": Stash(26, 0), - "m01s32i014": Stash(26, 0), - "m01s32i015": Stash(26, 0), - "m01s32i016": Stash(26, 0), - "m01s32i017": Stash(26, 0), - "m01s32i018": Stash(26, 0), - "m01s32i019": Stash(26, 0), - "m01s32i020": Stash(26, 0), - "m01s32i021": Stash(26, 0), - "m01s32i022": Stash(26, 0), - "m01s32i023": Stash(26, 0), - "m01s32i024": Stash(26, 0), - "m01s32i025": Stash(26, 0), - "m01s32i026": Stash(26, 0), - "m01s32i027": Stash(26, 0), - "m01s32i028": Stash(26, 0), - "m01s32i029": Stash(26, 0), - "m01s32i030": Stash(26, 0), - "m01s32i031": Stash(26, 0), - "m01s32i032": Stash(26, 0), - "m01s32i033": Stash(26, 0), - "m01s32i035": Stash(26, 0), - "m01s32i036": Stash(26, 0), - "m01s32i037": Stash(26, 0), - "m01s32i038": Stash(26, 0), - "m01s32i039": Stash(26, 0), - "m01s32i040": Stash(26, 0), - "m01s32i041": Stash(26, 0), - "m01s32i042": Stash(26, 0), - "m01s32i043": Stash(26, 0), - "m01s32i044": Stash(26, 0), - "m01s32i045": Stash(26, 0), - "m01s32i046": Stash(26, 0), - "m01s33i001": Stash(1, 501), - "m01s33i002": Stash(1, 502), - "m01s33i003": Stash(1, 503), - "m01s33i004": Stash(1, 504), - "m01s33i005": Stash(1, 505), - "m01s33i006": Stash(1, 506), - "m01s33i007": Stash(1, 507), - "m01s33i008": Stash(1, 508), - "m01s33i009": Stash(1, 509), - "m01s33i010": Stash(1, 510), - "m01s33i011": Stash(1, 511), - "m01s33i012": Stash(1, 512), - "m01s33i013": Stash(1, 513), - "m01s33i014": Stash(1, 514), - "m01s33i015": Stash(1, 515), - "m01s33i016": Stash(1, 516), - "m01s33i017": Stash(1, 517), - "m01s33i018": Stash(1, 518), - "m01s33i019": Stash(1, 519), - "m01s33i020": Stash(1, 520), - "m01s33i021": Stash(1, 521), - "m01s33i022": Stash(1, 522), - "m01s33i023": Stash(1, 523), - "m01s33i024": Stash(1, 524), - "m01s33i025": Stash(1, 525), - "m01s33i026": Stash(1, 526), - "m01s33i027": Stash(1, 527), - "m01s33i028": Stash(1, 528), - "m01s33i029": Stash(1, 529), - "m01s33i030": Stash(1, 530), - "m01s33i031": Stash(1, 0), - "m01s33i032": Stash(1, 0), - "m01s33i033": Stash(1, 0), - "m01s33i034": Stash(1, 0), - "m01s33i035": Stash(1, 0), - "m01s33i036": Stash(1, 0), - "m01s33i037": Stash(1, 501), - "m01s33i038": Stash(1, 501), - "m01s33i039": Stash(1, 501), - "m01s33i040": Stash(1, 501), - "m01s33i041": Stash(1, 501), - "m01s33i042": Stash(1, 501), - "m01s33i043": Stash(1, 501), - "m01s33i044": Stash(1, 501), - "m01s33i045": Stash(1, 501), - "m01s33i046": Stash(1, 501), - "m01s33i047": Stash(1, 501), - "m01s33i048": Stash(1, 501), - "m01s33i049": Stash(1, 501), - "m01s33i050": Stash(1, 501), - "m01s33i051": Stash(1, 501), - "m01s33i052": Stash(1, 501), - "m01s33i053": Stash(1, 501), - "m01s33i054": Stash(1, 501), - "m01s33i055": Stash(1, 501), - "m01s33i056": Stash(1, 501), - "m01s33i057": Stash(1, 501), - "m01s33i058": Stash(1, 501), - "m01s33i059": Stash(1, 501), - "m01s33i060": Stash(1, 501), - "m01s33i061": Stash(1, 501), - "m01s33i062": Stash(1, 501), - "m01s33i063": Stash(1, 501), - "m01s33i064": Stash(1, 501), - "m01s33i065": Stash(1, 501), - "m01s33i066": Stash(1, 501), - "m01s33i067": Stash(1, 501), - "m01s33i068": Stash(1, 501), - "m01s33i069": Stash(1, 501), - "m01s33i070": Stash(1, 501), - "m01s33i071": Stash(1, 501), - "m01s33i072": Stash(1, 501), - "m01s33i073": Stash(1, 501), - "m01s33i074": Stash(1, 501), - "m01s33i075": Stash(1, 501), - "m01s33i076": Stash(1, 501), - "m01s33i077": Stash(1, 501), - "m01s33i078": Stash(1, 501), - "m01s33i079": Stash(1, 501), - "m01s33i080": Stash(1, 501), - "m01s33i081": Stash(1, 501), - "m01s33i082": Stash(1, 501), - "m01s33i083": Stash(1, 501), - "m01s33i084": Stash(1, 501), - "m01s33i085": Stash(1, 501), - "m01s33i086": Stash(1, 501), - "m01s33i087": Stash(1, 501), - "m01s33i088": Stash(1, 501), - "m01s33i089": Stash(1, 501), - "m01s33i090": Stash(1, 501), - "m01s33i091": Stash(1, 501), - "m01s33i092": Stash(1, 501), - "m01s33i093": Stash(1, 501), - "m01s33i094": Stash(1, 501), - "m01s33i095": Stash(1, 501), - "m01s33i096": Stash(1, 501), - "m01s33i097": Stash(1, 501), - "m01s33i098": Stash(1, 501), - "m01s33i099": Stash(1, 501), - "m01s33i100": Stash(1, 501), - "m01s33i101": Stash(1, 501), - "m01s33i102": Stash(1, 501), - "m01s33i103": Stash(1, 501), - "m01s33i104": Stash(1, 501), - "m01s33i105": Stash(1, 501), - "m01s33i106": Stash(1, 501), - "m01s33i107": Stash(1, 501), - "m01s33i108": Stash(1, 501), - "m01s33i109": Stash(1, 501), - "m01s33i110": Stash(1, 501), - "m01s33i111": Stash(1, 501), - "m01s33i112": Stash(1, 501), - "m01s33i113": Stash(1, 501), - "m01s33i114": Stash(1, 501), - "m01s33i115": Stash(1, 501), - "m01s33i116": Stash(1, 501), - "m01s33i117": Stash(1, 501), - "m01s33i118": Stash(1, 501), - "m01s33i119": Stash(1, 501), - "m01s33i120": Stash(1, 501), - "m01s33i121": Stash(1, 501), - "m01s33i122": Stash(1, 501), - "m01s33i123": Stash(1, 501), - "m01s33i124": Stash(1, 501), - "m01s33i125": Stash(1, 501), - "m01s33i126": Stash(1, 501), - "m01s33i127": Stash(1, 501), - "m01s33i128": Stash(1, 501), - "m01s33i129": Stash(1, 501), - "m01s33i130": Stash(1, 501), - "m01s33i131": Stash(1, 501), - "m01s33i132": Stash(1, 501), - "m01s33i133": Stash(1, 501), - "m01s33i134": Stash(1, 501), - "m01s33i135": Stash(1, 501), - "m01s33i136": Stash(1, 501), - "m01s33i137": Stash(1, 501), - "m01s33i138": Stash(1, 501), - "m01s33i139": Stash(1, 501), - "m01s33i140": Stash(1, 501), - "m01s33i141": Stash(1, 501), - "m01s33i142": Stash(1, 501), - "m01s33i143": Stash(1, 501), - "m01s33i144": Stash(1, 501), - "m01s33i145": Stash(1, 501), - "m01s33i146": Stash(1, 501), - "m01s33i147": Stash(1, 501), - "m01s33i148": Stash(1, 501), - "m01s33i149": Stash(1, 501), - "m01s33i150": Stash(1, 501), - "m01s33i151": Stash(1, 581), - "m01s33i152": Stash(1, 0), - "m01s33i153": Stash(1, 0), - "m01s33i154": Stash(1, 0), - "m01s33i155": Stash(1, 0), - "m01s33i156": Stash(1, 0), - "m01s33i157": Stash(1, 0), - "m01s33i158": Stash(1, 0), - "m01s33i159": Stash(1, 0), - "m01s33i160": Stash(1, 0), - "m01s33i161": Stash(1, 0), - "m01s33i162": Stash(1, 0), - "m01s33i163": Stash(1, 0), - "m01s33i164": Stash(1, 0), - "m01s33i165": Stash(1, 0), - "m01s33i166": Stash(1, 0), - "m01s33i167": Stash(1, 667), - "m01s33i168": Stash(1, 668), - "m01s33i169": Stash(1, 669), - "m01s33i170": Stash(1, 670), - "m01s33i171": Stash(1, 671), - "m01s33i172": Stash(1, 672), - "m01s33i173": Stash(1, 673), - "m01s33i301": Stash(1, 1878), - "m01s33i302": Stash(1, 502), - "m01s33i303": Stash(1, 503), - "m01s33i304": Stash(1, 504), - "m01s33i305": Stash(1, 505), - "m01s33i306": Stash(1, 506), - "m01s33i307": Stash(1, 507), - "m01s33i308": Stash(1, 508), - "m01s33i309": Stash(1, 509), - "m01s33i310": Stash(1, 510), - "m01s33i311": Stash(1, 511), - "m01s33i312": Stash(1, 512), - "m01s33i313": Stash(1, 513), - "m01s33i314": Stash(1, 514), - "m01s33i315": Stash(1, 515), - "m01s33i316": Stash(1, 516), - "m01s33i317": Stash(1, 517), - "m01s33i318": Stash(1, 518), - "m01s33i319": Stash(1, 519), - "m01s33i320": Stash(1, 520), - "m01s33i321": Stash(1, 521), - "m01s33i322": Stash(1, 522), - "m01s33i323": Stash(1, 523), - "m01s33i324": Stash(1, 524), - "m01s33i325": Stash(1, 525), - "m01s33i326": Stash(1, 526), - "m01s33i327": Stash(1, 527), - "m01s33i328": Stash(1, 528), - "m01s33i329": Stash(1, 529), - "m01s33i330": Stash(1, 530), - "m01s33i331": Stash(1, 0), - "m01s33i332": Stash(1, 0), - "m01s33i333": Stash(1, 0), - "m01s33i334": Stash(1, 0), - "m01s33i335": Stash(1, 0), - "m01s33i336": Stash(1, 0), - "m01s33i337": Stash(1, 0), - "m01s33i338": Stash(1, 0), - "m01s33i339": Stash(1, 0), - "m01s33i340": Stash(1, 0), - "m01s33i341": Stash(1, 0), - "m01s33i342": Stash(1, 0), - "m01s33i343": Stash(1, 0), - "m01s33i344": Stash(1, 0), - "m01s33i345": Stash(1, 0), - "m01s33i346": Stash(1, 0), - "m01s33i347": Stash(1, 0), - "m01s33i348": Stash(1, 0), - "m01s33i349": Stash(1, 0), - "m01s33i350": Stash(1, 0), - "m01s33i351": Stash(1, 0), - "m01s33i352": Stash(1, 0), - "m01s33i353": Stash(1, 0), - "m01s33i354": Stash(1, 0), - "m01s33i355": Stash(1, 0), - "m01s33i356": Stash(1, 0), - "m01s33i357": Stash(1, 0), - "m01s33i358": Stash(1, 0), - "m01s33i359": Stash(1, 0), - "m01s33i360": Stash(1, 0), - "m01s33i361": Stash(1, 0), - "m01s33i362": Stash(1, 0), - "m01s33i363": Stash(1, 0), - "m01s33i364": Stash(1, 0), - "m01s33i365": Stash(1, 0), - "m01s33i366": Stash(1, 0), - "m01s33i367": Stash(1, 0), - "m01s33i368": Stash(1, 568), - "m01s33i369": Stash(1, 569), - "m01s33i370": Stash(1, 570), - "m01s33i371": Stash(1, 571), - "m01s33i372": Stash(1, 572), - "m01s33i373": Stash(1, 573), - "m01s33i374": Stash(1, 574), - "m01s33i375": Stash(1, 575), - "m01s33i376": Stash(1, 576), - "m01s33i377": Stash(1, 0), - "m01s33i378": Stash(1, 0), - "m01s33i379": Stash(1, 0), - "m01s33i380": Stash(1, 580), - "m01s33i381": Stash(1, 581), - "m01s33i382": Stash(1, 0), - "m01s33i383": Stash(1, 0), - "m01s33i384": Stash(1, 0), - "m01s33i385": Stash(1, 0), - "m01s33i386": Stash(1, 0), - "m01s33i387": Stash(1, 0), - "m01s33i388": Stash(1, 0), - "m01s33i389": Stash(1, 0), - "m01s33i390": Stash(1, 0), - "m01s33i391": Stash(1, 0), - "m01s33i392": Stash(1, 0), - "m01s33i393": Stash(1, 0), - "m01s33i394": Stash(1, 0), - "m01s33i395": Stash(1, 0), - "m01s33i396": Stash(1, 0), - "m01s33i397": Stash(1, 0), - "m01s33i398": Stash(1, 0), - "m01s33i399": Stash(1, 0), - "m01s33i400": Stash(1, 600), - "m01s33i401": Stash(1, 601), - "m01s33i402": Stash(1, 602), - "m01s33i403": Stash(1, 603), - "m01s33i404": Stash(1, 604), - "m01s33i405": Stash(1, 605), - "m01s33i406": Stash(1, 606), - "m01s33i407": Stash(1, 607), - "m01s33i408": Stash(1, 608), - "m01s33i409": Stash(1, 609), - "m01s33i410": Stash(1, 610), - "m01s33i411": Stash(1, 611), - "m01s33i412": Stash(1, 612), - "m01s33i413": Stash(1, 613), - "m01s33i414": Stash(1, 614), - "m01s33i415": Stash(1, 615), - "m01s33i416": Stash(1, 616), - "m01s33i417": Stash(1, 617), - "m01s33i418": Stash(1, 618), - "m01s33i419": Stash(1, 619), - "m01s33i420": Stash(1, 620), - "m01s33i421": Stash(1, 621), - "m01s33i422": Stash(1, 622), - "m01s33i423": Stash(1, 623), - "m01s33i424": Stash(1, 624), - "m01s33i425": Stash(1, 625), - "m01s33i426": Stash(1, 626), - "m01s33i427": Stash(1, 627), - "m01s33i428": Stash(1, 628), - "m01s33i429": Stash(1, 629), - "m01s33i430": Stash(1, 630), - "m01s33i431": Stash(1, 631), - "m01s33i432": Stash(1, 632), - "m01s33i433": Stash(1, 633), - "m01s33i434": Stash(1, 634), - "m01s33i435": Stash(1, 635), - "m01s33i436": Stash(1, 636), - "m01s33i437": Stash(1, 637), - "m01s33i438": Stash(1, 638), - "m01s33i439": Stash(1, 639), - "m01s33i440": Stash(1, 640), - "m01s33i441": Stash(1, 641), - "m01s33i442": Stash(1, 642), - "m01s33i443": Stash(1, 643), - "m01s33i444": Stash(1, 644), - "m01s33i445": Stash(1, 645), - "m01s33i446": Stash(1, 646), - "m01s33i447": Stash(1, 647), - "m01s33i448": Stash(1, 648), - "m01s33i449": Stash(1, 649), - "m01s33i450": Stash(1, 650), - "m01s33i451": Stash(1, 651), - "m01s33i452": Stash(1, 652), - "m01s33i453": Stash(1, 653), - "m01s33i454": Stash(1, 654), - "m01s33i455": Stash(1, 655), - "m01s33i456": Stash(1, 656), - "m01s33i457": Stash(1, 657), - "m01s33i458": Stash(1, 658), - "m01s33i459": Stash(1, 659), - "m01s33i460": Stash(1, 660), - "m01s33i461": Stash(1, 661), - "m01s33i462": Stash(1, 662), - "m01s33i463": Stash(1, 653), - "m01s33i464": Stash(1, 664), - "m01s33i465": Stash(1, 665), - "m01s33i466": Stash(1, 666), - "m01s33i467": Stash(1, 667), - "m01s33i468": Stash(1, 668), - "m01s33i469": Stash(1, 669), - "m01s33i470": Stash(1, 670), - "m01s33i481": Stash(1, 671), - "m01s33i482": Stash(1, 672), - "m01s33i483": Stash(1, 673), - "m01s33i484": Stash(1, 674), - "m01s33i485": Stash(1, 675), - "m01s33i486": Stash(1, 676), - "m01s33i487": Stash(1, 677), - "m01s33i488": Stash(1, 678), - "m01s33i489": Stash(1, 679), - "m01s33i490": Stash(1, 680), - "m01s33i491": Stash(1, 681), - "m01s33i492": Stash(1, 682), - "m01s33i493": Stash(1, 683), - "m01s33i494": Stash(1, 684), - "m01s33i495": Stash(1, 685), - "m01s33i496": Stash(1, 686), - "m01s33i497": Stash(1, 687), - "m01s33i498": Stash(1, 688), - "m01s33i499": Stash(1, 689), - "m01s33i500": Stash(1, 690), - "m01s33i501": Stash(1, 691), - "m01s33i502": Stash(1, 692), - "m01s33i503": Stash(1, 693), - "m01s33i504": Stash(1, 694), - "m01s33i505": Stash(1, 695), - "m01s33i506": Stash(1, 696), - "m01s34i001": Stash(1, 0), - "m01s34i002": Stash(1, 0), - "m01s34i003": Stash(1, 0), - "m01s34i004": Stash(1, 0), - "m01s34i005": Stash(1, 0), - "m01s34i006": Stash(1, 0), - "m01s34i007": Stash(1, 0), - "m01s34i008": Stash(1, 0), - "m01s34i009": Stash(1, 0), - "m01s34i010": Stash(1, 0), - "m01s34i011": Stash(1, 0), - "m01s34i012": Stash(1, 0), - "m01s34i013": Stash(1, 0), - "m01s34i014": Stash(1, 0), - "m01s34i015": Stash(1, 0), - "m01s34i016": Stash(1, 0), - "m01s34i017": Stash(1, 0), - "m01s34i018": Stash(1, 0), - "m01s34i019": Stash(1, 0), - "m01s34i020": Stash(1, 0), - "m01s34i021": Stash(1, 0), - "m01s34i022": Stash(1, 0), - "m01s34i023": Stash(1, 0), - "m01s34i024": Stash(1, 0), - "m01s34i025": Stash(1, 0), - "m01s34i026": Stash(1, 0), - "m01s34i027": Stash(1, 0), - "m01s34i028": Stash(1, 0), - "m01s34i029": Stash(1, 0), - "m01s34i030": Stash(1, 0), - "m01s34i031": Stash(1, 0), - "m01s34i032": Stash(1, 0), - "m01s34i033": Stash(1, 0), - "m01s34i034": Stash(1, 0), - "m01s34i035": Stash(1, 0), - "m01s34i036": Stash(1, 0), - "m01s34i037": Stash(1, 0), - "m01s34i038": Stash(1, 0), - "m01s34i039": Stash(1, 1861), - "m01s34i040": Stash(1, 0), - "m01s34i041": Stash(1, 0), - "m01s34i042": Stash(1, 0), - "m01s34i043": Stash(1, 0), - "m01s34i044": Stash(1, 0), - "m01s34i045": Stash(1, 0), - "m01s34i046": Stash(1, 1861), - "m01s34i047": Stash(1, 0), - "m01s34i048": Stash(1, 0), - "m01s34i049": Stash(1, 0), - "m01s34i050": Stash(1, 1861), - "m01s34i051": Stash(1, 0), - "m01s34i052": Stash(1, 0), - "m01s34i053": Stash(1, 0), - "m01s34i054": Stash(1, 0), - "m01s34i055": Stash(1, 0), - "m01s34i056": Stash(1, 0), - "m01s34i057": Stash(1, 0), - "m01s34i058": Stash(1, 0), - "m01s34i059": Stash(1, 0), - "m01s34i060": Stash(1, 0), - "m01s34i061": Stash(1, 1861), - "m01s34i062": Stash(1, 1861), - "m01s34i063": Stash(1, 1861), - "m01s34i064": Stash(1, 1861), - "m01s34i065": Stash(1, 1861), - "m01s34i066": Stash(1, 1861), - "m01s34i067": Stash(1, 1861), - "m01s34i068": Stash(1, 1861), - "m01s34i069": Stash(1, 1861), - "m01s34i070": Stash(1, 0), - "m01s34i071": Stash(1, 0), - "m01s34i072": Stash(1, 0), - "m01s34i073": Stash(1, 0), - "m01s34i074": Stash(1, 0), - "m01s34i075": Stash(1, 0), - "m01s34i076": Stash(1, 0), - "m01s34i077": Stash(1, 0), - "m01s34i078": Stash(1, 0), - "m01s34i079": Stash(1, 0), - "m01s34i080": Stash(1, 0), - "m01s34i081": Stash(1, 0), - "m01s34i082": Stash(1, 0), - "m01s34i083": Stash(1, 0), - "m01s34i084": Stash(1, 0), - "m01s34i085": Stash(1, 0), - "m01s34i086": Stash(1, 0), - "m01s34i087": Stash(1, 0), - "m01s34i088": Stash(1, 0), - "m01s34i089": Stash(1, 0), - "m01s34i090": Stash(1, 0), - "m01s34i091": Stash(1, 0), - "m01s34i092": Stash(1, 0), - "m01s34i093": Stash(1, 0), - "m01s34i094": Stash(1, 0), - "m01s34i095": Stash(1, 0), - "m01s34i096": Stash(1, 0), - "m01s34i097": Stash(1, 0), - "m01s34i098": Stash(1, 0), - "m01s34i099": Stash(1, 0), - "m01s34i100": Stash(1, 0), - "m01s34i101": Stash(1, 0), - "m01s34i102": Stash(1, 0), - "m01s34i103": Stash(1, 0), - "m01s34i104": Stash(1, 0), - "m01s34i105": Stash(1, 0), - "m01s34i106": Stash(1, 0), - "m01s34i107": Stash(1, 0), - "m01s34i108": Stash(1, 0), - "m01s34i109": Stash(1, 0), - "m01s34i110": Stash(1, 0), - "m01s34i111": Stash(1, 0), - "m01s34i112": Stash(1, 0), - "m01s34i113": Stash(1, 0), - "m01s34i114": Stash(1, 0), - "m01s34i115": Stash(1, 0), - "m01s34i116": Stash(1, 0), - "m01s34i117": Stash(1, 0), - "m01s34i118": Stash(1, 0), - "m01s34i119": Stash(1, 0), - "m01s34i120": Stash(1, 0), - "m01s34i121": Stash(1, 0), - "m01s34i122": Stash(1, 0), - "m01s34i123": Stash(1, 0), - "m01s34i124": Stash(1, 0), - "m01s34i125": Stash(1, 0), - "m01s34i126": Stash(1, 0), - "m01s34i127": Stash(1, 0), - "m01s34i128": Stash(1, 0), - "m01s34i129": Stash(1, 0), - "m01s34i130": Stash(1, 0), - "m01s34i131": Stash(1, 0), - "m01s34i132": Stash(1, 0), - "m01s34i133": Stash(1, 0), - "m01s34i134": Stash(1, 0), - "m01s34i135": Stash(1, 0), - "m01s34i136": Stash(1, 0), - "m01s34i137": Stash(1, 0), - "m01s34i138": Stash(1, 0), - "m01s34i139": Stash(1, 0), - "m01s34i140": Stash(1, 1861), - "m01s34i141": Stash(1, 1861), - "m01s34i142": Stash(1, 1861), - "m01s34i143": Stash(1, 1861), - "m01s34i144": Stash(1, 1861), - "m01s34i145": Stash(1, 1861), - "m01s34i146": Stash(1, 1861), - "m01s34i147": Stash(1, 1861), - "m01s34i148": Stash(1, 1861), - "m01s34i149": Stash(1, 0), - "m01s34i150": Stash(1, 0), - "m01s34i151": Stash(1, 1861), - "m01s34i152": Stash(1, 1861), - "m01s34i153": Stash(1, 1861), - "m01s34i154": Stash(1, 1861), - "m01s34i155": Stash(1, 1861), - "m01s34i156": Stash(1, 1861), - "m01s34i157": Stash(1, 1864), - "m01s34i158": Stash(1, 1861), - "m01s34i159": Stash(1, 158), - "m01s34i160": Stash(1, 1861), - "m01s34i161": Stash(1, 1861), - "m01s34i162": Stash(1, 1862), - "m01s34i163": Stash(1, 1862), - "m01s34i164": Stash(1, 1861), - "m01s34i165": Stash(1, 1861), - "m01s34i166": Stash(1, 1861), - "m01s34i167": Stash(1, 1861), - "m01s34i168": Stash(1, 1861), - "m01s34i169": Stash(1, 1861), - "m01s34i170": Stash(1, 1861), - "m01s34i171": Stash(1, 1861), - "m01s34i172": Stash(1, 1861), - "m01s34i173": Stash(1, 1861), - "m01s34i174": Stash(1, 1861), - "m01s34i175": Stash(1, 1861), - "m01s34i176": Stash(1, 1861), - "m01s34i177": Stash(1, 1861), - "m01s34i178": Stash(1, 1861), - "m01s34i179": Stash(1, 1861), - "m01s34i180": Stash(1, 1881), - "m01s34i181": Stash(1, 1881), - "m01s34i182": Stash(1, 1881), - "m01s34i183": Stash(1, 1881), - "m01s34i184": Stash(1, 1881), - "m01s34i185": Stash(1, 1881), - "m01s34i186": Stash(1, 1881), - "m01s34i187": Stash(1, 1881), - "m01s34i188": Stash(1, 1881), - "m01s34i189": Stash(1, 1881), - "m01s34i190": Stash(1, 1881), - "m01s34i191": Stash(1, 1881), - "m01s34i192": Stash(1, 1881), - "m01s34i193": Stash(1, 1881), - "m01s34i194": Stash(1, 1881), - "m01s34i195": Stash(1, 1881), - "m01s34i196": Stash(1, 1881), - "m01s34i197": Stash(1, 1881), - "m01s34i198": Stash(1, 1881), - "m01s34i199": Stash(1, 1881), - "m01s34i200": Stash(1, 1881), - "m01s34i201": Stash(1, 1881), - "m01s34i202": Stash(1, 1881), - "m01s34i203": Stash(1, 1881), - "m01s34i204": Stash(1, 1881), - "m01s34i205": Stash(1, 1881), - "m01s34i206": Stash(1, 1881), - "m01s34i207": Stash(1, 1881), - "m01s34i208": Stash(1, 1881), - "m01s34i209": Stash(1, 1881), - "m01s34i210": Stash(1, 1881), - "m01s34i211": Stash(1, 1881), - "m01s34i212": Stash(1, 1881), - "m01s34i213": Stash(1, 1881), - "m01s34i214": Stash(1, 1881), - "m01s34i215": Stash(1, 1881), - "m01s34i216": Stash(1, 1881), - "m01s34i217": Stash(1, 1881), - "m01s34i218": Stash(1, 1881), - "m01s34i219": Stash(1, 1881), - "m01s34i220": Stash(1, 1881), - "m01s34i221": Stash(1, 1881), - "m01s34i222": Stash(1, 1881), - "m01s34i223": Stash(1, 1881), - "m01s34i224": Stash(1, 1881), - "m01s34i225": Stash(1, 1873), - "m01s34i226": Stash(1, 1878), - "m01s34i227": Stash(1, 1873), - "m01s34i228": Stash(1, 1878), - "m01s34i231": Stash(1, 1883), - "m01s34i232": Stash(1, 1883), - "m01s34i233": Stash(1, 8), - "m01s34i234": Stash(1, 8), - "m01s34i235": Stash(1, 8), - "m01s34i236": Stash(1, 1875), - "m01s34i237": Stash(1, 1875), - "m01s34i238": Stash(1, 1875), - "m01s34i239": Stash(1, 1875), - "m01s34i240": Stash(1, 1875), - "m01s34i241": Stash(1, 1875), - "m01s34i242": Stash(1, 1875), - "m01s34i243": Stash(1, 1875), - "m01s34i244": Stash(1, 1875), - "m01s34i245": Stash(1, 1875), - "m01s34i246": Stash(1, 1875), - "m01s34i247": Stash(1, 1875), - "m01s34i248": Stash(1, 1875), - "m01s34i249": Stash(1, 1875), - "m01s34i250": Stash(1, 1875), - "m01s34i251": Stash(1, 1875), - "m01s34i252": Stash(1, 1875), - "m01s34i253": Stash(1, 1875), - "m01s34i254": Stash(1, 1875), - "m01s34i255": Stash(1, 1875), - "m01s34i256": Stash(1, 1875), - "m01s34i257": Stash(1, 1875), - "m01s34i258": Stash(1, 1875), - "m01s34i259": Stash(1, 1875), - "m01s34i260": Stash(1, 1875), - "m01s34i261": Stash(1, 1875), - "m01s34i262": Stash(1, 1875), - "m01s34i263": Stash(1, 1875), - "m01s34i264": Stash(1, 1875), - "m01s34i265": Stash(1, 1875), - "m01s34i266": Stash(1, 1875), - "m01s34i267": Stash(1, 1875), - "m01s34i268": Stash(1, 1875), - "m01s34i269": Stash(1, 1875), - "m01s34i270": Stash(1, 1875), - "m01s34i271": Stash(1, 1875), - "m01s34i272": Stash(1, 1875), - "m01s34i273": Stash(1, 1875), - "m01s34i274": Stash(1, 1875), - "m01s34i275": Stash(1, 1875), - "m01s34i276": Stash(1, 1875), - "m01s34i277": Stash(1, 1875), - "m01s34i278": Stash(1, 1875), - "m01s34i279": Stash(1, 1875), - "m01s34i280": Stash(1, 1875), - "m01s34i281": Stash(1, 1875), - "m01s34i282": Stash(1, 1875), - "m01s34i283": Stash(1, 1875), - "m01s34i284": Stash(1, 1875), - "m01s34i285": Stash(1, 1875), - "m01s34i286": Stash(1, 1875), - "m01s34i287": Stash(1, 1875), - "m01s34i288": Stash(1, 1875), - "m01s34i289": Stash(1, 1875), - "m01s34i290": Stash(1, 1875), - "m01s34i291": Stash(1, 1875), - "m01s34i292": Stash(1, 1875), - "m01s34i293": Stash(1, 1875), - "m01s34i294": Stash(1, 1875), - "m01s34i295": Stash(1, 1875), - "m01s34i296": Stash(1, 1875), - "m01s34i297": Stash(1, 1875), - "m01s34i298": Stash(1, 1875), - "m01s34i299": Stash(1, 1875), - "m01s34i300": Stash(1, 1875), - "m01s34i301": Stash(1, 1871), - "m01s34i302": Stash(1, 1871), - "m01s34i303": Stash(1, 1871), - "m01s34i304": Stash(1, 1871), - "m01s34i305": Stash(1, 1871), - "m01s34i306": Stash(1, 1871), - "m01s34i307": Stash(1, 1871), - "m01s34i308": Stash(1, 1875), - "m01s34i309": Stash(1, 1875), - "m01s34i310": Stash(1, 1875), - "m01s34i311": Stash(1, 1871), - "m01s34i312": Stash(1, 1871), - "m01s34i313": Stash(1, 1871), - "m01s34i314": Stash(1, 1871), - "m01s34i315": Stash(1, 1871), - "m01s34i316": Stash(1, 1871), - "m01s34i317": Stash(1, 1871), - "m01s34i318": Stash(1, 1875), - "m01s34i319": Stash(1, 1875), - "m01s34i320": Stash(1, 1875), - "m01s34i321": Stash(1, 1871), - "m01s34i322": Stash(1, 1871), - "m01s34i323": Stash(1, 1875), - "m01s34i324": Stash(1, 1875), - "m01s34i325": Stash(1, 1875), - "m01s34i326": Stash(1, 1875), - "m01s34i327": Stash(1, 1875), - "m01s34i328": Stash(1, 1875), - "m01s34i329": Stash(1, 1875), - "m01s34i330": Stash(1, 1875), - "m01s34i331": Stash(1, 1871), - "m01s34i332": Stash(1, 1875), - "m01s34i333": Stash(1, 1875), - "m01s34i334": Stash(1, 1875), - "m01s34i335": Stash(1, 1875), - "m01s34i336": Stash(1, 1875), - "m01s34i337": Stash(1, 1875), - "m01s34i338": Stash(1, 1875), - "m01s34i341": Stash(1, 1871), - "m01s34i342": Stash(1, 1871), - "m01s34i343": Stash(1, 1871), - "m01s34i344": Stash(1, 1871), - "m01s34i345": Stash(1, 1871), - "m01s34i346": Stash(1, 1871), - "m01s34i351": Stash(1, 1871), - "m01s34i352": Stash(1, 1871), - "m01s34i353": Stash(1, 1861), - "m01s34i354": Stash(1, 1871), - "m01s34i361": Stash(1, 1902), - "m01s34i362": Stash(1, 0), - "m01s34i363": Stash(1, 1902), - "m01s34i371": Stash(1, 1871), - "m01s34i372": Stash(1, 1871), - "m01s34i373": Stash(1, 1871), - "m01s34i374": Stash(1, 1871), - "m01s34i375": Stash(1, 1871), - "m01s34i376": Stash(1, 1871), - "m01s34i377": Stash(1, 1871), - "m01s34i378": Stash(1, 1871), - "m01s34i379": Stash(1, 1871), - "m01s34i380": Stash(1, 1875), - "m01s34i381": Stash(1, 1871), - "m01s34i382": Stash(1, 0), - "m01s34i383": Stash(1, 0), - "m01s34i384": Stash(1, 0), - "m01s34i385": Stash(1, 1875), - "m01s34i386": Stash(1, 1876), - "m01s34i391": Stash(1, 1871), - "m01s34i392": Stash(1, 1871), - "m01s34i401": Stash(1, 1871), - "m01s34i402": Stash(1, 1871), - "m01s34i403": Stash(1, 1871), - "m01s34i404": Stash(1, 1871), - "m01s34i405": Stash(1, 1875), - "m01s34i406": Stash(1, 1875), - "m01s34i407": Stash(1, 1875), - "m01s34i408": Stash(1, 1875), - "m01s34i409": Stash(1, 1875), - "m01s34i410": Stash(1, 1875), - "m01s34i411": Stash(1, 1871), - "m01s34i412": Stash(1, 1871), - "m01s34i413": Stash(1, 1871), - "m01s34i414": Stash(1, 1871), - "m01s34i415": Stash(1, 1871), - "m01s34i416": Stash(1, 1871), - "m01s34i417": Stash(1, 1871), - "m01s34i418": Stash(1, 1871), - "m01s34i419": Stash(1, 1871), - "m01s34i420": Stash(1, 1871), - "m01s34i421": Stash(1, 1871), - "m01s34i422": Stash(1, 1871), - "m01s34i423": Stash(1, 1871), - "m01s34i424": Stash(1, 1871), - "m01s34i425": Stash(1, 1871), - "m01s34i426": Stash(1, 1875), - "m01s34i427": Stash(1, 1875), - "m01s34i428": Stash(1, 1875), - "m01s34i429": Stash(1, 1875), - "m01s34i431": Stash(1, 1871), - "m01s34i432": Stash(1, 1871), - "m01s34i433": Stash(1, 1871), - "m01s34i438": Stash(1, 1875), - "m01s34i439": Stash(1, 1875), - "m01s34i440": Stash(1, 1871), - "m01s34i441": Stash(1, 1871), - "m01s34i442": Stash(1, 1871), - "m01s34i443": Stash(1, 1871), - "m01s34i444": Stash(1, 1871), - "m01s34i445": Stash(1, 1871), - "m01s34i446": Stash(1, 1871), - "m01s34i447": Stash(1, 1871), - "m01s34i448": Stash(1, 1871), - "m01s34i449": Stash(1, 1871), - "m01s34i450": Stash(1, 1871), - "m01s34i451": Stash(1, 1871), - "m01s34i452": Stash(1, 1871), - "m01s34i453": Stash(1, 1871), - "m01s34i454": Stash(1, 1871), - "m01s34i455": Stash(1, 1871), - "m01s34i456": Stash(1, 1875), - "m01s34i457": Stash(1, 1875), - "m01s34i458": Stash(1, 1875), - "m01s34i459": Stash(1, 1875), - "m01s34i460": Stash(1, 1875), - "m01s34i461": Stash(1, 1875), - "m01s34i462": Stash(1, 1875), - "m01s34i483": Stash(1, 1875), - "m01s34i484": Stash(1, 1875), - "m01s34i485": Stash(1, 1875), - "m01s34i486": Stash(1, 1875), - "m01s34i487": Stash(1, 1875), - "m01s34i488": Stash(1, 1875), - "m01s34i489": Stash(1, 1875), - "m01s34i490": Stash(1, 1875), - "m01s34i491": Stash(1, 1875), - "m01s34i492": Stash(1, 1875), - "m01s34i493": Stash(1, 1875), - "m01s34i494": Stash(1, 1875), - "m01s34i495": Stash(1, 1875), - "m01s34i496": Stash(1, 1875), - "m01s34i497": Stash(1, 1875), - "m01s34i498": Stash(1, 1875), - "m01s34i499": Stash(1, 1875), - "m01s34i500": Stash(1, 1875), - "m01s35i001": Stash(18, 56), - "m01s35i002": Stash(19, 57), - "m01s35i003": Stash(18, 318), - "m01s35i004": Stash(19, 319), - "m01s35i005": Stash(18, 318), - "m01s35i006": Stash(19, 319), - "m01s35i007": Stash(18, 318), - "m01s35i008": Stash(19, 319), - "m01s35i009": Stash(1, 63), - "m01s35i010": Stash(1, 63), - "m01s35i011": Stash(1, 2049), - "m01s35i012": Stash(1, 0), - "m01s35i013": Stash(1, 0), - "m01s35i014": Stash(1, 0), - "m01s35i015": Stash(1, 0), - "m01s35i016": Stash(1, 63), - "m01s35i017": Stash(1, 63), - "m01s35i018": Stash(1, 259), - "m01s35i019": Stash(1, 0), - "m01s35i020": Stash(1, 63), - "m01s35i021": Stash(1, 63), - "m01s35i022": Stash(1, 63), - "m01s36i001": Stash(26, 0), - "m01s36i002": Stash(26, 0), - "m01s36i003": Stash(26, 0), - "m01s36i004": Stash(26, 0), - "m01s36i005": Stash(26, 0), - "m01s36i006": Stash(26, 0), - "m01s36i007": Stash(26, 0), - "m01s36i008": Stash(26, 0), - "m01s36i009": Stash(26, 0), - "m01s36i010": Stash(26, 0), - "m01s36i011": Stash(26, 0), - "m01s36i012": Stash(26, 0), - "m01s36i013": Stash(26, 0), - "m01s36i014": Stash(26, 0), - "m01s36i015": Stash(26, 0), - "m01s36i016": Stash(26, 0), - "m01s36i017": Stash(26, 0), - "m01s36i018": Stash(26, 0), - "m01s36i019": Stash(26, 0), - "m01s36i020": Stash(26, 0), - "m01s36i021": Stash(26, 0), - "m01s36i022": Stash(26, 0), - "m01s36i023": Stash(26, 0), - "m01s36i024": Stash(26, 0), - "m01s36i025": Stash(26, 0), - "m01s36i026": Stash(26, 0), - "m01s36i027": Stash(26, 0), - "m01s36i028": Stash(26, 0), - "m01s36i029": Stash(26, 0), - "m01s36i030": Stash(26, 0), - "m01s36i031": Stash(26, 0), - "m01s36i032": Stash(26, 0), - "m01s36i033": Stash(26, 0), - "m01s36i034": Stash(26, 0), - "m01s36i035": Stash(26, 0), - "m01s36i036": Stash(26, 0), - "m01s36i037": Stash(26, 0), - "m01s36i038": Stash(26, 0), - "m01s36i039": Stash(26, 0), - "m01s36i040": Stash(26, 0), - "m01s36i041": Stash(26, 0), - "m01s36i042": Stash(26, 0), - "m01s36i043": Stash(26, 0), - "m01s36i044": Stash(26, 0), - "m01s36i045": Stash(26, 0), - "m01s36i046": Stash(26, 0), - "m01s36i047": Stash(26, 0), - "m01s36i048": Stash(26, 0), - "m01s36i049": Stash(26, 0), - "m01s36i050": Stash(26, 0), - "m01s36i051": Stash(26, 0), - "m01s36i052": Stash(26, 0), - "m01s36i053": Stash(26, 0), - "m01s36i054": Stash(26, 0), - "m01s36i055": Stash(26, 0), - "m01s36i056": Stash(26, 0), - "m01s36i057": Stash(26, 0), - "m01s36i058": Stash(26, 0), - "m01s36i059": Stash(26, 0), - "m01s36i060": Stash(26, 0), - "m01s36i061": Stash(26, 0), - "m01s36i062": Stash(26, 0), - "m01s36i063": Stash(26, 0), - "m01s36i064": Stash(26, 0), - "m01s36i065": Stash(26, 0), - "m01s36i066": Stash(26, 0), - "m01s36i067": Stash(26, 0), - "m01s36i068": Stash(26, 0), - "m01s36i069": Stash(26, 0), - "m01s36i070": Stash(26, 0), - "m01s36i071": Stash(26, 0), - "m01s36i072": Stash(26, 0), - "m01s36i073": Stash(26, 0), - "m01s36i074": Stash(26, 0), - "m01s36i075": Stash(26, 0), - "m01s36i076": Stash(26, 0), - "m01s36i077": Stash(26, 0), - "m01s36i078": Stash(26, 0), - "m01s36i079": Stash(26, 0), - "m01s36i080": Stash(26, 0), - "m01s36i081": Stash(26, 0), - "m01s36i082": Stash(26, 0), - "m01s36i083": Stash(26, 0), - "m01s36i084": Stash(26, 0), - "m01s36i085": Stash(26, 0), - "m01s36i086": Stash(26, 0), - "m01s36i087": Stash(26, 0), - "m01s36i088": Stash(26, 0), - "m01s36i089": Stash(26, 0), - "m01s36i090": Stash(26, 0), - "m01s36i091": Stash(26, 0), - "m01s36i092": Stash(26, 0), - "m01s36i093": Stash(26, 0), - "m01s36i094": Stash(26, 0), - "m01s36i095": Stash(26, 0), - "m01s36i096": Stash(26, 0), - "m01s36i097": Stash(26, 0), - "m01s36i098": Stash(26, 0), - "m01s36i099": Stash(26, 0), - "m01s36i100": Stash(26, 0), - "m01s36i101": Stash(26, 0), - "m01s36i102": Stash(26, 0), - "m01s36i103": Stash(26, 0), - "m01s36i104": Stash(26, 0), - "m01s36i105": Stash(26, 0), - "m01s36i106": Stash(26, 0), - "m01s36i107": Stash(26, 0), - "m01s36i108": Stash(26, 0), - "m01s36i109": Stash(26, 0), - "m01s36i110": Stash(26, 0), - "m01s36i111": Stash(26, 0), - "m01s36i112": Stash(26, 0), - "m01s36i113": Stash(26, 0), - "m01s36i114": Stash(26, 0), - "m01s36i115": Stash(26, 0), - "m01s36i116": Stash(26, 0), - "m01s36i117": Stash(26, 0), - "m01s36i118": Stash(26, 0), - "m01s36i119": Stash(26, 0), - "m01s36i120": Stash(26, 0), - "m01s36i121": Stash(26, 0), - "m01s36i122": Stash(26, 0), - "m01s36i123": Stash(26, 0), - "m01s36i124": Stash(26, 0), - "m01s36i125": Stash(26, 0), - "m01s36i126": Stash(26, 0), - "m01s36i127": Stash(26, 0), - "m01s36i128": Stash(26, 0), - "m01s36i129": Stash(26, 0), - "m01s36i130": Stash(26, 0), - "m01s36i131": Stash(26, 0), - "m01s36i132": Stash(26, 0), - "m01s36i133": Stash(26, 0), - "m01s36i134": Stash(26, 0), - "m01s36i135": Stash(26, 0), - "m01s36i136": Stash(26, 0), - "m01s36i137": Stash(26, 0), - "m01s36i138": Stash(26, 0), - "m01s36i139": Stash(26, 0), - "m01s36i140": Stash(26, 0), - "m01s36i141": Stash(26, 0), - "m01s36i142": Stash(26, 0), - "m01s36i143": Stash(26, 0), - "m01s36i144": Stash(26, 0), - "m01s36i145": Stash(26, 0), - "m01s36i146": Stash(26, 0), - "m01s36i147": Stash(26, 0), - "m01s36i148": Stash(26, 0), - "m01s36i149": Stash(26, 0), - "m01s36i150": Stash(26, 0), - "m01s36i257": Stash(26, 0), - "m01s36i258": Stash(26, 0), - "m01s36i259": Stash(26, 0), - "m01s36i260": Stash(26, 0), - "m01s36i261": Stash(26, 0), - "m01s36i262": Stash(26, 0), - "m01s36i263": Stash(26, 0), - "m01s36i264": Stash(26, 0), - "m01s36i265": Stash(26, 0), - "m01s36i266": Stash(26, 0), - "m01s36i267": Stash(26, 0), - "m01s36i268": Stash(26, 0), - "m01s36i269": Stash(26, 0), - "m01s36i270": Stash(26, 0), - "m01s36i271": Stash(26, 0), - "m01s36i272": Stash(26, 0), - "m01s36i273": Stash(26, 0), - "m01s36i274": Stash(26, 0), - "m01s36i275": Stash(26, 0), - "m01s36i276": Stash(26, 0), - "m01s36i277": Stash(26, 0), - "m01s36i278": Stash(26, 0), - "m01s36i279": Stash(26, 0), - "m01s36i280": Stash(26, 0), - "m01s36i281": Stash(26, 0), - "m01s36i282": Stash(26, 0), - "m01s36i283": Stash(26, 0), - "m01s36i284": Stash(26, 0), - "m01s36i285": Stash(26, 0), - "m01s36i286": Stash(26, 0), - "m01s36i287": Stash(26, 0), - "m01s36i288": Stash(26, 0), - "m01s36i289": Stash(26, 0), - "m01s36i290": Stash(26, 0), - "m01s36i291": Stash(26, 0), - "m01s36i292": Stash(26, 0), - "m01s36i293": Stash(26, 0), - "m01s36i294": Stash(26, 0), - "m01s36i295": Stash(26, 0), - "m01s36i296": Stash(26, 0), - "m01s36i297": Stash(26, 0), - "m01s36i298": Stash(26, 0), - "m01s36i299": Stash(26, 0), - "m01s36i300": Stash(26, 0), - "m01s36i301": Stash(26, 0), - "m01s36i302": Stash(26, 0), - "m01s36i303": Stash(26, 0), - "m01s36i304": Stash(26, 0), - "m01s36i305": Stash(26, 0), - "m01s36i306": Stash(26, 0), - "m01s36i307": Stash(26, 0), - "m01s36i308": Stash(26, 0), - "m01s36i309": Stash(26, 0), - "m01s36i310": Stash(26, 0), - "m01s36i311": Stash(26, 0), - "m01s36i312": Stash(26, 0), - "m01s36i313": Stash(26, 0), - "m01s36i314": Stash(26, 0), - "m01s36i315": Stash(26, 0), - "m01s36i316": Stash(26, 0), - "m01s36i317": Stash(26, 0), - "m01s36i318": Stash(26, 0), - "m01s36i319": Stash(26, 0), - "m01s36i320": Stash(26, 0), - "m01s36i321": Stash(26, 0), - "m01s36i322": Stash(26, 0), - "m01s36i323": Stash(26, 0), - "m01s36i324": Stash(26, 0), - "m01s36i325": Stash(26, 0), - "m01s36i326": Stash(26, 0), - "m01s36i327": Stash(26, 0), - "m01s36i328": Stash(26, 0), - "m01s36i329": Stash(26, 0), - "m01s36i330": Stash(26, 0), - "m01s36i331": Stash(26, 0), - "m01s36i332": Stash(26, 0), - "m01s36i333": Stash(26, 0), - "m01s36i334": Stash(26, 0), - "m01s36i335": Stash(26, 0), - "m01s36i336": Stash(26, 0), - "m01s36i337": Stash(26, 0), - "m01s36i338": Stash(26, 0), - "m01s36i339": Stash(26, 0), - "m01s36i340": Stash(26, 0), - "m01s36i341": Stash(26, 0), - "m01s36i342": Stash(26, 0), - "m01s36i343": Stash(26, 0), - "m01s36i344": Stash(26, 0), - "m01s36i345": Stash(26, 0), - "m01s36i346": Stash(26, 0), - "m01s36i347": Stash(26, 0), - "m01s36i348": Stash(26, 0), - "m01s36i349": Stash(26, 0), - "m01s36i350": Stash(26, 0), - "m01s36i351": Stash(26, 0), - "m01s36i352": Stash(26, 0), - "m01s36i353": Stash(26, 0), - "m01s36i354": Stash(26, 0), - "m01s36i355": Stash(26, 0), - "m01s36i356": Stash(26, 0), - "m01s36i357": Stash(26, 0), - "m01s36i358": Stash(26, 0), - "m01s36i359": Stash(26, 0), - "m01s36i360": Stash(26, 0), - "m01s36i361": Stash(26, 0), - "m01s36i362": Stash(26, 0), - "m01s36i363": Stash(26, 0), - "m01s36i364": Stash(26, 0), - "m01s36i365": Stash(26, 0), - "m01s36i366": Stash(26, 0), - "m01s36i367": Stash(26, 0), - "m01s36i368": Stash(26, 0), - "m01s36i369": Stash(26, 0), - "m01s36i370": Stash(26, 0), - "m01s36i371": Stash(26, 0), - "m01s36i372": Stash(26, 0), - "m01s36i373": Stash(26, 0), - "m01s36i374": Stash(26, 0), - "m01s36i375": Stash(26, 0), - "m01s36i376": Stash(26, 0), - "m01s36i377": Stash(26, 0), - "m01s36i378": Stash(26, 0), - "m01s36i379": Stash(26, 0), - "m01s36i380": Stash(26, 0), - "m01s36i381": Stash(26, 0), - "m01s36i382": Stash(26, 0), - "m01s36i383": Stash(26, 0), - "m01s36i384": Stash(26, 0), - "m01s36i385": Stash(26, 0), - "m01s36i386": Stash(26, 0), - "m01s36i387": Stash(26, 0), - "m01s36i388": Stash(26, 0), - "m01s36i389": Stash(26, 0), - "m01s36i390": Stash(26, 0), - "m01s36i391": Stash(26, 0), - "m01s36i392": Stash(26, 0), - "m01s36i393": Stash(26, 0), - "m01s36i394": Stash(26, 0), - "m01s36i395": Stash(26, 0), - "m01s36i396": Stash(26, 0), - "m01s36i397": Stash(26, 0), - "m01s36i398": Stash(26, 0), - "m01s36i399": Stash(26, 0), - "m01s36i400": Stash(26, 0), - "m01s36i401": Stash(26, 0), - "m01s36i402": Stash(26, 0), - "m01s36i403": Stash(26, 0), - "m01s36i404": Stash(26, 0), - "m01s36i405": Stash(26, 0), - "m01s36i406": Stash(26, 0), - "m01s37i001": Stash(26, 0), - "m01s37i002": Stash(26, 0), - "m01s37i003": Stash(26, 0), - "m01s37i004": Stash(26, 0), - "m01s37i005": Stash(26, 0), - "m01s37i006": Stash(26, 0), - "m01s37i007": Stash(26, 0), - "m01s37i008": Stash(26, 0), - "m01s37i009": Stash(26, 0), - "m01s37i010": Stash(26, 0), - "m01s37i011": Stash(26, 0), - "m01s37i012": Stash(26, 0), - "m01s37i013": Stash(26, 0), - "m01s37i014": Stash(26, 0), - "m01s37i015": Stash(26, 0), - "m01s37i016": Stash(26, 0), - "m01s37i017": Stash(26, 0), - "m01s37i018": Stash(26, 0), - "m01s37i019": Stash(26, 0), - "m01s37i020": Stash(26, 0), - "m01s37i021": Stash(26, 0), - "m01s37i022": Stash(26, 0), - "m01s37i023": Stash(26, 0), - "m01s37i024": Stash(26, 0), - "m01s37i025": Stash(26, 0), - "m01s37i026": Stash(26, 0), - "m01s37i027": Stash(26, 0), - "m01s37i028": Stash(26, 0), - "m01s37i029": Stash(26, 0), - "m01s37i030": Stash(26, 0), - "m01s37i031": Stash(26, 0), - "m01s37i032": Stash(26, 0), - "m01s37i033": Stash(26, 0), - "m01s37i034": Stash(26, 0), - "m01s37i035": Stash(26, 0), - "m01s37i036": Stash(26, 0), - "m01s37i037": Stash(26, 0), - "m01s37i038": Stash(26, 0), - "m01s37i039": Stash(26, 0), - "m01s37i040": Stash(26, 0), - "m01s37i041": Stash(26, 0), - "m01s37i042": Stash(26, 0), - "m01s37i043": Stash(26, 0), - "m01s37i044": Stash(26, 0), - "m01s37i045": Stash(26, 0), - "m01s37i046": Stash(26, 0), - "m01s37i047": Stash(26, 0), - "m01s37i048": Stash(26, 0), - "m01s37i049": Stash(26, 0), - "m01s37i050": Stash(26, 0), - "m01s37i051": Stash(26, 0), - "m01s37i052": Stash(26, 0), - "m01s37i053": Stash(26, 0), - "m01s37i054": Stash(26, 0), - "m01s37i055": Stash(26, 0), - "m01s37i056": Stash(26, 0), - "m01s37i057": Stash(26, 0), - "m01s37i058": Stash(26, 0), - "m01s37i059": Stash(26, 0), - "m01s37i060": Stash(26, 0), - "m01s37i061": Stash(26, 0), - "m01s37i062": Stash(26, 0), - "m01s37i063": Stash(26, 0), - "m01s37i064": Stash(26, 0), - "m01s37i065": Stash(26, 0), - "m01s37i066": Stash(26, 0), - "m01s37i067": Stash(26, 0), - "m01s37i068": Stash(26, 0), - "m01s37i069": Stash(26, 0), - "m01s37i070": Stash(26, 0), - "m01s37i071": Stash(26, 0), - "m01s37i072": Stash(26, 0), - "m01s37i073": Stash(26, 0), - "m01s37i074": Stash(26, 0), - "m01s37i075": Stash(26, 0), - "m01s37i076": Stash(26, 0), - "m01s37i077": Stash(26, 0), - "m01s37i078": Stash(26, 0), - "m01s37i079": Stash(26, 0), - "m01s37i080": Stash(26, 0), - "m01s37i081": Stash(26, 0), - "m01s37i082": Stash(26, 0), - "m01s37i083": Stash(26, 0), - "m01s37i084": Stash(26, 0), - "m01s37i085": Stash(26, 0), - "m01s37i086": Stash(26, 0), - "m01s37i087": Stash(26, 0), - "m01s37i088": Stash(26, 0), - "m01s37i089": Stash(26, 0), - "m01s37i090": Stash(26, 0), - "m01s37i091": Stash(26, 0), - "m01s37i092": Stash(26, 0), - "m01s37i093": Stash(26, 0), - "m01s37i094": Stash(26, 0), - "m01s37i095": Stash(26, 0), - "m01s37i096": Stash(26, 0), - "m01s37i097": Stash(26, 0), - "m01s37i098": Stash(26, 0), - "m01s37i099": Stash(26, 0), - "m01s37i100": Stash(26, 0), - "m01s37i101": Stash(26, 0), - "m01s37i102": Stash(26, 0), - "m01s37i103": Stash(26, 0), - "m01s37i104": Stash(26, 0), - "m01s37i105": Stash(26, 0), - "m01s37i106": Stash(26, 0), - "m01s37i107": Stash(26, 0), - "m01s37i108": Stash(26, 0), - "m01s37i109": Stash(26, 0), - "m01s37i110": Stash(26, 0), - "m01s37i111": Stash(26, 0), - "m01s37i112": Stash(26, 0), - "m01s37i113": Stash(26, 0), - "m01s37i114": Stash(26, 0), - "m01s37i115": Stash(26, 0), - "m01s37i116": Stash(26, 0), - "m01s37i117": Stash(26, 0), - "m01s37i118": Stash(26, 0), - "m01s37i119": Stash(26, 0), - "m01s37i120": Stash(26, 0), - "m01s37i121": Stash(26, 0), - "m01s37i122": Stash(26, 0), - "m01s37i123": Stash(26, 0), - "m01s37i124": Stash(26, 0), - "m01s37i125": Stash(26, 0), - "m01s37i126": Stash(26, 0), - "m01s37i127": Stash(26, 0), - "m01s37i128": Stash(26, 0), - "m01s37i129": Stash(26, 0), - "m01s37i130": Stash(26, 0), - "m01s37i131": Stash(26, 0), - "m01s37i132": Stash(26, 0), - "m01s37i133": Stash(26, 0), - "m01s37i134": Stash(26, 0), - "m01s37i135": Stash(26, 0), - "m01s37i136": Stash(26, 0), - "m01s37i137": Stash(26, 0), - "m01s37i138": Stash(26, 0), - "m01s37i139": Stash(26, 0), - "m01s37i140": Stash(26, 0), - "m01s37i141": Stash(26, 0), - "m01s37i142": Stash(26, 0), - "m01s37i143": Stash(26, 0), - "m01s37i144": Stash(26, 0), - "m01s37i145": Stash(26, 0), - "m01s37i146": Stash(26, 0), - "m01s37i147": Stash(26, 0), - "m01s37i148": Stash(26, 0), - "m01s37i149": Stash(26, 0), - "m01s37i150": Stash(26, 0), - "m01s37i257": Stash(26, 0), - "m01s37i258": Stash(26, 0), - "m01s37i259": Stash(26, 0), - "m01s37i260": Stash(26, 0), - "m01s37i261": Stash(26, 0), - "m01s37i262": Stash(26, 0), - "m01s37i263": Stash(26, 0), - "m01s37i264": Stash(26, 0), - "m01s37i265": Stash(26, 0), - "m01s37i266": Stash(26, 0), - "m01s37i267": Stash(26, 0), - "m01s37i268": Stash(26, 0), - "m01s37i269": Stash(26, 0), - "m01s37i270": Stash(26, 0), - "m01s37i271": Stash(26, 0), - "m01s37i272": Stash(26, 0), - "m01s37i273": Stash(26, 0), - "m01s37i274": Stash(26, 0), - "m01s37i275": Stash(26, 0), - "m01s37i276": Stash(26, 0), - "m01s37i277": Stash(26, 0), - "m01s37i278": Stash(26, 0), - "m01s37i279": Stash(26, 0), - "m01s37i280": Stash(26, 0), - "m01s37i281": Stash(26, 0), - "m01s37i282": Stash(26, 0), - "m01s37i283": Stash(26, 0), - "m01s37i284": Stash(26, 0), - "m01s37i285": Stash(26, 0), - "m01s37i286": Stash(26, 0), - "m01s37i287": Stash(26, 0), - "m01s37i288": Stash(26, 0), - "m01s37i289": Stash(26, 0), - "m01s37i290": Stash(26, 0), - "m01s37i291": Stash(26, 0), - "m01s37i292": Stash(26, 0), - "m01s37i293": Stash(26, 0), - "m01s37i294": Stash(26, 0), - "m01s37i295": Stash(26, 0), - "m01s37i296": Stash(26, 0), - "m01s37i297": Stash(26, 0), - "m01s37i298": Stash(26, 0), - "m01s37i299": Stash(26, 0), - "m01s37i300": Stash(26, 0), - "m01s37i301": Stash(26, 0), - "m01s37i302": Stash(26, 0), - "m01s37i303": Stash(26, 0), - "m01s37i304": Stash(26, 0), - "m01s37i305": Stash(26, 0), - "m01s37i306": Stash(26, 0), - "m01s37i307": Stash(26, 0), - "m01s37i308": Stash(26, 0), - "m01s37i309": Stash(26, 0), - "m01s37i310": Stash(26, 0), - "m01s37i311": Stash(26, 0), - "m01s37i312": Stash(26, 0), - "m01s37i313": Stash(26, 0), - "m01s37i314": Stash(26, 0), - "m01s37i315": Stash(26, 0), - "m01s37i316": Stash(26, 0), - "m01s37i317": Stash(26, 0), - "m01s37i318": Stash(26, 0), - "m01s37i319": Stash(26, 0), - "m01s37i320": Stash(26, 0), - "m01s37i321": Stash(26, 0), - "m01s37i322": Stash(26, 0), - "m01s37i323": Stash(26, 0), - "m01s37i324": Stash(26, 0), - "m01s37i325": Stash(26, 0), - "m01s37i326": Stash(26, 0), - "m01s37i327": Stash(26, 0), - "m01s37i328": Stash(26, 0), - "m01s37i329": Stash(26, 0), - "m01s37i330": Stash(26, 0), - "m01s37i331": Stash(26, 0), - "m01s37i332": Stash(26, 0), - "m01s37i333": Stash(26, 0), - "m01s37i334": Stash(26, 0), - "m01s37i335": Stash(26, 0), - "m01s37i336": Stash(26, 0), - "m01s37i337": Stash(26, 0), - "m01s37i338": Stash(26, 0), - "m01s37i339": Stash(26, 0), - "m01s37i340": Stash(26, 0), - "m01s37i341": Stash(26, 0), - "m01s37i342": Stash(26, 0), - "m01s37i343": Stash(26, 0), - "m01s37i344": Stash(26, 0), - "m01s37i345": Stash(26, 0), - "m01s37i346": Stash(26, 0), - "m01s37i347": Stash(26, 0), - "m01s37i348": Stash(26, 0), - "m01s37i349": Stash(26, 0), - "m01s37i350": Stash(26, 0), - "m01s37i351": Stash(26, 0), - "m01s37i352": Stash(26, 0), - "m01s37i353": Stash(26, 0), - "m01s37i354": Stash(26, 0), - "m01s37i355": Stash(26, 0), - "m01s37i356": Stash(26, 0), - "m01s37i357": Stash(26, 0), - "m01s37i358": Stash(26, 0), - "m01s37i359": Stash(26, 0), - "m01s37i360": Stash(26, 0), - "m01s37i361": Stash(26, 0), - "m01s37i362": Stash(26, 0), - "m01s37i363": Stash(26, 0), - "m01s37i364": Stash(26, 0), - "m01s37i365": Stash(26, 0), - "m01s37i366": Stash(26, 0), - "m01s37i367": Stash(26, 0), - "m01s37i368": Stash(26, 0), - "m01s37i369": Stash(26, 0), - "m01s37i370": Stash(26, 0), - "m01s37i371": Stash(26, 0), - "m01s37i372": Stash(26, 0), - "m01s37i373": Stash(26, 0), - "m01s37i374": Stash(26, 0), - "m01s37i375": Stash(26, 0), - "m01s37i376": Stash(26, 0), - "m01s37i377": Stash(26, 0), - "m01s37i378": Stash(26, 0), - "m01s37i379": Stash(26, 0), - "m01s37i380": Stash(26, 0), - "m01s37i381": Stash(26, 0), - "m01s37i382": Stash(26, 0), - "m01s37i383": Stash(26, 0), - "m01s37i384": Stash(26, 0), - "m01s37i385": Stash(26, 0), - "m01s37i386": Stash(26, 0), - "m01s37i387": Stash(26, 0), - "m01s37i388": Stash(26, 0), - "m01s37i389": Stash(26, 0), - "m01s37i390": Stash(26, 0), - "m01s37i391": Stash(26, 0), - "m01s37i392": Stash(26, 0), - "m01s37i393": Stash(26, 0), - "m01s37i394": Stash(26, 0), - "m01s37i395": Stash(26, 0), - "m01s37i396": Stash(26, 0), - "m01s37i397": Stash(26, 0), - "m01s37i398": Stash(26, 0), - "m01s37i399": Stash(26, 0), - "m01s37i400": Stash(26, 0), - "m01s37i401": Stash(26, 0), - "m01s37i402": Stash(26, 0), - "m01s37i403": Stash(26, 0), - "m01s37i404": Stash(26, 0), - "m01s37i405": Stash(26, 0), - "m01s37i406": Stash(26, 0), - "m01s38i001": Stash(1, 1875), - "m01s38i002": Stash(1, 1875), - "m01s38i003": Stash(1, 1875), - "m01s38i004": Stash(1, 1875), - "m01s38i005": Stash(1, 1875), - "m01s38i006": Stash(1, 1875), - "m01s38i007": Stash(1, 1875), - "m01s38i008": Stash(1, 1875), - "m01s38i009": Stash(1, 1875), - "m01s38i010": Stash(1, 1875), - "m01s38i011": Stash(1, 1875), - "m01s38i012": Stash(1, 1875), - "m01s38i013": Stash(1, 1875), - "m01s38i014": Stash(1, 1875), - "m01s38i015": Stash(1, 1875), - "m01s38i016": Stash(1, 1875), - "m01s38i017": Stash(1, 1875), - "m01s38i018": Stash(1, 1875), - "m01s38i019": Stash(1, 1875), - "m01s38i020": Stash(1, 1875), - "m01s38i021": Stash(1, 1875), - "m01s38i022": Stash(1, 1875), - "m01s38i023": Stash(1, 1875), - "m01s38i024": Stash(1, 1875), - "m01s38i025": Stash(1, 1875), - "m01s38i026": Stash(1, 1875), - "m01s38i027": Stash(1, 1875), - "m01s38i028": Stash(1, 1875), - "m01s38i029": Stash(1, 1875), - "m01s38i030": Stash(1, 1875), - "m01s38i031": Stash(1, 1875), - "m01s38i032": Stash(1, 1875), - "m01s38i033": Stash(1, 1875), - "m01s38i034": Stash(1, 1875), - "m01s38i035": Stash(1, 1875), - "m01s38i036": Stash(1, 1875), - "m01s38i037": Stash(1, 1875), - "m01s38i038": Stash(1, 1875), - "m01s38i039": Stash(1, 1875), - "m01s38i040": Stash(1, 1875), - "m01s38i041": Stash(1, 1875), - "m01s38i042": Stash(1, 1875), - "m01s38i043": Stash(1, 1875), - "m01s38i044": Stash(1, 1875), - "m01s38i045": Stash(1, 1875), - "m01s38i046": Stash(1, 1875), - "m01s38i047": Stash(1, 1875), - "m01s38i048": Stash(1, 1875), - "m01s38i049": Stash(1, 1875), - "m01s38i050": Stash(1, 1875), - "m01s38i051": Stash(1, 1875), - "m01s38i052": Stash(1, 1875), - "m01s38i053": Stash(1, 1875), - "m01s38i054": Stash(1, 1875), - "m01s38i055": Stash(1, 1875), - "m01s38i056": Stash(1, 1875), - "m01s38i057": Stash(1, 1875), - "m01s38i058": Stash(1, 1875), - "m01s38i059": Stash(1, 1875), - "m01s38i060": Stash(1, 1875), - "m01s38i061": Stash(1, 1875), - "m01s38i062": Stash(1, 1875), - "m01s38i063": Stash(1, 1875), - "m01s38i064": Stash(1, 1875), - "m01s38i065": Stash(1, 1875), - "m01s38i066": Stash(1, 1875), - "m01s38i067": Stash(1, 1875), - "m01s38i068": Stash(1, 1875), - "m01s38i069": Stash(1, 1875), - "m01s38i070": Stash(1, 1875), - "m01s38i071": Stash(1, 1875), - "m01s38i072": Stash(1, 1875), - "m01s38i073": Stash(1, 1875), - "m01s38i074": Stash(1, 1875), - "m01s38i075": Stash(1, 1875), - "m01s38i076": Stash(1, 1875), - "m01s38i077": Stash(1, 1875), - "m01s38i078": Stash(1, 1875), - "m01s38i079": Stash(1, 1875), - "m01s38i080": Stash(1, 1875), - "m01s38i081": Stash(1, 1875), - "m01s38i082": Stash(1, 1875), - "m01s38i083": Stash(1, 1875), - "m01s38i084": Stash(1, 1875), - "m01s38i085": Stash(1, 1875), - "m01s38i086": Stash(1, 1875), - "m01s38i087": Stash(1, 1875), - "m01s38i088": Stash(1, 1875), - "m01s38i089": Stash(1, 1875), - "m01s38i090": Stash(1, 1875), - "m01s38i091": Stash(1, 1875), - "m01s38i092": Stash(1, 1875), - "m01s38i093": Stash(1, 1875), - "m01s38i094": Stash(1, 1875), - "m01s38i095": Stash(1, 1875), - "m01s38i096": Stash(1, 1875), - "m01s38i097": Stash(1, 1875), - "m01s38i098": Stash(1, 1875), - "m01s38i099": Stash(1, 1875), - "m01s38i100": Stash(1, 1875), - "m01s38i101": Stash(1, 1875), - "m01s38i102": Stash(1, 1875), - "m01s38i103": Stash(1, 1875), - "m01s38i104": Stash(1, 1875), - "m01s38i105": Stash(1, 1875), - "m01s38i106": Stash(1, 1875), - "m01s38i107": Stash(1, 1875), - "m01s38i108": Stash(1, 1875), - "m01s38i109": Stash(1, 1875), - "m01s38i110": Stash(1, 1875), - "m01s38i111": Stash(1, 1875), - "m01s38i112": Stash(1, 1875), - "m01s38i113": Stash(1, 1875), - "m01s38i114": Stash(1, 1875), - "m01s38i115": Stash(1, 1875), - "m01s38i116": Stash(1, 1875), - "m01s38i117": Stash(1, 1875), - "m01s38i118": Stash(1, 1875), - "m01s38i119": Stash(1, 1875), - "m01s38i120": Stash(1, 1875), - "m01s38i121": Stash(1, 1875), - "m01s38i122": Stash(1, 1875), - "m01s38i123": Stash(1, 1875), - "m01s38i124": Stash(1, 1875), - "m01s38i125": Stash(1, 1875), - "m01s38i126": Stash(1, 1875), - "m01s38i127": Stash(1, 1875), - "m01s38i128": Stash(1, 1875), - "m01s38i129": Stash(1, 1875), - "m01s38i130": Stash(1, 1875), - "m01s38i131": Stash(1, 1875), - "m01s38i132": Stash(1, 1875), - "m01s38i133": Stash(1, 1875), - "m01s38i134": Stash(1, 1875), - "m01s38i135": Stash(1, 1875), - "m01s38i136": Stash(1, 1875), - "m01s38i137": Stash(1, 1875), - "m01s38i138": Stash(1, 1875), - "m01s38i139": Stash(1, 1875), - "m01s38i140": Stash(1, 1875), - "m01s38i141": Stash(1, 1875), - "m01s38i142": Stash(1, 1875), - "m01s38i143": Stash(1, 1875), - "m01s38i144": Stash(1, 1875), - "m01s38i145": Stash(1, 1875), - "m01s38i146": Stash(1, 1875), - "m01s38i147": Stash(1, 1875), - "m01s38i148": Stash(1, 1875), - "m01s38i149": Stash(1, 1875), - "m01s38i150": Stash(1, 1875), - "m01s38i151": Stash(1, 0), - "m01s38i152": Stash(1, 0), - "m01s38i153": Stash(1, 0), - "m01s38i154": Stash(1, 0), - "m01s38i155": Stash(1, 0), - "m01s38i156": Stash(1, 0), - "m01s38i157": Stash(1, 0), - "m01s38i158": Stash(1, 0), - "m01s38i159": Stash(1, 0), - "m01s38i160": Stash(1, 0), - "m01s38i161": Stash(1, 0), - "m01s38i162": Stash(1, 571), - "m01s38i163": Stash(1, 571), - "m01s38i164": Stash(1, 571), - "m01s38i165": Stash(1, 571), - "m01s38i166": Stash(1, 575), - "m01s38i167": Stash(1, 575), - "m01s38i168": Stash(1, 575), - "m01s38i169": Stash(1, 0), - "m01s38i170": Stash(1, 575), - "m01s38i171": Stash(1, 575), - "m01s38i172": Stash(1, 575), - "m01s38i173": Stash(1, 575), - "m01s38i174": Stash(1, 575), - "m01s38i186": Stash(1, 575), - "m01s38i187": Stash(1, 575), - "m01s38i188": Stash(1, 575), - "m01s38i189": Stash(1, 575), - "m01s38i201": Stash(1, 1870), - "m01s38i202": Stash(1, 1870), - "m01s38i203": Stash(1, 1870), - "m01s38i204": Stash(1, 1870), - "m01s38i205": Stash(1, 1870), - "m01s38i206": Stash(1, 1870), - "m01s38i207": Stash(1, 1870), - "m01s38i208": Stash(1, 1870), - "m01s38i209": Stash(1, 1870), - "m01s38i210": Stash(1, 1870), - "m01s38i211": Stash(1, 1870), - "m01s38i212": Stash(1, 1870), - "m01s38i213": Stash(1, 1870), - "m01s38i214": Stash(1, 1870), - "m01s38i215": Stash(1, 1870), - "m01s38i216": Stash(1, 1870), - "m01s38i217": Stash(1, 1870), - "m01s38i218": Stash(1, 1870), - "m01s38i219": Stash(1, 1870), - "m01s38i220": Stash(1, 1870), - "m01s38i221": Stash(1, 1870), - "m01s38i222": Stash(1, 1870), - "m01s38i223": Stash(1, 1870), - "m01s38i224": Stash(1, 1870), - "m01s38i225": Stash(1, 1870), - "m01s38i226": Stash(1, 1870), - "m01s38i227": Stash(1, 1870), - "m01s38i228": Stash(1, 1870), - "m01s38i229": Stash(1, 1870), - "m01s38i230": Stash(1, 1870), - "m01s38i231": Stash(1, 1870), - "m01s38i232": Stash(1, 1870), - "m01s38i233": Stash(1, 1870), - "m01s38i234": Stash(1, 1870), - "m01s38i235": Stash(1, 1870), - "m01s38i236": Stash(1, 1870), - "m01s38i237": Stash(1, 1870), - "m01s38i238": Stash(1, 1870), - "m01s38i239": Stash(1, 1870), - "m01s38i240": Stash(1, 1870), - "m01s38i241": Stash(1, 1870), - "m01s38i242": Stash(1, 1870), - "m01s38i243": Stash(1, 1870), - "m01s38i244": Stash(1, 1870), - "m01s38i245": Stash(1, 1870), - "m01s38i246": Stash(1, 1870), - "m01s38i247": Stash(1, 1870), - "m01s38i248": Stash(1, 1870), - "m01s38i249": Stash(1, 1870), - "m01s38i250": Stash(1, 1870), - "m01s38i251": Stash(1, 1870), - "m01s38i252": Stash(1, 1870), - "m01s38i253": Stash(1, 1870), - "m01s38i254": Stash(1, 1870), - "m01s38i255": Stash(1, 1870), - "m01s38i256": Stash(1, 1870), - "m01s38i257": Stash(1, 1870), - "m01s38i258": Stash(1, 1870), - "m01s38i259": Stash(1, 1870), - "m01s38i260": Stash(1, 1870), - "m01s38i261": Stash(1, 1870), - "m01s38i262": Stash(1, 1870), - "m01s38i263": Stash(1, 1870), - "m01s38i264": Stash(1, 1870), - "m01s38i265": Stash(1, 1870), - "m01s38i266": Stash(1, 1870), - "m01s38i267": Stash(1, 1870), - "m01s38i268": Stash(1, 1870), - "m01s38i269": Stash(1, 1870), - "m01s38i270": Stash(1, 1870), - "m01s38i271": Stash(1, 1870), - "m01s38i272": Stash(1, 1870), - "m01s38i273": Stash(1, 1870), - "m01s38i274": Stash(1, 1870), - "m01s38i275": Stash(1, 1870), - "m01s38i276": Stash(1, 1870), - "m01s38i277": Stash(1, 1870), - "m01s38i278": Stash(1, 1870), - "m01s38i279": Stash(1, 1870), - "m01s38i280": Stash(1, 1870), - "m01s38i281": Stash(1, 1870), - "m01s38i282": Stash(1, 1870), - "m01s38i283": Stash(1, 1870), - "m01s38i284": Stash(1, 1870), - "m01s38i285": Stash(1, 1870), - "m01s38i286": Stash(1, 1870), - "m01s38i287": Stash(1, 1870), - "m01s38i288": Stash(1, 1870), - "m01s38i289": Stash(1, 1870), - "m01s38i290": Stash(1, 1870), - "m01s38i291": Stash(1, 1870), - "m01s38i292": Stash(1, 1870), - "m01s38i293": Stash(1, 1870), - "m01s38i294": Stash(1, 1870), - "m01s38i295": Stash(1, 1870), - "m01s38i296": Stash(1, 1870), - "m01s38i297": Stash(1, 1870), - "m01s38i298": Stash(1, 1870), - "m01s38i299": Stash(1, 1870), - "m01s38i300": Stash(1, 1870), - "m01s38i301": Stash(1, 1870), - "m01s38i302": Stash(1, 1870), - "m01s38i303": Stash(1, 1870), - "m01s38i304": Stash(1, 1870), - "m01s38i305": Stash(1, 1870), - "m01s38i306": Stash(1, 1870), - "m01s38i307": Stash(1, 1870), - "m01s38i308": Stash(1, 1870), - "m01s38i309": Stash(1, 1870), - "m01s38i310": Stash(1, 1870), - "m01s38i311": Stash(1, 1870), - "m01s38i312": Stash(1, 1870), - "m01s38i313": Stash(1, 1870), - "m01s38i314": Stash(1, 1870), - "m01s38i315": Stash(1, 1870), - "m01s38i316": Stash(1, 1870), - "m01s38i317": Stash(1, 1870), - "m01s38i318": Stash(1, 1870), - "m01s38i319": Stash(1, 1870), - "m01s38i320": Stash(1, 1870), - "m01s38i321": Stash(1, 1870), - "m01s38i322": Stash(1, 1870), - "m01s38i323": Stash(1, 1870), - "m01s38i324": Stash(1, 1870), - "m01s38i325": Stash(1, 1870), - "m01s38i326": Stash(1, 1870), - "m01s38i327": Stash(1, 1870), - "m01s38i328": Stash(1, 1870), - "m01s38i329": Stash(1, 1870), - "m01s38i330": Stash(1, 1870), - "m01s38i331": Stash(1, 1870), - "m01s38i332": Stash(1, 1870), - "m01s38i333": Stash(1, 1870), - "m01s38i334": Stash(1, 1870), - "m01s38i335": Stash(1, 1870), - "m01s38i336": Stash(1, 1870), - "m01s38i337": Stash(1, 1870), - "m01s38i338": Stash(1, 1870), - "m01s38i339": Stash(1, 1870), - "m01s38i340": Stash(1, 1870), - "m01s38i341": Stash(1, 1870), - "m01s38i342": Stash(1, 1870), - "m01s38i343": Stash(1, 1870), - "m01s38i344": Stash(1, 1870), - "m01s38i345": Stash(1, 1870), - "m01s38i346": Stash(1, 1870), - "m01s38i347": Stash(1, 1870), - "m01s38i348": Stash(1, 1870), - "m01s38i349": Stash(1, 1870), - "m01s38i350": Stash(1, 1870), - "m01s38i351": Stash(1, 1870), - "m01s38i352": Stash(1, 1870), - "m01s38i353": Stash(1, 1870), - "m01s38i354": Stash(1, 1870), - "m01s38i355": Stash(1, 1870), - "m01s38i356": Stash(1, 1870), - "m01s38i357": Stash(1, 1870), - "m01s38i358": Stash(1, 1870), - "m01s38i359": Stash(1, 1870), - "m01s38i360": Stash(1, 1870), - "m01s38i361": Stash(1, 1870), - "m01s38i362": Stash(1, 1870), - "m01s38i363": Stash(1, 1870), - "m01s38i364": Stash(1, 1870), - "m01s38i365": Stash(1, 1870), - "m01s38i366": Stash(1, 1870), - "m01s38i367": Stash(1, 1870), - "m01s38i368": Stash(1, 1870), - "m01s38i369": Stash(1, 1870), - "m01s38i370": Stash(1, 1870), - "m01s38i371": Stash(1, 1870), - "m01s38i372": Stash(1, 1870), - "m01s38i373": Stash(1, 1870), - "m01s38i374": Stash(1, 1870), - "m01s38i375": Stash(1, 1870), - "m01s38i376": Stash(1, 1870), - "m01s38i377": Stash(1, 1870), - "m01s38i378": Stash(1, 1870), - "m01s38i379": Stash(1, 1870), - "m01s38i380": Stash(1, 1870), - "m01s38i381": Stash(1, 1870), - "m01s38i382": Stash(1, 1870), - "m01s38i383": Stash(1, 1870), - "m01s38i384": Stash(1, 1870), - "m01s38i385": Stash(1, 1870), - "m01s38i386": Stash(1, 1870), - "m01s38i387": Stash(1, 1870), - "m01s38i401": Stash(1, 0), - "m01s38i402": Stash(1, 0), - "m01s38i403": Stash(1, 0), - "m01s38i404": Stash(1, 0), - "m01s38i405": Stash(1, 0), - "m01s38i406": Stash(1, 0), - "m01s38i407": Stash(1, 0), - "m01s38i408": Stash(1, 0), - "m01s38i409": Stash(1, 0), - "m01s38i410": Stash(1, 0), - "m01s38i411": Stash(1, 0), - "m01s38i412": Stash(1, 0), - "m01s38i413": Stash(1, 0), - "m01s38i414": Stash(1, 0), - "m01s38i415": Stash(1, 0), - "m01s38i416": Stash(1, 1864), - "m01s38i417": Stash(1, 1864), - "m01s38i418": Stash(1, 1864), - "m01s38i419": Stash(1, 1864), - "m01s38i420": Stash(1, 1864), - "m01s38i421": Stash(1, 1864), - "m01s38i422": Stash(1, 1864), - "m01s38i423": Stash(1, 0), - "m01s38i424": Stash(1, 0), - "m01s38i425": Stash(1, 0), - "m01s38i426": Stash(1, 0), - "m01s38i427": Stash(1, 0), - "m01s38i428": Stash(1, 0), - "m01s38i429": Stash(1, 0), - "m01s38i430": Stash(1, 1867), - "m01s38i431": Stash(1, 1867), - "m01s38i432": Stash(1, 1867), - "m01s38i433": Stash(1, 1867), - "m01s38i434": Stash(1, 1867), - "m01s38i435": Stash(1, 1867), - "m01s38i436": Stash(1, 1867), - "m01s38i437": Stash(1, 1862), - "m01s38i438": Stash(1, 1862), - "m01s38i439": Stash(1, 1862), - "m01s38i440": Stash(1, 1862), - "m01s38i441": Stash(1, 1862), - "m01s38i442": Stash(1, 0), - "m01s38i443": Stash(1, 0), - "m01s38i444": Stash(1, 0), - "m01s38i445": Stash(1, 0), - "m01s38i446": Stash(1, 0), - "m01s38i447": Stash(1, 0), - "m01s38i448": Stash(1, 0), - "m01s38i449": Stash(1, 0), - "m01s38i450": Stash(1, 0), - "m01s38i451": Stash(1, 0), - "m01s38i452": Stash(1, 0), - "m01s38i453": Stash(1, 0), - "m01s38i454": Stash(1, 0), - "m01s38i455": Stash(1, 0), - "m01s38i456": Stash(1, 0), - "m01s38i457": Stash(1, 0), - "m01s38i458": Stash(1, 0), - "m01s38i459": Stash(1, 0), - "m01s38i460": Stash(1, 0), - "m01s38i461": Stash(1, 0), - "m01s38i462": Stash(1, 0), - "m01s38i463": Stash(1, 0), - "m01s38i464": Stash(1, 0), - "m01s38i465": Stash(1, 0), - "m01s38i466": Stash(1, 0), - "m01s38i467": Stash(1, 0), - "m01s38i468": Stash(1, 0), - "m01s38i469": Stash(1, 1862), - "m01s38i470": Stash(1, 1862), - "m01s38i471": Stash(1, 1862), - "m01s38i472": Stash(1, 1862), - "m01s38i473": Stash(1, 0), - "m01s38i474": Stash(1, 0), - "m01s38i475": Stash(1, 42), - "m01s38i476": Stash(1, 1425), - "m01s38i477": Stash(1, 1862), - "m01s38i478": Stash(1, 0), - "m01s38i479": Stash(1, 1862), - "m01s38i480": Stash(1, 0), - "m01s38i481": Stash(1, 0), - "m01s38i482": Stash(1, 0), - "m01s38i483": Stash(1, 0), - "m01s38i484": Stash(1, 1862), - "m01s39i001": Stash(1, 16), - "m01s39i002": Stash(1, 16), - "m01s39i003": Stash(1, 317), - "m01s39i004": Stash(1, 317), - "m01s39i005": Stash(1, 16), - "m01s39i006": Stash(18, 56), - "m01s39i007": Stash(18, 56), - "m01s39i008": Stash(18, 318), - "m01s39i009": Stash(18, 318), - "m01s39i010": Stash(18, 56), - "m01s39i011": Stash(19, 57), - "m01s39i012": Stash(19, 57), - "m01s39i013": Stash(19, 319), - "m01s39i014": Stash(19, 319), - "m01s39i015": Stash(19, 57), - "m01s44i001": Stash(1, 1102), - "m01s44i002": Stash(1, 1103), - "m01s44i003": Stash(1, 1104), - "m01s44i004": Stash(1, 1105), - "m01s44i005": Stash(1, 1106), - "m01s44i006": Stash(1, 1107), - "m01s44i007": Stash(1, 1108), - "m01s44i008": Stash(1, 1109), - "m01s44i009": Stash(1, 1110), - "m01s44i010": Stash(1, 1111), - "m01s44i011": Stash(1, 1136), - "m01s44i012": Stash(1, 1651), - "m01s44i013": Stash(1, 1652), - "m02s00i101": Stash(36, 601), - "m02s00i102": Stash(36, 602), - "m02s00i103": Stash(36, 801), - "m02s00i104": Stash(36, 802), - "m02s00i105": Stash(36, 803), - "m02s00i106": Stash(36, 804), - "m02s00i107": Stash(36, 805), - "m02s00i108": Stash(36, 806), - "m02s00i109": Stash(36, 807), - "m02s00i110": Stash(36, 808), - "m02s00i111": Stash(36, 809), - "m02s00i112": Stash(36, 810), - "m02s00i113": Stash(36, 811), - "m02s00i114": Stash(36, 812), - "m02s00i115": Stash(36, 813), - "m02s00i116": Stash(36, 814), - "m02s00i117": Stash(36, 815), - "m02s00i118": Stash(36, 816), - "m02s00i119": Stash(36, 817), - "m02s00i120": Stash(36, 818), - "m02s00i121": Stash(37, 701), - "m02s00i122": Stash(37, 702), - "m02s00i128": Stash(36, 943), - "m02s00i129": Stash(36, 944), - "m02s00i130": Stash(36, 611), - "m02s00i131": Stash(36, 612), - "m02s00i132": Stash(36, 613), - "m02s00i133": Stash(36, 614), - "m02s00i134": Stash(36, 608), - "m02s00i135": Stash(37, 711), - "m02s00i136": Stash(37, 712), - "m02s00i137": Stash(36, 653), - "m02s00i139": Stash(37, 733), - "m02s00i140": Stash(37, 734), - "m02s00i141": Stash(36, 688), - "m02s00i142": Stash(36, 685), - "m02s00i143": Stash(36, 684), - "m02s00i144": Stash(36, 686), - "m02s00i145": Stash(36, 0), - "m02s00i146": Stash(36, 683), - "m02s00i147": Stash(36, 687), - "m02s00i148": Stash(37, 728), - "m02s00i149": Stash(37, 729), - "m02s00i150": Stash(37, 721), - "m02s00i151": Stash(37, 722), - "m02s00i152": Stash(36, 627), - "m02s00i154": Stash(36, 866), - "m02s00i155": Stash(36, 867), - "m02s00i160": Stash(36, 659), - "m02s00i161": Stash(36, 625), - "m02s00i162": Stash(36, 626), - "m02s00i165": Stash(36, 629), - "m02s00i166": Stash(36, 631), - "m02s00i167": Stash(36, 0), - "m02s00i170": Stash(36, 698), - "m02s00i171": Stash(36, 623), - "m02s00i172": Stash(36, 624), - "m02s00i175": Stash(36, 670), - "m02s00i176": Stash(36, 670), - "m02s00i177": Stash(36, 677), - "m02s00i178": Stash(36, 678), - "m02s00i179": Stash(36, 679), - "m02s00i180": Stash(36, 650), - "m02s00i181": Stash(36, 649), - "m02s00i182": Stash(36, 0), - "m02s00i183": Stash(36, 675), - "m02s00i185": Stash(36, 671), - "m02s00i186": Stash(36, 672), - "m02s00i187": Stash(36, 687), - "m02s00i188": Stash(36, 688), - "m02s00i189": Stash(36, 689), - "m02s00i190": Stash(36, 681), - "m02s00i191": Stash(36, 682), - "m02s00i192": Stash(36, 615), - "m02s00i193": Stash(36, 616), - "m02s00i194": Stash(36, 658), - "m02s00i195": Stash(36, 609), - "m02s00i196": Stash(37, 713), - "m02s00i197": Stash(37, 714), - "m02s00i198": Stash(37, 715), - "m02s00i199": Stash(37, 716), - "m02s00i200": Stash(36, 838), - "m02s00i201": Stash(36, 839), - "m02s00i202": Stash(36, 840), - "m02s00i203": Stash(36, 841), - "m02s00i204": Stash(36, 747), - "m02s00i205": Stash(36, 748), - "m02s00i206": Stash(36, 749), - "m02s00i207": Stash(36, 0), - "m02s00i208": Stash(36, 0), - "m02s00i210": Stash(36, 800), - "m02s00i211": Stash(36, 800), - "m02s00i212": Stash(36, 800), - "m02s00i213": Stash(36, 800), - "m02s00i214": Stash(36, 800), - "m02s00i215": Stash(36, 800), - "m02s00i216": Stash(36, 800), - "m02s00i217": Stash(36, 800), - "m02s00i218": Stash(36, 800), - "m02s00i219": Stash(36, 800), - "m02s00i220": Stash(36, 800), - "m02s00i221": Stash(36, 800), - "m02s00i222": Stash(36, 1955), - "m02s00i223": Stash(36, 1953), - "m02s00i224": Stash(36, 1954), - "m02s00i225": Stash(36, 1951), - "m02s00i226": Stash(36, 1952), - "m02s00i231": Stash(41, 1037), - "m02s00i232": Stash(41, 1038), - "m02s00i233": Stash(41, 1039), - "m02s00i234": Stash(41, 1040), - "m02s00i235": Stash(41, 1041), - "m02s00i236": Stash(41, 1042), - "m02s00i237": Stash(41, 1043), - "m02s00i238": Stash(41, 1044), - "m02s00i239": Stash(41, 1045), - "m02s00i240": Stash(41, 1046), - "m02s00i285": Stash(37, 617), - "m02s00i291": Stash(36, 691), - "m02s00i292": Stash(36, 692), - "m02s00i293": Stash(36, 625), - "m02s00i294": Stash(36, 626), - "m02s00i295": Stash(36, 624), - "m02s00i296": Stash(36, 681), - "m02s00i297": Stash(36, 682), - "m02s00i298": Stash(36, 681), - "m02s00i299": Stash(36, 682), - "m02s00i331": Stash(36, 749), - "m02s00i332": Stash(36, 750), - "m02s00i333": Stash(36, 751), - "m02s30i201": Stash(41, 680), - "m02s30i202": Stash(41, 653), - "m02s30i203": Stash(41, 671), - "m02s30i204": Stash(41, 672), - "m02s30i205": Stash(41, 678), - "m02s30i206": Stash(41, 626), - "m02s30i207": Stash(41, 623), - "m02s30i208": Stash(41, 685), - "m02s30i210": Stash(41, 647), - "m02s30i211": Stash(44, 740), - "m02s30i212": Stash(44, 740), - "m02s30i213": Stash(44, 740), - "m02s30i214": Stash(44, 740), - "m02s30i215": Stash(44, 740), - "m02s30i216": Stash(44, 740), - "m02s30i217": Stash(44, 740), - "m02s30i218": Stash(44, 740), - "m02s30i219": Stash(44, 740), - "m02s30i220": Stash(44, 740), - "m02s30i221": Stash(44, 740), - "m02s30i222": Stash(44, 740), - "m02s30i223": Stash(44, 740), - "m02s30i224": Stash(44, 740), - "m02s30i225": Stash(44, 740), - "m02s30i226": Stash(44, 740), - "m02s30i227": Stash(44, 740), - "m02s30i228": Stash(44, 740), - "m02s30i229": Stash(44, 740), - "m02s30i230": Stash(44, 740), - "m02s30i231": Stash(41, 801), - "m02s30i232": Stash(41, 802), - "m02s30i233": Stash(41, 803), - "m02s30i234": Stash(41, 804), - "m02s30i235": Stash(41, 805), - "m02s30i236": Stash(41, 806), - "m02s30i237": Stash(41, 807), - "m02s30i238": Stash(41, 808), - "m02s30i239": Stash(41, 809), - "m02s30i240": Stash(41, 810), - "m02s30i241": Stash(41, 811), - "m02s30i242": Stash(41, 642), - "m02s30i243": Stash(41, 813), - "m02s30i244": Stash(41, 814), - "m02s30i245": Stash(41, 815), - "m02s30i246": Stash(42, 713), - "m02s30i247": Stash(42, 714), - "m02s30i248": Stash(41, 645), - "m02s30i249": Stash(41, 646), - "m02s30i250": Stash(41, 647), - "m02s30i251": Stash(41, 648), - "m02s30i252": Stash(41, 891), - "m02s30i253": Stash(41, 892), - "m02s30i254": Stash(41, 893), - "m02s30i255": Stash(41, 894), - "m02s30i256": Stash(41, 895), - "m02s30i257": Stash(41, 896), - "m02s30i258": Stash(41, 897), - "m02s30i259": Stash(41, 898), - "m02s30i260": Stash(41, 899), - "m02s30i261": Stash(41, 900), - "m02s30i262": Stash(41, 901), - "m02s30i263": Stash(41, 902), - "m02s30i264": Stash(41, 903), - "m02s30i265": Stash(41, 904), - "m02s30i266": Stash(41, 905), - "m02s30i267": Stash(41, 906), - "m02s30i268": Stash(41, 907), - "m02s30i269": Stash(41, 908), - "m02s30i270": Stash(41, 909), - "m02s30i271": Stash(41, 910), - "m02s30i272": Stash(41, 911), - "m02s30i273": Stash(41, 912), - "m02s30i274": Stash(41, 913), - "m02s30i275": Stash(41, 914), - "m02s30i276": Stash(41, 915), - "m02s30i277": Stash(41, 916), - "m02s30i278": Stash(41, 917), - "m02s30i279": Stash(41, 678), - "m02s30i280": Stash(41, 632), - "m02s30i281": Stash(41, 831), - "m02s30i282": Stash(41, 832), - "m02s30i283": Stash(41, 833), - "m02s30i284": Stash(41, 834), - "m02s30i285": Stash(41, 617), - "m02s30i286": Stash(42, 795), - "m02s30i287": Stash(41, 695), - "m02s30i288": Stash(42, 796), - "m02s30i289": Stash(41, 696), - "m02s30i290": Stash(42, 797), - "m02s30i291": Stash(41, 697), - "m02s30i292": Stash(41, 673), - "m02s30i293": Stash(41, 674), - "m02s30i294": Stash(41, 867), - "m02s30i296": Stash(42, 795), - "m02s30i297": Stash(41, 695), - "m02s30i298": Stash(42, 796), - "m02s30i299": Stash(41, 696), - "m02s30i301": Stash(41, 637), - "m02s30i302": Stash(42, 865), - "m02s30i303": Stash(41, 866), - "m02s30i306": Stash(41, 648), - "m02s30i307": Stash(41, 648), - "m02s30i308": Stash(41, 648), - "m02s30i309": Stash(41, 648), - "m02s30i310": Stash(41, 648), - "m02s30i311": Stash(41, 648), - "m02s30i312": Stash(41, 648), - "m02s30i313": Stash(41, 648), - "m02s30i314": Stash(41, 648), - "m02s30i315": Stash(41, 648), - "m02s30i316": Stash(41, 648), - "m02s30i317": Stash(41, 648), - "m02s30i318": Stash(41, 648), - "m02s30i319": Stash(41, 648), - "m02s30i320": Stash(42, 703), - "m02s30i321": Stash(42, 704), - "m02s30i322": Stash(41, 648), - "m02s30i323": Stash(41, 657), - "m02s30i324": Stash(41, 653), - "m02s30i325": Stash(41, 653), - "m02s30i330": Stash(41, 860), - "m02s30i331": Stash(41, 860), - "m02s30i400": Stash(41, 891), - "m02s30i401": Stash(41, 892), - "m02s30i402": Stash(41, 893), - "m02s30i403": Stash(41, 894), - "m02s30i404": Stash(41, 895), - "m02s30i405": Stash(41, 896), - "m02s30i406": Stash(41, 897), - "m02s30i410": Stash(41, 901), - "m02s30i411": Stash(41, 902), - "m02s30i412": Stash(41, 903), - "m02s30i413": Stash(41, 904), - "m02s30i414": Stash(41, 905), - "m02s30i415": Stash(41, 906), - "m02s30i416": Stash(41, 907), - "m02s30i417": Stash(41, 908), - "m02s30i418": Stash(41, 909), - "m02s30i419": Stash(41, 910), - "m02s30i420": Stash(41, 911), - "m02s30i421": Stash(41, 912), - "m02s30i422": Stash(41, 913), - "m02s30i423": Stash(41, 914), - "m02s30i424": Stash(41, 915), - "m02s30i425": Stash(41, 916), - "m02s30i426": Stash(41, 917), - "m02s30i427": Stash(41, 918), - "m02s30i428": Stash(41, 919), - "m02s30i429": Stash(41, 920), - "m02s30i430": Stash(41, 921), - "m02s30i431": Stash(41, 922), - "m02s30i432": Stash(41, 0), - "m02s30i433": Stash(41, 0), - "m02s30i434": Stash(41, 0), - "m02s30i435": Stash(41, 0), - "m02s30i436": Stash(41, 0), - "m02s30i437": Stash(41, 0), - "m02s30i438": Stash(41, 0), - "m02s30i439": Stash(41, 0), - "m02s30i440": Stash(41, 0), - "m02s30i441": Stash(41, 0), - "m02s30i442": Stash(41, 0), - "m02s30i443": Stash(41, 0), - "m02s30i444": Stash(41, 0), - "m02s30i445": Stash(41, 0), - "m02s30i446": Stash(41, 0), - "m02s30i447": Stash(41, 0), - "m02s30i448": Stash(41, 0), - "m02s30i449": Stash(41, 940), - "m02s30i450": Stash(41, 0), - "m02s30i451": Stash(41, 0), - "m02s30i452": Stash(41, 0), - "m02s30i453": Stash(41, 0), - "m02s30i454": Stash(41, 0), - "m02s30i455": Stash(41, 0), - "m02s30i456": Stash(41, 0), - "m02s30i457": Stash(41, 0), - "m02s30i458": Stash(41, 0), - "m02s30i459": Stash(41, 940), - "m02s30i460": Stash(41, 0), - "m02s30i461": Stash(41, 940), - "m02s30i462": Stash(41, 941), - "m02s30i463": Stash(41, 942), - "m02s30i464": Stash(41, 943), - "m02s30i465": Stash(41, 944), - "m02s30i466": Stash(41, 945), - "m02s30i467": Stash(41, 946), - "m02s30i468": Stash(41, 947), - "m02s30i469": Stash(41, 0), - "m02s30i470": Stash(41, 0), - "m02s30i471": Stash(41, 0), - "m02s31i201": Stash(42, 715), - "m02s31i202": Stash(41, 618), - "m02s31i211": Stash(36, 660), - "m02s31i212": Stash(36, 661), - "m02s31i213": Stash(36, 662), - "m02s31i214": Stash(36, 663), - "m02s31i215": Stash(36, 664), - "m02s31i216": Stash(36, 665), - "m02s31i217": Stash(36, 666), - "m02s31i218": Stash(36, 667), - "m02s31i219": Stash(36, 668), - "m02s31i220": Stash(36, 669), - "m02s31i285": Stash(41, 617), - "m02s32i201": Stash(41, 683), - "m02s32i202": Stash(41, 687), - "m02s32i203": Stash(41, 688), - "m02s32i204": Stash(41, 687), - "m02s32i209": Stash(42, 731), - "m02s32i210": Stash(42, 732), - "m02s32i211": Stash(41, 683), - "m02s32i212": Stash(41, 687), - "m02s32i213": Stash(41, 688), - "m02s32i214": Stash(41, 626), - "m02s32i215": Stash(41, 623), - "m02s32i216": Stash(41, 601), - "m02s32i217": Stash(41, 626), - "m02s32i218": Stash(41, 626), - "m02s32i219": Stash(42, 733), - "m02s32i220": Stash(42, 734), - "m02s32i221": Stash(42, 735), - "m02s32i222": Stash(42, 736), - "m02s32i223": Stash(41, 918), - "m02s32i224": Stash(41, 919), - "m02s32i225": Stash(41, 920), - "m02s32i226": Stash(41, 919), - "m02s32i227": Stash(41, 918), - "m02s32i228": Stash(41, 919), - "m02s32i229": Stash(41, 920), - "m02s32i230": Stash(42, 737), - "m02s32i231": Stash(42, 738), - "m02s32i232": Stash(41, 918), - "m02s32i233": Stash(41, 919), - "m02s32i234": Stash(41, 920), - "m02s32i235": Stash(41, 1959), - "m02s32i236": Stash(41, 1956), - "m02s32i237": Stash(41, 1957), - "m02s32i238": Stash(41, 1958), - "m02s32i239": Stash(41, 1956), - "m02s32i240": Stash(41, 1957), - "m02s32i241": Stash(41, 1958), - "m02s32i242": Stash(41, 1956), - "m02s32i243": Stash(41, 1957), - "m02s32i244": Stash(41, 1958), - "m02s32i245": Stash(41, 801), - "m02s32i246": Stash(41, 801), - "m02s32i247": Stash(41, 919), - "m02s32i248": Stash(41, 920), - "m02s32i249": Stash(41, 1957), - "m02s32i250": Stash(41, 1958), - "m02s32i300": Stash(41, 801), - "m02s32i301": Stash(41, 801), - "m02s32i302": Stash(42, 801), - "m02s32i303": Stash(42, 801), - "m02s32i304": Stash(42, 801), - "m02s32i305": Stash(42, 801), - "m02s32i306": Stash(42, 801), - "m02s32i307": Stash(42, 801), - "m02s32i308": Stash(42, 801), - "m02s32i309": Stash(42, 801), - "m02s35i101": Stash(36, 601), - "m02s35i102": Stash(36, 602), - "m02s35i121": Stash(37, 701), - "m02s35i122": Stash(37, 702), - "m02s35i130": Stash(36, 611), - "m02s35i134": Stash(36, 608), - "m02s35i135": Stash(37, 711), - "m02s35i136": Stash(37, 712), - "m02s35i137": Stash(36, 653), - "m02s35i201": Stash(36, 850), - "m02s35i202": Stash(36, 851), - "m02s35i203": Stash(36, 852), - "m02s35i204": Stash(36, 853), - "m02s35i205": Stash(36, 854), - "m02s35i206": Stash(37, 855), - "m02s35i211": Stash(36, 860), - "m02s35i213": Stash(36, 862), - "m02s35i214": Stash(36, 863), - "m02s35i215": Stash(36, 864), - "m02s35i221": Stash(37, 871), - "m02s35i224": Stash(37, 872), - "m02s35i225": Stash(37, 873), - "m02s35i231": Stash(37, 876), - "m02s35i234": Stash(37, 877), - "m02s35i235": Stash(37, 878), - "m02s35i241": Stash(36, 880), - "m02s35i244": Stash(36, 881), - "m02s35i245": Stash(36, 882), - "m02s35i251": Stash(36, 885), - "m02s35i254": Stash(36, 888), - "m02s35i255": Stash(36, 884), - "m02s35i281": Stash(41, 683), - "m02s35i282": Stash(41, 687), - "m02s35i283": Stash(41, 688), - "m02s35i284": Stash(41, 685), - "m02s35i285": Stash(41, 686), - "m02s35i301": Stash(41, 857), - "m02s35i302": Stash(41, 858), - "m02s35i310": Stash(41, 859), - "m02s35i323": Stash(41, 699), - "m02s41i101": Stash(36, 601), - "m02s41i102": Stash(36, 602), - "m02s41i103": Stash(36, 801), - "m02s41i104": Stash(36, 802), - "m02s41i105": Stash(36, 803), - "m02s41i106": Stash(36, 804), - "m02s41i107": Stash(36, 805), - "m02s41i108": Stash(36, 806), - "m02s41i109": Stash(36, 807), - "m02s41i110": Stash(36, 808), - "m02s41i111": Stash(36, 809), - "m02s41i112": Stash(36, 810), - "m02s41i113": Stash(36, 811), - "m02s41i114": Stash(36, 812), - "m02s41i115": Stash(36, 813), - "m02s41i116": Stash(36, 814), - "m02s41i117": Stash(36, 815), - "m02s41i118": Stash(36, 816), - "m02s41i119": Stash(36, 817), - "m02s41i120": Stash(36, 818), - "m02s41i121": Stash(37, 701), - "m02s41i122": Stash(37, 702), - "m02s41i130": Stash(36, 611), - "m02s41i131": Stash(36, 612), - "m02s41i132": Stash(36, 613), - "m02s41i133": Stash(36, 614), - "m02s41i134": Stash(36, 608), - "m02s41i135": Stash(37, 711), - "m02s41i136": Stash(37, 712), - "m02s41i137": Stash(36, 653), - "m02s41i139": Stash(37, 633), - "m02s41i140": Stash(37, 634), - "m02s41i141": Stash(36, 688), - "m02s41i142": Stash(36, 685), - "m02s41i143": Stash(36, 684), - "m02s41i144": Stash(36, 686), - "m02s41i145": Stash(36, 0), - "m02s41i146": Stash(36, 683), - "m02s41i147": Stash(36, 687), - "m02s41i148": Stash(37, 728), - "m02s41i149": Stash(37, 729), - "m02s41i150": Stash(37, 721), - "m02s41i151": Stash(37, 722), - "m02s41i152": Stash(36, 627), - "m02s41i161": Stash(36, 625), - "m02s41i162": Stash(36, 626), - "m02s41i165": Stash(36, 629), - "m02s41i166": Stash(36, 631), - "m02s41i167": Stash(36, 0), - "m02s41i170": Stash(36, 698), - "m02s41i171": Stash(36, 623), - "m02s41i172": Stash(36, 624), - "m02s41i180": Stash(36, 650), - "m02s41i181": Stash(36, 649), - "m02s41i182": Stash(36, 0), - "m02s41i183": Stash(36, 675), - "m02s41i185": Stash(36, 671), - "m02s41i186": Stash(36, 672), - "m02s41i187": Stash(36, 678), - "m02s41i190": Stash(36, 681), - "m02s41i191": Stash(36, 682), - "m02s42i101": Stash(36, 601), - "m02s42i102": Stash(36, 602), - "m02s42i103": Stash(36, 801), - "m02s42i104": Stash(36, 802), - "m02s42i105": Stash(36, 803), - "m02s42i106": Stash(36, 804), - "m02s42i107": Stash(36, 805), - "m02s42i108": Stash(36, 806), - "m02s42i109": Stash(36, 807), - "m02s42i110": Stash(36, 808), - "m02s42i111": Stash(36, 809), - "m02s42i112": Stash(36, 810), - "m02s42i113": Stash(36, 811), - "m02s42i114": Stash(36, 812), - "m02s42i115": Stash(36, 813), - "m02s42i116": Stash(36, 814), - "m02s42i117": Stash(36, 815), - "m02s42i118": Stash(36, 816), - "m02s42i119": Stash(36, 817), - "m02s42i120": Stash(36, 818), - "m02s42i121": Stash(37, 701), - "m02s42i122": Stash(37, 702), - "m02s42i130": Stash(36, 611), - "m02s42i131": Stash(36, 612), - "m02s42i132": Stash(36, 613), - "m02s42i133": Stash(36, 614), - "m02s42i134": Stash(36, 608), - "m02s42i135": Stash(37, 711), - "m02s42i136": Stash(37, 712), - "m02s42i137": Stash(36, 653), - "m02s42i139": Stash(37, 633), - "m02s42i140": Stash(37, 634), - "m02s42i141": Stash(36, 688), - "m02s42i142": Stash(36, 685), - "m02s42i143": Stash(36, 684), - "m02s42i144": Stash(36, 686), - "m02s42i145": Stash(36, 0), - "m02s42i146": Stash(36, 683), - "m02s42i147": Stash(36, 687), - "m02s42i148": Stash(37, 728), - "m02s42i149": Stash(37, 729), - "m02s42i150": Stash(37, 721), - "m02s42i151": Stash(37, 722), - "m02s42i152": Stash(36, 627), - "m02s42i161": Stash(36, 625), - "m02s42i162": Stash(36, 626), - "m02s42i165": Stash(36, 629), - "m02s42i166": Stash(36, 631), - "m02s42i167": Stash(36, 0), - "m02s42i170": Stash(36, 698), - "m02s42i171": Stash(36, 623), - "m02s42i172": Stash(36, 624), - "m02s42i180": Stash(36, 650), - "m02s42i181": Stash(36, 649), - "m02s42i182": Stash(36, 0), - "m02s42i183": Stash(36, 675), - "m02s42i185": Stash(36, 671), - "m02s42i186": Stash(36, 672), - "m02s42i187": Stash(36, 678), - "m02s42i190": Stash(36, 681), - "m02s42i191": Stash(36, 682), - "m02s43i101": Stash(36, 601), - "m02s43i102": Stash(36, 602), - "m02s43i103": Stash(36, 801), - "m02s43i104": Stash(36, 802), - "m02s43i105": Stash(36, 803), - "m02s43i106": Stash(36, 804), - "m02s43i107": Stash(36, 805), - "m02s43i108": Stash(36, 806), - "m02s43i109": Stash(36, 807), - "m02s43i110": Stash(36, 808), - "m02s43i111": Stash(36, 809), - "m02s43i112": Stash(36, 810), - "m02s43i113": Stash(36, 811), - "m02s43i114": Stash(36, 812), - "m02s43i115": Stash(36, 813), - "m02s43i116": Stash(36, 814), - "m02s43i117": Stash(36, 815), - "m02s43i118": Stash(36, 816), - "m02s43i119": Stash(36, 817), - "m02s43i120": Stash(36, 818), - "m02s43i121": Stash(37, 701), - "m02s43i122": Stash(37, 702), - "m02s43i130": Stash(36, 611), - "m02s43i131": Stash(36, 612), - "m02s43i132": Stash(36, 613), - "m02s43i133": Stash(36, 614), - "m02s43i134": Stash(36, 608), - "m02s43i135": Stash(37, 711), - "m02s43i136": Stash(37, 712), - "m02s43i137": Stash(36, 653), - "m02s43i139": Stash(37, 633), - "m02s43i140": Stash(37, 634), - "m02s43i141": Stash(36, 688), - "m02s43i142": Stash(36, 685), - "m02s43i143": Stash(36, 684), - "m02s43i144": Stash(36, 686), - "m02s43i145": Stash(36, 0), - "m02s43i146": Stash(36, 683), - "m02s43i147": Stash(36, 687), - "m02s43i148": Stash(37, 728), - "m02s43i149": Stash(37, 729), - "m02s43i150": Stash(37, 721), - "m02s43i151": Stash(37, 722), - "m02s43i152": Stash(36, 627), - "m02s43i161": Stash(36, 625), - "m02s43i162": Stash(36, 626), - "m02s43i165": Stash(36, 629), - "m02s43i166": Stash(36, 631), - "m02s43i167": Stash(36, 0), - "m02s43i170": Stash(36, 698), - "m02s43i171": Stash(36, 623), - "m02s43i172": Stash(36, 624), - "m02s43i180": Stash(36, 650), - "m02s43i181": Stash(36, 649), - "m02s43i182": Stash(36, 0), - "m02s43i183": Stash(36, 675), - "m02s43i185": Stash(36, 671), - "m02s43i186": Stash(36, 672), - "m02s43i187": Stash(36, 678), - "m02s43i190": Stash(36, 681), - "m02s43i191": Stash(36, 682), - "m02s44i101": Stash(36, 601), - "m02s44i102": Stash(36, 602), - "m02s44i103": Stash(36, 801), - "m02s44i104": Stash(36, 802), - "m02s44i105": Stash(36, 803), - "m02s44i106": Stash(36, 804), - "m02s44i107": Stash(36, 805), - "m02s44i108": Stash(36, 806), - "m02s44i109": Stash(36, 807), - "m02s44i110": Stash(36, 808), - "m02s44i111": Stash(36, 809), - "m02s44i112": Stash(36, 810), - "m02s44i113": Stash(36, 811), - "m02s44i114": Stash(36, 812), - "m02s44i115": Stash(36, 813), - "m02s44i116": Stash(36, 814), - "m02s44i117": Stash(36, 815), - "m02s44i118": Stash(36, 816), - "m02s44i119": Stash(36, 817), - "m02s44i120": Stash(36, 818), - "m02s44i121": Stash(37, 701), - "m02s44i122": Stash(37, 702), - "m02s44i130": Stash(36, 611), - "m02s44i131": Stash(36, 612), - "m02s44i132": Stash(36, 613), - "m02s44i133": Stash(36, 614), - "m02s44i134": Stash(36, 608), - "m02s44i135": Stash(37, 711), - "m02s44i136": Stash(37, 712), - "m02s44i137": Stash(36, 653), - "m02s44i139": Stash(37, 633), - "m02s44i140": Stash(37, 634), - "m02s44i141": Stash(36, 688), - "m02s44i142": Stash(36, 685), - "m02s44i143": Stash(36, 684), - "m02s44i144": Stash(36, 686), - "m02s44i145": Stash(36, 0), - "m02s44i146": Stash(36, 683), - "m02s44i147": Stash(36, 687), - "m02s44i148": Stash(37, 728), - "m02s44i149": Stash(37, 729), - "m02s44i150": Stash(37, 721), - "m02s44i151": Stash(37, 722), - "m02s44i152": Stash(36, 627), - "m02s44i161": Stash(36, 625), - "m02s44i162": Stash(36, 626), - "m02s44i165": Stash(36, 629), - "m02s44i166": Stash(36, 631), - "m02s44i167": Stash(36, 0), - "m02s44i170": Stash(36, 698), - "m02s44i171": Stash(36, 623), - "m02s44i172": Stash(36, 624), - "m02s44i180": Stash(36, 650), - "m02s44i181": Stash(36, 649), - "m02s44i182": Stash(36, 0), - "m02s44i183": Stash(36, 675), - "m02s44i185": Stash(36, 671), - "m02s44i186": Stash(36, 672), - "m02s44i187": Stash(36, 678), - "m02s44i190": Stash(36, 681), - "m02s44i191": Stash(36, 682), - "m03s00i142": Stash(3, 650), - "m03s00i143": Stash(3, 675), - "m03s00i177": Stash(1, 620), - "m03s00i178": Stash(1, 650), - "m03s00i179": Stash(1, 675), - "m03s00i210": Stash(3, 16), - "m03s00i211": Stash(11, 728), - "m03s00i212": Stash(11, 729), - "m03s00i280": Stash(3, 800), - "m03s00i281": Stash(3, 800), - "m03s00i282": Stash(3, 800), - "m03s00i283": Stash(3, 800), - "m03s00i284": Stash(3, 800), - "m03s00i285": Stash(3, 800), - "m03s00i286": Stash(3, 800), - "m03s00i287": Stash(3, 800), - "m03s00i288": Stash(3, 800), - "m03s00i289": Stash(3, 800), - "m03s00i290": Stash(3, 800), - "m03s00i291": Stash(3, 800), - "m03s00i292": Stash(18, 728), - "m03s00i293": Stash(19, 729), - "m03s21i177": Stash(1, 620), - "m03s21i178": Stash(1, 650), - "m03s21i179": Stash(1, 675), - "m03s21i225": Stash(3, 16), - "m03s21i226": Stash(11, 728), - "m03s21i227": Stash(11, 729), - "m03s22i177": Stash(1, 620), - "m03s22i178": Stash(1, 650), - "m03s22i179": Stash(1, 675), - "m03s22i225": Stash(3, 16), - "m03s22i226": Stash(11, 728), - "m03s22i227": Stash(11, 729), - "m03s23i177": Stash(1, 620), - "m03s23i178": Stash(1, 650), - "m03s23i179": Stash(1, 675), - "m03s23i225": Stash(3, 16), - "m03s23i226": Stash(11, 728), - "m03s23i227": Stash(11, 729), - "m03s24i177": Stash(1, 620), - "m03s24i178": Stash(1, 650), - "m03s24i179": Stash(1, 675), - "m03s24i225": Stash(3, 16), - "m03s24i226": Stash(11, 728), - "m03s24i227": Stash(11, 729), - "m03s40i023": Stash(1, 93), - "m03s40i024": Stash(1, 16), - "m03s40i031": Stash(3, 37), - "m03s40i032": Stash(3, 687), - "m03s40i177": Stash(1, 620), - "m03s40i178": Stash(1, 650), - "m03s40i179": Stash(1, 675), - "m03s40i201": Stash(1, 620), - "m03s40i202": Stash(3, 620), - "m03s40i203": Stash(3, 687), - "m03s40i204": Stash(3, 683), - "m03s40i205": Stash(3, 687), - "m03s40i206": Stash(3, 687), - "m03s40i207": Stash(3, 688), - "m03s40i208": Stash(3, 683), - "m03s40i209": Stash(3, 687), - "m03s40i210": Stash(3, 688), - "m03s40i211": Stash(3, 684), - "m03s40i212": Stash(3, 689), - "m03s40i213": Stash(3, 690), - "m03s40i214": Stash(3, 188), - "m03s40i215": Stash(3, 188), - "m03s40i216": Stash(3, 14), - "m03s40i217": Stash(3, 14), - "m03s40i218": Stash(3, 910), - "m03s40i219": Stash(3, 911), - "m03s40i220": Stash(3, 685), - "m03s40i221": Stash(3, 912), - "m03s40i222": Stash(3, 108), - "m03s40i223": Stash(3, 108), - "m03s40i224": Stash(3, 687), - "m03s40i225": Stash(3, 688), - "m03s40i226": Stash(3, 15), - "m03s40i230": Stash(3, 801), - "m03s40i231": Stash(3, 801), - "m03s40i232": Stash(19, 801), - "m03s40i233": Stash(19, 801), - "m03s40i234": Stash(19, 801), - "m03s40i235": Stash(19, 801), - "m03s40i240": Stash(1, 93), - "m03s40i241": Stash(3, 37), - "m03s40i242": Stash(3, 687), - "m03s40i243": Stash(3, 687), - "m03s40i244": Stash(3, 683), - "m03s40i245": Stash(3, 687), - "m03s40i246": Stash(3, 688), - "m03s40i247": Stash(3, 683), - "m03s40i248": Stash(3, 687), - "m03s40i249": Stash(3, 688), - "m03s40i250": Stash(3, 683), - "m03s40i251": Stash(3, 687), - "m03s40i252": Stash(3, 688), - "m03s40i253": Stash(3, 683), - "m03s40i254": Stash(3, 687), - "m03s40i255": Stash(3, 688), - "m04s00i001": Stash(62, 351), - "m04s00i002": Stash(60, 38), - "m04s00i003": Stash(62, 2), - "m04s00i004": Stash(62, 56), - "m04s00i005": Stash(62, 57), - "m04s00i006": Stash(62, 61), - "m04s00i007": Stash(62, 62), - "m04s00i008": Stash(62, 37), - "m04s00i009": Stash(62, 364), - "m04s00i010": Stash(62, 365), - "m04s01i001": Stash(60, 353), - "m04s02i001": Stash(60, 367), - "m04s02i002": Stash(62, 61), - "m04s02i003": Stash(62, 62), - "m04s02i004": Stash(62, 364), - "m04s02i005": Stash(62, 365), - "m04s02i006": Stash(60, 366), - "m04s02i007": Stash(60, 354), - "m04s03i001": Stash(60, 355), - "m04s04i001": Stash(60, 356), - "m04s05i001": Stash(60, 357), - "m04s06i001": Stash(60, 387), - "m04s06i002": Stash(60, 393), - "m04s06i003": Stash(60, 394), - "m04s06i004": Stash(60, 392), - "m04s06i005": Stash(60, 385), - "m04s06i006": Stash(60, 388), - "m04s06i007": Stash(60, 389), - "m04s06i008": Stash(60, 386), - "m04s06i009": Stash(60, 390), - "m04s06i010": Stash(60, 391), - "m04s06i011": Stash(60, 398), - "m04s06i012": Stash(60, 381), - "m04s06i013": Stash(60, 382), - "m04s06i014": Stash(60, 383), - "m04s06i015": Stash(60, 399), - "m04s06i016": Stash(60, 400), - "m04s06i017": Stash(60, 50), - "m04s06i018": Stash(60, 55), - "m04s06i019": Stash(60, 395), - "m04s06i020": Stash(60, 2), - "m04s06i021": Stash(60, 366), - "m04s06i022": Stash(60, 368), - "m04s06i023": Stash(60, 369), - "m04s06i024": Stash(60, 392), - "m04s06i025": Stash(60, 352), - "m04s06i026": Stash(60, 353), - "m04s06i027": Stash(60, 354), - "m04s06i028": Stash(60, 355), - "m04s06i029": Stash(60, 356), - "m04s06i030": Stash(60, 357), - "m04s06i031": Stash(60, 358), - "m04s06i032": Stash(60, 396), - "m04s06i033": Stash(60, 397), - "m04s06i034": Stash(60, 398), - "m04s06i035": Stash(60, 401), - "m04s07i001": Stash(60, 358), - "m04s07i002": Stash(60, 359), + "m01s00i001": Stash(1, 8, 0), + "m01s00i002": Stash(18, 56, 0), + "m01s00i003": Stash(19, 57, 0), + "m01s00i004": Stash(1, 19, 0), + "m01s00i005": Stash(21, 0, 0), + "m01s00i006": Stash(21, 0, 0), + "m01s00i007": Stash(1, 1, 0), + "m01s00i008": Stash(21, 2011, 0), + "m01s00i009": Stash(21, 122, 0), + "m01s00i010": Stash(1, 95, 0), + "m01s00i011": Stash(1, 95, 0), + "m01s00i012": Stash(1, 78, 0), + "m01s00i013": Stash(1, 34, 0), + "m01s00i014": Stash(1, 222, 0), + "m01s00i015": Stash(1, 223, 0), + "m01s00i016": Stash(1, 219, 0), + "m01s00i017": Stash(21, 174, 0), + "m01s00i018": Stash(21, 175, 0), + "m01s00i020": Stash(21, 23, 0), + "m01s00i021": Stash(1, 1100, 0), + "m01s00i022": Stash(21, 271, 0), + "m01s00i023": Stash(1, 93, 0), + "m01s00i024": Stash(1, 16, 0), + "m01s00i025": Stash(1, 5, 0), + "m01s00i026": Stash(1, 324, 0), + "m01s00i027": Stash(3, 0, 0), + "m01s00i028": Stash(18, 701, 0), + "m01s00i029": Stash(19, 702, 0), + "m01s00i030": Stash(1, 395, 0), + "m01s00i031": Stash(3, 37, 0), + "m01s00i032": Stash(3, 687, 0), + "m01s00i033": Stash(1, 1, 0), + "m01s00i034": Stash(21, 150, 0), + "m01s00i035": Stash(21, 152, 0), + "m01s00i036": Stash(21, 153, 0), + "m01s00i037": Stash(21, 154, 0), + "m01s00i038": Stash(3, 0, 0), + "m01s00i039": Stash(1, 0, 0), + "m01s00i040": Stash(21, 329, 0), + "m01s00i041": Stash(21, 330, 0), + "m01s00i042": Stash(21, 331, 0), + "m01s00i043": Stash(21, 332, 0), + "m01s00i044": Stash(21, 333, 0), + "m01s00i045": Stash(21, 334, 0), + "m01s00i046": Stash(21, 335, 0), + "m01s00i047": Stash(21, 336, 0), + "m01s00i048": Stash(21, 342, 0), + "m01s00i049": Stash(3, 209, 0), + "m01s00i050": Stash(21, 326, 0), + "m01s00i051": Stash(21, 321, 0), + "m01s00i052": Stash(21, 322, 0), + "m01s00i053": Stash(21, 328, 0), + "m01s00i054": Stash(21, 323, 0), + "m01s00i055": Stash(21, 325, 0), + "m01s00i056": Stash(21, 327, 0), + "m01s00i057": Stash(1, 287, 0), + "m01s00i058": Stash(1, 569, 0), + "m01s00i059": Stash(1, 570, 0), + "m01s00i060": Stash(22, 453, 0), + "m01s00i061": Stash(1, 501, 0), + "m01s00i062": Stash(1, 502, 0), + "m01s00i063": Stash(1, 503, 0), + "m01s00i064": Stash(1, 504, 0), + "m01s00i065": Stash(1, 505, 0), + "m01s00i066": Stash(1, 506, 0), + "m01s00i067": Stash(1, 507, 0), + "m01s00i068": Stash(1, 508, 0), + "m01s00i069": Stash(1, 509, 0), + "m01s00i070": Stash(1, 2038, 0), + "m01s00i071": Stash(1, 2039, 0), + "m01s00i072": Stash(1, 2040, 0), + "m01s00i073": Stash(1, 2041, 0), + "m01s00i074": Stash(1, 2056, 0), + "m01s00i075": Stash(1, 515, 0), + "m01s00i076": Stash(1, 516, 0), + "m01s00i077": Stash(1, 517, 0), + "m01s00i078": Stash(1, 518, 0), + "m01s00i079": Stash(1, 519, 0), + "m01s00i080": Stash(1, 520, 0), + "m01s00i081": Stash(1, 521, 0), + "m01s00i082": Stash(1, 522, 0), + "m01s00i083": Stash(1, 523, 0), + "m01s00i084": Stash(1, 524, 0), + "m01s00i085": Stash(1, 525, 0), + "m01s00i086": Stash(1, 526, 0), + "m01s00i087": Stash(1, 527, 0), + "m01s00i088": Stash(1, 528, 0), + "m01s00i089": Stash(1, 529, 0), + "m01s00i090": Stash(1, 286, 0), + "m01s00i091": Stash(1, 0, 0), + "m01s00i093": Stash(21, 0, 0), + "m01s00i095": Stash(3, 93, 0), + "m01s00i096": Stash(1, 921, 0), + "m01s00i097": Stash(0, 0, 0), + "m01s00i098": Stash(1, 0, 0), + "m01s00i099": Stash(1, 1709, 0), + "m01s00i100": Stash(1, 1711, 0), + "m01s00i101": Stash(1, 1374, 0), + "m01s00i102": Stash(1, 1373, 0), + "m01s00i103": Stash(1, 1370, 0), + "m01s00i104": Stash(1, 1371, 0), + "m01s00i105": Stash(1, 1372, 0), + "m01s00i106": Stash(1, 581, 0), + "m01s00i107": Stash(1, 1379, 0), + "m01s00i108": Stash(1, 1491, 0), + "m01s00i109": Stash(1, 1492, 0), + "m01s00i110": Stash(1, 1493, 0), + "m01s00i111": Stash(1, 1683, 0), + "m01s00i112": Stash(1, 1684, 0), + "m01s00i113": Stash(1, 1685, 0), + "m01s00i114": Stash(1, 1491, 0), + "m01s00i115": Stash(1, 1491, 0), + "m01s00i116": Stash(1, 1491, 0), + "m01s00i117": Stash(1, 1491, 0), + "m01s00i118": Stash(1, 1491, 0), + "m01s00i121": Stash(1, 569, 0), + "m01s00i122": Stash(1, 580, 0), + "m01s00i123": Stash(1, 600, 0), + "m01s00i124": Stash(1, 581, 0), + "m01s00i125": Stash(1, 60, 0), + "m01s00i126": Stash(1, 569, 0), + "m01s00i127": Stash(1, 572, 0), + "m01s00i128": Stash(1, 573, 0), + "m01s00i129": Stash(1, 573, 0), + "m01s00i130": Stash(1, 574, 0), + "m01s00i131": Stash(1, 574, 0), + "m01s00i132": Stash(1, 575, 0), + "m01s00i133": Stash(1, 1558, 0), + "m01s00i134": Stash(1, 573, 0), + "m01s00i135": Stash(1, 573, 0), + "m01s00i150": Stash(1, 42, 0), + "m01s00i151": Stash(23, 1905, 0), + "m01s00i152": Stash(23, 1906, 0), + "m01s00i153": Stash(23, 1902, 0), + "m01s00i154": Stash(19, 57, 0), + "m01s00i155": Stash(21, 1907, 0), + "m01s00i156": Stash(21, 1908, 0), + "m01s00i157": Stash(1, 1909, 0), + "m01s00i160": Stash(1, 1910, 0), + "m01s00i161": Stash(1, 1911, 0), + "m01s00i162": Stash(1, 1912, 0), + "m01s00i163": Stash(1, 1913, 0), + "m01s00i164": Stash(1, 1914, 0), + "m01s00i165": Stash(1, 1915, 0), + "m01s00i166": Stash(1, 1916, 0), + "m01s00i167": Stash(1, 1917, 0), + "m01s00i168": Stash(1, 1918, 0), + "m01s00i169": Stash(1, 1919, 0), + "m01s00i171": Stash(1, 186, 0), + "m01s00i172": Stash(1, 186, 0), + "m01s00i173": Stash(1, 187, 0), + "m01s00i174": Stash(1, 187, 0), + "m01s00i176": Stash(18, 61, 0), + "m01s00i177": Stash(19, 62, 0), + "m01s00i178": Stash(1, 182, 0), + "m01s00i179": Stash(1, 178, 0), + "m01s00i180": Stash(1, 107, 0), + "m01s00i181": Stash(1, 285, 0), + "m01s00i184": Stash(1, 1414, 10), + "m01s00i185": Stash(1, 1415, 10), + "m01s00i186": Stash(1, 99, 0), + "m01s00i187": Stash(1, 118, 0), + "m01s00i188": Stash(1, 98, 0), + "m01s00i189": Stash(1, 119, 0), + "m01s00i190": Stash(1, 922, 0), + "m01s00i191": Stash(1, 183, 0), + "m01s00i192": Stash(1, 112, 0), + "m01s00i201": Stash(1, 8, 0), + "m01s00i202": Stash(18, 56, 0), + "m01s00i203": Stash(19, 57, 0), + "m01s00i204": Stash(1, 19, 0), + "m01s00i205": Stash(1, 36, 0), + "m01s00i206": Stash(21, 1380, 0), + "m01s00i207": Stash(21, 1381, 0), + "m01s00i208": Stash(21, 1382, 0), + "m01s00i209": Stash(21, 1383, 0), + "m01s00i211": Stash(1, 218, 0), + "m01s00i212": Stash(1, 1101, 0), + "m01s00i213": Stash(21, 1384, 0), + "m01s00i214": Stash(21, 1385, 0), + "m01s00i215": Stash(21, 1386, 0), + "m01s00i216": Stash(21, 1391, 9), + "m01s00i217": Stash(21, 1392, 9), + "m01s00i218": Stash(21, 1393, 9), + "m01s00i219": Stash(21, 1394, 0), + "m01s00i220": Stash(21, 1395, 0), + "m01s00i221": Stash(1, 1396, 0), + "m01s00i222": Stash(1, 259, 0), + "m01s00i223": Stash(21, 1397, 0), + "m01s00i224": Stash(21, 1398, 9), + "m01s00i225": Stash(21, 1500, 9), + "m01s00i226": Stash(21, 1501, 9), + "m01s00i227": Stash(21, 1502, 9), + "m01s00i228": Stash(21, 1503, 0), + "m01s00i229": Stash(21, 1504, 9), + "m01s00i230": Stash(21, 1505, 9), + "m01s00i231": Stash(21, 1507, 9), + "m01s00i232": Stash(21, 1508, 0), + "m01s00i233": Stash(21, 1510, 9), + "m01s00i234": Stash(21, 1511, 9), + "m01s00i235": Stash(1, 113, 0), + "m01s00i236": Stash(21, 1579, 9), + "m01s00i237": Stash(21, 1580, 9), + "m01s00i238": Stash(1, 1581, 0), + "m01s00i239": Stash(1, 1582, 0), + "m01s00i240": Stash(21, 1583, 9), + "m01s00i241": Stash(21, 93, 9), + "m01s00i242": Stash(21, 93, 9), + "m01s00i243": Stash(21, 322, 0), + "m01s00i244": Stash(21, 322, 0), + "m01s00i245": Stash(21, 322, 0), + "m01s00i246": Stash(21, 1879, 9), + "m01s00i250": Stash(1, 1560, 0), + "m01s00i251": Stash(1, 1561, 0), + "m01s00i252": Stash(1, 1564, 0), + "m01s00i253": Stash(1, 0, 0), + "m01s00i254": Stash(1, 79, 0), + "m01s00i255": Stash(1, 7, 0), + "m01s00i256": Stash(18, 56, 0), + "m01s00i257": Stash(19, 57, 0), + "m01s00i258": Stash(1, 42, 0), + "m01s00i259": Stash(1, 0, 0), + "m01s00i260": Stash(1, 0, 0), + "m01s00i261": Stash(1, 0, 0), + "m01s00i262": Stash(1, 0, 0), + "m01s00i263": Stash(1, 0, 0), + "m01s00i264": Stash(1, 0, 0), + "m01s00i265": Stash(1, 1729, 0), + "m01s00i266": Stash(1, 220, 0), + "m01s00i267": Stash(1, 1425, 0), + "m01s00i268": Stash(1, 1426, 0), + "m01s00i269": Stash(1, 701, 0), + "m01s00i270": Stash(1, 702, 0), + "m01s00i271": Stash(1, 1689, 0), + "m01s00i272": Stash(1, 1681, 0), + "m01s00i273": Stash(1, 1921, 0), + "m01s00i274": Stash(21, 900, 0), + "m01s00i275": Stash(21, 900, 0), + "m01s00i276": Stash(21, 900, 0), + "m01s00i277": Stash(21, 900, 0), + "m01s00i278": Stash(21, 900, 0), + "m01s00i279": Stash(21, 900, 0), + "m01s00i280": Stash(21, 900, 0), + "m01s00i281": Stash(21, 900, 0), + "m01s00i282": Stash(21, 900, 0), + "m01s00i283": Stash(21, 900, 0), + "m01s00i284": Stash(21, 900, 0), + "m01s00i285": Stash(21, 900, 0), + "m01s00i286": Stash(21, 1394, 0), + "m01s00i287": Stash(21, 1513, 0), + "m01s00i288": Stash(21, 1513, 0), + "m01s00i289": Stash(21, 1513, 0), + "m01s00i290": Stash(1, 1907, 0), + "m01s00i291": Stash(21, 0, 0), + "m01s00i292": Stash(21, 0, 0), + "m01s00i293": Stash(21, 0, 0), + "m01s00i294": Stash(21, 0, 0), + "m01s00i295": Stash(21, 0, 0), + "m01s00i296": Stash(21, 0, 0), + "m01s00i297": Stash(21, 0, 0), + "m01s00i298": Stash(21, 0, 0), + "m01s00i299": Stash(21, 0, 0), + "m01s00i301": Stash(1, 0, 0), + "m01s00i302": Stash(1, 0, 0), + "m01s00i303": Stash(1, 0, 0), + "m01s00i304": Stash(1, 0, 0), + "m01s00i305": Stash(1, 0, 0), + "m01s00i306": Stash(1, 0, 0), + "m01s00i307": Stash(1, 0, 0), + "m01s00i308": Stash(1, 0, 0), + "m01s00i321": Stash(1, 573, 0), + "m01s00i340": Stash(1, 520, 0), + "m01s00i341": Stash(22, 453, 0), + "m01s00i342": Stash(1, 0, 0), + "m01s00i343": Stash(1, 2001, 0), + "m01s00i344": Stash(1, 2002, 0), + "m01s00i345": Stash(1, 1801, 0), + "m01s00i346": Stash(1, 1802, 0), + "m01s00i347": Stash(1, 1803, 0), + "m01s00i351": Stash(1, 385, 0), + "m01s00i352": Stash(1, 386, 0), + "m01s00i353": Stash(1, 387, 0), + "m01s00i354": Stash(1, 388, 0), + "m01s00i355": Stash(1, 389, 0), + "m01s00i356": Stash(1, 390, 0), + "m01s00i357": Stash(1, 391, 0), + "m01s00i358": Stash(1, 392, 0), + "m01s00i359": Stash(1, 393, 0), + "m01s00i360": Stash(1, 394, 0), + "m01s00i361": Stash(1, 395, 0), + "m01s00i362": Stash(1, 396, 0), + "m01s00i363": Stash(1, 397, 0), + "m01s00i364": Stash(1, 398, 0), + "m01s00i365": Stash(1, 399, 0), + "m01s00i366": Stash(1, 400, 0), + "m01s00i367": Stash(1, 401, 0), + "m01s00i368": Stash(1, 402, 0), + "m01s00i369": Stash(1, 403, 0), + "m01s00i370": Stash(1, 404, 0), + "m01s00i371": Stash(1, 405, 0), + "m01s00i376": Stash(21, 0, 9), + "m01s00i377": Stash(21, 0, 9), + "m01s00i378": Stash(21, 0, 9), + "m01s00i379": Stash(21, 0, 9), + "m01s00i380": Stash(21, 0, 9), + "m01s00i381": Stash(21, 0, 9), + "m01s00i382": Stash(21, 0, 9), + "m01s00i383": Stash(21, 0, 9), + "m01s00i384": Stash(21, 0, 9), + "m01s00i385": Stash(21, 0, 9), + "m01s00i386": Stash(21, 0, 9), + "m01s00i387": Stash(1, 43, 0), + "m01s00i388": Stash(1, 19, 0), + "m01s00i389": Stash(1, 27, 0), + "m01s00i390": Stash(1, 0, 0), + "m01s00i391": Stash(1, 101, 0), + "m01s00i392": Stash(1, 101, 0), + "m01s00i393": Stash(1, 101, 0), + "m01s00i394": Stash(1, 101, 0), + "m01s00i395": Stash(1, 101, 0), + "m01s00i396": Stash(1, 101, 0), + "m01s00i397": Stash(1, 0, 0), + "m01s00i398": Stash(1, 7, 0), + "m01s00i401": Stash(1, 7, 0), + "m01s00i402": Stash(1, 79, 0), + "m01s00i403": Stash(1, 78, 0), + "m01s00i404": Stash(1, 1731, 0), + "m01s00i405": Stash(21, 106, 0), + "m01s00i406": Stash(1, 7, 0), + "m01s00i407": Stash(1, 8, 0), + "m01s00i408": Stash(1, 8, 0), + "m01s00i409": Stash(1, 8, 0), + "m01s00i410": Stash(1, 0, 0), + "m01s00i411": Stash(1, 0, 0), + "m01s00i412": Stash(1, 0, 0), + "m01s00i413": Stash(1, 1411, 10), + "m01s00i414": Stash(1, 1410, 10), + "m01s00i415": Stash(1, 1413, 10), + "m01s00i416": Stash(1, 1412, 10), + "m01s00i418": Stash(1, 1630, 0), + "m01s00i419": Stash(1, 1631, 0), + "m01s00i420": Stash(1, 1632, 0), + "m01s00i421": Stash(1, 1633, 0), + "m01s00i422": Stash(1, 1633, 0), + "m01s00i423": Stash(1, 1633, 0), + "m01s00i424": Stash(1, 1633, 0), + "m01s00i425": Stash(1, 1633, 0), + "m01s00i426": Stash(1, 1633, 0), + "m01s00i431": Stash(1, 1634, 0), + "m01s00i432": Stash(1, 1634, 0), + "m01s00i433": Stash(1, 1634, 0), + "m01s00i434": Stash(1, 1634, 0), + "m01s00i435": Stash(1, 1634, 0), + "m01s00i436": Stash(1, 1634, 0), + "m01s00i460": Stash(1, 902, 0), + "m01s00i466": Stash(21, 1397, 0), + "m01s00i467": Stash(21, 1397, 0), + "m01s00i468": Stash(21, 1397, 0), + "m01s00i469": Stash(21, 1397, 0), + "m01s00i470": Stash(21, 1503, 0), + "m01s00i471": Stash(21, 1503, 0), + "m01s00i472": Stash(21, 1503, 0), + "m01s00i473": Stash(21, 1503, 0), + "m01s00i480": Stash(1, 1080, 0), + "m01s00i481": Stash(22, 1081, 0), + "m01s00i482": Stash(22, 1082, 0), + "m01s00i483": Stash(22, 1083, 0), + "m01s00i484": Stash(22, 1084, 0), + "m01s00i485": Stash(22, 1085, 0), + "m01s00i486": Stash(22, 1086, 0), + "m01s00i487": Stash(22, 1087, 0), + "m01s00i490": Stash(21, 1137, 9), + "m01s00i491": Stash(1, 1138, 0), + "m01s00i492": Stash(1, 1139, 0), + "m01s00i493": Stash(1, 40, 0), + "m01s00i494": Stash(21, 0, 0), + "m01s00i495": Stash(21, 0, 0), + "m01s00i496": Stash(21, 0, 0), + "m01s00i497": Stash(21, 0, 0), + "m01s00i498": Stash(21, 0, 0), + "m01s00i499": Stash(21, 0, 0), + "m01s00i500": Stash(21, 0, 0), + "m01s00i501": Stash(21, 0, 0), + "m01s00i502": Stash(21, 0, 0), + "m01s00i505": Stash(21, 395, 0), + "m01s00i506": Stash(1, 16, 0), + "m01s00i507": Stash(1, 16, 0), + "m01s00i508": Stash(1, 16, 0), + "m01s00i509": Stash(1, 322, 0), + "m01s00i510": Stash(1, 322, 0), + "m01s00i511": Stash(21, 1907, 0), + "m01s01i004": Stash(1, 16, 0), + "m01s01i101": Stash(1, 0, 0), + "m01s01i102": Stash(1, 0, 0), + "m01s01i103": Stash(1, 0, 0), + "m01s01i104": Stash(1, 0, 0), + "m01s01i105": Stash(1, 0, 0), + "m01s01i106": Stash(1, 0, 0), + "m01s01i107": Stash(1, 0, 0), + "m01s01i108": Stash(1, 0, 0), + "m01s01i109": Stash(1, 0, 0), + "m01s01i110": Stash(1, 0, 0), + "m01s01i111": Stash(1, 0, 0), + "m01s01i112": Stash(1, 0, 0), + "m01s01i113": Stash(1, 0, 0), + "m01s01i114": Stash(1, 0, 0), + "m01s01i115": Stash(1, 0, 0), + "m01s01i116": Stash(1, 0, 0), + "m01s01i161": Stash(1, 0, 0), + "m01s01i181": Stash(1, 0, 0), + "m01s01i182": Stash(1, 0, 0), + "m01s01i183": Stash(1, 0, 0), + "m01s01i192": Stash(1, 0, 0), + "m01s01i193": Stash(1, 0, 0), + "m01s01i194": Stash(1, 0, 0), + "m01s01i195": Stash(1, 0, 0), + "m01s01i198": Stash(1, 0, 0), + "m01s01i199": Stash(1, 0, 0), + "m01s01i201": Stash(1, 186, 0), + "m01s01i202": Stash(1, 186, 0), + "m01s01i203": Stash(1, 186, 0), + "m01s01i204": Stash(1, 186, 0), + "m01s01i205": Stash(1, 201, 0), + "m01s01i206": Stash(1, 328, 0), + "m01s01i207": Stash(1, 200, 0), + "m01s01i208": Stash(1, 201, 0), + "m01s01i209": Stash(1, 207, 0), + "m01s01i210": Stash(1, 208, 0), + "m01s01i211": Stash(1, 207, 0), + "m01s01i212": Stash(1, 1027, 0), + "m01s01i213": Stash(1, 1028, 0), + "m01s01i214": Stash(1, 1029, 0), + "m01s01i215": Stash(1, 186, 0), + "m01s01i216": Stash(1, 186, 0), + "m01s01i217": Stash(1, 0, 0), + "m01s01i218": Stash(1, 0, 0), + "m01s01i219": Stash(1, 0, 0), + "m01s01i220": Stash(1, 0, 0), + "m01s01i221": Stash(1, 164, 0), + "m01s01i222": Stash(1, 165, 0), + "m01s01i223": Stash(1, 166, 0), + "m01s01i224": Stash(1, 167, 0), + "m01s01i225": Stash(1, 163, 0), + "m01s01i226": Stash(1, 165, 0), + "m01s01i230": Stash(1, 0, 0), + "m01s01i231": Stash(1, 0, 0), + "m01s01i232": Stash(1, 251, 0), + "m01s01i233": Stash(1, 252, 0), + "m01s01i234": Stash(1, 1376, 0), + "m01s01i235": Stash(1, 203, 0), + "m01s01i236": Stash(1, 1377, 0), + "m01s01i237": Stash(1, 186, 0), + "m01s01i238": Stash(1, 201, 0), + "m01s01i241": Stash(1, 1464, 0), + "m01s01i242": Stash(1, 1465, 0), + "m01s01i243": Stash(1, 1466, 0), + "m01s01i244": Stash(1, 1467, 0), + "m01s01i245": Stash(1, 1468, 0), + "m01s01i246": Stash(1, 1469, 0), + "m01s01i247": Stash(1, 1470, 0), + "m01s01i248": Stash(1, 1471, 0), + "m01s01i254": Stash(1, 1805, 0), + "m01s01i255": Stash(1, 1806, 0), + "m01s01i257": Stash(1, 186, 0), + "m01s01i258": Stash(1, 186, 0), + "m01s01i259": Stash(1, 186, 0), + "m01s01i260": Stash(1, 186, 0), + "m01s01i262": Stash(1, 1714, 0), + "m01s01i263": Stash(1, 1715, 0), + "m01s01i264": Stash(1, 1721, 0), + "m01s01i265": Stash(1, 1722, 0), + "m01s01i266": Stash(1, 1723, 0), + "m01s01i267": Stash(1, 1724, 0), + "m01s01i268": Stash(1, 322, 1), + "m01s01i269": Stash(1, 322, 1), + "m01s01i270": Stash(1, 322, 9), + "m01s01i271": Stash(1, 322, 9), + "m01s01i280": Stash(1, 1807, 0), + "m01s01i281": Stash(1, 1808, 0), + "m01s01i288": Stash(1, 203, 0), + "m01s01i289": Stash(1, 208, 0), + "m01s01i290": Stash(1, 1891, 0), + "m01s01i291": Stash(1, 1892, 0), + "m01s01i292": Stash(1, 1030, 0), + "m01s01i293": Stash(1, 1031, 0), + "m01s01i294": Stash(1, 1032, 0), + "m01s01i295": Stash(1, 1033, 0), + "m01s01i296": Stash(1, 1034, 0), + "m01s01i408": Stash(1, 201, 0), + "m01s01i409": Stash(1, 207, 0), + "m01s01i410": Stash(1, 208, 0), + "m01s01i411": Stash(1, 207, 0), + "m01s01i417": Stash(1, 201, 0), + "m01s01i418": Stash(1, 203, 0), + "m01s01i419": Stash(1, 207, 0), + "m01s01i420": Stash(1, 208, 0), + "m01s01i433": Stash(1, 252, 0), + "m01s01i435": Stash(1, 203, 0), + "m01s01i437": Stash(1, 186, 0), + "m01s01i438": Stash(1, 201, 0), + "m01s02i004": Stash(1, 16, 0), + "m01s02i101": Stash(1, 0, 0), + "m01s02i161": Stash(1, 0, 0), + "m01s02i181": Stash(1, 0, 0), + "m01s02i182": Stash(1, 0, 0), + "m01s02i183": Stash(1, 0, 0), + "m01s02i192": Stash(1, 0, 0), + "m01s02i193": Stash(1, 0, 0), + "m01s02i194": Stash(1, 0, 0), + "m01s02i195": Stash(1, 0, 0), + "m01s02i198": Stash(1, 0, 0), + "m01s02i199": Stash(1, 0, 0), + "m01s02i201": Stash(1, 187, 0), + "m01s02i202": Stash(1, 187, 0), + "m01s02i203": Stash(1, 187, 0), + "m01s02i204": Stash(1, 30, 0), + "m01s02i205": Stash(1, 206, 0), + "m01s02i206": Stash(1, 210, 0), + "m01s02i207": Stash(1, 205, 0), + "m01s02i208": Stash(1, 211, 0), + "m01s02i217": Stash(1, 0, 0), + "m01s02i218": Stash(1, 0, 0), + "m01s02i219": Stash(1, 0, 0), + "m01s02i220": Stash(1, 0, 0), + "m01s02i232": Stash(1, 253, 0), + "m01s02i233": Stash(1, 254, 0), + "m01s02i237": Stash(1, 187, 0), + "m01s02i238": Stash(1, 205, 0), + "m01s02i251": Stash(1, 0, 4), + "m01s02i252": Stash(1, 0, 4), + "m01s02i253": Stash(1, 0, 4), + "m01s02i254": Stash(1, 0, 4), + "m01s02i255": Stash(1, 0, 4), + "m01s02i256": Stash(1, 0, 4), + "m01s02i260": Stash(1, 453, 0), + "m01s02i261": Stash(1, 1720, 0), + "m01s02i262": Stash(1, 1718, 0), + "m01s02i263": Stash(1, 1719, 0), + "m01s02i264": Stash(1, 1725, 0), + "m01s02i265": Stash(1, 1726, 0), + "m01s02i266": Stash(1, 1727, 0), + "m01s02i267": Stash(1, 1728, 0), + "m01s02i269": Stash(1, 30, 0), + "m01s02i270": Stash(1, 30, 0), + "m01s02i271": Stash(1, 30, 0), + "m01s02i272": Stash(1, 30, 0), + "m01s02i273": Stash(1, 30, 0), + "m01s02i274": Stash(1, 30, 0), + "m01s02i275": Stash(1, 30, 0), + "m01s02i276": Stash(1, 30, 0), + "m01s02i277": Stash(1, 30, 0), + "m01s02i280": Stash(1, 1930, 0), + "m01s02i281": Stash(1, 1931, 0), + "m01s02i282": Stash(1, 1932, 0), + "m01s02i283": Stash(1, 1932, 0), + "m01s02i284": Stash(1, 0, 4), + "m01s02i285": Stash(1, 0, 4), + "m01s02i286": Stash(1, 0, 4), + "m01s02i287": Stash(1, 0, 4), + "m01s02i288": Stash(1, 0, 4), + "m01s02i289": Stash(1, 0, 4), + "m01s02i290": Stash(1, 30, 0), + "m01s02i291": Stash(1, 30, 0), + "m01s02i292": Stash(1, 30, 0), + "m01s02i293": Stash(1, 30, 0), + "m01s02i295": Stash(1, 0, 4), + "m01s02i296": Stash(1, 0, 4), + "m01s02i297": Stash(1, 0, 4), + "m01s02i298": Stash(1, 0, 4), + "m01s02i299": Stash(1, 0, 4), + "m01s02i300": Stash(1, 0, 4), + "m01s02i301": Stash(1, 0, 4), + "m01s02i302": Stash(1, 0, 4), + "m01s02i303": Stash(1, 0, 4), + "m01s02i304": Stash(1, 0, 4), + "m01s02i305": Stash(1, 0, 4), + "m01s02i308": Stash(1, 79, 0), + "m01s02i309": Stash(1, 78, 0), + "m01s02i310": Stash(1, 79, 0), + "m01s02i311": Stash(1, 78, 0), + "m01s02i312": Stash(1, 1425, 0), + "m01s02i313": Stash(1, 1426, 0), + "m01s02i314": Stash(1, 1425, 0), + "m01s02i315": Stash(1, 1426, 0), + "m01s02i320": Stash(1, 0, 0), + "m01s02i321": Stash(1, 0, 0), + "m01s02i322": Stash(1, 0, 0), + "m01s02i323": Stash(1, 0, 0), + "m01s02i324": Stash(1, 0, 0), + "m01s02i325": Stash(1, 0, 0), + "m01s02i330": Stash(1, 0, 0), + "m01s02i331": Stash(1, 0, 0), + "m01s02i332": Stash(1, 0, 0), + "m01s02i333": Stash(1, 0, 0), + "m01s02i334": Stash(1, 0, 0), + "m01s02i335": Stash(1, 0, 0), + "m01s02i336": Stash(1, 0, 0), + "m01s02i337": Stash(1, 30, 15), + "m01s02i340": Stash(1, 0, 0), + "m01s02i341": Stash(1, 0, 16), + "m01s02i342": Stash(1, 0, 14), + "m01s02i343": Stash(1, 30, 0), + "m01s02i344": Stash(1, 30, 0), + "m01s02i345": Stash(1, 30, 0), + "m01s02i346": Stash(1, 30, 0), + "m01s02i347": Stash(1, 30, 0), + "m01s02i348": Stash(1, 0, 0), + "m01s02i349": Stash(1, 30, 0), + "m01s02i350": Stash(1, 0, 12), + "m01s02i351": Stash(1, 0, 16), + "m01s02i352": Stash(1, 0, 16), + "m01s02i353": Stash(1, 0, 0), + "m01s02i354": Stash(1, 0, 0), + "m01s02i355": Stash(1, 0, 0), + "m01s02i356": Stash(1, 0, 0), + "m01s02i360": Stash(1, 30, 15), + "m01s02i370": Stash(1, 0, 14), + "m01s02i371": Stash(1, 30, 0), + "m01s02i372": Stash(1, 0, 12), + "m01s02i373": Stash(1, 0, 13), + "m01s02i374": Stash(1, 30, 0), + "m01s02i375": Stash(1, 0, 0), + "m01s02i376": Stash(1, 0, 0), + "m01s02i377": Stash(1, 0, 0), + "m01s02i378": Stash(1, 0, 0), + "m01s02i380": Stash(1, 0, 0), + "m01s02i381": Stash(1, 0, 0), + "m01s02i382": Stash(1, 0, 0), + "m01s02i383": Stash(1, 0, 0), + "m01s02i384": Stash(1, 0, 0), + "m01s02i385": Stash(1, 0, 0), + "m01s02i386": Stash(1, 0, 0), + "m01s02i387": Stash(1, 0, 0), + "m01s02i388": Stash(1, 0, 0), + "m01s02i389": Stash(1, 1697, 0), + "m01s02i390": Stash(1, 1698, 0), + "m01s02i406": Stash(1, 210, 0), + "m01s02i407": Stash(1, 205, 0), + "m01s02i408": Stash(1, 211, 0), + "m01s02i417": Stash(1, 206, 0), + "m01s02i418": Stash(1, 205, 0), + "m01s02i419": Stash(1, 210, 0), + "m01s02i420": Stash(1, 211, 0), + "m01s02i421": Stash(1, 0, 4), + "m01s02i422": Stash(1, 0, 4), + "m01s02i423": Stash(1, 0, 4), + "m01s02i424": Stash(1, 0, 4), + "m01s02i425": Stash(1, 0, 4), + "m01s02i426": Stash(1, 0, 4), + "m01s02i427": Stash(1, 0, 4), + "m01s02i433": Stash(1, 254, 0), + "m01s02i437": Stash(1, 187, 0), + "m01s02i438": Stash(1, 205, 0), + "m01s03i002": Stash(18, 56, 0), + "m01s03i003": Stash(19, 57, 0), + "m01s03i004": Stash(1, 16, 0), + "m01s03i010": Stash(1, 95, 0), + "m01s03i024": Stash(1, 16, 0), + "m01s03i025": Stash(1, 5, 0), + "m01s03i026": Stash(1, 324, 0), + "m01s03i027": Stash(1, 324, 0), + "m01s03i028": Stash(1, 1075, 0), + "m01s03i049": Stash(3, 209, 0), + "m01s03i050": Stash(1, 0, 0), + "m01s03i051": Stash(2, 0, 9), + "m01s03i052": Stash(2, 0, 9), + "m01s03i053": Stash(2, 0, 9), + "m01s03i054": Stash(21, 1416, 0), + "m01s03i055": Stash(2, 0, 0), + "m01s03i056": Stash(2, 0, 0), + "m01s03i057": Stash(2, 0, 0), + "m01s03i058": Stash(2, 0, 0), + "m01s03i060": Stash(1, 1160, 0), + "m01s03i061": Stash(1, 1161, 0), + "m01s03i062": Stash(1, 1162, 0), + "m01s03i063": Stash(1, 1163, 0), + "m01s03i064": Stash(1, 1164, 0), + "m01s03i065": Stash(1, 1165, 0), + "m01s03i066": Stash(1, 1166, 9), + "m01s03i067": Stash(1, 1167, 9), + "m01s03i068": Stash(1, 1168, 9), + "m01s03i069": Stash(1, 1169, 0), + "m01s03i070": Stash(1, 1170, 9), + "m01s03i071": Stash(1, 1171, 9), + "m01s03i072": Stash(1, 1172, 9), + "m01s03i073": Stash(1, 1173, 0), + "m01s03i074": Stash(1, 1174, 0), + "m01s03i075": Stash(1, 1175, 0), + "m01s03i076": Stash(1, 1176, 0), + "m01s03i077": Stash(1, 1177, 0), + "m01s03i078": Stash(1, 1178, 0), + "m01s03i079": Stash(1, 1179, 0), + "m01s03i100": Stash(1, 1301, 0), + "m01s03i101": Stash(1, 1302, 0), + "m01s03i102": Stash(1, 1303, 0), + "m01s03i103": Stash(1, 1304, 0), + "m01s03i104": Stash(1, 1305, 0), + "m01s03i105": Stash(1, 1306, 0), + "m01s03i106": Stash(1, 1307, 0), + "m01s03i107": Stash(1, 1308, 0), + "m01s03i108": Stash(1, 1309, 0), + "m01s03i109": Stash(1, 1310, 0), + "m01s03i110": Stash(1, 1311, 0), + "m01s03i111": Stash(1, 1312, 0), + "m01s03i112": Stash(1, 1313, 0), + "m01s03i113": Stash(1, 1314, 0), + "m01s03i114": Stash(1, 1315, 0), + "m01s03i115": Stash(1, 1316, 0), + "m01s03i116": Stash(1, 1317, 0), + "m01s03i117": Stash(1, 1318, 0), + "m01s03i118": Stash(1, 1319, 0), + "m01s03i119": Stash(1, 1320, 0), + "m01s03i120": Stash(1, 1321, 0), + "m01s03i121": Stash(1, 1322, 0), + "m01s03i122": Stash(1, 1323, 0), + "m01s03i123": Stash(1, 1324, 0), + "m01s03i124": Stash(1, 1325, 0), + "m01s03i125": Stash(1, 1326, 0), + "m01s03i126": Stash(1, 1327, 0), + "m01s03i127": Stash(1, 1328, 0), + "m01s03i128": Stash(1, 1329, 0), + "m01s03i129": Stash(1, 1330, 0), + "m01s03i130": Stash(1, 2042, 0), + "m01s03i131": Stash(1, 2043, 0), + "m01s03i132": Stash(1, 2044, 0), + "m01s03i133": Stash(1, 2045, 0), + "m01s03i134": Stash(1, 2046, 0), + "m01s03i135": Stash(1, 2047, 0), + "m01s03i136": Stash(1, 2048, 0), + "m01s03i137": Stash(1, 2049, 0), + "m01s03i138": Stash(1, 2050, 0), + "m01s03i139": Stash(1, 2051, 0), + "m01s03i140": Stash(1, 2052, 0), + "m01s03i141": Stash(1, 2053, 0), + "m01s03i142": Stash(1, 2054, 0), + "m01s03i143": Stash(1, 2055, 0), + "m01s03i170": Stash(1, 0, 0), + "m01s03i171": Stash(1, 0, 0), + "m01s03i172": Stash(1, 0, 0), + "m01s03i173": Stash(1, 0, 0), + "m01s03i176": Stash(1, 0, 0), + "m01s03i177": Stash(1, 0, 0), + "m01s03i178": Stash(1, 0, 0), + "m01s03i179": Stash(1, 0, 0), + "m01s03i181": Stash(1, 0, 0), + "m01s03i182": Stash(1, 0, 0), + "m01s03i183": Stash(1, 0, 0), + "m01s03i184": Stash(1, 0, 0), + "m01s03i185": Stash(18, 0, 0), + "m01s03i186": Stash(19, 0, 0), + "m01s03i188": Stash(1, 0, 0), + "m01s03i189": Stash(1, 0, 0), + "m01s03i190": Stash(1, 0, 0), + "m01s03i192": Stash(1, 0, 0), + "m01s03i193": Stash(1, 0, 0), + "m01s03i194": Stash(1, 0, 0), + "m01s03i201": Stash(1, 261, 0), + "m01s03i202": Stash(2, 179, 0), + "m01s03i203": Stash(1, 160, 0), + "m01s03i204": Stash(1, 183, 0), + "m01s03i205": Stash(1, 52, 0), + "m01s03i206": Stash(11, 172, 0), + "m01s03i207": Stash(1, 171, 0), + "m01s03i208": Stash(1, 181, 0), + "m01s03i209": Stash(18, 56, 0), + "m01s03i210": Stash(19, 57, 0), + "m01s03i216": Stash(1, 178, 0), + "m01s03i217": Stash(1, 178, 0), + "m01s03i219": Stash(18, 61, 0), + "m01s03i220": Stash(19, 62, 0), + "m01s03i221": Stash(11, 1900, 0), + "m01s03i222": Stash(1, 184, 0), + "m01s03i223": Stash(1, 184, 0), + "m01s03i224": Stash(1, 182, 0), + "m01s03i225": Stash(11, 56, 0), + "m01s03i226": Stash(11, 57, 0), + "m01s03i227": Stash(11, 50, 0), + "m01s03i228": Stash(1, 178, 0), + "m01s03i229": Stash(2, 115, 0), + "m01s03i230": Stash(1, 183, 0), + "m01s03i231": Stash(1, 107, 0), + "m01s03i232": Stash(1, 285, 0), + "m01s03i234": Stash(1, 180, 0), + "m01s03i235": Stash(1, 260, 0), + "m01s03i236": Stash(1, 16, 0), + "m01s03i237": Stash(1, 95, 0), + "m01s03i238": Stash(2, 23, 0), + "m01s03i239": Stash(1, 79, 0), + "m01s03i240": Stash(1, 78, 0), + "m01s03i241": Stash(1, 184, 0), + "m01s03i242": Stash(1, 220, 0), + "m01s03i243": Stash(1, 79, 0), + "m01s03i244": Stash(1, 78, 0), + "m01s03i245": Stash(1, 88, 0), + "m01s03i247": Stash(1, 25, 0), + "m01s03i248": Stash(1, 220, 0), + "m01s03i249": Stash(11, 50, 0), + "m01s03i250": Stash(1, 17, 0), + "m01s03i251": Stash(1, 174, 0), + "m01s03i252": Stash(1, 175, 0), + "m01s03i253": Stash(1, 173, 0), + "m01s03i254": Stash(1, 19, 0), + "m01s03i255": Stash(1, 95, 0), + "m01s03i256": Stash(1, 1414, 10), + "m01s03i257": Stash(1, 1415, 10), + "m01s03i258": Stash(2, 141, 0), + "m01s03i259": Stash(2, 1384, 0), + "m01s03i260": Stash(2, 1387, 0), + "m01s03i261": Stash(2, 1388, 0), + "m01s03i262": Stash(2, 1389, 0), + "m01s03i263": Stash(2, 1390, 0), + "m01s03i264": Stash(2, 1382, 0), + "m01s03i265": Stash(2, 1383, 0), + "m01s03i270": Stash(1, 1400, 0), + "m01s03i271": Stash(1, 1401, 0), + "m01s03i272": Stash(1, 1402, 0), + "m01s03i273": Stash(1, 1403, 0), + "m01s03i274": Stash(1, 1542, 0), + "m01s03i275": Stash(1, 1543, 0), + "m01s03i276": Stash(1, 1406, 0), + "m01s03i277": Stash(1, 1407, 0), + "m01s03i278": Stash(1, 1408, 0), + "m01s03i279": Stash(1, 1409, 0), + "m01s03i280": Stash(1, 1410, 0), + "m01s03i281": Stash(1, 25, 0), + "m01s03i282": Stash(1, 220, 0), + "m01s03i283": Stash(1, 173, 0), + "m01s03i284": Stash(1, 25, 0), + "m01s03i285": Stash(1, 25, 0), + "m01s03i286": Stash(1, 1416, 0), + "m01s03i287": Stash(2, 1517, 9), + "m01s03i288": Stash(2, 1518, 9), + "m01s03i289": Stash(2, 1519, 9), + "m01s03i290": Stash(2, 1520, 9), + "m01s03i291": Stash(2, 1521, 9), + "m01s03i292": Stash(2, 1522, 9), + "m01s03i293": Stash(2, 1523, 0), + "m01s03i294": Stash(1, 1524, 9), + "m01s03i295": Stash(2, 1525, 0), + "m01s03i296": Stash(2, 1526, 0), + "m01s03i297": Stash(2, 1527, 0), + "m01s03i298": Stash(1, 1528, 0), + "m01s03i299": Stash(2, 1529, 0), + "m01s03i300": Stash(1, 1541, 0), + "m01s03i301": Stash(1, 1542, 0), + "m01s03i302": Stash(1, 1543, 0), + "m01s03i303": Stash(1, 1544, 0), + "m01s03i304": Stash(1, 1534, 0), + "m01s03i305": Stash(1, 1535, 0), + "m01s03i306": Stash(1, 1536, 0), + "m01s03i307": Stash(1, 1537, 0), + "m01s03i308": Stash(1, 1538, 0), + "m01s03i309": Stash(1, 1539, 0), + "m01s03i310": Stash(1, 1540, 0), + "m01s03i311": Stash(2, 1557, 0), + "m01s03i312": Stash(2, 1558, 0), + "m01s03i313": Stash(2, 1559, 9), + "m01s03i314": Stash(2, 202, 9), + "m01s03i315": Stash(2, 1391, 9), + "m01s03i316": Stash(2, 1510, 9), + "m01s03i317": Stash(2, 1893, 9), + "m01s03i318": Stash(2, 1894, 9), + "m01s03i319": Stash(2, 1895, 9), + "m01s03i320": Stash(2, 1397, 0), + "m01s03i321": Stash(2, 1504, 9), + "m01s03i322": Stash(2, 1505, 9), + "m01s03i323": Stash(2, 1508, 0), + "m01s03i324": Stash(2, 1511, 9), + "m01s03i325": Stash(2, 1499, 9), + "m01s03i326": Stash(2, 1562, 0), + "m01s03i327": Stash(1, 1563, 0), + "m01s03i328": Stash(2, 16, 9), + "m01s03i329": Stash(2, 95, 9), + "m01s03i330": Stash(2, 180, 9), + "m01s03i331": Stash(2, 1564, 9), + "m01s03i332": Stash(1, 206, 0), + "m01s03i333": Stash(1, 202, 0), + "m01s03i334": Stash(2, 115, 0), + "m01s03i335": Stash(2, 1517, 9), + "m01s03i337": Stash(2, 1564, 0), + "m01s03i338": Stash(1, 1565, 0), + "m01s03i339": Stash(1, 181, 0), + "m01s03i340": Stash(1, 1628, 0), + "m01s03i341": Stash(2, 115, 0), + "m01s03i342": Stash(2, 115, 0), + "m01s03i343": Stash(1, 285, 0), + "m01s03i347": Stash(1, 285, 0), + "m01s03i353": Stash(1, 1528, 0), + "m01s03i355": Stash(1, 1699, 0), + "m01s03i356": Stash(1, 1800, 0), + "m01s03i357": Stash(1, 1801, 0), + "m01s03i358": Stash(1, 1802, 0), + "m01s03i359": Stash(1, 1803, 0), + "m01s03i360": Stash(1, 1091, 0), + "m01s03i361": Stash(1, 1092, 0), + "m01s03i362": Stash(1, 1093, 0), + "m01s03i363": Stash(1, 1094, 0), + "m01s03i364": Stash(1, 0, 0), + "m01s03i381": Stash(1, 202, 0), + "m01s03i389": Stash(1, 52, 0), + "m01s03i390": Stash(1, 52, 0), + "m01s03i391": Stash(18, 61, 0), + "m01s03i392": Stash(18, 61, 0), + "m01s03i393": Stash(19, 62, 0), + "m01s03i394": Stash(19, 62, 0), + "m01s03i395": Stash(1, 202, 0), + "m01s03i396": Stash(1, 1686, 0), + "m01s03i397": Stash(1, 1687, 0), + "m01s03i398": Stash(1, 1688, 0), + "m01s03i400": Stash(1, 1646, 9), + "m01s03i401": Stash(1, 1635, 0), + "m01s03i402": Stash(1, 1635, 0), + "m01s03i403": Stash(1, 1635, 0), + "m01s03i404": Stash(1, 1635, 0), + "m01s03i405": Stash(1, 1635, 0), + "m01s03i406": Stash(1, 1635, 0), + "m01s03i407": Stash(1, 1542, 0), + "m01s03i408": Stash(1, 1543, 0), + "m01s03i409": Stash(1, 1544, 0), + "m01s03i411": Stash(1, 1636, 9), + "m01s03i412": Stash(1, 1636, 9), + "m01s03i413": Stash(1, 1636, 9), + "m01s03i414": Stash(1, 1636, 9), + "m01s03i415": Stash(1, 1636, 9), + "m01s03i416": Stash(1, 1636, 9), + "m01s03i417": Stash(1, 1636, 9), + "m01s03i418": Stash(1, 1636, 9), + "m01s03i419": Stash(1, 1636, 9), + "m01s03i421": Stash(1, 1637, 9), + "m01s03i422": Stash(1, 1637, 9), + "m01s03i423": Stash(1, 1637, 9), + "m01s03i424": Stash(1, 1637, 9), + "m01s03i425": Stash(1, 1637, 9), + "m01s03i426": Stash(1, 1637, 9), + "m01s03i427": Stash(1, 1637, 9), + "m01s03i428": Stash(1, 1637, 9), + "m01s03i429": Stash(1, 1637, 9), + "m01s03i430": Stash(1, 1638, 9), + "m01s03i441": Stash(1, 1639, 0), + "m01s03i442": Stash(1, 1639, 0), + "m01s03i443": Stash(1, 1639, 0), + "m01s03i444": Stash(1, 1639, 0), + "m01s03i445": Stash(1, 1639, 0), + "m01s03i446": Stash(1, 1639, 0), + "m01s03i451": Stash(1, 1640, 0), + "m01s03i452": Stash(1, 1640, 0), + "m01s03i453": Stash(1, 1640, 0), + "m01s03i454": Stash(1, 1640, 0), + "m01s03i455": Stash(1, 1640, 0), + "m01s03i456": Stash(1, 1640, 0), + "m01s03i460": Stash(18, 1025, 0), + "m01s03i461": Stash(19, 1026, 0), + "m01s03i462": Stash(1, 1896, 9), + "m01s03i463": Stash(1, 1694, 0), + "m01s03i464": Stash(1, 1695, 0), + "m01s03i465": Stash(1, 1696, 0), + "m01s03i466": Stash(1, 1015, 0), + "m01s03i467": Stash(1, 1016, 0), + "m01s03i468": Stash(1, 1017, 0), + "m01s03i469": Stash(1, 1018, 0), + "m01s03i470": Stash(1, 1019, 0), + "m01s03i471": Stash(1, 1020, 0), + "m01s03i472": Stash(1, 1021, 0), + "m01s03i473": Stash(1, 1022, 0), + "m01s03i474": Stash(18, 1023, 0), + "m01s03i475": Stash(19, 1024, 0), + "m01s03i476": Stash(1, 1036, 0), + "m01s03i477": Stash(2, 1397, 0), + "m01s03i478": Stash(2, 1397, 0), + "m01s03i479": Stash(2, 1397, 0), + "m01s03i480": Stash(2, 1397, 0), + "m01s03i481": Stash(2, 1503, 0), + "m01s03i482": Stash(2, 1503, 0), + "m01s03i483": Stash(2, 1503, 0), + "m01s03i484": Stash(2, 1503, 0), + "m01s03i485": Stash(2, 1503, 0), + "m01s03i486": Stash(2, 1503, 0), + "m01s03i490": Stash(2, 2040, 9), + "m01s03i491": Stash(2, 2041, 9), + "m01s03i492": Stash(2, 2042, 9), + "m01s03i493": Stash(2, 2043, 9), + "m01s03i494": Stash(2, 2044, 9), + "m01s03i501": Stash(1, 1400, 0), + "m01s03i502": Stash(1, 1401, 0), + "m01s03i503": Stash(1, 1402, 0), + "m01s03i504": Stash(1, 1403, 0), + "m01s03i505": Stash(1, 1404, 0), + "m01s03i506": Stash(1, 1405, 0), + "m01s03i507": Stash(1, 1406, 0), + "m01s03i508": Stash(1, 1407, 0), + "m01s03i509": Stash(1, 0, 0), + "m01s03i510": Stash(1, 0, 0), + "m01s03i511": Stash(1, 0, 0), + "m01s04i004": Stash(1, 16, 0), + "m01s04i010": Stash(1, 95, 0), + "m01s04i100": Stash(1, 0, 0), + "m01s04i101": Stash(1, 0, 0), + "m01s04i102": Stash(1, 0, 0), + "m01s04i103": Stash(1, 0, 0), + "m01s04i104": Stash(1, 0, 0), + "m01s04i105": Stash(1, 0, 0), + "m01s04i110": Stash(1, 0, 0), + "m01s04i111": Stash(1, 0, 0), + "m01s04i112": Stash(1, 0, 0), + "m01s04i113": Stash(1, 0, 0), + "m01s04i114": Stash(1, 0, 0), + "m01s04i115": Stash(1, 0, 0), + "m01s04i116": Stash(1, 0, 0), + "m01s04i117": Stash(1, 0, 0), + "m01s04i118": Stash(1, 0, 0), + "m01s04i130": Stash(1, 0, 0), + "m01s04i131": Stash(1, 0, 0), + "m01s04i132": Stash(1, 0, 0), + "m01s04i133": Stash(1, 0, 0), + "m01s04i136": Stash(1, 0, 0), + "m01s04i137": Stash(1, 0, 0), + "m01s04i138": Stash(1, 0, 0), + "m01s04i139": Stash(1, 0, 0), + "m01s04i141": Stash(1, 0, 0), + "m01s04i142": Stash(1, 0, 0), + "m01s04i143": Stash(1, 0, 0), + "m01s04i144": Stash(1, 0, 0), + "m01s04i152": Stash(1, 0, 0), + "m01s04i153": Stash(1, 0, 0), + "m01s04i154": Stash(1, 0, 0), + "m01s04i170": Stash(1, 0, 0), + "m01s04i171": Stash(1, 0, 0), + "m01s04i172": Stash(1, 0, 0), + "m01s04i173": Stash(1, 0, 0), + "m01s04i176": Stash(1, 0, 0), + "m01s04i177": Stash(1, 0, 0), + "m01s04i178": Stash(1, 0, 0), + "m01s04i179": Stash(1, 0, 0), + "m01s04i181": Stash(1, 0, 0), + "m01s04i182": Stash(1, 0, 0), + "m01s04i183": Stash(1, 0, 0), + "m01s04i184": Stash(1, 0, 0), + "m01s04i189": Stash(1, 1681, 0), + "m01s04i190": Stash(1, 1921, 0), + "m01s04i191": Stash(1, 1689, 0), + "m01s04i192": Stash(1, 0, 0), + "m01s04i193": Stash(1, 0, 0), + "m01s04i194": Stash(1, 0, 0), + "m01s04i201": Stash(1, 102, 0), + "m01s04i202": Stash(1, 116, 0), + "m01s04i203": Stash(1, 99, 0), + "m01s04i204": Stash(1, 118, 0), + "m01s04i205": Stash(1, 79, 0), + "m01s04i206": Stash(1, 78, 0), + "m01s04i207": Stash(1, 88, 0), + "m01s04i208": Stash(1, 25, 0), + "m01s04i210": Stash(1, 0, 0), + "m01s04i211": Stash(1, 0, 0), + "m01s04i212": Stash(1, 1422, 0), + "m01s04i213": Stash(1, 1546, 0), + "m01s04i214": Stash(1, 1546, 0), + "m01s04i215": Stash(1, 1545, 0), + "m01s04i216": Stash(1, 1547, 0), + "m01s04i217": Stash(1, 1548, 0), + "m01s04i218": Stash(1, 1549, 0), + "m01s04i219": Stash(1, 1550, 0), + "m01s04i220": Stash(1, 1546, 0), + "m01s04i221": Stash(1, 1546, 0), + "m01s04i222": Stash(1, 99, 0), + "m01s04i223": Stash(1, 118, 0), + "m01s04i224": Stash(1, 1573, 0), + "m01s04i225": Stash(1, 1574, 0), + "m01s04i227": Stash(1, 1575, 0), + "m01s04i228": Stash(1, 1546, 0), + "m01s04i229": Stash(1, 1546, 0), + "m01s04i231": Stash(1, 1641, 0), + "m01s04i232": Stash(1, 1641, 0), + "m01s04i233": Stash(1, 1641, 0), + "m01s04i234": Stash(1, 1641, 0), + "m01s04i235": Stash(1, 1641, 0), + "m01s04i236": Stash(1, 1641, 0), + "m01s04i237": Stash(1, 1691, 0), + "m01s04i238": Stash(1, 1692, 0), + "m01s04i240": Stash(1, 0, 0), + "m01s04i241": Stash(1, 0, 0), + "m01s04i242": Stash(1, 0, 0), + "m01s04i243": Stash(1, 0, 0), + "m01s04i244": Stash(1, 0, 0), + "m01s04i245": Stash(1, 0, 0), + "m01s04i246": Stash(1, 0, 0), + "m01s04i247": Stash(1, 0, 0), + "m01s04i248": Stash(1, 0, 0), + "m01s04i249": Stash(1, 0, 0), + "m01s04i250": Stash(1, 0, 0), + "m01s04i251": Stash(1, 0, 0), + "m01s04i252": Stash(1, 0, 0), + "m01s04i253": Stash(1, 0, 0), + "m01s04i254": Stash(1, 0, 0), + "m01s04i255": Stash(1, 0, 0), + "m01s04i256": Stash(1, 0, 0), + "m01s04i257": Stash(1, 0, 0), + "m01s04i258": Stash(1, 0, 0), + "m01s04i259": Stash(1, 0, 0), + "m01s04i260": Stash(1, 0, 0), + "m01s04i261": Stash(1, 0, 0), + "m01s04i262": Stash(1, 0, 0), + "m01s04i263": Stash(1, 0, 0), + "m01s04i264": Stash(1, 0, 0), + "m01s04i265": Stash(1, 0, 0), + "m01s04i266": Stash(1, 0, 0), + "m01s04i267": Stash(1, 0, 0), + "m01s04i268": Stash(1, 0, 0), + "m01s04i269": Stash(1, 0, 0), + "m01s04i270": Stash(1, 0, 0), + "m01s04i271": Stash(1, 0, 0), + "m01s04i281": Stash(1, 0, 0), + "m01s04i282": Stash(1, 0, 0), + "m01s04i283": Stash(1, 0, 0), + "m01s04i292": Stash(1, 0, 0), + "m01s04i293": Stash(1, 0, 0), + "m01s05i004": Stash(1, 19, 0), + "m01s05i010": Stash(1, 95, 0), + "m01s05i013": Stash(1, 34, 0), + "m01s05i140": Stash(1, 0, 0), + "m01s05i141": Stash(1, 0, 0), + "m01s05i142": Stash(1, 0, 0), + "m01s05i143": Stash(1, 0, 0), + "m01s05i146": Stash(1, 0, 0), + "m01s05i147": Stash(1, 0, 0), + "m01s05i148": Stash(1, 0, 0), + "m01s05i149": Stash(1, 0, 0), + "m01s05i150": Stash(1, 0, 0), + "m01s05i151": Stash(1, 0, 0), + "m01s05i152": Stash(1, 0, 0), + "m01s05i156": Stash(1, 0, 0), + "m01s05i157": Stash(1, 0, 0), + "m01s05i158": Stash(1, 0, 0), + "m01s05i161": Stash(1, 0, 0), + "m01s05i162": Stash(1, 0, 0), + "m01s05i163": Stash(1, 0, 0), + "m01s05i164": Stash(1, 0, 0), + "m01s05i172": Stash(1, 0, 0), + "m01s05i173": Stash(1, 0, 0), + "m01s05i174": Stash(1, 0, 0), + "m01s05i181": Stash(1, 0, 0), + "m01s05i182": Stash(1, 0, 0), + "m01s05i183": Stash(1, 0, 0), + "m01s05i184": Stash(1, 0, 0), + "m01s05i185": Stash(18, 0, 0), + "m01s05i186": Stash(19, 0, 0), + "m01s05i187": Stash(1, 0, 0), + "m01s05i188": Stash(1, 0, 0), + "m01s05i192": Stash(1, 0, 0), + "m01s05i193": Stash(1, 0, 0), + "m01s05i194": Stash(1, 0, 0), + "m01s05i196": Stash(1, 0, 0), + "m01s05i197": Stash(1, 0, 0), + "m01s05i198": Stash(1, 0, 0), + "m01s05i199": Stash(1, 0, 0), + "m01s05i201": Stash(1, 94, 0), + "m01s05i202": Stash(1, 117, 0), + "m01s05i203": Stash(1, 24, 0), + "m01s05i204": Stash(1, 95, 0), + "m01s05i205": Stash(1, 98, 0), + "m01s05i206": Stash(1, 119, 0), + "m01s05i207": Stash(1, 34, 0), + "m01s05i208": Stash(1, 34, 0), + "m01s05i209": Stash(1, 16, 0), + "m01s05i210": Stash(1, 34, 0), + "m01s05i211": Stash(1, 34, 0), + "m01s05i212": Stash(1, 34, 0), + "m01s05i213": Stash(1, 218, 0), + "m01s05i214": Stash(1, 97, 0), + "m01s05i215": Stash(1, 108, 0), + "m01s05i216": Stash(1, 90, 0), + "m01s05i217": Stash(1, 213, 0), + "m01s05i218": Stash(1, 222, 0), + "m01s05i219": Stash(1, 223, 0), + "m01s05i220": Stash(1, 343, 0), + "m01s05i221": Stash(1, 219, 0), + "m01s05i222": Stash(1, 344, 0), + "m01s05i223": Stash(1, 345, 0), + "m01s05i224": Stash(1, 346, 0), + "m01s05i225": Stash(1, 347, 0), + "m01s05i226": Stash(1, 77, 0), + "m01s05i227": Stash(1, 1697, 0), + "m01s05i228": Stash(1, 1698, 0), + "m01s05i229": Stash(1, 1419, 0), + "m01s05i230": Stash(1, 1420, 0), + "m01s05i231": Stash(1, 1134, 0), + "m01s05i232": Stash(1, 1135, 0), + "m01s05i233": Stash(1, 1482, 0), + "m01s05i234": Stash(1, 1629, 0), + "m01s05i235": Stash(18, 56, 0), + "m01s05i236": Stash(19, 57, 0), + "m01s05i237": Stash(1, 1551, 0), + "m01s05i238": Stash(1, 1553, 0), + "m01s05i239": Stash(1, 1554, 0), + "m01s05i240": Stash(1, 1555, 0), + "m01s05i241": Stash(1, 1556, 0), + "m01s05i242": Stash(1, 1552, 0), + "m01s05i243": Stash(1, 1693, 0), + "m01s05i244": Stash(1, 1552, 0), + "m01s05i246": Stash(1, 40, 0), + "m01s05i247": Stash(1, 1552, 0), + "m01s05i248": Stash(1, 1552, 0), + "m01s05i249": Stash(1, 40, 0), + "m01s05i250": Stash(1, 40, 0), + "m01s05i251": Stash(1, 40, 0), + "m01s05i252": Stash(1, 74, 0), + "m01s05i253": Stash(1, 74, 0), + "m01s05i254": Stash(1, 74, 0), + "m01s05i255": Stash(1, 74, 0), + "m01s05i256": Stash(1, 318, 0), + "m01s05i257": Stash(1, 319, 0), + "m01s05i258": Stash(1, 61, 0), + "m01s05i259": Stash(1, 62, 0), + "m01s05i260": Stash(1, 61, 0), + "m01s05i261": Stash(1, 62, 0), + "m01s05i262": Stash(1, 34, 0), + "m01s05i263": Stash(1, 61, 0), + "m01s05i264": Stash(1, 62, 0), + "m01s05i267": Stash(1, 0, 0), + "m01s05i268": Stash(1, 0, 0), + "m01s05i269": Stash(1, 0, 0), + "m01s05i270": Stash(1, 1598, 0), + "m01s05i271": Stash(1, 1599, 0), + "m01s05i272": Stash(1, 1934, 0), + "m01s05i273": Stash(1, 1935, 0), + "m01s05i274": Stash(1, 1936, 0), + "m01s05i275": Stash(1, 132, 0), + "m01s05i276": Stash(1, 1937, 0), + "m01s05i277": Stash(1, 90, 0), + "m01s05i278": Stash(1, 90, 0), + "m01s05i279": Stash(1, 90, 0), + "m01s05i280": Stash(1, 90, 0), + "m01s05i281": Stash(1, 1642, 0), + "m01s05i282": Stash(1, 1642, 0), + "m01s05i283": Stash(1, 1642, 0), + "m01s05i284": Stash(1, 1642, 0), + "m01s05i285": Stash(1, 1642, 0), + "m01s05i286": Stash(1, 1642, 0), + "m01s05i290": Stash(1, 1001, 0), + "m01s05i291": Stash(1, 1002, 0), + "m01s05i292": Stash(1, 1003, 0), + "m01s05i293": Stash(1, 1004, 0), + "m01s05i300": Stash(1, 1005, 0), + "m01s05i301": Stash(1, 1006, 0), + "m01s05i302": Stash(1, 1007, 0), + "m01s05i303": Stash(1, 1007, 0), + "m01s05i304": Stash(1, 1001, 0), + "m01s05i305": Stash(1, 1003, 0), + "m01s05i306": Stash(1, 1001, 0), + "m01s05i307": Stash(1, 1003, 0), + "m01s05i308": Stash(1, 1011, 0), + "m01s05i309": Stash(1, 1012, 0), + "m01s05i310": Stash(1, 1008, 0), + "m01s05i311": Stash(1, 1009, 0), + "m01s05i312": Stash(1, 1010, 0), + "m01s05i313": Stash(1, 1013, 0), + "m01s05i314": Stash(1, 1014, 0), + "m01s05i319": Stash(1, 0, 0), + "m01s05i320": Stash(1, 40, 0), + "m01s05i321": Stash(1, 40, 0), + "m01s05i322": Stash(1, 40, 0), + "m01s05i323": Stash(1, 40, 0), + "m01s05i324": Stash(1, 0, 0), + "m01s05i325": Stash(1, 0, 0), + "m01s05i326": Stash(1, 0, 0), + "m01s05i327": Stash(1, 0, 0), + "m01s05i328": Stash(1, 0, 0), + "m01s05i329": Stash(1, 0, 0), + "m01s05i330": Stash(1, 0, 0), + "m01s05i331": Stash(1, 0, 0), + "m01s05i332": Stash(1, 318, 0), + "m01s05i333": Stash(1, 318, 0), + "m01s05i334": Stash(1, 318, 0), + "m01s05i335": Stash(1, 318, 0), + "m01s05i336": Stash(1, 319, 0), + "m01s05i337": Stash(1, 319, 0), + "m01s05i338": Stash(1, 319, 0), + "m01s05i339": Stash(1, 319, 0), + "m01s05i400": Stash(1, 0, 0), + "m01s05i401": Stash(1, 0, 0), + "m01s05i402": Stash(1, 0, 0), + "m01s05i403": Stash(1, 0, 0), + "m01s05i404": Stash(1, 0, 0), + "m01s05i405": Stash(1, 0, 0), + "m01s05i406": Stash(1, 0, 0), + "m01s05i407": Stash(1, 0, 0), + "m01s05i408": Stash(1, 0, 0), + "m01s05i409": Stash(1, 0, 0), + "m01s05i410": Stash(1, 0, 0), + "m01s05i411": Stash(1, 0, 0), + "m01s05i412": Stash(1, 0, 0), + "m01s05i413": Stash(1, 0, 0), + "m01s05i414": Stash(1, 0, 0), + "m01s05i415": Stash(1, 0, 0), + "m01s05i416": Stash(1, 0, 0), + "m01s05i417": Stash(1, 40, 0), + "m01s05i418": Stash(1, 40, 0), + "m01s05i419": Stash(1, 40, 0), + "m01s05i421": Stash(1, 0, 0), + "m01s05i422": Stash(1, 0, 0), + "m01s05i423": Stash(1, 0, 0), + "m01s05i424": Stash(1, 0, 0), + "m01s05i425": Stash(1, 0, 0), + "m01s05i426": Stash(1, 0, 0), + "m01s05i427": Stash(1, 0, 0), + "m01s05i428": Stash(1, 0, 0), + "m01s05i429": Stash(1, 0, 0), + "m01s05i430": Stash(1, 0, 0), + "m01s05i431": Stash(1, 0, 0), + "m01s05i432": Stash(1, 0, 0), + "m01s06i002": Stash(18, 56, 0), + "m01s06i003": Stash(19, 57, 0), + "m01s06i101": Stash(18, 420, 0), + "m01s06i102": Stash(19, 421, 0), + "m01s06i103": Stash(18, 422, 0), + "m01s06i104": Stash(19, 423, 0), + "m01s06i105": Stash(18, 424, 0), + "m01s06i106": Stash(19, 425, 0), + "m01s06i111": Stash(11, 1095, 0), + "m01s06i113": Stash(11, 1096, 0), + "m01s06i115": Stash(11, 1097, 0), + "m01s06i181": Stash(1, 0, 0), + "m01s06i185": Stash(18, 0, 0), + "m01s06i186": Stash(19, 0, 0), + "m01s06i201": Stash(18, 61, 0), + "m01s06i202": Stash(19, 62, 0), + "m01s06i203": Stash(1, 150, 0), + "m01s06i204": Stash(1, 152, 0), + "m01s06i205": Stash(1, 153, 0), + "m01s06i206": Stash(1, 154, 0), + "m01s06i207": Stash(18, 68, 0), + "m01s06i208": Stash(19, 69, 0), + "m01s06i209": Stash(18, 70, 0), + "m01s06i210": Stash(19, 71, 0), + "m01s06i211": Stash(18, 124, 0), + "m01s06i212": Stash(19, 124, 0), + "m01s06i213": Stash(11, 125, 0), + "m01s06i214": Stash(1, 1579, 0), + "m01s06i215": Stash(1, 1580, 0), + "m01s06i216": Stash(1, 1581, 0), + "m01s06i217": Stash(1, 1582, 0), + "m01s06i218": Stash(1, 1583, 0), + "m01s06i219": Stash(1, 1584, 0), + "m01s06i220": Stash(1, 1585, 0), + "m01s06i221": Stash(1, 1586, 0), + "m01s06i222": Stash(1, 1587, 0), + "m01s06i223": Stash(18, 1588, 0), + "m01s06i224": Stash(19, 1589, 0), + "m01s06i225": Stash(18, 1590, 0), + "m01s06i226": Stash(19, 1591, 0), + "m01s06i227": Stash(18, 1592, 0), + "m01s06i228": Stash(19, 1593, 0), + "m01s06i229": Stash(18, 1594, 0), + "m01s06i230": Stash(19, 1595, 0), + "m01s06i231": Stash(18, 1596, 0), + "m01s06i232": Stash(19, 1597, 0), + "m01s06i233": Stash(1, 0, 0), + "m01s06i234": Stash(1, 0, 0), + "m01s06i235": Stash(18, 61, 0), + "m01s06i236": Stash(19, 62, 0), + "m01s06i237": Stash(1, 0, 0), + "m01s06i241": Stash(11, 1098, 0), + "m01s06i247": Stash(11, 1099, 0), + "m01s06i248": Stash(1, 0, 0), + "m01s06i249": Stash(1, 0, 0), + "m01s06i250": Stash(1, 0, 0), + "m01s07i002": Stash(11, 56, 0), + "m01s07i003": Stash(11, 57, 0), + "m01s07i201": Stash(11, 195, 0), + "m01s07i202": Stash(11, 196, 0), + "m01s08i023": Stash(1, 93, 0), + "m01s08i024": Stash(1, 16, 0), + "m01s08i201": Stash(2, 110, 0), + "m01s08i202": Stash(2, 197, 0), + "m01s08i203": Stash(2, 274, 0), + "m01s08i204": Stash(2, 111, 0), + "m01s08i205": Stash(2, 112, 0), + "m01s08i206": Stash(2, 337, 0), + "m01s08i207": Stash(2, 338, 0), + "m01s08i208": Stash(2, 106, 0), + "m01s08i209": Stash(2, 271, 0), + "m01s08i210": Stash(2, 329, 0), + "m01s08i211": Stash(2, 330, 0), + "m01s08i212": Stash(2, 331, 0), + "m01s08i213": Stash(2, 332, 0), + "m01s08i214": Stash(2, 333, 0), + "m01s08i215": Stash(2, 334, 0), + "m01s08i216": Stash(2, 335, 0), + "m01s08i217": Stash(2, 336, 0), + "m01s08i218": Stash(2, 326, 0), + "m01s08i219": Stash(2, 321, 0), + "m01s08i220": Stash(1, 323, 0), + "m01s08i221": Stash(1, 325, 0), + "m01s08i222": Stash(1, 327, 0), + "m01s08i223": Stash(2, 122, 0), + "m01s08i224": Stash(1, 342, 0), + "m01s08i225": Stash(2, 23, 0), + "m01s08i226": Stash(2, 141, 0), + "m01s08i227": Stash(2, 1380, 0), + "m01s08i228": Stash(2, 1381, 0), + "m01s08i229": Stash(2, 1385, 0), + "m01s08i230": Stash(2, 1386, 0), + "m01s08i231": Stash(2, 1530, 0), + "m01s08i233": Stash(2, 1531, 0), + "m01s08i234": Stash(2, 1532, 0), + "m01s08i235": Stash(2, 1533, 0), + "m01s08i236": Stash(2, 1566, 9), + "m01s08i237": Stash(2, 1567, 9), + "m01s08i238": Stash(2, 1568, 9), + "m01s08i239": Stash(2, 1534, 0), + "m01s08i240": Stash(2, 1535, 0), + "m01s08i241": Stash(2, 1536, 0), + "m01s08i242": Stash(2, 1537, 0), + "m01s08i243": Stash(2, 1537, 0), + "m01s08i244": Stash(2, 1537, 0), + "m01s08i245": Stash(2, 1907, 0), + "m01s08i246": Stash(2, 1537, 0), + "m01s08i247": Stash(2, 1537, 0), + "m01s08i248": Stash(2, 1537, 0), + "m01s08i249": Stash(2, 1537, 0), + "m01s08i250": Stash(2, 1537, 0), + "m01s08i251": Stash(2, 1537, 0), + "m01s08i252": Stash(2, 1534, 0), + "m01s08i254": Stash(2, 1532, 0), + "m01s08i255": Stash(2, 1533, 0), + "m01s08i258": Stash(2, 1532, 0), + "m01s08i259": Stash(2, 1533, 0), + "m01s09i004": Stash(1, 16, 0), + "m01s09i010": Stash(1, 95, 0), + "m01s09i181": Stash(1, 0, 0), + "m01s09i182": Stash(1, 0, 0), + "m01s09i183": Stash(1, 0, 0), + "m01s09i201": Stash(1, 220, 0), + "m01s09i202": Stash(1, 1090, 0), + "m01s09i203": Stash(1, 33, 0), + "m01s09i204": Stash(1, 32, 0), + "m01s09i205": Stash(1, 31, 0), + "m01s09i206": Stash(1, 79, 0), + "m01s09i207": Stash(1, 78, 0), + "m01s09i208": Stash(1, 136, 0), + "m01s09i209": Stash(1, 136, 0), + "m01s09i210": Stash(1, 136, 0), + "m01s09i211": Stash(1, 136, 0), + "m01s09i212": Stash(1, 136, 0), + "m01s09i213": Stash(1, 136, 0), + "m01s09i214": Stash(1, 136, 0), + "m01s09i215": Stash(1, 136, 0), + "m01s09i216": Stash(1, 30, 0), + "m01s09i217": Stash(1, 30, 0), + "m01s09i218": Stash(1, 29, 0), + "m01s09i219": Stash(1, 75, 0), + "m01s09i220": Stash(1, 76, 0), + "m01s09i221": Stash(1, 139, 0), + "m01s09i222": Stash(1, 41, 0), + "m01s09i223": Stash(1, 216, 0), + "m01s09i224": Stash(1, 1425, 0), + "m01s09i225": Stash(1, 1426, 0), + "m01s09i226": Stash(1, 1729, 0), + "m01s09i227": Stash(1, 1729, 0), + "m01s09i228": Stash(1, 1730, 0), + "m01s09i229": Stash(1, 88, 0), + "m01s09i230": Stash(1, 25, 0), + "m01s09i231": Stash(1, 0, 0), + "m01s09i232": Stash(1, 30, 0), + "m01s09i233": Stash(1, 30, 0), + "m01s09i234": Stash(1, 0, 0), + "m01s09i310": Stash(1, 1730, 0), + "m01s09i311": Stash(1, 1730, 0), + "m01s09i312": Stash(1, 1730, 0), + "m01s09i313": Stash(1, 1730, 0), + "m01s09i314": Stash(1, 1730, 0), + "m01s09i315": Stash(1, 1730, 0), + "m01s09i316": Stash(1, 1730, 0), + "m01s09i317": Stash(1, 1730, 0), + "m01s09i318": Stash(1, 1730, 0), + "m01s09i319": Stash(1, 1730, 0), + "m01s09i320": Stash(1, 1730, 0), + "m01s09i321": Stash(1, 1730, 0), + "m01s09i322": Stash(1, 1730, 0), + "m01s09i323": Stash(1, 1730, 0), + "m01s09i324": Stash(1, 1730, 0), + "m01s09i325": Stash(1, 1730, 0), + "m01s09i326": Stash(1, 1730, 0), + "m01s09i327": Stash(1, 1730, 0), + "m01s09i328": Stash(1, 1730, 0), + "m01s09i329": Stash(1, 1730, 0), + "m01s09i330": Stash(1, 1730, 0), + "m01s09i331": Stash(1, 1730, 0), + "m01s09i332": Stash(1, 1730, 0), + "m01s09i333": Stash(1, 1730, 0), + "m01s09i334": Stash(1, 1730, 0), + "m01s09i335": Stash(1, 1730, 0), + "m01s09i336": Stash(1, 1730, 0), + "m01s09i337": Stash(1, 1730, 0), + "m01s09i338": Stash(1, 1730, 0), + "m01s09i339": Stash(1, 1730, 0), + "m01s09i340": Stash(1, 1730, 0), + "m01s09i341": Stash(1, 1730, 0), + "m01s09i342": Stash(1, 1730, 0), + "m01s09i343": Stash(1, 1730, 0), + "m01s09i344": Stash(1, 1730, 0), + "m01s09i345": Stash(1, 1730, 0), + "m01s09i346": Stash(1, 1730, 0), + "m01s09i347": Stash(1, 1730, 0), + "m01s09i348": Stash(1, 1730, 0), + "m01s09i349": Stash(1, 1730, 0), + "m01s09i350": Stash(1, 1730, 0), + "m01s09i351": Stash(1, 1730, 0), + "m01s09i352": Stash(1, 1730, 0), + "m01s09i353": Stash(1, 1730, 0), + "m01s09i354": Stash(1, 1730, 0), + "m01s09i355": Stash(1, 1730, 0), + "m01s09i356": Stash(1, 1730, 0), + "m01s09i357": Stash(1, 1730, 0), + "m01s09i358": Stash(1, 1730, 0), + "m01s09i359": Stash(1, 1730, 0), + "m01s09i360": Stash(1, 1730, 0), + "m01s09i361": Stash(1, 1730, 0), + "m01s09i362": Stash(1, 1730, 0), + "m01s09i363": Stash(1, 1730, 0), + "m01s09i364": Stash(1, 1730, 0), + "m01s09i365": Stash(1, 1730, 0), + "m01s09i366": Stash(1, 1730, 0), + "m01s09i367": Stash(1, 1730, 0), + "m01s09i368": Stash(1, 1730, 0), + "m01s09i369": Stash(1, 1730, 0), + "m01s09i370": Stash(1, 1730, 0), + "m01s09i371": Stash(1, 1730, 0), + "m01s09i372": Stash(1, 1730, 0), + "m01s09i373": Stash(1, 1730, 0), + "m01s09i374": Stash(1, 1730, 0), + "m01s09i375": Stash(1, 1730, 0), + "m01s09i376": Stash(1, 1730, 0), + "m01s09i377": Stash(1, 1730, 0), + "m01s09i378": Stash(1, 1730, 0), + "m01s09i379": Stash(1, 1730, 0), + "m01s09i380": Stash(1, 1730, 0), + "m01s09i381": Stash(1, 1730, 0), + "m01s09i382": Stash(1, 1730, 0), + "m01s09i383": Stash(1, 1730, 0), + "m01s09i384": Stash(1, 1730, 0), + "m01s09i385": Stash(1, 1730, 0), + "m01s09i386": Stash(1, 1730, 0), + "m01s09i387": Stash(1, 1730, 0), + "m01s09i388": Stash(1, 1730, 0), + "m01s09i389": Stash(1, 1730, 0), + "m01s09i391": Stash(1, 30, 0), + "m01s09i392": Stash(1, 30, 0), + "m01s09i393": Stash(1, 30, 0), + "m01s09i394": Stash(1, 30, 0), + "m01s09i395": Stash(1, 30, 0), + "m01s09i396": Stash(1, 30, 0), + "m01s09i397": Stash(1, 30, 0), + "m01s09i398": Stash(1, 30, 0), + "m01s10i001": Stash(1, 8, 0), + "m01s10i002": Stash(11, 56, 0), + "m01s10i003": Stash(11, 57, 0), + "m01s10i004": Stash(1, 19, 0), + "m01s10i010": Stash(1, 95, 0), + "m01s10i185": Stash(18, 56, 0), + "m01s10i186": Stash(19, 57, 0), + "m01s10i187": Stash(1, 42, 0), + "m01s10i201": Stash(11, 224, 0), + "m01s10i202": Stash(11, 225, 0), + "m01s10i203": Stash(1, 151, 0), + "m01s10i204": Stash(1, 43, 0), + "m01s10i205": Stash(1, 28, 0), + "m01s10i206": Stash(1, 3, 0), + "m01s10i207": Stash(18, 229, 0), + "m01s10i208": Stash(19, 230, 0), + "m01s10i209": Stash(18, 231, 0), + "m01s10i210": Stash(19, 232, 0), + "m01s10i211": Stash(18, 233, 0), + "m01s10i212": Stash(19, 234, 0), + "m01s10i213": Stash(18, 235, 0), + "m01s10i214": Stash(19, 236, 0), + "m01s10i215": Stash(11, 263, 0), + "m01s10i216": Stash(11, 264, 0), + "m01s10i217": Stash(11, 265, 0), + "m01s10i218": Stash(11, 266, 0), + "m01s10i219": Stash(18, 267, 0), + "m01s10i220": Stash(19, 268, 0), + "m01s10i221": Stash(18, 269, 0), + "m01s10i222": Stash(19, 270, 0), + "m01s10i223": Stash(11, 56, 0), + "m01s10i224": Stash(11, 57, 0), + "m01s10i225": Stash(11, 88, 0), + "m01s10i226": Stash(11, 56, 0), + "m01s10i227": Stash(11, 57, 0), + "m01s10i228": Stash(11, 88, 0), + "m01s10i229": Stash(1, 79, 0), + "m01s10i230": Stash(1, 78, 0), + "m01s12i002": Stash(18, 0, 0), + "m01s12i003": Stash(19, 0, 0), + "m01s12i004": Stash(1, 0, 0), + "m01s12i010": Stash(1, 0, 0), + "m01s12i012": Stash(1, 0, 0), + "m01s12i170": Stash(1, 0, 0), + "m01s12i171": Stash(1, 0, 0), + "m01s12i172": Stash(1, 0, 0), + "m01s12i173": Stash(1, 0, 0), + "m01s12i176": Stash(1, 0, 0), + "m01s12i177": Stash(1, 0, 0), + "m01s12i178": Stash(1, 0, 0), + "m01s12i179": Stash(1, 0, 0), + "m01s12i181": Stash(1, 0, 0), + "m01s12i182": Stash(1, 0, 0), + "m01s12i183": Stash(1, 0, 0), + "m01s12i184": Stash(1, 0, 0), + "m01s12i185": Stash(18, 0, 0), + "m01s12i186": Stash(19, 0, 0), + "m01s12i187": Stash(1, 0, 0), + "m01s12i189": Stash(1, 1681, 0), + "m01s12i190": Stash(1, 1921, 0), + "m01s12i191": Stash(1, 1689, 0), + "m01s12i192": Stash(1, 0, 0), + "m01s12i193": Stash(1, 0, 0), + "m01s12i194": Stash(1, 0, 0), + "m01s12i201": Stash(11, 40, 0), + "m01s12i202": Stash(11, 40, 0), + "m01s12i203": Stash(1, 0, 0), + "m01s12i204": Stash(1, 0, 0), + "m01s12i205": Stash(1, 0, 0), + "m01s12i254": Stash(1, 0, 0), + "m01s13i002": Stash(11, 56, 0), + "m01s13i003": Stash(11, 57, 0), + "m01s13i004": Stash(1, 19, 0), + "m01s13i010": Stash(1, 95, 0), + "m01s13i181": Stash(1, 16, 0), + "m01s13i182": Stash(1, 95, 0), + "m01s13i185": Stash(18, 56, 0), + "m01s13i186": Stash(19, 57, 0), + "m01s13i190": Stash(1, 0, 0), + "m01s13i191": Stash(1, 0, 0), + "m01s13i192": Stash(1, 0, 0), + "m01s13i193": Stash(1, 0, 0), + "m01s13i194": Stash(1, 0, 0), + "m01s13i195": Stash(1, 0, 0), + "m01s13i196": Stash(1, 0, 0), + "m01s13i197": Stash(1, 0, 0), + "m01s13i201": Stash(1, 0, 0), + "m01s13i381": Stash(1, 0, 0), + "m01s13i385": Stash(18, 0, 0), + "m01s13i386": Stash(19, 0, 0), + "m01s13i387": Stash(1, 0, 0), + "m01s13i388": Stash(1, 0, 0), + "m01s13i481": Stash(1, 0, 0), + "m01s13i485": Stash(18, 0, 0), + "m01s13i486": Stash(19, 0, 0), + "m01s13i487": Stash(1, 0, 0), + "m01s14i181": Stash(1, 0, 0), + "m01s14i201": Stash(1, 259, 0), + "m01s15i002": Stash(11, 56, 0), + "m01s15i003": Stash(11, 57, 0), + "m01s15i101": Stash(1, 1, 0), + "m01s15i102": Stash(1, 1, 0), + "m01s15i108": Stash(1, 8, 0), + "m01s15i119": Stash(1, 19, 0), + "m01s15i127": Stash(1, 27, 0), + "m01s15i142": Stash(1, 42, 0), + "m01s15i143": Stash(18, 56, 0), + "m01s15i144": Stash(19, 57, 0), + "m01s15i181": Stash(1, 16, 0), + "m01s15i182": Stash(1, 95, 0), + "m01s15i183": Stash(1, 0, 0), + "m01s15i201": Stash(11, 56, 0), + "m01s15i202": Stash(11, 57, 0), + "m01s15i203": Stash(11, 190, 0), + "m01s15i204": Stash(11, 8, 0), + "m01s15i205": Stash(11, 190, 0), + "m01s15i206": Stash(11, 1, 0), + "m01s15i207": Stash(11, 4, 0), + "m01s15i208": Stash(11, 8, 0), + "m01s15i209": Stash(11, 56, 0), + "m01s15i210": Stash(11, 57, 0), + "m01s15i211": Stash(11, 190, 0), + "m01s15i212": Stash(11, 56, 0), + "m01s15i213": Stash(11, 57, 0), + "m01s15i214": Stash(11, 82, 0), + "m01s15i215": Stash(11, 19, 0), + "m01s15i216": Stash(11, 19, 0), + "m01s15i217": Stash(11, 82, 0), + "m01s15i218": Stash(1, 83, 0), + "m01s15i219": Stash(11, 13, 0), + "m01s15i220": Stash(11, 58, 0), + "m01s15i221": Stash(11, 59, 0), + "m01s15i222": Stash(11, 40, 0), + "m01s15i223": Stash(11, 14, 0), + "m01s15i224": Stash(11, 53, 0), + "m01s15i225": Stash(11, 54, 0), + "m01s15i226": Stash(11, 95, 0), + "m01s15i227": Stash(11, 46, 0), + "m01s15i228": Stash(11, 47, 0), + "m01s15i229": Stash(11, 82, 0), + "m01s15i230": Stash(1, 19, 0), + "m01s15i231": Stash(19, 144, 0), + "m01s15i232": Stash(1, 145, 0), + "m01s15i233": Stash(1, 146, 0), + "m01s15i234": Stash(1, 147, 0), + "m01s15i235": Stash(11, 1334, 0), + "m01s15i236": Stash(11, 1335, 0), + "m01s15i237": Stash(11, 63, 0), + "m01s15i238": Stash(11, 1, 0), + "m01s15i239": Stash(11, 1334, 0), + "m01s15i240": Stash(11, 1334, 0), + "m01s15i241": Stash(11, 1399, 0), + "m01s15i242": Stash(1, 42, 0), + "m01s15i243": Stash(18, 56, 0), + "m01s15i244": Stash(19, 57, 0), + "m01s15i245": Stash(18, 56, 0), + "m01s15i246": Stash(19, 57, 0), + "m01s15i260": Stash(1, 0, 0), + "m01s15i261": Stash(1, 0, 0), + "m01s15i262": Stash(1, 0, 0), + "m01s15i263": Stash(1, 0, 0), + "m01s15i264": Stash(1, 0, 0), + "m01s15i265": Stash(1, 0, 0), + "m01s15i266": Stash(1, 0, 0), + "m01s15i270": Stash(1, 0, 0), + "m01s15i271": Stash(1, 0, 0), + "m01s16i004": Stash(1, 16, 0), + "m01s16i140": Stash(1, 0, 0), + "m01s16i141": Stash(1, 0, 0), + "m01s16i142": Stash(1, 0, 0), + "m01s16i143": Stash(1, 0, 0), + "m01s16i146": Stash(1, 0, 0), + "m01s16i147": Stash(1, 0, 0), + "m01s16i148": Stash(1, 0, 0), + "m01s16i149": Stash(1, 0, 0), + "m01s16i150": Stash(1, 0, 0), + "m01s16i151": Stash(1, 0, 0), + "m01s16i156": Stash(1, 0, 0), + "m01s16i157": Stash(1, 0, 0), + "m01s16i161": Stash(1, 0, 0), + "m01s16i162": Stash(1, 0, 0), + "m01s16i163": Stash(1, 0, 0), + "m01s16i164": Stash(1, 0, 0), + "m01s16i172": Stash(1, 0, 0), + "m01s16i173": Stash(1, 0, 0), + "m01s16i174": Stash(1, 0, 0), + "m01s16i181": Stash(1, 0, 0), + "m01s16i182": Stash(1, 0, 0), + "m01s16i183": Stash(1, 0, 0), + "m01s16i184": Stash(1, 0, 0), + "m01s16i192": Stash(1, 0, 0), + "m01s16i193": Stash(1, 0, 0), + "m01s16i194": Stash(1, 0, 0), + "m01s16i201": Stash(1, 1, 0), + "m01s16i202": Stash(1, 1, 0), + "m01s16i203": Stash(1, 16, 0), + "m01s16i204": Stash(1, 88, 0), + "m01s16i205": Stash(1, 22, 0), + "m01s16i206": Stash(1, 299, 0), + "m01s16i207": Stash(1, 1929, 0), + "m01s16i208": Stash(1, 8, 0), + "m01s16i209": Stash(1, 4, 0), + "m01s16i210": Stash(1, 1, 0), + "m01s16i211": Stash(1, 8, 0), + "m01s16i212": Stash(1, 35, 0), + "m01s16i213": Stash(1, 35, 0), + "m01s16i214": Stash(1, 8, 0), + "m01s16i215": Stash(1, 16, 0), + "m01s16i216": Stash(1, 1, 0), + "m01s16i217": Stash(1, 4, 0), + "m01s16i218": Stash(1, 1, 0), + "m01s16i219": Stash(1, 189, 0), + "m01s16i220": Stash(1, 1, 0), + "m01s16i221": Stash(1, 199, 0), + "m01s16i222": Stash(1, 8, 0), + "m01s16i223": Stash(1, 189, 0), + "m01s16i224": Stash(1, 15, 0), + "m01s16i225": Stash(1, 1, 0), + "m01s16i226": Stash(1, 501, 0), + "m01s16i227": Stash(1, 502, 0), + "m01s16i228": Stash(1, 503, 0), + "m01s16i229": Stash(1, 504, 0), + "m01s16i230": Stash(1, 505, 0), + "m01s16i231": Stash(1, 506, 0), + "m01s16i232": Stash(1, 507, 0), + "m01s16i233": Stash(1, 508, 0), + "m01s16i234": Stash(1, 509, 0), + "m01s16i235": Stash(1, 510, 0), + "m01s16i236": Stash(1, 511, 0), + "m01s16i237": Stash(1, 512, 0), + "m01s16i238": Stash(1, 513, 0), + "m01s16i239": Stash(1, 514, 0), + "m01s16i240": Stash(1, 515, 0), + "m01s16i241": Stash(1, 516, 0), + "m01s16i242": Stash(1, 517, 0), + "m01s16i243": Stash(1, 518, 0), + "m01s16i244": Stash(1, 519, 0), + "m01s16i245": Stash(1, 520, 0), + "m01s16i246": Stash(1, 521, 0), + "m01s16i247": Stash(1, 522, 0), + "m01s16i248": Stash(1, 523, 0), + "m01s16i249": Stash(1, 524, 0), + "m01s16i250": Stash(1, 525, 0), + "m01s16i251": Stash(1, 526, 0), + "m01s16i252": Stash(1, 527, 0), + "m01s16i253": Stash(1, 528, 0), + "m01s16i254": Stash(1, 529, 0), + "m01s16i255": Stash(1, 1, 0), + "m01s16i256": Stash(1, 88, 0), + "m01s17i201": Stash(1, 1494, 0), + "m01s17i202": Stash(1, 1495, 0), + "m01s17i203": Stash(1, 1496, 0), + "m01s17i204": Stash(1, 1497, 0), + "m01s17i205": Stash(1, 576, 0), + "m01s17i206": Stash(1, 0, 0), + "m01s17i207": Stash(1, 0, 0), + "m01s17i208": Stash(1, 0, 0), + "m01s17i209": Stash(1, 0, 0), + "m01s17i210": Stash(1, 0, 0), + "m01s17i211": Stash(1, 0, 0), + "m01s17i212": Stash(1, 0, 0), + "m01s17i213": Stash(1, 0, 0), + "m01s17i214": Stash(1, 0, 0), + "m01s17i215": Stash(1, 0, 0), + "m01s17i216": Stash(1, 0, 0), + "m01s17i217": Stash(1, 0, 0), + "m01s17i218": Stash(1, 0, 0), + "m01s17i219": Stash(1, 0, 0), + "m01s17i220": Stash(1, 2020, 0), + "m01s17i221": Stash(1, 2021, 0), + "m01s17i222": Stash(1, 2022, 0), + "m01s17i223": Stash(1, 2023, 0), + "m01s17i224": Stash(1, 2024, 0), + "m01s17i225": Stash(1, 2025, 0), + "m01s17i226": Stash(1, 2026, 0), + "m01s17i227": Stash(1, 2027, 0), + "m01s17i228": Stash(1, 2028, 0), + "m01s17i229": Stash(1, 2029, 0), + "m01s17i230": Stash(1, 2030, 0), + "m01s17i231": Stash(1, 2031, 0), + "m01s17i232": Stash(1, 2032, 0), + "m01s17i233": Stash(1, 2033, 0), + "m01s17i234": Stash(1, 2034, 0), + "m01s17i235": Stash(1, 2035, 0), + "m01s17i236": Stash(1, 2036, 0), + "m01s17i237": Stash(1, 2037, 0), + "m01s17i240": Stash(1, 0, 0), + "m01s17i241": Stash(1, 0, 0), + "m01s17i242": Stash(1, 0, 0), + "m01s17i257": Stash(1, 1645, 0), + "m01s18i001": Stash(1, 1929, 0), + "m01s18i002": Stash(11, 56, 0), + "m01s18i003": Stash(11, 57, 0), + "m01s18i004": Stash(1, 19, 0), + "m01s18i010": Stash(1, 95, 0), + "m01s18i201": Stash(1, 290, 3), + "m01s18i202": Stash(1, 291, 3), + "m01s18i203": Stash(11, 292, 3), + "m01s18i204": Stash(1, 294, 3), + "m01s18i205": Stash(1, 295, 3), + "m01s18i209": Stash(1, 288, 3), + "m01s18i211": Stash(1, 303, 3), + "m01s18i212": Stash(1, 304, 3), + "m01s18i213": Stash(11, 305, 3), + "m01s18i214": Stash(1, 309, 3), + "m01s18i215": Stash(1, 310, 3), + "m01s18i219": Stash(1, 289, 3), + "m01s18i223": Stash(11, 306, 3), + "m01s18i231": Stash(1, 304, 3), + "m01s18i241": Stash(11, 305, 3), + "m01s18i242": Stash(11, 305, 3), + "m01s18i251": Stash(11, 306, 3), + "m01s18i252": Stash(11, 306, 3), + "m01s18i261": Stash(1, 303, 3), + "m01s18i262": Stash(1, 304, 3), + "m01s18i271": Stash(1, 24, 3), + "m01s18i272": Stash(1, 304, 3), + "m01s19i001": Stash(2, 1512, 9), + "m01s19i002": Stash(2, 1513, 0), + "m01s19i003": Stash(2, 1514, 9), + "m01s19i004": Stash(2, 1515, 9), + "m01s19i005": Stash(2, 1516, 0), + "m01s19i006": Stash(2, 1500, 9), + "m01s19i007": Stash(2, 1392, 9), + "m01s19i008": Stash(2, 1500, 9), + "m01s19i009": Stash(2, 1398, 9), + "m01s19i010": Stash(2, 1502, 9), + "m01s19i011": Stash(2, 1503, 0), + "m01s19i012": Stash(2, 1394, 0), + "m01s19i013": Stash(2, 1391, 9), + "m01s19i014": Stash(2, 1392, 9), + "m01s19i015": Stash(2, 1393, 9), + "m01s19i016": Stash(2, 1397, 0), + "m01s19i017": Stash(2, 1503, 0), + "m01s19i018": Stash(2, 1503, 0), + "m01s19i019": Stash(2, 1503, 0), + "m01s19i020": Stash(2, 1503, 0), + "m01s19i021": Stash(2, 1397, 0), + "m01s19i022": Stash(2, 1397, 0), + "m01s19i023": Stash(2, 1397, 0), + "m01s19i024": Stash(2, 1397, 0), + "m01s19i025": Stash(2, 1512, 9), + "m01s19i026": Stash(2, 1513, 0), + "m01s19i027": Stash(2, 1512, 9), + "m01s19i028": Stash(2, 1513, 0), + "m01s19i029": Stash(2, 1512, 9), + "m01s19i030": Stash(2, 1513, 0), + "m01s19i031": Stash(2, 1394, 0), + "m01s19i032": Stash(2, 1397, 0), + "m01s19i033": Stash(2, 1397, 0), + "m01s19i034": Stash(2, 1397, 0), + "m01s19i035": Stash(2, 1515, 9), + "m01s19i036": Stash(2, 1516, 0), + "m01s19i037": Stash(2, 1516, 0), + "m01s19i038": Stash(2, 1516, 0), + "m01s19i039": Stash(2, 1516, 0), + "m01s19i040": Stash(2, 1516, 0), + "m01s19i041": Stash(2, 1516, 0), + "m01s19i042": Stash(2, 1516, 0), + "m01s20i001": Stash(1, 2, 0), + "m01s20i002": Stash(1, 2, 0), + "m01s20i003": Stash(1, 50, 0), + "m01s20i004": Stash(1, 50, 0), + "m01s20i005": Stash(1, 74, 0), + "m01s20i006": Stash(1, 73, 0), + "m01s20i007": Stash(1, 1578, 0), + "m01s20i012": Stash(1, 34, 0), + "m01s20i013": Stash(1, 1577, 0), + "m01s20i014": Stash(1, 1564, 0), + "m01s20i015": Stash(1, 1565, 0), + "m01s20i016": Stash(1, 1690, 0), + "m01s20i017": Stash(1, 1690, 0), + "m01s20i018": Stash(1, 8, 0), + "m01s20i020": Stash(11, 56, 0), + "m01s20i021": Stash(11, 57, 0), + "m01s20i022": Stash(1, 8, 0), + "m01s20i023": Stash(1, 4, 0), + "m01s20i024": Stash(1, 8, 0), + "m01s20i025": Stash(1, 16, 0), + "m01s20i026": Stash(1, 1, 0), + "m01s20i027": Stash(1, 4, 0), + "m01s20i028": Stash(1, 191, 0), + "m01s20i029": Stash(1, 35, 0), + "m01s20i030": Stash(1, 35, 0), + "m01s20i031": Stash(1, 189, 0), + "m01s20i032": Stash(1, 89, 0), + "m01s20i033": Stash(1, 1, 0), + "m01s20i034": Stash(1, 8, 0), + "m01s20i035": Stash(1, 4, 0), + "m01s20i036": Stash(1, 1, 0), + "m01s20i037": Stash(1, 8, 0), + "m01s20i038": Stash(1, 4, 0), + "m01s20i039": Stash(1, 4, 0), + "m01s20i040": Stash(1, 4, 0), + "m01s20i041": Stash(11, 4, 0), + "m01s20i042": Stash(11, 4, 0), + "m01s20i043": Stash(11, 1981, 0), + "m01s20i044": Stash(11, 1982, 0), + "m01s20i045": Stash(11, 1983, 0), + "m01s20i046": Stash(11, 1984, 0), + "m01s20i047": Stash(11, 1985, 0), + "m01s20i048": Stash(11, 1986, 0), + "m01s20i049": Stash(11, 1987, 0), + "m01s20i050": Stash(11, 1988, 0), + "m01s20i051": Stash(11, 1989, 0), + "m01s20i052": Stash(11, 1990, 0), + "m01s20i053": Stash(11, 1991, 0), + "m01s20i054": Stash(11, 1992, 0), + "m01s20i055": Stash(11, 1993, 0), + "m01s20i056": Stash(11, 1994, 0), + "m01s20i057": Stash(11, 1995, 0), + "m01s20i058": Stash(11, 1643, 0), + "m01s20i059": Stash(11, 1644, 0), + "m01s20i060": Stash(11, 1114, 0), + "m01s20i061": Stash(1, 1, 0), + "m01s20i062": Stash(1, 8, 0), + "m01s20i063": Stash(1, 4, 0), + "m01s20i064": Stash(1, 8, 0), + "m01s20i065": Stash(1, 16, 0), + "m01s20i066": Stash(1, 1, 0), + "m01s20i067": Stash(1, 4, 0), + "m01s20i068": Stash(1, 99, 0), + "m01s20i069": Stash(1, 90, 0), + "m01s20i070": Stash(11, 1649, 0), + "m01s20i071": Stash(11, 1650, 0), + "m01s21i001": Stash(1, 8, 0), + "m01s21i002": Stash(11, 56, 0), + "m01s21i003": Stash(11, 57, 0), + "m01s21i004": Stash(1, 19, 0), + "m01s21i010": Stash(1, 95, 0), + "m01s21i013": Stash(1, 34, 0), + "m01s21i014": Stash(1, 222, 0), + "m01s21i015": Stash(1, 223, 0), + "m01s21i016": Stash(1, 219, 0), + "m01s21i023": Stash(1, 93, 0), + "m01s21i024": Stash(1, 16, 0), + "m01s21i025": Stash(1, 5, 0), + "m01s21i026": Stash(1, 324, 0), + "m01s21i028": Stash(3, 701, 0), + "m01s21i029": Stash(3, 702, 0), + "m01s21i031": Stash(3, 37, 0), + "m01s21i032": Stash(3, 687, 0), + "m01s21i061": Stash(1, 501, 0), + "m01s21i062": Stash(1, 502, 0), + "m01s21i063": Stash(1, 503, 0), + "m01s21i064": Stash(1, 504, 0), + "m01s21i065": Stash(1, 505, 0), + "m01s21i066": Stash(1, 506, 0), + "m01s21i067": Stash(1, 507, 0), + "m01s21i068": Stash(1, 508, 0), + "m01s21i069": Stash(1, 509, 0), + "m01s21i070": Stash(1, 510, 0), + "m01s21i071": Stash(1, 511, 0), + "m01s21i072": Stash(1, 512, 0), + "m01s21i073": Stash(1, 513, 0), + "m01s21i074": Stash(1, 514, 0), + "m01s21i075": Stash(1, 515, 0), + "m01s21i076": Stash(1, 516, 0), + "m01s21i077": Stash(1, 517, 0), + "m01s21i078": Stash(1, 518, 0), + "m01s21i079": Stash(1, 519, 0), + "m01s21i080": Stash(1, 520, 0), + "m01s21i081": Stash(1, 521, 0), + "m01s21i082": Stash(1, 522, 0), + "m01s21i083": Stash(1, 523, 0), + "m01s21i084": Stash(1, 524, 0), + "m01s21i085": Stash(1, 525, 0), + "m01s21i086": Stash(1, 526, 0), + "m01s21i087": Stash(1, 527, 0), + "m01s21i088": Stash(1, 528, 0), + "m01s21i089": Stash(1, 529, 0), + "m01s21i100": Stash(1, 0, 0), + "m01s21i101": Stash(1, 0, 0), + "m01s21i102": Stash(1, 0, 0), + "m01s21i103": Stash(1, 0, 0), + "m01s21i104": Stash(1, 2061, 0), + "m01s21i105": Stash(1, 0, 0), + "m01s21i106": Stash(1, 0, 0), + "m01s21i201": Stash(11, 56, 0), + "m01s21i202": Stash(11, 57, 0), + "m01s21i203": Stash(11, 40, 0), + "m01s21i205": Stash(11, 190, 0), + "m01s21i206": Stash(11, 1, 0), + "m01s21i207": Stash(11, 8, 0), + "m01s21i208": Stash(11, 56, 0), + "m01s21i209": Stash(11, 57, 0), + "m01s21i210": Stash(1, 1, 0), + "m01s21i211": Stash(1, 1, 0), + "m01s21i212": Stash(1, 16, 0), + "m01s21i213": Stash(1, 88, 0), + "m01s21i214": Stash(1, 22, 0), + "m01s21i215": Stash(1, 191, 0), + "m01s21i216": Stash(1, 1, 0), + "m01s21i217": Stash(1, 8, 0), + "m01s21i218": Stash(1, 8, 0), + "m01s21i219": Stash(1, 16, 0), + "m01s21i220": Stash(1, 1, 0), + "m01s21i221": Stash(1, 31, 0), + "m01s21i222": Stash(1, 32, 0), + "m01s21i223": Stash(1, 33, 0), + "m01s21i224": Stash(1, 8, 0), + "m01s22i001": Stash(1, 8, 0), + "m01s22i002": Stash(11, 56, 0), + "m01s22i003": Stash(11, 57, 0), + "m01s22i004": Stash(1, 19, 0), + "m01s22i010": Stash(1, 95, 0), + "m01s22i013": Stash(1, 34, 0), + "m01s22i014": Stash(1, 222, 0), + "m01s22i015": Stash(1, 223, 0), + "m01s22i016": Stash(1, 219, 0), + "m01s22i023": Stash(1, 93, 0), + "m01s22i024": Stash(1, 16, 0), + "m01s22i025": Stash(1, 5, 0), + "m01s22i026": Stash(1, 324, 0), + "m01s22i028": Stash(3, 701, 0), + "m01s22i029": Stash(3, 702, 0), + "m01s22i031": Stash(3, 37, 0), + "m01s22i032": Stash(3, 687, 0), + "m01s22i061": Stash(1, 501, 0), + "m01s22i062": Stash(1, 502, 0), + "m01s22i063": Stash(1, 503, 0), + "m01s22i064": Stash(1, 504, 0), + "m01s22i065": Stash(1, 505, 0), + "m01s22i066": Stash(1, 506, 0), + "m01s22i067": Stash(1, 507, 0), + "m01s22i068": Stash(1, 508, 0), + "m01s22i069": Stash(1, 509, 0), + "m01s22i070": Stash(1, 510, 0), + "m01s22i071": Stash(1, 511, 0), + "m01s22i072": Stash(1, 512, 0), + "m01s22i073": Stash(1, 513, 0), + "m01s22i074": Stash(1, 514, 0), + "m01s22i075": Stash(1, 515, 0), + "m01s22i076": Stash(1, 516, 0), + "m01s22i077": Stash(1, 517, 0), + "m01s22i078": Stash(1, 518, 0), + "m01s22i079": Stash(1, 519, 0), + "m01s22i080": Stash(1, 520, 0), + "m01s22i081": Stash(1, 521, 0), + "m01s22i082": Stash(1, 522, 0), + "m01s22i083": Stash(1, 523, 0), + "m01s22i084": Stash(1, 524, 0), + "m01s22i085": Stash(1, 525, 0), + "m01s22i086": Stash(1, 526, 0), + "m01s22i087": Stash(1, 527, 0), + "m01s22i088": Stash(1, 528, 0), + "m01s22i089": Stash(1, 529, 0), + "m01s22i201": Stash(11, 56, 0), + "m01s22i202": Stash(11, 57, 0), + "m01s22i203": Stash(11, 40, 0), + "m01s22i205": Stash(11, 190, 0), + "m01s22i206": Stash(11, 1, 0), + "m01s22i207": Stash(11, 8, 0), + "m01s22i208": Stash(11, 56, 0), + "m01s22i209": Stash(11, 57, 0), + "m01s22i210": Stash(1, 1, 0), + "m01s22i211": Stash(1, 1, 0), + "m01s22i212": Stash(1, 16, 0), + "m01s22i213": Stash(1, 88, 0), + "m01s22i214": Stash(1, 22, 0), + "m01s22i215": Stash(1, 191, 0), + "m01s22i216": Stash(1, 1, 0), + "m01s22i217": Stash(1, 8, 0), + "m01s22i218": Stash(1, 8, 0), + "m01s22i219": Stash(1, 16, 0), + "m01s22i220": Stash(1, 1, 0), + "m01s22i221": Stash(1, 31, 0), + "m01s22i222": Stash(1, 32, 0), + "m01s22i223": Stash(1, 33, 0), + "m01s22i224": Stash(1, 8, 0), + "m01s23i001": Stash(1, 8, 0), + "m01s23i002": Stash(11, 56, 0), + "m01s23i003": Stash(11, 57, 0), + "m01s23i004": Stash(1, 19, 0), + "m01s23i010": Stash(1, 95, 0), + "m01s23i013": Stash(1, 34, 0), + "m01s23i014": Stash(1, 222, 0), + "m01s23i015": Stash(1, 223, 0), + "m01s23i016": Stash(1, 219, 0), + "m01s23i023": Stash(1, 93, 0), + "m01s23i024": Stash(1, 16, 0), + "m01s23i025": Stash(1, 5, 0), + "m01s23i026": Stash(1, 324, 0), + "m01s23i028": Stash(3, 701, 0), + "m01s23i029": Stash(3, 702, 0), + "m01s23i031": Stash(3, 37, 0), + "m01s23i032": Stash(3, 687, 0), + "m01s23i061": Stash(1, 501, 0), + "m01s23i062": Stash(1, 502, 0), + "m01s23i063": Stash(1, 503, 0), + "m01s23i064": Stash(1, 504, 0), + "m01s23i065": Stash(1, 505, 0), + "m01s23i066": Stash(1, 506, 0), + "m01s23i067": Stash(1, 507, 0), + "m01s23i068": Stash(1, 508, 0), + "m01s23i069": Stash(1, 509, 0), + "m01s23i070": Stash(1, 510, 0), + "m01s23i071": Stash(1, 511, 0), + "m01s23i072": Stash(1, 512, 0), + "m01s23i073": Stash(1, 513, 0), + "m01s23i074": Stash(1, 514, 0), + "m01s23i075": Stash(1, 515, 0), + "m01s23i076": Stash(1, 516, 0), + "m01s23i077": Stash(1, 517, 0), + "m01s23i078": Stash(1, 518, 0), + "m01s23i079": Stash(1, 519, 0), + "m01s23i080": Stash(1, 520, 0), + "m01s23i081": Stash(1, 521, 0), + "m01s23i082": Stash(1, 522, 0), + "m01s23i083": Stash(1, 523, 0), + "m01s23i084": Stash(1, 524, 0), + "m01s23i085": Stash(1, 525, 0), + "m01s23i086": Stash(1, 526, 0), + "m01s23i087": Stash(1, 527, 0), + "m01s23i088": Stash(1, 528, 0), + "m01s23i089": Stash(1, 529, 0), + "m01s23i201": Stash(11, 56, 0), + "m01s23i202": Stash(11, 57, 0), + "m01s23i203": Stash(11, 40, 0), + "m01s23i205": Stash(11, 190, 0), + "m01s23i206": Stash(11, 1, 0), + "m01s23i207": Stash(11, 8, 0), + "m01s23i208": Stash(11, 56, 0), + "m01s23i209": Stash(11, 57, 0), + "m01s23i210": Stash(1, 1, 0), + "m01s23i211": Stash(1, 1, 0), + "m01s23i212": Stash(1, 16, 0), + "m01s23i213": Stash(1, 88, 0), + "m01s23i214": Stash(1, 22, 0), + "m01s23i215": Stash(1, 191, 0), + "m01s23i216": Stash(1, 1, 0), + "m01s23i217": Stash(1, 8, 0), + "m01s23i218": Stash(1, 8, 0), + "m01s23i219": Stash(1, 16, 0), + "m01s23i220": Stash(1, 1, 0), + "m01s23i221": Stash(1, 31, 0), + "m01s23i222": Stash(1, 32, 0), + "m01s23i223": Stash(1, 33, 0), + "m01s23i224": Stash(1, 8, 0), + "m01s24i001": Stash(1, 8, 0), + "m01s24i002": Stash(11, 56, 0), + "m01s24i003": Stash(11, 57, 0), + "m01s24i004": Stash(1, 19, 0), + "m01s24i010": Stash(1, 95, 0), + "m01s24i013": Stash(1, 34, 0), + "m01s24i014": Stash(1, 222, 0), + "m01s24i015": Stash(1, 223, 0), + "m01s24i016": Stash(1, 219, 0), + "m01s24i023": Stash(1, 93, 0), + "m01s24i024": Stash(1, 16, 0), + "m01s24i025": Stash(1, 5, 0), + "m01s24i026": Stash(1, 324, 0), + "m01s24i028": Stash(3, 701, 0), + "m01s24i029": Stash(3, 702, 0), + "m01s24i031": Stash(3, 37, 0), + "m01s24i032": Stash(3, 687, 0), + "m01s24i061": Stash(1, 501, 0), + "m01s24i062": Stash(1, 502, 0), + "m01s24i063": Stash(1, 503, 0), + "m01s24i064": Stash(1, 504, 0), + "m01s24i065": Stash(1, 505, 0), + "m01s24i066": Stash(1, 506, 0), + "m01s24i067": Stash(1, 507, 0), + "m01s24i068": Stash(1, 508, 0), + "m01s24i069": Stash(1, 509, 0), + "m01s24i070": Stash(1, 510, 0), + "m01s24i071": Stash(1, 511, 0), + "m01s24i072": Stash(1, 512, 0), + "m01s24i073": Stash(1, 513, 0), + "m01s24i074": Stash(1, 514, 0), + "m01s24i075": Stash(1, 515, 0), + "m01s24i076": Stash(1, 516, 0), + "m01s24i077": Stash(1, 517, 0), + "m01s24i078": Stash(1, 518, 0), + "m01s24i079": Stash(1, 519, 0), + "m01s24i080": Stash(1, 520, 0), + "m01s24i081": Stash(1, 521, 0), + "m01s24i082": Stash(1, 522, 0), + "m01s24i083": Stash(1, 523, 0), + "m01s24i084": Stash(1, 524, 0), + "m01s24i085": Stash(1, 525, 0), + "m01s24i086": Stash(1, 526, 0), + "m01s24i087": Stash(1, 527, 0), + "m01s24i088": Stash(1, 528, 0), + "m01s24i089": Stash(1, 529, 0), + "m01s24i201": Stash(11, 56, 0), + "m01s24i202": Stash(11, 57, 0), + "m01s24i203": Stash(11, 40, 0), + "m01s24i205": Stash(11, 190, 0), + "m01s24i206": Stash(11, 1, 0), + "m01s24i207": Stash(11, 8, 0), + "m01s24i208": Stash(11, 56, 0), + "m01s24i209": Stash(11, 57, 0), + "m01s24i210": Stash(1, 1, 0), + "m01s24i211": Stash(1, 1, 0), + "m01s24i212": Stash(1, 16, 0), + "m01s24i213": Stash(1, 88, 0), + "m01s24i214": Stash(1, 22, 0), + "m01s24i215": Stash(1, 191, 0), + "m01s24i216": Stash(1, 1, 0), + "m01s24i217": Stash(1, 8, 0), + "m01s24i218": Stash(1, 8, 0), + "m01s24i219": Stash(1, 16, 0), + "m01s24i220": Stash(1, 1, 0), + "m01s24i221": Stash(1, 31, 0), + "m01s24i222": Stash(1, 32, 0), + "m01s24i223": Stash(1, 33, 0), + "m01s24i224": Stash(1, 8, 0), + "m01s26i001": Stash(23, 1902, 0), + "m01s26i002": Stash(23, 1904, 0), + "m01s26i003": Stash(23, 1903, 0), + "m01s26i004": Stash(1, 1901, 0), + "m01s26i006": Stash(23, 1906, 0), + "m01s30i001": Stash(1, 56, 0), + "m01s30i002": Stash(1, 57, 0), + "m01s30i003": Stash(1, 42, 0), + "m01s30i004": Stash(1, 16, 0), + "m01s30i005": Stash(1, 95, 0), + "m01s30i006": Stash(1, 1, 0), + "m01s30i007": Stash(1, 60, 0), + "m01s30i008": Stash(1, 40, 0), + "m01s30i011": Stash(1, 0, 0), + "m01s30i012": Stash(1, 0, 0), + "m01s30i013": Stash(1, 0, 0), + "m01s30i014": Stash(1, 0, 0), + "m01s30i015": Stash(1, 0, 0), + "m01s30i016": Stash(1, 0, 0), + "m01s30i017": Stash(1, 0, 0), + "m01s30i018": Stash(1, 0, 0), + "m01s30i022": Stash(1, 0, 0), + "m01s30i023": Stash(1, 0, 0), + "m01s30i024": Stash(1, 0, 0), + "m01s30i025": Stash(1, 0, 0), + "m01s30i026": Stash(1, 0, 0), + "m01s30i027": Stash(1, 0, 0), + "m01s30i028": Stash(1, 0, 0), + "m01s30i033": Stash(1, 0, 0), + "m01s30i034": Stash(1, 0, 0), + "m01s30i035": Stash(1, 0, 0), + "m01s30i036": Stash(1, 0, 0), + "m01s30i037": Stash(1, 0, 0), + "m01s30i038": Stash(1, 0, 0), + "m01s30i044": Stash(1, 0, 0), + "m01s30i045": Stash(1, 0, 0), + "m01s30i046": Stash(1, 0, 0), + "m01s30i047": Stash(1, 0, 0), + "m01s30i048": Stash(1, 0, 0), + "m01s30i055": Stash(1, 0, 0), + "m01s30i056": Stash(1, 0, 0), + "m01s30i057": Stash(1, 0, 0), + "m01s30i058": Stash(1, 0, 0), + "m01s30i066": Stash(1, 0, 0), + "m01s30i067": Stash(1, 0, 0), + "m01s30i077": Stash(1, 0, 0), + "m01s30i078": Stash(1, 0, 0), + "m01s30i088": Stash(1, 0, 0), + "m01s30i101": Stash(1, 56, 0), + "m01s30i102": Stash(1, 57, 0), + "m01s30i103": Stash(1, 42, 0), + "m01s30i104": Stash(1, 16, 0), + "m01s30i105": Stash(1, 95, 0), + "m01s30i106": Stash(1, 1, 0), + "m01s30i107": Stash(1, 95, 0), + "m01s30i111": Stash(1, 16, 0), + "m01s30i112": Stash(1, 42, 0), + "m01s30i113": Stash(1, 88, 0), + "m01s30i114": Stash(1, 42, 0), + "m01s30i115": Stash(1, 0, 0), + "m01s30i171": Stash(1, 16, 0), + "m01s30i172": Stash(1, 95, 0), + "m01s30i173": Stash(1, 79, 0), + "m01s30i174": Stash(1, 78, 0), + "m01s30i175": Stash(18, 56, 0), + "m01s30i176": Stash(19, 57, 0), + "m01s30i177": Stash(1, 42, 0), + "m01s30i178": Stash(1, 7, 0), + "m01s30i181": Stash(1, 16, 0), + "m01s30i182": Stash(1, 95, 0), + "m01s30i183": Stash(1, 79, 0), + "m01s30i184": Stash(1, 78, 0), + "m01s30i185": Stash(18, 56, 0), + "m01s30i186": Stash(19, 57, 0), + "m01s30i187": Stash(1, 42, 0), + "m01s30i188": Stash(1, 7, 0), + "m01s30i189": Stash(1, 1681, 0), + "m01s30i190": Stash(1, 1921, 0), + "m01s30i191": Stash(1, 1689, 0), + "m01s30i201": Stash(11, 56, 0), + "m01s30i202": Stash(11, 57, 0), + "m01s30i203": Stash(11, 0, 0), + "m01s30i204": Stash(11, 16, 0), + "m01s30i205": Stash(11, 95, 0), + "m01s30i206": Stash(11, 88, 0), + "m01s30i207": Stash(11, 1, 0), + "m01s30i208": Stash(11, 40, 0), + "m01s30i211": Stash(11, 0, 0), + "m01s30i212": Stash(11, 0, 0), + "m01s30i213": Stash(11, 0, 0), + "m01s30i214": Stash(11, 0, 0), + "m01s30i215": Stash(11, 0, 0), + "m01s30i217": Stash(11, 0, 0), + "m01s30i218": Stash(11, 0, 0), + "m01s30i222": Stash(11, 0, 0), + "m01s30i223": Stash(11, 0, 0), + "m01s30i224": Stash(11, 0, 0), + "m01s30i225": Stash(11, 0, 0), + "m01s30i227": Stash(11, 0, 0), + "m01s30i228": Stash(11, 0, 0), + "m01s30i233": Stash(11, 0, 0), + "m01s30i234": Stash(11, 0, 0), + "m01s30i235": Stash(11, 0, 0), + "m01s30i237": Stash(11, 0, 0), + "m01s30i238": Stash(11, 0, 0), + "m01s30i244": Stash(11, 0, 0), + "m01s30i245": Stash(11, 0, 0), + "m01s30i247": Stash(11, 0, 0), + "m01s30i248": Stash(11, 0, 0), + "m01s30i255": Stash(11, 0, 0), + "m01s30i257": Stash(11, 0, 0), + "m01s30i258": Stash(11, 0, 0), + "m01s30i277": Stash(11, 0, 0), + "m01s30i278": Stash(11, 0, 0), + "m01s30i288": Stash(11, 0, 0), + "m01s30i301": Stash(11, 1335, 0), + "m01s30i302": Stash(11, 16, 0), + "m01s30i303": Stash(11, 16, 0), + "m01s30i310": Stash(14, 1075, 0), + "m01s30i311": Stash(14, 1076, 0), + "m01s30i312": Stash(14, 1077, 0), + "m01s30i313": Stash(14, 1078, 0), + "m01s30i314": Stash(14, 1079, 0), + "m01s30i315": Stash(14, 1080, 0), + "m01s30i316": Stash(14, 1081, 0), + "m01s30i401": Stash(1, 63, 0), + "m01s30i402": Stash(1, 63, 0), + "m01s30i403": Stash(1, 0, 0), + "m01s30i404": Stash(1, 0, 0), + "m01s30i405": Stash(1, 0, 0), + "m01s30i406": Stash(1, 0, 0), + "m01s30i407": Stash(1, 0, 0), + "m01s30i408": Stash(1, 0, 0), + "m01s30i409": Stash(1, 0, 0), + "m01s30i410": Stash(18, 1399, 0), + "m01s30i411": Stash(1, 56, 0), + "m01s30i412": Stash(1, 57, 0), + "m01s30i413": Stash(1, 0, 0), + "m01s30i414": Stash(1, 56, 0), + "m01s30i415": Stash(1, 57, 0), + "m01s30i416": Stash(1, 0, 0), + "m01s30i417": Stash(1, 8, 0), + "m01s30i418": Stash(11, 8, 0), + "m01s30i419": Stash(1, 259, 0), + "m01s30i420": Stash(1, 0, 0), + "m01s30i421": Stash(1, 0, 0), + "m01s30i422": Stash(1, 0, 0), + "m01s30i423": Stash(1, 0, 0), + "m01s30i424": Stash(1, 0, 0), + "m01s30i425": Stash(1, 0, 0), + "m01s30i426": Stash(1, 0, 0), + "m01s30i427": Stash(1, 0, 0), + "m01s30i428": Stash(1, 0, 0), + "m01s30i429": Stash(1, 0, 0), + "m01s30i430": Stash(1, 0, 0), + "m01s30i431": Stash(1, 0, 0), + "m01s30i432": Stash(1, 0, 0), + "m01s30i433": Stash(1, 0, 0), + "m01s30i434": Stash(1, 0, 0), + "m01s30i435": Stash(1, 0, 0), + "m01s30i436": Stash(1, 0, 0), + "m01s30i437": Stash(1, 0, 0), + "m01s30i438": Stash(1, 0, 0), + "m01s30i439": Stash(1, 0, 0), + "m01s30i440": Stash(18, 0, 0), + "m01s30i441": Stash(19, 0, 0), + "m01s30i442": Stash(1, 0, 0), + "m01s30i451": Stash(1, 8, 0), + "m01s30i452": Stash(1, 16, 0), + "m01s30i453": Stash(1, 1, 0), + "m01s30i454": Stash(1, 4, 0), + "m01s31i001": Stash(29, 0, 0), + "m01s31i002": Stash(27, 0, 0), + "m01s31i003": Stash(28, 0, 0), + "m01s31i004": Stash(26, 0, 0), + "m01s31i005": Stash(26, 0, 0), + "m01s31i006": Stash(26, 0, 0), + "m01s31i007": Stash(26, 0, 0), + "m01s31i008": Stash(26, 0, 0), + "m01s31i009": Stash(26, 0, 0), + "m01s31i010": Stash(26, 0, 0), + "m01s31i011": Stash(27, 0, 0), + "m01s31i012": Stash(28, 0, 0), + "m01s31i013": Stash(26, 0, 0), + "m01s31i014": Stash(26, 0, 0), + "m01s31i015": Stash(26, 0, 0), + "m01s31i016": Stash(26, 0, 0), + "m01s31i017": Stash(26, 0, 0), + "m01s31i018": Stash(26, 0, 0), + "m01s31i019": Stash(26, 0, 0), + "m01s31i020": Stash(26, 0, 0), + "m01s31i023": Stash(26, 0, 0), + "m01s31i024": Stash(26, 0, 0), + "m01s31i025": Stash(26, 0, 0), + "m01s31i026": Stash(26, 0, 0), + "m01s31i027": Stash(26, 0, 0), + "m01s31i028": Stash(26, 0, 0), + "m01s31i029": Stash(26, 0, 0), + "m01s31i030": Stash(26, 0, 0), + "m01s31i031": Stash(26, 0, 0), + "m01s31i032": Stash(26, 0, 0), + "m01s31i033": Stash(26, 0, 0), + "m01s31i035": Stash(26, 0, 0), + "m01s31i036": Stash(26, 0, 0), + "m01s31i037": Stash(26, 0, 0), + "m01s31i038": Stash(26, 0, 0), + "m01s31i039": Stash(26, 0, 0), + "m01s31i040": Stash(26, 0, 0), + "m01s31i041": Stash(26, 0, 0), + "m01s31i042": Stash(26, 0, 0), + "m01s31i043": Stash(26, 0, 0), + "m01s31i044": Stash(26, 0, 0), + "m01s31i045": Stash(26, 0, 0), + "m01s31i046": Stash(26, 0, 0), + "m01s31i257": Stash(27, 0, 0), + "m01s31i258": Stash(28, 0, 0), + "m01s31i259": Stash(26, 0, 0), + "m01s31i260": Stash(26, 0, 0), + "m01s31i261": Stash(26, 0, 0), + "m01s31i262": Stash(26, 0, 0), + "m01s31i263": Stash(26, 0, 0), + "m01s31i264": Stash(26, 0, 0), + "m01s31i265": Stash(26, 0, 0), + "m01s31i266": Stash(27, 0, 0), + "m01s31i267": Stash(28, 0, 0), + "m01s31i268": Stash(26, 0, 0), + "m01s31i269": Stash(26, 0, 0), + "m01s31i270": Stash(26, 0, 0), + "m01s31i271": Stash(26, 0, 0), + "m01s31i272": Stash(26, 0, 0), + "m01s31i273": Stash(26, 0, 0), + "m01s31i274": Stash(26, 0, 0), + "m01s31i275": Stash(26, 0, 0), + "m01s31i276": Stash(26, 0, 0), + "m01s31i277": Stash(26, 0, 0), + "m01s31i278": Stash(26, 0, 0), + "m01s31i279": Stash(26, 0, 0), + "m01s31i280": Stash(26, 0, 0), + "m01s31i281": Stash(26, 0, 0), + "m01s31i282": Stash(26, 0, 0), + "m01s31i283": Stash(26, 0, 0), + "m01s31i284": Stash(26, 0, 0), + "m01s31i285": Stash(26, 0, 0), + "m01s31i286": Stash(26, 0, 0), + "m01s31i288": Stash(26, 0, 0), + "m01s31i289": Stash(26, 0, 0), + "m01s31i290": Stash(26, 0, 0), + "m01s31i291": Stash(26, 0, 0), + "m01s31i292": Stash(26, 0, 0), + "m01s31i293": Stash(26, 0, 0), + "m01s31i294": Stash(26, 0, 0), + "m01s31i295": Stash(26, 0, 0), + "m01s31i296": Stash(26, 0, 0), + "m01s31i297": Stash(26, 0, 0), + "m01s31i298": Stash(26, 0, 0), + "m01s31i299": Stash(26, 0, 0), + "m01s32i001": Stash(29, 0, 0), + "m01s32i002": Stash(27, 0, 0), + "m01s32i003": Stash(28, 0, 0), + "m01s32i004": Stash(26, 0, 0), + "m01s32i005": Stash(26, 0, 0), + "m01s32i006": Stash(26, 0, 0), + "m01s32i007": Stash(26, 0, 0), + "m01s32i008": Stash(26, 0, 0), + "m01s32i009": Stash(26, 0, 0), + "m01s32i010": Stash(26, 0, 0), + "m01s32i011": Stash(27, 0, 0), + "m01s32i012": Stash(28, 0, 0), + "m01s32i013": Stash(26, 0, 0), + "m01s32i014": Stash(26, 0, 0), + "m01s32i015": Stash(26, 0, 0), + "m01s32i016": Stash(26, 0, 0), + "m01s32i017": Stash(26, 0, 0), + "m01s32i018": Stash(26, 0, 0), + "m01s32i019": Stash(26, 0, 0), + "m01s32i020": Stash(26, 0, 0), + "m01s32i021": Stash(26, 0, 0), + "m01s32i022": Stash(26, 0, 0), + "m01s32i023": Stash(26, 0, 0), + "m01s32i024": Stash(26, 0, 0), + "m01s32i025": Stash(26, 0, 0), + "m01s32i026": Stash(26, 0, 0), + "m01s32i027": Stash(26, 0, 0), + "m01s32i028": Stash(26, 0, 0), + "m01s32i029": Stash(26, 0, 0), + "m01s32i030": Stash(26, 0, 0), + "m01s32i031": Stash(26, 0, 0), + "m01s32i032": Stash(26, 0, 0), + "m01s32i033": Stash(26, 0, 0), + "m01s32i035": Stash(26, 0, 0), + "m01s32i036": Stash(26, 0, 0), + "m01s32i037": Stash(26, 0, 0), + "m01s32i038": Stash(26, 0, 0), + "m01s32i039": Stash(26, 0, 0), + "m01s32i040": Stash(26, 0, 0), + "m01s32i041": Stash(26, 0, 0), + "m01s32i042": Stash(26, 0, 0), + "m01s32i043": Stash(26, 0, 0), + "m01s32i044": Stash(26, 0, 0), + "m01s32i045": Stash(26, 0, 0), + "m01s32i046": Stash(26, 0, 0), + "m01s33i001": Stash(1, 501, 0), + "m01s33i002": Stash(1, 502, 0), + "m01s33i003": Stash(1, 503, 0), + "m01s33i004": Stash(1, 504, 0), + "m01s33i005": Stash(1, 505, 0), + "m01s33i006": Stash(1, 506, 0), + "m01s33i007": Stash(1, 507, 0), + "m01s33i008": Stash(1, 508, 0), + "m01s33i009": Stash(1, 509, 0), + "m01s33i010": Stash(1, 510, 0), + "m01s33i011": Stash(1, 511, 0), + "m01s33i012": Stash(1, 512, 0), + "m01s33i013": Stash(1, 513, 0), + "m01s33i014": Stash(1, 514, 0), + "m01s33i015": Stash(1, 515, 0), + "m01s33i016": Stash(1, 516, 0), + "m01s33i017": Stash(1, 517, 0), + "m01s33i018": Stash(1, 518, 0), + "m01s33i019": Stash(1, 519, 0), + "m01s33i020": Stash(1, 520, 0), + "m01s33i021": Stash(1, 521, 0), + "m01s33i022": Stash(1, 522, 0), + "m01s33i023": Stash(1, 523, 0), + "m01s33i024": Stash(1, 524, 0), + "m01s33i025": Stash(1, 525, 0), + "m01s33i026": Stash(1, 526, 0), + "m01s33i027": Stash(1, 527, 0), + "m01s33i028": Stash(1, 528, 0), + "m01s33i029": Stash(1, 529, 0), + "m01s33i030": Stash(1, 530, 0), + "m01s33i031": Stash(1, 0, 0), + "m01s33i032": Stash(1, 0, 0), + "m01s33i033": Stash(1, 0, 0), + "m01s33i034": Stash(1, 0, 0), + "m01s33i035": Stash(1, 0, 0), + "m01s33i036": Stash(1, 0, 0), + "m01s33i037": Stash(1, 501, 0), + "m01s33i038": Stash(1, 501, 0), + "m01s33i039": Stash(1, 501, 0), + "m01s33i040": Stash(1, 501, 0), + "m01s33i041": Stash(1, 501, 0), + "m01s33i042": Stash(1, 501, 0), + "m01s33i043": Stash(1, 501, 0), + "m01s33i044": Stash(1, 501, 0), + "m01s33i045": Stash(1, 501, 0), + "m01s33i046": Stash(1, 501, 0), + "m01s33i047": Stash(1, 501, 0), + "m01s33i048": Stash(1, 501, 0), + "m01s33i049": Stash(1, 501, 0), + "m01s33i050": Stash(1, 501, 0), + "m01s33i051": Stash(1, 501, 0), + "m01s33i052": Stash(1, 501, 0), + "m01s33i053": Stash(1, 501, 0), + "m01s33i054": Stash(1, 501, 0), + "m01s33i055": Stash(1, 501, 0), + "m01s33i056": Stash(1, 501, 0), + "m01s33i057": Stash(1, 501, 0), + "m01s33i058": Stash(1, 501, 0), + "m01s33i059": Stash(1, 501, 0), + "m01s33i060": Stash(1, 501, 0), + "m01s33i061": Stash(1, 501, 0), + "m01s33i062": Stash(1, 501, 0), + "m01s33i063": Stash(1, 501, 0), + "m01s33i064": Stash(1, 501, 0), + "m01s33i065": Stash(1, 501, 0), + "m01s33i066": Stash(1, 501, 0), + "m01s33i067": Stash(1, 501, 0), + "m01s33i068": Stash(1, 501, 0), + "m01s33i069": Stash(1, 501, 0), + "m01s33i070": Stash(1, 501, 0), + "m01s33i071": Stash(1, 501, 0), + "m01s33i072": Stash(1, 501, 0), + "m01s33i073": Stash(1, 501, 0), + "m01s33i074": Stash(1, 501, 0), + "m01s33i075": Stash(1, 501, 0), + "m01s33i076": Stash(1, 501, 0), + "m01s33i077": Stash(1, 501, 0), + "m01s33i078": Stash(1, 501, 0), + "m01s33i079": Stash(1, 501, 0), + "m01s33i080": Stash(1, 501, 0), + "m01s33i081": Stash(1, 501, 0), + "m01s33i082": Stash(1, 501, 0), + "m01s33i083": Stash(1, 501, 0), + "m01s33i084": Stash(1, 501, 0), + "m01s33i085": Stash(1, 501, 0), + "m01s33i086": Stash(1, 501, 0), + "m01s33i087": Stash(1, 501, 0), + "m01s33i088": Stash(1, 501, 0), + "m01s33i089": Stash(1, 501, 0), + "m01s33i090": Stash(1, 501, 0), + "m01s33i091": Stash(1, 501, 0), + "m01s33i092": Stash(1, 501, 0), + "m01s33i093": Stash(1, 501, 0), + "m01s33i094": Stash(1, 501, 0), + "m01s33i095": Stash(1, 501, 0), + "m01s33i096": Stash(1, 501, 0), + "m01s33i097": Stash(1, 501, 0), + "m01s33i098": Stash(1, 501, 0), + "m01s33i099": Stash(1, 501, 0), + "m01s33i100": Stash(1, 501, 0), + "m01s33i101": Stash(1, 501, 0), + "m01s33i102": Stash(1, 501, 0), + "m01s33i103": Stash(1, 501, 0), + "m01s33i104": Stash(1, 501, 0), + "m01s33i105": Stash(1, 501, 0), + "m01s33i106": Stash(1, 501, 0), + "m01s33i107": Stash(1, 501, 0), + "m01s33i108": Stash(1, 501, 0), + "m01s33i109": Stash(1, 501, 0), + "m01s33i110": Stash(1, 501, 0), + "m01s33i111": Stash(1, 501, 0), + "m01s33i112": Stash(1, 501, 0), + "m01s33i113": Stash(1, 501, 0), + "m01s33i114": Stash(1, 501, 0), + "m01s33i115": Stash(1, 501, 0), + "m01s33i116": Stash(1, 501, 0), + "m01s33i117": Stash(1, 501, 0), + "m01s33i118": Stash(1, 501, 0), + "m01s33i119": Stash(1, 501, 0), + "m01s33i120": Stash(1, 501, 0), + "m01s33i121": Stash(1, 501, 0), + "m01s33i122": Stash(1, 501, 0), + "m01s33i123": Stash(1, 501, 0), + "m01s33i124": Stash(1, 501, 0), + "m01s33i125": Stash(1, 501, 0), + "m01s33i126": Stash(1, 501, 0), + "m01s33i127": Stash(1, 501, 0), + "m01s33i128": Stash(1, 501, 0), + "m01s33i129": Stash(1, 501, 0), + "m01s33i130": Stash(1, 501, 0), + "m01s33i131": Stash(1, 501, 0), + "m01s33i132": Stash(1, 501, 0), + "m01s33i133": Stash(1, 501, 0), + "m01s33i134": Stash(1, 501, 0), + "m01s33i135": Stash(1, 501, 0), + "m01s33i136": Stash(1, 501, 0), + "m01s33i137": Stash(1, 501, 0), + "m01s33i138": Stash(1, 501, 0), + "m01s33i139": Stash(1, 501, 0), + "m01s33i140": Stash(1, 501, 0), + "m01s33i141": Stash(1, 501, 0), + "m01s33i142": Stash(1, 501, 0), + "m01s33i143": Stash(1, 501, 0), + "m01s33i144": Stash(1, 501, 0), + "m01s33i145": Stash(1, 501, 0), + "m01s33i146": Stash(1, 501, 0), + "m01s33i147": Stash(1, 501, 0), + "m01s33i148": Stash(1, 501, 0), + "m01s33i149": Stash(1, 501, 0), + "m01s33i150": Stash(1, 501, 0), + "m01s33i151": Stash(1, 581, 0), + "m01s33i152": Stash(1, 0, 0), + "m01s33i153": Stash(1, 0, 0), + "m01s33i154": Stash(1, 0, 0), + "m01s33i155": Stash(1, 0, 0), + "m01s33i156": Stash(1, 0, 0), + "m01s33i157": Stash(1, 0, 0), + "m01s33i158": Stash(1, 0, 0), + "m01s33i159": Stash(1, 0, 0), + "m01s33i160": Stash(1, 0, 0), + "m01s33i161": Stash(1, 0, 0), + "m01s33i162": Stash(1, 0, 0), + "m01s33i163": Stash(1, 0, 0), + "m01s33i164": Stash(1, 0, 0), + "m01s33i165": Stash(1, 0, 0), + "m01s33i166": Stash(1, 0, 0), + "m01s33i167": Stash(1, 667, 0), + "m01s33i168": Stash(1, 668, 0), + "m01s33i169": Stash(1, 669, 0), + "m01s33i170": Stash(1, 670, 0), + "m01s33i171": Stash(1, 671, 0), + "m01s33i172": Stash(1, 672, 0), + "m01s33i173": Stash(1, 673, 0), + "m01s33i301": Stash(1, 1878, 0), + "m01s33i302": Stash(1, 502, 0), + "m01s33i303": Stash(1, 503, 0), + "m01s33i304": Stash(1, 504, 0), + "m01s33i305": Stash(1, 505, 0), + "m01s33i306": Stash(1, 506, 0), + "m01s33i307": Stash(1, 507, 0), + "m01s33i308": Stash(1, 508, 0), + "m01s33i309": Stash(1, 509, 0), + "m01s33i310": Stash(1, 510, 0), + "m01s33i311": Stash(1, 511, 0), + "m01s33i312": Stash(1, 512, 0), + "m01s33i313": Stash(1, 513, 0), + "m01s33i314": Stash(1, 514, 0), + "m01s33i315": Stash(1, 515, 0), + "m01s33i316": Stash(1, 516, 0), + "m01s33i317": Stash(1, 517, 0), + "m01s33i318": Stash(1, 518, 0), + "m01s33i319": Stash(1, 519, 0), + "m01s33i320": Stash(1, 520, 0), + "m01s33i321": Stash(1, 521, 0), + "m01s33i322": Stash(1, 522, 0), + "m01s33i323": Stash(1, 523, 0), + "m01s33i324": Stash(1, 524, 0), + "m01s33i325": Stash(1, 525, 0), + "m01s33i326": Stash(1, 526, 0), + "m01s33i327": Stash(1, 527, 0), + "m01s33i328": Stash(1, 528, 0), + "m01s33i329": Stash(1, 529, 0), + "m01s33i330": Stash(1, 530, 0), + "m01s33i331": Stash(1, 0, 0), + "m01s33i332": Stash(1, 0, 0), + "m01s33i333": Stash(1, 0, 0), + "m01s33i334": Stash(1, 0, 0), + "m01s33i335": Stash(1, 0, 0), + "m01s33i336": Stash(1, 0, 0), + "m01s33i337": Stash(1, 0, 0), + "m01s33i338": Stash(1, 0, 0), + "m01s33i339": Stash(1, 0, 0), + "m01s33i340": Stash(1, 0, 0), + "m01s33i341": Stash(1, 0, 0), + "m01s33i342": Stash(1, 0, 0), + "m01s33i343": Stash(1, 0, 0), + "m01s33i344": Stash(1, 0, 0), + "m01s33i345": Stash(1, 0, 0), + "m01s33i346": Stash(1, 0, 0), + "m01s33i347": Stash(1, 0, 0), + "m01s33i348": Stash(1, 0, 0), + "m01s33i349": Stash(1, 0, 0), + "m01s33i350": Stash(1, 0, 0), + "m01s33i351": Stash(1, 0, 0), + "m01s33i352": Stash(1, 0, 0), + "m01s33i353": Stash(1, 0, 0), + "m01s33i354": Stash(1, 0, 0), + "m01s33i355": Stash(1, 0, 0), + "m01s33i356": Stash(1, 0, 0), + "m01s33i357": Stash(1, 0, 0), + "m01s33i358": Stash(1, 0, 0), + "m01s33i359": Stash(1, 0, 0), + "m01s33i360": Stash(1, 0, 0), + "m01s33i361": Stash(1, 0, 0), + "m01s33i362": Stash(1, 0, 0), + "m01s33i363": Stash(1, 0, 0), + "m01s33i364": Stash(1, 0, 0), + "m01s33i365": Stash(1, 0, 0), + "m01s33i366": Stash(1, 0, 0), + "m01s33i367": Stash(1, 0, 0), + "m01s33i368": Stash(1, 568, 0), + "m01s33i369": Stash(1, 569, 0), + "m01s33i370": Stash(1, 570, 0), + "m01s33i371": Stash(1, 571, 0), + "m01s33i372": Stash(1, 572, 0), + "m01s33i373": Stash(1, 573, 0), + "m01s33i374": Stash(1, 574, 0), + "m01s33i375": Stash(1, 575, 0), + "m01s33i376": Stash(1, 576, 0), + "m01s33i377": Stash(1, 0, 0), + "m01s33i378": Stash(1, 0, 0), + "m01s33i379": Stash(1, 0, 0), + "m01s33i380": Stash(1, 580, 0), + "m01s33i381": Stash(1, 581, 0), + "m01s33i382": Stash(1, 0, 0), + "m01s33i383": Stash(1, 0, 0), + "m01s33i384": Stash(1, 0, 0), + "m01s33i385": Stash(1, 0, 0), + "m01s33i386": Stash(1, 0, 0), + "m01s33i387": Stash(1, 0, 0), + "m01s33i388": Stash(1, 0, 0), + "m01s33i389": Stash(1, 0, 0), + "m01s33i390": Stash(1, 0, 0), + "m01s33i391": Stash(1, 0, 0), + "m01s33i392": Stash(1, 0, 0), + "m01s33i393": Stash(1, 0, 0), + "m01s33i394": Stash(1, 0, 0), + "m01s33i395": Stash(1, 0, 0), + "m01s33i396": Stash(1, 0, 0), + "m01s33i397": Stash(1, 0, 0), + "m01s33i398": Stash(1, 0, 0), + "m01s33i399": Stash(1, 0, 0), + "m01s33i400": Stash(1, 600, 0), + "m01s33i401": Stash(1, 601, 0), + "m01s33i402": Stash(1, 602, 0), + "m01s33i403": Stash(1, 603, 0), + "m01s33i404": Stash(1, 604, 0), + "m01s33i405": Stash(1, 605, 0), + "m01s33i406": Stash(1, 606, 0), + "m01s33i407": Stash(1, 607, 0), + "m01s33i408": Stash(1, 608, 0), + "m01s33i409": Stash(1, 609, 0), + "m01s33i410": Stash(1, 610, 0), + "m01s33i411": Stash(1, 611, 0), + "m01s33i412": Stash(1, 612, 0), + "m01s33i413": Stash(1, 613, 0), + "m01s33i414": Stash(1, 614, 0), + "m01s33i415": Stash(1, 615, 0), + "m01s33i416": Stash(1, 616, 0), + "m01s33i417": Stash(1, 617, 0), + "m01s33i418": Stash(1, 618, 0), + "m01s33i419": Stash(1, 619, 0), + "m01s33i420": Stash(1, 620, 0), + "m01s33i421": Stash(1, 621, 0), + "m01s33i422": Stash(1, 622, 0), + "m01s33i423": Stash(1, 623, 0), + "m01s33i424": Stash(1, 624, 0), + "m01s33i425": Stash(1, 625, 0), + "m01s33i426": Stash(1, 626, 0), + "m01s33i427": Stash(1, 627, 0), + "m01s33i428": Stash(1, 628, 0), + "m01s33i429": Stash(1, 629, 0), + "m01s33i430": Stash(1, 630, 0), + "m01s33i431": Stash(1, 631, 0), + "m01s33i432": Stash(1, 632, 0), + "m01s33i433": Stash(1, 633, 0), + "m01s33i434": Stash(1, 634, 0), + "m01s33i435": Stash(1, 635, 0), + "m01s33i436": Stash(1, 636, 0), + "m01s33i437": Stash(1, 637, 0), + "m01s33i438": Stash(1, 638, 0), + "m01s33i439": Stash(1, 639, 0), + "m01s33i440": Stash(1, 640, 0), + "m01s33i441": Stash(1, 641, 0), + "m01s33i442": Stash(1, 642, 0), + "m01s33i443": Stash(1, 643, 0), + "m01s33i444": Stash(1, 644, 0), + "m01s33i445": Stash(1, 645, 0), + "m01s33i446": Stash(1, 646, 0), + "m01s33i447": Stash(1, 647, 0), + "m01s33i448": Stash(1, 648, 0), + "m01s33i449": Stash(1, 649, 0), + "m01s33i450": Stash(1, 650, 0), + "m01s33i451": Stash(1, 651, 0), + "m01s33i452": Stash(1, 652, 0), + "m01s33i453": Stash(1, 653, 0), + "m01s33i454": Stash(1, 654, 0), + "m01s33i455": Stash(1, 655, 0), + "m01s33i456": Stash(1, 656, 0), + "m01s33i457": Stash(1, 657, 0), + "m01s33i458": Stash(1, 658, 0), + "m01s33i459": Stash(1, 659, 0), + "m01s33i460": Stash(1, 660, 0), + "m01s33i461": Stash(1, 661, 0), + "m01s33i462": Stash(1, 662, 0), + "m01s33i463": Stash(1, 653, 0), + "m01s33i464": Stash(1, 664, 0), + "m01s33i465": Stash(1, 665, 0), + "m01s33i466": Stash(1, 666, 0), + "m01s33i467": Stash(1, 667, 0), + "m01s33i468": Stash(1, 668, 0), + "m01s33i469": Stash(1, 669, 0), + "m01s33i470": Stash(1, 670, 0), + "m01s33i481": Stash(1, 671, 0), + "m01s33i482": Stash(1, 672, 0), + "m01s33i483": Stash(1, 673, 0), + "m01s33i484": Stash(1, 674, 0), + "m01s33i485": Stash(1, 675, 0), + "m01s33i486": Stash(1, 676, 0), + "m01s33i487": Stash(1, 677, 0), + "m01s33i488": Stash(1, 678, 0), + "m01s33i489": Stash(1, 679, 0), + "m01s33i490": Stash(1, 680, 0), + "m01s33i491": Stash(1, 681, 0), + "m01s33i492": Stash(1, 682, 0), + "m01s33i493": Stash(1, 683, 0), + "m01s33i494": Stash(1, 684, 0), + "m01s33i495": Stash(1, 685, 0), + "m01s33i496": Stash(1, 686, 0), + "m01s33i497": Stash(1, 687, 0), + "m01s33i498": Stash(1, 688, 0), + "m01s33i499": Stash(1, 689, 0), + "m01s33i500": Stash(1, 690, 0), + "m01s33i501": Stash(1, 691, 0), + "m01s33i502": Stash(1, 692, 0), + "m01s33i503": Stash(1, 693, 0), + "m01s33i504": Stash(1, 694, 0), + "m01s33i505": Stash(1, 695, 0), + "m01s33i506": Stash(1, 696, 0), + "m01s34i001": Stash(1, 2101, 0), + "m01s34i002": Stash(1, 2102, 0), + "m01s34i003": Stash(1, 2103, 0), + "m01s34i004": Stash(1, 2104, 0), + "m01s34i005": Stash(1, 2105, 0), + "m01s34i006": Stash(1, 2106, 0), + "m01s34i007": Stash(1, 2107, 0), + "m01s34i008": Stash(1, 2108, 0), + "m01s34i009": Stash(1, 2109, 0), + "m01s34i010": Stash(1, 2110, 0), + "m01s34i011": Stash(1, 2111, 0), + "m01s34i012": Stash(1, 2112, 0), + "m01s34i013": Stash(1, 2113, 0), + "m01s34i014": Stash(1, 2114, 0), + "m01s34i015": Stash(1, 2115, 0), + "m01s34i016": Stash(1, 2116, 0), + "m01s34i017": Stash(1, 2117, 0), + "m01s34i018": Stash(1, 2118, 0), + "m01s34i019": Stash(1, 2119, 0), + "m01s34i020": Stash(1, 2120, 0), + "m01s34i021": Stash(1, 2121, 0), + "m01s34i022": Stash(1, 2122, 0), + "m01s34i023": Stash(1, 2123, 0), + "m01s34i024": Stash(1, 2124, 0), + "m01s34i025": Stash(1, 2125, 0), + "m01s34i026": Stash(1, 2126, 0), + "m01s34i027": Stash(1, 2127, 0), + "m01s34i028": Stash(1, 2128, 0), + "m01s34i029": Stash(1, 2129, 0), + "m01s34i030": Stash(1, 2130, 0), + "m01s34i031": Stash(1, 2131, 0), + "m01s34i032": Stash(1, 2132, 0), + "m01s34i033": Stash(1, 2133, 0), + "m01s34i034": Stash(1, 2134, 0), + "m01s34i035": Stash(1, 2135, 0), + "m01s34i036": Stash(1, 2136, 0), + "m01s34i037": Stash(1, 2137, 0), + "m01s34i038": Stash(1, 2138, 0), + "m01s34i039": Stash(1, 0, 0), + "m01s34i040": Stash(1, 2140, 0), + "m01s34i041": Stash(1, 2141, 0), + "m01s34i042": Stash(1, 2142, 0), + "m01s34i043": Stash(1, 2143, 0), + "m01s34i044": Stash(1, 2144, 0), + "m01s34i045": Stash(1, 2145, 0), + "m01s34i046": Stash(1, 1861, 0), + "m01s34i047": Stash(1, 2147, 0), + "m01s34i048": Stash(1, 2148, 0), + "m01s34i049": Stash(1, 2149, 0), + "m01s34i050": Stash(1, 1861, 0), + "m01s34i051": Stash(1, 2151, 0), + "m01s34i052": Stash(1, 2152, 0), + "m01s34i053": Stash(1, 2153, 0), + "m01s34i054": Stash(1, 2154, 0), + "m01s34i055": Stash(1, 2155, 0), + "m01s34i056": Stash(1, 2156, 0), + "m01s34i057": Stash(1, 2157, 0), + "m01s34i058": Stash(1, 2158, 0), + "m01s34i059": Stash(1, 2159, 0), + "m01s34i060": Stash(1, 2160, 0), + "m01s34i061": Stash(1, 1861, 0), + "m01s34i062": Stash(1, 1861, 0), + "m01s34i063": Stash(1, 1861, 0), + "m01s34i064": Stash(1, 1861, 0), + "m01s34i065": Stash(1, 1861, 0), + "m01s34i066": Stash(1, 1861, 0), + "m01s34i067": Stash(1, 1861, 0), + "m01s34i068": Stash(1, 1861, 0), + "m01s34i069": Stash(1, 0, 0), + "m01s34i070": Stash(1, 2170, 0), + "m01s34i071": Stash(1, 2171, 0), + "m01s34i072": Stash(1, 2172, 0), + "m01s34i073": Stash(1, 2173, 0), + "m01s34i074": Stash(1, 2174, 0), + "m01s34i075": Stash(1, 2175, 0), + "m01s34i076": Stash(1, 2176, 0), + "m01s34i077": Stash(1, 2177, 0), + "m01s34i078": Stash(1, 2178, 0), + "m01s34i079": Stash(1, 2179, 0), + "m01s34i080": Stash(1, 2180, 0), + "m01s34i081": Stash(1, 2181, 0), + "m01s34i082": Stash(1, 2182, 0), + "m01s34i083": Stash(1, 2183, 0), + "m01s34i084": Stash(1, 2184, 0), + "m01s34i085": Stash(1, 2185, 0), + "m01s34i086": Stash(1, 2186, 0), + "m01s34i087": Stash(1, 2187, 0), + "m01s34i088": Stash(1, 2188, 0), + "m01s34i089": Stash(1, 2189, 0), + "m01s34i090": Stash(1, 2190, 0), + "m01s34i091": Stash(1, 2191, 0), + "m01s34i092": Stash(1, 2192, 0), + "m01s34i093": Stash(1, 2193, 0), + "m01s34i094": Stash(1, 2194, 0), + "m01s34i095": Stash(1, 2195, 0), + "m01s34i096": Stash(1, 2196, 0), + "m01s34i097": Stash(1, 2197, 0), + "m01s34i098": Stash(1, 2198, 0), + "m01s34i099": Stash(1, 2199, 0), + "m01s34i100": Stash(1, 2200, 0), + "m01s34i101": Stash(1, 2201, 0), + "m01s34i102": Stash(1, 2202, 0), + "m01s34i103": Stash(1, 2203, 0), + "m01s34i104": Stash(1, 2204, 0), + "m01s34i105": Stash(1, 2205, 0), + "m01s34i106": Stash(1, 2206, 0), + "m01s34i107": Stash(1, 2207, 0), + "m01s34i108": Stash(1, 2208, 0), + "m01s34i109": Stash(1, 2209, 0), + "m01s34i110": Stash(1, 2210, 0), + "m01s34i111": Stash(1, 2211, 0), + "m01s34i112": Stash(1, 2212, 0), + "m01s34i113": Stash(1, 2213, 0), + "m01s34i114": Stash(1, 2214, 0), + "m01s34i115": Stash(1, 2215, 0), + "m01s34i116": Stash(1, 2216, 0), + "m01s34i117": Stash(1, 2217, 0), + "m01s34i118": Stash(1, 2218, 0), + "m01s34i119": Stash(1, 2219, 0), + "m01s34i120": Stash(1, 2220, 0), + "m01s34i121": Stash(1, 2221, 0), + "m01s34i122": Stash(1, 2222, 0), + "m01s34i123": Stash(1, 2223, 0), + "m01s34i124": Stash(1, 2224, 0), + "m01s34i125": Stash(1, 2225, 0), + "m01s34i126": Stash(1, 2226, 0), + "m01s34i127": Stash(1, 2227, 0), + "m01s34i128": Stash(1, 2228, 0), + "m01s34i129": Stash(1, 2229, 0), + "m01s34i130": Stash(1, 2230, 0), + "m01s34i131": Stash(1, 2231, 0), + "m01s34i132": Stash(1, 2232, 0), + "m01s34i133": Stash(1, 2233, 0), + "m01s34i134": Stash(1, 2234, 0), + "m01s34i135": Stash(1, 2235, 0), + "m01s34i136": Stash(1, 2236, 0), + "m01s34i137": Stash(1, 2237, 0), + "m01s34i138": Stash(1, 2238, 0), + "m01s34i139": Stash(1, 2239, 0), + "m01s34i140": Stash(1, 1861, 0), + "m01s34i141": Stash(1, 1861, 0), + "m01s34i142": Stash(1, 1861, 0), + "m01s34i143": Stash(1, 1861, 0), + "m01s34i144": Stash(1, 1861, 0), + "m01s34i145": Stash(1, 1861, 0), + "m01s34i146": Stash(1, 1861, 0), + "m01s34i147": Stash(1, 1861, 0), + "m01s34i148": Stash(1, 1861, 0), + "m01s34i149": Stash(1, 2249, 0), + "m01s34i150": Stash(1, 2250, 0), + "m01s34i151": Stash(1, 0, 0), + "m01s34i152": Stash(1, 0, 0), + "m01s34i153": Stash(1, 0, 0), + "m01s34i154": Stash(1, 0, 0), + "m01s34i155": Stash(1, 0, 0), + "m01s34i156": Stash(1, 0, 0), + "m01s34i157": Stash(1, 0, 0), + "m01s34i158": Stash(1, 0, 0), + "m01s34i159": Stash(1, 0, 0), + "m01s34i160": Stash(1, 0, 0), + "m01s34i161": Stash(1, 0, 0), + "m01s34i162": Stash(1, 0, 0), + "m01s34i163": Stash(1, 0, 0), + "m01s34i164": Stash(1, 0, 0), + "m01s34i165": Stash(1, 0, 0), + "m01s34i166": Stash(1, 0, 0), + "m01s34i167": Stash(1, 0, 0), + "m01s34i168": Stash(1, 0, 0), + "m01s34i169": Stash(1, 0, 0), + "m01s34i170": Stash(1, 0, 0), + "m01s34i171": Stash(1, 0, 0), + "m01s34i172": Stash(1, 0, 0), + "m01s34i173": Stash(1, 0, 0), + "m01s34i174": Stash(1, 1861, 0), + "m01s34i175": Stash(1, 1861, 0), + "m01s34i176": Stash(1, 1861, 0), + "m01s34i177": Stash(1, 1861, 0), + "m01s34i178": Stash(1, 1861, 0), + "m01s34i179": Stash(1, 1861, 0), + "m01s34i180": Stash(1, 1881, 0), + "m01s34i181": Stash(1, 1881, 0), + "m01s34i182": Stash(1, 1881, 0), + "m01s34i183": Stash(1, 1881, 0), + "m01s34i184": Stash(1, 1881, 0), + "m01s34i185": Stash(1, 1881, 0), + "m01s34i186": Stash(1, 1881, 0), + "m01s34i187": Stash(1, 1881, 0), + "m01s34i188": Stash(1, 1881, 0), + "m01s34i189": Stash(1, 1881, 0), + "m01s34i190": Stash(1, 1881, 0), + "m01s34i191": Stash(1, 1881, 0), + "m01s34i192": Stash(1, 1881, 0), + "m01s34i193": Stash(1, 1881, 0), + "m01s34i194": Stash(1, 1881, 0), + "m01s34i195": Stash(1, 1881, 0), + "m01s34i196": Stash(1, 1881, 0), + "m01s34i197": Stash(1, 1881, 0), + "m01s34i198": Stash(1, 1881, 0), + "m01s34i199": Stash(1, 1881, 0), + "m01s34i200": Stash(1, 1881, 0), + "m01s34i201": Stash(1, 1881, 0), + "m01s34i202": Stash(1, 1881, 0), + "m01s34i203": Stash(1, 1881, 0), + "m01s34i204": Stash(1, 1881, 0), + "m01s34i205": Stash(1, 1881, 0), + "m01s34i206": Stash(1, 1881, 0), + "m01s34i207": Stash(1, 1881, 0), + "m01s34i208": Stash(1, 1881, 0), + "m01s34i209": Stash(1, 1881, 0), + "m01s34i210": Stash(1, 1881, 0), + "m01s34i211": Stash(1, 1881, 0), + "m01s34i212": Stash(1, 1881, 0), + "m01s34i213": Stash(1, 1881, 0), + "m01s34i214": Stash(1, 1881, 0), + "m01s34i215": Stash(1, 1881, 0), + "m01s34i216": Stash(1, 1881, 0), + "m01s34i217": Stash(1, 1881, 0), + "m01s34i218": Stash(1, 1881, 0), + "m01s34i219": Stash(1, 1881, 0), + "m01s34i220": Stash(1, 1881, 0), + "m01s34i221": Stash(1, 1881, 0), + "m01s34i222": Stash(1, 1881, 0), + "m01s34i223": Stash(1, 1881, 0), + "m01s34i224": Stash(1, 1881, 0), + "m01s34i225": Stash(1, 1873, 11), + "m01s34i226": Stash(1, 1878, 11), + "m01s34i227": Stash(1, 1873, 11), + "m01s34i228": Stash(1, 1878, 11), + "m01s34i231": Stash(1, 1883, 0), + "m01s34i232": Stash(1, 1883, 0), + "m01s34i233": Stash(1, 8, 0), + "m01s34i234": Stash(1, 8, 0), + "m01s34i235": Stash(1, 8, 0), + "m01s34i236": Stash(1, 1875, 0), + "m01s34i237": Stash(1, 1875, 0), + "m01s34i238": Stash(1, 1875, 0), + "m01s34i239": Stash(1, 1875, 0), + "m01s34i240": Stash(1, 1875, 0), + "m01s34i241": Stash(1, 1875, 0), + "m01s34i242": Stash(1, 1875, 0), + "m01s34i243": Stash(1, 1875, 0), + "m01s34i244": Stash(1, 1875, 0), + "m01s34i245": Stash(1, 1875, 0), + "m01s34i246": Stash(1, 1875, 0), + "m01s34i247": Stash(1, 1875, 0), + "m01s34i248": Stash(1, 1875, 0), + "m01s34i249": Stash(1, 1875, 0), + "m01s34i250": Stash(1, 1875, 0), + "m01s34i251": Stash(1, 1875, 0), + "m01s34i252": Stash(1, 1875, 0), + "m01s34i253": Stash(1, 1875, 0), + "m01s34i254": Stash(1, 1875, 0), + "m01s34i255": Stash(1, 1875, 0), + "m01s34i256": Stash(1, 1875, 0), + "m01s34i257": Stash(1, 1875, 0), + "m01s34i258": Stash(1, 1875, 0), + "m01s34i259": Stash(1, 1875, 0), + "m01s34i260": Stash(1, 1875, 0), + "m01s34i261": Stash(1, 1875, 0), + "m01s34i262": Stash(1, 1875, 0), + "m01s34i263": Stash(1, 1875, 0), + "m01s34i264": Stash(1, 1875, 0), + "m01s34i265": Stash(1, 1875, 0), + "m01s34i266": Stash(1, 1875, 0), + "m01s34i267": Stash(1, 1875, 0), + "m01s34i268": Stash(1, 1875, 0), + "m01s34i269": Stash(1, 1875, 0), + "m01s34i270": Stash(1, 1875, 0), + "m01s34i271": Stash(1, 1875, 0), + "m01s34i272": Stash(1, 1875, 0), + "m01s34i273": Stash(1, 1875, 0), + "m01s34i274": Stash(1, 1875, 0), + "m01s34i275": Stash(1, 1875, 0), + "m01s34i276": Stash(1, 1875, 0), + "m01s34i277": Stash(1, 1875, 0), + "m01s34i278": Stash(1, 1875, 0), + "m01s34i279": Stash(1, 1875, 0), + "m01s34i280": Stash(1, 1875, 0), + "m01s34i281": Stash(1, 1875, 0), + "m01s34i282": Stash(1, 1875, 0), + "m01s34i283": Stash(1, 1875, 0), + "m01s34i284": Stash(1, 1875, 0), + "m01s34i285": Stash(1, 1875, 0), + "m01s34i286": Stash(1, 1875, 0), + "m01s34i287": Stash(1, 1875, 0), + "m01s34i288": Stash(1, 1875, 0), + "m01s34i289": Stash(1, 1875, 0), + "m01s34i290": Stash(1, 1875, 0), + "m01s34i291": Stash(1, 1875, 0), + "m01s34i292": Stash(1, 1875, 0), + "m01s34i293": Stash(1, 1875, 0), + "m01s34i294": Stash(1, 1875, 0), + "m01s34i295": Stash(1, 1875, 0), + "m01s34i296": Stash(1, 1875, 0), + "m01s34i297": Stash(1, 1875, 0), + "m01s34i298": Stash(1, 1875, 0), + "m01s34i299": Stash(1, 1875, 0), + "m01s34i300": Stash(1, 1875, 0), + "m01s34i301": Stash(1, 1871, 0), + "m01s34i302": Stash(1, 1871, 0), + "m01s34i303": Stash(1, 1871, 0), + "m01s34i304": Stash(1, 1871, 0), + "m01s34i305": Stash(1, 1871, 0), + "m01s34i306": Stash(1, 1871, 0), + "m01s34i307": Stash(1, 1871, 0), + "m01s34i308": Stash(1, 1875, 0), + "m01s34i309": Stash(1, 1875, 0), + "m01s34i310": Stash(1, 1875, 0), + "m01s34i311": Stash(1, 1871, 0), + "m01s34i312": Stash(1, 1871, 0), + "m01s34i313": Stash(1, 1871, 0), + "m01s34i314": Stash(1, 1871, 0), + "m01s34i315": Stash(1, 1871, 0), + "m01s34i316": Stash(1, 1871, 0), + "m01s34i317": Stash(1, 1871, 0), + "m01s34i318": Stash(1, 1875, 0), + "m01s34i319": Stash(1, 1875, 0), + "m01s34i320": Stash(1, 1875, 0), + "m01s34i321": Stash(1, 1871, 0), + "m01s34i322": Stash(1, 1871, 0), + "m01s34i323": Stash(1, 1875, 0), + "m01s34i324": Stash(1, 1875, 0), + "m01s34i325": Stash(1, 1875, 0), + "m01s34i326": Stash(1, 1875, 0), + "m01s34i327": Stash(1, 1875, 0), + "m01s34i328": Stash(1, 1875, 0), + "m01s34i329": Stash(1, 1875, 0), + "m01s34i330": Stash(1, 1875, 0), + "m01s34i331": Stash(1, 1871, 0), + "m01s34i332": Stash(1, 1875, 0), + "m01s34i333": Stash(1, 1875, 0), + "m01s34i334": Stash(1, 1875, 0), + "m01s34i335": Stash(1, 1875, 0), + "m01s34i336": Stash(1, 1875, 0), + "m01s34i337": Stash(1, 1875, 0), + "m01s34i338": Stash(1, 1875, 0), + "m01s34i341": Stash(1, 1871, 0), + "m01s34i342": Stash(1, 1871, 0), + "m01s34i343": Stash(1, 1871, 0), + "m01s34i344": Stash(1, 1871, 0), + "m01s34i345": Stash(1, 1871, 0), + "m01s34i346": Stash(1, 1871, 0), + "m01s34i351": Stash(1, 1871, 0), + "m01s34i352": Stash(1, 1871, 0), + "m01s34i353": Stash(1, 1861, 0), + "m01s34i354": Stash(1, 1871, 0), + "m01s34i361": Stash(1, 1902, 0), + "m01s34i362": Stash(1, 0, 0), + "m01s34i363": Stash(1, 1902, 0), + "m01s34i371": Stash(1, 1871, 0), + "m01s34i372": Stash(1, 1871, 0), + "m01s34i373": Stash(1, 1871, 0), + "m01s34i374": Stash(1, 1871, 0), + "m01s34i375": Stash(1, 1871, 0), + "m01s34i376": Stash(1, 1871, 0), + "m01s34i377": Stash(1, 1871, 0), + "m01s34i378": Stash(1, 1871, 0), + "m01s34i379": Stash(1, 1871, 0), + "m01s34i380": Stash(1, 1875, 0), + "m01s34i381": Stash(1, 1871, 0), + "m01s34i382": Stash(1, 0, 0), + "m01s34i383": Stash(1, 0, 0), + "m01s34i384": Stash(1, 0, 0), + "m01s34i385": Stash(1, 1875, 0), + "m01s34i386": Stash(1, 1876, 0), + "m01s34i391": Stash(1, 1871, 0), + "m01s34i392": Stash(1, 1871, 0), + "m01s34i401": Stash(1, 1871, 0), + "m01s34i402": Stash(1, 1871, 0), + "m01s34i403": Stash(1, 1871, 0), + "m01s34i404": Stash(1, 1871, 0), + "m01s34i405": Stash(1, 1875, 0), + "m01s34i406": Stash(1, 1875, 0), + "m01s34i407": Stash(1, 1875, 0), + "m01s34i408": Stash(1, 1875, 0), + "m01s34i409": Stash(1, 1875, 0), + "m01s34i410": Stash(1, 1875, 0), + "m01s34i411": Stash(1, 1871, 0), + "m01s34i412": Stash(1, 1871, 0), + "m01s34i413": Stash(1, 1871, 0), + "m01s34i414": Stash(1, 1871, 0), + "m01s34i415": Stash(1, 1871, 0), + "m01s34i416": Stash(1, 1871, 0), + "m01s34i417": Stash(1, 1871, 0), + "m01s34i418": Stash(1, 1871, 0), + "m01s34i419": Stash(1, 1871, 0), + "m01s34i420": Stash(1, 1871, 0), + "m01s34i421": Stash(1, 1871, 0), + "m01s34i422": Stash(1, 1871, 0), + "m01s34i423": Stash(1, 1871, 0), + "m01s34i424": Stash(1, 1871, 0), + "m01s34i425": Stash(1, 1871, 0), + "m01s34i426": Stash(1, 1875, 0), + "m01s34i427": Stash(1, 1875, 0), + "m01s34i428": Stash(1, 1875, 0), + "m01s34i429": Stash(1, 1875, 0), + "m01s34i431": Stash(1, 1871, 0), + "m01s34i432": Stash(1, 1871, 0), + "m01s34i433": Stash(1, 1871, 0), + "m01s34i438": Stash(1, 1875, 0), + "m01s34i439": Stash(1, 1875, 0), + "m01s34i440": Stash(1, 1871, 0), + "m01s34i441": Stash(1, 1871, 0), + "m01s34i442": Stash(1, 1871, 0), + "m01s34i443": Stash(1, 1871, 0), + "m01s34i444": Stash(1, 1871, 0), + "m01s34i445": Stash(1, 1871, 0), + "m01s34i446": Stash(1, 1871, 0), + "m01s34i447": Stash(1, 1871, 0), + "m01s34i448": Stash(1, 1871, 0), + "m01s34i449": Stash(1, 1871, 0), + "m01s34i450": Stash(1, 1871, 0), + "m01s34i451": Stash(1, 1871, 0), + "m01s34i452": Stash(1, 1871, 0), + "m01s34i453": Stash(1, 1871, 0), + "m01s34i454": Stash(1, 1871, 0), + "m01s34i455": Stash(1, 1871, 0), + "m01s34i456": Stash(1, 1875, 0), + "m01s34i457": Stash(1, 1875, 0), + "m01s34i458": Stash(1, 1875, 0), + "m01s34i459": Stash(1, 1875, 0), + "m01s34i460": Stash(1, 1875, 0), + "m01s34i461": Stash(1, 1875, 0), + "m01s34i462": Stash(1, 1875, 0), + "m01s34i483": Stash(1, 1875, 0), + "m01s34i484": Stash(1, 1875, 0), + "m01s34i485": Stash(1, 1875, 0), + "m01s34i486": Stash(1, 1875, 0), + "m01s34i487": Stash(1, 1875, 0), + "m01s34i488": Stash(1, 1875, 0), + "m01s34i489": Stash(1, 1875, 0), + "m01s34i490": Stash(1, 1875, 0), + "m01s34i491": Stash(1, 1875, 0), + "m01s34i492": Stash(1, 1875, 0), + "m01s34i493": Stash(1, 1875, 0), + "m01s34i494": Stash(1, 1875, 0), + "m01s34i495": Stash(1, 1875, 0), + "m01s34i496": Stash(1, 1875, 0), + "m01s34i497": Stash(1, 1875, 0), + "m01s34i498": Stash(1, 1875, 0), + "m01s34i499": Stash(1, 1875, 0), + "m01s34i500": Stash(1, 1875, 0), + "m01s35i001": Stash(18, 56, 0), + "m01s35i002": Stash(19, 57, 0), + "m01s35i003": Stash(18, 318, 0), + "m01s35i004": Stash(19, 319, 0), + "m01s35i005": Stash(18, 318, 0), + "m01s35i006": Stash(19, 319, 0), + "m01s35i007": Stash(18, 318, 0), + "m01s35i008": Stash(19, 319, 0), + "m01s35i009": Stash(1, 63, 0), + "m01s35i010": Stash(1, 63, 0), + "m01s35i011": Stash(1, 2049, 0), + "m01s35i012": Stash(1, 0, 0), + "m01s35i013": Stash(1, 0, 0), + "m01s35i014": Stash(1, 0, 0), + "m01s35i015": Stash(1, 0, 0), + "m01s35i016": Stash(1, 63, 0), + "m01s35i017": Stash(1, 63, 0), + "m01s35i018": Stash(1, 259, 0), + "m01s35i019": Stash(1, 0, 0), + "m01s35i020": Stash(1, 63, 0), + "m01s35i021": Stash(1, 63, 0), + "m01s35i022": Stash(1, 63, 0), + "m01s35i023": Stash(1, 0, 0), + "m01s35i024": Stash(1, 0, 0), + "m01s35i025": Stash(1, 0, 0), + "m01s35i026": Stash(18, 0, 0), + "m01s35i027": Stash(19, 0, 0), + "m01s35i028": Stash(1, 0, 0), + "m01s36i001": Stash(26, 0, 0), + "m01s36i002": Stash(26, 0, 0), + "m01s36i003": Stash(26, 0, 0), + "m01s36i004": Stash(26, 0, 0), + "m01s36i005": Stash(26, 0, 0), + "m01s36i006": Stash(26, 0, 0), + "m01s36i007": Stash(26, 0, 0), + "m01s36i008": Stash(26, 0, 0), + "m01s36i009": Stash(26, 0, 0), + "m01s36i010": Stash(26, 0, 0), + "m01s36i011": Stash(26, 0, 0), + "m01s36i012": Stash(26, 0, 0), + "m01s36i013": Stash(26, 0, 0), + "m01s36i014": Stash(26, 0, 0), + "m01s36i015": Stash(26, 0, 0), + "m01s36i016": Stash(26, 0, 0), + "m01s36i017": Stash(26, 0, 0), + "m01s36i018": Stash(26, 0, 0), + "m01s36i019": Stash(26, 0, 0), + "m01s36i020": Stash(26, 0, 0), + "m01s36i021": Stash(26, 0, 0), + "m01s36i022": Stash(26, 0, 0), + "m01s36i023": Stash(26, 0, 0), + "m01s36i024": Stash(26, 0, 0), + "m01s36i025": Stash(26, 0, 0), + "m01s36i026": Stash(26, 0, 0), + "m01s36i027": Stash(26, 0, 0), + "m01s36i028": Stash(26, 0, 0), + "m01s36i029": Stash(26, 0, 0), + "m01s36i030": Stash(26, 0, 0), + "m01s36i031": Stash(26, 0, 0), + "m01s36i032": Stash(26, 0, 0), + "m01s36i033": Stash(26, 0, 0), + "m01s36i034": Stash(26, 0, 0), + "m01s36i035": Stash(26, 0, 0), + "m01s36i036": Stash(26, 0, 0), + "m01s36i037": Stash(26, 0, 0), + "m01s36i038": Stash(26, 0, 0), + "m01s36i039": Stash(26, 0, 0), + "m01s36i040": Stash(26, 0, 0), + "m01s36i041": Stash(26, 0, 0), + "m01s36i042": Stash(26, 0, 0), + "m01s36i043": Stash(26, 0, 0), + "m01s36i044": Stash(26, 0, 0), + "m01s36i045": Stash(26, 0, 0), + "m01s36i046": Stash(26, 0, 0), + "m01s36i047": Stash(26, 0, 0), + "m01s36i048": Stash(26, 0, 0), + "m01s36i049": Stash(26, 0, 0), + "m01s36i050": Stash(26, 0, 0), + "m01s36i051": Stash(26, 0, 0), + "m01s36i052": Stash(26, 0, 0), + "m01s36i053": Stash(26, 0, 0), + "m01s36i054": Stash(26, 0, 0), + "m01s36i055": Stash(26, 0, 0), + "m01s36i056": Stash(26, 0, 0), + "m01s36i057": Stash(26, 0, 0), + "m01s36i058": Stash(26, 0, 0), + "m01s36i059": Stash(26, 0, 0), + "m01s36i060": Stash(26, 0, 0), + "m01s36i061": Stash(26, 0, 0), + "m01s36i062": Stash(26, 0, 0), + "m01s36i063": Stash(26, 0, 0), + "m01s36i064": Stash(26, 0, 0), + "m01s36i065": Stash(26, 0, 0), + "m01s36i066": Stash(26, 0, 0), + "m01s36i067": Stash(26, 0, 0), + "m01s36i068": Stash(26, 0, 0), + "m01s36i069": Stash(26, 0, 0), + "m01s36i070": Stash(26, 0, 0), + "m01s36i071": Stash(26, 0, 0), + "m01s36i072": Stash(26, 0, 0), + "m01s36i073": Stash(26, 0, 0), + "m01s36i074": Stash(26, 0, 0), + "m01s36i075": Stash(26, 0, 0), + "m01s36i076": Stash(26, 0, 0), + "m01s36i077": Stash(26, 0, 0), + "m01s36i078": Stash(26, 0, 0), + "m01s36i079": Stash(26, 0, 0), + "m01s36i080": Stash(26, 0, 0), + "m01s36i081": Stash(26, 0, 0), + "m01s36i082": Stash(26, 0, 0), + "m01s36i083": Stash(26, 0, 0), + "m01s36i084": Stash(26, 0, 0), + "m01s36i085": Stash(26, 0, 0), + "m01s36i086": Stash(26, 0, 0), + "m01s36i087": Stash(26, 0, 0), + "m01s36i088": Stash(26, 0, 0), + "m01s36i089": Stash(26, 0, 0), + "m01s36i090": Stash(26, 0, 0), + "m01s36i091": Stash(26, 0, 0), + "m01s36i092": Stash(26, 0, 0), + "m01s36i093": Stash(26, 0, 0), + "m01s36i094": Stash(26, 0, 0), + "m01s36i095": Stash(26, 0, 0), + "m01s36i096": Stash(26, 0, 0), + "m01s36i097": Stash(26, 0, 0), + "m01s36i098": Stash(26, 0, 0), + "m01s36i099": Stash(26, 0, 0), + "m01s36i100": Stash(26, 0, 0), + "m01s36i101": Stash(26, 0, 0), + "m01s36i102": Stash(26, 0, 0), + "m01s36i103": Stash(26, 0, 0), + "m01s36i104": Stash(26, 0, 0), + "m01s36i105": Stash(26, 0, 0), + "m01s36i106": Stash(26, 0, 0), + "m01s36i107": Stash(26, 0, 0), + "m01s36i108": Stash(26, 0, 0), + "m01s36i109": Stash(26, 0, 0), + "m01s36i110": Stash(26, 0, 0), + "m01s36i111": Stash(26, 0, 0), + "m01s36i112": Stash(26, 0, 0), + "m01s36i113": Stash(26, 0, 0), + "m01s36i114": Stash(26, 0, 0), + "m01s36i115": Stash(26, 0, 0), + "m01s36i116": Stash(26, 0, 0), + "m01s36i117": Stash(26, 0, 0), + "m01s36i118": Stash(26, 0, 0), + "m01s36i119": Stash(26, 0, 0), + "m01s36i120": Stash(26, 0, 0), + "m01s36i121": Stash(26, 0, 0), + "m01s36i122": Stash(26, 0, 0), + "m01s36i123": Stash(26, 0, 0), + "m01s36i124": Stash(26, 0, 0), + "m01s36i125": Stash(26, 0, 0), + "m01s36i126": Stash(26, 0, 0), + "m01s36i127": Stash(26, 0, 0), + "m01s36i128": Stash(26, 0, 0), + "m01s36i129": Stash(26, 0, 0), + "m01s36i130": Stash(26, 0, 0), + "m01s36i131": Stash(26, 0, 0), + "m01s36i132": Stash(26, 0, 0), + "m01s36i133": Stash(26, 0, 0), + "m01s36i134": Stash(26, 0, 0), + "m01s36i135": Stash(26, 0, 0), + "m01s36i136": Stash(26, 0, 0), + "m01s36i137": Stash(26, 0, 0), + "m01s36i138": Stash(26, 0, 0), + "m01s36i139": Stash(26, 0, 0), + "m01s36i140": Stash(26, 0, 0), + "m01s36i141": Stash(26, 0, 0), + "m01s36i142": Stash(26, 0, 0), + "m01s36i143": Stash(26, 0, 0), + "m01s36i144": Stash(26, 0, 0), + "m01s36i145": Stash(26, 0, 0), + "m01s36i146": Stash(26, 0, 0), + "m01s36i147": Stash(26, 0, 0), + "m01s36i148": Stash(26, 0, 0), + "m01s36i149": Stash(26, 0, 0), + "m01s36i150": Stash(26, 0, 0), + "m01s36i257": Stash(26, 0, 0), + "m01s36i258": Stash(26, 0, 0), + "m01s36i259": Stash(26, 0, 0), + "m01s36i260": Stash(26, 0, 0), + "m01s36i261": Stash(26, 0, 0), + "m01s36i262": Stash(26, 0, 0), + "m01s36i263": Stash(26, 0, 0), + "m01s36i264": Stash(26, 0, 0), + "m01s36i265": Stash(26, 0, 0), + "m01s36i266": Stash(26, 0, 0), + "m01s36i267": Stash(26, 0, 0), + "m01s36i268": Stash(26, 0, 0), + "m01s36i269": Stash(26, 0, 0), + "m01s36i270": Stash(26, 0, 0), + "m01s36i271": Stash(26, 0, 0), + "m01s36i272": Stash(26, 0, 0), + "m01s36i273": Stash(26, 0, 0), + "m01s36i274": Stash(26, 0, 0), + "m01s36i275": Stash(26, 0, 0), + "m01s36i276": Stash(26, 0, 0), + "m01s36i277": Stash(26, 0, 0), + "m01s36i278": Stash(26, 0, 0), + "m01s36i279": Stash(26, 0, 0), + "m01s36i280": Stash(26, 0, 0), + "m01s36i281": Stash(26, 0, 0), + "m01s36i282": Stash(26, 0, 0), + "m01s36i283": Stash(26, 0, 0), + "m01s36i284": Stash(26, 0, 0), + "m01s36i285": Stash(26, 0, 0), + "m01s36i286": Stash(26, 0, 0), + "m01s36i287": Stash(26, 0, 0), + "m01s36i288": Stash(26, 0, 0), + "m01s36i289": Stash(26, 0, 0), + "m01s36i290": Stash(26, 0, 0), + "m01s36i291": Stash(26, 0, 0), + "m01s36i292": Stash(26, 0, 0), + "m01s36i293": Stash(26, 0, 0), + "m01s36i294": Stash(26, 0, 0), + "m01s36i295": Stash(26, 0, 0), + "m01s36i296": Stash(26, 0, 0), + "m01s36i297": Stash(26, 0, 0), + "m01s36i298": Stash(26, 0, 0), + "m01s36i299": Stash(26, 0, 0), + "m01s36i300": Stash(26, 0, 0), + "m01s36i301": Stash(26, 0, 0), + "m01s36i302": Stash(26, 0, 0), + "m01s36i303": Stash(26, 0, 0), + "m01s36i304": Stash(26, 0, 0), + "m01s36i305": Stash(26, 0, 0), + "m01s36i306": Stash(26, 0, 0), + "m01s36i307": Stash(26, 0, 0), + "m01s36i308": Stash(26, 0, 0), + "m01s36i309": Stash(26, 0, 0), + "m01s36i310": Stash(26, 0, 0), + "m01s36i311": Stash(26, 0, 0), + "m01s36i312": Stash(26, 0, 0), + "m01s36i313": Stash(26, 0, 0), + "m01s36i314": Stash(26, 0, 0), + "m01s36i315": Stash(26, 0, 0), + "m01s36i316": Stash(26, 0, 0), + "m01s36i317": Stash(26, 0, 0), + "m01s36i318": Stash(26, 0, 0), + "m01s36i319": Stash(26, 0, 0), + "m01s36i320": Stash(26, 0, 0), + "m01s36i321": Stash(26, 0, 0), + "m01s36i322": Stash(26, 0, 0), + "m01s36i323": Stash(26, 0, 0), + "m01s36i324": Stash(26, 0, 0), + "m01s36i325": Stash(26, 0, 0), + "m01s36i326": Stash(26, 0, 0), + "m01s36i327": Stash(26, 0, 0), + "m01s36i328": Stash(26, 0, 0), + "m01s36i329": Stash(26, 0, 0), + "m01s36i330": Stash(26, 0, 0), + "m01s36i331": Stash(26, 0, 0), + "m01s36i332": Stash(26, 0, 0), + "m01s36i333": Stash(26, 0, 0), + "m01s36i334": Stash(26, 0, 0), + "m01s36i335": Stash(26, 0, 0), + "m01s36i336": Stash(26, 0, 0), + "m01s36i337": Stash(26, 0, 0), + "m01s36i338": Stash(26, 0, 0), + "m01s36i339": Stash(26, 0, 0), + "m01s36i340": Stash(26, 0, 0), + "m01s36i341": Stash(26, 0, 0), + "m01s36i342": Stash(26, 0, 0), + "m01s36i343": Stash(26, 0, 0), + "m01s36i344": Stash(26, 0, 0), + "m01s36i345": Stash(26, 0, 0), + "m01s36i346": Stash(26, 0, 0), + "m01s36i347": Stash(26, 0, 0), + "m01s36i348": Stash(26, 0, 0), + "m01s36i349": Stash(26, 0, 0), + "m01s36i350": Stash(26, 0, 0), + "m01s36i351": Stash(26, 0, 0), + "m01s36i352": Stash(26, 0, 0), + "m01s36i353": Stash(26, 0, 0), + "m01s36i354": Stash(26, 0, 0), + "m01s36i355": Stash(26, 0, 0), + "m01s36i356": Stash(26, 0, 0), + "m01s36i357": Stash(26, 0, 0), + "m01s36i358": Stash(26, 0, 0), + "m01s36i359": Stash(26, 0, 0), + "m01s36i360": Stash(26, 0, 0), + "m01s36i361": Stash(26, 0, 0), + "m01s36i362": Stash(26, 0, 0), + "m01s36i363": Stash(26, 0, 0), + "m01s36i364": Stash(26, 0, 0), + "m01s36i365": Stash(26, 0, 0), + "m01s36i366": Stash(26, 0, 0), + "m01s36i367": Stash(26, 0, 0), + "m01s36i368": Stash(26, 0, 0), + "m01s36i369": Stash(26, 0, 0), + "m01s36i370": Stash(26, 0, 0), + "m01s36i371": Stash(26, 0, 0), + "m01s36i372": Stash(26, 0, 0), + "m01s36i373": Stash(26, 0, 0), + "m01s36i374": Stash(26, 0, 0), + "m01s36i375": Stash(26, 0, 0), + "m01s36i376": Stash(26, 0, 0), + "m01s36i377": Stash(26, 0, 0), + "m01s36i378": Stash(26, 0, 0), + "m01s36i379": Stash(26, 0, 0), + "m01s36i380": Stash(26, 0, 0), + "m01s36i381": Stash(26, 0, 0), + "m01s36i382": Stash(26, 0, 0), + "m01s36i383": Stash(26, 0, 0), + "m01s36i384": Stash(26, 0, 0), + "m01s36i385": Stash(26, 0, 0), + "m01s36i386": Stash(26, 0, 0), + "m01s36i387": Stash(26, 0, 0), + "m01s36i388": Stash(26, 0, 0), + "m01s36i389": Stash(26, 0, 0), + "m01s36i390": Stash(26, 0, 0), + "m01s36i391": Stash(26, 0, 0), + "m01s36i392": Stash(26, 0, 0), + "m01s36i393": Stash(26, 0, 0), + "m01s36i394": Stash(26, 0, 0), + "m01s36i395": Stash(26, 0, 0), + "m01s36i396": Stash(26, 0, 0), + "m01s36i397": Stash(26, 0, 0), + "m01s36i398": Stash(26, 0, 0), + "m01s36i399": Stash(26, 0, 0), + "m01s36i400": Stash(26, 0, 0), + "m01s36i401": Stash(26, 0, 0), + "m01s36i402": Stash(26, 0, 0), + "m01s36i403": Stash(26, 0, 0), + "m01s36i404": Stash(26, 0, 0), + "m01s36i405": Stash(26, 0, 0), + "m01s36i406": Stash(26, 0, 0), + "m01s37i001": Stash(26, 0, 0), + "m01s37i002": Stash(26, 0, 0), + "m01s37i003": Stash(26, 0, 0), + "m01s37i004": Stash(26, 0, 0), + "m01s37i005": Stash(26, 0, 0), + "m01s37i006": Stash(26, 0, 0), + "m01s37i007": Stash(26, 0, 0), + "m01s37i008": Stash(26, 0, 0), + "m01s37i009": Stash(26, 0, 0), + "m01s37i010": Stash(26, 0, 0), + "m01s37i011": Stash(26, 0, 0), + "m01s37i012": Stash(26, 0, 0), + "m01s37i013": Stash(26, 0, 0), + "m01s37i014": Stash(26, 0, 0), + "m01s37i015": Stash(26, 0, 0), + "m01s37i016": Stash(26, 0, 0), + "m01s37i017": Stash(26, 0, 0), + "m01s37i018": Stash(26, 0, 0), + "m01s37i019": Stash(26, 0, 0), + "m01s37i020": Stash(26, 0, 0), + "m01s37i021": Stash(26, 0, 0), + "m01s37i022": Stash(26, 0, 0), + "m01s37i023": Stash(26, 0, 0), + "m01s37i024": Stash(26, 0, 0), + "m01s37i025": Stash(26, 0, 0), + "m01s37i026": Stash(26, 0, 0), + "m01s37i027": Stash(26, 0, 0), + "m01s37i028": Stash(26, 0, 0), + "m01s37i029": Stash(26, 0, 0), + "m01s37i030": Stash(26, 0, 0), + "m01s37i031": Stash(26, 0, 0), + "m01s37i032": Stash(26, 0, 0), + "m01s37i033": Stash(26, 0, 0), + "m01s37i034": Stash(26, 0, 0), + "m01s37i035": Stash(26, 0, 0), + "m01s37i036": Stash(26, 0, 0), + "m01s37i037": Stash(26, 0, 0), + "m01s37i038": Stash(26, 0, 0), + "m01s37i039": Stash(26, 0, 0), + "m01s37i040": Stash(26, 0, 0), + "m01s37i041": Stash(26, 0, 0), + "m01s37i042": Stash(26, 0, 0), + "m01s37i043": Stash(26, 0, 0), + "m01s37i044": Stash(26, 0, 0), + "m01s37i045": Stash(26, 0, 0), + "m01s37i046": Stash(26, 0, 0), + "m01s37i047": Stash(26, 0, 0), + "m01s37i048": Stash(26, 0, 0), + "m01s37i049": Stash(26, 0, 0), + "m01s37i050": Stash(26, 0, 0), + "m01s37i051": Stash(26, 0, 0), + "m01s37i052": Stash(26, 0, 0), + "m01s37i053": Stash(26, 0, 0), + "m01s37i054": Stash(26, 0, 0), + "m01s37i055": Stash(26, 0, 0), + "m01s37i056": Stash(26, 0, 0), + "m01s37i057": Stash(26, 0, 0), + "m01s37i058": Stash(26, 0, 0), + "m01s37i059": Stash(26, 0, 0), + "m01s37i060": Stash(26, 0, 0), + "m01s37i061": Stash(26, 0, 0), + "m01s37i062": Stash(26, 0, 0), + "m01s37i063": Stash(26, 0, 0), + "m01s37i064": Stash(26, 0, 0), + "m01s37i065": Stash(26, 0, 0), + "m01s37i066": Stash(26, 0, 0), + "m01s37i067": Stash(26, 0, 0), + "m01s37i068": Stash(26, 0, 0), + "m01s37i069": Stash(26, 0, 0), + "m01s37i070": Stash(26, 0, 0), + "m01s37i071": Stash(26, 0, 0), + "m01s37i072": Stash(26, 0, 0), + "m01s37i073": Stash(26, 0, 0), + "m01s37i074": Stash(26, 0, 0), + "m01s37i075": Stash(26, 0, 0), + "m01s37i076": Stash(26, 0, 0), + "m01s37i077": Stash(26, 0, 0), + "m01s37i078": Stash(26, 0, 0), + "m01s37i079": Stash(26, 0, 0), + "m01s37i080": Stash(26, 0, 0), + "m01s37i081": Stash(26, 0, 0), + "m01s37i082": Stash(26, 0, 0), + "m01s37i083": Stash(26, 0, 0), + "m01s37i084": Stash(26, 0, 0), + "m01s37i085": Stash(26, 0, 0), + "m01s37i086": Stash(26, 0, 0), + "m01s37i087": Stash(26, 0, 0), + "m01s37i088": Stash(26, 0, 0), + "m01s37i089": Stash(26, 0, 0), + "m01s37i090": Stash(26, 0, 0), + "m01s37i091": Stash(26, 0, 0), + "m01s37i092": Stash(26, 0, 0), + "m01s37i093": Stash(26, 0, 0), + "m01s37i094": Stash(26, 0, 0), + "m01s37i095": Stash(26, 0, 0), + "m01s37i096": Stash(26, 0, 0), + "m01s37i097": Stash(26, 0, 0), + "m01s37i098": Stash(26, 0, 0), + "m01s37i099": Stash(26, 0, 0), + "m01s37i100": Stash(26, 0, 0), + "m01s37i101": Stash(26, 0, 0), + "m01s37i102": Stash(26, 0, 0), + "m01s37i103": Stash(26, 0, 0), + "m01s37i104": Stash(26, 0, 0), + "m01s37i105": Stash(26, 0, 0), + "m01s37i106": Stash(26, 0, 0), + "m01s37i107": Stash(26, 0, 0), + "m01s37i108": Stash(26, 0, 0), + "m01s37i109": Stash(26, 0, 0), + "m01s37i110": Stash(26, 0, 0), + "m01s37i111": Stash(26, 0, 0), + "m01s37i112": Stash(26, 0, 0), + "m01s37i113": Stash(26, 0, 0), + "m01s37i114": Stash(26, 0, 0), + "m01s37i115": Stash(26, 0, 0), + "m01s37i116": Stash(26, 0, 0), + "m01s37i117": Stash(26, 0, 0), + "m01s37i118": Stash(26, 0, 0), + "m01s37i119": Stash(26, 0, 0), + "m01s37i120": Stash(26, 0, 0), + "m01s37i121": Stash(26, 0, 0), + "m01s37i122": Stash(26, 0, 0), + "m01s37i123": Stash(26, 0, 0), + "m01s37i124": Stash(26, 0, 0), + "m01s37i125": Stash(26, 0, 0), + "m01s37i126": Stash(26, 0, 0), + "m01s37i127": Stash(26, 0, 0), + "m01s37i128": Stash(26, 0, 0), + "m01s37i129": Stash(26, 0, 0), + "m01s37i130": Stash(26, 0, 0), + "m01s37i131": Stash(26, 0, 0), + "m01s37i132": Stash(26, 0, 0), + "m01s37i133": Stash(26, 0, 0), + "m01s37i134": Stash(26, 0, 0), + "m01s37i135": Stash(26, 0, 0), + "m01s37i136": Stash(26, 0, 0), + "m01s37i137": Stash(26, 0, 0), + "m01s37i138": Stash(26, 0, 0), + "m01s37i139": Stash(26, 0, 0), + "m01s37i140": Stash(26, 0, 0), + "m01s37i141": Stash(26, 0, 0), + "m01s37i142": Stash(26, 0, 0), + "m01s37i143": Stash(26, 0, 0), + "m01s37i144": Stash(26, 0, 0), + "m01s37i145": Stash(26, 0, 0), + "m01s37i146": Stash(26, 0, 0), + "m01s37i147": Stash(26, 0, 0), + "m01s37i148": Stash(26, 0, 0), + "m01s37i149": Stash(26, 0, 0), + "m01s37i150": Stash(26, 0, 0), + "m01s37i257": Stash(26, 0, 0), + "m01s37i258": Stash(26, 0, 0), + "m01s37i259": Stash(26, 0, 0), + "m01s37i260": Stash(26, 0, 0), + "m01s37i261": Stash(26, 0, 0), + "m01s37i262": Stash(26, 0, 0), + "m01s37i263": Stash(26, 0, 0), + "m01s37i264": Stash(26, 0, 0), + "m01s37i265": Stash(26, 0, 0), + "m01s37i266": Stash(26, 0, 0), + "m01s37i267": Stash(26, 0, 0), + "m01s37i268": Stash(26, 0, 0), + "m01s37i269": Stash(26, 0, 0), + "m01s37i270": Stash(26, 0, 0), + "m01s37i271": Stash(26, 0, 0), + "m01s37i272": Stash(26, 0, 0), + "m01s37i273": Stash(26, 0, 0), + "m01s37i274": Stash(26, 0, 0), + "m01s37i275": Stash(26, 0, 0), + "m01s37i276": Stash(26, 0, 0), + "m01s37i277": Stash(26, 0, 0), + "m01s37i278": Stash(26, 0, 0), + "m01s37i279": Stash(26, 0, 0), + "m01s37i280": Stash(26, 0, 0), + "m01s37i281": Stash(26, 0, 0), + "m01s37i282": Stash(26, 0, 0), + "m01s37i283": Stash(26, 0, 0), + "m01s37i284": Stash(26, 0, 0), + "m01s37i285": Stash(26, 0, 0), + "m01s37i286": Stash(26, 0, 0), + "m01s37i287": Stash(26, 0, 0), + "m01s37i288": Stash(26, 0, 0), + "m01s37i289": Stash(26, 0, 0), + "m01s37i290": Stash(26, 0, 0), + "m01s37i291": Stash(26, 0, 0), + "m01s37i292": Stash(26, 0, 0), + "m01s37i293": Stash(26, 0, 0), + "m01s37i294": Stash(26, 0, 0), + "m01s37i295": Stash(26, 0, 0), + "m01s37i296": Stash(26, 0, 0), + "m01s37i297": Stash(26, 0, 0), + "m01s37i298": Stash(26, 0, 0), + "m01s37i299": Stash(26, 0, 0), + "m01s37i300": Stash(26, 0, 0), + "m01s37i301": Stash(26, 0, 0), + "m01s37i302": Stash(26, 0, 0), + "m01s37i303": Stash(26, 0, 0), + "m01s37i304": Stash(26, 0, 0), + "m01s37i305": Stash(26, 0, 0), + "m01s37i306": Stash(26, 0, 0), + "m01s37i307": Stash(26, 0, 0), + "m01s37i308": Stash(26, 0, 0), + "m01s37i309": Stash(26, 0, 0), + "m01s37i310": Stash(26, 0, 0), + "m01s37i311": Stash(26, 0, 0), + "m01s37i312": Stash(26, 0, 0), + "m01s37i313": Stash(26, 0, 0), + "m01s37i314": Stash(26, 0, 0), + "m01s37i315": Stash(26, 0, 0), + "m01s37i316": Stash(26, 0, 0), + "m01s37i317": Stash(26, 0, 0), + "m01s37i318": Stash(26, 0, 0), + "m01s37i319": Stash(26, 0, 0), + "m01s37i320": Stash(26, 0, 0), + "m01s37i321": Stash(26, 0, 0), + "m01s37i322": Stash(26, 0, 0), + "m01s37i323": Stash(26, 0, 0), + "m01s37i324": Stash(26, 0, 0), + "m01s37i325": Stash(26, 0, 0), + "m01s37i326": Stash(26, 0, 0), + "m01s37i327": Stash(26, 0, 0), + "m01s37i328": Stash(26, 0, 0), + "m01s37i329": Stash(26, 0, 0), + "m01s37i330": Stash(26, 0, 0), + "m01s37i331": Stash(26, 0, 0), + "m01s37i332": Stash(26, 0, 0), + "m01s37i333": Stash(26, 0, 0), + "m01s37i334": Stash(26, 0, 0), + "m01s37i335": Stash(26, 0, 0), + "m01s37i336": Stash(26, 0, 0), + "m01s37i337": Stash(26, 0, 0), + "m01s37i338": Stash(26, 0, 0), + "m01s37i339": Stash(26, 0, 0), + "m01s37i340": Stash(26, 0, 0), + "m01s37i341": Stash(26, 0, 0), + "m01s37i342": Stash(26, 0, 0), + "m01s37i343": Stash(26, 0, 0), + "m01s37i344": Stash(26, 0, 0), + "m01s37i345": Stash(26, 0, 0), + "m01s37i346": Stash(26, 0, 0), + "m01s37i347": Stash(26, 0, 0), + "m01s37i348": Stash(26, 0, 0), + "m01s37i349": Stash(26, 0, 0), + "m01s37i350": Stash(26, 0, 0), + "m01s37i351": Stash(26, 0, 0), + "m01s37i352": Stash(26, 0, 0), + "m01s37i353": Stash(26, 0, 0), + "m01s37i354": Stash(26, 0, 0), + "m01s37i355": Stash(26, 0, 0), + "m01s37i356": Stash(26, 0, 0), + "m01s37i357": Stash(26, 0, 0), + "m01s37i358": Stash(26, 0, 0), + "m01s37i359": Stash(26, 0, 0), + "m01s37i360": Stash(26, 0, 0), + "m01s37i361": Stash(26, 0, 0), + "m01s37i362": Stash(26, 0, 0), + "m01s37i363": Stash(26, 0, 0), + "m01s37i364": Stash(26, 0, 0), + "m01s37i365": Stash(26, 0, 0), + "m01s37i366": Stash(26, 0, 0), + "m01s37i367": Stash(26, 0, 0), + "m01s37i368": Stash(26, 0, 0), + "m01s37i369": Stash(26, 0, 0), + "m01s37i370": Stash(26, 0, 0), + "m01s37i371": Stash(26, 0, 0), + "m01s37i372": Stash(26, 0, 0), + "m01s37i373": Stash(26, 0, 0), + "m01s37i374": Stash(26, 0, 0), + "m01s37i375": Stash(26, 0, 0), + "m01s37i376": Stash(26, 0, 0), + "m01s37i377": Stash(26, 0, 0), + "m01s37i378": Stash(26, 0, 0), + "m01s37i379": Stash(26, 0, 0), + "m01s37i380": Stash(26, 0, 0), + "m01s37i381": Stash(26, 0, 0), + "m01s37i382": Stash(26, 0, 0), + "m01s37i383": Stash(26, 0, 0), + "m01s37i384": Stash(26, 0, 0), + "m01s37i385": Stash(26, 0, 0), + "m01s37i386": Stash(26, 0, 0), + "m01s37i387": Stash(26, 0, 0), + "m01s37i388": Stash(26, 0, 0), + "m01s37i389": Stash(26, 0, 0), + "m01s37i390": Stash(26, 0, 0), + "m01s37i391": Stash(26, 0, 0), + "m01s37i392": Stash(26, 0, 0), + "m01s37i393": Stash(26, 0, 0), + "m01s37i394": Stash(26, 0, 0), + "m01s37i395": Stash(26, 0, 0), + "m01s37i396": Stash(26, 0, 0), + "m01s37i397": Stash(26, 0, 0), + "m01s37i398": Stash(26, 0, 0), + "m01s37i399": Stash(26, 0, 0), + "m01s37i400": Stash(26, 0, 0), + "m01s37i401": Stash(26, 0, 0), + "m01s37i402": Stash(26, 0, 0), + "m01s37i403": Stash(26, 0, 0), + "m01s37i404": Stash(26, 0, 0), + "m01s37i405": Stash(26, 0, 0), + "m01s37i406": Stash(26, 0, 0), + "m01s38i001": Stash(1, 1875, 0), + "m01s38i002": Stash(1, 1875, 0), + "m01s38i003": Stash(1, 1875, 0), + "m01s38i004": Stash(1, 1875, 0), + "m01s38i005": Stash(1, 1875, 0), + "m01s38i006": Stash(1, 1875, 0), + "m01s38i007": Stash(1, 1875, 0), + "m01s38i008": Stash(1, 1875, 0), + "m01s38i009": Stash(1, 1875, 0), + "m01s38i010": Stash(1, 1875, 0), + "m01s38i011": Stash(1, 1875, 0), + "m01s38i012": Stash(1, 1875, 0), + "m01s38i013": Stash(1, 1875, 0), + "m01s38i014": Stash(1, 1875, 0), + "m01s38i015": Stash(1, 1875, 0), + "m01s38i016": Stash(1, 1875, 0), + "m01s38i017": Stash(1, 1875, 0), + "m01s38i018": Stash(1, 1875, 0), + "m01s38i019": Stash(1, 1875, 0), + "m01s38i020": Stash(1, 1875, 0), + "m01s38i021": Stash(1, 1875, 0), + "m01s38i022": Stash(1, 1875, 0), + "m01s38i023": Stash(1, 1875, 0), + "m01s38i024": Stash(1, 1875, 0), + "m01s38i025": Stash(1, 1875, 0), + "m01s38i026": Stash(1, 1875, 0), + "m01s38i027": Stash(1, 1875, 0), + "m01s38i028": Stash(1, 1875, 0), + "m01s38i029": Stash(1, 1875, 0), + "m01s38i030": Stash(1, 1875, 0), + "m01s38i031": Stash(1, 1875, 0), + "m01s38i032": Stash(1, 1875, 0), + "m01s38i033": Stash(1, 1875, 0), + "m01s38i034": Stash(1, 1875, 0), + "m01s38i035": Stash(1, 1875, 0), + "m01s38i036": Stash(1, 1875, 0), + "m01s38i037": Stash(1, 1875, 0), + "m01s38i038": Stash(1, 1875, 0), + "m01s38i039": Stash(1, 1875, 0), + "m01s38i040": Stash(1, 1875, 0), + "m01s38i041": Stash(1, 1875, 0), + "m01s38i042": Stash(1, 1875, 0), + "m01s38i043": Stash(1, 1875, 0), + "m01s38i044": Stash(1, 1875, 0), + "m01s38i045": Stash(1, 1875, 0), + "m01s38i046": Stash(1, 1875, 0), + "m01s38i047": Stash(1, 1875, 0), + "m01s38i048": Stash(1, 1875, 0), + "m01s38i049": Stash(1, 1875, 0), + "m01s38i050": Stash(1, 1875, 0), + "m01s38i051": Stash(1, 1875, 0), + "m01s38i052": Stash(1, 1875, 0), + "m01s38i053": Stash(1, 1875, 0), + "m01s38i054": Stash(1, 1875, 0), + "m01s38i055": Stash(1, 1875, 0), + "m01s38i056": Stash(1, 1875, 0), + "m01s38i057": Stash(1, 1875, 0), + "m01s38i058": Stash(1, 1875, 0), + "m01s38i059": Stash(1, 1875, 0), + "m01s38i060": Stash(1, 1875, 0), + "m01s38i061": Stash(1, 1875, 0), + "m01s38i062": Stash(1, 1875, 0), + "m01s38i063": Stash(1, 1875, 0), + "m01s38i064": Stash(1, 1875, 0), + "m01s38i065": Stash(1, 1875, 0), + "m01s38i066": Stash(1, 1875, 0), + "m01s38i067": Stash(1, 1875, 0), + "m01s38i068": Stash(1, 1875, 0), + "m01s38i069": Stash(1, 1875, 0), + "m01s38i070": Stash(1, 1875, 0), + "m01s38i071": Stash(1, 1875, 0), + "m01s38i072": Stash(1, 1875, 0), + "m01s38i073": Stash(1, 1875, 0), + "m01s38i074": Stash(1, 1875, 0), + "m01s38i075": Stash(1, 1875, 0), + "m01s38i076": Stash(1, 1875, 0), + "m01s38i077": Stash(1, 1875, 0), + "m01s38i078": Stash(1, 1875, 0), + "m01s38i079": Stash(1, 1875, 0), + "m01s38i080": Stash(1, 1875, 0), + "m01s38i081": Stash(1, 1875, 0), + "m01s38i082": Stash(1, 1875, 0), + "m01s38i083": Stash(1, 1875, 0), + "m01s38i084": Stash(1, 1875, 0), + "m01s38i085": Stash(1, 1875, 0), + "m01s38i086": Stash(1, 1875, 0), + "m01s38i087": Stash(1, 1875, 0), + "m01s38i088": Stash(1, 1875, 0), + "m01s38i089": Stash(1, 1875, 0), + "m01s38i090": Stash(1, 1875, 0), + "m01s38i091": Stash(1, 1875, 0), + "m01s38i092": Stash(1, 1875, 0), + "m01s38i093": Stash(1, 1875, 0), + "m01s38i094": Stash(1, 1875, 0), + "m01s38i095": Stash(1, 1875, 0), + "m01s38i096": Stash(1, 1875, 0), + "m01s38i097": Stash(1, 1875, 0), + "m01s38i098": Stash(1, 1875, 0), + "m01s38i099": Stash(1, 1875, 0), + "m01s38i100": Stash(1, 1875, 0), + "m01s38i101": Stash(1, 1875, 0), + "m01s38i102": Stash(1, 1875, 0), + "m01s38i103": Stash(1, 1875, 0), + "m01s38i104": Stash(1, 1875, 0), + "m01s38i105": Stash(1, 1875, 0), + "m01s38i106": Stash(1, 1875, 0), + "m01s38i107": Stash(1, 1875, 0), + "m01s38i108": Stash(1, 1875, 0), + "m01s38i109": Stash(1, 1875, 0), + "m01s38i110": Stash(1, 1875, 0), + "m01s38i111": Stash(1, 1875, 0), + "m01s38i112": Stash(1, 1875, 0), + "m01s38i113": Stash(1, 1875, 0), + "m01s38i114": Stash(1, 1875, 0), + "m01s38i115": Stash(1, 1875, 0), + "m01s38i116": Stash(1, 1875, 0), + "m01s38i117": Stash(1, 1875, 0), + "m01s38i118": Stash(1, 1875, 0), + "m01s38i119": Stash(1, 1875, 0), + "m01s38i120": Stash(1, 1875, 0), + "m01s38i121": Stash(1, 1875, 0), + "m01s38i122": Stash(1, 1875, 0), + "m01s38i123": Stash(1, 1875, 0), + "m01s38i124": Stash(1, 1875, 0), + "m01s38i125": Stash(1, 1875, 0), + "m01s38i126": Stash(1, 1875, 0), + "m01s38i127": Stash(1, 1875, 0), + "m01s38i128": Stash(1, 1875, 0), + "m01s38i129": Stash(1, 1875, 0), + "m01s38i130": Stash(1, 1875, 0), + "m01s38i131": Stash(1, 1875, 0), + "m01s38i132": Stash(1, 1875, 0), + "m01s38i133": Stash(1, 1875, 0), + "m01s38i134": Stash(1, 1875, 0), + "m01s38i135": Stash(1, 1875, 0), + "m01s38i136": Stash(1, 1875, 0), + "m01s38i137": Stash(1, 1875, 0), + "m01s38i138": Stash(1, 1875, 0), + "m01s38i139": Stash(1, 1875, 0), + "m01s38i140": Stash(1, 1875, 0), + "m01s38i141": Stash(1, 1875, 0), + "m01s38i142": Stash(1, 1875, 0), + "m01s38i143": Stash(1, 1875, 0), + "m01s38i144": Stash(1, 1875, 0), + "m01s38i145": Stash(1, 1875, 0), + "m01s38i146": Stash(1, 1875, 0), + "m01s38i147": Stash(1, 1875, 0), + "m01s38i148": Stash(1, 1875, 0), + "m01s38i149": Stash(1, 1875, 0), + "m01s38i150": Stash(1, 1875, 0), + "m01s38i151": Stash(1, 0, 0), + "m01s38i152": Stash(1, 0, 0), + "m01s38i153": Stash(1, 0, 0), + "m01s38i154": Stash(1, 0, 0), + "m01s38i155": Stash(1, 0, 0), + "m01s38i156": Stash(1, 0, 0), + "m01s38i157": Stash(1, 0, 0), + "m01s38i158": Stash(1, 0, 0), + "m01s38i159": Stash(1, 0, 0), + "m01s38i160": Stash(1, 0, 0), + "m01s38i161": Stash(1, 0, 0), + "m01s38i162": Stash(1, 571, 0), + "m01s38i163": Stash(1, 571, 0), + "m01s38i164": Stash(1, 571, 0), + "m01s38i165": Stash(1, 571, 0), + "m01s38i166": Stash(1, 575, 0), + "m01s38i167": Stash(1, 575, 0), + "m01s38i168": Stash(1, 575, 0), + "m01s38i169": Stash(1, 0, 0), + "m01s38i170": Stash(1, 575, 0), + "m01s38i171": Stash(1, 575, 0), + "m01s38i172": Stash(1, 575, 0), + "m01s38i173": Stash(1, 575, 0), + "m01s38i174": Stash(1, 575, 0), + "m01s38i186": Stash(1, 575, 0), + "m01s38i187": Stash(1, 575, 0), + "m01s38i188": Stash(1, 575, 0), + "m01s38i189": Stash(1, 575, 0), + "m01s38i201": Stash(1, 1870, 0), + "m01s38i202": Stash(1, 1870, 0), + "m01s38i203": Stash(1, 1870, 0), + "m01s38i204": Stash(1, 1870, 0), + "m01s38i205": Stash(1, 1870, 0), + "m01s38i206": Stash(1, 1870, 0), + "m01s38i207": Stash(1, 1870, 0), + "m01s38i208": Stash(1, 1870, 0), + "m01s38i209": Stash(1, 1870, 0), + "m01s38i210": Stash(1, 1870, 0), + "m01s38i211": Stash(1, 1870, 0), + "m01s38i212": Stash(1, 1870, 0), + "m01s38i213": Stash(1, 1870, 0), + "m01s38i214": Stash(1, 1870, 0), + "m01s38i215": Stash(1, 1870, 0), + "m01s38i216": Stash(1, 1870, 0), + "m01s38i217": Stash(1, 1870, 0), + "m01s38i218": Stash(1, 1870, 0), + "m01s38i219": Stash(1, 1870, 0), + "m01s38i220": Stash(1, 1870, 0), + "m01s38i221": Stash(1, 1870, 0), + "m01s38i222": Stash(1, 1870, 0), + "m01s38i223": Stash(1, 1870, 0), + "m01s38i224": Stash(1, 1870, 0), + "m01s38i225": Stash(1, 1870, 0), + "m01s38i226": Stash(1, 1870, 0), + "m01s38i227": Stash(1, 1870, 0), + "m01s38i228": Stash(1, 1870, 0), + "m01s38i229": Stash(1, 1870, 0), + "m01s38i230": Stash(1, 1870, 0), + "m01s38i231": Stash(1, 1870, 0), + "m01s38i232": Stash(1, 1870, 0), + "m01s38i233": Stash(1, 1870, 0), + "m01s38i234": Stash(1, 1870, 0), + "m01s38i235": Stash(1, 1870, 0), + "m01s38i236": Stash(1, 1870, 0), + "m01s38i237": Stash(1, 1870, 0), + "m01s38i238": Stash(1, 1870, 0), + "m01s38i239": Stash(1, 1870, 0), + "m01s38i240": Stash(1, 1870, 0), + "m01s38i241": Stash(1, 1870, 0), + "m01s38i242": Stash(1, 1870, 0), + "m01s38i243": Stash(1, 1870, 0), + "m01s38i244": Stash(1, 1870, 0), + "m01s38i245": Stash(1, 1870, 0), + "m01s38i246": Stash(1, 1870, 0), + "m01s38i247": Stash(1, 1870, 0), + "m01s38i248": Stash(1, 1870, 0), + "m01s38i249": Stash(1, 1870, 0), + "m01s38i250": Stash(1, 1870, 0), + "m01s38i251": Stash(1, 1870, 0), + "m01s38i252": Stash(1, 1870, 0), + "m01s38i253": Stash(1, 1870, 0), + "m01s38i254": Stash(1, 1870, 0), + "m01s38i255": Stash(1, 1870, 0), + "m01s38i256": Stash(1, 1870, 0), + "m01s38i257": Stash(1, 1870, 0), + "m01s38i258": Stash(1, 1870, 0), + "m01s38i259": Stash(1, 1870, 0), + "m01s38i260": Stash(1, 1870, 0), + "m01s38i261": Stash(1, 1870, 0), + "m01s38i262": Stash(1, 1870, 0), + "m01s38i263": Stash(1, 1870, 0), + "m01s38i264": Stash(1, 1870, 0), + "m01s38i265": Stash(1, 1870, 0), + "m01s38i266": Stash(1, 1870, 0), + "m01s38i267": Stash(1, 1870, 0), + "m01s38i268": Stash(1, 1870, 0), + "m01s38i269": Stash(1, 1870, 0), + "m01s38i270": Stash(1, 1870, 0), + "m01s38i271": Stash(1, 1870, 0), + "m01s38i272": Stash(1, 1870, 0), + "m01s38i273": Stash(1, 1870, 0), + "m01s38i274": Stash(1, 1870, 0), + "m01s38i275": Stash(1, 1870, 0), + "m01s38i276": Stash(1, 1870, 0), + "m01s38i277": Stash(1, 1870, 0), + "m01s38i278": Stash(1, 1870, 0), + "m01s38i279": Stash(1, 1870, 0), + "m01s38i280": Stash(1, 1870, 0), + "m01s38i281": Stash(1, 1870, 0), + "m01s38i282": Stash(1, 1870, 0), + "m01s38i283": Stash(1, 1870, 0), + "m01s38i284": Stash(1, 1870, 0), + "m01s38i285": Stash(1, 1870, 0), + "m01s38i286": Stash(1, 1870, 0), + "m01s38i287": Stash(1, 1870, 0), + "m01s38i288": Stash(1, 1870, 0), + "m01s38i289": Stash(1, 1870, 0), + "m01s38i290": Stash(1, 1870, 0), + "m01s38i291": Stash(1, 1870, 0), + "m01s38i292": Stash(1, 1870, 0), + "m01s38i293": Stash(1, 1870, 0), + "m01s38i294": Stash(1, 1870, 0), + "m01s38i295": Stash(1, 1870, 0), + "m01s38i296": Stash(1, 1870, 0), + "m01s38i297": Stash(1, 1870, 0), + "m01s38i298": Stash(1, 1870, 0), + "m01s38i299": Stash(1, 1870, 0), + "m01s38i300": Stash(1, 1870, 0), + "m01s38i301": Stash(1, 1870, 0), + "m01s38i302": Stash(1, 1870, 0), + "m01s38i303": Stash(1, 1870, 0), + "m01s38i304": Stash(1, 1870, 0), + "m01s38i305": Stash(1, 1870, 0), + "m01s38i306": Stash(1, 1870, 0), + "m01s38i307": Stash(1, 1870, 0), + "m01s38i308": Stash(1, 1870, 0), + "m01s38i309": Stash(1, 1870, 0), + "m01s38i310": Stash(1, 1870, 0), + "m01s38i311": Stash(1, 1870, 0), + "m01s38i312": Stash(1, 1870, 0), + "m01s38i313": Stash(1, 1870, 0), + "m01s38i314": Stash(1, 1870, 0), + "m01s38i315": Stash(1, 1870, 0), + "m01s38i316": Stash(1, 1870, 0), + "m01s38i317": Stash(1, 1870, 0), + "m01s38i318": Stash(1, 1870, 0), + "m01s38i319": Stash(1, 1870, 0), + "m01s38i320": Stash(1, 1870, 0), + "m01s38i321": Stash(1, 1870, 0), + "m01s38i322": Stash(1, 1870, 0), + "m01s38i323": Stash(1, 1870, 0), + "m01s38i324": Stash(1, 1870, 0), + "m01s38i325": Stash(1, 1870, 0), + "m01s38i326": Stash(1, 1870, 0), + "m01s38i327": Stash(1, 1870, 0), + "m01s38i328": Stash(1, 1870, 0), + "m01s38i329": Stash(1, 1870, 0), + "m01s38i330": Stash(1, 1870, 0), + "m01s38i331": Stash(1, 1870, 0), + "m01s38i332": Stash(1, 1870, 0), + "m01s38i333": Stash(1, 1870, 0), + "m01s38i334": Stash(1, 1870, 0), + "m01s38i335": Stash(1, 1870, 0), + "m01s38i336": Stash(1, 1870, 0), + "m01s38i337": Stash(1, 1870, 0), + "m01s38i338": Stash(1, 1870, 0), + "m01s38i339": Stash(1, 1870, 0), + "m01s38i340": Stash(1, 1870, 0), + "m01s38i341": Stash(1, 1870, 0), + "m01s38i342": Stash(1, 1870, 0), + "m01s38i343": Stash(1, 1870, 0), + "m01s38i344": Stash(1, 1870, 0), + "m01s38i345": Stash(1, 1870, 0), + "m01s38i346": Stash(1, 1870, 0), + "m01s38i347": Stash(1, 1870, 0), + "m01s38i348": Stash(1, 1870, 0), + "m01s38i349": Stash(1, 1870, 0), + "m01s38i350": Stash(1, 1870, 0), + "m01s38i351": Stash(1, 1870, 0), + "m01s38i352": Stash(1, 1870, 0), + "m01s38i353": Stash(1, 1870, 0), + "m01s38i354": Stash(1, 1870, 0), + "m01s38i355": Stash(1, 1870, 0), + "m01s38i356": Stash(1, 1870, 0), + "m01s38i357": Stash(1, 1870, 0), + "m01s38i358": Stash(1, 1870, 0), + "m01s38i359": Stash(1, 1870, 0), + "m01s38i360": Stash(1, 1870, 0), + "m01s38i361": Stash(1, 1870, 0), + "m01s38i362": Stash(1, 1870, 0), + "m01s38i363": Stash(1, 1870, 0), + "m01s38i364": Stash(1, 1870, 0), + "m01s38i365": Stash(1, 1870, 0), + "m01s38i366": Stash(1, 1870, 0), + "m01s38i367": Stash(1, 1870, 0), + "m01s38i368": Stash(1, 1870, 0), + "m01s38i369": Stash(1, 1870, 0), + "m01s38i370": Stash(1, 1870, 0), + "m01s38i371": Stash(1, 1870, 0), + "m01s38i372": Stash(1, 1870, 0), + "m01s38i373": Stash(1, 1870, 0), + "m01s38i374": Stash(1, 1870, 0), + "m01s38i375": Stash(1, 1870, 0), + "m01s38i376": Stash(1, 1870, 0), + "m01s38i377": Stash(1, 1870, 0), + "m01s38i378": Stash(1, 1870, 0), + "m01s38i379": Stash(1, 1870, 0), + "m01s38i380": Stash(1, 1870, 0), + "m01s38i381": Stash(1, 1870, 0), + "m01s38i382": Stash(1, 1870, 0), + "m01s38i383": Stash(1, 1870, 0), + "m01s38i384": Stash(1, 1870, 0), + "m01s38i385": Stash(1, 1870, 0), + "m01s38i386": Stash(1, 1870, 0), + "m01s38i387": Stash(1, 1870, 0), + "m01s38i401": Stash(1, 0, 0), + "m01s38i402": Stash(1, 0, 0), + "m01s38i403": Stash(1, 0, 0), + "m01s38i404": Stash(1, 0, 0), + "m01s38i405": Stash(1, 0, 0), + "m01s38i406": Stash(1, 0, 0), + "m01s38i407": Stash(1, 0, 0), + "m01s38i408": Stash(1, 0, 0), + "m01s38i409": Stash(1, 0, 0), + "m01s38i410": Stash(1, 0, 0), + "m01s38i411": Stash(1, 0, 0), + "m01s38i412": Stash(1, 0, 0), + "m01s38i413": Stash(1, 0, 0), + "m01s38i414": Stash(1, 0, 0), + "m01s38i415": Stash(1, 0, 0), + "m01s38i416": Stash(1, 1864, 0), + "m01s38i417": Stash(1, 1864, 0), + "m01s38i418": Stash(1, 1864, 0), + "m01s38i419": Stash(1, 1864, 0), + "m01s38i420": Stash(1, 1864, 0), + "m01s38i421": Stash(1, 1864, 0), + "m01s38i422": Stash(1, 1864, 0), + "m01s38i423": Stash(1, 0, 0), + "m01s38i424": Stash(1, 0, 0), + "m01s38i425": Stash(1, 0, 0), + "m01s38i426": Stash(1, 0, 0), + "m01s38i427": Stash(1, 0, 0), + "m01s38i428": Stash(1, 0, 0), + "m01s38i429": Stash(1, 0, 0), + "m01s38i430": Stash(1, 1867, 0), + "m01s38i431": Stash(1, 1867, 0), + "m01s38i432": Stash(1, 1867, 0), + "m01s38i433": Stash(1, 1867, 0), + "m01s38i434": Stash(1, 1867, 0), + "m01s38i435": Stash(1, 1867, 0), + "m01s38i436": Stash(1, 1867, 0), + "m01s38i437": Stash(1, 1862, 0), + "m01s38i438": Stash(1, 1862, 0), + "m01s38i439": Stash(1, 1862, 0), + "m01s38i440": Stash(1, 1862, 0), + "m01s38i441": Stash(1, 1862, 0), + "m01s38i442": Stash(1, 0, 0), + "m01s38i443": Stash(1, 0, 0), + "m01s38i444": Stash(1, 0, 0), + "m01s38i445": Stash(1, 0, 0), + "m01s38i446": Stash(1, 0, 0), + "m01s38i447": Stash(1, 0, 0), + "m01s38i448": Stash(1, 0, 0), + "m01s38i449": Stash(1, 0, 0), + "m01s38i450": Stash(1, 0, 0), + "m01s38i451": Stash(1, 0, 0), + "m01s38i452": Stash(1, 0, 0), + "m01s38i453": Stash(1, 0, 0), + "m01s38i454": Stash(1, 0, 0), + "m01s38i455": Stash(1, 0, 0), + "m01s38i456": Stash(1, 0, 0), + "m01s38i457": Stash(1, 0, 0), + "m01s38i458": Stash(1, 0, 0), + "m01s38i459": Stash(1, 0, 0), + "m01s38i460": Stash(1, 0, 0), + "m01s38i461": Stash(1, 0, 0), + "m01s38i462": Stash(1, 0, 0), + "m01s38i463": Stash(1, 0, 0), + "m01s38i464": Stash(1, 0, 0), + "m01s38i465": Stash(1, 0, 0), + "m01s38i466": Stash(1, 0, 0), + "m01s38i467": Stash(1, 0, 0), + "m01s38i468": Stash(1, 0, 0), + "m01s38i469": Stash(1, 1862, 0), + "m01s38i470": Stash(1, 1862, 0), + "m01s38i471": Stash(1, 1862, 0), + "m01s38i472": Stash(1, 1862, 0), + "m01s38i473": Stash(1, 0, 0), + "m01s38i474": Stash(1, 0, 0), + "m01s38i475": Stash(1, 42, 0), + "m01s38i476": Stash(1, 1425, 0), + "m01s38i477": Stash(1, 1862, 0), + "m01s38i478": Stash(1, 0, 0), + "m01s38i479": Stash(1, 1862, 0), + "m01s38i480": Stash(1, 0, 0), + "m01s38i481": Stash(1, 0, 0), + "m01s38i482": Stash(1, 0, 0), + "m01s38i483": Stash(1, 0, 0), + "m01s38i484": Stash(1, 1862, 0), + "m01s39i001": Stash(1, 16, 0), + "m01s39i002": Stash(1, 16, 0), + "m01s39i003": Stash(1, 317, 0), + "m01s39i004": Stash(1, 317, 0), + "m01s39i005": Stash(1, 16, 0), + "m01s39i006": Stash(18, 56, 0), + "m01s39i007": Stash(18, 56, 0), + "m01s39i008": Stash(18, 318, 0), + "m01s39i009": Stash(18, 318, 0), + "m01s39i010": Stash(18, 56, 0), + "m01s39i011": Stash(19, 57, 0), + "m01s39i012": Stash(19, 57, 0), + "m01s39i013": Stash(19, 319, 0), + "m01s39i014": Stash(19, 319, 0), + "m01s39i015": Stash(19, 57, 0), + "m01s44i001": Stash(1, 1102, 0), + "m01s44i002": Stash(1, 1103, 0), + "m01s44i003": Stash(1, 1104, 0), + "m01s44i004": Stash(1, 1105, 0), + "m01s44i005": Stash(1, 1106, 0), + "m01s44i006": Stash(1, 1107, 0), + "m01s44i007": Stash(1, 1108, 0), + "m01s44i008": Stash(1, 1109, 0), + "m01s44i009": Stash(1, 1110, 0), + "m01s44i010": Stash(1, 1111, 0), + "m01s44i011": Stash(1, 1136, 0), + "m01s44i012": Stash(1, 1651, 4), + "m01s44i013": Stash(1, 1652, 4), + "m01s50i001": Stash(1, 1871, 0), + "m01s50i002": Stash(1, 1871, 0), + "m01s50i003": Stash(1, 1871, 0), + "m01s50i004": Stash(1, 1871, 0), + "m01s50i005": Stash(1, 1871, 0), + "m01s50i006": Stash(1, 1871, 0), + "m01s50i007": Stash(1, 1871, 0), + "m01s50i011": Stash(1, 1871, 0), + "m01s50i012": Stash(1, 1871, 0), + "m01s50i013": Stash(1, 1871, 0), + "m01s50i014": Stash(1, 1871, 0), + "m01s50i015": Stash(1, 1871, 0), + "m01s50i016": Stash(1, 1871, 0), + "m01s50i017": Stash(1, 1871, 0), + "m01s50i021": Stash(1, 1871, 0), + "m01s50i022": Stash(1, 1871, 0), + "m01s50i031": Stash(1, 1871, 0), + "m01s50i041": Stash(1, 1871, 0), + "m01s50i042": Stash(1, 1871, 0), + "m01s50i043": Stash(1, 1871, 0), + "m01s50i044": Stash(1, 1871, 0), + "m01s50i045": Stash(1, 1871, 0), + "m01s50i046": Stash(1, 1871, 0), + "m01s50i051": Stash(1, 1871, 0), + "m01s50i052": Stash(1, 1871, 0), + "m01s50i053": Stash(1, 1861, 0), + "m01s50i054": Stash(1, 1871, 0), + "m01s50i061": Stash(1, 1902, 0), + "m01s50i062": Stash(1, 0, 0), + "m01s50i063": Stash(1, 1902, 0), + "m01s50i071": Stash(1, 1871, 0), + "m01s50i072": Stash(1, 1871, 0), + "m01s50i073": Stash(1, 1871, 0), + "m01s50i074": Stash(1, 1871, 0), + "m01s50i075": Stash(1, 1871, 0), + "m01s50i076": Stash(1, 1871, 0), + "m01s50i077": Stash(1, 1871, 0), + "m01s50i078": Stash(1, 1871, 0), + "m01s50i079": Stash(1, 1871, 0), + "m01s50i081": Stash(1, 1871, 0), + "m01s50i082": Stash(1, 0, 0), + "m01s50i083": Stash(1, 0, 0), + "m01s50i084": Stash(1, 0, 0), + "m01s50i085": Stash(1, 1875, 0), + "m01s50i086": Stash(1, 1876, 0), + "m01s50i091": Stash(1, 1871, 0), + "m01s50i092": Stash(1, 1871, 0), + "m01s50i101": Stash(1, 1871, 0), + "m01s50i102": Stash(1, 1871, 0), + "m01s50i103": Stash(1, 1871, 0), + "m01s50i104": Stash(1, 1871, 0), + "m01s50i111": Stash(1, 1871, 0), + "m01s50i112": Stash(1, 1871, 0), + "m01s50i113": Stash(1, 1871, 0), + "m01s50i114": Stash(1, 1871, 0), + "m01s50i115": Stash(1, 1871, 0), + "m01s50i116": Stash(1, 1871, 0), + "m01s50i117": Stash(1, 1871, 0), + "m01s50i118": Stash(1, 1871, 0), + "m01s50i119": Stash(1, 1871, 0), + "m01s50i120": Stash(1, 1871, 0), + "m01s50i121": Stash(1, 1871, 0), + "m01s50i122": Stash(1, 1871, 0), + "m01s50i123": Stash(1, 1871, 0), + "m01s50i124": Stash(1, 1871, 0), + "m01s50i125": Stash(1, 1871, 0), + "m01s50i131": Stash(1, 1871, 0), + "m01s50i132": Stash(1, 1871, 0), + "m01s50i133": Stash(1, 1871, 0), + "m01s50i140": Stash(1, 1871, 0), + "m01s50i141": Stash(1, 1871, 0), + "m01s50i142": Stash(1, 1871, 0), + "m01s50i143": Stash(1, 1871, 0), + "m01s50i144": Stash(1, 1871, 0), + "m01s50i145": Stash(1, 1871, 0), + "m01s50i146": Stash(1, 1871, 0), + "m01s50i147": Stash(1, 1871, 0), + "m01s50i148": Stash(1, 1871, 0), + "m01s50i149": Stash(1, 1871, 0), + "m01s50i150": Stash(1, 1871, 0), + "m01s50i151": Stash(1, 1871, 0), + "m01s50i152": Stash(1, 1871, 0), + "m01s50i153": Stash(1, 1871, 0), + "m01s50i154": Stash(1, 1871, 0), + "m01s50i155": Stash(1, 1871, 0), + "m01s50i156": Stash(1, 1876, 0), + "m01s50i157": Stash(1, 1876, 0), + "m01s50i158": Stash(1, 1876, 0), + "m01s50i159": Stash(1, 1876, 0), + "m01s50i160": Stash(1, 1876, 0), + "m01s50i161": Stash(1, 1876, 0), + "m01s50i162": Stash(1, 1876, 0), + "m01s50i163": Stash(1, 1876, 0), + "m01s50i164": Stash(1, 1876, 0), + "m01s50i165": Stash(1, 1876, 0), + "m01s50i166": Stash(1, 1876, 0), + "m01s50i167": Stash(1, 1876, 0), + "m01s50i168": Stash(1, 1876, 0), + "m01s50i169": Stash(1, 1876, 0), + "m01s50i170": Stash(1, 1876, 0), + "m01s50i171": Stash(1, 1876, 0), + "m01s50i172": Stash(1, 1878, 0), + "m01s50i173": Stash(1, 0, 0), + "m01s50i174": Stash(1, 0, 0), + "m01s50i175": Stash(1, 0, 0), + "m01s50i176": Stash(1, 0, 0), + "m01s50i177": Stash(1, 0, 0), + "m01s50i178": Stash(1, 0, 0), + "m01s50i179": Stash(1, 0, 0), + "m01s50i180": Stash(1, 0, 0), + "m01s50i181": Stash(1, 0, 0), + "m01s50i182": Stash(1, 0, 0), + "m01s50i183": Stash(1, 0, 0), + "m01s50i184": Stash(1, 0, 0), + "m01s50i185": Stash(1, 0, 0), + "m01s50i186": Stash(1, 0, 0), + "m01s50i187": Stash(1, 0, 0), + "m01s50i188": Stash(1, 0, 0), + "m01s50i189": Stash(1, 0, 0), + "m01s50i190": Stash(1, 0, 0), + "m01s50i191": Stash(1, 0, 0), + "m01s50i192": Stash(1, 0, 0), + "m01s50i193": Stash(1, 0, 0), + "m01s50i194": Stash(1, 0, 0), + "m01s50i195": Stash(1, 0, 0), + "m01s50i196": Stash(1, 0, 0), + "m01s50i197": Stash(1, 0, 0), + "m01s50i198": Stash(1, 0, 0), + "m01s50i199": Stash(1, 0, 0), + "m01s50i200": Stash(1, 0, 0), + "m01s50i201": Stash(1, 0, 0), + "m01s50i202": Stash(1, 0, 0), + "m01s50i203": Stash(1, 0, 0), + "m01s50i204": Stash(1, 0, 0), + "m01s50i205": Stash(1, 0, 0), + "m01s50i206": Stash(1, 1861, 0), + "m01s50i207": Stash(1, 1861, 0), + "m01s50i208": Stash(1, 1861, 0), + "m01s50i209": Stash(1, 1861, 0), + "m01s50i210": Stash(1, 1861, 0), + "m02s00i101": Stash(0, 601, 0), + "m02s00i102": Stash(0, 602, 0), + "m02s00i103": Stash(0, 801, 0), + "m02s00i104": Stash(0, 802, 0), + "m02s00i105": Stash(0, 803, 0), + "m02s00i106": Stash(0, 804, 0), + "m02s00i107": Stash(0, 805, 0), + "m02s00i108": Stash(0, 806, 0), + "m02s00i109": Stash(0, 807, 0), + "m02s00i110": Stash(0, 808, 0), + "m02s00i111": Stash(0, 809, 0), + "m02s00i112": Stash(0, 810, 0), + "m02s00i113": Stash(0, 811, 0), + "m02s00i114": Stash(0, 812, 0), + "m02s00i115": Stash(0, 813, 0), + "m02s00i116": Stash(0, 814, 0), + "m02s00i117": Stash(0, 815, 0), + "m02s00i118": Stash(0, 816, 0), + "m02s00i119": Stash(0, 817, 0), + "m02s00i120": Stash(0, 818, 0), + "m02s00i121": Stash(0, 701, 0), + "m02s00i122": Stash(0, 702, 0), + "m02s00i128": Stash(0, 943, 0), + "m02s00i129": Stash(0, 944, 0), + "m02s00i130": Stash(0, 611, 0), + "m02s00i131": Stash(0, 612, 0), + "m02s00i132": Stash(0, 613, 0), + "m02s00i133": Stash(0, 614, 0), + "m02s00i134": Stash(0, 608, 0), + "m02s00i135": Stash(0, 711, 0), + "m02s00i136": Stash(0, 712, 0), + "m02s00i137": Stash(0, 653, 0), + "m02s00i139": Stash(0, 733, 0), + "m02s00i140": Stash(0, 734, 0), + "m02s00i141": Stash(0, 688, 0), + "m02s00i142": Stash(0, 685, 0), + "m02s00i143": Stash(0, 684, 0), + "m02s00i144": Stash(0, 686, 0), + "m02s00i145": Stash(0, 0, 0), + "m02s00i146": Stash(0, 683, 0), + "m02s00i147": Stash(0, 687, 0), + "m02s00i148": Stash(0, 728, 0), + "m02s00i149": Stash(0, 729, 0), + "m02s00i150": Stash(0, 721, 0), + "m02s00i151": Stash(0, 722, 0), + "m02s00i152": Stash(0, 627, 0), + "m02s00i153": Stash(0, 0, 0), + "m02s00i154": Stash(0, 866, 0), + "m02s00i155": Stash(0, 867, 0), + "m02s00i160": Stash(0, 659, 0), + "m02s00i161": Stash(0, 625, 0), + "m02s00i162": Stash(0, 626, 0), + "m02s00i165": Stash(0, 629, 0), + "m02s00i166": Stash(0, 631, 0), + "m02s00i167": Stash(0, 0, 0), + "m02s00i170": Stash(0, 698, 0), + "m02s00i171": Stash(0, 623, 0), + "m02s00i172": Stash(0, 624, 0), + "m02s00i175": Stash(0, 670, 0), + "m02s00i176": Stash(0, 670, 0), + "m02s00i177": Stash(0, 677, 0), + "m02s00i178": Stash(0, 678, 0), + "m02s00i179": Stash(0, 679, 0), + "m02s00i180": Stash(0, 650, 0), + "m02s00i181": Stash(0, 649, 0), + "m02s00i182": Stash(0, 0, 0), + "m02s00i183": Stash(0, 675, 0), + "m02s00i185": Stash(0, 671, 0), + "m02s00i186": Stash(0, 672, 0), + "m02s00i187": Stash(0, 687, 0), + "m02s00i188": Stash(0, 688, 0), + "m02s00i189": Stash(0, 689, 0), + "m02s00i190": Stash(0, 681, 0), + "m02s00i191": Stash(0, 682, 0), + "m02s00i192": Stash(0, 615, 0), + "m02s00i193": Stash(0, 616, 0), + "m02s00i194": Stash(0, 658, 0), + "m02s00i195": Stash(0, 609, 0), + "m02s00i196": Stash(0, 713, 0), + "m02s00i197": Stash(0, 714, 0), + "m02s00i198": Stash(0, 715, 0), + "m02s00i199": Stash(0, 716, 0), + "m02s00i200": Stash(0, 838, 0), + "m02s00i201": Stash(0, 839, 0), + "m02s00i202": Stash(0, 840, 0), + "m02s00i203": Stash(0, 841, 0), + "m02s00i204": Stash(0, 747, 0), + "m02s00i205": Stash(0, 748, 0), + "m02s00i206": Stash(0, 749, 0), + "m02s00i207": Stash(0, 0, 0), + "m02s00i208": Stash(0, 0, 0), + "m02s00i210": Stash(0, 800, 0), + "m02s00i211": Stash(0, 800, 0), + "m02s00i212": Stash(0, 800, 0), + "m02s00i213": Stash(0, 800, 0), + "m02s00i214": Stash(0, 800, 0), + "m02s00i215": Stash(0, 800, 0), + "m02s00i216": Stash(0, 800, 0), + "m02s00i217": Stash(0, 800, 0), + "m02s00i218": Stash(0, 800, 0), + "m02s00i219": Stash(0, 800, 0), + "m02s00i220": Stash(0, 800, 0), + "m02s00i221": Stash(0, 800, 0), + "m02s00i222": Stash(0, 1955, 10), + "m02s00i223": Stash(0, 1953, 10), + "m02s00i224": Stash(0, 1954, 10), + "m02s00i225": Stash(0, 1951, 10), + "m02s00i226": Stash(0, 1952, 10), + "m02s00i231": Stash(0, 1037, 0), + "m02s00i232": Stash(0, 1038, 0), + "m02s00i233": Stash(0, 1039, 0), + "m02s00i234": Stash(0, 1040, 0), + "m02s00i235": Stash(0, 1041, 0), + "m02s00i236": Stash(0, 1042, 0), + "m02s00i237": Stash(0, 1043, 0), + "m02s00i238": Stash(0, 1044, 0), + "m02s00i239": Stash(0, 1045, 0), + "m02s00i240": Stash(0, 1046, 0), + "m02s00i285": Stash(0, 617, 0), + "m02s00i291": Stash(0, 691, 0), + "m02s00i292": Stash(0, 692, 0), + "m02s00i293": Stash(0, 625, 0), + "m02s00i294": Stash(0, 626, 0), + "m02s00i295": Stash(0, 624, 0), + "m02s00i296": Stash(0, 681, 0), + "m02s00i297": Stash(0, 682, 0), + "m02s00i298": Stash(0, 681, 0), + "m02s00i299": Stash(0, 682, 0), + "m02s00i331": Stash(0, 749, 0), + "m02s00i332": Stash(0, 750, 0), + "m02s00i333": Stash(0, 751, 0), + "m02s30i201": Stash(0, 680, 0), + "m02s30i202": Stash(0, 653, 0), + "m02s30i203": Stash(0, 671, 0), + "m02s30i204": Stash(0, 672, 0), + "m02s30i205": Stash(0, 678, 0), + "m02s30i206": Stash(0, 626, 0), + "m02s30i207": Stash(0, 623, 0), + "m02s30i208": Stash(0, 685, 0), + "m02s30i210": Stash(0, 647, 0), + "m02s30i211": Stash(0, 740, 0), + "m02s30i212": Stash(0, 740, 0), + "m02s30i213": Stash(0, 740, 0), + "m02s30i214": Stash(0, 740, 0), + "m02s30i215": Stash(0, 740, 0), + "m02s30i216": Stash(0, 740, 0), + "m02s30i217": Stash(0, 740, 0), + "m02s30i218": Stash(0, 740, 0), + "m02s30i219": Stash(0, 740, 0), + "m02s30i220": Stash(0, 740, 0), + "m02s30i221": Stash(0, 740, 0), + "m02s30i222": Stash(0, 740, 0), + "m02s30i223": Stash(0, 740, 0), + "m02s30i224": Stash(0, 740, 0), + "m02s30i225": Stash(0, 740, 0), + "m02s30i226": Stash(0, 740, 0), + "m02s30i227": Stash(0, 740, 0), + "m02s30i228": Stash(0, 740, 0), + "m02s30i229": Stash(0, 740, 0), + "m02s30i230": Stash(0, 740, 0), + "m02s30i231": Stash(0, 801, 0), + "m02s30i232": Stash(0, 802, 0), + "m02s30i233": Stash(0, 803, 0), + "m02s30i234": Stash(0, 804, 0), + "m02s30i235": Stash(0, 805, 0), + "m02s30i236": Stash(0, 806, 0), + "m02s30i237": Stash(0, 807, 0), + "m02s30i238": Stash(0, 808, 0), + "m02s30i239": Stash(0, 809, 0), + "m02s30i240": Stash(0, 810, 0), + "m02s30i241": Stash(0, 811, 0), + "m02s30i242": Stash(0, 642, 0), + "m02s30i243": Stash(0, 813, 0), + "m02s30i244": Stash(0, 814, 0), + "m02s30i245": Stash(0, 815, 0), + "m02s30i246": Stash(0, 713, 0), + "m02s30i247": Stash(0, 714, 0), + "m02s30i248": Stash(0, 645, 0), + "m02s30i249": Stash(0, 646, 0), + "m02s30i250": Stash(0, 647, 0), + "m02s30i251": Stash(0, 648, 0), + "m02s30i252": Stash(0, 891, 0), + "m02s30i253": Stash(0, 892, 0), + "m02s30i254": Stash(0, 893, 0), + "m02s30i255": Stash(0, 894, 0), + "m02s30i256": Stash(0, 895, 0), + "m02s30i257": Stash(0, 896, 0), + "m02s30i258": Stash(0, 897, 0), + "m02s30i259": Stash(0, 898, 0), + "m02s30i260": Stash(0, 899, 0), + "m02s30i261": Stash(0, 900, 0), + "m02s30i262": Stash(0, 901, 0), + "m02s30i263": Stash(0, 902, 0), + "m02s30i264": Stash(0, 903, 0), + "m02s30i265": Stash(0, 904, 0), + "m02s30i266": Stash(0, 905, 0), + "m02s30i267": Stash(0, 906, 0), + "m02s30i268": Stash(0, 907, 0), + "m02s30i269": Stash(0, 908, 0), + "m02s30i270": Stash(0, 909, 0), + "m02s30i271": Stash(0, 910, 0), + "m02s30i272": Stash(0, 911, 0), + "m02s30i273": Stash(0, 912, 0), + "m02s30i274": Stash(0, 913, 0), + "m02s30i275": Stash(0, 914, 0), + "m02s30i276": Stash(0, 915, 0), + "m02s30i277": Stash(0, 916, 0), + "m02s30i278": Stash(0, 917, 0), + "m02s30i279": Stash(0, 678, 0), + "m02s30i280": Stash(0, 632, 0), + "m02s30i281": Stash(0, 831, 0), + "m02s30i282": Stash(0, 832, 0), + "m02s30i283": Stash(0, 833, 0), + "m02s30i284": Stash(0, 834, 0), + "m02s30i285": Stash(0, 617, 0), + "m02s30i286": Stash(0, 795, 0), + "m02s30i287": Stash(0, 695, 0), + "m02s30i288": Stash(0, 796, 0), + "m02s30i289": Stash(0, 696, 0), + "m02s30i290": Stash(0, 797, 0), + "m02s30i291": Stash(0, 697, 0), + "m02s30i292": Stash(0, 673, 0), + "m02s30i293": Stash(0, 674, 0), + "m02s30i294": Stash(0, 867, 0), + "m02s30i296": Stash(0, 795, 0), + "m02s30i297": Stash(0, 695, 0), + "m02s30i298": Stash(0, 796, 0), + "m02s30i299": Stash(0, 696, 0), + "m02s30i301": Stash(0, 637, 0), + "m02s30i302": Stash(0, 865, 0), + "m02s30i303": Stash(0, 866, 0), + "m02s30i306": Stash(0, 648, 0), + "m02s30i307": Stash(0, 648, 0), + "m02s30i308": Stash(0, 648, 0), + "m02s30i309": Stash(0, 648, 0), + "m02s30i310": Stash(0, 648, 0), + "m02s30i311": Stash(0, 648, 0), + "m02s30i312": Stash(0, 648, 0), + "m02s30i313": Stash(0, 648, 0), + "m02s30i314": Stash(0, 648, 0), + "m02s30i315": Stash(0, 648, 0), + "m02s30i316": Stash(0, 648, 0), + "m02s30i317": Stash(0, 648, 0), + "m02s30i318": Stash(0, 648, 0), + "m02s30i319": Stash(0, 648, 0), + "m02s30i320": Stash(0, 703, 0), + "m02s30i321": Stash(0, 704, 0), + "m02s30i322": Stash(0, 648, 0), + "m02s30i323": Stash(0, 657, 0), + "m02s30i324": Stash(0, 653, 0), + "m02s30i325": Stash(0, 653, 0), + "m02s30i330": Stash(0, 860, 0), + "m02s30i331": Stash(0, 860, 0), + "m02s30i400": Stash(0, 891, 0), + "m02s30i401": Stash(0, 892, 0), + "m02s30i402": Stash(0, 893, 0), + "m02s30i403": Stash(0, 894, 0), + "m02s30i404": Stash(0, 895, 0), + "m02s30i405": Stash(0, 896, 0), + "m02s30i406": Stash(0, 897, 0), + "m02s30i410": Stash(0, 901, 0), + "m02s30i411": Stash(0, 902, 0), + "m02s30i412": Stash(0, 903, 0), + "m02s30i413": Stash(0, 904, 0), + "m02s30i414": Stash(0, 905, 0), + "m02s30i415": Stash(0, 906, 0), + "m02s30i416": Stash(0, 907, 0), + "m02s30i417": Stash(0, 908, 0), + "m02s30i418": Stash(0, 909, 0), + "m02s30i419": Stash(0, 910, 0), + "m02s30i420": Stash(0, 911, 0), + "m02s30i421": Stash(0, 912, 0), + "m02s30i422": Stash(0, 913, 0), + "m02s30i423": Stash(0, 914, 0), + "m02s30i424": Stash(0, 915, 0), + "m02s30i425": Stash(0, 916, 0), + "m02s30i426": Stash(0, 917, 0), + "m02s30i427": Stash(0, 918, 0), + "m02s30i428": Stash(0, 919, 0), + "m02s30i429": Stash(0, 920, 0), + "m02s30i430": Stash(0, 921, 0), + "m02s30i431": Stash(0, 922, 0), + "m02s30i432": Stash(0, 0, 0), + "m02s30i433": Stash(0, 0, 0), + "m02s30i434": Stash(0, 0, 0), + "m02s30i435": Stash(0, 0, 0), + "m02s30i436": Stash(0, 0, 0), + "m02s30i437": Stash(0, 0, 0), + "m02s30i438": Stash(0, 0, 0), + "m02s30i439": Stash(0, 0, 0), + "m02s30i440": Stash(0, 0, 0), + "m02s30i441": Stash(0, 0, 0), + "m02s30i442": Stash(0, 0, 0), + "m02s30i443": Stash(0, 0, 0), + "m02s30i444": Stash(0, 0, 0), + "m02s30i445": Stash(0, 0, 0), + "m02s30i446": Stash(0, 0, 0), + "m02s30i447": Stash(0, 0, 0), + "m02s30i448": Stash(0, 0, 0), + "m02s30i449": Stash(0, 940, 0), + "m02s30i450": Stash(0, 0, 0), + "m02s30i451": Stash(0, 0, 0), + "m02s30i452": Stash(0, 0, 0), + "m02s30i453": Stash(0, 0, 0), + "m02s30i454": Stash(0, 0, 0), + "m02s30i455": Stash(0, 0, 0), + "m02s30i456": Stash(0, 0, 0), + "m02s30i457": Stash(0, 0, 0), + "m02s30i458": Stash(0, 0, 0), + "m02s30i459": Stash(0, 940, 0), + "m02s30i460": Stash(0, 0, 0), + "m02s30i461": Stash(0, 940, 0), + "m02s30i462": Stash(0, 941, 0), + "m02s30i463": Stash(0, 942, 0), + "m02s30i464": Stash(0, 943, 0), + "m02s30i465": Stash(0, 944, 0), + "m02s30i466": Stash(0, 945, 0), + "m02s30i467": Stash(0, 946, 0), + "m02s30i468": Stash(0, 947, 0), + "m02s30i469": Stash(0, 0, 0), + "m02s30i470": Stash(0, 0, 0), + "m02s30i471": Stash(0, 0, 0), + "m02s31i201": Stash(0, 715, 0), + "m02s31i202": Stash(0, 618, 0), + "m02s31i211": Stash(0, 660, 0), + "m02s31i212": Stash(0, 661, 0), + "m02s31i213": Stash(0, 662, 0), + "m02s31i214": Stash(0, 663, 0), + "m02s31i215": Stash(0, 664, 0), + "m02s31i216": Stash(0, 665, 0), + "m02s31i217": Stash(0, 666, 0), + "m02s31i218": Stash(0, 667, 0), + "m02s31i219": Stash(0, 668, 0), + "m02s31i220": Stash(0, 669, 0), + "m02s31i285": Stash(0, 617, 0), + "m02s31i290": Stash(0, 669, 0), + "m02s32i201": Stash(0, 683, 0), + "m02s32i202": Stash(0, 687, 0), + "m02s32i203": Stash(0, 688, 0), + "m02s32i204": Stash(0, 687, 0), + "m02s32i205": Stash(0, 689, 0), + "m02s32i206": Stash(0, 690, 0), + "m02s32i207": Stash(0, 728, 0), + "m02s32i208": Stash(0, 729, 0), + "m02s32i209": Stash(0, 731, 0), + "m02s32i210": Stash(0, 732, 0), + "m02s32i211": Stash(0, 683, 0), + "m02s32i212": Stash(0, 687, 0), + "m02s32i213": Stash(0, 688, 0), + "m02s32i214": Stash(0, 626, 0), + "m02s32i215": Stash(0, 623, 0), + "m02s32i216": Stash(0, 601, 0), + "m02s32i217": Stash(0, 626, 0), + "m02s32i218": Stash(0, 626, 0), + "m02s32i219": Stash(0, 733, 0), + "m02s32i220": Stash(0, 734, 0), + "m02s32i221": Stash(0, 735, 0), + "m02s32i222": Stash(0, 736, 0), + "m02s32i223": Stash(0, 918, 0), + "m02s32i224": Stash(0, 919, 0), + "m02s32i225": Stash(0, 920, 0), + "m02s32i226": Stash(0, 919, 0), + "m02s32i227": Stash(0, 918, 0), + "m02s32i228": Stash(0, 919, 0), + "m02s32i229": Stash(0, 920, 0), + "m02s32i230": Stash(0, 737, 0), + "m02s32i231": Stash(0, 738, 0), + "m02s32i232": Stash(0, 918, 0), + "m02s32i233": Stash(0, 919, 0), + "m02s32i234": Stash(0, 920, 0), + "m02s32i235": Stash(0, 1959, 10), + "m02s32i236": Stash(0, 1956, 10), + "m02s32i237": Stash(0, 1957, 10), + "m02s32i238": Stash(0, 1958, 10), + "m02s32i239": Stash(0, 1956, 10), + "m02s32i240": Stash(0, 1957, 10), + "m02s32i241": Stash(0, 1958, 10), + "m02s32i242": Stash(0, 1956, 10), + "m02s32i243": Stash(0, 1957, 10), + "m02s32i244": Stash(0, 1958, 10), + "m02s32i245": Stash(0, 801, 0), + "m02s32i246": Stash(0, 801, 0), + "m02s32i247": Stash(0, 919, 0), + "m02s32i248": Stash(0, 920, 0), + "m02s32i249": Stash(0, 1957, 10), + "m02s32i250": Stash(0, 1958, 10), + "m02s32i300": Stash(0, 801, 0), + "m02s32i301": Stash(0, 801, 0), + "m02s32i302": Stash(0, 801, 0), + "m02s32i303": Stash(0, 801, 0), + "m02s32i304": Stash(0, 801, 0), + "m02s32i305": Stash(0, 801, 0), + "m02s32i306": Stash(0, 801, 0), + "m02s32i307": Stash(0, 801, 0), + "m02s32i308": Stash(0, 801, 0), + "m02s32i309": Stash(0, 801, 0), + "m02s35i101": Stash(0, 601, 0), + "m02s35i102": Stash(0, 602, 0), + "m02s35i121": Stash(0, 701, 0), + "m02s35i122": Stash(0, 702, 0), + "m02s35i130": Stash(0, 611, 0), + "m02s35i134": Stash(0, 608, 0), + "m02s35i135": Stash(0, 711, 0), + "m02s35i136": Stash(0, 712, 0), + "m02s35i137": Stash(0, 653, 0), + "m02s35i201": Stash(0, 850, 0), + "m02s35i202": Stash(0, 851, 0), + "m02s35i203": Stash(0, 852, 0), + "m02s35i204": Stash(0, 853, 0), + "m02s35i205": Stash(0, 854, 0), + "m02s35i206": Stash(0, 855, 0), + "m02s35i211": Stash(0, 860, 0), + "m02s35i213": Stash(0, 862, 0), + "m02s35i214": Stash(0, 863, 0), + "m02s35i215": Stash(0, 864, 0), + "m02s35i221": Stash(0, 871, 0), + "m02s35i224": Stash(0, 872, 0), + "m02s35i225": Stash(0, 873, 0), + "m02s35i231": Stash(0, 876, 0), + "m02s35i234": Stash(0, 877, 0), + "m02s35i235": Stash(0, 878, 0), + "m02s35i241": Stash(0, 880, 0), + "m02s35i244": Stash(0, 881, 0), + "m02s35i245": Stash(0, 882, 0), + "m02s35i251": Stash(0, 885, 0), + "m02s35i254": Stash(0, 888, 0), + "m02s35i255": Stash(0, 884, 0), + "m02s35i281": Stash(0, 683, 0), + "m02s35i282": Stash(0, 687, 0), + "m02s35i283": Stash(0, 688, 0), + "m02s35i284": Stash(0, 685, 0), + "m02s35i285": Stash(0, 686, 0), + "m02s35i301": Stash(0, 857, 0), + "m02s35i302": Stash(0, 858, 0), + "m02s35i310": Stash(0, 859, 0), + "m02s35i323": Stash(0, 699, 0), + "m02s41i101": Stash(0, 601, 0), + "m02s41i102": Stash(0, 602, 0), + "m02s41i103": Stash(0, 801, 0), + "m02s41i104": Stash(0, 802, 0), + "m02s41i105": Stash(0, 803, 0), + "m02s41i106": Stash(0, 804, 0), + "m02s41i107": Stash(0, 805, 0), + "m02s41i108": Stash(0, 806, 0), + "m02s41i109": Stash(0, 807, 0), + "m02s41i110": Stash(0, 808, 0), + "m02s41i111": Stash(0, 809, 0), + "m02s41i112": Stash(0, 810, 0), + "m02s41i113": Stash(0, 811, 0), + "m02s41i114": Stash(0, 812, 0), + "m02s41i115": Stash(0, 813, 0), + "m02s41i116": Stash(0, 814, 0), + "m02s41i117": Stash(0, 815, 0), + "m02s41i118": Stash(0, 816, 0), + "m02s41i119": Stash(0, 817, 0), + "m02s41i120": Stash(0, 818, 0), + "m02s41i121": Stash(0, 701, 0), + "m02s41i122": Stash(0, 702, 0), + "m02s41i130": Stash(0, 611, 0), + "m02s41i131": Stash(0, 612, 0), + "m02s41i132": Stash(0, 613, 0), + "m02s41i133": Stash(0, 614, 0), + "m02s41i134": Stash(0, 608, 0), + "m02s41i135": Stash(0, 711, 0), + "m02s41i136": Stash(0, 712, 0), + "m02s41i137": Stash(0, 653, 0), + "m02s41i139": Stash(0, 633, 0), + "m02s41i140": Stash(0, 634, 0), + "m02s41i141": Stash(0, 688, 0), + "m02s41i142": Stash(0, 685, 0), + "m02s41i143": Stash(0, 684, 0), + "m02s41i144": Stash(0, 686, 0), + "m02s41i145": Stash(0, 0, 0), + "m02s41i146": Stash(0, 683, 0), + "m02s41i147": Stash(0, 687, 0), + "m02s41i148": Stash(0, 728, 0), + "m02s41i149": Stash(0, 729, 0), + "m02s41i150": Stash(0, 721, 0), + "m02s41i151": Stash(0, 722, 0), + "m02s41i152": Stash(0, 627, 0), + "m02s41i153": Stash(0, 0, 0), + "m02s41i161": Stash(0, 625, 0), + "m02s41i162": Stash(0, 626, 0), + "m02s41i165": Stash(0, 629, 0), + "m02s41i166": Stash(0, 631, 0), + "m02s41i167": Stash(0, 0, 0), + "m02s41i170": Stash(0, 698, 0), + "m02s41i171": Stash(0, 623, 0), + "m02s41i172": Stash(0, 624, 0), + "m02s41i180": Stash(0, 650, 0), + "m02s41i181": Stash(0, 649, 0), + "m02s41i182": Stash(0, 0, 0), + "m02s41i183": Stash(0, 675, 0), + "m02s41i185": Stash(0, 671, 0), + "m02s41i186": Stash(0, 672, 0), + "m02s41i187": Stash(0, 678, 0), + "m02s41i190": Stash(0, 681, 0), + "m02s41i191": Stash(0, 682, 0), + "m02s42i101": Stash(0, 601, 0), + "m02s42i102": Stash(0, 602, 0), + "m02s42i103": Stash(0, 801, 0), + "m02s42i104": Stash(0, 802, 0), + "m02s42i105": Stash(0, 803, 0), + "m02s42i106": Stash(0, 804, 0), + "m02s42i107": Stash(0, 805, 0), + "m02s42i108": Stash(0, 806, 0), + "m02s42i109": Stash(0, 807, 0), + "m02s42i110": Stash(0, 808, 0), + "m02s42i111": Stash(0, 809, 0), + "m02s42i112": Stash(0, 810, 0), + "m02s42i113": Stash(0, 811, 0), + "m02s42i114": Stash(0, 812, 0), + "m02s42i115": Stash(0, 813, 0), + "m02s42i116": Stash(0, 814, 0), + "m02s42i117": Stash(0, 815, 0), + "m02s42i118": Stash(0, 816, 0), + "m02s42i119": Stash(0, 817, 0), + "m02s42i120": Stash(0, 818, 0), + "m02s42i121": Stash(0, 701, 0), + "m02s42i122": Stash(0, 702, 0), + "m02s42i130": Stash(0, 611, 0), + "m02s42i131": Stash(0, 612, 0), + "m02s42i132": Stash(0, 613, 0), + "m02s42i133": Stash(0, 614, 0), + "m02s42i134": Stash(0, 608, 0), + "m02s42i135": Stash(0, 711, 0), + "m02s42i136": Stash(0, 712, 0), + "m02s42i137": Stash(0, 653, 0), + "m02s42i139": Stash(0, 633, 0), + "m02s42i140": Stash(0, 634, 0), + "m02s42i141": Stash(0, 688, 0), + "m02s42i142": Stash(0, 685, 0), + "m02s42i143": Stash(0, 684, 0), + "m02s42i144": Stash(0, 686, 0), + "m02s42i145": Stash(0, 0, 0), + "m02s42i146": Stash(0, 683, 0), + "m02s42i147": Stash(0, 687, 0), + "m02s42i148": Stash(0, 728, 0), + "m02s42i149": Stash(0, 729, 0), + "m02s42i150": Stash(0, 721, 0), + "m02s42i151": Stash(0, 722, 0), + "m02s42i152": Stash(0, 627, 0), + "m02s42i153": Stash(0, 0, 0), + "m02s42i161": Stash(0, 625, 0), + "m02s42i162": Stash(0, 626, 0), + "m02s42i165": Stash(0, 629, 0), + "m02s42i166": Stash(0, 631, 0), + "m02s42i167": Stash(0, 0, 0), + "m02s42i170": Stash(0, 698, 0), + "m02s42i171": Stash(0, 623, 0), + "m02s42i172": Stash(0, 624, 0), + "m02s42i180": Stash(0, 650, 0), + "m02s42i181": Stash(0, 649, 0), + "m02s42i182": Stash(0, 0, 0), + "m02s42i183": Stash(0, 675, 0), + "m02s42i185": Stash(0, 671, 0), + "m02s42i186": Stash(0, 672, 0), + "m02s42i187": Stash(0, 678, 0), + "m02s42i190": Stash(0, 681, 0), + "m02s42i191": Stash(0, 682, 0), + "m02s43i101": Stash(0, 601, 0), + "m02s43i102": Stash(0, 602, 0), + "m02s43i103": Stash(0, 801, 0), + "m02s43i104": Stash(0, 802, 0), + "m02s43i105": Stash(0, 803, 0), + "m02s43i106": Stash(0, 804, 0), + "m02s43i107": Stash(0, 805, 0), + "m02s43i108": Stash(0, 806, 0), + "m02s43i109": Stash(0, 807, 0), + "m02s43i110": Stash(0, 808, 0), + "m02s43i111": Stash(0, 809, 0), + "m02s43i112": Stash(0, 810, 0), + "m02s43i113": Stash(0, 811, 0), + "m02s43i114": Stash(0, 812, 0), + "m02s43i115": Stash(0, 813, 0), + "m02s43i116": Stash(0, 814, 0), + "m02s43i117": Stash(0, 815, 0), + "m02s43i118": Stash(0, 816, 0), + "m02s43i119": Stash(0, 817, 0), + "m02s43i120": Stash(0, 818, 0), + "m02s43i121": Stash(0, 701, 0), + "m02s43i122": Stash(0, 702, 0), + "m02s43i130": Stash(0, 611, 0), + "m02s43i131": Stash(0, 612, 0), + "m02s43i132": Stash(0, 613, 0), + "m02s43i133": Stash(0, 614, 0), + "m02s43i134": Stash(0, 608, 0), + "m02s43i135": Stash(0, 711, 0), + "m02s43i136": Stash(0, 712, 0), + "m02s43i137": Stash(0, 653, 0), + "m02s43i139": Stash(0, 633, 0), + "m02s43i140": Stash(0, 634, 0), + "m02s43i141": Stash(0, 688, 0), + "m02s43i142": Stash(0, 685, 0), + "m02s43i143": Stash(0, 684, 0), + "m02s43i144": Stash(0, 686, 0), + "m02s43i145": Stash(0, 0, 0), + "m02s43i146": Stash(0, 683, 0), + "m02s43i147": Stash(0, 687, 0), + "m02s43i148": Stash(0, 728, 0), + "m02s43i149": Stash(0, 729, 0), + "m02s43i150": Stash(0, 721, 0), + "m02s43i151": Stash(0, 722, 0), + "m02s43i152": Stash(0, 627, 0), + "m02s43i153": Stash(0, 0, 0), + "m02s43i161": Stash(0, 625, 0), + "m02s43i162": Stash(0, 626, 0), + "m02s43i165": Stash(0, 629, 0), + "m02s43i166": Stash(0, 631, 0), + "m02s43i167": Stash(0, 0, 0), + "m02s43i170": Stash(0, 698, 0), + "m02s43i171": Stash(0, 623, 0), + "m02s43i172": Stash(0, 624, 0), + "m02s43i180": Stash(0, 650, 0), + "m02s43i181": Stash(0, 649, 0), + "m02s43i182": Stash(0, 0, 0), + "m02s43i183": Stash(0, 675, 0), + "m02s43i185": Stash(0, 671, 0), + "m02s43i186": Stash(0, 672, 0), + "m02s43i187": Stash(0, 678, 0), + "m02s43i190": Stash(0, 681, 0), + "m02s43i191": Stash(0, 682, 0), + "m02s44i101": Stash(0, 601, 0), + "m02s44i102": Stash(0, 602, 0), + "m02s44i103": Stash(0, 801, 0), + "m02s44i104": Stash(0, 802, 0), + "m02s44i105": Stash(0, 803, 0), + "m02s44i106": Stash(0, 804, 0), + "m02s44i107": Stash(0, 805, 0), + "m02s44i108": Stash(0, 806, 0), + "m02s44i109": Stash(0, 807, 0), + "m02s44i110": Stash(0, 808, 0), + "m02s44i111": Stash(0, 809, 0), + "m02s44i112": Stash(0, 810, 0), + "m02s44i113": Stash(0, 811, 0), + "m02s44i114": Stash(0, 812, 0), + "m02s44i115": Stash(0, 813, 0), + "m02s44i116": Stash(0, 814, 0), + "m02s44i117": Stash(0, 815, 0), + "m02s44i118": Stash(0, 816, 0), + "m02s44i119": Stash(0, 817, 0), + "m02s44i120": Stash(0, 818, 0), + "m02s44i121": Stash(0, 701, 0), + "m02s44i122": Stash(0, 702, 0), + "m02s44i130": Stash(0, 611, 0), + "m02s44i131": Stash(0, 612, 0), + "m02s44i132": Stash(0, 613, 0), + "m02s44i133": Stash(0, 614, 0), + "m02s44i134": Stash(0, 608, 0), + "m02s44i135": Stash(0, 711, 0), + "m02s44i136": Stash(0, 712, 0), + "m02s44i137": Stash(0, 653, 0), + "m02s44i139": Stash(0, 633, 0), + "m02s44i140": Stash(0, 634, 0), + "m02s44i141": Stash(0, 688, 0), + "m02s44i142": Stash(0, 685, 0), + "m02s44i143": Stash(0, 684, 0), + "m02s44i144": Stash(0, 686, 0), + "m02s44i145": Stash(0, 0, 0), + "m02s44i146": Stash(0, 683, 0), + "m02s44i147": Stash(0, 687, 0), + "m02s44i148": Stash(0, 728, 0), + "m02s44i149": Stash(0, 729, 0), + "m02s44i150": Stash(0, 721, 0), + "m02s44i151": Stash(0, 722, 0), + "m02s44i152": Stash(0, 627, 0), + "m02s44i153": Stash(0, 0, 0), + "m02s44i161": Stash(0, 625, 0), + "m02s44i162": Stash(0, 626, 0), + "m02s44i165": Stash(0, 629, 0), + "m02s44i166": Stash(0, 631, 0), + "m02s44i167": Stash(0, 0, 0), + "m02s44i170": Stash(0, 698, 0), + "m02s44i171": Stash(0, 623, 0), + "m02s44i172": Stash(0, 624, 0), + "m02s44i180": Stash(0, 650, 0), + "m02s44i181": Stash(0, 649, 0), + "m02s44i182": Stash(0, 0, 0), + "m02s44i183": Stash(0, 675, 0), + "m02s44i185": Stash(0, 671, 0), + "m02s44i186": Stash(0, 672, 0), + "m02s44i187": Stash(0, 678, 0), + "m02s44i190": Stash(0, 681, 0), + "m02s44i191": Stash(0, 682, 0), + "m03s00i142": Stash(3, 650, 0), + "m03s00i143": Stash(3, 675, 0), + "m03s00i177": Stash(1, 620, 0), + "m03s00i178": Stash(1, 650, 0), + "m03s00i179": Stash(1, 675, 0), + "m03s00i210": Stash(3, 16, 0), + "m03s00i211": Stash(11, 728, 0), + "m03s00i212": Stash(11, 729, 0), + "m03s00i280": Stash(3, 800, 0), + "m03s00i281": Stash(3, 800, 0), + "m03s00i282": Stash(3, 800, 0), + "m03s00i283": Stash(3, 800, 0), + "m03s00i284": Stash(3, 800, 0), + "m03s00i285": Stash(3, 800, 0), + "m03s00i286": Stash(3, 800, 0), + "m03s00i287": Stash(3, 800, 0), + "m03s00i288": Stash(3, 800, 0), + "m03s00i289": Stash(3, 800, 0), + "m03s00i290": Stash(3, 800, 0), + "m03s00i291": Stash(3, 800, 0), + "m03s00i292": Stash(18, 728, 0), + "m03s00i293": Stash(19, 729, 0), + "m03s21i177": Stash(1, 620, 0), + "m03s21i178": Stash(1, 650, 0), + "m03s21i179": Stash(1, 675, 0), + "m03s21i225": Stash(3, 16, 0), + "m03s21i226": Stash(11, 728, 0), + "m03s21i227": Stash(11, 729, 0), + "m03s22i177": Stash(1, 620, 0), + "m03s22i178": Stash(1, 650, 0), + "m03s22i179": Stash(1, 675, 0), + "m03s22i225": Stash(3, 16, 0), + "m03s22i226": Stash(11, 728, 0), + "m03s22i227": Stash(11, 729, 0), + "m03s23i177": Stash(1, 620, 0), + "m03s23i178": Stash(1, 650, 0), + "m03s23i179": Stash(1, 675, 0), + "m03s23i225": Stash(3, 16, 0), + "m03s23i226": Stash(11, 728, 0), + "m03s23i227": Stash(11, 729, 0), + "m03s24i177": Stash(1, 620, 0), + "m03s24i178": Stash(1, 650, 0), + "m03s24i179": Stash(1, 675, 0), + "m03s24i225": Stash(3, 16, 0), + "m03s24i226": Stash(11, 728, 0), + "m03s24i227": Stash(11, 729, 0), + "m03s40i023": Stash(1, 93, 0), + "m03s40i024": Stash(1, 16, 0), + "m03s40i031": Stash(3, 37, 0), + "m03s40i032": Stash(3, 687, 0), + "m03s40i177": Stash(1, 620, 0), + "m03s40i178": Stash(1, 650, 0), + "m03s40i179": Stash(1, 675, 0), + "m03s40i201": Stash(1, 620, 0), + "m03s40i202": Stash(3, 620, 0), + "m03s40i203": Stash(3, 687, 0), + "m03s40i204": Stash(3, 683, 0), + "m03s40i205": Stash(3, 687, 0), + "m03s40i206": Stash(3, 687, 0), + "m03s40i207": Stash(3, 688, 0), + "m03s40i208": Stash(3, 683, 0), + "m03s40i209": Stash(3, 687, 0), + "m03s40i210": Stash(3, 688, 0), + "m03s40i211": Stash(3, 684, 0), + "m03s40i212": Stash(3, 689, 0), + "m03s40i213": Stash(3, 690, 0), + "m03s40i214": Stash(3, 188, 0), + "m03s40i215": Stash(3, 188, 0), + "m03s40i216": Stash(3, 14, 0), + "m03s40i217": Stash(3, 14, 0), + "m03s40i218": Stash(3, 910, 0), + "m03s40i219": Stash(3, 911, 0), + "m03s40i220": Stash(3, 685, 0), + "m03s40i221": Stash(3, 912, 0), + "m03s40i222": Stash(3, 108, 0), + "m03s40i223": Stash(3, 108, 0), + "m03s40i224": Stash(3, 687, 0), + "m03s40i225": Stash(3, 688, 0), + "m03s40i226": Stash(3, 15, 0), + "m03s40i230": Stash(3, 801, 0), + "m03s40i231": Stash(3, 801, 0), + "m03s40i232": Stash(19, 801, 0), + "m03s40i233": Stash(19, 801, 0), + "m03s40i234": Stash(19, 801, 0), + "m03s40i235": Stash(19, 801, 0), + "m03s40i240": Stash(1, 93, 10), + "m03s40i241": Stash(3, 37, 10), + "m03s40i242": Stash(3, 687, 10), + "m03s40i243": Stash(3, 687, 10), + "m03s40i244": Stash(3, 683, 10), + "m03s40i245": Stash(3, 687, 10), + "m03s40i246": Stash(3, 688, 10), + "m03s40i247": Stash(3, 683, 10), + "m03s40i248": Stash(3, 687, 10), + "m03s40i249": Stash(3, 688, 10), + "m03s40i250": Stash(3, 683, 0), + "m03s40i251": Stash(3, 687, 0), + "m03s40i252": Stash(3, 688, 0), + "m03s40i253": Stash(3, 683, 0), + "m03s40i254": Stash(3, 687, 0), + "m03s40i255": Stash(3, 688, 0), + "m04s00i001": Stash(0, 351, 0), + "m04s00i002": Stash(0, 38, 0), + "m04s00i003": Stash(0, 2, 0), + "m04s00i004": Stash(0, 56, 0), + "m04s00i005": Stash(0, 57, 0), + "m04s00i006": Stash(0, 61, 0), + "m04s00i007": Stash(0, 62, 0), + "m04s00i008": Stash(0, 37, 0), + "m04s00i009": Stash(0, 364, 0), + "m04s00i010": Stash(0, 365, 0), + "m04s01i001": Stash(0, 353, 0), + "m04s02i001": Stash(0, 367, 0), + "m04s02i002": Stash(0, 61, 0), + "m04s02i003": Stash(0, 62, 0), + "m04s02i004": Stash(0, 364, 0), + "m04s02i005": Stash(0, 365, 0), + "m04s02i006": Stash(0, 366, 0), + "m04s02i007": Stash(0, 354, 0), + "m04s03i001": Stash(0, 355, 0), + "m04s04i001": Stash(0, 356, 0), + "m04s05i001": Stash(0, 357, 0), + "m04s06i001": Stash(0, 387, 0), + "m04s06i002": Stash(0, 393, 0), + "m04s06i003": Stash(0, 394, 0), + "m04s06i004": Stash(0, 392, 0), + "m04s06i005": Stash(0, 385, 0), + "m04s06i006": Stash(0, 388, 0), + "m04s06i007": Stash(0, 389, 0), + "m04s06i008": Stash(0, 386, 0), + "m04s06i009": Stash(0, 390, 0), + "m04s06i010": Stash(0, 391, 0), + "m04s06i011": Stash(0, 398, 0), + "m04s06i012": Stash(0, 381, 0), + "m04s06i013": Stash(0, 382, 0), + "m04s06i014": Stash(0, 383, 0), + "m04s06i015": Stash(0, 399, 0), + "m04s06i016": Stash(0, 400, 0), + "m04s06i017": Stash(0, 50, 0), + "m04s06i018": Stash(0, 55, 0), + "m04s06i019": Stash(0, 395, 0), + "m04s06i020": Stash(0, 2, 0), + "m04s06i021": Stash(0, 366, 0), + "m04s06i022": Stash(0, 368, 0), + "m04s06i023": Stash(0, 369, 0), + "m04s06i024": Stash(0, 392, 0), + "m04s06i025": Stash(0, 352, 0), + "m04s06i026": Stash(0, 353, 0), + "m04s06i027": Stash(0, 354, 0), + "m04s06i028": Stash(0, 355, 0), + "m04s06i029": Stash(0, 356, 0), + "m04s06i030": Stash(0, 357, 0), + "m04s06i031": Stash(0, 358, 0), + "m04s06i032": Stash(0, 396, 0), + "m04s06i033": Stash(0, 397, 0), + "m04s06i034": Stash(0, 398, 0), + "m04s06i035": Stash(0, 401, 0), + "m04s07i001": Stash(0, 358, 0), + "m04s07i002": Stash(0, 359, 0), + "m04s07i003": Stash(0, 360, 0), } diff --git a/lib/iris/fileformats/_pp_lbproc_pairs.py b/lib/iris/fileformats/_pp_lbproc_pairs.py new file mode 100644 index 0000000000..28e35a8e86 --- /dev/null +++ b/lib/iris/fileformats/_pp_lbproc_pairs.py @@ -0,0 +1,48 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +import itertools + + +# LBPROC codes and their English equivalents +LBPROC_PAIRS = ((1, "Difference from another experiment"), + (2, "Difference from zonal (or other spatial) mean"), + (4, "Difference from time mean"), + (8, "X-derivative (d/dx)"), + (16, "Y-derivative (d/dy)"), + (32, "Time derivative (d/dt)"), + (64, "Zonal mean field"), + (128, "Time mean field"), + (256, "Product of two fields"), + (512, "Square root of a field"), + (1024, "Difference between fields at levels BLEV and BRLEV"), + (2048, "Mean over layer between levels BLEV and BRLEV"), + (4096, "Minimum value of field during time period"), + (8192, "Maximum value of field during time period"), + (16384, "Magnitude of a vector, not specifically wind speed"), + (32768, "Log10 of a field"), + (65536, "Variance of a field"), + (131072, "Mean over an ensemble of parallel runs")) + +# lbproc_map is dict mapping lbproc->English and English->lbproc +# essentially a one to one mapping +LBPROC_MAP = {x: y for x, y in + itertools.chain(LBPROC_PAIRS, ((y, x) for x, y in LBPROC_PAIRS))} diff --git a/lib/iris/fileformats/_pyke_rules/fc_rules_cf.krb b/lib/iris/fileformats/_pyke_rules/fc_rules_cf.krb index a3798072bf..5fc68e58c2 100644 --- a/lib/iris/fileformats/_pyke_rules/fc_rules_cf.krb +++ b/lib/iris/fileformats/_pyke_rules/fc_rules_cf.krb @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2012, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -40,7 +40,7 @@ fc_default # # Context: -# This rule will trigger iff a grid_mapping() case specific fact +# This rule will trigger iff a grid_mapping() case specific fact # has been asserted that refers to a rotated pole. # # Purpose: @@ -96,13 +96,113 @@ fc_provides_grid_mapping_transverse_mercator facts_cf.provides(coordinate_system, transverse_mercator) python engine.rule_triggered.add(rule.name) + +# +# Context: +# This rule will trigger iff a grid_mapping() case specific fact +# has been asserted that refers to a Mercator. +# +# Purpose: +# Creates the Mercator coordinate system. +# +fc_provides_grid_mapping_mercator + foreach + facts_cf.grid_mapping($grid_mapping) + check is_grid_mapping(engine, $grid_mapping, CF_GRID_MAPPING_MERCATOR) + check has_supported_mercator_parameters(engine, $grid_mapping) + assert + python cf_grid_var = engine.cf_var.cf_group.grid_mappings[$grid_mapping] + python coordinate_system = build_mercator_coordinate_system(engine, cf_grid_var) + python engine.provides['coordinate_system'] = coordinate_system + facts_cf.provides(coordinate_system, mercator) + python engine.rule_triggered.add(rule.name) + + +# +# Context: +# This rule will trigger iff a grid_mapping() case specific fact +# has been asserted that refers to a stereographic. +# +# Purpose: +# Creates the stereographic coordinate system. +# +fc_provides_grid_mapping_stereographic + foreach + facts_cf.grid_mapping($grid_mapping) + check is_grid_mapping(engine, $grid_mapping, CF_GRID_MAPPING_STEREO) + check has_supported_stereographic_parameters(engine, $grid_mapping) + assert + python cf_grid_var = engine.cf_var.cf_group.grid_mappings[$grid_mapping] + python coordinate_system = build_stereographic_coordinate_system(engine, cf_grid_var) + python engine.provides['coordinate_system'] = coordinate_system + facts_cf.provides(coordinate_system, stereographic) + python engine.rule_triggered.add(rule.name) + + +# +# Context: This rule will trigger iff a grid_mapping() case specific fact +# has been asserted that refers to a Lambert conformal. +# +# Purpose: +# Creates the Lambert conformal conic coordinate system. +# +fc_provides_grid_mapping_lambert_conformal + foreach + facts_cf.grid_mapping($grid_mapping) + check is_grid_mapping(engine, $grid_mapping, CF_GRID_MAPPING_LAMBERT_CONFORMAL) + assert + python cf_grid_var = engine.cf_var.cf_group.grid_mappings[$grid_mapping] + python coordinate_system = build_lambert_conformal_coordinate_system(engine, cf_grid_var) + python engine.provides['coordinate_system'] = coordinate_system + facts_cf.provides(coordinate_system, lambert_conformal) + python engine.rule_triggered.add(rule.name) + +# +# Context: +# This rule will trigger iff a grid_mapping() case specific fact +# has been asserted that refers to a lambert azimuthal equal area. +# +# Purpose: +# Creates the lambert azimuthal equal area coordinate system. +# +fc_provides_grid_mapping_lambert_azimuthal_equal_area + foreach + facts_cf.grid_mapping($grid_mapping) + check is_grid_mapping(engine, $grid_mapping, CF_GRID_MAPPING_LAMBERT_AZIMUTHAL) + assert + python cf_grid_var = engine.cf_var.cf_group.grid_mappings[$grid_mapping] + python coordinate_system = build_lambert_azimuthal_equal_area_coordinate_system(engine, cf_grid_var) + python engine.provides['coordinate_system'] = coordinate_system + facts_cf.provides(coordinate_system, lambert_azimuthal_equal_area) + python engine.rule_triggered.add(rule.name) + +# +# Context: +# This rule will trigger iff a grid_mapping() case specific fact +# has been asserted that refers to a albers conical equal area. +# +# Purpose: +# Creates the albers conical equal area coordinate system. +# +fc_provides_grid_mapping_albers_equal_area + foreach + facts_cf.grid_mapping($grid_mapping) + check is_grid_mapping(engine, $grid_mapping, CF_GRID_MAPPING_ALBERS) + assert + python cf_grid_var = engine.cf_var.cf_group.grid_mappings[$grid_mapping] + python coordinate_system = build_albers_equal_area_coordinate_system(engine, cf_grid_var) + python engine.provides['coordinate_system'] = coordinate_system + facts_cf.provides(coordinate_system, albers_equal_area) + python engine.rule_triggered.add(rule.name) + + # # Context: # This rule will trigger iff a coordinate() case specific fact -# has been asserted that refers to a CF latitude coordinate. +# has been asserted that refers to a CF latitude coordinate. # # Purpose: -# Assert that the CF latitude coordinate exists. +# Assert that the CF latitude coordinate exists. # fc_provides_coordinate_latitude foreach @@ -335,10 +435,10 @@ fc_build_auxiliary_coordinate_longitude_rotated # # Context: # This rule will trigger for each auxiliary_coordinate() case specific fact -# that is not a spatio-temporal related auxiliary coordinate. +# that is not a spatio-temporal related auxiliary coordinate. # # Purpose: -# Add the auxiliary coordinate to the cube. +# Add the auxiliary coordinate to the cube. # fc_build_auxiliary_coordinate foreach @@ -352,6 +452,21 @@ fc_build_auxiliary_coordinate python build_auxiliary_coordinate(engine, cf_coord_var) python engine.rule_triggered.add(rule.name) +# +# Context: +# This rule will trigger for each cell_measure case specific fact. +# +# Purpose: +# Add the cell measures attribute to the cube. +# +fc_build_cell_measure + foreach + facts_cf.cell_measure($coordinate) + assert + python cf_coord_var = engine.cf_var.cf_group.cell_measures[$coordinate] + python build_cell_measures(engine, cf_coord_var) + python engine.rule_triggered.add(rule.name) + # # Context: @@ -434,7 +549,7 @@ fc_build_coordinate_longitude_rotated python build_dimension_coordinate(engine, cf_coord_var, coord_name=CF_VALUE_STD_NAME_GRID_LON, coord_system=engine.provides['coordinate_system']) - python engine.rule_triggered.add(rule.name) + python engine.rule_triggered.add(rule.name) # @@ -482,7 +597,7 @@ fc_build_coordinate_longitude_nocs coord_system=None) python engine.rule_triggered.add(rule.name) - + # # Context: # This rule will trigger iff a projection_x_coordinate coordinate exists and @@ -522,6 +637,200 @@ fc_build_coordinate_projection_y_transverse_mercator coord_system=engine.provides['coordinate_system']) python engine.rule_triggered.add(rule.name) +# +# Context: +# This rule will trigger iff a projection_x_coordinate coordinate exists and +# a Lambert conformal coordinate system exists. +# +# Purpose: +# Add the projection_x_coordinate coordinate into the cube. +# +fc_build_coordinate_projection_x_lambert_conformal + foreach + facts_cf.provides(coordinate, projection_x_coordinate, $coordinate) + facts_cf.provides(coordinate_system, lambert_conformal) + assert + python cf_coord_var = engine.cf_var.cf_group.coordinates[$coordinate] + python build_dimension_coordinate(engine, cf_coord_var, + coord_name=CF_VALUE_STD_NAME_PROJ_X, + coord_system=engine.provides['coordinate_system']) + python engine.rule_triggered.add(rule.name) + + +# +# Context: +# This rule will trigger iff a projection_y_coordinate coordinate exists and +# a Lambert conformal coordinate system exists. +# +# Purpose: +# Add the projection_y_coordinate coordinate into the cube. +# +fc_build_coordinate_projection_y_lambert_conformal + foreach + facts_cf.provides(coordinate, projection_y_coordinate, $coordinate) + facts_cf.provides(coordinate_system, lambert_conformal) + assert + python cf_coord_var = engine.cf_var.cf_group.coordinates[$coordinate] + python build_dimension_coordinate(engine, cf_coord_var, + coord_name=CF_VALUE_STD_NAME_PROJ_Y, + coord_system=engine.provides['coordinate_system']) + python engine.rule_triggered.add(rule.name) + + +# +# Context: +# This rule will trigger iff a projection_x_coordinate coordinate exists and +# a Mercator coordinate system exists. +# +# Purpose: +# Add the projection_x_coordinate coordinate into the cube. +# +fc_build_coordinate_projection_x_mercator + foreach + facts_cf.provides(coordinate, projection_x_coordinate, $coordinate) + facts_cf.provides(coordinate_system, mercator) + assert + python cf_coord_var = engine.cf_var.cf_group.coordinates[$coordinate] + python build_dimension_coordinate(engine, cf_coord_var, + coord_name=CF_VALUE_STD_NAME_PROJ_X, + coord_system=engine.provides['coordinate_system']) + python engine.rule_triggered.add(rule.name) + +# +# Context: +# This rule will trigger iff a projection_y_coordinate coordinate exists and +# a Mercator coordinate system exists. +# +# Purpose: +# Add the projection_y_coordinate coordinate into the cube. +# +fc_build_coordinate_projection_y_mercator + foreach + facts_cf.provides(coordinate, projection_y_coordinate, $coordinate) + facts_cf.provides(coordinate_system, mercator) + assert + python cf_coord_var = engine.cf_var.cf_group.coordinates[$coordinate] + python build_dimension_coordinate(engine, cf_coord_var, + coord_name=CF_VALUE_STD_NAME_PROJ_Y, + coord_system=engine.provides['coordinate_system']) + python engine.rule_triggered.add(rule.name) + +# +# Context: +# This rule will trigger iff a projection_x_coordinate coordinate exists and +# a sterographic coordinate system exists. +# +# Purpose: +# Add the projection_x_coordinate coordinate into the cube. +# +fc_build_coordinate_projection_x_stereographic + foreach + facts_cf.provides(coordinate, projection_x_coordinate, $coordinate) + facts_cf.provides(coordinate_system, stereographic) + assert + python cf_coord_var = engine.cf_var.cf_group.coordinates[$coordinate] + python build_dimension_coordinate(engine, cf_coord_var, + coord_name=CF_VALUE_STD_NAME_PROJ_X, + coord_system=engine.provides['coordinate_system']) + python engine.rule_triggered.add(rule.name) + +# +# Context: +# This rule will trigger iff a projection_y_coordinate coordinate exists and +# a stereographic coordinate system exists. +# +# Purpose: +# Add the projection_y_coordinate coordinate into the cube. +# +fc_build_coordinate_projection_y_stereographic + foreach + facts_cf.provides(coordinate, projection_y_coordinate, $coordinate) + facts_cf.provides(coordinate_system, stereographic) + assert + python cf_coord_var = engine.cf_var.cf_group.coordinates[$coordinate] + python build_dimension_coordinate(engine, cf_coord_var, + coord_name=CF_VALUE_STD_NAME_PROJ_Y, + coord_system=engine.provides['coordinate_system']) + python engine.rule_triggered.add(rule.name) + + +# +# Context: +# This rule will trigger iff a projection_x_coordinate coordinate exists and +# a lambert azimuthal equal area coordinate system exists. +# +# Purpose: +# Add the projection_x_coordinate coordinate into the cube. +# +fc_build_coordinate_projection_x_lambert_azimuthal_equal_area + foreach + facts_cf.provides(coordinate, projection_x_coordinate, $coordinate) + facts_cf.provides(coordinate_system, lambert_azimuthal_equal_area) + assert + python cf_coord_var = engine.cf_var.cf_group.coordinates[$coordinate] + python build_dimension_coordinate(engine, cf_coord_var, + coord_name=CF_VALUE_STD_NAME_PROJ_X, + coord_system=engine.provides['coordinate_system']) + python engine.rule_triggered.add(rule.name) + + +# +# Context: +# This rule will trigger iff a projection_y_coordinate coordinate exists and +# a lambert azimuthal equal area coordinate system exists. +# +# Purpose: +# Add the projection_y_coordinate coordinate into the cube. +# +fc_build_coordinate_projection_y_lambert_azimuthal_equal_area + foreach + facts_cf.provides(coordinate, projection_y_coordinate, $coordinate) + facts_cf.provides(coordinate_system, lambert_azimuthal_equal_area) + assert + python cf_coord_var = engine.cf_var.cf_group.coordinates[$coordinate] + python build_dimension_coordinate(engine, cf_coord_var, + coord_name=CF_VALUE_STD_NAME_PROJ_Y, + coord_system=engine.provides['coordinate_system']) + python engine.rule_triggered.add(rule.name) + +# +# Context: +# This rule will trigger iff a projection_x_coordinate coordinate exists and +# a albers conical equal area coordinate system exists. +# +# Purpose: +# Add the projection_x_coordinate coordinate into the cube. +# +fc_build_coordinate_projection_x_albers_equal_area + foreach + facts_cf.provides(coordinate, projection_x_coordinate, $coordinate) + facts_cf.provides(coordinate_system, albers_equal_area) + assert + python cf_coord_var = engine.cf_var.cf_group.coordinates[$coordinate] + python build_dimension_coordinate(engine, cf_coord_var, + coord_name=CF_VALUE_STD_NAME_PROJ_X, + coord_system=engine.provides['coordinate_system']) + python engine.rule_triggered.add(rule.name) + + +# +# Context: +# This rule will trigger iff a projection_y_coordinate coordinate exists and +# a albers conical equal area coordinate system exists. +# +# Purpose: +# Add the projection_y_coordinate coordinate into the cube. +# +fc_build_coordinate_projection_y_albers_equal_area + foreach + facts_cf.provides(coordinate, projection_y_coordinate, $coordinate) + facts_cf.provides(coordinate_system, albers_equal_area) + assert + python cf_coord_var = engine.cf_var.cf_group.coordinates[$coordinate] + python build_dimension_coordinate(engine, cf_coord_var, + coord_name=CF_VALUE_STD_NAME_PROJ_Y, + coord_system=engine.provides['coordinate_system']) + python engine.rule_triggered.add(rule.name) # # Context: @@ -577,19 +886,19 @@ fc_default_coordinate # # Context: -# This rule will trigger iff the "ukmo__um_stash_source" attribute exists +# This rule will trigger iff the "um_stash_source" or "ukmo__um_stash_source" attributes exist # on the CF-netCDF data variable. # # Purpose: -# Add the CF-netCDF data variable "ukmo__um_stash_source" attribute to the +# Add the CF-netCDF data variable "um_stash_source" attribute to the # cube attributes dictionary as a "STASH" key. # fc_attribute_ukmo__um_stash_source foreach - check hasattr(engine.cf_var, 'ukmo__um_stash_source') + check hasattr(engine.cf_var, 'ukmo__um_stash_source') or hasattr(engine.cf_var, 'um_stash_source') assert - python attr_value = engine.cf_var.ukmo__um_stash_source - python engine.cube.attributes['STASH'] = pp.STASH.from_msi(engine.cf_var.ukmo__um_stash_source) + python attr_value = getattr(engine.cf_var, 'um_stash_source', None) or getattr(engine.cf_var, 'ukmo__um_stash_source') + python engine.cube.attributes['STASH'] = pp.STASH.from_msi(attr_value) python engine.rule_triggered.add(rule.name) # @@ -608,8 +917,8 @@ fc_attribute_ukmo__process_flags python attr_value = engine.cf_var.ukmo__process_flags python engine.cube.attributes['ukmo__process_flags'] = tuple([x.replace("_", " ") for x in attr_value.split(" ")]) python engine.rule_triggered.add(rule.name) - - + + # # Context: # This rule will trigger iff a formula term that refers to a @@ -627,6 +936,107 @@ fc_formula_type_atmosphere_hybrid_height_coordinate facts_cf.formula_type(atmosphere_hybrid_height_coordinate) python engine.rule_triggered.add(rule.name) +# +# Context: +# This rule will trigger iff a formula term that refers to a +# dimensionless vertical coordinate of hybrid pressure. +# +# Purpose: +# Assert that the formula term refers to hybrid pressure. +# +fc_formula_type_atmosphere_hybrid_sigma_pressure_coordinate + foreach + facts_cf.formula_root($coordinate) + check getattr(engine.cf_var.cf_group[$coordinate], 'standard_name') == 'atmosphere_hybrid_sigma_pressure_coordinate' + assert + python engine.requires['formula_type'] = 'atmosphere_hybrid_sigma_pressure_coordinate' + facts_cf.formula_type(atmosphere_hybrid_height_coordinate) + python engine.rule_triggered.add(rule.name) + +# +# Context: +# This rule will trigger iff a formula term that refers to a +# dimensionless vertical coordinate of ocean sigma over z +# +# Purpose: +# Assert that the formula term refers to ocean sigma over z. +# +fc_formula_type_ocean_sigma_z_coordinate + foreach + facts_cf.formula_root($coordinate) + check getattr(engine.cf_var.cf_group[$coordinate], 'standard_name') == 'ocean_sigma_z_coordinate' + assert + python engine.requires['formula_type'] = 'ocean_sigma_z_coordinate' + facts_cf.formula_type(ocean_sigma_z_coordinate) + python engine.rule_triggered.add(rule.name) + +# +# Context: +# This rule will trigger if a formula term that refers to a +# dimensionless vertical coordinate of ocean sigma +# +# Purpose: +# Assert that the formula term refers to ocean sigma +# +fc_formula_type_ocean_sigma_coordinate + foreach + facts_cf.formula_root($coordinate) + check getattr(engine.cf_var.cf_group[$coordinate], 'standard_name') == 'ocean_sigma_coordinate' + assert + python engine.requires['formula_type'] = 'ocean_sigma_coordinate' + facts_cf.formula_type(ocean_sigma_coordinate) + python engine.rule_triggered.add(rule.name) + +# +# Context: +# This rule will trigger if a formula term that refers to a +# dimensionless vertical coordinate of ocean s coordinate +# +# Purpose: +# Assert that the formula term refers to ocean sigma +# +fc_formula_type_ocean_s_coordinate + foreach + facts_cf.formula_root($coordinate) + check getattr(engine.cf_var.cf_group[$coordinate], 'standard_name') == 'ocean_s_coordinate' + assert + python engine.requires['formula_type'] = 'ocean_s_coordinate' + facts_cf.formula_type(ocean_s_coordinate) + python engine.rule_triggered.add(rule.name) + +# +# Context: +# This rule will trigger if a formula term that refers to a +# dimensionless vertical coordinate of Ocean s-coordinate g1 +# +# Purpose: +# Assert that the formula term refers to Ocean s-coordinate g1 +# +fc_formula_type_ocean_s_coordinate_g1 + foreach + facts_cf.formula_root($coordinate) + check getattr(engine.cf_var.cf_group[$coordinate], 'standard_name') == 'ocean_s_coordinate_g1' + assert + python engine.requires['formula_type'] = 'ocean_s_coordinate_g1' + facts_cf.formula_type(ocean_s_coordinate_g1) + python engine.rule_triggered.add(rule.name) + +# +# Context: +# This rule will trigger if a formula term that refers to a +# dimensionless vertical coordinate of Ocean s-coordinate g2 +# +# Purpose: +# Assert that the formula term refers to Ocean s-coordinate g2 +# +fc_formula_type_ocean_s_coordinate_g2 + foreach + facts_cf.formula_root($coordinate) + check getattr(engine.cf_var.cf_group[$coordinate], 'standard_name') == 'ocean_s_coordinate_g2' + assert + python engine.requires['formula_type'] = 'ocean_s_coordinate_g2' + facts_cf.formula_type(ocean_s_coordinate_g2) + python engine.rule_triggered.add(rule.name) # # Context: @@ -646,9 +1056,11 @@ fc_formula_terms fc_extras - import re + import six + import warnings + import cf_units import netCDF4 import numpy as np import numpy.ma as ma @@ -657,12 +1069,15 @@ fc_extras import iris.coords import iris.coord_systems import iris.fileformats.cf as cf + import iris.fileformats.netcdf + from iris.fileformats.netcdf import _get_cf_var_data, parse_cell_methods, UnknownCellMethodWarning import iris.fileformats.pp as pp import iris.exceptions import iris.std_names - import iris.unit - - + import iris.util + from iris._lazy_data import as_lazy_data + + # # UD Units Constants (based on Unidata udunits.dat definition file) # @@ -672,7 +1087,7 @@ fc_extras UD_UNITS_LON = ['degrees_east', 'degree_east', 'degree_e', 'degrees_e', 'degreee', 'degreese', 'degrees', 'degrees east', 'degree east', 'degree e', 'degrees e'] - + # # CF Dimensionless Vertical Coordinates # @@ -684,8 +1099,10 @@ fc_extras 'ocean_sigma_coordinate':['sigma', 'eta', 'depth'], 'ocean_s_coordinate':['s', 'eta', 'depth', 'a', 'b', 'depth_c'], 'ocean_sigma_z_coordinate':['sigma', 'eta', 'depth', 'depth_c', 'nsigma', 'zlev'], - 'ocean_double_sigma_coordinate':['sigma', 'depth', 'z1', 'z2', 'a', 'href', 'k_c']} - + 'ocean_double_sigma_coordinate':['sigma', 'depth', 'z1', 'z2', 'a', 'href', 'k_c'], + 'ocean_s_coordinate_g1':['s', 'eta', 'depth', 'depth_c', 'C'], + 'ocean_s_coordinate_g2':['s', 'eta', 'depth', 'depth_c', 'C']} + # # CF Grid Mappings # @@ -702,7 +1119,7 @@ fc_extras CF_GRID_MAPPING_STEREO = 'stereographic' CF_GRID_MAPPING_TRANSVERSE = 'transverse_mercator' CF_GRID_MAPPING_VERTICAL = 'vertical_perspective' - + # # CF Attribute Names. # @@ -720,17 +1137,19 @@ fc_extras CF_ATTR_GRID_SEMI_MINOR_AXIS = 'semi_minor_axis' CF_ATTR_GRID_LAT_OF_PROJ_ORIGIN = 'latitude_of_projection_origin' CF_ATTR_GRID_LON_OF_PROJ_ORIGIN = 'longitude_of_projection_origin' + CF_ATTR_GRID_STANDARD_PARALLEL = 'standard_parallel' CF_ATTR_GRID_FALSE_EASTING = 'false_easting' CF_ATTR_GRID_FALSE_NORTHING = 'false_northing' CF_ATTR_GRID_SCALE_FACTOR_AT_PROJ_ORIGIN = 'scale_factor_at_projection_origin' CF_ATTR_GRID_SCALE_FACTOR_AT_CENT_MERIDIAN = 'scale_factor_at_central_meridian' CF_ATTR_GRID_LON_OF_CENT_MERIDIAN = 'longitude_of_central_meridian' + CF_ATTR_GRID_STANDARD_PARALLEL = 'standard_parallel' CF_ATTR_POSITIVE = 'positive' CF_ATTR_STD_NAME = 'standard_name' CF_ATTR_LONG_NAME = 'long_name' CF_ATTR_UNITS = 'units' CF_ATTR_CELL_METHODS = 'cell_methods' - + # # CF Attribute Value Constants. # @@ -739,11 +1158,11 @@ fc_extras CF_VALUE_AXIS_Y = 'y' CF_VALUE_AXIS_T = 't' CF_VALUE_AXIS_Z = 'z' - - + + # Attribute - positive. CF_VALUE_POSITIVE = ['down', 'up'] - + # Attribute - standard_name. CF_VALUE_STD_NAME_LAT = 'latitude' CF_VALUE_STD_NAME_LON = 'longitude' @@ -751,26 +1170,6 @@ fc_extras CF_VALUE_STD_NAME_GRID_LON = 'grid_longitude' CF_VALUE_STD_NAME_PROJ_X = 'projection_x_coordinate' CF_VALUE_STD_NAME_PROJ_Y = 'projection_y_coordinate' - - # Cell methods. - CM_KNOWN_METHODS = ['point', 'sum', 'mean', 'maximum', 'minimum', 'mid_range', - 'standard_deviation', 'variance', 'mode', 'median'] - - CM_COMMENT = 'comment' - CM_EXTRA = 'extra' - CM_INTERVAL = 'interval' - CM_METHOD = 'method' - CM_NAME = 'name' - - CM_PARSE = re.compile( r''' - (?P([\w_]+:\s+)+) - (?P[\w_]+)\s* - (?: - \(\s* - (?P[^\)]+) - \)\s* - )? - ''', re.VERBOSE) ################################################################################ @@ -801,17 +1200,32 @@ fc_extras # Incorporate cell methods nc_att_cell_methods = getattr(cf_var, CF_ATTR_CELL_METHODS, None) - cube.cell_methods = _parse_cell_methods(cf_var.cf_name, nc_att_cell_methods) - - # Set the cube global attributes. - for attr_name, attr_value in cf_var.cf_group.global_attributes.iteritems(): - if isinstance(attr_value, unicode): - try: - cube.attributes[str(attr_name)] = str(attr_value) - except UnicodeEncodeError: + with warnings.catch_warnings(record=True) as warning_records: + cube.cell_methods = parse_cell_methods(nc_att_cell_methods) + # Filter to get the warning we are interested in. + warning_records = [record for record in warning_records + if issubclass(record.category, UnknownCellMethodWarning)] + if len(warning_records) > 0: + # Output an enhanced warning message. + warn_record = warning_records[0] + name = '{}'.format(cf_var.cf_name) + msg = warn_record.message.args[0] + msg = msg.replace('variable', 'variable {!r}'.format(name)) + warnings.warn(message=msg, category=UnknownCellMethodWarning) + + # Set the cube global attributes. + for attr_name, attr_value in six.iteritems(cf_var.cf_group.global_attributes): + try: + if six.PY2 and isinstance(attr_value, six.text_type): + try: + cube.attributes[str(attr_name)] = str(attr_value) + except UnicodeEncodeError: + cube.attributes[str(attr_name)] = attr_value + else: cube.attributes[str(attr_name)] = attr_value - else: - cube.attributes[str(attr_name)] = attr_value + except ValueError as e: + msg = 'Skipping global attribute {!r}: {}' + warnings.warn(msg.format(attr_name, str(e))) @@ -828,7 +1242,7 @@ fc_extras # Check for a default spherical earth. if major is None and minor is None and inverse_flattening is None: - major = getattr(cf_grid_var, CF_ATTR_GRID_EARTH_RADIUS, None) + major = getattr(cf_grid_var, CF_ATTR_GRID_EARTH_RADIUS, None) return major, minor, inverse_flattening @@ -905,10 +1319,169 @@ fc_extras return cs + ################################################################################ + def build_lambert_conformal_coordinate_system(engine, cf_grid_var): + """ + Create a Lambert conformal conic coordinate system from the CF-netCDF + grid mapping variable. + + """ + major, minor, inverse_flattening = _get_ellipsoid(cf_grid_var) + + latitude_of_projection_origin = getattr( + cf_grid_var, CF_ATTR_GRID_LAT_OF_PROJ_ORIGIN, None) + longitude_of_central_meridian = getattr( + cf_grid_var, CF_ATTR_GRID_LON_OF_CENT_MERIDIAN, None) + false_easting = getattr( + cf_grid_var, CF_ATTR_GRID_FALSE_EASTING, None) + false_northing = getattr( + cf_grid_var, CF_ATTR_GRID_FALSE_NORTHING, None) + standard_parallel = getattr( + cf_grid_var, CF_ATTR_GRID_STANDARD_PARALLEL, None) + + ellipsoid = None + if major is not None or minor is not None or \ + inverse_flattening is not None: + ellipsoid = iris.coord_systems.GeogCS(major, minor, + inverse_flattening) + + cs = iris.coord_systems.LambertConformal( + latitude_of_projection_origin, longitude_of_central_meridian, + false_easting, false_northing, standard_parallel, + ellipsoid) + + return cs + + ################################################################################ + def build_stereographic_coordinate_system(engine, cf_grid_var): + """ + Create a stereographic coordinate system from the CF-netCDF + grid mapping variable. + + """ + major, minor, inverse_flattening = _get_ellipsoid(cf_grid_var) + + latitude_of_projection_origin = getattr( + cf_grid_var, CF_ATTR_GRID_LAT_OF_PROJ_ORIGIN, None) + longitude_of_projection_origin = getattr( + cf_grid_var, CF_ATTR_GRID_LON_OF_PROJ_ORIGIN, None) + false_easting = getattr( + cf_grid_var, CF_ATTR_GRID_FALSE_EASTING, None) + false_northing = getattr( + cf_grid_var, CF_ATTR_GRID_FALSE_NORTHING, None) + # Iris currently only supports Stereographic projections with a scale + # factor of 1.0. This is checked elsewhere. + + ellipsoid = None + if major is not None or minor is not None or \ + inverse_flattening is not None: + ellipsoid = iris.coord_systems.GeogCS(major, minor, + inverse_flattening) + + cs = iris.coord_systems.Stereographic( + latitude_of_projection_origin, longitude_of_projection_origin, + false_easting, false_northing, + true_scale_lat=None, + ellipsoid=ellipsoid) + + return cs + + ################################################################################ + def build_mercator_coordinate_system(engine, cf_grid_var): + """ + Create a Mercator coordinate system from the CF-netCDF + grid mapping variable. + + """ + major, minor, inverse_flattening = _get_ellipsoid(cf_grid_var) + + longitude_of_projection_origin = getattr( + cf_grid_var, CF_ATTR_GRID_LON_OF_PROJ_ORIGIN, None) + # Iris currently only supports Mercator projections with specific + # values for false_easting, false_northing, + # scale_factor_at_projection_origin and standard_parallel. These are + # checked elsewhere. + + ellipsoid = None + if major is not None or minor is not None or \ + inverse_flattening is not None: + ellipsoid = iris.coord_systems.GeogCS(major, minor, + inverse_flattening) + + cs = iris.coord_systems.Mercator( + longitude_of_projection_origin, + ellipsoid=ellipsoid) + + return cs + + + ################################################################################ + def build_lambert_azimuthal_equal_area_coordinate_system(engine, cf_grid_var): + """ + Create a lambert azimuthal equal area coordinate system from the CF-netCDF + grid mapping variable. + + """ + major, minor, inverse_flattening = _get_ellipsoid(cf_grid_var) + + latitude_of_projection_origin = getattr( + cf_grid_var, CF_ATTR_GRID_LAT_OF_PROJ_ORIGIN, None) + longitude_of_projection_origin = getattr( + cf_grid_var, CF_ATTR_GRID_LON_OF_PROJ_ORIGIN, None) + false_easting = getattr( + cf_grid_var, CF_ATTR_GRID_FALSE_EASTING, None) + false_northing = getattr( + cf_grid_var, CF_ATTR_GRID_FALSE_NORTHING, None) + + ellipsoid = None + if major is not None or minor is not None or \ + inverse_flattening is not None: + ellipsoid = iris.coord_systems.GeogCS(major, minor, + inverse_flattening) + + cs = iris.coord_systems.LambertAzimuthalEqualArea( + latitude_of_projection_origin, longitude_of_projection_origin, + false_easting, false_northing, ellipsoid) + + return cs + + ################################################################################ + def build_albers_equal_area_coordinate_system(engine, cf_grid_var): + """ + Create a albers conical equal area coordinate system from the CF-netCDF + grid mapping variable. + + """ + major, minor, inverse_flattening = _get_ellipsoid(cf_grid_var) + + latitude_of_projection_origin = getattr( + cf_grid_var, CF_ATTR_GRID_LAT_OF_PROJ_ORIGIN, None) + longitude_of_central_meridian = getattr( + cf_grid_var, CF_ATTR_GRID_LON_OF_CENT_MERIDIAN, None) + false_easting = getattr( + cf_grid_var, CF_ATTR_GRID_FALSE_EASTING, None) + false_northing = getattr( + cf_grid_var, CF_ATTR_GRID_FALSE_NORTHING, None) + standard_parallels = getattr( + cf_grid_var, CF_ATTR_GRID_STANDARD_PARALLEL, None) + + ellipsoid = None + if major is not None or minor is not None or \ + inverse_flattening is not None: + ellipsoid = iris.coord_systems.GeogCS(major, minor, + inverse_flattening) + + cs = iris.coord_systems.AlbersEqualArea( + latitude_of_projection_origin, longitude_of_central_meridian, + false_easting, false_northing, standard_parallels, ellipsoid) + + return cs ################################################################################ def get_attr_units(cf_var, attributes): - attr_units = getattr(cf_var, CF_ATTR_UNITS, iris.unit._UNKNOWN_UNIT_STRING) + attr_units = getattr(cf_var, CF_ATTR_UNITS, cf_units._UNIT_DIMENSIONLESS) + if not attr_units: + attr_units = '1' # Sanitise lat/lon units. if attr_units in UD_UNITS_LAT or attr_units in UD_UNITS_LON: @@ -916,24 +1489,27 @@ fc_extras # Graceful loading of invalid units. try: - iris.unit.as_unit(attr_units) + cf_units.as_unit(attr_units) except ValueError: - msg = 'Ignoring netCDF variable {!r} invalid units {!r}' - msg_name = '{}'.format(cf_var.cf_name) - msg_units = '{}'.format(attr_units) - warnings.warn(msg.format(msg_name, msg_units)) + # Using converted unicode message. Can be reverted with Python 3. + msg = u'Ignoring netCDF variable {!r} invalid units {!r}'.format( + cf_var.cf_name, attr_units) + if six.PY3: + warnings.warn(msg) + else: + warnings.warn(msg.encode('ascii', errors='backslashreplace')) attributes['invalid_units'] = attr_units - attr_units = iris.unit._UNKNOWN_UNIT_STRING + attr_units = cf_units._UNKNOWN_UNIT_STRING - if np.issubdtype(cf_var.dtype, np.str): - attr_units = iris.unit._NO_UNIT_STRING + if np.issubdtype(cf_var.dtype, np.str_): + attr_units = cf_units._NO_UNIT_STRING # Get any assoicated calendar for a time reference coordinate. - if iris.unit.as_unit(attr_units).is_time_reference(): + if cf_units.as_unit(attr_units).is_time_reference(): attr_calendar = getattr(cf_var, CF_ATTR_CALENDAR, None) if attr_calendar: - attr_units = iris.unit.Unit(attr_units, calendar=attr_calendar) + attr_units = cf_units.Unit(attr_units, calendar=attr_calendar) return attr_units @@ -1005,6 +1581,35 @@ fc_extras return cf_bounds_var + ################################################################################ + def reorder_bounds_data(bounds_data, cf_bounds_var, cf_coord_var): + """ + Return a bounds_data array with the vertex dimension as the most + rapidly varying. + + .. note:: + + This function assumes the dimension names of the coordinate + variable match those of the bounds variable in order to determine + which is the vertex dimension. + + + """ + vertex_dim_names = set(cf_bounds_var.dimensions).difference( + cf_coord_var.dimensions) + if len(vertex_dim_names) != 1: + msg = 'Too many dimension names differ between coordinate ' \ + 'variable {!r} and the bounds variable {!r}. ' \ + 'Expected 1, got {}.' + raise ValueError(msg.format(str(cf_coord_var.cf_name), + str(cf_bounds_var.cf_name), + len(vertex_dim_names))) + vertex_dim = cf_bounds_var.dimensions.index(*vertex_dim_names) + bounds_data = np.rollaxis(bounds_data.view(), vertex_dim, + len(bounds_data.shape)) + return bounds_data + + ################################################################################ def build_dimension_coordinate(engine, cf_coord_var, coord_name=None, coord_system=None): """Create a dimension coordinate (DimCoord) and add it to the cube.""" @@ -1016,7 +1621,7 @@ fc_extras attr_units = get_attr_units(cf_coord_var, attributes) points_data = cf_coord_var[:] # Gracefully fill points masked array. - if ma.isMaskedArray(points_data): + if ma.is_masked(points_data): points_data = ma.filled(points_data) msg = 'Gracefully filling {!r} dimension coordinate masked points' warnings.warn(msg.format(str(cf_coord_var.cf_name))) @@ -1026,47 +1631,30 @@ fc_extras if cf_bounds_var is not None: bounds_data = cf_bounds_var[:] # Gracefully fill bounds masked array. - if ma.isMaskedArray(bounds_data): + if ma.is_masked(bounds_data): bounds_data = ma.filled(bounds_data) msg = 'Gracefully filling {!r} dimension coordinate masked bounds' warnings.warn(msg.format(str(cf_coord_var.cf_name))) + # Handle transposed bounds where the vertex dimension is not + # the last one. Test based on shape to support different + # dimension names. + if cf_bounds_var.shape[:-1] != cf_coord_var.shape: + bounds_data = reorder_bounds_data(bounds_data, cf_bounds_var, + cf_coord_var) else: bounds_data = None # Determine whether the coordinate is circular. circular = False - if points_data.ndim == 1 and coord_name in [CF_VALUE_STD_NAME_LON, CF_VALUE_STD_NAME_GRID_LON]: - diff = list(set(np.diff(points_data))) - diff_approx_equal = True - if len(points_data) > 1: - try: - for value in diff[1:]: - np.testing.assert_approx_equal(diff[0], value, significant=4) - diff = max(diff) - except AssertionError: - diff_approx_equal = False - - if diff_approx_equal and iris.unit.Unit(attr_units) in [iris.unit.Unit('radians'), iris.unit.Unit('degrees')]: - modulus_value = iris.unit.Unit(attr_units).modulus - - if len(points_data) > 1: - circular_value = (points_data[-1] + diff) % modulus_value - try: - np.testing.assert_approx_equal(points_data[0], circular_value, significant=4) - circular = True - except AssertionError: - if points_data[0] == 0: - try: - np.testing.assert_approx_equal(modulus_value, circular_value, significant=4) - circular = True - except AssertionError: - pass - else: - circular = points_data[0] >= modulus_value + if points_data.ndim == 1 and coord_name in [CF_VALUE_STD_NAME_LON, CF_VALUE_STD_NAME_GRID_LON] \ + and cf_units.Unit(attr_units) in [cf_units.Unit('radians'), cf_units.Unit('degrees')]: + modulus_value = cf_units.Unit(attr_units).modulus + circular = iris.util._is_circular(points_data, modulus_value, bounds=bounds_data) # Determine the name of the dimension/s shared between the CF-netCDF data variable # and the coordinate being built. - common_dims = filter(lambda dim: dim in cf_var.dimensions, cf_coord_var.dimensions) + common_dims = [dim for dim in cf_coord_var.dimensions + if dim in cf_var.dimensions] data_dims = None if common_dims: # Calculate the offset of each common dimension. @@ -1091,6 +1679,7 @@ fc_extras coord = iris.coords.AuxCoord(points_data, standard_name=standard_name, long_name=long_name, + var_name=var_name, units=attr_units, bounds=bounds_data, attributes=attributes, @@ -1107,19 +1696,11 @@ fc_extras else: # Scalar coords are placed in the aux_coords container. cube.add_aux_coord(coord, data_dims) - + # Update the coordinate to CF-netCDF variable mapping. engine.provides['coordinates'].append((coord, cf_coord_var.cf_name)) - ################################################################################ - def deferred_load(filename, nc_var_name): - dataset = netCDF4.Dataset(filename) - nc_var = dataset.variables[nc_var_name] - values = nc_var[:] - return values - - ################################################################################ def build_auxiliary_coordinate(engine, cf_coord_var, coord_name=None, coord_system=None): """Create an auxiliary coordinate (AuxCoord) and add it to the cube.""" @@ -1135,29 +1716,30 @@ fc_extras if isinstance(cf_coord_var, cf.CFLabelVariable): points_data = cf_coord_var.cf_label_data(cf_var) else: - # Use a closure to capture the current file/variable names. - filename = engine.filename - nc_var_name = cf_coord_var.cf_name - get_values = lambda: deferred_load(filename, nc_var_name) - points_data = iris.aux_factory.LazyArray(cf_coord_var.shape, - get_values) + points_data = _get_cf_var_data(cf_coord_var, engine.filename) # Get any coordinate bounds. cf_bounds_var = get_cf_bounds_var(cf_coord_var) if cf_bounds_var is not None: - # Use a closure to capture the current file/variable names. - filename = engine.filename - nc_bounds_var_name = cf_bounds_var.cf_name - get_values = lambda: deferred_load(filename, nc_bounds_var_name) - bounds_data = iris.aux_factory.LazyArray(cf_bounds_var.shape, - get_values) + bounds_data = _get_cf_var_data(cf_bounds_var, engine.filename) + + # Handle transposed bounds where the vertex dimension is not + # the last one. Test based on shape to support different + # dimension names. + if cf_bounds_var.shape[:-1] != cf_coord_var.shape: + # Resolving the data to a numpy array (i.e. *not* masked) for + # compatibility with array creators (i.e. dask) + bounds_data = np.asarray(bounds_data) + bounds_data = reorder_bounds_data(bounds_data, cf_bounds_var, + cf_coord_var) else: bounds_data = None # Determine the name of the dimension/s shared between the CF-netCDF data variable # and the coordinate being built. - common_dims = filter(lambda dim: dim in cf_var.dimensions, cf_coord_var.dimensions) - data_dims = None + common_dims = [dim for dim in cf_coord_var.dimensions + if dim in cf_var.dimensions] + data_dims = None if common_dims: # Calculate the offset of each common dimension. data_dims = [cf_var.dimensions.index(dim) for dim in common_dims] @@ -1182,14 +1764,55 @@ fc_extras engine.provides['coordinates'].append((coord, cf_coord_var.cf_name)) + ################################################################################ + def build_cell_measures(engine, cf_cm_attr, coord_name=None): + """Create a CellMeasure instance and add it to the cube.""" + cf_var = engine.cf_var + cube = engine.cube + attributes = {} + + # Get units + attr_units = get_attr_units(cf_cm_attr, attributes) + + data = _get_cf_var_data(cf_cm_attr, engine.filename) + + # Determine the name of the dimension/s shared between the CF-netCDF data variable + # and the coordinate being built. + common_dims = [dim for dim in cf_cm_attr.dimensions + if dim in cf_var.dimensions] + data_dims = None + if common_dims: + # Calculate the offset of each common dimension. + data_dims = [cf_var.dimensions.index(dim) for dim in common_dims] + + # Determine the standard_name, long_name and var_name + standard_name, long_name, var_name = get_names(cf_cm_attr, coord_name, attributes) + + # Obtain the cf_measure. + measure = cf_cm_attr.cf_measure + + # Create the CellMeasure + cell_measure = iris.coords.CellMeasure(data, + standard_name=standard_name, + long_name=long_name, + var_name=var_name, + units=attr_units, + attributes=attributes, + measure=measure) + + # Add it to the cube + cube.add_cell_measure(cell_measure, data_dims) + + + ################################################################################ def _is_lat_lon(cf_var, ud_units, std_name, std_name_grid, axis_name, prefixes): """ Determine whether the CF coordinate variable is a latitude/longitude variable. - + Ref: [CF] Section 4.1 Latitude Coordinate. [CF] Section 4.2 Longitude Coordinate. - + """ is_valid = False attr_units = getattr(cf_var, CF_ATTR_UNITS, None) @@ -1231,7 +1854,7 @@ fc_extras def is_latitude(engine, cf_name): """Determine whether the CF coordinate variable is a latitude variable.""" cf_var = engine.cf_var.cf_group[cf_name] - return _is_lat_lon(cf_var, UD_UNITS_LAT, CF_VALUE_STD_NAME_LAT, + return _is_lat_lon(cf_var, UD_UNITS_LAT, CF_VALUE_STD_NAME_LAT, CF_VALUE_STD_NAME_GRID_LAT, CF_VALUE_AXIS_Y, ['lat', 'rlat']) @@ -1284,10 +1907,10 @@ fc_extras attr_std_name = getattr(cf_var, CF_ATTR_STD_NAME, None) attr_axis = getattr(cf_var, CF_ATTR_AXIS, '') try: - is_time_reference = iris.unit.Unit(attr_units or 1).is_time_reference() + is_time_reference = cf_units.Unit(attr_units or 1).is_time_reference() except ValueError: is_time_reference = False - + return is_time_reference and (attr_std_name=='time' or attr_axis.lower()==CF_VALUE_AXIS_T) @@ -1300,7 +1923,7 @@ fc_extras if attr_units is not None: try: - is_valid = iris.unit.is_time(attr_units) + is_valid = cf_units.is_time(attr_units) except ValueError: is_valid = False @@ -1351,6 +1974,67 @@ fc_extras return _is_rotated(engine, cf_name, CF_VALUE_STD_NAME_GRID_LON) + ################################################################################ + def has_supported_mercator_parameters(engine, cf_name): + """Determine whether the CF grid mapping variable has the supported + values for the parameters of the Mercator projection.""" + + is_valid = True + cf_grid_var = engine.cf_var.cf_group[cf_name] + + false_easting = getattr( + cf_grid_var, CF_ATTR_GRID_FALSE_EASTING, None) + false_northing = getattr( + cf_grid_var, CF_ATTR_GRID_FALSE_NORTHING, None) + scale_factor_at_projection_origin = getattr( + cf_grid_var, CF_ATTR_GRID_SCALE_FACTOR_AT_PROJ_ORIGIN, None) + standard_parallel = getattr( + cf_grid_var, CF_ATTR_GRID_STANDARD_PARALLEL, None) + + if false_easting is not None and \ + false_easting != 0: + warnings.warn('False eastings other than 0.0 not yet supported ' + 'for Mercator projections') + is_valid = False + if false_northing is not None and \ + false_northing != 0: + warnings.warn('False northings other than 0.0 not yet supported ' + 'for Mercator projections') + is_valid = False + if scale_factor_at_projection_origin is not None and \ + scale_factor_at_projection_origin != 1: + warnings.warn('Scale factors other than 1.0 not yet supported for ' + 'Mercator projections') + is_valid = False + if standard_parallel is not None and \ + standard_parallel != 0: + warnings.warn('Standard parallels other than 0.0 not yet ' + 'supported for Mercator projections') + is_valid = False + + return is_valid + + + ################################################################################ + def has_supported_stereographic_parameters(engine, cf_name): + """Determine whether the CF grid mapping variable has a value of 1.0 + for the scale_factor_at_projection_origin attribute.""" + + is_valid = True + cf_grid_var = engine.cf_var.cf_group[cf_name] + + scale_factor_at_projection_origin = getattr( + cf_grid_var, CF_ATTR_GRID_SCALE_FACTOR_AT_PROJ_ORIGIN, None) + + if scale_factor_at_projection_origin is not None and \ + scale_factor_at_projection_origin != 1: + warnings.warn('Scale factors other than 1.0 not yet supported for ' + 'stereographic projections') + is_valid = False + + return is_valid + + ################################################################################ def _parse_cell_methods(cf_var_name, nc_cell_methods): """Parse the CF cell_methods attribute string.""" @@ -1359,8 +2043,17 @@ fc_extras if nc_cell_methods is not None: for m in CM_PARSE.finditer(nc_cell_methods): d = m.groupdict() - if d[CM_METHOD].lower() not in CM_KNOWN_METHODS: - warnings.warn('NetCDF variable {!r} contains unknown cell method {!r}'.format('{}'.format(cf_var_name), '{}'.format(d[CM_METHOD]))) + method = d[CM_METHOD] + method = method.strip() + # Check validity of method, allowing for multi-part methods + # e.g. mean over years. + method_words = method.split() + if method_words[0].lower() not in CM_KNOWN_METHODS: + msg = 'NetCDF variable {!r} contains unknown cell ' \ + 'method {!r}' + warnings.warn(msg.format('{}'.format(cf_var_name), + '{}'.format(method_words[0]))) + d[CM_METHOD] = method name = d[CM_NAME] name = name.replace(' ', '') name = name.rstrip(':') @@ -1409,6 +2102,6 @@ fc_extras if len(d[CM_NAME]) != len(comment) and len(comment) == 1: comment = comment*len(d[CM_NAME]) d[CM_INTERVAL] = tuple(interval) - d[CM_COMMENT] = tuple(comment) + d[CM_COMMENT] = tuple(comment) cell_methods.append(iris.coords.CellMethod(d[CM_METHOD], coords=d[CM_NAME], intervals=d[CM_INTERVAL], comments=d[CM_COMMENT])) return tuple(cell_methods) diff --git a/lib/iris/fileformats/_structured_array_identification.py b/lib/iris/fileformats/_structured_array_identification.py new file mode 100644 index 0000000000..2c1ab9045d --- /dev/null +++ b/lib/iris/fileformats/_structured_array_identification.py @@ -0,0 +1,497 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +r""" +The purpose of this module is to provide utilities for the identification +of multi-dimensional structure in a flat sequence of homogeneous objects. +One application of this is to efficiently identify a higher dimensional +structure from a sorted sequence of PPField instances; for an example, given +a list of 12 PPFields, identification that there are 3 unique "time" values +and 4 unique "height" values where time and height are linearly independent +means that we could construct a resulting cube with a shape of +``(3, 4) + ``. + +An example using numpy arrays: + + >>> import numpy as np + >>> orig_x, orig_y = np.arange(2), np.arange(3) + >>> x, y = np.meshgrid(orig_x, orig_y) + + >>> # Remove the dimensional structure from the arrays. + >>> x, y = x.flatten(), y.flatten() + + >>> print(x) + [0 1 0 1 0 1] + >>> print(y) + [0 0 1 1 2 2] + + >>> arrays = {'x': x, 'y': y} + >>> group = GroupStructure.from_component_arrays(arrays) + >>> print(group) + Group structure: + Length: 6 + Element names: x, y + Possible structures ("c" order): + (y: 3; x: 2) + + >>> built_arrays = group.build_arrays((3, 2), arrays) + >>> y_array, y_axes = built_arrays['y'] + >>> print(y_array, y_axes) + [0 1 2] (0,) + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +from collections import namedtuple + +import numpy as np + + +class _UnstructuredArrayException(Exception): + """ + Raised when an array has been incorrectly assumed to be + structured in a specific way. + + """ + + +class ArrayStructure(namedtuple('ArrayStructure', + ['stride', 'unique_ordered_values'])): + """ + Represents the identified structure of an array, where stride is the + step between each unique value being seen in order in the flattened + version of the array. + + Note: Stride is **not** in bytes, but is instead the number of objects in + the original list of arrays, thus, stride is dtype independent. + + For column major (aka "F" order) arrays, stride will be one for those + arrays which vary over the first dimension, and conversely will be one for + C order arrays when varying over the last dimension. + + Constructing an ArrayStructure is most frequently done through the + :meth:`ArrayStructure.from_array` class method, which takes a flattened + array as its input. + + Stride examples: + + >>> ArrayStructure.from_array(np.array([1, 2])).stride + 1 + >>> ArrayStructure.from_array(np.array([1, 1, 2, 2])).stride + 2 + >>> ArrayStructure.from_array(np.array([1, 1, 1, 2, 2, 2])).stride + 3 + >>> ArrayStructure.from_array(np.array([1, 2, 1, 2])).stride + 1 + >>> ArrayStructure.from_array(np.array([1, 1, 2, 2, 1, 1, 2, 2])).stride + 2 + + """ + def __new__(cls, stride, unique_ordered_values): + self = super(ArrayStructure, cls).__new__(cls, stride, + unique_ordered_values) + return self + + __slots__ = () + + @property + def size(self): + """ + The ``size`` attribute is the number of the unique values in the + original array. It is **not** the length of the original array. + + """ + return len(self.unique_ordered_values) + + def __hash__(self): + return super(ArrayStructure, self).__hash__() + + def __eq__(self, other): + stride = getattr(other, 'stride', None) + arr = getattr(other, 'unique_ordered_values', None) + + result = NotImplemented + if stride is not None or arr is not None: + result = (stride == self.stride and + np.all(self.unique_ordered_values == arr)) + return result + + def __ne__(self, other): + return not (self == other) + + def construct_array(self, size): + """ + The inverse operation of :func:`ArrayStructure.from_array`, returning + a 1D array of the given length with the appropriate repetition + pattern. + + """ + return np.tile(np.repeat(self.unique_ordered_values, self.stride), + size // (self.size * self.stride)) + + def nd_array_and_dims(self, original_array, target_shape, order='c'): + """ + Given a 1D array, and a target shape, construct an ndarray + and associated dimensions. + + Raises an _UnstructuredArrayException if no optimised shape array can + be returned, in which case, simply reshaping the original_array would + be just as effective. + + For example: + + >>> orig = np.array([1, 2, 3, 1, 2, 3]) + >>> structure = ArrayStructure.from_array(orig) + >>> array, dims = structure.nd_array_and_dims(orig, (2, 1, 3)) + >>> array + array([1, 2, 3]) + >>> dims + (2,) + >>> # Filling the array with dimensions of length one should impact + >>> # dims but not the array which is returned. + >>> _, dims = structure.nd_array_and_dims(orig, (1, 2, 1, 3, 1)) + >>> dims + (3,) + + """ + if original_array.shape[0] != np.prod(target_shape): + raise ValueError('Original array and target shape do not ' + 'match up.') + stride_product = 1 + + result = None + + if self.size == 1: + # There is no need to even consider the dimensionality - this + # array structure only has one unique value, so it is a scalar + # and has no associated dimension. + result = (np.array(original_array[0]), ()) + + for dim, length in sorted(enumerate(target_shape), + reverse=order.lower() == 'c'): + if result is not None: + break + + # Does this array structure represent a flattened array of the + # given shape? If so, reshape it back to the target shape, + # then index out any dimensions which are constant. + if self.stride == stride_product and length == self.size: + vector = original_array.reshape(target_shape + (-1, ), + order=order) + # Reduce the dimensionality to a 1d array by indexing + # everything but this dimension. + vector = vector[tuple(0 if dim != i else slice(None) + for i in range(len(target_shape)))] + # Remove any trailing dimension if it is trivial. + if len(vector.shape) != 1 and vector.shape[-1] == 1: + vector = vector[..., 0] + + result = [vector, (dim, )] + break + + stride_product *= length + + if result is not None: + return result + else: + msg = ('Unable to construct an efficient nd_array for the target ' + 'shape. Consider reshaping the array to the full shape ' + 'instead.') + raise _UnstructuredArrayException(msg) + + @classmethod + def from_array(cls, arr): + """ + Return the computed ArrayStructure for the given flat array + (if a structure exists, otherwise return None). + + """ + # Note: This algorithm will only find distinct value columns/rows/axes + # any dimension with repeat values will not have its structure + # identified and will be considered irregular. + + if not isinstance(arr, np.ndarray): + arr = np.array(arr) + + if arr.ndim != 1: + raise ValueError('The given array must be 1D.') + + if arr.size == 0: + return cls(1, arr) + + # unique is a *sorted* array of unique values. + # unique_inds takes us from the sorted unique values back to inds in + # the input array inds_back_to_orig gives us the indices of each value + # in the array vs the index in the *sorted* unique array. + _, unique_inds = np.unique(arr, return_index=True) + + # Return the unique values back into an ordered array. + unique = arr[np.sort(unique_inds)] + + # what we actually want is inds_back_to_orig in the sort order of the + # original array. + new_inds = np.empty(arr.shape, dtype=unique_inds.dtype) + + for ind, unique_val in enumerate(unique): + new_inds[arr == unique_val] = ind + + inds_back_to_orig = new_inds + + u_len = len(unique) + n_fields = arr.size + + structure = None + + # If the length of the unique values is not a divisor of the + # length of the original array, it is going to be an irregular + # array, so we can avoid some processing. + if (n_fields % u_len) != 0: + # No structure. + pass + # Shortcut the simple case of all values being distinct. + elif u_len == 1: + structure = ArrayStructure(1, unique) + else: + # Working in index space, compute indices where values change. + ind_diffs = np.diff(inds_back_to_orig) + + # Find the indices where a change takes place. + ind_diffs_which_changed = np.nonzero(ind_diffs)[0] + + # Any index which changed by a different consecutive amount is a + # stride. For example, an input array of [1,1,2,2,1,1,2,2] + # results in ind_diffs looking like [0,1,0,-1,0,1,0] and + # ind_diffs_which_changed being [1,3,5]. So now identifying the + # "stride" (being the length of any sequence which has + # consecutively equal values) is a matter of identifying the + # difference between any two consecutive values from + # ind_diffs_which_changed. If we don't have enough + # ind_diffs_which_changed values to compute a difference, then + # there is either one or two distinct values in the original + # array, and the stride is therefore the total length / number + # of unique values. + try: + stride = np.diff(ind_diffs_which_changed[:2])[0] + except IndexError: + stride = n_fields // u_len + + structure = cls(stride, unique) + + # Do one last sanity check - does the array we've just described + # actually compute the correct array? + constructed_array = structure.construct_array(arr.size) + if not np.all(constructed_array == arr): + structure = None + + return structure + + +class GroupStructure(object): + """ + The GroupStructure class represents a collection of array structures along + with additional information such as the length of the arrays and the array + order in which they are found (row-major or column-major). + + """ + def __init__(self, length, component_structure, array_order='c'): + """ + group_component_to_array - a dictionary. See also TODO + """ + #: The size common to all of the original arrays and used to determine + #: possible shape configurations. + self.length = length + + #: A dictionary mapping component name to ArrayStructure instance + #: (or None if no such structure exists for that component). + self._cmpt_structure = component_structure + + array_order = array_order.lower() + if array_order not in ['c', 'f']: + raise ValueError('Invalid array order {!r}'.format(array_order)) + self._array_order = array_order + + @classmethod + def from_component_arrays(cls, component_arrays, array_order='c'): + """ + Given a dictionary of component name to flattened numpy array, + return an :class:`GroupStructure` instance which is representative + of the underlying array structures. + + Args: + + * component_arrays - A dictionary mapping component name to the + full sized 1d (flattened) numpy array. + + """ + cmpt_structure = {name: ArrayStructure.from_array(array) + for name, array in component_arrays.items()} + + sizes = np.array([array.size for array in component_arrays.values()]) + if not np.all(sizes == sizes[0]): + raise ValueError('All array elements must have the same size.') + + return cls(sizes[0], cmpt_structure, array_order=array_order) + + def _potentially_flattened_components(self): + """ + Return a generator of the components which could form non-trivial + (i.e. ``length > 1``) array dimensions. + + """ + for name, structure in self._cmpt_structure.items(): + if structure is not None and structure.size > 1: + yield (name, structure) + + @property + def is_row_major(self): + return self._array_order == 'c' + + def possible_structures(self): + """ + Return a tuple containing the possible structures that this group + could have. + + A structure in this case is an iterable of + ``(name, ArrayStructure)`` pairs, one per dimension, of a possible + array. The shape of the resulting array would then be + ``tuple(array_struct.size for (name, array_struct) in pair)`` for any + of the returned structures. + + The algorithm does not deal with incomplete structures, such that + all components critical for the identification of a shape are + necessary. + + """ + vector_structures = sorted(self._potentially_flattened_components()) + + def filter_strides_of_length(length): + return [(name, struct) for (name, struct) in vector_structures + if struct.stride == length] + + # Keep track of our structures so far. This will be a list of lists + # containing the actual structure pairs. + possible = [] + + # Get hold of all array structures with a stride of 1. These are the + # only possible array structures for the first dimension (i.e. on the + # left-most dimension for column-major ordering). Start a list of + # structures, one for each possible left hand side dimension + # component. + for structure in filter_strides_of_length(1): + possible.append([structure]) + + # Keep track of all structures which are valid, these are ultimately + # what will be returned from this function. + allowed_structures = [] + + # We will make use of the mutability of the possible list, removing + # each list representing a potential structure. With the potential + # just removed, we will find any array structures which could be the + # next dimension in the potential, adding one new possible structure + # per array structure found. If at any point, a possible's stride + # product is the same as the length of this group, we've got an + # allowed structure. + while possible: + for potential in possible[:]: + possible.remove(potential) + # If we are to build another dimension on top of this possible + # structure, we need to compute the stride that would be + # needed for that dimension. + next_stride = np.product([struct.size + for (_, struct) in potential]) + + # If we've found a structure whose product is the length of + # the fields of this Group, we've got a valid potential. + if next_stride == self.length: + allowed_structures.append(potential) + + # So let's get all of the potential nd-arrays which would be + # viable dimensions on this potential structure. + next_dim_structs = filter_strides_of_length(next_stride) + + # Any we find get added to this potential and put back in the + # possibles. + for struct in next_dim_structs: + if struct in potential: + continue + new_potential = potential[:] + # Add the structure to the potential on the right hand + # side of the structure (column-major). + new_potential.append(struct) + possible.append(new_potential) + + # We've been working in column-major order, so let's reverse the + # dimensionality if we are in row-major. + if self.is_row_major: + for potential in allowed_structures: + potential.reverse() + + return tuple(allowed_structures) + + def __str__(self): + result = ['Group structure:', + ' Length: {}'.format(self.length), + ' Element names: {}'.format( + ', '.join(sorted(self._cmpt_structure.keys()))), + ' Possible structures ("{}" order):'.format( + self._array_order)] + + for structure in self.possible_structures(): + sizes = ('{}: {}'.format(name, arr_struct.size) + for name, arr_struct in structure) + result.append(' ({})'.format('; '.join(sizes))) + + return '\n'.join(result) + + def build_arrays(self, shape, elements_arrays): + """ + Given the target shape, and a dictionary mapping name to 1D array of + :attr:`.length`, return a dictionary mapping element name to + ``(ndarray, dims)``. + + Note: Actually the arrays may be more than one dimension, and the + trailing dimensions will be preserved. This is useful for items such + as datetimes, where an efficiency exists to avoid the construction + of datetime objects until the last moment. + + """ + elem_to_nd_and_dims = {} + + if sorted(elements_arrays.keys()) != sorted(self._cmpt_structure): + raise ValueError('The GroupStructure elements were not the same ' + 'as those provided in the element_arrays.') + + for name, array in elements_arrays.items(): + struct = self._cmpt_structure[name] + nd_array_and_dims = None + if struct is not None: + try: + nd_array_and_dims = struct.nd_array_and_dims( + array, shape, order=self._array_order) + except _UnstructuredArrayException: + pass + + if nd_array_and_dims is None: + reshape_shape = shape + if array.ndim > 1: + reshape_shape = reshape_shape + (-1, ) + nd_array_and_dims = [array.reshape(reshape_shape, + order=self._array_order), + tuple(range(len(shape)))] + elem_to_nd_and_dims[name] = nd_array_and_dims + return elem_to_nd_and_dims diff --git a/lib/iris/fileformats/abf.py b/lib/iris/fileformats/abf.py index 525b30bd36..061c65aa6a 100644 --- a/lib/iris/fileformats/abf.py +++ b/lib/iris/fileformats/abf.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2012 - 2013, Met Office +# (C) British Crown Copyright 2012 - 2015, Met Office # # This file is part of Iris. # @@ -25,6 +25,10 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + import calendar import datetime import glob @@ -190,7 +194,7 @@ def load_cubes(filespecs, callback=None): The resultant cubes may not be in the same order as in the file. """ - if isinstance(filespecs, basestring): + if isinstance(filespecs, six.string_types): filespecs = [filespecs] for filespec in filespecs: diff --git a/lib/iris/fileformats/cf.py b/lib/iris/fileformats/cf.py index f3308b2541..f2fc895d1c 100644 --- a/lib/iris/fileformats/cf.py +++ b/lib/iris/fileformats/cf.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -15,7 +15,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """ -Provides the capability to load netCDF files and interprete them +Provides the capability to load netCDF files and interpret them according to the 'NetCDF Climate and Forecast (CF) Metadata Conventions'. References: @@ -25,16 +25,21 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + from abc import ABCMeta, abstractmethod +from collections import Iterable, MutableMapping import os import re -import UserDict import warnings import netCDF4 import numpy as np import numpy.ma as ma +from iris._deprecation import warn_deprecated import iris.util @@ -53,33 +58,49 @@ # therefore automatically classed as "used" attributes. _CF_ATTRS_IGNORE = set(['_FillValue', 'add_offset', 'missing_value', 'scale_factor', ]) +#: Supported dimensionless vertical coordinate reference surface/phemomenon +#: formula terms. Ref: [CF] Appendix D. +reference_terms = dict(atmosphere_sigma_coordinate=['ps'], + atmosphere_hybrid_sigma_pressure_coordinate=['ps'], + atmosphere_hybrid_height_coordinate=['orog'], + atmosphere_sleve_coordinate=['zsurf1', 'zsurf2'], + ocean_sigma_coordinate=['eta', 'depth'], + ocean_s_coordinate=['eta', 'depth'], + ocean_sigma_z_coordinate=['eta', 'depth'], + ocean_s_coordinate_g1=['eta', 'depth'], + ocean_s_coordinate_g2=['eta', 'depth']) + + +# NetCDF returns a different type for strings depending on Python version. +def _is_str_dtype(var): + return ((six.PY2 and np.issubdtype(var.dtype, np.str_)) or + (six.PY3 and np.issubdtype(var.dtype, np.bytes_))) + ################################################################################ -class CFVariable(object): +class CFVariable(six.with_metaclass(ABCMeta, object)): """Abstract base class wrapper for a CF-netCDF variable.""" - __metaclass__ = ABCMeta - #: Name of the netCDF variable attribute that identifies this #: CF-netCDF variable. cf_identity = None - + def __init__(self, name, data): # Accessing the list of netCDF attributes is surprisingly slow. # Since it's used repeatedly, caching the list makes things # quite a bit faster. self._nc_attrs = data.ncattrs() - #: NetCDF variable name + #: NetCDF variable name. self.cf_name = name - #: NetCDF4 Variable data instance + #: NetCDF4 Variable data instance. self.cf_data = data - #: Collection of CF-netCDF variables associated with this variable + #: Collection of CF-netCDF variables associated with this variable. self.cf_group = None - #: CF-netCDF formula terms that his variable participates in + #: CF-netCDF formula terms that his variable participates in. self.cf_terms_by_root = {} self.cf_attrs_reset() @@ -91,7 +112,7 @@ def _identify_common(variables, ignore, target): if target is None: target = variables - elif isinstance(target, basestring): + elif isinstance(target, six.string_types): if target not in variables: raise ValueError('Cannot identify unknown target CF-netCDF variable %r' % target) target = {target: variables[target]} @@ -125,6 +146,26 @@ def identify(self, variables, ignore=None, target=None, warn=True): """ pass + def spans(self, cf_variable): + """ + Determine whether the dimensionality of this variable + is a subset of the specified target variable. + + Note that, by default scalar variables always span the + dimensionality of the target variable. + + Args: + + * cf_variable: + Compare dimensionality with the :class:`CFVariable`. + + Returns: + Boolean. + + """ + result = set(self.dimensions).issubset(cf_variable.dimensions) + return result + def __eq__(self, other): # CF variable names are unique. return self.cf_name == other.cf_name @@ -133,6 +174,10 @@ def __ne__(self, other): # CF variable names are unique. return self.cf_name != other.cf_name + def __hash__(self): + # CF variable names are unique. + return hash(self.cf_name) + def __getattr__(self, name): # Accessing netCDF attributes is surprisingly slow. Since # they're often read repeatedly, caching the values makes things @@ -220,17 +265,16 @@ class CFAncillaryDataVariable(CFVariable): def identify(cls, variables, ignore=None, target=None, warn=True): result = {} ignore, target = cls._identify_common(variables, ignore, target) - netcdf_variable_names = variables.keys() # Identify all CF ancillary data variables. - for nc_var_name, nc_var in target.iteritems(): + for nc_var_name, nc_var in six.iteritems(target): # Check for ancillary data variable references. nc_var_att = getattr(nc_var, cls.cf_identity, None) if nc_var_att is not None: for name in nc_var_att.split(): if name not in ignore: - if name not in netcdf_variable_names: + if name not in variables: if warn: message = 'Missing CF-netCDF ancillary data variable %r, referenced by netCDF variable %r' warnings.warn(message % (name, nc_var_name)) @@ -261,23 +305,22 @@ class CFAuxiliaryCoordinateVariable(CFVariable): def identify(cls, variables, ignore=None, target=None, warn=True): result = {} ignore, target = cls._identify_common(variables, ignore, target) - netcdf_variable_names = variables.keys() # Identify all CF auxiliary coordinate variables. - for nc_var_name, nc_var in target.iteritems(): + for nc_var_name, nc_var in six.iteritems(target): # Check for auxiliary coordinate variable references. nc_var_att = getattr(nc_var, cls.cf_identity, None) if nc_var_att is not None: for name in nc_var_att.split(): if name not in ignore: - if name not in netcdf_variable_names: + if name not in variables: if warn: message = 'Missing CF-netCDF auxiliary coordinate variable %r, referenced by netCDF variable %r' warnings.warn(message % (name, nc_var_name)) else: # Restrict to non-string type i.e. not a CFLabelVariable. - if not np.issubdtype(variables[name].dtype, np.str): + if not _is_str_dtype(variables[name]): result[name] = CFAuxiliaryCoordinateVariable(name, variables[name]) return result @@ -304,10 +347,9 @@ class CFBoundaryVariable(CFVariable): def identify(cls, variables, ignore=None, target=None, warn=True): result = {} ignore, target = cls._identify_common(variables, ignore, target) - netcdf_variable_names = variables.keys() # Identify all CF boundary variables. - for nc_var_name, nc_var in target.iteritems(): + for nc_var_name, nc_var in six.iteritems(target): # Check for a boundary variable reference. nc_var_att = getattr(nc_var, cls.cf_identity, None) @@ -315,7 +357,7 @@ def identify(cls, variables, ignore=None, target=None, warn=True): name = nc_var_att.strip() if name not in ignore: - if name not in netcdf_variable_names: + if name not in variables: if warn: message = 'Missing CF-netCDF boundary variable %r, referenced by netCDF variable %r' warnings.warn(message % (name, nc_var_name)) @@ -324,6 +366,33 @@ def identify(cls, variables, ignore=None, target=None, warn=True): return result + def spans(self, cf_variable): + """ + Determine whether the dimensionality of this variable + is a subset of the specified target variable. + + Note that, by default scalar variables always span the + dimensionality of the target variable. + + Args: + + * cf_variable: + Compare dimensionality with the :class:`CFVariable`. + + Returns: + Boolean. + + """ + # Scalar variables always span the target variable. + result = True + if self.dimensions: + source = self.dimensions + target = cf_variable.dimensions + # Ignore the bounds extent dimension. + result = set(source[:-1]).issubset(target) or \ + set(source[1:]).issubset(target) + return result + class CFClimatologyVariable(CFVariable): """ @@ -346,10 +415,9 @@ class CFClimatologyVariable(CFVariable): def identify(cls, variables, ignore=None, target=None, warn=True): result = {} ignore, target = cls._identify_common(variables, ignore, target) - netcdf_variable_names = variables.keys() # Identify all CF climatology variables. - for nc_var_name, nc_var in target.iteritems(): + for nc_var_name, nc_var in six.iteritems(target): # Check for a climatology variable reference. nc_var_att = getattr(nc_var, cls.cf_identity, None) @@ -357,7 +425,7 @@ def identify(cls, variables, ignore=None, target=None, warn=True): name = nc_var_att.strip() if name not in ignore: - if name not in netcdf_variable_names: + if name not in variables: if warn: message = 'Missing CF-netCDF climatology variable %r, referenced by netCDF variable %r' warnings.warn(message % (name, nc_var_name)) @@ -366,6 +434,33 @@ def identify(cls, variables, ignore=None, target=None, warn=True): return result + def spans(self, cf_variable): + """ + Determine whether the dimensionality of this variable + is a subset of the specified target variable. + + Note that, by default scalar variables always span the + dimensionality of the target variable. + + Args: + + * cf_variable: + Compare dimensionality with the :class:`CFVariable`. + + Returns: + Boolean. + + """ + # Scalar variables always span the target variable. + result = True + if self.dimensions: + source = self.dimensions + target = cf_variable.dimensions + # Ignore the climatology extent dimension. + result = set(source[:-1]).issubset(target) or \ + set(source[1:]).issubset(target) + return result + class CFCoordinateVariable(CFVariable): """ @@ -386,14 +481,14 @@ def identify(cls, variables, ignore=None, target=None, warn=True, monotonic=Fals ignore, target = cls._identify_common(variables, ignore, target) # Identify all CF coordinate variables. - for nc_var_name, nc_var in target.iteritems(): + for nc_var_name, nc_var in six.iteritems(target): if nc_var_name in ignore: continue # String variables can't be coordinates - if np.issubdtype(nc_var.dtype, np.str): + if _is_str_dtype(nc_var): continue - # Restrict to one-dimensional with name as dimension OR zero-dimensional scalar - if not ((nc_var.ndim == 1 and nc_var_name in nc_var.dimensions) or (nc_var.ndim == 0)): + # Restrict to one-dimensional with name as dimension + if not (nc_var.ndim == 1 and nc_var_name in nc_var.dimensions): continue # Restrict to monotonic? if monotonic: @@ -435,44 +530,45 @@ class _CFFormulaTermsVariable(CFVariable): def __init__(self, name, data, formula_root, formula_term): CFVariable.__init__(self, name, data) - #: CF-netCDF variable name that defines the formula terms - self.cf_root = formula_root - #: Formula term of the associated formula variable - self.cf_term = formula_term + # Register the formula root and term relationship. + self.add_formula_term(formula_root, formula_term) @classmethod def identify(cls, variables, ignore=None, target=None, warn=True): result = {} ignore, target = cls._identify_common(variables, ignore, target) - netcdf_variable_names = variables.keys() # Identify all CF formula terms variables. - for nc_var_name, nc_var in target.iteritems(): + for nc_var_name, nc_var in six.iteritems(target): # Check for formula terms variable references. nc_var_att = getattr(nc_var, cls.cf_identity, None) if nc_var_att is not None: for match_item in _CF_PARSE.finditer(nc_var_att): match_group = match_item.groupdict() - term_name = match_group['lhs'] + # Ensure that term name is lower case, as expected. + term_name = match_group['lhs'].lower() variable_name = match_group['rhs'] if variable_name not in ignore: - if variable_name not in netcdf_variable_names: + if variable_name not in variables: if warn: message = 'Missing CF-netCDF formula term variable %r, referenced by netCDF variable %r' warnings.warn(message % (variable_name, nc_var_name)) else: - result[variable_name] = _CFFormulaTermsVariable(variable_name, - variables[variable_name], - nc_var_name, term_name) + if variable_name not in result: + result[variable_name] = _CFFormulaTermsVariable(variable_name, + variables[variable_name], + nc_var_name, term_name) + else: + result[variable_name].add_formula_term(nc_var_name, term_name) return result def __repr__(self): - return '%s(%r, %r, %r, %r)' % (self.__class__.__name__, - self.cf_name, self.cf_data, - self.cf_root, self.cf_term) + return '%s(%r, %r, %r)' % (self.__class__.__name__, + self.cf_name, self.cf_data, + self.cf_terms_by_root) class CFGridMappingVariable(CFVariable): @@ -497,10 +593,9 @@ class CFGridMappingVariable(CFVariable): def identify(cls, variables, ignore=None, target=None, warn=True): result = {} ignore, target = cls._identify_common(variables, ignore, target) - netcdf_variable_names = variables.keys() # Identify all grid mapping variables. - for nc_var_name, nc_var in target.iteritems(): + for nc_var_name, nc_var in six.iteritems(target): # Check for a grid mapping variable reference. nc_var_att = getattr(nc_var, cls.cf_identity, None) @@ -508,7 +603,7 @@ def identify(cls, variables, ignore=None, target=None, warn=True): name = nc_var_att.strip() if name not in ignore: - if name not in netcdf_variable_names: + if name not in variables: if warn: message = 'Missing CF-netCDF grid mapping variable %r, referenced by netCDF variable %r' warnings.warn(message % (name, nc_var_name)) @@ -535,24 +630,24 @@ class CFLabelVariable(CFVariable): def identify(cls, variables, ignore=None, target=None, warn=True): result = {} ignore, target = cls._identify_common(variables, ignore, target) - netcdf_variable_names = variables.keys() # Identify all CF label variables. - for nc_var_name, nc_var in target.iteritems(): + for nc_var_name, nc_var in six.iteritems(target): # Check for label variable references. nc_var_att = getattr(nc_var, cls.cf_identity, None) if nc_var_att is not None: for name in nc_var_att.split(): if name not in ignore: - if name not in netcdf_variable_names: + if name not in variables: if warn: message = 'Missing CF-netCDF label variable %r, referenced by netCDF variable %r' warnings.warn(message % (name, nc_var_name)) else: - # Restrict to only string type. - if np.issubdtype(variables[name].dtype, np.str): - result[name] = CFLabelVariable(name, variables[name]) + # Register variable, but only allow string type. + var = variables[name] + if _is_str_dtype(var): + result[name] = CFLabelVariable(name, var) return result @@ -583,20 +678,25 @@ def cf_label_data(self, cf_data_var): str_dim_name = str_dim_name[0] label_data = self[:] - if isinstance(label_data, ma.MaskedArray): + if ma.isMaskedArray(label_data): label_data = label_data.filled() # Determine whether we have a string-valued scalar label # i.e. a character variable that only has one dimension (the length of the string). if self.ndim == 1: - data = np.array([''.join(label_data).strip()]) + label_string = b''.join(label_data).strip() + if six.PY3: + label_string = label_string.decode('utf8') + data = np.array([label_string]) else: # Determine the index of the string dimension. str_dim = self.dimensions.index(str_dim_name) # Calculate new label data shape (without string dimension) and create payload array. new_shape = tuple(dim_len for i, dim_len in enumerate(self.shape) if i != str_dim) - data = np.empty(new_shape, dtype='|S%d' % self.shape[str_dim]) + string_basetype = '|S%d' if six.PY2 else '|U%d' + string_dtype = string_basetype % self.shape[str_dim] + data = np.empty(new_shape, dtype=string_dtype) for index in np.ndindex(new_shape): # Create the slice for the label data. @@ -605,7 +705,10 @@ def cf_label_data(self, cf_data_var): else: label_index = index + (slice(None, None),) - data[index] = ''.join(label_data[label_index]).strip() + label_string = b''.join(label_data[label_index]).strip() + if six.PY3: + label_string = label_string.decode('utf8') + data[index] = label_string return data @@ -628,6 +731,33 @@ def cf_label_dimensions(self, cf_data_var): return tuple([dim_name for dim_name in self.dimensions if dim_name in cf_data_var.dimensions]) + def spans(self, cf_variable): + """ + Determine whether the dimensionality of this variable + is a subset of the specified target variable. + + Note that, by default scalar variables always span the + dimensionality of the target variable. + + Args: + + * cf_variable: + Compare dimensionality with the :class:`CFVariable`. + + Returns: + Boolean. + + """ + # Scalar variables always span the target variable. + result = True + if self.dimensions: + source = self.dimensions + target = cf_variable.dimensions + # Ignore label string length dimension. + result = set(source[:-1]).issubset(target) or \ + set(source[1:]).issubset(target) + return result + class CFMeasureVariable(CFVariable): """ @@ -644,15 +774,14 @@ def __init__(self, name, data, measure): CFVariable.__init__(self, name, data) #: Associated cell measure of the cell variable self.cf_measure = measure - + @classmethod def identify(cls, variables, ignore=None, target=None, warn=True): result = {} ignore, target = cls._identify_common(variables, ignore, target) - netcdf_variable_names = variables.keys() # Identify all CF measure variables. - for nc_var_name, nc_var in target.iteritems(): + for nc_var_name, nc_var in six.iteritems(target): # Check for measure variable references. nc_var_att = getattr(nc_var, cls.cf_identity, None) @@ -663,7 +792,7 @@ def identify(cls, variables, ignore=None, target=None, warn=True): variable_name = match_group['rhs'] if variable_name not in ignore: - if variable_name not in netcdf_variable_names: + if variable_name not in variables: if warn: message = 'Missing CF-netCDF measure variable %r, referenced by netCDF variable %r' warnings.warn(message % (variable_name, nc_var_name)) @@ -674,21 +803,25 @@ def identify(cls, variables, ignore=None, target=None, warn=True): ################################################################################ -class CFGroup(object, UserDict.DictMixin): +class CFGroup(MutableMapping, object): """ Represents a collection of 'NetCDF Climate and Forecast (CF) Metadata Conventions' variables and netCDF global attributes. """ - def __init__(self): + def __init__(self): #: Collection of CF-netCDF variables self._cf_variables = {} #: Collection of netCDF global attributes self.global_attributes = {} + #: Collection of CF-netCDF variables promoted to a CFDataVariable. + self.promoted = {} def _cf_getter(self, cls): # Generate dictionary with dictionary comprehension. - return {cf_name:cf_var for cf_name, cf_var in self._cf_variables.iteritems() if isinstance(cf_var, cls)} + return {cf_name: cf_var + for cf_name, cf_var in six.iteritems(self._cf_variables) + if isinstance(cf_var, cls)} @property def ancillary_variables(self): @@ -723,7 +856,9 @@ def data_variables(self): @property def formula_terms(self): """Collection of CF-netCDF variables that participate in a CF-netCDF formula term.""" - return {cf_name:cf_var for cf_name, cf_var in self._cf_variables.iteritems() if cf_var.has_formula_terms()} + return {cf_name: cf_var + for cf_name, cf_var in six.iteritems(self._cf_variables) + if cf_var.has_formula_terms()} @property def grid_mappings(self): @@ -744,6 +879,13 @@ def keys(self): """Return the names of all the CF-netCDF variables in the group.""" return self._cf_variables.keys() + def __len__(self): + return len(self._cf_variables) + + def __iter__(self): + for item in self._cf_variables: + yield item + def __setitem__(self, name, variable): if not isinstance(variable, CFVariable): raise TypeError('Attempted to add an invalid CF-netCDF variable to the %s' % self.__class__.__name__) @@ -769,6 +911,7 @@ def __repr__(self): result = [] result.append('variables:%d' % len(self._cf_variables)) result.append('global_attributes:%d' % len(self.global_attributes)) + result.append('promoted:%d' % len(self.promoted)) return '<%s of %s>' % (self.__class__.__name__, ', '.join(result)) @@ -787,7 +930,7 @@ def __init__(self, filename, warn=False, monotonic=False): self._variable_types = (CFAncillaryDataVariable, CFAuxiliaryCoordinateVariable, CFBoundaryVariable, CFClimatologyVariable, CFGridMappingVariable, CFLabelVariable, CFMeasureVariable) - + #: Collection of CF-netCDF variables associated with this netCDF file self.cf_group = CFGroup() @@ -810,7 +953,7 @@ def __repr__(self): def _translate(self): """Classify the netCDF variables into CF-netCDF variables.""" - netcdf_variable_names = self._dataset.variables.keys() + netcdf_variable_names = list(self._dataset.variables.keys()) # Identify all CF coordinate variables first. This must be done # first as, by CF convention, the definition of a CF auxiliary @@ -819,7 +962,7 @@ def _translate(self): coords = CFCoordinateVariable.identify(self._dataset.variables, monotonic=self._check_monotonic) self.cf_group.update(coords) - coordinate_names = self.cf_group.coordinates.keys() + coordinate_names = list(self.cf_group.coordinates.keys()) # Identify all CF variables EXCEPT for the "special cases". for variable_type in self._variable_types: @@ -828,10 +971,22 @@ def _translate(self): self.cf_group.update(variable_type.identify(self._dataset.variables, ignore=ignore)) # Identify global netCDF attributes. - attr_dict = {attr_name: getattr(self._dataset, attr_name, '') for + attr_dict = {attr_name: _getncattr(self._dataset, attr_name, '') for attr_name in self._dataset.ncattrs()} self.cf_group.global_attributes.update(attr_dict) + # Identify and register all CF formula terms. + formula_terms = _CFFormulaTermsVariable.identify(self._dataset.variables) + + for cf_var in six.itervalues(formula_terms): + for cf_root, cf_term in six.iteritems(cf_var.cf_terms_by_root): + # Ignore formula terms owned by a bounds variable. + if cf_root not in self.cf_group.bounds: + cf_name = cf_var.cf_name + if cf_var.cf_name not in self.cf_group: + self.cf_group[cf_name] = CFAuxiliaryCoordinateVariable(cf_name, cf_var.cf_data) + self.cf_group[cf_name].add_formula_term(cf_root, cf_term) + # Determine the CF data variables. data_variable_names = set(netcdf_variable_names) - set(self.cf_group.ancillary_variables) - \ set(self.cf_group.auxiliary_coordinates) - set(self.cf_group.bounds) - \ @@ -842,33 +997,46 @@ def _translate(self): for name in data_variable_names: self.cf_group[name] = CFDataVariable(name, self._dataset.variables[name]) - # Identify and register all CF formula terms with the relevant CF variables. - formula_terms = _CFFormulaTermsVariable.identify(self._dataset.variables) - for cf_var in formula_terms.itervalues(): - if cf_var.cf_name in self.cf_group: - self.cf_group[cf_var.cf_name].add_formula_term(cf_var.cf_root, cf_var.cf_term) - def _build_cf_groups(self): """Build the first order relationships between CF-netCDF variables.""" - coordinate_names = self.cf_group.coordinates.keys() - - for cf_variable in self.cf_group.itervalues(): + def _build(cf_variable): + coordinate_names = list(self.cf_group.coordinates.keys()) cf_group = CFGroup() # Build CF variable relationships. for variable_type in self._variable_types: # Prevent grid mapping variables being mis-identified as # CF coordinate variables. - ignore = None if issubclass(variable_type, CFGridMappingVariable) else coordinate_names - match = variable_type.identify(self._dataset.variables, ignore=ignore, - target=cf_variable.cf_name, warn=False) - cf_group.update({name: self.cf_group[name] for name in match.iterkeys()}) + if issubclass(variable_type, CFGridMappingVariable): + ignore = None + else: + ignore = coordinate_names + match = variable_type.identify(self._dataset.variables, + ignore=ignore, + target=cf_variable.cf_name, + warn=False) + # Sanity check dimensionality coverage. + for cf_name, cf_var in six.iteritems(match): + if cf_var.spans(cf_variable): + cf_group[cf_name] = self.cf_group[cf_name] + else: + # Register the ignored variable. + # N.B. 'ignored' variable from enclosing scope. + ignored.add(cf_name) + msg = 'Ignoring variable {!r} referenced ' \ + 'by variable {!r}: Dimensions {!r} do not ' \ + 'span {!r}'.format(cf_name, + cf_variable.cf_name, + cf_var.dimensions, + cf_variable.dimensions) + warnings.warn(msg) # Build CF data variable relationships. if isinstance(cf_variable, CFDataVariable): # Add global netCDF attributes. - cf_group.global_attributes.update(self.cf_group.global_attributes) + cf_group.global_attributes.update( + self.cf_group.global_attributes) # Add appropriate "dimensioned" CF coordinate variables. cf_group.update({cf_name: self.cf_group[cf_name] for cf_name in cf_variable.dimensions if cf_name in @@ -878,16 +1046,92 @@ def _build_cf_groups(self): cf_group.update({cf_name: self.cf_group[cf_name] for cf_name in coordinates_attr.split() if cf_name in self.cf_group.coordinates}) + # Add appropriate formula terms. + for cf_var in six.itervalues(self.cf_group.formula_terms): + for cf_root in cf_var.cf_terms_by_root: + if (cf_root in cf_group and + cf_var.cf_name not in cf_group): + # Sanity check dimensionality. + if cf_var.spans(cf_variable): + cf_group[cf_var.cf_name] = cf_var + else: + # Register the ignored variable. + # N.B. 'ignored' variable from enclosing scope. + ignored.add(cf_var.cf_name) + msg = 'Ignoring formula terms variable {!r} ' \ + 'referenced by data variable {!r} via ' \ + 'variable {!r}: Dimensions {!r} do not ' \ + 'span {!r}'.format(cf_var.cf_name, + cf_variable.cf_name, + cf_root, + cf_var.dimensions, + cf_variable.dimensions) + warnings.warn(msg) # Add the CF group to the variable. cf_variable.cf_group = cf_group + # Ignored variables are those that cannot be attached to a + # data variable as the dimensionality of that variable is not + # a subset of the dimensionality of the data variable. + ignored = set() + + for cf_variable in six.itervalues(self.cf_group): + _build(cf_variable) + + # Determine whether there are any formula terms that + # may be promoted to a CFDataVariable and restrict promotion to only + # those formula terms that are reference surface/phenomenon. + for cf_var in six.itervalues(self.cf_group.formula_terms): + for cf_root, cf_term in six.iteritems(cf_var.cf_terms_by_root): + cf_root_var = self.cf_group[cf_root] + name = cf_root_var.standard_name or cf_root_var.long_name + terms = reference_terms.get(name, []) + if isinstance(terms, six.string_types) or \ + not isinstance(terms, Iterable): + terms = [terms] + cf_var_name = cf_var.cf_name + if cf_term in terms and \ + cf_var_name not in self.cf_group.promoted: + data_var = CFDataVariable(cf_var_name, cf_var.cf_data) + self.cf_group.promoted[cf_var_name] = data_var + _build(data_var) + break + # Promote any ignored variables. + promoted = set() + not_promoted = ignored.difference(promoted) + while not_promoted: + cf_name = not_promoted.pop() + if cf_name not in self.cf_group.data_variables and \ + cf_name not in self.cf_group.promoted: + data_var = CFDataVariable(cf_name, + self.cf_group[cf_name].cf_data) + self.cf_group.promoted[cf_name] = data_var + _build(data_var) + # Determine whether there are still any ignored variables + # yet to be promoted. + promoted.add(cf_name) + not_promoted = ignored.difference(promoted) + + def _reset(self): """Reset the attribute touch history of each variable.""" - - for nc_var_name in self._dataset.variables.iterkeys(): + for nc_var_name in six.iterkeys(self._dataset.variables): self.cf_group[nc_var_name].cf_attrs_reset() def __del__(self): # Explicitly close dataset to prevent file remaining open. self._dataset.close() + + +def _getncattr(dataset, attr, default=None): + """ + Simple wrapper round `netCDF4.Dataset.getncattr` to make it behave + more like `getattr`. + + """ + try: + value = dataset.getncattr(attr) + except AttributeError: + value = default + return value diff --git a/lib/iris/fileformats/dot.py b/lib/iris/fileformats/dot.py index 84f7c1b252..bdaf98aedf 100644 --- a/lib/iris/fileformats/dot.py +++ b/lib/iris/fileformats/dot.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2016, Met Office # # This file is part of Iris. # @@ -19,6 +19,10 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + import os import subprocess @@ -29,12 +33,35 @@ _GRAPH_INDENT = ' ' * 4 _SUBGRAPH_INDENT = ' ' * 8 -_DOT_EXECUTABLE_PATH = iris.config.get_option('System', 'dot_path', - default='dot') -if not os.path.exists(_DOT_EXECUTABLE_PATH): - _DOT_EXECUTABLE_PATH = None + +_DOT_CHECKED = False +_DOT_EXECUTABLE_PATH = None + + +def _dot_path(): + global _DOT_CHECKED, _DOT_EXECUTABLE_PATH + + if _DOT_CHECKED: + path = _DOT_EXECUTABLE_PATH + else: + path = iris.config.get_option('System', 'dot_path', default='dot') + if not os.path.exists(path): + if not os.path.isabs(path): + try: + # Check PATH + subprocess.check_output([path, '-V'], + stderr=subprocess.STDOUT) + except (OSError, subprocess.CalledProcessError): + path = None + else: + path = None + _DOT_EXECUTABLE_PATH = path + _DOT_CHECKED = True + return path + + #: Whether the 'dot' program is present (required for "dotpng" output). -DOT_AVAILABLE = _DOT_EXECUTABLE_PATH is not None +DOT_AVAILABLE = _dot_path() is not None def save(cube, target): @@ -48,7 +75,7 @@ def save(cube, target): See also :func:`iris.io.save`. """ - if isinstance(target, basestring): + if isinstance(target, six.string_types): dot_file = open(target, "wt") elif hasattr(target, "write"): if hasattr(target, "mode") and "b" in target.mode: @@ -57,10 +84,11 @@ def save(cube, target): else: raise ValueError("Can only save dot to filename or filehandle") - dot_file.write(cube_text(cube)) - - if isinstance(target, basestring): - dot_file.close() + try: + dot_file.write(cube_text(cube)) + finally: + if isinstance(target, six.string_types): + dot_file.close() def save_png(source, target, launch=False): @@ -85,23 +113,23 @@ def save_png(source, target, launch=False): # Create dot file dot_file_path = iris.util.create_temp_filename(".dot") save(source, dot_file_path) - elif isinstance(source, basestring): + elif isinstance(source, six.string_types): dot_file_path = source else: raise ValueError("Can only write dot png for a Cube or DOT file") # Create png data - if not _DOT_EXECUTABLE_PATH: + if not _dot_path(): raise ValueError('Executable "dot" not found: ' 'Review dot_path setting in site.cfg.') # To filename or open file handle? - if isinstance(target, basestring): - subprocess.call([_DOT_EXECUTABLE_PATH, '-T', 'png', '-o', target, + if isinstance(target, six.string_types): + subprocess.call([_dot_path(), '-T', 'png', '-o', target, dot_file_path]) elif hasattr(target, "write"): if hasattr(target, "mode") and "b" not in target.mode: raise ValueError("Target not binary") - subprocess.call([_DOT_EXECUTABLE_PATH, '-T', 'png', dot_file_path], + subprocess.call([_dot_path(), '-T', 'png', dot_file_path], stdout=target) else: raise ValueError("Can only write dot png for a filename or writable") @@ -227,7 +255,8 @@ def cube_text(cube): %(associations)s } ''' - cube_attributes = [(name, value) for name, value in sorted(cube.attributes.iteritems(), key=lambda item: item[0])] + cube_attributes = list(sorted(six.iteritems(cube.attributes), + key=lambda item: item[0])) cube_node = _dot_node(_GRAPH_INDENT, ':Cube', 'Cube', cube_attributes) res_string = template % { 'cube_node': cube_node, @@ -263,7 +292,7 @@ def _coord_text(label, coord): attrs = [(name, getattr(coord, name)) for name in _dot_attrs] if coord.attributes: - custom_attrs = sorted(coord.attributes.iteritems(), key=lambda item: item[0]) + custom_attrs = sorted(six.iteritems(coord.attributes), key=lambda item: item[0]) attrs.extend(custom_attrs) node = _dot_node(_SUBGRAPH_INDENT, label, coord.__class__.__name__, attrs) @@ -283,7 +312,7 @@ def _coord_system_text(cs, uid): """ attrs = [] - for k, v in cs.__dict__.iteritems(): + for k, v in six.iteritems(cs.__dict__): if isinstance(v, iris.cube.Cube): attrs.append((k, 'defined')) else: diff --git a/lib/iris/fileformats/ff.py b/lib/iris/fileformats/ff.py deleted file mode 100644 index 7bab9ade03..0000000000 --- a/lib/iris/fileformats/ff.py +++ /dev/null @@ -1,679 +0,0 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -""" -Provides UK Met Office Fields File (FF) format specific capabilities. - -""" - -import os -import warnings - -import numpy as np - -from iris.exceptions import NotYetImplementedError -from iris.fileformats._ff_cross_references import STASH_TRANS -import pp - - -IMDI = -32768 - -FF_HEADER_DEPTH = 256 # In words (64-bit). -DEFAULT_FF_WORD_DEPTH = 8 # In bytes. - -# UM marker to signify empty lookup table entry. -_FF_LOOKUP_TABLE_TERMINATE = -99 - -# UM FieldsFile fixed length header names and positions. -UM_FIXED_LENGTH_HEADER = [ - ('data_set_format_version', (1, )), - ('sub_model', (2, )), - ('vert_coord_type', (3, )), - ('horiz_grid_type', (4, )), - ('dataset_type', (5, )), - ('run_identifier', (6, )), - ('experiment_number', (7, )), - ('calendar', (8, )), - ('grid_staggering', (9, )), - ('time_type', (10, )), - ('projection_number', (11, )), - ('model_version', (12, )), - ('obs_file_type', (14, )), - ('last_fieldop_type', (15, )), - ('first_validity_time', (21, 22, 23, 24, 25, 26, 27, )), - ('last_validity_time', (28, 29, 30, 31, 32, 33, 34, )), - ('misc_validity_time', (35, 36, 37, 38, 39, 40, 41, )), - ('integer_constants', (100, 101, )), - ('real_constants', (105, 106, )), - ('level_dependent_constants', (110, 111, 112, )), - ('row_dependent_constants', (115, 116, 117, )), - ('column_dependent_constants', (120, 121, 122, )), - ('fields_of_constants', (125, 126, 127, )), - ('extra_constants', (130, 131, )), - ('temp_historyfile', (135, 136, )), - ('compressed_field_index1', (140, 141, )), - ('compressed_field_index2', (142, 143, )), - ('compressed_field_index3', (144, 145, )), - ('lookup_table', (150, 151, 152, )), - ('total_prognostic_fields', (153, )), - ('data', (160, 161, 162, )), ] - -# Offset value to convert from UM_FIXED_LENGTH_HEADER positions to -# FF_HEADER offsets. -UM_TO_FF_HEADER_OFFSET = 1 -# Offset the UM_FIXED_LENGTH_HEADER positions to FF_HEADER offsets. -FF_HEADER = [ - (name, tuple(position - UM_TO_FF_HEADER_OFFSET for position in positions)) - for name, positions in UM_FIXED_LENGTH_HEADER] - -# UM FieldsFile fixed length header pointer names. -_FF_HEADER_POINTERS = [ - 'integer_constants', - 'real_constants', - 'level_dependent_constants', - 'row_dependent_constants', - 'column_dependent_constants', - 'fields_of_constants', - 'extra_constants', - 'temp_historyfile', - 'compressed_field_index1', - 'compressed_field_index2', - 'compressed_field_index3', - 'lookup_table', - 'data', ] - -_LBUSER_DTYPE_LOOKUP = {1: '>f{word_depth}', - 2: '>i{word_depth}', - 3: '>i{word_depth}', - 'default': '>f{word_depth}', } - - -#: Codes used in STASH_GRID which indicate the x coordinate is on the -#: edge of the cell. -X_COORD_U_GRID = (11, 18, 27) - -#: Codes used in STASH_GRID which indicate the y coordinate is on the -#: edge of the cell. -Y_COORD_V_GRID = (11, 19, 28) - -#: Grid codes found in the STASH master which are currently known to be -#: handled correctly. A warning is issued if a grid is found which is not -#: handled. -HANDLED_GRIDS = (1, 2, 3, 4, 5, 26, 29) + X_COORD_U_GRID + Y_COORD_V_GRID - -# REAL constants header names as described by UM documentation paper F3. -# NB. These are zero-based indices as opposed to the one-based indices -# used in F3. -REAL_EW_SPACING = 0 -REAL_NS_SPACING = 1 -REAL_FIRST_LAT = 2 -REAL_FIRST_LON = 3 -REAL_POLE_LAT = 4 -REAL_POLE_LON = 5 - - -class Grid(object): - """ - An abstract class representing the default/file-level grid - definition for a FieldsFile. - - """ - def __init__(self, column_dependent_constants, row_dependent_constants, - real_constants, horiz_grid_type): - """ - Create a Grid from the relevant sections of the FFHeader. - - Args: - - * column_dependent_constants (numpy.ndarray): - The `column_dependent_constants` from a FFHeader. - - * row_dependent_constants (numpy.ndarray): - The `row_dependent_constants` from a FFHeader. - - * real_constants (numpy.ndarray): - The `real_constants` from a FFHeader. - - * horiz_grid_type (integer): - `horiz_grid_type` from a FFHeader. - - """ - self.column_dependent_constants = column_dependent_constants - self.row_dependent_constants = row_dependent_constants - self.ew_spacing = real_constants[REAL_EW_SPACING] - self.ns_spacing = real_constants[REAL_NS_SPACING] - self.first_lat = real_constants[REAL_FIRST_LAT] - self.first_lon = real_constants[REAL_FIRST_LON] - self.pole_lat = real_constants[REAL_POLE_LAT] - self.pole_lon = real_constants[REAL_POLE_LON] - self.horiz_grid_type = horiz_grid_type - - def _x_vectors(self, subgrid): - # Abstract method to return the X vector for the given sub-grid. - raise NotImplementedError() - - def _y_vectors(self, subgrid): - # Abstract method to return the X vector for the given sub-grid. - raise NotImplementedError() - - def regular_x(self, subgrid): - # Abstract method to return BZX, BDX for the given sub-grid. - raise NotImplementedError() - - def regular_y(self, subgrid): - # Abstract method to return BZY, BDY for the given sub-grid. - raise NotImplementedError() - - def vectors(self, subgrid): - """ - Return the X and Y coordinate vectors for the given sub-grid of - this grid. - - Args: - - * subgrid (integer): - A "grid type code" as described in UM documentation paper C4. - - Returns: - A 2-tuple of X-vector, Y-vector. - - """ - x_p, x_u = self._x_vectors() - y_p, y_v = self._y_vectors() - x = x_p - y = y_p - if subgrid in X_COORD_U_GRID: - x = x_u - if subgrid in Y_COORD_V_GRID: - y = y_v - return x, y - - -class ArakawaC(Grid): - """ - An abstract class representing an Arakawa C-grid. - - """ - def _x_vectors(self): - x_p, x_u = None, None - if self.column_dependent_constants is not None: - x_p = self.column_dependent_constants[:, 0] - if self.column_dependent_constants.shape[1] == 2: - # Wrap around for global field - if self.horiz_grid_type == 0: - x_u = self.column_dependent_constants[:-1, 1] - else: - x_u = self.column_dependent_constants[:, 1] - return x_p, x_u - - def regular_x(self, subgrid): - """ - Return the "zeroth" value and step for the X coordinate on the - given sub-grid of this grid. - - Args: - - * subgrid (integer): - A "grid type code" as described in UM documentation paper C4. - - Returns: - A 2-tuple of BZX, BDX. - - """ - bdx = self.ew_spacing - bzx = self.first_lon - bdx - if subgrid in X_COORD_U_GRID: - bzx += 0.5 * bdx - return bzx, bdx - - def regular_y(self, subgrid): - """ - Return the "zeroth" value and step for the Y coordinate on the - given sub-grid of this grid. - - Args: - - * subgrid (integer): - A "grid type code" as described in UM documentation paper C4. - - Returns: - A 2-tuple of BZY, BDY. - - """ - bdy = self.ns_spacing - bzy = self.first_lat - bdy - if subgrid in Y_COORD_V_GRID: - bzy += self._v_offset * bdy - return bzy, bdy - - -class NewDynamics(ArakawaC): - """ - An Arakawa C-grid as used by UM New Dynamics. - - The theta and u points are at the poles. - - """ - - _v_offset = 0.5 - - def _y_vectors(self): - y_p, y_v = None, None - if self.row_dependent_constants is not None: - y_p = self.row_dependent_constants[:, 0] - if self.row_dependent_constants.shape[1] == 2: - y_v = self.row_dependent_constants[:-1, 1] - return y_p, y_v - - -class ENDGame(ArakawaC): - """ - An Arakawa C-grid as used by UM ENDGame. - - The v points are at the poles. - - """ - - _v_offset = -0.5 - - def _y_vectors(self): - y_p, y_v = None, None - if self.row_dependent_constants is not None: - y_p = self.row_dependent_constants[:-1, 0] - if self.row_dependent_constants.shape[1] == 2: - y_v = self.row_dependent_constants[:, 1] - return y_p, y_v - - -class FFHeader(object): - """A class to represent the FIXED_LENGTH_HEADER section of a FieldsFile.""" - - GRID_STAGGERING_CLASS = {3: NewDynamics, 6: ENDGame} - - def __init__(self, filename, word_depth=DEFAULT_FF_WORD_DEPTH): - """ - Create a FieldsFile header instance by reading the - FIXED_LENGTH_HEADER section of the FieldsFile, making the names - defined in FF_HEADER available as attributes of a FFHeader instance. - - Args: - - * filename (string): - Specify the name of the FieldsFile. - - Returns: - FFHeader object. - - """ - - #: File name of the FieldsFile. - self.ff_filename = filename - self._word_depth = word_depth - - # Read the FF header data - with open(filename, 'rb') as ff_file: - # typically 64-bit words (aka. int64 or ">i8") - header_data = np.fromfile(ff_file, - dtype='>i{0}'.format(word_depth), - count=FF_HEADER_DEPTH) - header_data = tuple(header_data) - # Create FF instance attributes - for name, offsets in FF_HEADER: - if len(offsets) == 1: - value = header_data[offsets[0]] - else: - value = header_data[offsets[0]:offsets[-1] + 1] - setattr(self, name, value) - - # Turn the pointer values into real arrays. - for elem in _FF_HEADER_POINTERS: - if elem not in ['data', 'lookup_table']: - if self._attribute_is_pointer_and_needs_addressing(elem): - addr = getattr(self, elem) - ff_file.seek((addr[0] - 1) * word_depth, os.SEEK_SET) - if len(addr) == 2: - res = np.fromfile(ff_file, - dtype='>f{0}'.format(word_depth), - count=addr[1]) - elif len(addr) == 3: - res = np.fromfile(ff_file, - dtype='>f{0}'.format(word_depth), - count=addr[1]*addr[2]) - res = res.reshape((addr[1], addr[2]), order='F') - else: - raise ValueError('ff header element {} is not' - 'handled correctly'.format(elem)) - else: - res = None - setattr(self, elem, res) - - def __str__(self): - attributes = [] - for name, _ in FF_HEADER: - attributes.append(' {}: {}'.format(name, getattr(self, name))) - return 'FF Header:\n' + '\n'.join(attributes) - - def __repr__(self): - return '{}({!r})'.format(type(self).__name__, self.ff_filename) - - def _attribute_is_pointer_and_needs_addressing(self, name): - if name in _FF_HEADER_POINTERS: - attr = getattr(self, name) - - # Check that we haven't already addressed this pointer, - # that the pointer is actually referenceable (i.e. >0) - # and that the attribute is not marked as missing. - is_referenceable = (isinstance(attr, tuple) and - attr[0] > 0 and attr[0] != IMDI) - else: - msg = '{!r} object does not have pointer attribute {!r}' - raise AttributeError(msg.format(self.__class__.__name__, name)) - return is_referenceable - - def shape(self, name): - """ - Return the dimension shape of the FieldsFile FIXED_LENGTH_HEADER - pointer attribute. - - Args: - - * name (string): - Specify the name of the FIXED_LENGTH_HEADER attribute. - - Returns: - Dimension tuple. - - """ - - if name in _FF_HEADER_POINTERS: - value = getattr(self, name)[1:] - else: - msg = '{!r} object does not have pointer address {!r}' - raise AttributeError(msg.format(self.__class_.__name__, name)) - return value - - def grid(self): - """Return the Grid definition for the FieldsFile.""" - grid_class = self.GRID_STAGGERING_CLASS.get(self.grid_staggering) - if grid_class is None: - grid_class = NewDynamics - warnings.warn( - 'Staggered grid type: {} not currently interpreted, assuming ' - 'standard C-grid'.format(self.grid_staggering)) - grid = grid_class(self.column_dependent_constants, - self.row_dependent_constants, - self.real_constants, self.horiz_grid_type) - return grid - - -class FF2PP(object): - """A class to extract the individual PPFields from within a FieldsFile.""" - - def __init__(self, filename, read_data=False, - word_depth=DEFAULT_FF_WORD_DEPTH): - """ - Create a FieldsFile to Post Process instance that returns a generator - of PPFields contained within the FieldsFile. - - Args: - - * filename (string): - Specify the name of the FieldsFile. - - Kwargs: - - * read_data (boolean): - Specify whether to read the associated PPField data within - the FieldsFile. Default value is False. - - Returns: - PPField generator. - - For example:: - - >>> for field in ff.FF2PP(filename): - ... print field - - """ - - self._ff_header = FFHeader(filename, word_depth=word_depth) - self._word_depth = word_depth - self._filename = filename - self._read_data = read_data - - def _payload(self, field): - """Calculate the payload data depth (in bytes) and type.""" - if field.lbpack.n1 == 0: - # Data payload is not packed. - data_depth = (field.lblrec - field.lbext) * self._word_depth - # Determine PP field 64-bit payload datatype. - lookup = _LBUSER_DTYPE_LOOKUP - dtype_template = lookup.get(field.lbuser[0], lookup['default']) - dtype_name = dtype_template.format(word_depth=self._word_depth) - data_type = np.dtype(dtype_name) - else: - # Data payload is packed. - if field.lbpack.n1 == 1: - # Data packed using WGDOS archive method. - data_depth = ((field.lbnrec * 2) - 1) * pp.PP_WORD_DEPTH - elif field.lbpack.n1 == 2: - # Data packed using CRAY 32-bit method. - data_depth = (field.lblrec - field.lbext) * pp.PP_WORD_DEPTH - else: - msg = 'PP fields with LBPACK of {} are not supported.' - raise NotYetImplementedError(msg.format(field.lbpack)) - - # Determine PP field payload datatype. - lookup = pp.LBUSER_DTYPE_LOOKUP - data_type = lookup.get(field.lbuser[0], lookup['default']) - - return data_depth, data_type - - def _det_border(self, field_dim, halo_dim): - # Update field coordinates for a variable resolution LBC file where - # the resolution of the very edge (within the rim width) is assumed to - # be same as the halo. - def range_order(range1, range2, resolution): - # Handles whether increasing/decreasing ranges. - if np.sign(resolution) > 0: - lower = range1 - upper = range2 - else: - upper = range1 - lower = range2 - return lower, upper - - # Ensure that the resolution is the same on both edges. - res_low = np.array([field_dim[1] - field_dim[0]]) - res_high = np.array([field_dim[-1] - field_dim[-2]]) - if not np.allclose(res_low, res_high): - msg = ('The x or y coordinates of your boundary condition field ' - 'may be incorrect, not having taken into account the ' - 'boundary size.') - warnings.warn(msg) - else: - range2 = field_dim[0] - res_low - range1 = field_dim[0] - halo_dim * res_low - lower, upper = range_order(range1, range2, res_low) - extra_before = np.linspace(lower, upper, halo_dim) - - range1 = field_dim[-1] + res_high - range2 = field_dim[-1] + halo_dim * res_high - lower, upper = range_order(range1, range2, res_high) - extra_after = np.linspace(lower, upper, halo_dim) - - field_dim = np.concatenate([extra_before, field_dim, extra_after]) - return field_dim - - def _extract_field(self): - # FF table pointer initialisation based on FF LOOKUP table - # configuration. - - lookup_table = self._ff_header.lookup_table - table_index, table_entry_depth, table_count = lookup_table - table_offset = (table_index - 1) * self._word_depth # in bytes - table_entry_depth = table_entry_depth * self._word_depth # in bytes - # Open the FF for processing. - ff_file = open(self._ff_header.ff_filename, 'rb') - ff_file_seek = ff_file.seek - - # Check for an instantaneous dump. - if self._ff_header.dataset_type == 1: - table_count = self._ff_header.total_prognostic_fields - - is_boundary_packed = self._ff_header.dataset_type == 5 - - grid = self._ff_header.grid() - - # Process each FF LOOKUP table entry. - while table_count: - table_count -= 1 - # Move file pointer to the start of the current FF LOOKUP - # table entry. - ff_file_seek(table_offset, os.SEEK_SET) - # Read the current PP header entry from the FF LOOKUP table. - header_integers = np.fromfile( - ff_file, dtype='>i{0}'.format(self._word_depth), - count=pp.NUM_LONG_HEADERS) - header_floats = np.fromfile( - ff_file, dtype='>f{0}'.format(self._word_depth), - count=pp.NUM_FLOAT_HEADERS) - # In 64-bit words. - header_data = tuple(header_integers) + tuple(header_floats) - # Check whether the current FF LOOKUP table entry is valid. - if header_data[0] == _FF_LOOKUP_TABLE_TERMINATE: - # There are no more FF LOOKUP table entries to read. - break - # Calculate next FF LOOKUP table entry. - table_offset += table_entry_depth - # Construct a PPField object and populate using the header_data - # read from the current FF LOOKUP table. - # (The PPField sub-class will depend on the header release number.) - field = pp.make_pp_field(header_data) - # Calculate start address of the associated PP header data. - data_offset = field.lbegin * self._word_depth - # Determine PP field payload depth and type. - data_depth, data_type = self._payload(field) - - stash_entry = STASH_TRANS.get(str(field.stash), None) - if stash_entry is None: - subgrid = None - warnings.warn('The STASH code {0} was not found in the ' - 'STASH to grid type mapping. Picking the P ' - 'position as the cell type'.format(field.stash)) - else: - subgrid = stash_entry.grid_code - if subgrid not in HANDLED_GRIDS: - warnings.warn('The stash code {} is on a grid {} which ' - 'has not been explicitly handled by the ' - 'fieldsfile loader. Assuming the data is on ' - 'a P grid.'.format(field.stash, subgrid)) - - field.x, field.y = grid.vectors(subgrid) - - # Use the per-file grid if no per-field metadata is available. - no_x = field.bzx in (0, field.bmdi) and field.x is None - no_y = field.bzy in (0, field.bmdi) and field.y is None - if no_x and no_y: - field.bzx, field.bdx = grid.regular_x(subgrid) - field.bzy, field.bdy = grid.regular_y(subgrid) - field.bplat = grid.pole_lat - field.bplon = grid.pole_lon - elif no_x or no_y: - warnings.warn('Partially missing X or Y coordinate values.') - - if is_boundary_packed: - name_mapping = dict(rim_width=slice(4, 6), y_halo=slice(2, 4), - x_halo=slice(0, 2)) - b_packing = pp.SplittableInt(field.lbuser[2], name_mapping) - field.lbpack.boundary_packing = b_packing - # Fix the lbrow and lbnpt to be the actual size of the data - # array, since the field is no longer a "boundary" fields file - # field. - # Note: The documentation states that lbrow (y) doesn't - # contain the halo rows, but no such comment exists at UM v8.5 - # for lbnpt (x). Experimentation has shown that lbnpt also - # excludes the halo size. - field.lbrow += 2 * field.lbpack.boundary_packing.y_halo - field.lbnpt += 2 * field.lbpack.boundary_packing.x_halo - # Update the x and y coordinates for this field. Note: it may - # be that this needs to update x and y also, but that is yet - # to be confirmed. - if (field.bdx in (0, field.bmdi) or - field.bdy in (0, field.bmdi)): - field.x = self._det_border(field.x, b_packing.x_halo) - field.y = self._det_border(field.y, b_packing.y_halo) - else: - if field.bdy < 0: - warnings.warn('The LBC has a bdy less than 0. No ' - 'case has previously been seen of ' - 'this, and the decompression may be ' - 'erroneous.') - field.bzx -= field.bdx * b_packing.x_halo - field.bzy -= field.bdy * b_packing.y_halo - - if self._read_data: - # Read the actual bytes. This can then be converted to a - # numpy array at a higher level. - ff_file_seek(data_offset, os.SEEK_SET) - field._data = pp.LoadedArrayBytes(ff_file.read(data_depth), - data_type) - else: - # Provide enough context to read the data bytes later on. - field._data = pp.DeferredArrayBytes(self._filename, - data_offset, data_depth, - data_type) - yield field - ff_file.close() - - def __iter__(self): - return pp._interpret_fields(self._extract_field()) - - -def load_cubes(filenames, callback): - """ - Loads cubes from a list of fields files filenames. - - Args: - - * filenames - list of fields files filenames to load - - Kwargs: - - * callback - a function which can be passed on to - :func:`iris.io.run_callback` - - .. note:: - - The resultant cubes may not be in the order that they are in the - file (order is not preserved when there is a field with - orography references). - - """ - return pp._load_cubes_variable_loader(filenames, callback, FF2PP) - - -def load_cubes_32bit_ieee(filenames, callback): - """ - Loads cubes from a list of 32bit ieee converted fieldsfiles filenames. - - .. seealso:: - - :func:`load_cubes` for keyword details - - """ - return pp._load_cubes_variable_loader(filenames, callback, FF2PP, - {'word_depth': 4}) diff --git a/lib/iris/fileformats/grib/__init__.py b/lib/iris/fileformats/grib/__init__.py deleted file mode 100644 index ac706bca00..0000000000 --- a/lib/iris/fileformats/grib/__init__.py +++ /dev/null @@ -1,814 +0,0 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -""" -Conversion of cubes to/from GRIB. - -See also: `ECMWF GRIB API `_. - -""" - -import datetime -import math #for fmod -import os -import warnings - -import cartopy -import numpy as np -import numpy.ma as ma -import scipy.interpolate - -import iris.proxy -iris.proxy.apply_proxy('gribapi', globals()) - -from iris.analysis.interpolate import Linear1dExtrapolator -import iris.coord_systems as coord_systems -from iris.exceptions import TranslationError -# NOTE: careful here, to avoid circular imports (as iris imports grib) -from iris.fileformats.grib import grib_phenom_translation as gptx -from iris.fileformats.grib import grib_save_rules -import iris.fileformats.grib.load_rules -import iris.unit - - -__all__ = ['add_load_rules', 'grib_generator', 'load_cubes', - 'reset_load_rules', 'save_grib2', 'GribWrapper', - 'hindcast_workaround'] - - -#: Set this flag to True to enable support of negative forecast periods -#: when loading and saving GRIB files. -hindcast_workaround = False - - -# rules for converting a grib message to a cm cube -_load_rules = None - - -CENTRE_TITLES = {'egrr': 'U.K. Met Office - Exeter', - 'ecmf': 'European Centre for Medium Range Weather Forecasts', - 'rjtd': 'Tokyo, Japan Meteorological Agency', - '55' : 'San Francisco', - 'kwbc': 'US National Weather Service, National Centres for Environmental Prediction'} - -TIME_RANGE_INDICATORS = {0:'none', 1:'none', 3:'time mean', 4:'time sum', - 5:'time _difference', 10:'none', - # TODO #567 Further exploration of the following mappings - 51:'time mean', 113:'time mean', 114:'time sum', - 115:'time mean', 116:'time sum', 117:'time mean', - 118:'time _covariance', 123:'time mean', - 124:'time sum', 125:'time standard_deviation'} - -PROCESSING_TYPES = {0:'time mean', 1:'time sum', 2:'time maximum', 3:'time minimum', - 4:'time _difference', 5:'time _root mean square', - 6:'time standard_deviation', 7:'time _convariance', - 8:'time _difference', 9:'time _ratio'} - -TIME_CODES_EDITION1 = { - 0: ('minutes', 60), - 1: ('hours', 60*60), - 2: ('days', 24*60*60), - # NOTE: do *not* support calendar-dependent units at all. - # So the following possible keys remain unsupported: - # 3: 'months', - # 4: 'years', - # 5: 'decades', - # 6: '30 years', - # 7: 'century', - 10: ('3 hours', 3*60*60), - 11: ('6 hours', 6*60*60), - 12: ('12 hours', 12*60*60), - 13: ('15 minutes', 15*60), - 14: ('30 minutes', 30*60), - 254: ('seconds', 1), -} - -TIME_CODES_EDITION2 = { - 0: ('minutes', 60), - 1: ('hours', 60*60), - 2: ('days', 24*60*60), - # NOTE: do *not* support calendar-dependent units at all. - # So the following possible keys remain unsupported: - # 3: 'months', - # 4: 'years', - # 5: 'decades', - # 6: '30 years', - # 7: 'century', - 10: ('3 hours', 3*60*60), - 11: ('6 hours', 6*60*60), - 12: ('12 hours', 12*60*60), - 13: ('seconds', 1), -} - -unknown_string = "???" - - -def add_load_rules(filename): - """ - Registers a rules file for use during the GRIB load process. - - Registered files are processed after the standard rules, and in the order - they were registered. - - .. deprecated:: 1.5 - - """ - msg = "The 'add_load_rules' function is deprecated." - warnings.warn(msg, UserWarning, stacklevel=2) - - # Uses this module-level variable - global _load_rules - - if _load_rules is None: - _load_rules = iris.fileformats.rules.RulesContainer(filename) - else: - _load_rules.import_rules(filename) - - -def reset_load_rules(): - """Resets the GRIB load process to use only the standard conversion rules.""" - - # Uses this module-level variable - global _load_rules - - _load_rules = None - - -class GribWrapper(object): - """ - Contains a pygrib object plus some extra keys of our own. - - """ - def __init__(self, grib_message): - """Store the grib message and compute our extra keys.""" - self.grib_message = grib_message - - # Initialise the key-extension dictionary. - # NOTE: this attribute *must* exist, or the the __getattr__ overload - # can hit an infinite loop. - self.extra_keys = {} - - self._confirm_in_scope() - - self._compute_extra_keys() - - #this is something pygrib did for us - reshape, - #but it flipped the data - which we don't want - ni = self.Ni - nj = self.Nj - - # set the missing value key to get np.nan where values are missing, - # must be done before values are read from the message - gribapi.grib_set_double(self.grib_message, "missingValue", np.nan) - self.data = self.values - j_fast = gribapi.grib_get_long(grib_message, "jPointsAreConsecutive") - if j_fast == 0: - self.data = self.data.reshape(nj, ni) - else: - self.data = self.data.reshape(ni, nj) - # handle missing values in a sensible way - mask = np.isnan(self.data) - if mask.any(): - self.data = ma.array(self.data, mask=mask) - - def _confirm_in_scope(self): - """Ensure we have a grib flavour that we choose to support.""" - - #forbid alternate row scanning - #(uncommon entry from GRIB2 flag table 3.4, also in GRIB1) - if self.alternativeRowScanning == 1: - raise iris.exceptions.IrisError("alternativeRowScanning == 1 not handled.") - - def __getattr__(self, key): - """Return a grib key, or one of our extra keys.""" - - # is it in the grib message? - try: - # we just get as the type of the "values" array...special case here... - if key in ["values", "pv"]: - res = gribapi.grib_get_double_array(self.grib_message, key) - elif key in ('typeOfFirstFixedSurface','typeOfSecondFixedSurface'): - res = np.int32(gribapi.grib_get_long(self.grib_message, key)) - else: - key_type = gribapi.grib_get_native_type(self.grib_message, key) - if key_type == int: - res = np.int32(gribapi.grib_get_long(self.grib_message, key)) - elif key_type == float: - # Because some computer keys are floats, like - # longitudeOfFirstGridPointInDegrees, a float32 is not always enough... - res = np.float64(gribapi.grib_get_double(self.grib_message, key)) - elif key_type == str: - res = gribapi.grib_get_string(self.grib_message, key) - else: - raise ValueError("Unknown type for %s : %s" % (key, str(key_type))) - except gribapi.GribInternalError: - res = None - - #...or is it in our list of extras? - if res == None: - if key in self.extra_keys: - res = self.extra_keys[key] - else: - #must raise an exception for the hasattr() mechanism to work - raise AttributeError("Cannot find GRIB key %s" % key) - - return res - - def _timeunit_detail(self): - """Return the (string, seconds) describing the message time unit.""" - if self.edition == 1: - code_to_detail = TIME_CODES_EDITION1 - else: - code_to_detail = TIME_CODES_EDITION2 - unit_code = self.indicatorOfUnitOfTimeRange - if unit_code not in code_to_detail: - message = 'Unhandled time unit for forecast ' \ - 'indicatorOfUnitOfTimeRange : ' + str(unit_code) - raise iris.exceptions.NotYetImplementedError(message) - return code_to_detail[unit_code] - - def _timeunit_string(self): - """Get the udunits string for the message time unit.""" - return self._timeunit_detail()[0] - - def _timeunit_seconds(self): - """Get the number of seconds in the message time unit.""" - return self._timeunit_detail()[1] - - def _compute_extra_keys(self): - """Compute our extra keys.""" - global unknown_string - - self.extra_keys = {} - - # work out stuff based on these values from the message - edition = self.edition - - # time-processed forcast time is from reference time to start of period - if edition == 2: - forecastTime = self.forecastTime - - uft = np.uint32(forecastTime) - BILL = 2**30 - - # Workaround grib api's assumption that forecast time is positive. - # Handles correctly encoded -ve forecast times up to one -1 billion. - if hindcast_workaround: - if 2 * BILL < uft < 3 * BILL: - msg = "Re-interpreting negative forecastTime from " \ - + str(forecastTime) - forecastTime = -(uft - 2 * BILL) - msg += " to " + str(forecastTime) - warnings.warn(msg) - - else: - forecastTime = self.startStep - - #regular or rotated grid? - try: - longitudeOfSouthernPoleInDegrees = self.longitudeOfSouthernPoleInDegrees - latitudeOfSouthernPoleInDegrees = self.latitudeOfSouthernPoleInDegrees - except AttributeError: - longitudeOfSouthernPoleInDegrees = 0.0 - latitudeOfSouthernPoleInDegrees = 90.0 - - centre = gribapi.grib_get_string(self.grib_message, "centre") - - - #default values - self.extra_keys = {'_referenceDateTime':-1.0, '_phenomenonDateTime':-1.0, - '_periodStartDateTime':-1.0, '_periodEndDateTime':-1.0, - '_levelTypeName':unknown_string, - '_levelTypeUnits':unknown_string, '_firstLevelTypeName':unknown_string, - '_firstLevelTypeUnits':unknown_string, '_firstLevel':-1.0, - '_secondLevelTypeName':unknown_string, '_secondLevel':-1.0, - '_originatingCentre':unknown_string, - '_forecastTime':None, '_forecastTimeUnit':unknown_string, - '_coord_system':None, '_x_circular':False, - '_x_coord_name':unknown_string, '_y_coord_name':unknown_string, - # These are here to avoid repetition in the rules files, - # and reduce the very long line lengths. - '_x_points':None, '_y_points':None, - '_cf_data':None} - - # cf phenomenon translation - if edition == 1: - # Get centre code (N.B. self.centre has default type = string) - centre_number = gribapi.grib_get_long(self.grib_message, "centre") - # Look for a known grib1-to-cf translation (or None). - cf_data = gptx.grib1_phenom_to_cf_info( - table2_version=self.table2Version, - centre_number=centre_number, - param_number=self.indicatorOfParameter) - self.extra_keys['_cf_data'] = cf_data - elif edition == 2: - # Don't attempt to interpret params if 'master tables version' is - # 255, as local params may then have same codes as standard ones. - if self.tablesVersion != 255: - # Look for a known grib2-to-cf translation (or None). - cf_data = gptx.grib2_phenom_to_cf_info( - param_discipline=self.discipline, - param_category=self.parameterCategory, - param_number=self.parameterNumber) - self.extra_keys['_cf_data'] = cf_data - - #reference date - self.extra_keys['_referenceDateTime'] = \ - datetime.datetime(int(self.year), int(self.month), int(self.day), - int(self.hour), int(self.minute)) - - # forecast time with workarounds - self.extra_keys['_forecastTime'] = forecastTime - - #verification date - processingDone = self._get_processing_done() - #time processed? - if processingDone.startswith("time"): - if self.edition == 1: - validityDate = str(self.validityDate) - validityTime = "{:04}".format(int(self.validityTime)) - endYear = int(validityDate[:4]) - endMonth = int(validityDate[4:6]) - endDay = int(validityDate[6:8]) - endHour = int(validityTime[:2]) - endMinute = int(validityTime[2:4]) - elif self.edition == 2: - endYear = self.yearOfEndOfOverallTimeInterval - endMonth = self.monthOfEndOfOverallTimeInterval - endDay = self.dayOfEndOfOverallTimeInterval - endHour = self.hourOfEndOfOverallTimeInterval - endMinute = self.minuteOfEndOfOverallTimeInterval - - # fixed forecastTime in hours - self.extra_keys['_periodStartDateTime'] = \ - (self.extra_keys['_referenceDateTime'] + - datetime.timedelta(hours=int(forecastTime))) - self.extra_keys['_periodEndDateTime'] = \ - datetime.datetime(endYear, endMonth, endDay, endHour, endMinute) - else: - self.extra_keys['_phenomenonDateTime'] = self._get_verification_date() - - - #originating centre - #TODO #574 Expand to include sub-centre - self.extra_keys['_originatingCentre'] = CENTRE_TITLES.get( - centre, "unknown centre %s" % centre) - - #forecast time unit as a cm string - #TODO #575 Do we want PP or GRIB style forecast delta? - self.extra_keys['_forecastTimeUnit'] = self._timeunit_string() - - - #shape of the earth - - #pre-defined sphere - if self.shapeOfTheEarth == 0: - geoid = coord_systems.GeogCS(semi_major_axis=6367470) - - #custom sphere - elif self.shapeOfTheEarth == 1: - geoid = coord_systems.GeogCS( - self.scaledValueOfRadiusOfSphericalEarth * - 10 ** -self.scaleFactorOfRadiusOfSphericalEarth) - - #IAU65 oblate sphere - elif self.shapeOfTheEarth == 2: - geoid = coord_systems.GeogCS(6378160, inverse_flattening=297.0) - - #custom oblate spheroid (km) - elif self.shapeOfTheEarth == 3: - geoid = coord_systems.GeogCS( - semi_major_axis=self.scaledValueOfEarthMajorAxis * - 10 ** -self.scaleFactorOfEarthMajorAxis * 1000., - semi_minor_axis=self.scaledValueOfEarthMinorAxis * - 10 ** -self.scaleFactorOfEarthMinorAxis * 1000.) - - #IAG-GRS80 oblate spheroid - elif self.shapeOfTheEarth == 4: - geoid = coord_systems.GeogCS(6378137, None, 298.257222101) - - #WGS84 - elif self.shapeOfTheEarth == 5: - geoid = \ - coord_systems.GeogCS(6378137, inverse_flattening=298.257223563) - - #pre-defined sphere - elif self.shapeOfTheEarth == 6: - geoid = coord_systems.GeogCS(6371229) - - #custom oblate spheroid (m) - elif self.shapeOfTheEarth == 7: - geoid = coord_systems.GeogCS( - semi_major_axis=self.scaledValueOfEarthMajorAxis * - 10 ** -self.scaleFactorOfEarthMajorAxis, - semi_minor_axis=self.scaledValueOfEarthMinorAxis * - 10 ** -self.scaleFactorOfEarthMinorAxis) - - elif self.shapeOfTheEarth == 8: - raise ValueError("unhandled shape of earth : grib earth shape = 8") - - else: - raise ValueError("undefined shape of earth") - - gridType = gribapi.grib_get_string(self.grib_message, "gridType") - - if gridType in ["regular_ll", "regular_gg"]: - self.extra_keys['_x_coord_name'] = "longitude" - self.extra_keys['_y_coord_name'] = "latitude" - self.extra_keys['_coord_system'] = geoid - elif gridType == 'rotated_ll': - # TODO: Confirm the translation from angleOfRotation to - # north_pole_lon (usually 0 for both) - self.extra_keys['_x_coord_name'] = "grid_longitude" - self.extra_keys['_y_coord_name'] = "grid_latitude" - southPoleLon = longitudeOfSouthernPoleInDegrees - southPoleLat = latitudeOfSouthernPoleInDegrees - self.extra_keys['_coord_system'] = \ - iris.coord_systems.RotatedGeogCS( - -southPoleLat, - math.fmod(southPoleLon + 180.0, 360.0), - self.angleOfRotation, geoid) - elif gridType == 'polar_stereographic': - self.extra_keys['_x_coord_name'] = "projection_x_coordinate" - self.extra_keys['_y_coord_name'] = "projection_y_coordinate" - - if self.projectionCentreFlag == 0: - pole_lat = 90 - elif self.projectionCentreFlag == 1: - pole_lat = -90 - else: - raise TranslationError("Unhandled projectionCentreFlag") - - # Note: I think the grib api defaults LaDInDegrees to 60 for grib1. - self.extra_keys['_coord_system'] = \ - iris.coord_systems.Stereographic( - pole_lat, self.orientationOfTheGridInDegrees, 0, 0, - self.LaDInDegrees, ellipsoid=geoid) - - elif gridType == 'lambert': - self.extra_keys['_x_coord_name'] = "projection_x_coordinate" - self.extra_keys['_y_coord_name'] = "projection_y_coordinate" - - if self.edition == 1: - flag_name = "projectionCenterFlag" - else: - flag_name = "projectionCentreFlag" - - if getattr(self, flag_name) == 0: - pole_lat = 90 - elif getattr(self, flag_name) == 1: - pole_lat = -90 - else: - raise TranslationError("Unhandled projectionCentreFlag") - - LambertConformal = iris.coord_systems.LambertConformal - self.extra_keys['_coord_system'] = LambertConformal( - self.LaDInDegrees, self.LoVInDegrees, 0, 0, - secant_latitudes=(self.Latin1InDegrees, self.Latin2InDegrees), - ellipsoid=geoid) - else: - raise TranslationError("unhandled grid type: {}".format(gridType)) - - if gridType in ["regular_ll", "rotated_ll"]: - self._regular_longitude_common() - j_step = self.jDirectionIncrementInDegrees - if not self.jScansPositively: - j_step = -j_step - self._y_points = (np.arange(self.Nj, dtype=np.float64) * j_step + - self.latitudeOfFirstGridPointInDegrees) - - elif gridType in ['regular_gg']: - # longitude coordinate is straight-forward - self._regular_longitude_common() - # get the distinct latitudes, and make sure they are sorted - # (south-to-north) and then put them in the right direction - # depending on the scan direction - latitude_points = gribapi.grib_get_double_array( - self.grib_message, 'distinctLatitudes').astype(np.float64) - latitude_points.sort() - if not self.jScansPositively: - # we require latitudes north-to-south - self._y_points = latitude_points[::-1] - else: - self._y_points = latitude_points - - elif gridType in ["polar_stereographic", "lambert"]: - # convert the starting latlon into meters - cartopy_crs = self.extra_keys['_coord_system'].as_cartopy_crs() - x1, y1 = cartopy_crs.transform_point( - self.longitudeOfFirstGridPointInDegrees, - self.latitudeOfFirstGridPointInDegrees, - cartopy.crs.Geodetic()) - - if not np.all(np.isfinite([x1, y1])): - raise TranslationError("Could not determine the first latitude" - " and/or longitude grid point.") - - self._x_points = x1 + self.DxInMetres * np.arange(self.Nx, - dtype=np.float64) - self._y_points = y1 + self.DyInMetres * np.arange(self.Ny, - dtype=np.float64) - - else: - raise TranslationError("unhandled grid type") - - def _regular_longitude_common(self): - """Define a regular longitude dimension.""" - i_step = self.iDirectionIncrementInDegrees - if self.iScansNegatively: - i_step = -i_step - self._x_points = (np.arange(self.Ni, dtype=np.float64) * i_step + - self.longitudeOfFirstGridPointInDegrees) - if "longitude" in self.extra_keys['_x_coord_name'] and self.Ni > 1: - if _longitude_is_cyclic(self._x_points): - self.extra_keys['_x_circular'] = True - - def _get_processing_done(self): - """Determine the type of processing that was done on the data.""" - - processingDone = 'unknown' - edition = self.edition - - #grib1 - if edition == 1: - timeRangeIndicator = self.timeRangeIndicator - processingDone = TIME_RANGE_INDICATORS.get(timeRangeIndicator, - 'time _grib1_process_unknown_%i' % timeRangeIndicator) - - #grib2 - else: - - pdt = self.productDefinitionTemplateNumber - - #pdt 4.0? (standard forecast) - if pdt == 0: - processingDone = 'none' - - #pdt 4.8 or 4.9? (time-processed) - elif pdt in (8, 9): - typeOfStatisticalProcessing = self.typeOfStatisticalProcessing - processingDone = PROCESSING_TYPES.get(typeOfStatisticalProcessing, - 'time _grib2_process_unknown_%i' % typeOfStatisticalProcessing) - - return processingDone - - def _get_verification_date(self): - reference_date_time = self._referenceDateTime - - # calculate start time (edition-dependent) - if self.edition == 1: - time_range_indicator = self.timeRangeIndicator - P1 = self.P1 - P2 = self.P2 - if time_range_indicator == 0: time_diff = P1 #Forecast product valid at reference time + P1 P1>0), or Uninitialized analysis product for reference time (P1=0). Or Image product for reference time (P1=0) - elif time_range_indicator == 1: time_diff = P1 #Initialized analysis product for reference time (P1=0). - elif time_range_indicator == 2: time_diff = (P1 + P2) * 0.5 #Product with a valid time ranging between reference time + P1 and reference time + P2 - elif time_range_indicator == 3: time_diff = (P1 + P2) * 0.5 #Average(reference time + P1 to reference time + P2) - elif time_range_indicator == 4: time_diff = P2 #Accumulation (reference time + P1 to reference time + P2) product considered valid at reference time + P2 - elif time_range_indicator == 5: time_diff = P2 #Difference(reference time + P2 minus reference time + P1) product considered valid at reference time + P2 - elif time_range_indicator == 10: time_diff = P1 * 256 + P2 #P1 occupies octets 19 and 20; product valid at reference time + P1 - elif time_range_indicator == 51: #Climatological Mean Value: multiple year averages of quantities which are themselves means over some period of time (P2) less than a year. The reference time (R) indicates the date and time of the start of a period of time, given by R to R + P2, over which a mean is formed; N indicates the number of such period-means that are averaged together to form the climatological value, assuming that the N period-mean fields are separated by one year. The reference time indicates the start of the N-year climatology. N is given in octets 22-23 of the PDS. If P1 = 0 then the data averaged in the basic interval P2 are assumed to be continuous, i.e., all available data are simply averaged together. If P1 = 1 (the units of time - octet 18, code table 4 - are not relevant here) then the data averaged together in the basic interval P2 are valid only at the time (hour, minute) given in the reference time, for all the days included in the P2 period. The units of P2 are given by the contents of octet 18 and Table 4. - raise TranslationError("unhandled grib1 timeRangeIndicator " - "= 51 (avg of avgs)") - elif time_range_indicator == 113: time_diff = P1 #Average of N forecasts (or initialized analyses); each product has forecast period of P1 (P1=0 for initialized analyses); products have reference times at intervals of P2, beginning at the given reference time. - elif time_range_indicator == 114: time_diff = P1 #Accumulation of N forecasts (or initialized analyses); each product has forecast period of P1 (P1=0 for initialized analyses); products have reference times at intervals of P2, beginning at the given reference time. - elif time_range_indicator == 115: time_diff = P1 #Average of N forecasts, all with the same reference time; the first has a forecast period of P1, the remaining forecasts follow at intervals of P2. - elif time_range_indicator == 116: time_diff = P1 #Accumulation of N forecasts, all with the same reference time; the first has a forecast period of P1, the remaining follow at intervals of P2. - elif time_range_indicator == 117: time_diff = P1 #Average of N forecasts, the first has a period of P1, the subsequent ones have forecast periods reduced from the previous one by an interval of P2; the reference time for the first is given in octets 13-17, the subsequent ones have reference times increased from the previous one by an interval of P2. Thus all the forecasts have the same valid time, given by the initial reference time + P1. - elif time_range_indicator == 118: time_diff = P1 #Temporal variance, or covariance, of N initialized analyses; each product has forecast period P1=0; products have reference times at intervals of P2, beginning at the given reference time. - elif time_range_indicator == 123: time_diff = P1 #Average of N uninitialized analyses, starting at the reference time, at intervals of P2. - elif time_range_indicator == 124: time_diff = P1 #Accumulation of N uninitialized analyses, starting at the reference time, at intervals of P2. - else: - raise TranslationError("unhandled grib1 timeRangeIndicator " - "= %i" % time_range_indicator) - elif self.edition == 2: - time_diff = int(self.stepRange) # gribapi gives us a string! - - else: - raise TranslationError( - "unhandled grib edition = {}".format(self.edition) - ) - - # Get the timeunit interval. - interval_secs = self._timeunit_seconds() - # Multiply by start-offset and convert to a timedelta. - # NOTE: a 'float' conversion is required here, as time_diff may be - # a numpy scalar, which timedelta will not accept. - interval_delta = datetime.timedelta( - seconds=float(time_diff * interval_secs)) - # Return validity_time = (reference_time + start_offset*time_unit). - return reference_date_time + interval_delta - - def phenomenon_points(self, time_unit): - """ - Return the phenomenon time point offset from the epoch time reference - measured in the appropriate time units. - - """ - time_reference = '%s since epoch' % time_unit - return iris.unit.date2num(self._phenomenonDateTime, time_reference, - iris.unit.CALENDAR_GREGORIAN) - - def phenomenon_bounds(self, time_unit): - """ - Return the phenomenon time bound offsets from the epoch time reference - measured in the appropriate time units. - - """ - # TODO #576 Investigate when it's valid to get phenomenon_bounds - time_reference = '%s since epoch' % time_unit - unit = iris.unit.Unit(time_reference, iris.unit.CALENDAR_GREGORIAN) - return [unit.date2num(self._periodStartDateTime), - unit.date2num(self._periodEndDateTime)] - - -def _longitude_is_cyclic(points): - """Work out if a set of longitude points is cyclic.""" - # Is the gap from end to start smaller, or about equal to the max step? - gap = 360.0 - abs(points[-1] - points[0]) - max_step = abs(np.diff(points)).max() - cyclic = False - if gap <= max_step: - cyclic = True - else: - delta = 0.001 - if abs(1.0 - gap / max_step) < delta: - cyclic = True - return cyclic - - -def _is_quasi_regular_grib(grib_message): - """Detect GRIB 'thinned' a.k.a 'reduced' a.k.a 'quasi-regular' grid.""" - reduced_grids = ("reduced_ll", "reduced_gg") - return gribapi.grib_get(grib_message, 'gridType') in reduced_grids - - -def _regularise(grib_message): - """ - Transform a reduced grid to a regular grid using interpolation. - - Uses 1d linear interpolation at constant latitude to make the grid - regular. If the longitude dimension is circular then this is taken - into account by the interpolation. If the longitude dimension is not - circular then extrapolation is allowed to make sure all end regular - grid points get a value. In practice this extrapolation is likely to - be minimal. - - """ - # Make sure to read any missing values as NaN. - gribapi.grib_set_double(grib_message, "missingValue", np.nan) - - # Get full lat/lon/data values, these describe the latitude, longitude - # and data value of *every* point in the grid, they are not 1d monotonic - # coordinates. - lats = gribapi.grib_get_double_array(grib_message, "latitudes") - lons = gribapi.grib_get_double_array(grib_message, "longitudes") - values = gribapi.grib_get_double_array(grib_message, "values") - - # Compute the new longitude coordinate for the regular grid. - new_nx = max(gribapi.grib_get_long_array(grib_message, "pl")) - new_x_step = (max(lons) - min(lons)) / (new_nx - 1) - if gribapi.grib_get_long(grib_message, "iScansNegatively"): - new_x_step *= -1 - new_lons = np.arange(new_nx) * new_x_step + lons[0] - - # Retrieve the distinct latitudes from the GRIB message. GRIBAPI docs - # don't specify if these points are guaranteed to be oriented correctly so - # the safe option is to sort them into ascending (south-to-north) order - # and then reverse the order if necessary. - new_lats = gribapi.grib_get_double_array(grib_message, "distinctLatitudes") - new_lats.sort() - if not gribapi.grib_get_long(grib_message, "jScansPositively"): - new_lats = new_lats[::-1] - ny = new_lats.shape[0] - - # Use 1d linear interpolation along latitude circles to regularise the - # reduced data. - cyclic = _longitude_is_cyclic(new_lons) - new_values = np.empty([ny, new_nx], dtype=values.dtype) - for ilat, lat in enumerate(new_lats): - idx = np.where(lats == lat) - llons = lons[idx] - vvalues = values[idx] - if cyclic: - # For cyclic data we insert dummy points at each end to ensure - # we can interpolate to all output longitudes using pure - # interpolation. - cgap = (360 - llons[-1] - llons[0]) - llons = np.concatenate( - (llons[0:1] - cgap, llons, llons[-1:] + cgap)) - vvalues = np.concatenate( - (vvalues[-1:], vvalues, vvalues[0:1])) - fixed_latitude_interpolator = scipy.interpolate.interp1d( - llons, vvalues) - else: - # Allow extrapolation for non-cyclic data sets to ensure we can - # interpolate to all output longitudes. - fixed_latitude_interpolator = Linear1dExtrapolator( - scipy.interpolate.interp1d(llons, vvalues)) - new_values[ilat] = fixed_latitude_interpolator(new_lons) - new_values = new_values.flatten() - - # Set flags for the regularised data. - if np.isnan(new_values).any(): - # Account for any missing data. - gribapi.grib_set_double(grib_message, "missingValue", np.inf) - gribapi.grib_set(grib_message, "bitmapPresent", 1) - new_values = np.where(np.isnan(new_values), np.inf, new_values) - gribapi.grib_set_long(grib_message, "Nx", int(new_nx)) - gribapi.grib_set_double(grib_message, - "iDirectionIncrementInDegrees", float(new_x_step)) - gribapi.grib_set_double_array(grib_message, "values", new_values) - gribapi.grib_set_long(grib_message, "jPointsAreConsecutive", 0) - gribapi.grib_set_long(grib_message, "PLPresent", 0) - - -def grib_generator(filename): - """Returns a generator of GribWrapper fields from the given filename.""" - with open(filename, 'rb') as grib_file: - while True: - grib_message = gribapi.grib_new_from_file(grib_file) - if grib_message is None: - break - - if _is_quasi_regular_grib(grib_message): - warnings.warn("Regularising GRIB message.") - _regularise(grib_message) - - grib_wrapper = GribWrapper(grib_message) - - yield grib_wrapper - - # finished with the grib message - claimed by the ecmwf c library. - gribapi.grib_release(grib_message) - - -def load_cubes(filenames, callback=None): - """Returns a generator of cubes from the given list of filenames.""" - grib_loader = iris.fileformats.rules.Loader( - grib_generator, {}, iris.fileformats.grib.load_rules.convert, - _load_rules) - return iris.fileformats.rules.load_cubes(filenames, callback, grib_loader) - - -def save_grib2(cube, target, append=False, **kwargs): - """ - Save a cube to a GRIB2 file. - - Args: - - * cube - A :class:`iris.cube.Cube`, :class:`iris.cube.CubeList` or list of cubes. - * target - A filename or open file handle. - - Kwargs: - - * append - Whether to start a new file afresh or add the cube(s) to the end of the file. - Only applicable when target is a filename, not a file handle. - Default is False. - - See also :func:`iris.io.save`. - - """ - - # grib file (this bit is common to the pp and grib savers...) - if isinstance(target, basestring): - grib_file = open(target, "ab" if append else "wb") - elif hasattr(target, "write"): - if hasattr(target, "mode") and "b" not in target.mode: - raise ValueError("Target not binary") - grib_file = target - else: - raise ValueError("Can only save grib to filename or writable") - - # discover the lat and lon coords (this bit is common to the pp and grib savers...) - lat_coords = filter(lambda coord: "latitude" in coord.name(), cube.coords()) - lon_coords = filter(lambda coord: "longitude" in coord.name(), cube.coords()) - if len(lat_coords) != 1 or len(lon_coords) != 1: - raise TranslationError("Did not find one (and only one) " - "latitude or longitude coord") - - # Save each latlon slice2D in the cube - for slice2D in cube.slices([lat_coords[0], lon_coords[0]]): - - # Save this slice to the grib file - grib_message = gribapi.grib_new_from_samples("GRIB2") - grib_save_rules.run(slice2D, grib_message) - gribapi.grib_write(grib_message, grib_file) - gribapi.grib_release(grib_message) - - # (this bit is common to the pp and grib savers...) - if isinstance(target, basestring): - grib_file.close() diff --git a/lib/iris/fileformats/grib/_grib_cf_map.py b/lib/iris/fileformats/grib/_grib_cf_map.py deleted file mode 100644 index 93b16f6117..0000000000 --- a/lib/iris/fileformats/grib/_grib_cf_map.py +++ /dev/null @@ -1,176 +0,0 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -# -# DO NOT EDIT: AUTO-GENERATED -""" -Provides GRIB/CF phenomenon translations. - -""" -from collections import namedtuple - - -CFName = namedtuple('CFName', 'standard_name long_name units') - -DimensionCoordinate = namedtuple('DimensionCoordinate', - 'standard_name units points') - -G1LocalParam = namedtuple('G1LocalParam', 'edition t2version centre iParam') -G2Param = namedtuple('G2Param', 'edition discipline category number') - - -GRIB1_LOCAL_TO_CF_CONSTRAINED = { - G1LocalParam(1, 128, 98, 165): (CFName('x_wind', None, 'm s-1'), DimensionCoordinate('height', 'm', (10,))), - G1LocalParam(1, 128, 98, 166): (CFName('y_wind', None, 'm s-1'), DimensionCoordinate('height', 'm', (10,))), - G1LocalParam(1, 128, 98, 167): (CFName('air_temperature', None, 'K'), DimensionCoordinate('height', 'm', (2,))), - G1LocalParam(1, 128, 98, 168): (CFName('dew_point_temperature', None, 'K'), DimensionCoordinate('height', 'm', (2,))), - } - -GRIB1_LOCAL_TO_CF = { - G1LocalParam(1, 128, 98, 31): CFName('sea_ice_area_fraction', None, '1'), - G1LocalParam(1, 128, 98, 34): CFName('sea_surface_temperature', None, 'K'), - G1LocalParam(1, 128, 98, 59): CFName('atmosphere_specific_convective_available_potential_energy', None, 'J kg-1'), - G1LocalParam(1, 128, 98, 129): CFName('geopotential', None, 'm2 s-2'), - G1LocalParam(1, 128, 98, 130): CFName('air_temperature', None, 'K'), - G1LocalParam(1, 128, 98, 131): CFName('x_wind', None, 'm s-1'), - G1LocalParam(1, 128, 98, 132): CFName('y_wind', None, 'm s-1'), - G1LocalParam(1, 128, 98, 135): CFName('lagrangian_tendency_of_air_pressure', None, 'Pa s-1'), - G1LocalParam(1, 128, 98, 141): CFName('thickness_of_snowfall_amount', None, 'm'), - G1LocalParam(1, 128, 98, 151): CFName('air_pressure_at_sea_level', None, 'Pa'), - G1LocalParam(1, 128, 98, 157): CFName('relative_humidity', None, '%'), - G1LocalParam(1, 128, 98, 164): CFName('cloud_area_fraction', None, '1'), - G1LocalParam(1, 128, 98, 173): CFName('surface_roughness_length', None, 'm'), - G1LocalParam(1, 128, 98, 174): CFName(None, 'grib_physical_atmosphere_albedo', '1'), - G1LocalParam(1, 128, 98, 186): CFName('low_type_cloud_area_fraction', None, '1'), - G1LocalParam(1, 128, 98, 187): CFName('medium_type_cloud_area_fraction', None, '1'), - G1LocalParam(1, 128, 98, 188): CFName('high_type_cloud_area_fraction', None, '1'), - G1LocalParam(1, 128, 98, 235): CFName(None, 'grib_skin_temperature', 'K'), - } - -GRIB2_TO_CF = { - G2Param(2, 0, 0, 0): CFName('air_temperature', None, 'K'), - G2Param(2, 0, 0, 2): CFName('air_potential_temperature', None, 'K'), - G2Param(2, 0, 0, 6): CFName('dew_point_temperature', None, 'K'), - G2Param(2, 0, 0, 17): CFName(None, 'grib_skin_temperature', 'K'), - G2Param(2, 0, 1, 0): CFName('specific_humidity', None, 'kg kg-1'), - G2Param(2, 0, 1, 1): CFName('relative_humidity', None, '%'), - G2Param(2, 0, 1, 3): CFName(None, 'precipitable_water', 'kg m-2'), - G2Param(2, 0, 1, 11): CFName('thickness_of_snowfall_amount', None, 'm'), - G2Param(2, 0, 1, 13): CFName('liquid_water_content_of_surface_snow', None, 'kg m-2'), - G2Param(2, 0, 1, 22): CFName(None, 'cloud_mixing_ratio', 'kg kg-1'), - G2Param(2, 0, 1, 64): CFName('atmosphere_mass_content_of_water_vapor', None, 'kg m-2'), - G2Param(2, 0, 2, 0): CFName('wind_from_direction', None, 'degrees'), - G2Param(2, 0, 2, 1): CFName('wind_speed', None, 'm s-1'), - G2Param(2, 0, 2, 2): CFName('x_wind', None, 'm s-1'), - G2Param(2, 0, 2, 3): CFName('y_wind', None, 'm s-1'), - G2Param(2, 0, 2, 8): CFName('lagrangian_tendency_of_air_pressure', None, 'Pa s-1'), - G2Param(2, 0, 2, 10): CFName('atmosphere_absolute_vorticity', None, 's-1'), - G2Param(2, 0, 3, 0): CFName('air_pressure', None, 'Pa'), - G2Param(2, 0, 3, 1): CFName('air_pressure_at_sea_level', None, 'Pa'), - G2Param(2, 0, 3, 3): CFName(None, 'icao_standard_atmosphere_reference_height', 'm'), - G2Param(2, 0, 3, 4): CFName('geopotential', None, 'm2 s-2'), - G2Param(2, 0, 3, 5): CFName('geopotential_height', None, 'm'), - G2Param(2, 0, 3, 9): CFName('geopotential_height_anomaly', None, 'm'), - G2Param(2, 0, 6, 1): CFName('cloud_area_fraction', None, '%'), - G2Param(2, 0, 6, 3): CFName('low_type_cloud_area_fraction', None, '%'), - G2Param(2, 0, 6, 4): CFName('medium_type_cloud_area_fraction', None, '%'), - G2Param(2, 0, 6, 5): CFName('high_type_cloud_area_fraction', None, '%'), - G2Param(2, 0, 6, 6): CFName('atmosphere_mass_content_of_cloud_liquid_water', None, 'kg m-2'), - G2Param(2, 0, 6, 7): CFName('cloud_area_fraction_in_atmosphere_layer', None, '%'), - G2Param(2, 0, 7, 6): CFName('atmosphere_specific_convective_available_potential_energy', None, 'J kg-1'), - G2Param(2, 0, 7, 7): CFName(None, 'convective_inhibition', 'J kg-1'), - G2Param(2, 0, 7, 8): CFName(None, 'storm_relative_helicity', 'J kg-1'), - G2Param(2, 0, 14, 0): CFName('atmosphere_mole_content_of_ozone', None, 'Dobson'), - G2Param(2, 0, 19, 1): CFName(None, 'grib_physical_atmosphere_albedo', '%'), - G2Param(2, 2, 0, 0): CFName('land_area_fraction', None, '1'), - G2Param(2, 2, 0, 1): CFName('surface_roughness_length', None, 'm'), - G2Param(2, 2, 0, 2): CFName('soil_temperature', None, 'K'), - G2Param(2, 2, 0, 7): CFName('surface_altitude', None, 'm'), - G2Param(2, 10, 2, 0): CFName('sea_ice_area_fraction', None, '1'), - G2Param(2, 10, 3, 0): CFName('sea_surface_temperature', None, 'K'), - } - -CF_CONSTRAINED_TO_GRIB1_LOCAL = { - (CFName('air_temperature', None, 'K'), DimensionCoordinate('height', 'm', (2,))): G1LocalParam(1, 128, 98, 167), - (CFName('dew_point_temperature', None, 'K'), DimensionCoordinate('height', 'm', (2,))): G1LocalParam(1, 128, 98, 168), - (CFName('x_wind', None, 'm s-1'), DimensionCoordinate('height', 'm', (10,))): G1LocalParam(1, 128, 98, 165), - (CFName('y_wind', None, 'm s-1'), DimensionCoordinate('height', 'm', (10,))): G1LocalParam(1, 128, 98, 166), - } - -CF_TO_GRIB1_LOCAL = { - CFName(None, 'grib_physical_atmosphere_albedo', '1'): G1LocalParam(1, 128, 98, 174), - CFName(None, 'grib_skin_temperature', 'K'): G1LocalParam(1, 128, 98, 235), - CFName('air_pressure_at_sea_level', None, 'Pa'): G1LocalParam(1, 128, 98, 151), - CFName('air_temperature', None, 'K'): G1LocalParam(1, 128, 98, 130), - CFName('atmosphere_specific_convective_available_potential_energy', None, 'J kg-1'): G1LocalParam(1, 128, 98, 59), - CFName('cloud_area_fraction', None, '1'): G1LocalParam(1, 128, 98, 164), - CFName('geopotential', None, 'm2 s-2'): G1LocalParam(1, 128, 98, 129), - CFName('high_type_cloud_area_fraction', None, '1'): G1LocalParam(1, 128, 98, 188), - CFName('lagrangian_tendency_of_air_pressure', None, 'Pa s-1'): G1LocalParam(1, 128, 98, 135), - CFName('low_type_cloud_area_fraction', None, '1'): G1LocalParam(1, 128, 98, 186), - CFName('medium_type_cloud_area_fraction', None, '1'): G1LocalParam(1, 128, 98, 187), - CFName('relative_humidity', None, '%'): G1LocalParam(1, 128, 98, 157), - CFName('sea_ice_area_fraction', None, '1'): G1LocalParam(1, 128, 98, 31), - CFName('sea_surface_temperature', None, 'K'): G1LocalParam(1, 128, 98, 34), - CFName('surface_roughness_length', None, 'm'): G1LocalParam(1, 128, 98, 173), - CFName('thickness_of_snowfall_amount', None, 'm'): G1LocalParam(1, 128, 98, 141), - CFName('x_wind', None, 'm s-1'): G1LocalParam(1, 128, 98, 131), - CFName('y_wind', None, 'm s-1'): G1LocalParam(1, 128, 98, 132), - } - -CF_TO_GRIB2 = { - CFName(None, 'cloud_mixing_ratio', 'kg kg-1'): G2Param(2, 0, 1, 22), - CFName(None, 'convective_inhibition', 'J kg-1'): G2Param(2, 0, 7, 7), - CFName(None, 'grib_physical_atmosphere_albedo', '%'): G2Param(2, 0, 19, 1), - CFName(None, 'grib_skin_temperature', 'K'): G2Param(2, 0, 0, 17), - CFName(None, 'icao_standard_atmosphere_reference_height', 'm'): G2Param(2, 0, 3, 3), - CFName(None, 'precipitable_water', 'kg m-2'): G2Param(2, 0, 1, 3), - CFName(None, 'storm_relative_helicity', 'J kg-1'): G2Param(2, 0, 7, 8), - CFName('air_potential_temperature', None, 'K'): G2Param(2, 0, 0, 2), - CFName('air_pressure', None, 'Pa'): G2Param(2, 0, 3, 0), - CFName('air_pressure_at_sea_level', None, 'Pa'): G2Param(2, 0, 3, 1), - CFName('air_temperature', None, 'K'): G2Param(2, 0, 0, 0), - CFName('atmosphere_absolute_vorticity', None, 's-1'): G2Param(2, 0, 2, 10), - CFName('atmosphere_mass_content_of_cloud_liquid_water', None, 'kg m-2'): G2Param(2, 0, 6, 6), - CFName('atmosphere_mass_content_of_water_vapor', None, 'kg m-2'): G2Param(2, 0, 1, 64), - CFName('atmosphere_mole_content_of_ozone', None, 'Dobson'): G2Param(2, 0, 14, 0), - CFName('atmosphere_specific_convective_available_potential_energy', None, 'J kg-1'): G2Param(2, 0, 7, 6), - CFName('cloud_area_fraction', None, '%'): G2Param(2, 0, 6, 1), - CFName('cloud_area_fraction_in_atmosphere_layer', None, '%'): G2Param(2, 0, 6, 7), - CFName('dew_point_temperature', None, 'K'): G2Param(2, 0, 0, 6), - CFName('geopotential', None, 'm2 s-2'): G2Param(2, 0, 3, 4), - CFName('geopotential_height', None, 'm'): G2Param(2, 0, 3, 5), - CFName('geopotential_height_anomaly', None, 'm'): G2Param(2, 0, 3, 9), - CFName('high_type_cloud_area_fraction', None, '%'): G2Param(2, 0, 6, 5), - CFName('lagrangian_tendency_of_air_pressure', None, 'Pa s-1'): G2Param(2, 0, 2, 8), - CFName('land_area_fraction', None, '1'): G2Param(2, 2, 0, 0), - CFName('land_binary_mask', None, '1'): G2Param(2, 2, 0, 0), - CFName('liquid_water_content_of_surface_snow', None, 'kg m-2'): G2Param(2, 0, 1, 13), - CFName('low_type_cloud_area_fraction', None, '%'): G2Param(2, 0, 6, 3), - CFName('medium_type_cloud_area_fraction', None, '%'): G2Param(2, 0, 6, 4), - CFName('relative_humidity', None, '%'): G2Param(2, 0, 1, 1), - CFName('sea_ice_area_fraction', None, '1'): G2Param(2, 10, 2, 0), - CFName('sea_surface_temperature', None, 'K'): G2Param(2, 10, 3, 0), - CFName('soil_temperature', None, 'K'): G2Param(2, 2, 0, 2), - CFName('specific_humidity', None, 'kg kg-1'): G2Param(2, 0, 1, 0), - CFName('surface_altitude', None, 'm'): G2Param(2, 2, 0, 7), - CFName('surface_roughness_length', None, 'm'): G2Param(2, 2, 0, 1), - CFName('thickness_of_snowfall_amount', None, 'm'): G2Param(2, 0, 1, 11), - CFName('wind_from_direction', None, 'degrees'): G2Param(2, 0, 2, 0), - CFName('wind_speed', None, 'm s-1'): G2Param(2, 0, 2, 1), - CFName('x_wind', None, 'm s-1'): G2Param(2, 0, 2, 2), - CFName('y_wind', None, 'm s-1'): G2Param(2, 0, 2, 3), - } diff --git a/lib/iris/fileformats/grib/grib_phenom_translation.py b/lib/iris/fileformats/grib/grib_phenom_translation.py deleted file mode 100644 index 9966558196..0000000000 --- a/lib/iris/fileformats/grib/grib_phenom_translation.py +++ /dev/null @@ -1,330 +0,0 @@ -# (C) British Crown Copyright 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -''' -Provide grib 1 and 2 phenomenon translations to + from CF terms. - -This is done by wrapping '_grib_cf_map.py', -which is in a format provided by the metadata translation project. - -Currently supports only these ones: - -* grib1 --> cf -* grib2 --> cf -* cf --> grib2 - -''' - -import collections -import warnings - -import numpy as np - -from iris.fileformats.grib import _grib_cf_map as grcf -import iris.std_names -import iris.unit - - -class LookupTable(dict): - """ - Specialised dictionary object for making lookup tables. - - Returns None for unknown keys (instead of raising exception). - Raises exception for any attempt to change an existing entry, - (but it is still possible to remove keys) - - """ - def __init__(self, *args, **kwargs): - self._super = super(LookupTable, self) - self._super.__init__(*args, **kwargs) - - def __getitem__(self, key): - if not key in self: - return None - return self._super.__getitem__(key) - - def __setitem__(self, key, value): - if key in self and self[key] is not value: - raise KeyError('Attempted to set dict[{}] = {}, ' - 'but this is already set to {}.'.format( - key, value, self[key])) - self._super.__setitem__(key, value) - - -# Define namedtuples for keys+values of the Grib1 lookup table. - -_Grib1ToCfKeyClass = collections.namedtuple( - 'Grib1CfKey', - ('table2_version', 'centre_number', 'param_number')) - -# NOTE: this form is currently used for both Grib1 *and* Grib2 -_GribToCfDataClass = collections.namedtuple( - 'Grib1CfData', - ('standard_name', 'long_name', 'units', 'set_height')) - - -# Create the grib1-to-cf lookup table. - -def _make_grib1_cf_table(): - """ Build the Grib1 to CF phenomenon translation table. """ - table = LookupTable() - - def _make_grib1_cf_entry(table2_version, centre_number, param_number, - standard_name, long_name, units, set_height=None): - """ - Check data, convert types and create a new _GRIB1_CF_TABLE key/value. - - Note that set_height is an optional parameter. Used to denote - phenomena that imply a height definition (agl), - e.g. "2-metre tempererature". - - """ - grib1_key = _Grib1ToCfKeyClass(table2_version=int(table2_version), - centre_number=int(centre_number), - param_number=int(param_number)) - if standard_name is not None: - if standard_name not in iris.std_names.STD_NAMES: - warnings.warn('{} is not a recognised CF standard name ' - '(skipping).'.format(standard_name)) - return None - # convert units string to iris Unit (i.e. mainly, check it is good) - iris_units = iris.unit.Unit(units) - cf_data = _GribToCfDataClass(standard_name=standard_name, - long_name=long_name, - units=iris_units, - set_height=set_height) - return (grib1_key, cf_data) - - # Interpret the imported Grib1-to-CF table. - for (grib1data, cfdata) in grcf.GRIB1_LOCAL_TO_CF.iteritems(): - assert grib1data.edition == 1 - association_entry = _make_grib1_cf_entry( - table2_version=grib1data.t2version, - centre_number=grib1data.centre, - param_number=grib1data.iParam, - standard_name=cfdata.standard_name, - long_name=cfdata.long_name, - units=cfdata.units) - if association_entry is not None: - key, value = association_entry - table[key] = value - - # Do the same for special Grib1 codes that include an implied height level. - for (grib1data, (cfdata, extra_dimcoord)) \ - in grcf.GRIB1_LOCAL_TO_CF_CONSTRAINED.iteritems(): - assert grib1data.edition == 1 - if extra_dimcoord.standard_name != 'height': - raise ValueError('Got implied dimension coord of "{}", ' - 'currently can only handle "height".'.format( - extra_dimcoord.standard_name)) - if extra_dimcoord.units != 'm': - raise ValueError('Got implied dimension units of "{}", ' - 'currently can only handle "m".'.format( - extra_dimcoord.units)) - if len(extra_dimcoord.points) != 1: - raise ValueError('Implied dimension has {} points, ' - 'currently can only handle 1.'.format( - len(extra_dimcoord.points))) - association_entry = _make_grib1_cf_entry( - table2_version=int(grib1data.t2version), - centre_number=int(grib1data.centre), - param_number=int(grib1data.iParam), - standard_name=cfdata.standard_name, - long_name=cfdata.long_name, - units=cfdata.units, - set_height=extra_dimcoord.points[0]) - if association_entry is not None: - key, value = association_entry - table[key] = value - - return table - - -_GRIB1_CF_TABLE = _make_grib1_cf_table() - - -# Define a namedtuple for the keys of the Grib2 lookup table. - -_Grib2ToCfKeyClass = collections.namedtuple( - 'Grib2CfKey', - ('param_discipline', 'param_category', 'param_number')) - - -# Create the grib2-to-cf lookup table. - -def _make_grib2_to_cf_table(): - """ Build the Grib2 to CF phenomenon translation table. """ - table = LookupTable() - - def _make_grib2_cf_entry(param_discipline, param_category, param_number, - standard_name, long_name, units): - """ - Check data, convert types and make a _GRIB2_CF_TABLE key/value pair. - - Note that set_height is an optional parameter. Used to denote - phenomena that imply a height definition (agl), - e.g. "2-metre tempererature". - - """ - grib2_key = _Grib2ToCfKeyClass(param_discipline=int(param_discipline), - param_category=int(param_category), - param_number=int(param_number)) - if standard_name is not None: - if standard_name not in iris.std_names.STD_NAMES: - warnings.warn('{} is not a recognised CF standard name ' - '(skipping).'.format(standard_name)) - return None - # convert units string to iris Unit (i.e. mainly, check it is good) - iris_units = iris.unit.Unit(units) - cf_data = _GribToCfDataClass(standard_name=standard_name, - long_name=long_name, - units=iris_units, - set_height=None) - return (grib2_key, cf_data) - - # Interpret the grib2 info from grib_cf_map - for grib2data, cfdata in grcf.GRIB2_TO_CF.iteritems(): - assert grib2data.edition == 2 - association_entry = _make_grib2_cf_entry( - param_discipline=grib2data.discipline, - param_category=grib2data.category, - param_number=grib2data.number, - standard_name=cfdata.standard_name, - long_name=cfdata.long_name, - units=cfdata.units) - if association_entry is not None: - key, value = association_entry - table[key] = value - - return table - - -_GRIB2_CF_TABLE = _make_grib2_to_cf_table() - - -# Define namedtuples for key+values of the cf-to-grib2 lookup table. - -_CfToGrib2KeyClass = collections.namedtuple( - 'CfGrib2Key', - ('standard_name', 'long_name')) - -_CfToGrib2DataClass = collections.namedtuple( - 'CfGrib2Data', - ('discipline', 'category', 'number', 'units')) - - -# Create the cf-to-grib2 lookup table. - -def _make_cf_to_grib2_table(): - """ Build the Grib1 to CF phenomenon translation table. """ - table = LookupTable() - - def _make_cf_grib2_entry(standard_name, long_name, - param_discipline, param_category, param_number, - units): - """ - Check data, convert types and make a new _CF_TABLE key/value pair. - - """ - assert standard_name is not None or long_name is not None - if standard_name is not None: - long_name = None - if standard_name not in iris.std_names.STD_NAMES: - warnings.warn('{} is not a recognised CF standard name ' - '(skipping).'.format(standard_name)) - return None - cf_key = _CfToGrib2KeyClass(standard_name, long_name) - # convert units string to iris Unit (i.e. mainly, check it is good) - iris_units = iris.unit.Unit(units) - grib2_data = _CfToGrib2DataClass(discipline=int(param_discipline), - category=int(param_category), - number=int(param_number), - units=iris_units) - return (cf_key, grib2_data) - - # Interpret the imported CF-to-Grib2 table into a lookup table - for cfdata, grib2data in grcf.CF_TO_GRIB2.iteritems(): - assert grib2data.edition == 2 - iris_units = iris.unit.Unit(cfdata.units) - association_entry = _make_cf_grib2_entry( - standard_name=cfdata.standard_name, - long_name=cfdata.long_name, - param_discipline=grib2data.discipline, - param_category=grib2data.category, - param_number=grib2data.number, - units=iris_units) - if association_entry is not None: - key, value = association_entry - table[key] = value - - return table - -_CF_GRIB2_TABLE = _make_cf_to_grib2_table() - - -# Interface functions for translation lookup - -def grib1_phenom_to_cf_info(table2_version, centre_number, param_number): - """ - Lookup grib-1 parameter --> cf_data or None. - - Returned cf_data has attributes: - - * standard_name - * long_name - * units : a :class:`iris.unit.Unit` - * set_height : a scalar 'height' value , or None - - """ - grib1_key = _Grib1ToCfKeyClass(table2_version=table2_version, - centre_number=centre_number, - param_number=param_number) - return _GRIB1_CF_TABLE[grib1_key] - - -def grib2_phenom_to_cf_info(param_discipline, param_category, param_number): - """ - Lookup grib-2 parameter --> cf_data or None. - - Returned cf_data has attributes: - - * standard_name - * long_name - * units : a :class:`iris.unit.Unit` - - """ - grib2_key = _Grib2ToCfKeyClass(param_discipline=int(param_discipline), - param_category=int(param_category), - param_number=int(param_number)) - return _GRIB2_CF_TABLE[grib2_key] - - -def cf_phenom_to_grib2_info(standard_name, long_name=None): - """ - Lookup CF names --> grib2_data or None. - - Returned grib2_data has attributes: - - * discipline - * category - * number - * units : a :class:`iris.unit.Unit` - The unit represents the defined reference units for the message data. - - """ - if standard_name is not None: - long_name = None - return _CF_GRIB2_TABLE[(standard_name, long_name)] diff --git a/lib/iris/fileformats/grib/grib_save_rules.py b/lib/iris/fileformats/grib/grib_save_rules.py deleted file mode 100644 index 05142076dc..0000000000 --- a/lib/iris/fileformats/grib/grib_save_rules.py +++ /dev/null @@ -1,623 +0,0 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . - - -import warnings - -import gribapi -import numpy as np -import numpy.ma as ma - -import iris -import iris.exceptions -import iris.unit -from iris.fileformats.rules import is_regular, regular_step -from iris.fileformats.grib import grib_phenom_translation as gptx - - -def gribbability_check(cube): - "We always need the following things for grib saving." - - # GeogCS exists? - cs0 = cube.coord(dimensions=[0]).coord_system - cs1 = cube.coord(dimensions=[1]).coord_system - if cs0 is None or cs1 is None: - raise iris.exceptions.TranslationError("CoordSystem not present") - if cs0 != cs1: - raise iris.exceptions.TranslationError("Inconsistent CoordSystems") - - # Regular? - y_coord = cube.coord(dimensions=[0]) - x_coord = cube.coord(dimensions=[1]) - if not is_regular(x_coord) or not is_regular(y_coord): - raise iris.exceptions.TranslationError( - "Cannot save irregular grids to grib") - - # Time period exists? - if not cube.coords("time"): - raise iris.exceptions.TranslationError("time coord not found") - - -########################### -### grid template stuff ### -########################### - - -def shape_of_the_earth(cube, grib): - - # assume latlon - cs = cube.coord(dimensions=[0]).coord_system - - # Turn them all missing to start with (255 for byte, -1 for long) - gribapi.grib_set_long(grib, "scaleFactorOfRadiusOfSphericalEarth", 255) - gribapi.grib_set_long(grib, "scaledValueOfRadiusOfSphericalEarth", -1) - gribapi.grib_set_long(grib, "scaleFactorOfEarthMajorAxis", 255) - gribapi.grib_set_long(grib, "scaledValueOfEarthMajorAxis", -1) - gribapi.grib_set_long(grib, "scaleFactorOfEarthMinorAxis", 255) - gribapi.grib_set_long(grib, "scaledValueOfEarthMinorAxis", -1) - - ellipsoid = cs - if isinstance(cs, iris.coord_systems.RotatedGeogCS): - ellipsoid = cs.ellipsoid - - if ellipsoid.inverse_flattening == 0.0: - gribapi.grib_set_long(grib, "shapeOfTheEarth", 1) - gribapi.grib_set_long(grib, "scaleFactorOfRadiusOfSphericalEarth", 0) - gribapi.grib_set_long(grib, "scaledValueOfRadiusOfSphericalEarth", - ellipsoid.semi_major_axis) - else: - gribapi.grib_set_long(grib, "shapeOfTheEarth", 7) - gribapi.grib_set_long(grib, "scaleFactorOfEarthMajorAxis", 0) - gribapi.grib_set_long(grib, "scaledValueOfEarthMajorAxis", - ellipsoid.semi_major_axis) - gribapi.grib_set_long(grib, "scaleFactorOfEarthMinorAxis", 0) - gribapi.grib_set_long(grib, "scaledValueOfEarthMinorAxis", - ellipsoid.semi_minor_axis) - - -def grid_dims(x_coord, y_coord, grib): - gribapi.grib_set_long(grib, "Ni", x_coord.shape[0]) - gribapi.grib_set_long(grib, "Nj", y_coord.shape[0]) - - -def latlon_first_last(x_coord, y_coord, grib): - if x_coord.has_bounds() or y_coord.has_bounds(): - warnings.warn("Ignoring xy bounds") - -# XXX Pending #1125 -# gribapi.grib_set_double(grib, "latitudeOfFirstGridPointInDegrees", -# float(y_coord.points[0])) -# gribapi.grib_set_double(grib, "latitudeOfLastGridPointInDegrees", -# float(y_coord.points[-1])) -# gribapi.grib_set_double(grib, "longitudeOfFirstGridPointInDegrees", -# float(x_coord.points[0])) -# gribapi.grib_set_double(grib, "longitudeOfLastGridPointInDegrees", -# float(x_coord.points[-1])) -# WORKAROUND - gribapi.grib_set_long(grib, "latitudeOfFirstGridPoint", - int(y_coord.points[0]*1000000)) - gribapi.grib_set_long(grib, "latitudeOfLastGridPoint", - int(y_coord.points[-1]*1000000)) - gribapi.grib_set_long(grib, "longitudeOfFirstGridPoint", - int((x_coord.points[0] % 360)*1000000)) - gribapi.grib_set_long(grib, "longitudeOfLastGridPoint", - int((x_coord.points[-1] % 360)*1000000)) - - -def dx_dy(x_coord, y_coord, grib): - x_step = regular_step(x_coord) - y_step = regular_step(y_coord) - # TODO: THIS USED BE "Dx" and "Dy"!!! DID THE API CHANGE AGAIN??? - gribapi.grib_set_double(grib, "DxInDegrees", float(abs(x_step))) - gribapi.grib_set_double(grib, "DyInDegrees", float(abs(y_step))) - - -def scanning_mode_flags(x_coord, y_coord, grib): - gribapi.grib_set_long(grib, "iScansPositively", - int(x_coord.points[1] - x_coord.points[0] > 0)) - gribapi.grib_set_long(grib, "jScansPositively", - int(y_coord.points[1] - y_coord.points[0] > 0)) - - -def latlon_common(cube, grib): - y_coord = cube.coord(dimensions=[0]) - x_coord = cube.coord(dimensions=[1]) - shape_of_the_earth(cube, grib) - grid_dims(x_coord, y_coord, grib) - latlon_first_last(x_coord, y_coord, grib) - dx_dy(x_coord, y_coord, grib) - scanning_mode_flags(x_coord, y_coord, grib) - - -def rotated_pole(cube, grib): - cs = cube.coord(dimensions=[0]).coord_system - -# XXX Pending #1125 -# gribapi.grib_set_double(grib, "latitudeOfSouthernPoleInDegrees", -# float(cs.n_pole.latitude)) -# gribapi.grib_set_double(grib, "longitudeOfSouthernPoleInDegrees", -# float(cs.n_pole.longitude)) -# gribapi.grib_set_double(grib, "angleOfRotationInDegrees", 0) -# WORKAROUND - latitude = -int(cs.grid_north_pole_latitude*1000000) - longitude = int(((cs.grid_north_pole_longitude+180) % 360)*1000000) - gribapi.grib_set_long(grib, "latitudeOfSouthernPole", latitude) - gribapi.grib_set_long(grib, "longitudeOfSouthernPole", longitude) - gribapi.grib_set_long(grib, "angleOfRotation", 0) - - -def grid_template(cube, grib): - cs = cube.coord(dimensions=[0]).coord_system - if isinstance(cs, iris.coord_systems.GeogCS): - # template 3.0 - gribapi.grib_set_long(grib, "gridDefinitionTemplateNumber", 0) - latlon_common(cube, grib) - - # rotated - elif isinstance(cs, iris.coord_systems.RotatedGeogCS): - # template 3.1 - gribapi.grib_set_long(grib, "gridDefinitionTemplateNumber", 1) - latlon_common(cube, grib) - rotated_pole(cube, grib) - else: - raise ValueError("Currently unhandled CoordSystem: %s" % cs) - - -############################## -### product template stuff ### -############################## - - -def param_code(cube, grib): - # NOTE: for now, can match by *either* standard_name or long_name. - # This allows workarounds for data with no identified standard_name. - grib2_info = gptx.cf_phenom_to_grib2_info(cube.standard_name, - cube.long_name) - if grib2_info is not None: - gribapi.grib_set_long(grib, "discipline", - int(grib2_info.discipline)) - gribapi.grib_set_long(grib, "parameterCategory", - int(grib2_info.category)) - gribapi.grib_set_long(grib, "parameterNumber", - int(grib2_info.number)) - else: - gribapi.grib_set_long(grib, "discipline", 255) - gribapi.grib_set_long(grib, "parameterCategory", 255) - gribapi.grib_set_long(grib, "parameterNumber", 255) - warnings.warn('Unable to determine Grib2 parameter code for cube.\n' - 'discipline, parameterCategory and parameterNumber ' - 'have been set to "missing".') - - -def generating_process_type(cube, grib): - # analysis = 0 - # initialisation = 1 - # forecast = 2 - # more... - - # missing - gribapi.grib_set_long(grib, "typeOfGeneratingProcess", 255) - - -def background_process_id(cube, grib): - # locally defined - gribapi.grib_set_long(grib, "backgroundProcess", 255) - - -def generating_process_id(cube, grib): - # locally defined - gribapi.grib_set_long(grib, "generatingProcessIdentifier", 255) - - -def obs_time_after_cutoff(cube, grib): - # nothing stored in iris for this at present - gribapi.grib_set_long(grib, "hoursAfterDataCutoff", 0) - gribapi.grib_set_long(grib, "minutesAfterDataCutoff", 0) - - -def _non_missing_forecast_period(cube): - # Calculate "model start time" to use as the reference time. - fp_coord = cube.coord("forecast_period") - - # Convert fp and t to hours so we can subtract to calculate R. - cf_fp_hrs = fp_coord.units.convert(fp_coord.points[0], 'hours') - t_coord = cube.coord("time").copy() - hours_since = iris.unit.Unit("hours since epoch", - calendar=t_coord.units.calendar) - t_coord.convert_units(hours_since) - - rt_num = t_coord.points[0] - cf_fp_hrs - rt = hours_since.num2date(rt_num) - rt_meaning = 1 # "start of forecast" - - # Forecast period - if fp_coord.has_bounds(): - raise iris.exceptions.TranslationError( - "Bounds not expected for 'forecast_period'") - - if fp_coord.units == iris.unit.Unit("hours"): - grib_time_code = 1 - elif fp_coord.units == iris.unit.Unit("minutes"): - grib_time_code = 0 - elif fp_coord.units == iris.unit.Unit("seconds"): - grib_time_code = 13 - else: - raise iris.exceptions.TranslationError( - "Unexpected units for 'forecast_period' : %s" % fp_coord.units) - - # Convert fp meaning from Iris (R to t) to grib (R to start-of-period) - if not t_coord.has_bounds(): - fp = fp_coord.points[0] - else: - fp = t_coord.bounds[0][0] - rt_num - fp = iris.unit.Unit('hours').convert(fp, fp_coord.units) - - if fp - int(fp): - warnings.warn("forecast_period encoding problem: " - "scaling required.") - fp = int(fp) - - # Turn negative forecast times into grib negative numbers? - from iris.fileformats.grib import hindcast_workaround - if hindcast_workaround and fp < 0: - msg = "Encoding negative forecast period from {} to ".format(fp) - fp = 2**31 + abs(fp) - msg += "{}".format(np.int32(fp)) - warnings.warn(msg) - - return rt, rt_meaning, fp, grib_time_code - - -def _missing_forecast_period(cube): - # We have no way of knowing the CF forecast reference time. - # Set GRIB reference time to "verifying time of forecast", - # and the forecast period to 0h. - warnings.warn('No CF forecast_period. Setting reference time to mean ' - '"verifying time of forecast", "forecast time" = 0h') - - t_coord = cube.coord("time") - t = t_coord.bounds[0, 0] if t_coord.has_bounds() else t_coord.points[0] - rt = t_coord.units.num2date(t) - rt_meaning = 2 # "verification time of forecast" - - fp = 0 - fp_meaning = 1 # hours - - return rt, rt_meaning, fp, fp_meaning - - -def time_range(cube, grib): - """Grib encoding of forecast_period.""" - try: - fp_coord = cube.coord("forecast_period") - except iris.exceptions.CoordinateNotFoundError: - fp_coord = None - - if fp_coord is not None: - _, _, fp, grib_time_code = _non_missing_forecast_period(cube) - else: - _, _, fp, grib_time_code = _missing_forecast_period(cube) - - gribapi.grib_set_long(grib, "indicatorOfUnitOfTimeRange", grib_time_code) - gribapi.grib_set_long(grib, "forecastTime", fp) - - -def hybrid_surfaces(cube, grib): - is_hybrid = False -# XXX Addressed in #1118 pending #1039 for hybrid levels -# -# # hybrid height? (assume points) -# if cube.coords("model_level") and cube.coords("level_height") and \ -# cube.coords("sigma") and \ -# isinstance(cube.coord("sigma").coord_system, -# iris.coord_systems.HybridHeightCS): -# is_hybrid = True -# gribapi.grib_set_long(grib, "typeOfFirstFixedSurface", 118) -# gribapi.grib_set_long(grib, "scaledValueOfFirstFixedSurface", -# long(cube.coord("model_level").points[0])) -# gribapi.grib_set_long(grib, "PVPresent", 1) -# gribapi.grib_set_long(grib, "numberOfVerticalCoordinateValues", 2) -# level_height = cube.coord("level_height").points[0] -# sigma = cube.coord("sigma").points[0] -# gribapi.grib_set_double_array(grib, "pv", [level_height, sigma]) -# -# # hybrid pressure? -# if XXX: -# pass - return is_hybrid - - -def non_hybrid_surfaces(cube, grib): - - # Look for something we can export - v_coord = grib_v_code = output_unit = None - - # pressure - if cube.coords("air_pressure") or cube.coords("pressure"): - grib_v_code = 100 - output_unit = iris.unit.Unit("Pa") - v_coord = (cube.coords("air_pressure") or cube.coords("pressure"))[0] - - # altitude - elif cube.coords("altitude"): - grib_v_code = 102 - output_unit = iris.unit.Unit("m") - v_coord = cube.coord("altitude") - - # height - elif cube.coords("height"): - grib_v_code = 103 - output_unit = iris.unit.Unit("m") - v_coord = cube.coord("height") - - # unknown / absent - else: - # check for *ANY* height coords at all... - v_coords = cube.coords(axis='z') - if v_coords: - # There are vertical coordinate(s), but we don't understand them... - v_coords_str = ' ,'.join(["'{}'".format(c.name()) - for c in v_coords]) - raise iris.exceptions.TranslationError( - 'The vertical-axis coordinate(s) ({}) ' - 'are not recognised or handled.'.format(v_coords_str)) - - # What did we find? - if v_coord is None: - # No vertical coordinate: record as 'surface' level (levelType=1). - # NOTE: may *not* be truly correct, but seems to be common practice. - # Still under investigation : - # See https://github.com/SciTools/iris/issues/519 - gribapi.grib_set_long(grib, "typeOfFirstFixedSurface", 1) - gribapi.grib_set_long(grib, "scaleFactorOfFirstFixedSurface", 0) - gribapi.grib_set_long(grib, "scaledValueOfFirstFixedSurface", 0) - # Set secondary surface = 'missing'. - gribapi.grib_set_long(grib, "typeOfSecondFixedSurface", -1) - gribapi.grib_set_long(grib, "scaleFactorOfSecondFixedSurface", 255) - gribapi.grib_set_long(grib, "scaledValueOfSecondFixedSurface", -1) - elif not v_coord.has_bounds(): - # No second surface - output_v = v_coord.units.convert(v_coord.points[0], output_unit) - if output_v - abs(output_v): - warnings.warn("Vertical level encoding problem: scaling required.") - output_v = int(output_v) - - gribapi.grib_set_long(grib, "typeOfFirstFixedSurface", grib_v_code) - gribapi.grib_set_long(grib, "scaleFactorOfFirstFixedSurface", 0) - gribapi.grib_set_long(grib, "scaledValueOfFirstFixedSurface", output_v) - gribapi.grib_set_long(grib, "typeOfSecondFixedSurface", -1) - gribapi.grib_set_long(grib, "scaleFactorOfSecondFixedSurface", 255) - gribapi.grib_set_long(grib, "scaledValueOfSecondFixedSurface", -1) - else: - # bounded : set lower+upper surfaces - output_v = v_coord.units.convert(v_coord.bounds[0], output_unit) - if output_v[0] - abs(output_v[0]) or output_v[1] - abs(output_v[1]): - warnings.warn("Vertical level encoding problem: scaling required.") - gribapi.grib_set_long(grib, "typeOfFirstFixedSurface", grib_v_code) - gribapi.grib_set_long(grib, "typeOfSecondFixedSurface", grib_v_code) - gribapi.grib_set_long(grib, "scaleFactorOfFirstFixedSurface", 0) - gribapi.grib_set_long(grib, "scaleFactorOfSecondFixedSurface", 0) - gribapi.grib_set_long(grib, "scaledValueOfFirstFixedSurface", - int(output_v[0])) - gribapi.grib_set_long(grib, "scaledValueOfSecondFixedSurface", - int(output_v[1])) - - -def surfaces(cube, grib): - if not hybrid_surfaces(cube, grib): - non_hybrid_surfaces(cube, grib) - - -def product_common(cube, grib): - param_code(cube, grib) - generating_process_type(cube, grib) - background_process_id(cube, grib) - generating_process_id(cube, grib) - obs_time_after_cutoff(cube, grib) - time_range(cube, grib) - surfaces(cube, grib) - - -def type_of_statistical_processing(cube, grib, coord): - """Search for processing over the given coord.""" - stat_code = 255 # (grib code table 4.10) - - # if the last cell method applies only to the given coord... - cell_method = cube.cell_methods[-1] - coord_names = cell_method.coord_names - if len(coord_names) == 1 and coord_names[0] == coord.name(): - stat_codes = {'mean': 0, 'sum': 1, 'maximum': 2, 'minimum': 3, - 'standard_deviation': 6} - stat_code = stat_codes[cell_method.method] - if stat_code == 255: - warnings.warn("Unable to determine type of statistical processing") - gribapi.grib_set_long(grib, "typeOfStatisticalProcessing", stat_code) - - -def time_processing_period(cube, grib): - """ - For template 4.8 (time mean, time max, etc). - - The time range is taken from the 'time' coordinate bounds. - If the cell-method coordinate is not 'time' itself, the type of statistic - will always be 'unknown'. - - """ - # We could probably split this function up a bit - - # Can safely assume bounded pt. - pt_coord = cube.coord("time") - end = iris.unit.num2date(pt_coord.bounds[0, 1], pt_coord.units.name, - pt_coord.units.calendar) - - gribapi.grib_set_long(grib, "yearOfEndOfOverallTimeInterval", end.year) - gribapi.grib_set_long(grib, "monthOfEndOfOverallTimeInterval", end.month) - gribapi.grib_set_long(grib, "dayOfEndOfOverallTimeInterval", end.day) - gribapi.grib_set_long(grib, "hourOfEndOfOverallTimeInterval", end.hour) - gribapi.grib_set_long(grib, "minuteOfEndOfOverallTimeInterval", end.minute) - gribapi.grib_set_long(grib, "secondOfEndOfOverallTimeInterval", end.second) - - gribapi.grib_set_long(grib, "numberOfTimeRange", 1) - gribapi.grib_set_long(grib, "numberOfMissingInStatisticalProcess", 0) - - type_of_statistical_processing(cube, grib, pt_coord) - - # Type of time increment, e.g incrementing fp, incrementing ref - # time, etc. (code table 4.11) - gribapi.grib_set_long(grib, "typeOfTimeIncrement", 255) - # time unit for period over which statistical processing is done (hours) - gribapi.grib_set_long(grib, "indicatorOfUnitForTimeRange", 1) - # period over which statistical processing is done - gribapi.grib_set_long(grib, "lengthOfTimeRange", - float(pt_coord.bounds[0, 1] - pt_coord.bounds[0, 0])) - # time unit between successive source fields (not setting this at present) - gribapi.grib_set_long(grib, "indicatorOfUnitForTimeIncrement", 255) - # between successive source fields (just set to 0 for now) - gribapi.grib_set_long(grib, "timeIncrement", 0) - - -def _cube_is_time_statistic(cube): - """ - Test whether we can identify this cube as a statistic over time. - - At present, accept anything whose latest cell method operates over a single - coordinate that "looks like" a time factor (i.e. some specific names). - In particular, we recognise the coordinate names defined in - :py:mod:`iris.coord_categorisation`. - - """ - # The *only* relevant information is in cell_methods, as coordinates or - # dimensions of aggregation may no longer exist. So it's not possible to - # be definitive, but we handle *some* useful cases. - # In other cases just say "no", which is safe even when not ideal. - - # Identify a single coordinate from the latest cell_method. - if not cube.cell_methods: - return False - latest_coordnames = cube.cell_methods[-1].coord_names - if len(latest_coordnames) != 1: - return False - coord_name = latest_coordnames[0] - - # Define accepted time names, including those from coord_categorisations. - recognised_time_names = ['time', 'year', 'month', 'day', 'weekday', - 'season'] - - # Accept it if the name is recognised. - # Currently does *not* recognise related names like 'month_number' or - # 'years', as that seems potentially unsafe. - return coord_name in recognised_time_names - - -def product_template(cube, grib): - # This will become more complex if we cover more templates, such as 4.15 - - # forecast (template 4.0) - if not cube.coord("time").has_bounds(): - gribapi.grib_set_long(grib, "productDefinitionTemplateNumber", 0) - product_common(cube, grib) - return - - # time processed (template 4.8) - if _cube_is_time_statistic(cube): - gribapi.grib_set_long(grib, "productDefinitionTemplateNumber", 8) - product_common(cube, grib) - time_processing_period(cube, grib) - return - - # Don't know how to handle this kind of data - raise iris.exceptions.TranslationError( - 'A suitable product template could not be deduced') - - -def centre(cube, grib): - # TODO: read centre from cube - gribapi.grib_set_long(grib, "centre", 74) # UKMO - gribapi.grib_set_long(grib, "subCentre", 0) # exeter is not in the spec - - -def reference_time(cube, grib): - # Set the reference time. - # (analysis, forecast start, verify time, obs time, etc) - try: - fp_coord = cube.coord("forecast_period") - except iris.exceptions.CoordinateNotFoundError: - fp_coord = None - - if fp_coord is not None: - rt, rt_meaning, _, _ = _non_missing_forecast_period(cube) - else: - rt, rt_meaning, _, _ = _missing_forecast_period(cube) - - gribapi.grib_set_long(grib, "significanceOfReferenceTime", rt_meaning) - gribapi.grib_set_long( - grib, "dataDate", "%04d%02d%02d" % (rt.year, rt.month, rt.day)) - gribapi.grib_set_long( - grib, "dataTime", "%02d%02d" % (rt.hour, rt.minute)) - - # TODO: Set the calendar, when we find out what happened to the proposal! - # http://tinyurl.com/oefqgv6 - # I was sure it was approved for pre-operational use but it's not there. - - -def identification(cube, grib): - centre(cube, grib) - reference_time(cube, grib) - - # operational product, operational test, research product, etc - # (missing for now) - gribapi.grib_set_long(grib, "productionStatusOfProcessedData", 255) - # analysis, forecast, processed satellite, processed radar, - # (analysis and forecast products for now) - gribapi.grib_set_long(grib, "typeOfProcessedData", 2) - - -def data(cube, grib): - # mdi - if isinstance(cube.data, ma.core.MaskedArray): - gribapi.grib_set(grib, "bitmapPresent", 1) - gribapi.grib_set_double(grib, "missingValue", - float(cube.data.fill_value)) - data = cube.data.filled() - else: - gribapi.grib_set_double(grib, "missingValue", float(-1e9)) - data = cube.data - - # units scaling - grib2_info = gptx.cf_phenom_to_grib2_info(cube.standard_name, - cube.long_name) - if grib2_info is None: - # for now, just allow this - warnings.warn('Unable to determine Grib2 parameter code for cube.\n' - 'Message data may not be correctly scaled.') - else: - if cube.units != grib2_info.units: - data = cube.units.convert(data, grib2_info.units) - - # values - gribapi.grib_set_double_array(grib, "values", data.flatten()) - - # todo: check packing accuracy? - #print "packingError", gribapi.getb_get_double(grib, "packingError") - - -def run(cube, grib): - gribbability_check(cube) - identification(cube, grib) - grid_template(cube, grib) - product_template(cube, grib) - data(cube, grib) diff --git a/lib/iris/fileformats/grib/load_rules.py b/lib/iris/fileformats/grib/load_rules.py deleted file mode 100644 index 8fe3f6031c..0000000000 --- a/lib/iris/fileformats/grib/load_rules.py +++ /dev/null @@ -1,378 +0,0 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . - -# Historically this was auto-generated from -# SciTools/iris-code-generators:tools/gen_rules.py - -import warnings - -import numpy as np - -from iris.aux_factory import HybridHeightFactory, HybridPressureFactory -from iris.coords import AuxCoord, CellMethod, DimCoord -from iris.fileformats.rules import Factory, Reference, ReferenceTarget -from iris.fileformats.um_cf_map import LBFC_TO_CF, STASH_TO_CF -from iris.unit import Unit -import iris.fileformats.pp -import iris.unit - - -def convert(grib): - factories = [] - references = [] - standard_name = None - long_name = None - units = None - attributes = {} - cell_methods = [] - dim_coords_and_dims = [] - aux_coords_and_dims = [] - - if \ - (grib.gridType=="regular_ll") and \ - (grib.jPointsAreConsecutive == 0): - dim_coords_and_dims.append((DimCoord(grib._y_points, grib._y_coord_name, units='degrees', coord_system=grib._coord_system), 0)) - dim_coords_and_dims.append((DimCoord(grib._x_points, grib._x_coord_name, units='degrees', coord_system=grib._coord_system, circular=grib._x_circular), 1)) - - if \ - (grib.gridType=="regular_ll") and \ - (grib.jPointsAreConsecutive == 1): - dim_coords_and_dims.append((DimCoord(grib._y_points, grib._y_coord_name, units='degrees', coord_system=grib._coord_system), 1)) - dim_coords_and_dims.append((DimCoord(grib._x_points, grib._x_coord_name, units='degrees', coord_system=grib._coord_system, circular=grib._x_circular), 0)) - - if \ - (grib.gridType=="regular_gg") and \ - (grib.jPointsAreConsecutive == 0): - dim_coords_and_dims.append((DimCoord(grib._y_points, grib._y_coord_name, units='degrees', coord_system=grib._coord_system), 0)) - dim_coords_and_dims.append((DimCoord(grib._x_points, grib._x_coord_name, units='degrees', coord_system=grib._coord_system, circular=grib._x_circular), 1)) - - if \ - (grib.gridType=="regular_gg") and \ - (grib.jPointsAreConsecutive == 1): - dim_coords_and_dims.append((DimCoord(grib._y_points, grib._y_coord_name, units='degrees', coord_system=grib._coord_system), 1)) - dim_coords_and_dims.append((DimCoord(grib._x_points, grib._x_coord_name, units='degrees', coord_system=grib._coord_system, circular=grib._x_circular), 0)) - - if \ - (grib.gridType=="rotated_ll") and \ - (grib.jPointsAreConsecutive == 0): - dim_coords_and_dims.append((DimCoord(grib._y_points, grib._y_coord_name, units='degrees', coord_system=grib._coord_system), 0)) - dim_coords_and_dims.append((DimCoord(grib._x_points, grib._x_coord_name, units='degrees', coord_system=grib._coord_system, circular=grib._x_circular), 1)) - - if \ - (grib.gridType=="rotated_ll") and \ - (grib.jPointsAreConsecutive == 1): - dim_coords_and_dims.append((DimCoord(grib._y_points, grib._y_coord_name, units='degrees', coord_system=grib._coord_system), 1)) - dim_coords_and_dims.append((DimCoord(grib._x_points, grib._x_coord_name, units='degrees', coord_system=grib._coord_system, circular=grib._x_circular), 0)) - - if grib.gridType in ["polar_stereographic", "lambert"]: - dim_coords_and_dims.append((DimCoord(grib._y_points, grib._y_coord_name, units="m", coord_system=grib._coord_system), 0)) - dim_coords_and_dims.append((DimCoord(grib._x_points, grib._x_coord_name, units="m", coord_system=grib._coord_system), 1)) - - if \ - (grib.edition == 1) and \ - (grib.table2Version < 128) and \ - (grib.indicatorOfParameter == 11) and \ - (grib._cf_data is None): - standard_name = "air_temperature" - units = "kelvin" - - if \ - (grib.edition == 1) and \ - (grib.table2Version < 128) and \ - (grib.indicatorOfParameter == 33) and \ - (grib._cf_data is None): - standard_name = "x_wind" - units = "m s-1" - - if \ - (grib.edition == 1) and \ - (grib.table2Version < 128) and \ - (grib.indicatorOfParameter == 34) and \ - (grib._cf_data is None): - standard_name = "y_wind" - units = "m s-1" - - if \ - (grib.edition == 1) and \ - (grib._cf_data is not None): - standard_name = grib._cf_data.standard_name - long_name = grib._cf_data.standard_name or grib._cf_data.long_name - units = grib._cf_data.units - - if \ - (grib.edition == 1) and \ - (grib.table2Version >= 128) and \ - (grib._cf_data is None): - long_name = "UNKNOWN LOCAL PARAM " + str(grib.indicatorOfParameter) + "." + str(grib.table2Version) - units = "???" - - if \ - (grib.edition == 1) and \ - (grib.table2Version == 1) and \ - (grib.indicatorOfParameter >= 128): - long_name = "UNKNOWN LOCAL PARAM " + str(grib.indicatorOfParameter) + "." + str(grib.table2Version) - units = "???" - - if \ - (grib.edition == 2) and \ - (grib._cf_data is not None): - standard_name = grib._cf_data.standard_name - long_name = grib._cf_data.long_name - units = grib._cf_data.units - - if \ - (grib.edition == 1) and \ - (grib._phenomenonDateTime != -1.0): - aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None)) - aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_points('hours'), standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None)) - - if \ - (grib.edition == 1) and \ - (grib.timeRangeIndicator == 3): - aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None)) - aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'), standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None)) - cell_methods.append(CellMethod("mean", coords="time")) - - if \ - (grib.edition == 1) and \ - (grib.timeRangeIndicator == 4): - aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None)) - aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'), standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None)) - cell_methods.append(CellMethod("sum", coords="time")) - - if \ - (grib.edition == 1) and \ - (grib.timeRangeIndicator == 5): - aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None)) - aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'), standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None)) - cell_methods.append(CellMethod("_difference", coords="time")) - - if \ - (grib.edition == 1) and \ - (grib.timeRangeIndicator == 51): - aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None)) - aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'), standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None)) - cell_methods.append(CellMethod("mean", coords="time")) - - if \ - (grib.edition == 1) and \ - (grib.timeRangeIndicator == 113): - aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None)) - aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'), standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None)) - cell_methods.append(CellMethod("mean", coords="time")) - - if \ - (grib.edition == 1) and \ - (grib.timeRangeIndicator == 114): - aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None)) - aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'), standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None)) - cell_methods.append(CellMethod("sum", coords="time")) - - if \ - (grib.edition == 1) and \ - (grib.timeRangeIndicator == 115): - aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None)) - aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'), standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None)) - cell_methods.append(CellMethod("mean", coords="time")) - - if \ - (grib.edition == 1) and \ - (grib.timeRangeIndicator == 116): - aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None)) - aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'), standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None)) - cell_methods.append(CellMethod("sum", coords="time")) - - if \ - (grib.edition == 1) and \ - (grib.timeRangeIndicator == 117): - aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None)) - aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'), standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None)) - cell_methods.append(CellMethod("mean", coords="time")) - - if \ - (grib.edition == 1) and \ - (grib.timeRangeIndicator == 118): - aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None)) - aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'), standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None)) - cell_methods.append(CellMethod("_covariance", coords="time")) - - if \ - (grib.edition == 1) and \ - (grib.timeRangeIndicator == 123): - aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None)) - aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'), standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None)) - cell_methods.append(CellMethod("mean", coords="time")) - - if \ - (grib.edition == 1) and \ - (grib.timeRangeIndicator == 124): - aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None)) - aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'), standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None)) - cell_methods.append(CellMethod("sum", coords="time")) - - if \ - (grib.edition == 1) and \ - (grib.timeRangeIndicator == 125): - aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None)) - aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'), standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None)) - cell_methods.append(CellMethod("standard_deviation", coords="time")) - - if \ - (grib.edition == 2) and \ - (grib.productDefinitionTemplateNumber == 0): - aux_coords_and_dims.append((DimCoord(points=Unit(grib._forecastTimeUnit).convert(np.int32(grib._forecastTime), "hours"), standard_name='forecast_period', units="hours"), None)) - aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_points('hours'), standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None)) - - if \ - (grib.edition == 2) and \ - (grib.productDefinitionTemplateNumber in (8, 9)): - aux_coords_and_dims.append((DimCoord(points=Unit(grib._forecastTimeUnit).convert(np.int32(grib._forecastTime), "hours"), standard_name='forecast_period', units="hours"), None)) - aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN), bounds=grib.phenomenon_bounds('hours')), None)) - - if \ - (grib.edition == 2) and \ - (grib.productDefinitionTemplateNumber == 8) and \ - (grib.typeOfStatisticalProcessing == 0): - cell_methods.append(CellMethod("mean", coords="time")) - - if \ - (grib.edition == 2) and \ - (grib.productDefinitionTemplateNumber == 8) and \ - (grib.typeOfStatisticalProcessing == 1): - cell_methods.append(CellMethod("sum", coords="time")) - - if \ - (grib.edition == 2) and \ - (grib.productDefinitionTemplateNumber == 8) and \ - (grib.typeOfStatisticalProcessing == 2): - cell_methods.append(CellMethod("maximum", coords="time")) - - if \ - (grib.edition == 2) and \ - (grib.productDefinitionTemplateNumber == 8) and \ - (grib.typeOfStatisticalProcessing == 3): - cell_methods.append(CellMethod("minimum", coords="time")) - - if \ - (grib.edition == 2) and \ - (grib.productDefinitionTemplateNumber == 8) and \ - (grib.typeOfStatisticalProcessing == 4): - cell_methods.append(CellMethod("_difference", coords="time")) - - if \ - (grib.edition == 2) and \ - (grib.productDefinitionTemplateNumber == 8) and \ - (grib.typeOfStatisticalProcessing == 5): - cell_methods.append(CellMethod("_root_mean_square", coords="time")) - - if \ - (grib.edition == 2) and \ - (grib.productDefinitionTemplateNumber == 8) and \ - (grib.typeOfStatisticalProcessing == 6): - cell_methods.append(CellMethod("standard_deviation", coords="time")) - - if \ - (grib.edition == 2) and \ - (grib.productDefinitionTemplateNumber == 8) and \ - (grib.typeOfStatisticalProcessing == 7): - cell_methods.append(CellMethod("_convariance", coords="time")) - - if \ - (grib.edition == 2) and \ - (grib.productDefinitionTemplateNumber == 8) and \ - (grib.typeOfStatisticalProcessing == 8): - cell_methods.append(CellMethod("_difference", coords="time")) - - if \ - (grib.edition == 2) and \ - (grib.productDefinitionTemplateNumber == 8) and \ - (grib.typeOfStatisticalProcessing == 9): - cell_methods.append(CellMethod("_ratio", coords="time")) - - if \ - (grib.edition == 1) and \ - (grib.levelType == 'pl'): - aux_coords_and_dims.append((DimCoord(points=grib.level, long_name="pressure", units="hPa"), None)) - - if \ - (grib.edition == 1) and \ - (grib.levelType == 'sfc') and \ - (grib._cf_data is not None) and \ - (grib._cf_data.set_height is not None): - aux_coords_and_dims.append((DimCoord(points=grib._cf_data.set_height, long_name="height", units="m", attributes={'positive':'up'}), None)) - - - if \ - (grib.edition == 2) and \ - (grib.typeOfFirstFixedSurface != grib.typeOfSecondFixedSurface): - warnings.warn("Different vertical bound types not yet handled.") - - if \ - (grib.edition == 2) and \ - (grib.typeOfFirstFixedSurface == 103) and \ - (grib.typeOfSecondFixedSurface == 255): - aux_coords_and_dims.append((DimCoord(points=grib.scaledValueOfFirstFixedSurface/(10.0**grib.scaleFactorOfFirstFixedSurface), standard_name="height", units="m"), None)) - - if \ - (grib.edition == 2) and \ - (grib.typeOfFirstFixedSurface == 103) and \ - (grib.typeOfSecondFixedSurface != 255): - aux_coords_and_dims.append((DimCoord(points=0.5*(grib.scaledValueOfFirstFixedSurface/(10.0**grib.scaleFactorOfFirstFixedSurface) + grib.scaledValueOfSecondFixedSurface/(10.0**grib.scaleFactorOfSecondFixedSurface)), standard_name="height", units="m", bounds=[grib.scaledValueOfFirstFixedSurface/(10.0**grib.scaleFactorOfFirstFixedSurface) , grib.scaledValueOfSecondFixedSurface/(10.0**grib.scaleFactorOfSecondFixedSurface)]), None)) - - if \ - (grib.edition == 2) and \ - (grib.typeOfFirstFixedSurface == 100) and \ - (grib.typeOfSecondFixedSurface == 255): - aux_coords_and_dims.append((DimCoord(points=grib.scaledValueOfFirstFixedSurface/(10.0**grib.scaleFactorOfFirstFixedSurface), long_name="pressure", units="Pa"), None)) - - if \ - (grib.edition == 2) and \ - (grib.typeOfFirstFixedSurface == 100) and \ - (grib.typeOfSecondFixedSurface != 255): - aux_coords_and_dims.append((DimCoord(points=0.5*(grib.scaledValueOfFirstFixedSurface/(10.0**grib.scaleFactorOfFirstFixedSurface) + grib.scaledValueOfSecondFixedSurface/(10.0**grib.scaleFactorOfSecondFixedSurface)), long_name="pressure", units="Pa", bounds=[grib.scaledValueOfFirstFixedSurface/(10.0**grib.scaleFactorOfFirstFixedSurface) , grib.scaledValueOfSecondFixedSurface/(10.0**grib.scaleFactorOfSecondFixedSurface)]), None)) - - if \ - (grib.edition == 2) and \ - (grib.typeOfFirstFixedSurface in [105, 119]) and \ - (grib.numberOfCoordinatesValues > 0): - aux_coords_and_dims.append((AuxCoord(grib.scaledValueOfFirstFixedSurface, standard_name='model_level_number', attributes={'positive': 'up'}), None)) - aux_coords_and_dims.append((DimCoord(grib.pv[grib.scaledValueOfFirstFixedSurface], long_name='level_pressure', units='Pa'), None)) - aux_coords_and_dims.append((AuxCoord(grib.pv[grib.numberOfCoordinatesValues/2 + grib.scaledValueOfFirstFixedSurface], long_name='sigma'), None)) - factories.append(Factory(HybridPressureFactory, [{'long_name': 'level_pressure'}, {'long_name': 'sigma'}, Reference('surface_air_pressure')])) - - if grib._originatingCentre != 'unknown': - aux_coords_and_dims.append((AuxCoord(points=grib._originatingCentre, long_name='originating_centre', units='no_unit'), None)) - - if \ - (grib.edition == 2) and \ - (grib.productDefinitionTemplateNumber == 1): - aux_coords_and_dims.append((DimCoord(points=grib.perturbationNumber, long_name='ensemble_member', units='no_unit'), None)) - - if grib.productDefinitionTemplateNumber not in (0, 8): - attributes["GRIB_LOAD_WARNING"] = ("unsupported GRIB%d ProductDefinitionTemplate: #4.%d" % (grib.edition, grib.productDefinitionTemplateNumber)) - - if \ - (grib.edition == 2) and \ - (grib.centre == 'ecmf') and \ - (grib.discipline == 0) and \ - (grib.parameterCategory == 3) and \ - (grib.parameterNumber == 25) and \ - (grib.typeOfFirstFixedSurface == 105): - references.append(ReferenceTarget('surface_air_pressure', lambda cube: {'standard_name': 'surface_air_pressure', 'units': 'Pa', 'data': np.exp(cube.data)})) - - return (factories, references, standard_name, long_name, units, attributes, - cell_methods, dim_coords_and_dims, aux_coords_and_dims) diff --git a/lib/iris/fileformats/name.py b/lib/iris/fileformats/name.py index 952220a200..e35e8034f8 100644 --- a/lib/iris/fileformats/name.py +++ b/lib/iris/fileformats/name.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2016, Met Office # # This file is part of Iris. # @@ -16,6 +16,10 @@ # along with Iris. If not, see . """Provides NAME file format loading capabilities.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + import iris.io @@ -34,13 +38,17 @@ def _get_NAME_loader(filename): header = name_loaders.read_header(file_handle) # Infer file type based on contents of header. - if 'Run name' in header: + if 'Run name' in header and 'Output format' not in header: if 'X grid origin' not in header: load = name_loaders.load_NAMEIII_trajectory elif header.get('X grid origin') is not None: load = name_loaders.load_NAMEIII_field else: load = name_loaders.load_NAMEIII_timeseries + + elif 'Output format' in header: + load = name_loaders.load_NAMEIII_version2 + elif 'Title' in header: if 'Number of series' in header: load = name_loaders.load_NAMEII_timeseries @@ -73,7 +81,7 @@ def load_cubes(filenames, callback): A generator of :class:`iris.cubes.Cube` instances. """ - if isinstance(filenames, basestring): + if isinstance(filenames, six.string_types): filenames = [filenames] for filename in filenames: diff --git a/lib/iris/fileformats/name_loaders.py b/lib/iris/fileformats/name_loaders.py index 87e0752f80..eb61bba836 100644 --- a/lib/iris/fileformats/name_loaders.py +++ b/lib/iris/fileformats/name_loaders.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -16,23 +16,30 @@ # along with Iris. If not, see . """NAME file format loading functions.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + import collections import datetime -from itertools import izip import re import warnings +import cf_units import numpy as np from iris.coords import AuxCoord, DimCoord, CellMethod import iris.coord_systems import iris.cube from iris.exceptions import TranslationError -import iris.unit +import iris.util + +from operator import itemgetter EARTH_RADIUS = 6371229.0 NAMEIII_DATETIME_FORMAT = '%d/%m/%Y %H:%M %Z' +NAMETRAJ_DATETIME_FORMAT = '%d/%m/%Y %H:%M:%S %Z' NAMEII_FIELD_DATETIME_FORMAT = '%H%M%Z %d/%m/%Y' NAMEII_TIMESERIES_DATETIME_FORMAT = '%d/%m/%Y %H:%M:%S' @@ -48,7 +55,7 @@ def _split_name_and_units(name): split = name.rsplit("(", 1) try_units = split[1].replace(")", "").strip() try: - try_units = iris.unit.Unit(try_units) + try_units = cf_units.Unit(try_units) except ValueError: pass else: @@ -72,10 +79,12 @@ def read_header(file_handle): """ header = {} - header['NAME Version'] = file_handle.next().strip() + header['NAME Version'] = next(file_handle).strip() for line in file_handle: words = line.split(':', 1) if len(words) != 2: + if 'Forward' in line or 'Backward' in line: + header['Trajectory direction'] = words[0].strip() break key, value = [word.strip() for word in words] header[key] = value @@ -128,25 +137,29 @@ def _read_data_arrays(file_handle, n_arrays, shape): return data_arrays -def _build_lat_lon_for_NAME_field(header): +def _build_lat_lon_for_NAME_field(header, dimindex, x_or_y, + coord_names=['longitude', 'latitude']): """ Return regular latitude and longitude coordinates extracted from the provided header dictionary. - """ - start = header['X grid origin'] - step = header['X grid resolution'] - count = header['X grid size'] - pts = start + np.arange(count, dtype=np.float64) * step - lon = NAMECoord(name='longitude', dimension=1, values=pts) - - start = header['Y grid origin'] - step = header['Y grid resolution'] - count = header['Y grid size'] - pts = start + np.arange(count, dtype=np.float64) * step - lat = NAMECoord(name='latitude', dimension=0, values=pts) - return lat, lon + if x_or_y == 'X': + start = header['X grid origin'] + step = header['X grid resolution'] + count = header['X grid size'] + pts = start + np.arange(count, dtype=np.float64) * step + lat_lon = NAMECoord(name=coord_names[0], + dimension=dimindex, values=pts) + else: + start = header['Y grid origin'] + step = header['Y grid resolution'] + count = header['Y grid size'] + pts = start + np.arange(count, dtype=np.float64) * step + lat_lon = NAMECoord(name=coord_names[1], + dimension=dimindex, values=pts) + + return lat_lon def _build_lat_lon_for_NAME_timeseries(column_headings): @@ -189,19 +202,22 @@ def _calc_integration_period(time_avgs): """ integration_periods = [] pattern = re.compile( - r'(\d{0,2})(day)?\s*(\d{1,2})(hr)?\s*(\d{1,2})(min)?\s*(\w*)') + r'\s*(\d{1,2}day)?\s*(\d{1,2}hr)?\s*(\d{1,2}min)?\s*(\w*)\s*') for time_str in time_avgs: days = 0 hours = 0 minutes = 0 matches = pattern.search(time_str) if matches: - if len(matches.group(1)) > 0: - days = float(matches.group(1)) - if len(matches.group(3)) > 0: - hours = float(matches.group(3)) - if len(matches.group(1)) > 0: - minutes = float(matches.group(5)) + _days = matches.group(1) + if _days is not None and len(_days) > 0: + days = float(_days.rstrip('day')) + _hours = matches.group(2) + if _hours is not None and len(_hours) > 0: + hours = float(_hours.rstrip('hr')) + _minutes = matches.group(3) + if _minutes is not None and len(_minutes) > 0: + minutes = float(_minutes.rstrip('min')) total_hours = days * 24.0 + hours + minutes / 60.0 integration_periods.append(datetime.timedelta(hours=total_hours)) return integration_periods @@ -209,7 +225,7 @@ def _calc_integration_period(time_avgs): def _parse_units(units): """ - Return a known :class:`iris.unit.Unit` given a NAME unit + Return a known :class:`cf_units.Unit` given a NAME unit .. note:: @@ -225,7 +241,7 @@ def _parse_units(units): NAME units. Returns: - An instance of :class:`iris.unit.Unit`. + An instance of :class:`cf_units.Unit`. """ @@ -249,15 +265,15 @@ def _parse_units(units): units = units.replace('mcBq', 'uBq') units = units.replace('mcg', 'ug') try: - units = iris.unit.Unit(units) + units = cf_units.Unit(units) except ValueError: warnings.warn('Unknown units: {!r}'.format(units)) - units = iris.unit.Unit(None) + units = cf_units.Unit(None) return units -def _cf_height_from_name(z_coord): +def _cf_height_from_name(z_coord, lower_bound=None, upper_bound=None): """ Parser for the z component of field headings. @@ -297,7 +313,7 @@ def _cf_height_from_name(z_coord): # NAMEIII - integer/float support. # Match scalar against height agl, asl, Pa, FL pattern_scalar = re.compile(r'Z\s*=\s*' - '(?P[0-9]+(\.[0-9]+)?)' + '(?P[0-9]+(\.[0-9]+)?([eE][+-]?\d+)?)' '\s*(?Pm\s*agl|m\s*asl|FL|Pa)' '(?P.*)') @@ -310,6 +326,11 @@ def _cf_height_from_name(z_coord): bounds = None standard_name = None long_name = 'z' + + if upper_bound is not None and lower_bound is not None: + match_ub = pattern_scalar.match(upper_bound) + match_lb = pattern_scalar.match(lower_bound) + for pattern in patterns: match = pattern.match(z_coord) if match: @@ -323,6 +344,9 @@ def _cf_height_from_name(z_coord): # Interpret points if present. if 'point' in match: points = float(match['point']) + if upper_bound is not None and lower_bound is not None: + bounds = np.array([float(match_lb.groupdict()['point']), + float(match_ub.groupdict()['point'])]) # Interpret points from bounds. else: bounds = np.array([float(match['lower_bound']), @@ -330,9 +354,14 @@ def _cf_height_from_name(z_coord): points = bounds.sum() / 2. long_name = None - if name in ['height', 'altitude']: + if name == 'altitude': + units = units[0] + standard_name = name + long_name = 'altitude above sea level' + elif name == 'height': units = units[0] standard_name = name + long_name = 'height above ground level' elif name == 'air_pressure': standard_name = name elif name == 'flight_level': @@ -359,8 +388,7 @@ def _generate_cubes(header, column_headings, coords, data_arrays, # Turn the dictionary of column headings with a list of header # information for each field into a dictionary of headings for # just this field. - field_headings = {k: v[i] for k, v in - column_headings.iteritems()} + field_headings = {k: v[i] for k, v in six.iteritems(column_headings)} # Make a cube. cube = iris.cube.Cube(data_array) @@ -374,34 +402,72 @@ def _generate_cubes(header, column_headings, coords, data_arrays, # Some units are not in SI units, are missing spaces or typed # in the wrong case. _parse_units returns units that are # recognised by Iris. - cube.units = _parse_units(field_headings['Unit']) + cube.units = _parse_units(field_headings['Units']) # Define and add the singular coordinates of the field (flight # level, time etc.) - z_coord = _cf_height_from_name(field_headings['Z']) - cube.add_aux_coord(z_coord) + if 'Z' in field_headings: + upper_bound, = [field_headings['... to [Z]'] + if '... to [Z]' in field_headings else None] + lower_bound, = [field_headings['... from [Z]'] + if '... from [Z]' in field_headings else None] + z_coord = _cf_height_from_name(field_headings['Z'], + upper_bound=upper_bound, + lower_bound=lower_bound) + cube.add_aux_coord(z_coord) # Define the time unit and use it to serialise the datetime for # the time coordinate. - time_unit = iris.unit.Unit( - 'hours since epoch', calendar=iris.unit.CALENDAR_GREGORIAN) + time_unit = cf_units.Unit( + 'hours since epoch', calendar=cf_units.CALENDAR_GREGORIAN) - # Build time, latitude and longitude coordinates. + # Build time, height, latitude and longitude coordinates. for coord in coords: pts = coord.values coord_sys = None if coord.name == 'latitude' or coord.name == 'longitude': coord_units = 'degrees' coord_sys = iris.coord_systems.GeogCS(EARTH_RADIUS) + if coord.name == 'projection_x_coordinate' \ + or coord.name == 'projection_y_coordinate': + coord_units = 'm' + coord_sys = iris.coord_systems.OSGB() + if coord.name == 'height': + coord_units = 'm' + long_name = 'height above ground level' + pts = coord.values + if coord.name == 'altitude': + coord_units = 'm' + long_name = 'altitude above sea level' + pts = coord.values + if coord.name == 'air_pressure': + coord_units = 'Pa' + pts = coord.values + if coord.name == 'flight_level': + pts = coord.values + long_name = 'flight_level' + coord_units = _parse_units('FL') if coord.name == 'time': coord_units = time_unit pts = time_unit.date2num(coord.values) if coord.dimension is not None: - icoord = DimCoord(points=pts, - standard_name=coord.name, - units=coord_units, - coord_system=coord_sys) + if coord.name == 'longitude': + circular = iris.util._is_circular(pts, 360.0) + else: + circular = False + if coord.name == 'flight_level': + icoord = DimCoord(points=pts, + units=coord_units, + long_name=long_name,) + else: + icoord = DimCoord(points=pts, + standard_name=coord.name, + units=coord_units, + coord_system=coord_sys, + circular=circular) + if coord.name == 'height' or coord.name == 'altitude': + icoord.long_name = long_name if coord.name == 'time' and 'Av or Int period' in \ field_headings: dt = coord.values - \ @@ -427,19 +493,24 @@ def _generate_cubes(header, column_headings, coords, data_arrays, cube.add_aux_coord(icoord) # Headings/column headings which are encoded elsewhere. - headings = ['X', 'Y', 'Z', 'Time', 'Unit', 'Av or Int period', + headings = ['X', 'Y', 'Z', 'Time', 'T', 'Units', + 'Av or Int period', + '... from [Z]', '... to [Z]', 'X grid origin', 'Y grid origin', 'X grid size', 'Y grid size', - 'X grid resolution', 'Y grid resolution', ] + 'X grid resolution', 'Y grid resolution', + 'Number of field cols', 'Number of preliminary cols', + 'Number of fields', 'Number of series', + 'Output format', ] # Add the Main Headings as attributes. - for key, value in header.iteritems(): + for key, value in six.iteritems(header): if value is not None and value != '' and \ key not in headings: cube.attributes[key] = value # Add the Column Headings as attributes - for key, value in field_headings.iteritems(): + for key, value in six.iteritems(field_headings): if value is not None and value != '' and \ key not in headings: cube.attributes[key] = value @@ -450,16 +521,41 @@ def _generate_cubes(header, column_headings, coords, data_arrays, yield cube -def _build_cell_methods(av_or_ints): +def _build_cell_methods(av_or_ints, coord): + """ + Return a list of :class:`iris.coords.CellMethod` instances + based on the provided list of column heading entries and the + associated coordinate. If a given entry does not correspond to a cell + method (e.g. "No time averaging"), a value of None is inserted. + + Args: + + * av_or_ints (iterable of strings): + An iterable of strings containing the colummn heading entries + to be parsed. + * coord (string or :class:`iris.coords.Coord`): + The coordinate name (or :class:`iris.coords.Coord` instance) + to which the column heading entries refer. + + Returns: + A list that is the same length as `av_or_ints` containing + :class:`iris.coords.CellMethod` instances or values of None. + + """ cell_methods = [] + no_avg_pattern = re.compile(r'^(no( (.* )?averaging)?)?$', re.IGNORECASE) for av_or_int in av_or_ints: - if 'average' in av_or_int or 'averaged' in av_or_int: - method = 'mean' + if no_avg_pattern.search(av_or_int) is not None: + cell_method = None + elif 'average' in av_or_int or 'averaged' in av_or_int: + cell_method = CellMethod('mean', coord) elif 'integral' in av_or_int or 'integrated' in av_or_int: - method = 'sum' + cell_method = CellMethod('sum', coord) else: - raise TranslationError("Unhandled time statistic") - cell_methods.append(CellMethod(method, 'time')) + cell_method = None + msg = 'Unknown {} statistic: {!r}. Unable to create cell method.' + warnings.warn(msg.format(coord, av_or_int)) + cell_methods.append(cell_method) return cell_methods @@ -478,7 +574,7 @@ def load_NAMEIII_field(filename): """ # Loading a file gives a generator of lines which can be progressed using - # the next() method. This will come in handy as we wish to progress + # the next() function. This will come in handy as we wish to progress # through the file line by line. with open(filename, 'r') as file_handle: # Create a dictionary which can hold the header metadata about this @@ -486,21 +582,30 @@ def load_NAMEIII_field(filename): header = read_header(file_handle) # Skip the next line (contains the word Fields:) in the file. - file_handle.next() + next(file_handle) # Read the lines of column definitions. # In this version a fixed order of column headings is assumed (and # first 4 columns are ignored). column_headings = {} for column_header_name in ['Species Category', 'Name', 'Quantity', - 'Species', 'Unit', 'Sources', 'Ensemble Av', + 'Species', 'Units', 'Sources', + 'Ensemble Av', 'Time Av or Int', 'Horizontal Av or Int', 'Vertical Av or Int', 'Prob Perc', 'Prob Perc Ens', 'Prob Perc Time', 'Time', 'Z', 'D']: - cols = [col.strip() for col in file_handle.next().split(',')] + cols = [col.strip() for col in next(file_handle).split(',')] column_headings[column_header_name] = cols[4:-1] + # Read in the column titles to determine the coordinate system + col_titles = next(file_handle).split(',') + if 'National Grid' in col_titles[2]: + coord_names = ['projection_x_coordinate', + 'projection_y_coordinate'] + else: + coord_names = ['longitude', 'latitude'] + # Convert the time to python datetimes. new_time_column_header = [] for i, t in enumerate(column_headings['Time']): @@ -516,16 +621,17 @@ def load_NAMEIII_field(filename): tdim = NAMECoord(name='time', dimension=None, values=np.array(column_headings['Time'])) - cell_methods = _build_cell_methods(column_headings['Time Av or Int']) + cell_methods = _build_cell_methods(column_headings['Time Av or Int'], + tdim.name) # Build regular latitude and longitude coordinates. - lat, lon = _build_lat_lon_for_NAME_field(header) + lon = _build_lat_lon_for_NAME_field(header, 1, 'X', + coord_names=coord_names) + lat = _build_lat_lon_for_NAME_field(header, 0, 'Y', + coord_names=coord_names) coords = [lon, lat, tdim] - # Skip the line after the column headings. - file_handle.next() - # Create data arrays to hold the data for each column. n_arrays = header['Number of field cols'] shape = (header['Y grid size'], header['X grid size']) @@ -567,8 +673,8 @@ def load_NAMEII_field(filename): column_headings = {} for column_header_name in ['Species Category', 'Species', 'Time Av or Int', 'Quantity', - 'Unit', 'Z', 'Time']: - cols = [col.strip() for col in file_handle.next().split(',')] + 'Units', 'Z', 'Time']: + cols = [col.strip() for col in next(file_handle).split(',')] column_headings[column_header_name] = cols[4:-1] # Convert the time to python datetimes @@ -594,15 +700,17 @@ def load_NAMEII_field(filename): tdim = NAMECoord(name='time', dimension=None, values=np.array(column_headings['Time'])) - cell_methods = _build_cell_methods(column_headings['Time Av or Int']) + cell_methods = _build_cell_methods(column_headings['Time Av or Int'], + tdim.name) # Build regular latitude and longitude coordinates. - lat, lon = _build_lat_lon_for_NAME_field(header) + lon = _build_lat_lon_for_NAME_field(header, 1, 'X') + lat = _build_lat_lon_for_NAME_field(header, 0, 'Y') coords = [lon, lat, tdim] # Skip the blank line after the column headings. - file_handle.next() + next(file_handle) # Create data arrays to hold the data for each column. n_arrays = header['Number of fields'] @@ -633,17 +741,17 @@ def load_NAMEIII_timeseries(filename): header = read_header(file_handle) # skip the next line (contains the word Fields:) in the file. - file_handle.next() + next(file_handle) # Read the lines of column definitions - currently hardwired column_headings = {} for column_header_name in ['Species Category', 'Name', 'Quantity', - 'Species', 'Unit', 'Sources', 'Ens Av', + 'Species', 'Units', 'Sources', 'Ens Av', 'Time Av or Int', 'Horizontal Av or Int', 'Vertical Av or Int', 'Prob Perc', 'Prob Perc Ens', 'Prob Perc Time', 'Location', 'X', 'Y', 'Z', 'D']: - cols = [col.strip() for col in file_handle.next().split(',')] + cols = [col.strip() for col in next(file_handle).split(',')] column_headings[column_header_name] = cols[1:-1] # Determine the coordinates of the data and store in namedtuples. @@ -656,7 +764,7 @@ def load_NAMEIII_timeseries(filename): column_headings['Time Av or Int']) # Skip the line after the column headings. - file_handle.next() + next(file_handle) # Make a list of data lists to hold the data for each column. data_lists = [[] for i in range(header['Number of field cols'])] @@ -710,8 +818,8 @@ def load_NAMEII_timeseries(filename): column_headings = {} for column_header_name in ['Y', 'X', 'Location', 'Species Category', 'Species', - 'Quantity', 'Z', 'Unit']: - cols = [col.strip() for col in file_handle.next().split(',')] + 'Quantity', 'Z', 'Units']: + cols = [col.strip() for col in next(file_handle).split(',')] column_headings[column_header_name] = cols[1:-1] # Determine the coordinates of the data and store in namedtuples. @@ -720,7 +828,7 @@ def load_NAMEII_timeseries(filename): lat, lon = _build_lat_lon_for_NAME_timeseries(column_headings) # Skip the blank line after the column headings. - file_handle.next() + next(file_handle) # Make a list of data arrays to hold the data for each column. data_lists = [[] for i in range(header['Number of series'])] @@ -752,6 +860,222 @@ def load_NAMEII_timeseries(filename): return _generate_cubes(header, column_headings, coords, data_arrays) +def load_NAMEIII_version2(filename): + """ + Load a NAME III version 2 file returning a + generator of :class:`iris.cube.Cube` instances. + + Args: + + * filename (string): + Name of file to load. + + Returns: + A generator :class:`iris.cube.Cube` instances. + + """ + + # loading a file gives a generator of lines which can be progressed + # using the next() method. This will come in handy as we wish to + # progress through the file line by line. + with open(filename, 'r') as file_handle: + + # define a dictionary to hold the header metadata about this file + header = read_header(file_handle) + + # Skip next line which contains (Fields:) + next(file_handle) + + # Now carry on and read column headers + column_headings = {} + datacol1 = header['Number of preliminary cols'] + for line in file_handle: + + data = [col.strip() for col in line.split(',')][:-1] + + # If first column is not zero we have reached the end + # of the headers + if data[0] != "": + break + + column_key = data[datacol1 - 1].strip(':') + + # This will filter out any zero columns + if filter(None, data[datacol1:]): + column_headings[column_key] = data[datacol1:] + + # Some tidying up + if 'T' in column_headings: + new_time_column_header = [] + for i, t in enumerate(column_headings['T']): + dt = datetime.datetime.strptime(t, NAMEIII_DATETIME_FORMAT) + new_time_column_header.append(dt) + column_headings['T'] = new_time_column_header + + # Convert averaging/integrating period to timedeltas. + column_headings['Av or Int period'] = _calc_integration_period( + column_headings['Time av/int info']) + + # Next we need to figure out what we have in the preliminary columns + # For X and Y we want the index + # And the values can be extracted from the header information + xindex = None + yindex = None + dim_coords = [] + + # First determine whether we are using National Grid or lat/lon + if 'X (UK National Grid (m))' in data: + coord_names = ['projection_x_coordinate', + 'projection_y_coordinate'] + else: + coord_names = ['longitude', 'latitude'] + + if 'Y Index' in data: + yindex = data.index('Y Index') + dim_coords.append('Y') + lat = _build_lat_lon_for_NAME_field(header, + dim_coords.index('Y'), + 'Y', + coord_names=coord_names) + if 'X Index' in data: + xindex = data.index('X Index') + dim_coords.append('X') + lon = _build_lat_lon_for_NAME_field(header, + dim_coords.index('X'), + 'X', + coord_names=coord_names) + + # For all other variables we need the values (note that for Z the units + # will also be given in the column header) + tindex = None + zindex = None + if 'T' in data: + tindex = data.index('T') + dim_coords.append('T') + + if 'Z' in line: + zgrid = [item for item in data if item[0:3] == 'Z ('] + zunits = zgrid[0].split('(')[1].strip(')') + if zunits == 'm asl': + z_name = 'altitude' + elif zunits == 'm agl': + z_name = 'height' + elif zunits == 'FL': + z_name = 'flight_level' + elif zunits == 'Pa': + z_name = 'air_pressure' + else: + ValueError('Vertical coordinate unkown') + zindex = data.index(zgrid[0]) + dim_coords.append('Z') + + # Make a list of data lists to hold the data + # for each column.(aimed at T-Z data) + data_lists = [[] for i in range(header['Number of field cols'])] + coord_lists = [[] for i in + range(header['Number of preliminary cols']-1)] + + # Iterate over the remaining lines which represent the data in a + # column form. + for line in file_handle: + # Split the line by comma, removing the last empty column caused + # by the trailing comma. + vals = line.split(',')[:-1] + + # Time is stored in the column labelled T index + if tindex is not None: + t = vals[tindex].strip() + dt = datetime.datetime.strptime(t, NAMEIII_DATETIME_FORMAT) + coord_lists[dim_coords.index('T')].append(dt) + + # Z is stored in the column labelled ZIndex + if zindex is not None: + z = vals[zindex].strip() + coord_lists[dim_coords.index('Z')].append(float(z)) + + # For X and Y we are extracting indices not values + if yindex is not None: + yind = vals[yindex].strip() + coord_lists[dim_coords.index('Y')].append(int(yind)-1) + if xindex is not None: + xind = vals[xindex].strip() + coord_lists[dim_coords.index('X')].append(int(xind)-1) + + # Populate the data arrays. + for i, data_list in enumerate(data_lists): + data_list.append(float(vals[i + datacol1])) + + data_arrays = [np.array(l) for l in data_lists] + + # Convert Z and T arrays into arrays of indices + zind = [] + if zindex is not None: + z_array = np.array(coord_lists[dim_coords.index('Z')]) + z_unique = sorted(list(set(coord_lists[dim_coords.index('Z')]))) + z_coord = NAMECoord(name=z_name, dimension=dim_coords.index('Z'), + values=z_unique) + for z in z_array: + zind.append(z_unique.index(z)) + coord_lists[dim_coords.index('Z')] = zind + + tind = [] + if tindex is not None: + time_array = np.array(coord_lists[dim_coords.index('T')]) + t_unique = sorted(list(set(coord_lists[dim_coords.index('T')]))) + time = NAMECoord(name='time', dimension=dim_coords.index('T'), + values=np.array(t_unique)) + for t in time_array: + tind.append(t_unique.index(t)) + coord_lists[dim_coords.index('T')] = tind + + # Now determine the shape of the multidimensional array to store + # the data in based on the length of the coordinates + array_shape_list = [] + coords = [] + for cname in dim_coords: + if cname == 'X': + coords.append(lon) + array_shape_list.append(len(lon.values)) + elif cname == 'Y': + coords.append(lat) + array_shape_list.append(len(lat.values)) + elif cname == 'Z': + coords.append(z_coord) + array_shape_list.append(len(z_coord.values)) + elif cname == 'T': + coords.append(time) + array_shape_list.append(len(time.values)) + array_shape = np.array(array_shape_list) + + # Reshape the data to the new multidimensional shape + new_data_arrays = [] + for data_array in data_arrays: + new_data_array = np.zeros(array_shape, dtype=np.float32) + for ind1, item in enumerate(data_array): + index_list = [] + for column, dcoord in enumerate(dim_coords): + index_list.append(coord_lists[column][ind1]) + index_array = np.array(index_list) + mindex = np.ravel_multi_index(index_array, array_shape) + new_data_array[np.unravel_index(mindex, array_shape)] = item + new_data_arrays.append(new_data_array) + + # If X and Y are in the column headings build coordinates + if 'X' in column_headings and 'Y' in column_headings: + lat, lon = _build_lat_lon_for_NAME_timeseries(column_headings) + coords.append(lat) + coords.append(lon) + + # If time is in the column heading build a coordinate + if 'T' in column_headings: + tdim = NAMECoord(name='time', dimension=None, + values=np.array(column_headings['T'])) + coords.append(tdim) + + return _generate_cubes(header, column_headings, coords, new_data_arrays, + cell_methods=None) + + def load_NAMEIII_trajectory(filename): """ Load a NAME III trajectory file returning a @@ -766,8 +1090,8 @@ def load_NAMEIII_trajectory(filename): A generator :class:`iris.cube.Cube` instances. """ - time_unit = iris.unit.Unit('hours since epoch', - calendar=iris.unit.CALENDAR_GREGORIAN) + time_unit = cf_units.Unit('hours since epoch', + calendar=cf_units.CALENDAR_GREGORIAN) with open(filename, 'r') as infile: header = read_header(infile) @@ -784,8 +1108,7 @@ def load_NAMEIII_trajectory(filename): values = [v.strip() for v in line.split(",")] for c, v in enumerate(values): if "UTC" in v: - v = v.replace(":00 ", " ") # Strip out milliseconds. - v = datetime.datetime.strptime(v, NAMEIII_DATETIME_FORMAT) + v = datetime.datetime.strptime(v, NAMETRAJ_DATETIME_FORMAT) else: try: v = float(v) @@ -793,6 +1116,11 @@ def load_NAMEIII_trajectory(filename): pass columns[c].append(v) + # Sort columns according to PP Index + columns_t = list(map(list, zip(*columns))) + columns_t.sort(key=itemgetter(1)) + columns = list(map(list, zip(*columns_t))) + # Where's the Z column? z_column = None for i, heading in enumerate(headings): @@ -800,11 +1128,11 @@ def load_NAMEIII_trajectory(filename): z_column = i break if z_column is None: - raise iris.exceptions.TranslationError("Expected a Z column") + raise TranslationError("Expected a Z column") # Every column up to Z becomes a coordinate. coords = [] - for name, values in izip(headings[:z_column+1], columns[:z_column+1]): + for name, values in zip(headings[:z_column+1], columns[:z_column+1]): values = np.array(values) if np.all(np.array(values) == values[0]): values = [values[0]] @@ -822,18 +1150,28 @@ def load_NAMEIII_trajectory(filename): name = "latitude" units = "degrees" elif name == "Z (m asl)": - name = "height" + name = "altitude" + units = "m" + long_name = "altitude above sea level" + elif name == "Z (m agl)": + name = 'height' units = "m" + long_name = "height above ground level" + elif name == "Z (FL)": + name = "flight_level" + long_name = name try: coord = DimCoord(values, units=units) except ValueError: coord = AuxCoord(values, units=units) coord.rename(name) + if coord.long_name is None and long_name is not None: + coord.long_name = long_name coords.append(coord) # Every numerical column after the Z becomes a cube. - for name, values in izip(headings[z_column+1:], columns[z_column+1:]): + for name, values in zip(headings[z_column+1:], columns[z_column+1:]): try: float(values[0]) except ValueError: @@ -842,9 +1180,17 @@ def load_NAMEIII_trajectory(filename): name, units = _split_name_and_units(name) cube = iris.cube.Cube(values, units=units) cube.rename(name) + # Add the Main Headings as attributes. + for key, value in six.iteritems(header): + if value is not None and value != '' and \ + key not in headings: + cube.attributes[key] = value + # Add coordinates for coord in coords: dim = 0 if len(coord.points) > 1 else None - if isinstance(coord, DimCoord) and coord.name() == "time": + if dim == 0 and coord.name() == "time": + cube.add_dim_coord(coord.copy(), dim) + elif dim == 0 and coord.name() == 'PP Index': cube.add_dim_coord(coord.copy(), dim) else: cube.add_aux_coord(coord.copy(), dim) diff --git a/lib/iris/fileformats/netcdf.py b/lib/iris/fileformats/netcdf.py index 8352d9d81c..8c965ef1a5 100644 --- a/lib/iris/fileformats/netcdf.py +++ b/lib/iris/fileformats/netcdf.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -24,21 +24,31 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +from six.moves import zip_longest # Previous line may not be tampered with! +import six + import collections -import itertools +from itertools import repeat import os import os.path +import re import string import warnings -import biggus -import iris.proxy -iris.proxy.apply_proxy('netCDF4', globals()) +import dask.array as da +import netCDF4 import numpy as np import numpy.ma as ma from pyke import knowledge_engine +from iris._deprecation import warn_deprecated import iris.analysis +from iris.aux_factory import HybridHeightFactory, HybridPressureFactory, \ + OceanSigmaZFactory, OceanSigmaFactory, OceanSFactory, OceanSg1Factory, \ + OceanSg2Factory +import iris.config import iris.coord_systems import iris.coords import iris.cube @@ -46,9 +56,8 @@ import iris.fileformats.cf import iris.fileformats._pyke_rules import iris.io -import iris.unit import iris.util - +from iris._lazy_data import as_lazy_data # Show Pyke inference engine statistics. DEBUG = False @@ -63,6 +72,9 @@ # Pass through CF attributes: # - comment # - Conventions +# - flag_masks +# - flag_meanings +# - flag_values # - history # - institution # - reference @@ -72,32 +84,179 @@ # _CF_ATTRS = ['add_offset', 'ancillary_variables', 'axis', 'bounds', 'calendar', 'cell_measures', 'cell_methods', 'climatology', 'compress', - 'coordinates', '_FillValue', 'flag_masks', 'flag_meanings', - 'flag_values', 'formula_terms', 'grid_mapping', 'leap_month', - 'leap_year', 'long_name', 'missing_value', 'month_lengths', - 'scale_factor', 'standard_error_multiplier', - 'standard_name', 'units', 'valid_max', 'valid_min', 'valid_range'] + 'coordinates', '_FillValue', 'formula_terms', 'grid_mapping', + 'leap_month', 'leap_year', 'long_name', 'missing_value', + 'month_lengths', 'scale_factor', 'standard_error_multiplier', + 'standard_name', 'units'] # CF attributes that should not be global. _CF_DATA_ATTRS = ['flag_masks', 'flag_meanings', 'flag_values', - 'instance_dimension', 'sample_dimension', + 'instance_dimension', 'missing_value', 'sample_dimension', 'standard_error_multiplier'] # CF attributes that should only be global. _CF_GLOBAL_ATTRS = ['conventions', 'featureType', 'history', 'title'] # UKMO specific attributes that should not be global. -_UKMO_DATA_ATTRS = ['STASH', 'ukmo__um_stash_source', 'ukmo__process_flags'] +_UKMO_DATA_ATTRS = ['STASH', 'um_stash_source', 'ukmo__process_flags'] -_CF_CONVENTIONS_VERSION = 'CF-1.5' +CF_CONVENTIONS_VERSION = 'CF-1.5' _FactoryDefn = collections.namedtuple('_FactoryDefn', ('primary', 'std_name', 'formula_terms_format')) _FACTORY_DEFNS = { - iris.aux_factory.HybridHeightFactory: _FactoryDefn( + HybridHeightFactory: _FactoryDefn( primary='delta', std_name='atmosphere_hybrid_height_coordinate', - formula_terms_format='a: {delta} b: {sigma} orog: {orography}'), } + formula_terms_format='a: {delta} b: {sigma} orog: {orography}'), + HybridPressureFactory: _FactoryDefn( + primary='delta', + std_name='atmosphere_hybrid_sigma_pressure_coordinate', + formula_terms_format='ap: {delta} b: {sigma} ' + 'ps: {surface_air_pressure}'), + OceanSigmaZFactory: _FactoryDefn( + primary='zlev', + std_name='ocean_sigma_z_coordinate', + formula_terms_format='sigma: {sigma} eta: {eta} depth: {depth} ' + 'depth_c: {depth_c} nsigma: {nsigma} zlev: {zlev}'), + OceanSigmaFactory: _FactoryDefn( + primary='sigma', + std_name='ocean_sigma_coordinate', + formula_terms_format='sigma: {sigma} eta: {eta} depth: {depth}'), + OceanSFactory: _FactoryDefn( + primary='s', + std_name='ocean_s_coordinate', + formula_terms_format='s: {s} eta: {eta} depth: {depth} a: {a} b: {b} ' + 'depth_c: {depth_c}'), + OceanSg1Factory: _FactoryDefn( + primary='s', + std_name='ocean_s_coordinate_g1', + formula_terms_format='s: {s} c: {c} eta: {eta} depth: {depth} ' + 'depth_c: {depth_c}'), + OceanSg2Factory: _FactoryDefn( + primary='s', + std_name='ocean_s_coordinate_g2', + formula_terms_format='s: {s} c: {c} eta: {eta} depth: {depth} ' + 'depth_c: {depth_c}') +} + + +# Cell methods. +_CM_KNOWN_METHODS = ['point', 'sum', 'mean', 'maximum', 'minimum', 'mid_range', + 'standard_deviation', 'variance', 'mode', 'median'] + +_CM_COMMENT = 'comment' +_CM_EXTRA = 'extra' +_CM_INTERVAL = 'interval' +_CM_METHOD = 'method' +_CM_NAME = 'name' +_CM_PARSE = re.compile(r''' + (?P([\w_]+\s*?:\s+)+) + (?P[\w_\s]+(?![\w_]*\s*?:))\s* + (?: + \(\s* + (?P[^\)]+) + \)\s* + )? + ''', re.VERBOSE) + + +class UnknownCellMethodWarning(Warning): + pass + + +def parse_cell_methods(nc_cell_methods): + """ + Parse a CF cell_methods attribute string into a tuple of zero or + more CellMethod instances. + + Args: + + * nc_cell_methods (str): + The value of the cell methods attribute to be parsed. + + Returns: + + * cell_methods + An iterable of :class:`iris.coords.CellMethod`. + + Multiple coordinates, intervals and comments are supported. + If a method has a non-standard name a warning will be issued, but the + results are not affected. + + """ + + cell_methods = [] + if nc_cell_methods is not None: + for m in _CM_PARSE.finditer(nc_cell_methods): + d = m.groupdict() + method = d[_CM_METHOD] + method = method.strip() + # Check validity of method, allowing for multi-part methods + # e.g. mean over years. + method_words = method.split() + if method_words[0].lower() not in _CM_KNOWN_METHODS: + msg = 'NetCDF variable contains unknown cell method {!r}' + warnings.warn(msg.format('{}'.format(method_words[0])), + UnknownCellMethodWarning) + d[_CM_METHOD] = method + name = d[_CM_NAME] + name = name.replace(' ', '') + name = name.rstrip(':') + d[_CM_NAME] = tuple([n for n in name.split(':')]) + interval = [] + comment = [] + if d[_CM_EXTRA] is not None: + # + # tokenise the key words and field colon marker + # + d[_CM_EXTRA] = d[_CM_EXTRA].replace('comment:', + '<><<:>>') + d[_CM_EXTRA] = d[_CM_EXTRA].replace('interval:', + '<><<:>>') + d[_CM_EXTRA] = d[_CM_EXTRA].split('<<:>>') + if len(d[_CM_EXTRA]) == 1: + comment.extend(d[_CM_EXTRA]) + else: + next_field_type = comment + for field in d[_CM_EXTRA]: + field_type = next_field_type + index = field.rfind('<>') + if index == 0: + next_field_type = interval + continue + elif index > 0: + next_field_type = interval + else: + index = field.rfind('<>') + if index == 0: + next_field_type = comment + continue + elif index > 0: + next_field_type = comment + if index != -1: + field = field[:index] + field_type.append(field.strip()) + # + # cater for a shared interval over multiple axes + # + if len(interval): + if len(d[_CM_NAME]) != len(interval) and len(interval) == 1: + interval = interval*len(d[_CM_NAME]) + # + # cater for a shared comment over multiple axes + # + if len(comment): + if len(d[_CM_NAME]) != len(comment) and len(comment) == 1: + comment = comment*len(d[_CM_NAME]) + d[_CM_INTERVAL] = tuple(interval) + d[_CM_COMMENT] = tuple(comment) + cell_method = iris.coords.CellMethod(d[_CM_METHOD], + coords=d[_CM_NAME], + intervals=d[_CM_INTERVAL], + comments=d[_CM_COMMENT]) + cell_methods.append(cell_method) + return tuple(cell_methods) class CFNameCoordMap(object): @@ -233,10 +392,10 @@ def __getitem__(self, keys): try: variable = dataset.variables[self.variable_name] # Get the NetCDF variable data and slice. - data = variable[keys] + var = variable[keys] finally: dataset.close() - return data + return np.asanyarray(var) def __repr__(self): fmt = '<{self.__class__.__name__} shape={self.shape}' \ @@ -248,7 +407,7 @@ def __getstate__(self): return {attr: getattr(self, attr) for attr in self.__slots__} def __setstate__(self, state): - for key, value in state.iteritems(): + for key, value in six.iteritems(state): setattr(self, key, value) @@ -257,30 +416,35 @@ def _assert_case_specific_facts(engine, cf, cf_group): engine.provides['coordinates'] = [] # Assert facts for CF coordinates. - for cf_name in cf_group.coordinates.iterkeys(): + for cf_name in six.iterkeys(cf_group.coordinates): engine.add_case_specific_fact(_PYKE_FACT_BASE, 'coordinate', (cf_name,)) # Assert facts for CF auxiliary coordinates. - for cf_name in cf_group.auxiliary_coordinates.iterkeys(): + for cf_name in six.iterkeys(cf_group.auxiliary_coordinates): engine.add_case_specific_fact(_PYKE_FACT_BASE, 'auxiliary_coordinate', (cf_name,)) + # Assert facts for CF cell measures. + for cf_name in six.iterkeys(cf_group.cell_measures): + engine.add_case_specific_fact(_PYKE_FACT_BASE, + 'cell_measure', (cf_name,)) + # Assert facts for CF grid_mappings. - for cf_name in cf_group.grid_mappings.iterkeys(): + for cf_name in six.iterkeys(cf_group.grid_mappings): engine.add_case_specific_fact(_PYKE_FACT_BASE, 'grid_mapping', (cf_name,)) # Assert facts for CF labels. - for cf_name in cf_group.labels.iterkeys(): + for cf_name in six.iterkeys(cf_group.labels): engine.add_case_specific_fact(_PYKE_FACT_BASE, 'label', (cf_name,)) # Assert facts for CF formula terms associated with the cf_group # of the CF data variable. formula_root = set() - for cf_var in cf.cf_group.formula_terms.itervalues(): - for cf_root, cf_term in cf_var.cf_terms_by_root.iteritems(): + for cf_var in six.itervalues(cf.cf_group.formula_terms): + for cf_root, cf_term in six.iteritems(cf_var.cf_terms_by_root): # Only assert this fact if the formula root variable is # defined in the CF group of the CF data variable. if cf_root in cf_group: @@ -296,28 +460,28 @@ def _assert_case_specific_facts(engine, cf, cf_group): def _pyke_stats(engine, cf_name): if DEBUG: - print '-' * 80 - print 'CF Data Variable: %r' % cf_name + print('-' * 80) + print('CF Data Variable: %r' % cf_name) engine.print_stats() - print 'Rules Triggered:' + print('Rules Triggered:') for rule in sorted(list(engine.rule_triggered)): - print '\t%s' % rule + print('\t%s' % rule) - print 'Case Specific Facts:' + print('Case Specific Facts:') kb_facts = engine.get_kb(_PYKE_FACT_BASE) - for key in kb_facts.entity_lists.iterkeys(): + for key in six.iterkeys(kb_facts.entity_lists): for arg in kb_facts.entity_lists[key].case_specific_facts: - print '\t%s%s' % (key, arg) + print('\t%s%s' % (key, arg)) def _set_attributes(attributes, key, value): """Set attributes dictionary, converting unicode strings appropriately.""" - if isinstance(value, unicode): + if isinstance(value, six.text_type): try: attributes[str(key)] = str(value) except UnicodeEncodeError: @@ -326,9 +490,7 @@ def _set_attributes(attributes, key, value): attributes[str(key)] = value -def _load_cube(engine, cf, cf_var, filename): - """Create the cube associated with the CF-netCDF data variable.""" - +def _get_actual_dtype(cf_var): # Figure out what the eventual data type will be after any scale/offset # transforms. dummy_data = np.zeros(1, dtype=cf_var.dtype) @@ -336,13 +498,28 @@ def _load_cube(engine, cf, cf_var, filename): dummy_data = cf_var.scale_factor * dummy_data if hasattr(cf_var, 'add_offset'): dummy_data = cf_var.add_offset + dummy_data + return dummy_data.dtype + + +def _get_cf_var_data(cf_var, filename): + # Get lazy chunked data out of a cf variable. + dtype = _get_actual_dtype(cf_var) # Create cube with deferred data, but no metadata fill_value = getattr(cf_var.cf_data, '_FillValue', netCDF4.default_fillvals[cf_var.dtype.str[1:]]) - proxy = NetCDFDataProxy(cf_var.shape, dummy_data.dtype, - filename, cf_var.cf_name, fill_value) - data = biggus.OrthoArrayAdapter(proxy) + proxy = NetCDFDataProxy(cf_var.shape, dtype, filename, cf_var.cf_name, + fill_value) + chunks = cf_var.cf_data.chunking() + # Chunks can be an iterable, None, or `'contiguous'`. + if chunks == 'contiguous': + chunks = None + return as_lazy_data(proxy, chunks=chunks) + + +def _load_cube(engine, cf, cf_var, filename): + """Create the cube associated with the CF-netCDF data variable.""" + data = _get_cf_var_data(cf_var, filename) cube = iris.cube.Cube(data) # Reset the pyke inference engine. @@ -365,47 +542,138 @@ def _load_cube(engine, cf, cf_var, filename): # Populate coordinate attributes with the untouched attributes from the # associated CF-netCDF variable. coordinates = engine.provides.get('coordinates', []) - attribute_predicate = lambda item: item[0] not in _CF_ATTRS + + def attribute_predicate(item): + return item[0] not in _CF_ATTRS for coord, cf_var_name in coordinates: - tmpvar = itertools.ifilter(attribute_predicate, - cf.cf_group[cf_var_name].cf_attrs_unused()) + tmpvar = filter(attribute_predicate, + cf.cf_group[cf_var_name].cf_attrs_unused()) for attr_name, attr_value in tmpvar: _set_attributes(coord.attributes, attr_name, attr_value) - tmpvar = itertools.ifilter(attribute_predicate, cf_var.cf_attrs_unused()) + tmpvar = filter(attribute_predicate, cf_var.cf_attrs_unused()) # Attach untouched attributes of the associated CF-netCDF data variable to # the cube. for attr_name, attr_value in tmpvar: _set_attributes(cube.attributes, attr_name, attr_value) + names = {coord.var_name: coord.standard_name or coord.var_name or 'unknown' + for coord in cube.coords()} + + cube.cell_methods = [ + iris.coords.CellMethod( + method=method.method, + intervals=method.intervals, + comments=method.comments, + coords=[names[coord_name] if + coord_name in names else coord_name + for coord_name in method.coord_names]) + for method in cube.cell_methods] + # Show pyke session statistics. _pyke_stats(engine, cf_var.cf_name) return cube -def _load_aux_factory(engine, cf, filename, cube): +def _load_aux_factory(engine, cube): """ Convert any CF-netCDF dimensionless coordinate to an AuxCoordFactory. """ formula_type = engine.requires.get('formula_type') - - if formula_type == 'atmosphere_hybrid_height_coordinate': - def coord_from_var_name(name): - mapping = engine.provides['coordinates'] - for coord, cf_var_name in engine.provides['coordinates']: - if cf_var_name == name: - return coord - raise ValueError('Unable to find coordinate for variable ' - '{!r}'.format(name)) - # Convert term names to coordinates (via netCDF variable names). - terms_to_var_names = engine.requires['formula_terms'] - delta = coord_from_var_name(terms_to_var_names['a']) - sigma = coord_from_var_name(terms_to_var_names['b']) - orography = coord_from_var_name(terms_to_var_names['orog']) - factory = iris.aux_factory.HybridHeightFactory(delta, sigma, orography) + if formula_type in ['atmosphere_hybrid_height_coordinate', + 'atmosphere_hybrid_sigma_pressure_coordinate', + 'ocean_sigma_z_coordinate', 'ocean_sigma_coordinate', + 'ocean_s_coordinate', 'ocean_s_coordinate_g1', + 'ocean_s_coordinate_g2']: + def coord_from_term(term): + # Convert term names to coordinates (via netCDF variable names). + name = engine.requires['formula_terms'].get(term, None) + if name is not None: + for coord, cf_var_name in engine.provides['coordinates']: + if cf_var_name == name: + return coord + warnings.warn('Unable to find coordinate for variable ' + '{!r}'.format(name)) + + if formula_type == 'atmosphere_hybrid_height_coordinate': + delta = coord_from_term('a') + sigma = coord_from_term('b') + orography = coord_from_term('orog') + factory = HybridHeightFactory(delta, sigma, orography) + elif formula_type == 'atmosphere_hybrid_sigma_pressure_coordinate': + # Hybrid pressure has two valid versions of its formula terms: + # "p0: var1 a: var2 b: var3 ps: var4" or + # "ap: var1 b: var2 ps: var3" where "ap = p0 * a" + # Attempt to get the "ap" term. + delta = coord_from_term('ap') + if delta is None: + # The "ap" term is unavailable, so try getting terms "p0" + # and "a" terms in order to derive an "ap" equivalent term. + coord_p0 = coord_from_term('p0') + if coord_p0 is not None: + if coord_p0.shape != (1,): + msg = 'Expecting {!r} to be a scalar reference ' \ + 'pressure coordinate, got shape {!r}'.format( + coord_p0.var_name, + coord_p0.shape) + raise ValueError(msg) + if coord_p0.has_bounds(): + msg = 'Ignoring atmosphere hybrid sigma pressure ' \ + 'scalar coordinate {!r} bounds.'.format( + coord_p0.name()) + warnings.warn(msg) + coord_a = coord_from_term('a') + if coord_a is not None: + delta = coord_a * coord_p0.points[0] + delta.units = coord_a.units * coord_p0.units + delta.rename('vertical pressure') + delta.var_name = 'ap' + cube.add_aux_coord(delta, cube.coord_dims(coord_a)) + + sigma = coord_from_term('b') + surface_air_pressure = coord_from_term('ps') + factory = HybridPressureFactory(delta, sigma, surface_air_pressure) + elif formula_type == 'ocean_sigma_z_coordinate': + sigma = coord_from_term('sigma') + eta = coord_from_term('eta') + depth = coord_from_term('depth') + depth_c = coord_from_term('depth_c') + nsigma = coord_from_term('nsigma') + zlev = coord_from_term('zlev') + factory = OceanSigmaZFactory(sigma, eta, depth, + depth_c, nsigma, zlev) + elif formula_type == 'ocean_sigma_coordinate': + sigma = coord_from_term('sigma') + eta = coord_from_term('eta') + depth = coord_from_term('depth') + factory = OceanSigmaFactory(sigma, eta, depth) + elif formula_type == 'ocean_s_coordinate': + s = coord_from_term('s') + eta = coord_from_term('eta') + depth = coord_from_term('depth') + a = coord_from_term('a') + depth_c = coord_from_term('depth_c') + b = coord_from_term('b') + factory = OceanSFactory(s, eta, depth, a, b, depth_c) + elif formula_type == 'ocean_s_coordinate_g1': + s = coord_from_term('s') + c = coord_from_term('c') + eta = coord_from_term('eta') + depth = coord_from_term('depth') + depth_c = coord_from_term('depth_c') + factory = OceanSg1Factory(s, c, eta, depth, + depth_c) + elif formula_type == 'ocean_s_coordinate_g2': + s = coord_from_term('s') + c = coord_from_term('c') + eta = coord_from_term('eta') + depth = coord_from_term('depth') + depth_c = coord_from_term('depth_c') + factory = OceanSg2Factory(s, c, eta, depth, + depth_c) cube.add_aux_factory(factory) @@ -430,7 +698,7 @@ def load_cubes(filenames, callback=None): # Initialise the pyke inference engine. engine = _pyke_kb_engine() - if isinstance(filenames, basestring): + if isinstance(filenames, six.string_types): filenames = [filenames] for filename in filenames: @@ -438,25 +706,74 @@ def load_cubes(filenames, callback=None): cf = iris.fileformats.cf.CFReader(filename) # Process each CF data variable. - for cf_var in cf.cf_group.data_variables.itervalues(): - # Only process CF data variables that do not participate in a - # formula term. - if not cf_var.has_formula_terms(): - cube = _load_cube(engine, cf, cf_var, filename) + data_variables = (list(cf.cf_group.data_variables.values()) + + list(cf.cf_group.promoted.values())) + for cf_var in data_variables: + cube = _load_cube(engine, cf, cf_var, filename) + + # Process any associated formula terms and attach + # the corresponding AuxCoordFactory. + try: + _load_aux_factory(engine, cube) + except ValueError as e: + warnings.warn('{}'.format(e)) + + # Perform any user registered callback function. + cube = iris.io.run_callback(callback, cube, cf_var, filename) + + # Callback mechanism may return None, which must not be yielded + if cube is None: + continue + + yield cube - # Process any associated formula terms and attach - # the corresponding AuxCoordFactory. - _load_aux_factory(engine, cf, filename, cube) - # Perform any user registered callback function. - cube = iris.io.run_callback(callback, cube, engine.cf_var, - filename) +def _bytes_if_ascii(string): + """ + Convert the given string to a byte string (str in py2k, bytes in py3k) + if the given string can be encoded to ascii, else maintain the type + of the inputted string. + + Note: passing objects without an `encode` method (such as None) will + be returned by the function unchanged. - # Callback mechanism may return None, which must not be yielded - if cube is None: - continue + """ + if isinstance(string, six.string_types): + try: + return string.encode(encoding='ascii') + except (AttributeError, UnicodeEncodeError): + pass + return string - yield cube + +def _setncattr(variable, name, attribute): + """ + Put the given attribute on the given netCDF4 Data type, casting + attributes as we go to bytes rather than unicode. + + """ + attribute = _bytes_if_ascii(attribute) + return variable.setncattr(name, attribute) + + +class _FillValueMaskCheckAndStoreTarget(object): + """ + To be used with da.store. Remembers whether any element was equal to a + given value and whether it was masked, before passing the chunk to the + given target. + + """ + def __init__(self, target, fill_value=None): + self.target = target + self.fill_value = fill_value + self.contains_value = False + self.is_masked = False + + def __setitem__(self, keys, arr): + if self.fill_value is not None: + self.contains_value = self.contains_value or self.fill_value in arr + self.is_masked = self.is_masked or ma.is_masked(arr) + self.target[keys] = arr class Saver(object): @@ -501,6 +818,8 @@ def __init__(self, filename, netcdf_format): self._coord_systems = [] #: A dictionary, listing dimension names and corresponding length self._existing_dim = {} + #: A dictionary, mapping formula terms to owner cf variable name + self._formula_terms_cache = {} #: NetCDF dataset try: self._dataset = netCDF4.Dataset(filename, mode='w', @@ -528,7 +847,7 @@ def __exit__(self, type, value, traceback): def write(self, cube, local_keys=None, unlimited_dimensions=None, zlib=False, complevel=4, shuffle=True, fletcher32=False, contiguous=False, chunksizes=None, endian='native', - least_significant_digit=None): + least_significant_digit=None, packing=None, fill_value=None): """ Wrapper for saving cubes to a NetCDF file. @@ -546,13 +865,11 @@ def write(self, cube, local_keys=None, unlimited_dimensions=None, * unlimited_dimensions (iterable of strings and/or :class:`iris.coords.Coord` objects): - Explicit list of coordinate names (or coordinate objects) + List of coordinate names (or coordinate objects) corresponding to coordinate dimensions of `cube` to save with the - NetCDF dimension variable length 'UNLIMITED'. By default, the - outermost (first) dimension for each cube is used. Only the - 'NETCDF4' format supports multiple 'UNLIMITED' dimensions. To save - no unlimited dimensions, use `unlimited_dimensions=[]` (an empty - list). + NetCDF dimension variable length 'UNLIMITED'. By default, no + unlimited dimensions are saved. Only the 'NETCDF4' format + supports multiple 'UNLIMITED' dimensions. * zlib (bool): If `True`, the data will be compressed in the netCDF file using @@ -602,11 +919,32 @@ def write(self, cube, local_keys=None, unlimited_dimensions=None, using `numpy.around(scale*data)/scale`, where `scale = 2**bits`, and `bits` is determined so that a precision of 0.1 is retained (in this case `bits=4`). From - http://www.cdc.noaa.gov/cdc/conventions/cdc_netcdf_standard.shtml: + http://www.esrl.noaa.gov/psd/data/gridded/conventions/cdc_netcdf_standard.shtml: "least_significant_digit -- power of ten of the smallest decimal place in unpacked data that is a reliable value". Default is `None`, or no quantization, or 'lossless' compression. + * packing (type or string or dict or list): A numpy integer datatype + (signed or unsigned) or a string that describes a numpy integer + dtype(i.e. 'i2', 'short', 'u4') or a dict of packing parameters as + described below. This provides support for netCDF data packing as + described in + http://www.unidata.ucar.edu/software/netcdf/docs/BestPractices.html#bp_Packed-Data-Values + If this argument is a type (or type string), appropriate values of + scale_factor and add_offset will be automatically calculated based + on `cube.data` and possible masking. For more control, pass a dict + with one or more of the following keys: `dtype` (required), + `scale_factor` and `add_offset`. Note that automatic calculation of + packing parameters will trigger loading of lazy data; set them + manually using a dict to avoid this. The default is `None`, in + which case the datatype is determined from the cube and no packing + will occur. + + * fill_value: + The value to use for the `_FillValue` attribute on the netCDF + variable. If `packing` is specified the value of `fill_value` + should be in the domain of the packed data. + Returns: None. @@ -616,19 +954,23 @@ def write(self, cube, local_keys=None, unlimited_dimensions=None, `chunksizes` and `endian` keywords are silently ignored for netCDF 3 files that do not use HDF5. - """ - if len(cube.aux_factories) > 1: - raise ValueError('Multiple auxiliary factories are not supported.') - - cf_profile_available = ( - 'cf_profile' in iris.site_configuration and - iris.site_configuration['cf_profile'] not in [None, False]) + """ + if unlimited_dimensions is None: + unlimited_dimensions = [] + cf_profile_available = (iris.site_configuration.get('cf_profile') not + in [None, False]) if cf_profile_available: # Perform a CF profile of the cube. This may result in an exception # being raised if mandatory requirements are not satisfied. profile = iris.site_configuration['cf_profile'](cube) + # Ensure that attributes are CF compliant and if possible to make them + # compliant. + self.check_attribute_compliance(cube, cube.lazy_data()) + for coord in cube.coords(): + self.check_attribute_compliance(coord, coord.points) + # Get suitable dimension names. dimension_names = self._get_dim_names(cube) @@ -640,15 +982,23 @@ def write(self, cube, local_keys=None, unlimited_dimensions=None, cube, dimension_names, local_keys, zlib=zlib, complevel=complevel, shuffle=shuffle, fletcher32=fletcher32, contiguous=contiguous, chunksizes=chunksizes, endian=endian, - least_significant_digit=least_significant_digit) + least_significant_digit=least_significant_digit, packing=packing, + fill_value=fill_value) - # Add coordinate variables and return factory definitions - factory_defn = self._add_dim_coords(cube, dimension_names) + # Add coordinate variables. + self._add_dim_coords(cube, dimension_names) # Add the auxiliary coordinate variable names and associate the data # variable to them - cf_var_cube = self._add_aux_coords(cube, cf_var_cube, dimension_names, - factory_defn) + self._add_aux_coords(cube, cf_var_cube, dimension_names) + + # Add the cell_measures variable names and associate the data + # variable to them + self._add_cell_measures(cube, cf_var_cube, dimension_names) + + # Add the formula terms to the appropriate cf variables for each + # aux factory in the cube. + self._add_aux_factories(cube, cf_var_cube, dimension_names) # Add data variable-only attribute names to local_keys. if local_keys is None: @@ -658,14 +1008,51 @@ def write(self, cube, local_keys=None, unlimited_dimensions=None, local_keys.update(_CF_DATA_ATTRS, _UKMO_DATA_ATTRS) # Add global attributes taking into account local_keys. - global_attributes = {k: v for k, v in cube.attributes.iteritems() if k - not in local_keys and k.lower() != 'conventions'} + global_attributes = {k: v for k, v in six.iteritems(cube.attributes) + if (k not in local_keys and + k.lower() != 'conventions')} self.update_global_attributes(global_attributes) if cf_profile_available: - # Perform a CF patch of the dataset. - iris.site_configuration['cf_patch'](profile, self._dataset, - cf_var_cube) + cf_patch = iris.site_configuration.get('cf_patch') + if cf_patch is not None: + # Perform a CF patch of the dataset. + cf_patch(profile, self._dataset, cf_var_cube) + else: + msg = 'cf_profile is available but no {} defined.'.format( + 'cf_patch') + warnings.warn(msg) + + @staticmethod + def check_attribute_compliance(container, data): + def _coerce_value(val_attr, val_attr_value, data_dtype): + val_attr_tmp = np.array(val_attr_value, dtype=data_dtype) + if (val_attr_tmp != val_attr_value).any(): + msg = '"{}" is not of a suitable value ({})' + raise ValueError(msg.format(val_attr, val_attr_value)) + return val_attr_tmp + + data_dtype = data.dtype + + # Ensure that conflicting attributes are not provided. + if ((container.attributes.get('valid_min') is not None or + container.attributes.get('valid_max') is not None) and + container.attributes.get('valid_range') is not None): + msg = ('Both "valid_range" and "valid_min" or "valid_max" ' + 'attributes present.') + raise ValueError(msg) + + # Ensure correct datatype + for val_attr in ['valid_range', 'valid_min', 'valid_max']: + val_attr_value = container.attributes.get(val_attr) + if val_attr_value is not None: + val_attr_value = np.asarray(val_attr_value) + if data_dtype.itemsize is 1: + # Allow signed integral type + if val_attr_value.dtype.kind == 'i': + continue + new_val = _coerce_value(val_attr, val_attr_value, data_dtype) + container.attributes[val_attr] = new_val def update_global_attributes(self, attributes=None, **kwargs): """ @@ -684,10 +1071,10 @@ def update_global_attributes(self, attributes=None, **kwargs): attributes = dict(attributes) for attr_name in sorted(attributes): - setattr(self._dataset, attr_name, attributes[attr_name]) + _setncattr(self._dataset, attr_name, attributes[attr_name]) for attr_name in sorted(kwargs): - setattr(self._dataset, attr_name, kwargs[attr_name]) + _setncattr(self._dataset, attr_name, kwargs[attr_name]) def _create_cf_dimensions(self, cube, dimension_names, unlimited_dimensions=None): @@ -703,28 +1090,23 @@ def _create_cf_dimensions(self, cube, dimension_names, * unlimited_dimensions (iterable of strings and/or :class:`iris.coords.Coord` objects): - List of coordinates to make unlimited. By default, the - outermost dimension is made unlimited. + List of coordinates to make unlimited (None by default). Returns: None. """ unlimited_dim_names = [] - if unlimited_dimensions is None: - if dimension_names: - unlimited_dim_names.append(dimension_names[0]) - else: - for coord in unlimited_dimensions: - try: - coord = cube.coord(name_or_coord=coord, dim_coords=True) - except iris.exceptions.CoordinateNotFoundError: - # coordinate isn't used for this cube, but it might be - # used for a different one - pass - else: - dim_name = self._get_coord_variable_name(cube, coord) - unlimited_dim_names.append(dim_name) + for coord in unlimited_dimensions: + try: + coord = cube.coord(name_or_coord=coord, dim_coords=True) + except iris.exceptions.CoordinateNotFoundError: + # coordinate isn't used for this cube, but it might be + # used for a different one + pass + else: + dim_name = self._get_coord_variable_name(cube, coord) + unlimited_dim_names.append(dim_name) for dim_name in dimension_names: if dim_name not in self._dataset.dimensions: @@ -734,27 +1116,18 @@ def _create_cf_dimensions(self, cube, dimension_names, size = self._existing_dim[dim_name] self._dataset.createDimension(dim_name, size) - def _add_aux_coords(self, cube, cf_var_cube, dimension_names, - factory_defn): + def _add_aux_coords(self, cube, cf_var_cube, dimension_names): """ Add aux. coordinate to the dataset and associate with the data variable Args: - * cube (:class:`iris.cube.Cube`) or cubelist - (:class:`iris.cube.CubeList`): - A :class:`iris.cube.Cube`, :class:`iris.cube.CubeList` or list of - cubes to be saved to a netCDF file. + * cube (:class:`iris.cube.Cube`): + A :class:`iris.cube.Cube` to be saved to a netCDF file. * cf_var_cube (:class:`netcdf.netcdf_variable`): cf variable cube representation. * dimension_names (list): Names associated with the dimensions of the cube. - * factory_defn (:class:`_FactoryDefn`): - An optional description of the AuxCoordFactory relevant to this - cube. - - Returns: - Updated cf_var_cube with coordinates added. """ auxiliary_coordinate_names = [] @@ -763,7 +1136,7 @@ def _add_aux_coords(self, cube, cf_var_cube, dimension_names, # Create the associated coordinate CF-netCDF variable. if coord not in self._name_coord_map.coords: cf_name = self._create_cf_variable(cube, dimension_names, - coord, factory_defn) + coord) self._name_coord_map.append(cf_name, coord) else: cf_name = self._name_coord_map.name(coord) @@ -774,41 +1147,147 @@ def _add_aux_coords(self, cube, cf_var_cube, dimension_names, # Add CF-netCDF auxiliary coordinate variable references to the # CF-netCDF data variable. if auxiliary_coordinate_names: - cf_var_cube.coordinates = ' '.join( - sorted(auxiliary_coordinate_names)) - return cf_var_cube + coord_variable_names = ' '.join(sorted(auxiliary_coordinate_names)) + _setncattr(cf_var_cube, 'coordinates', coord_variable_names) - def _add_dim_coords(self, cube, dimension_names): + def _add_cell_measures(self, cube, cf_var_cube, dim_names): """ - Add coordinate variables to NetCDF dataset. + Add cell measures to the dataset and associate with the data variable Args: - * cube (:class:`iris.cube.Cube`) or cubelist - (:class:`iris.cube.CubeList`): - A :class:`iris.cube.Cube`, :class:`iris.cube.CubeList` or list of - cubes to be saved to a netCDF file. + * cube (:class:`iris.cube.Cube`): + A :class:`iris.cube.Cube` to be saved to a netCDF file. + * cf_var_cube (:class:`netcdf.netcdf_variable`): + cf variable cube representation. * dimension_names (list): Names associated with the dimensions of the cube. - Returns: - Factory definitions, a description of the AuxCoordFactory relevant - to this cube. + """ + cell_measure_names = [] + # Add CF-netCDF variables for the associated cell measures. + for cm in sorted(cube.cell_measures(), key=lambda cm: cm.name()): + # Create the associated cell measure CF-netCDF variable. + if cm not in self._name_coord_map.coords: + cf_name = self._create_cf_cell_measure_variable(cube, + dim_names, + cm) + self._name_coord_map.append(cf_name, cm) + else: + cf_name = self._name_coord_map.name(cm) + + if cf_name is not None: + cell_measure_names.append('{}: {}'.format(cm.measure, cf_name)) + + # Add CF-netCDF cell measure variable references to the + # CF-netCDF data variable. + if cell_measure_names: + cm_var_names = ' '.join(sorted(cell_measure_names)) + _setncattr(cf_var_cube, 'cell_measures', cm_var_names) + def _add_dim_coords(self, cube, dimension_names): """ - factory_defn = None - if cube.aux_factories: - factory = cube.aux_factories[0] - factory_defn = _FACTORY_DEFNS.get(type(factory), None) + Add coordinate variables to NetCDF dataset. + Args: + + * cube (:class:`iris.cube.Cube`): + A :class:`iris.cube.Cube` to be saved to a netCDF file. + * dimension_names (list): + Names associated with the dimensions of the cube. + + """ # Ensure we create the netCDF coordinate variables first. for coord in cube.dim_coords: # Create the associated coordinate CF-netCDF variable. if coord not in self._name_coord_map.coords: cf_name = self._create_cf_variable(cube, dimension_names, - coord, factory_defn) + coord) self._name_coord_map.append(cf_name, coord) - return factory_defn + + def _add_aux_factories(self, cube, cf_var_cube, dimension_names): + """ + Modifies the variables of the NetCDF dataset to represent + the presence of dimensionless vertical coordinates based on + the aux factories of the cube (if any). + + Args: + + * cube (:class:`iris.cube.Cube`): + A :class:`iris.cube.Cube` to be saved to a netCDF file. + * cf_var_cube (:class:`netcdf.netcdf_variable`) + CF variable cube representation. + * dimension_names (list): + Names associated with the dimensions of the cube. + + """ + primaries = [] + for factory in cube.aux_factories: + factory_defn = _FACTORY_DEFNS.get(type(factory), None) + if factory_defn is None: + msg = 'Unable to determine formula terms ' \ + 'for AuxFactory: {!r}'.format(factory) + warnings.warn(msg) + else: + # Override `standard_name`, `long_name`, and `axis` of the + # primary coord that signals the presense of a dimensionless + # vertical coord, then set the `formula_terms` attribute. + primary_coord = factory.dependencies[factory_defn.primary] + if primary_coord in primaries: + msg = 'Cube {!r} has multiple aux factories that share ' \ + 'a common primary coordinate {!r}. Unable to save ' \ + 'to netCDF as having multiple formula terms on a ' \ + 'single coordinate is not supported.' + raise ValueError(msg.format(cube, primary_coord.name())) + primaries.append(primary_coord) + + cf_name = self._name_coord_map.name(primary_coord) + cf_var = self._dataset.variables[cf_name] + + names = {key: self._name_coord_map.name(coord) for + key, coord in six.iteritems(factory.dependencies)} + formula_terms = factory_defn.formula_terms_format.format( + **names) + std_name = factory_defn.std_name + + if hasattr(cf_var, 'formula_terms'): + if cf_var.formula_terms != formula_terms or \ + cf_var.standard_name != std_name: + # TODO: We need to resolve this corner-case where + # the dimensionless vertical coordinate containing the + # formula_terms is a dimension coordinate of the + # associated cube and a new alternatively named + # dimensionless vertical coordinate is required with + # new formula_terms and a renamed dimension. + if cf_name in dimension_names: + msg = 'Unable to create dimensonless vertical ' \ + 'coordinate.' + raise ValueError(msg) + key = (cf_name, std_name, formula_terms) + name = self._formula_terms_cache.get(key) + if name is None: + # Create a new variable + name = self._create_cf_variable(cube, + dimension_names, + primary_coord) + cf_var = self._dataset.variables[name] + _setncattr(cf_var, 'standard_name', std_name) + _setncattr(cf_var, 'axis', 'Z') + # Update the formula terms. + ft = formula_terms.split() + ft = [name if t == cf_name else t for t in ft] + _setncattr(cf_var, 'formula_terms', ' '.join(ft)) + # Update the cache. + self._formula_terms_cache[key] = name + # Update the associated cube variable. + coords = cf_var_cube.coordinates.split() + coords = [name if c == cf_name else c for c in coords] + _setncattr(cf_var_cube, 'coordinates', + ' '.join(coords)) + else: + _setncattr(cf_var, 'standard_name', std_name) + _setncattr(cf_var, 'axis', 'Z') + _setncattr(cf_var, 'formula_terms', formula_terms) def _get_dim_names(self, cube): """ @@ -816,10 +1295,8 @@ def _get_dim_names(self, cube): Args: - * cube (:class:`iris.cube.Cube`) or cubelist - (:class:`iris.cube.CubeList`): - A :class:`iris.cube.Cube`, :class:`iris.cube.CubeList` or list of - cubes to be saved to a netCDF file. + * cube (:class:`iris.cube.Cube`): + A :class:`iris.cube.Cube` to be saved to a netCDF file. Returns: List of dimension names with length equal the number of dimensions @@ -827,7 +1304,7 @@ def _get_dim_names(self, cube): """ dimension_names = [] - for dim in xrange(cube.ndim): + for dim in range(cube.ndim): coords = cube.coords(dimensions=dim, dim_coords=True) if coords: coord = coords[0] @@ -871,7 +1348,29 @@ def _get_dim_names(self, cube): dimension_names.append(dim_name) return dimension_names - def _cf_coord_identity(self, coord): + @staticmethod + def cf_valid_var_name(var_name): + """ + Return a valid CF var_name given a potentially invalid name. + + Args: + + * var_name (str): + The var_name to normalise + + Returns: + A var_name suitable for passing through for variable creation. + + """ + # Replace invalid charaters with an underscore ("_"). + var_name = re.sub(r'[^a-zA-Z0-9]', "_", var_name) + # Ensure the variable name starts with a letter. + if re.match(r'^[^a-zA-Z]', var_name): + var_name = 'var_{}'.format(var_name) + return var_name + + @staticmethod + def _cf_coord_identity(coord): """ Determine a suitable units from a given coordinate. @@ -887,30 +1386,27 @@ def _cf_coord_identity(self, coord): """ units = str(coord.units) - - # TODO: Use #61 to get the units. - if isinstance(coord.coord_system, iris.coord_systems.GeogCS): - if "latitude" in coord.standard_name: + # Set the 'units' of 'latitude' and 'longitude' coordinates specified + # in 'degrees' to 'degrees_north' and 'degrees_east' respectively, + # as defined in the CF conventions for netCDF files: sections 4.1 and + # 4.2. + if ((isinstance(coord.coord_system, iris.coord_systems.GeogCS) or + coord.coord_system is None) and coord.units == 'degrees'): + if coord.standard_name == "latitude": units = 'degrees_north' - elif "longitude" in coord.standard_name: + elif coord.standard_name == "longitude": units = 'degrees_east' - elif isinstance(coord.coord_system, iris.coord_systems.RotatedGeogCS): - units = 'degrees' - - elif isinstance(coord.coord_system, - iris.coord_systems.TransverseMercator): - units = 'm' - return coord.standard_name, coord.long_name, units def _ensure_valid_dtype(self, values, src_name, src_object): - # NetCDF3 does not support int64 or unsigned ints, so we check - # if we can store them as int32 instead. + # NetCDF3 and NetCDF4 classic do not support int64 or unsigned ints, + # so we check if we can store them as int32 instead. if ((np.issubdtype(values.dtype, np.int64) or np.issubdtype(values.dtype, np.unsignedinteger)) and self._dataset.file_format in ('NETCDF3_CLASSIC', - 'NETCDF3_64BIT')): + 'NETCDF3_64BIT', + 'NETCDF4_CLASSIC')): # Cast to an integer type supported by netCDF3. if not np.can_cast(values.max(), np.int32) or \ not np.can_cast(values.min(), np.int32): @@ -956,7 +1452,7 @@ def _create_cf_bounds(self, coord, cf_var, cf_name): # Create the bounds dimension with the appropriate extent. self._dataset.createDimension(bounds_dimension_name, n_bounds) - cf_var.bounds = cf_name + '_bnds' + _setncattr(cf_var, 'bounds', cf_name + '_bnds') cf_var_bounds = self._dataset.createVariable( cf_var.bounds, bounds.dtype.newbyteorder('='), cf_var.dimensions + (bounds_dimension_name,)) @@ -982,6 +1478,7 @@ def _get_cube_variable_name(self, cube): # Convert to lower case and replace whitespace by underscores. cf_name = '_'.join(cube.name().lower().split()) + cf_name = self.cf_valid_var_name(cf_name) return cf_name def _get_coord_variable_name(self, cube, coord): @@ -1015,9 +1512,76 @@ def _get_coord_variable_name(self, cube, coord): # Convert to lower case and replace whitespace by underscores. cf_name = '_'.join(name.lower().split()) + cf_name = self.cf_valid_var_name(cf_name) + return cf_name + + def _create_cf_cell_measure_variable(self, cube, dimension_names, + cell_measure): + """ + Create the associated CF-netCDF variable in the netCDF dataset for the + given cell_measure. + + Args: + + * cube (:class:`iris.cube.Cube`): + The associated cube being saved to CF-netCDF file. + * dimension_names (list): + Names for each dimension of the cube. + * cell_measure (:class:`iris.coords.CellMeasure`): + The cell measure to be saved to CF-netCDF file. + + Returns: + The string name of the associated CF-netCDF variable saved. + + """ + cf_name = self._get_coord_variable_name(cube, cell_measure) + while cf_name in self._dataset.variables: + cf_name = self._increment_name(cf_name) + + # Derive the data dimension names for the coordinate. + cf_dimensions = [dimension_names[dim] for dim in + cube.cell_measure_dims(cell_measure)] + + # Get the data values. + data = cell_measure.data + + # Disallow saving of *masked* cell measures. + if ma.is_masked(data): + # We can't save masked points properly, as we don't maintain a + # suitable fill_value. (Load will not record one, either). + msg = "Cell measures with missing data are not supported." + raise ValueError(msg) + + # Get the values in a form which is valid for the file format. + data = self._ensure_valid_dtype(data, 'coordinate', cell_measure) + + # Create the CF-netCDF variable. + cf_var = self._dataset.createVariable( + cf_name, data.dtype.newbyteorder('='), cf_dimensions) + + # Add the data to the CF-netCDF variable. + cf_var[:] = data + + if cell_measure.units != 'unknown': + _setncattr(cf_var, 'units', str(cell_measure.units)) + + if cell_measure.standard_name is not None: + _setncattr(cf_var, 'standard_name', cell_measure.standard_name) + + if cell_measure.long_name is not None: + _setncattr(cf_var, 'long_name', cell_measure.long_name) + + # Add any other custom coordinate attributes. + for name in sorted(cell_measure.attributes): + value = cell_measure.attributes[name] + + # Don't clobber existing attributes. + if not hasattr(cf_var, name): + _setncattr(cf_var, name, value) + return cf_name - def _create_cf_variable(self, cube, dimension_names, coord, factory_defn): + def _create_cf_variable(self, cube, dimension_names, coord): """ Create the associated CF-netCDF variable in the netCDF dataset for the given coordinate. If required, also create the CF-netCDF bounds @@ -1025,17 +1589,12 @@ def _create_cf_variable(self, cube, dimension_names, coord, factory_defn): Args: - * dataset (:class:`netCDF4.Dataset`): - The CF-netCDF data file being created. * cube (:class:`iris.cube.Cube`): The associated cube being saved to CF-netCDF file. * dimension_names (list): Names for each dimension of the cube. * coord (:class:`iris.coords.Coord`): The coordinate to be saved to CF-netCDF file. - * factory_defn (:class:`_FactoryDefn`): - An optional description of the AuxCoordFactory relevant to this - cube. Returns: The string name of the associated CF-netCDF variable saved. @@ -1049,8 +1608,10 @@ def _create_cf_variable(self, cube, dimension_names, coord, factory_defn): cf_dimensions = [dimension_names[dim] for dim in cube.coord_dims(coord)] - if np.issubdtype(coord.points.dtype, np.str): + if np.issubdtype(coord.points.dtype, np.str_): string_dimension_depth = coord.points.dtype.itemsize + if coord.points.dtype.kind == 'U': + string_dimension_depth //= 4 string_dimension_name = 'string%d' % string_dimension_depth # Determine whether to create the string length dimension. @@ -1098,7 +1659,7 @@ def _create_cf_variable(self, cube, dimension_names, coord, factory_defn): if coord in cf_coordinates: axis = iris.util.guess_coord_axis(coord) if axis is not None and axis.lower() in SPATIO_TEMPORAL_AXES: - cf_var.axis = axis.upper() + _setncattr(cf_var, 'axis', axis.upper()) # Add the data to the CF-netCDF variable. cf_var[:] = points @@ -1109,33 +1670,18 @@ def _create_cf_variable(self, cube, dimension_names, coord, factory_defn): # Deal with CF-netCDF units and standard name. standard_name, long_name, units = self._cf_coord_identity(coord) - # If this coordinate should describe a dimensionless vertical - # coordinate, then override `standard_name`, `long_name`, and `axis`, - # and also set the `formula_terms` attribute. - if factory_defn: - dependencies = cube.aux_factories[0].dependencies - if coord is dependencies[factory_defn.primary]: - standard_name = factory_defn.std_name - cf_var.axis = 'Z' - - fmt = factory_defn.formula_terms_format - names = {key: coord.name() for key, coord in - dependencies.iteritems()} - formula_terms = fmt.format(**names) - cf_var.formula_terms = formula_terms - if units != 'unknown': - cf_var.units = units + _setncattr(cf_var, 'units', units) if standard_name is not None: - cf_var.standard_name = standard_name + _setncattr(cf_var, 'standard_name', standard_name) if long_name is not None: - cf_var.long_name = long_name + _setncattr(cf_var, 'long_name', long_name) # Add the CF-netCDF calendar attribute. if coord.units.calendar: - cf_var.calendar = coord.units.calendar + _setncattr(cf_var, 'calendar', coord.units.calendar) # Add any other custom coordinate attributes. for name in sorted(coord.attributes): @@ -1144,12 +1690,12 @@ def _create_cf_variable(self, cube, dimension_names, coord, factory_defn): if name == 'STASH': # Adopting provisional Metadata Conventions for representing MO # Scientific Data encoded in NetCDF Format. - name = 'ukmo__um_stash_source' + name = 'um_stash_source' value = str(value) # Don't clobber existing attributes. if not hasattr(cf_var, name): - setattr(cf_var, name, value) + _setncattr(cf_var, name, value) return cf_name @@ -1225,32 +1771,33 @@ def _create_cf_grid_mapping(self, cube, cf_var_cube): # Grid var not yet created? if cs not in self._coord_systems: while cs.grid_mapping_name in self._dataset.variables: - cs.grid_mapping_name = ( - self._increment_name(cs.grid_mapping_name)) + aname = self._increment_name(cs.grid_mapping_name) + cs.grid_mapping_name = aname cf_var_grid = self._dataset.createVariable( cs.grid_mapping_name, np.int32) - cf_var_grid.grid_mapping_name = cs.grid_mapping_name + _setncattr(cf_var_grid, 'grid_mapping_name', + cs.grid_mapping_name) - def add_ellipsoid(): - if cs.ellipsoid: - cf_var_grid.longitude_of_prime_meridian = ( - cs.ellipsoid.longitude_of_prime_meridian) - cf_var_grid.semi_major_axis = ( - cs.ellipsoid.semi_major_axis) - cf_var_grid.semi_minor_axis = ( - cs.ellipsoid.semi_minor_axis) + def add_ellipsoid(ellipsoid): + cf_var_grid.longitude_of_prime_meridian = ( + ellipsoid.longitude_of_prime_meridian) + semi_major = ellipsoid.semi_major_axis + semi_minor = ellipsoid.semi_minor_axis + if semi_minor == semi_major: + cf_var_grid.earth_radius = semi_major + else: + cf_var_grid.semi_major_axis = semi_major + cf_var_grid.semi_minor_axis = semi_minor # latlon if isinstance(cs, iris.coord_systems.GeogCS): - cf_var_grid.longitude_of_prime_meridian = ( - cs.longitude_of_prime_meridian) - cf_var_grid.semi_major_axis = cs.semi_major_axis - cf_var_grid.semi_minor_axis = cs.semi_minor_axis + add_ellipsoid(cs) # rotated latlon elif isinstance(cs, iris.coord_systems.RotatedGeogCS): - add_ellipsoid() + if cs.ellipsoid: + add_ellipsoid(cs.ellipsoid) cf_var_grid.grid_north_pole_latitude = ( cs.grid_north_pole_latitude) cf_var_grid.grid_north_pole_longitude = ( @@ -1260,7 +1807,8 @@ def add_ellipsoid(): # tmerc elif isinstance(cs, iris.coord_systems.TransverseMercator): - add_ellipsoid() + if cs.ellipsoid: + add_ellipsoid(cs.ellipsoid) cf_var_grid.longitude_of_central_meridian = ( cs.longitude_of_central_meridian) cf_var_grid.latitude_of_projection_origin = ( @@ -1270,10 +1818,76 @@ def add_ellipsoid(): cf_var_grid.scale_factor_at_central_meridian = ( cs.scale_factor_at_central_meridian) + # merc + elif isinstance(cs, iris.coord_systems.Mercator): + if cs.ellipsoid: + add_ellipsoid(cs.ellipsoid) + cf_var_grid.longitude_of_projection_origin = ( + cs.longitude_of_projection_origin) + # The Mercator class has implicit defaults for certain + # parameters + cf_var_grid.false_easting = 0.0 + cf_var_grid.false_northing = 0.0 + cf_var_grid.scale_factor_at_projection_origin = 1.0 + + # lcc + elif isinstance(cs, iris.coord_systems.LambertConformal): + if cs.ellipsoid: + add_ellipsoid(cs.ellipsoid) + cf_var_grid.standard_parallel = cs.secant_latitudes + cf_var_grid.latitude_of_projection_origin = cs.central_lat + cf_var_grid.longitude_of_central_meridian = cs.central_lon + cf_var_grid.false_easting = cs.false_easting + cf_var_grid.false_northing = cs.false_northing + + # stereo + elif isinstance(cs, iris.coord_systems.Stereographic): + if cs.true_scale_lat is not None: + warnings.warn('Stereographic coordinate systems with ' + 'true scale latitude specified are not ' + 'yet handled') + else: + if cs.ellipsoid: + add_ellipsoid(cs.ellipsoid) + cf_var_grid.longitude_of_projection_origin = ( + cs.central_lon) + cf_var_grid.latitude_of_projection_origin = ( + cs.central_lat) + cf_var_grid.false_easting = cs.false_easting + cf_var_grid.false_northing = cs.false_northing + # The Stereographic class has an implicit scale + # factor + cf_var_grid.scale_factor_at_projection_origin = 1.0 + # osgb (a specific tmerc) elif isinstance(cs, iris.coord_systems.OSGB): warnings.warn('OSGB coordinate system not yet handled') + # lambert azimuthal equal area + elif isinstance(cs, + iris.coord_systems.LambertAzimuthalEqualArea): + if cs.ellipsoid: + add_ellipsoid(cs.ellipsoid) + cf_var_grid.longitude_of_projection_origin = ( + cs.longitude_of_projection_origin) + cf_var_grid.latitude_of_projection_origin = ( + cs.latitude_of_projection_origin) + cf_var_grid.false_easting = cs.false_easting + cf_var_grid.false_northing = cs.false_northing + + # albers conical equal area + elif isinstance(cs, + iris.coord_systems.AlbersEqualArea): + if cs.ellipsoid: + add_ellipsoid(cs.ellipsoid) + cf_var_grid.longitude_of_central_meridian = ( + cs.longitude_of_central_meridian) + cf_var_grid.latitude_of_projection_origin = ( + cs.latitude_of_projection_origin) + cf_var_grid.false_easting = cs.false_easting + cf_var_grid.false_northing = cs.false_northing + cf_var_grid.standard_parallel = (cs.standard_parallels) + # other else: warnings.warn('Unable to represent the horizontal ' @@ -1283,10 +1897,10 @@ def add_ellipsoid(): self._coord_systems.append(cs) # Refer to grid var - cf_var_cube.grid_mapping = cs.grid_mapping_name + _setncattr(cf_var_cube, 'grid_mapping', cs.grid_mapping_name) def _create_cf_data_variable(self, cube, dimension_names, local_keys=None, - **kwargs): + packing=None, fill_value=None, **kwargs): """ Create CF-netCDF data variable for the cube and any associated grid mapping. @@ -1301,8 +1915,11 @@ def _create_cf_data_variable(self, cube, dimension_names, local_keys=None, Kwargs: * local_keys (iterable of strings): - An interable of cube attribute keys. Any cube attributes - with matching keys will become attributes on the data variable. + * see :func:`iris.fileformats.netcdf.Saver.write` + * packing (type or string or dict or list): + * see :func:`iris.fileformats.netcdf.Saver.write` + * fill_value: + * see :func:`iris.fileformats.netcdf.Saver.write` All other keywords are passed through to the dataset's `createVariable` method. @@ -1311,32 +1928,127 @@ def _create_cf_data_variable(self, cube, dimension_names, local_keys=None, The newly created CF-netCDF data variable. """ + + if packing: + if isinstance(packing, dict): + if 'dtype' not in packing: + msg = "The dtype attribute is required for packing." + raise ValueError(msg) + dtype = np.dtype(packing['dtype']) + scale_factor = packing.get('scale_factor', None) + add_offset = packing.get('add_offset', None) + valid_keys = {'dtype', 'scale_factor', 'add_offset'} + invalid_keys = set(packing.keys()) - valid_keys + if invalid_keys: + msg = ("Invalid packing key(s) found: '{}'. The valid " + "keys are '{}'.".format("', '".join(invalid_keys), + "', '".join(valid_keys))) + raise ValueError(msg) + else: + # We compute the scale_factor and add_offset based on the + # min/max of the data. This requires the data to be loaded. + masked = ma.isMaskedArray(cube.data) + dtype = np.dtype(packing) + cmax = cube.data.max() + cmin = cube.data.min() + n = dtype.itemsize * 8 + if masked: + scale_factor = (cmax - cmin)/(2**n-2) + else: + scale_factor = (cmax - cmin)/(2**n-1) + if dtype.kind == 'u': + add_offset = cmin + elif dtype.kind == 'i': + if masked: + add_offset = (cmax + cmin)/2 + else: + add_offset = cmin + 2**(n-1)*scale_factor + + def set_packing_ncattrs(cfvar): + """Set netCDF packing attributes.""" + if packing: + if scale_factor: + _setncattr(cfvar, 'scale_factor', scale_factor) + if add_offset: + _setncattr(cfvar, 'add_offset', add_offset) + cf_name = self._get_cube_variable_name(cube) while cf_name in self._dataset.variables: cf_name = self._increment_name(cf_name) - # Determine whether there is a cube MDI value. - fill_value = None - if isinstance(cube.data, ma.core.MaskedArray): - fill_value = cube.data.fill_value + # if netcdf3 avoid streaming due to dtype handling + if (not cube.has_lazy_data() or + self._dataset.file_format in ('NETCDF3_CLASSIC', + 'NETCDF3_64BIT')): - # Get the values in a form which is valid for the file format. - data = self._ensure_valid_dtype(cube.data, 'cube', cube) + # Get the values in a form which is valid for the file format. + data = self._ensure_valid_dtype(cube.data, 'cube', cube) + + def store(data, cf_var, fill_value): + cf_var[:] = data + is_masked = ma.is_masked(data) + contains_value = fill_value is not None and fill_value in data + return is_masked, contains_value + else: + data = cube.lazy_data() + + def store(data, cf_var, fill_value): + # Store lazy data and check whether it is masked and contains + # the fill value + target = _FillValueMaskCheckAndStoreTarget(cf_var, fill_value) + da.store([data], [target]) + return target.is_masked, target.contains_value + + if not packing: + dtype = data.dtype.newbyteorder('=') # Create the cube CF-netCDF data variable with data payload. - cf_var = self._dataset.createVariable( - cf_name, data.dtype.newbyteorder('='), dimension_names, - fill_value=fill_value, **kwargs) - cf_var[:] = data + cf_var = self._dataset.createVariable(cf_name, dtype, dimension_names, + fill_value=fill_value, + **kwargs) + set_packing_ncattrs(cf_var) + + # If packing attributes are specified, don't bother checking whether + # the fill value is in the data. + if packing: + fill_value_to_check = None + elif fill_value is not None: + fill_value_to_check = fill_value + else: + fill_value_to_check = netCDF4.default_fillvals[dtype.str[1:]] + + # Store the data and check if it is masked and contains the fill value + is_masked, contains_fill_value = store(data, cf_var, + fill_value_to_check) + + if dtype.itemsize == 1 and fill_value is None: + if is_masked: + msg = ("Cube '{}' contains byte data with masked points, but " + "no fill_value keyword was given. As saved, these " + "points will read back as valid values. To save as " + "masked byte data, please explicitly specify the " + "'fill_value' keyword.") + warnings.warn(msg.format(cube.name())) + elif contains_fill_value: + msg = ("Cube '{}' contains unmasked data points equal to the " + "fill-value, {}. As saved, these points will read back " + "as missing data. To save these as normal values, please " + "specify a 'fill_value' keyword not equal to any valid " + "data points.") + warnings.warn(msg.format(cube.name(), fill_value)) if cube.standard_name: - cf_var.standard_name = cube.standard_name + _setncattr(cf_var, 'standard_name', cube.standard_name) if cube.long_name: - cf_var.long_name = cube.long_name + _setncattr(cf_var, 'long_name', cube.long_name) if cube.units != 'unknown': - cf_var.units = str(cube.units) + _setncattr(cf_var, 'units', str(cube.units)) + + # Add the CF-netCDF calendar attribute. + if cube.units.calendar: + _setncattr(cf_var, 'calendar', cube.units.calendar) # Add data variable-only attribute names to local_keys. if local_keys is None: @@ -1358,7 +2070,7 @@ def _create_cf_data_variable(self, cube, dimension_names, local_keys=None, if attr_name == 'STASH': # Adopting provisional Metadata Conventions for representing MO # Scientific Data encoded in NetCDF Format. - attr_name = 'ukmo__um_stash_source' + attr_name = 'um_stash_source' value = str(value) if attr_name == "ukmo__process_flags": @@ -1370,13 +2082,13 @@ def _create_cf_data_variable(self, cube, dimension_names, local_keys=None, 'global attribute.'.format(attr_name=attr_name) warnings.warn(msg) - setattr(cf_var, attr_name, value) + _setncattr(cf_var, attr_name, value) # Create the CF-netCDF data variable cell method attribute. cell_methods = self._create_cf_cell_methods(cube, dimension_names) if cell_methods: - cf_var.cell_methods = cell_methods + _setncattr(cf_var, 'cell_methods', cell_methods) # Create the CF-netCDF grid mapping. self._create_cf_grid_mapping(cube, cf_var) @@ -1414,7 +2126,7 @@ def _increment_name(self, varname): def save(cube, filename, netcdf_format='NETCDF4', local_keys=None, unlimited_dimensions=None, zlib=False, complevel=4, shuffle=True, fletcher32=False, contiguous=False, chunksizes=None, endian='native', - least_significant_digit=None): + least_significant_digit=None, packing=None, fill_value=None): """ Save cube(s) to a netCDF file, given the cube and the filename. @@ -1425,6 +2137,10 @@ def save(cube, filename, netcdf_format='NETCDF4', local_keys=None, * Keyword arguments specifying how to save the data are applied to each cube. To use different settings for different cubes, use the NetCDF Context manager (:class:`~Saver`) directly. + * The save process will stream the data payload to the file using dask, + enabling large data payloads to be saved and maintaining the 'lazy' + status of the cube's data payload, unless the netcdf_format is explicitly + specified to be 'NETCDF3' or 'NETCDF3_CLASSIC'. Args: @@ -1448,12 +2164,11 @@ def save(cube, filename, netcdf_format='NETCDF4', local_keys=None, * unlimited_dimensions (iterable of strings and/or :class:`iris.coords.Coord` objects): - Explicit list of coordinate names (or coordinate objects) corresponding + List of coordinate names (or coordinate objects) corresponding to coordinate dimensions of `cube` to save with the NetCDF dimension - variable length 'UNLIMITED'. By default, the outermost (first) - dimension for each cube is used. Only the 'NETCDF4' format supports - multiple 'UNLIMITED' dimensions. To save no unlimited dimensions, use - `unlimited_dimensions=[]` (an empty list). + variable length 'UNLIMITED'. By default, no unlimited dimensions are + saved. Only the 'NETCDF4' format supports multiple 'UNLIMITED' + dimensions. * zlib (bool): If `True`, the data will be compressed in the netCDF file using gzip @@ -1502,11 +2217,37 @@ def save(cube, filename, netcdf_format='NETCDF4', local_keys=None, `numpy.around(scale*data)/scale`, where `scale = 2**bits`, and `bits` is determined so that a precision of 0.1 is retained (in this case `bits=4`). From - http://www.cdc.noaa.gov/cdc/conventions/cdc_netcdf_standard.shtml: + http://www.esrl.noaa.gov/psd/data/gridded/conventions/cdc_netcdf_standard.shtml: "least_significant_digit -- power of ten of the smallest decimal place in unpacked data that is a reliable value". Default is `None`, or no quantization, or 'lossless' compression. + * packing (type or string or dict or list): A numpy integer datatype + (signed or unsigned) or a string that describes a numpy integer dtype + (i.e. 'i2', 'short', 'u4') or a dict of packing parameters as described + below or an iterable of such types, strings, or dicts. + This provides support for netCDF data packing as described in + http://www.unidata.ucar.edu/software/netcdf/docs/BestPractices.html#bp_Packed-Data-Values + If this argument is a type (or type string), appropriate values of + scale_factor and add_offset will be automatically calculated based + on `cube.data` and possible masking. For more control, pass a dict with + one or more of the following keys: `dtype` (required), `scale_factor` + and `add_offset`. Note that automatic calculation of packing parameters + will trigger loading of lazy data; set them manually using a dict to + avoid this. The default is `None`, in which case the datatype is + determined from the cube and no packing will occur. If this argument is + a list it must have the same number of elements as `cube` if `cube` is + a `:class:`iris.cube.CubeList`, or one element, and each element of + this argument will be applied to each cube separately. + + * fill_value (numeric or list): + The value to use for the `_FillValue` attribute on the netCDF variable. + If `packing` is specified the value of `fill_value` should be in the + domain of the packed data. If this argument is a list it must have the + same number of elements as `cube` if `cube` is a + `:class:`iris.cube.CubeList`, or a single element, and each element of + this argument will be applied to each cube separately. + Returns: None. @@ -1521,6 +2262,9 @@ def save(cube, filename, netcdf_format='NETCDF4', local_keys=None, NetCDF Context manager (:class:`~Saver`). """ + if unlimited_dimensions is None: + unlimited_dimensions = [] + if isinstance(cube, iris.cube.Cube): cubes = iris.cube.CubeList() cubes.append(cube) @@ -1543,18 +2287,89 @@ def save(cube, filename, netcdf_format='NETCDF4', local_keys=None, common_keys.intersection_update(keys) different_value_keys = [] for key in common_keys: - if attributes[key] != cube.attributes[key]: + if np.any(attributes[key] != cube.attributes[key]): different_value_keys.append(key) common_keys.difference_update(different_value_keys) local_keys.update(different_value_keys) + def is_valid_packspec(p): + """ Only checks that the datatype is valid. """ + if isinstance(p, dict): + if 'dtype' in p: + return is_valid_packspec(p['dtype']) + else: + msg = "The argument to packing must contain the key 'dtype'." + raise ValueError(msg) + elif (isinstance(p, six.text_type) or isinstance(p, type) or + isinstance(p, str)): + pdtype = np.dtype(p) # Does nothing if it's already a numpy dtype + if pdtype.kind != 'i' and pdtype.kind != 'u': + msg = "The packing datatype must be a numpy integer type." + raise ValueError(msg) + return True + elif p is None: + return True + else: + return False + + if is_valid_packspec(packing): + packspecs = repeat(packing) + else: + # Assume iterable, make sure packing is the same length as cubes. + for cube, packspec in zip_longest(cubes, packing, fillvalue=-1): + if cube == -1 or packspec == -1: + msg = ('If packing is a list, it must have the ' + 'same number of elements as the argument to' + 'cube.') + raise ValueError(msg) + if not is_valid_packspec(packspec): + msg = ('Invalid packing argument: {}.'.format(packspec)) + raise ValueError(msg) + packspecs = packing + + # Make fill-value(s) into an iterable over cubes. + if isinstance(fill_value, six.string_types): + # Strings are awkward -- handle separately. + fill_values = repeat(fill_value) + else: + try: + fill_values = tuple(fill_value) + except TypeError: + fill_values = repeat(fill_value) + else: + if len(fill_values) != len(cubes): + msg = ('If fill_value is a list, it must have the ' + 'same number of elements as the cube argument.') + raise ValueError(msg) + # Initialise Manager for saving with Saver(filename, netcdf_format) as sman: # Iterate through the cubelist. - for cube in cubes: + for cube, packspec, fill_value in zip(cubes, packspecs, fill_values): sman.write(cube, local_keys, unlimited_dimensions, zlib, complevel, shuffle, fletcher32, contiguous, chunksizes, endian, - least_significant_digit) + least_significant_digit, packing=packspec, + fill_value=fill_value) + + if iris.config.netcdf.conventions_override: + # Set to the default if custom conventions are not available. + conventions = cube.attributes.get('Conventions', + CF_CONVENTIONS_VERSION) + else: + conventions = CF_CONVENTIONS_VERSION + + # Perform a CF patch of the conventions attribute. + cf_profile_available = (iris.site_configuration.get('cf_profile') not + in [None, False]) + if cf_profile_available: + conventions_patch = iris.site_configuration.get( + 'cf_patch_conventions') + if conventions_patch is not None: + conventions = conventions_patch(conventions) + else: + msg = 'cf_profile is available but no {} defined.'.format( + 'cf_patch_conventions') + warnings.warn(msg) # Add conventions attribute. - sman.update_global_attributes(Conventions=_CF_CONVENTIONS_VERSION) + sman.update_global_attributes(Conventions=conventions) diff --git a/lib/iris/fileformats/nimrod.py b/lib/iris/fileformats/nimrod.py index 61ca285c88..34db078ec8 100644 --- a/lib/iris/fileformats/nimrod.py +++ b/lib/iris/fileformats/nimrod.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -16,6 +16,10 @@ # along with Iris. If not, see . """Provides NIMROD file format capabilities.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + import glob import numpy as np import os @@ -77,7 +81,11 @@ def _read_chars(infile, num): """Read characters from the (big-endian) file.""" instr = infile.read(num) - return struct.unpack(">%ds" % num, instr)[0] + result = struct.unpack(">%ds" % num, instr)[0] + if six.PY3: + # For Python 3, convert raw bytes into a string. + result = result.decode() + return result class NimrodField(object): @@ -220,7 +228,7 @@ def load_cubes(filenames, callback=None): The resultant cubes may not be in the same order as in the files. """ - if isinstance(filenames, basestring): + if isinstance(filenames, six.string_types): filenames = [filenames] for filename in filenames: diff --git a/lib/iris/fileformats/nimrod_load_rules.py b/lib/iris/fileformats/nimrod_load_rules.py index 16dbe5ba4c..3dbb47cc35 100644 --- a/lib/iris/fileformats/nimrod_load_rules.py +++ b/lib/iris/fileformats/nimrod_load_rules.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -16,10 +16,14 @@ # along with Iris. If not, see . """Rules for converting NIMROD fields into cubes.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + import warnings -import netcdftime +import cf_units +import cftime import numpy as np import iris @@ -30,14 +34,21 @@ __all__ = ['run'] -MERIDIAN_SCALING_BNG = 999601 # Merdian scaling for British National grid. +# Meridian scaling for British National grid. +MERIDIAN_SCALING_BNG = 0.9996012717 + +NIMROD_DEFAULT = -32767.0 + +TIME_UNIT = cf_units.Unit('hours since 1970-01-01 00:00:00', + calendar=cf_units.CALENDAR_GREGORIAN) -TIME_UNIT = iris.unit.Unit('hours since 1970-01-01 00:00:00', - calendar=iris.unit.CALENDAR_STANDARD) +FIELD_CODES = {73: "orography"} +VERTICAL_CODES = {0: "height", 1: "altitude", 12: "levels_below_ground"} -FIELD_CODES = {"orography": 73} -VERTICAL_CODES = {"height": 0, "altitude": 1, "levels_below_ground": 12} + +class TranslationWarning(Warning): + pass def name(cube, field): @@ -65,9 +76,9 @@ def units(cube, field): def time(cube, field): """Add a time coord to the cube.""" - valid_date = netcdftime.datetime(field.vt_year, field.vt_month, - field.vt_day, field.vt_hour, - field.vt_minute, field.vt_second) + valid_date = cftime.datetime(field.vt_year, field.vt_month, + field.vt_day, field.vt_hour, + field.vt_minute, field.vt_second) point = TIME_UNIT.date2num(valid_date) bounds = None @@ -86,9 +97,9 @@ def time(cube, field): def reference_time(cube, field): """Add a 'reference time' to the cube, if present in the field.""" if field.dt_year != field.int_mdi: - data_date = netcdftime.datetime(field.dt_year, field.dt_month, - field.dt_day, field.dt_hour, - field.dt_minute) + data_date = cftime.datetime(field.dt_year, field.dt_month, + field.dt_day, field.dt_hour, + field.dt_minute) ref_time_coord = DimCoord(TIME_UNIT.date2num(data_date), standard_name='forecast_reference_time', @@ -114,17 +125,19 @@ def proj_biaxial_ellipsoid(cube, field): def tm_meridian_scaling(cube, field): """ - Deal with 'tm_meridian_scaling', if present in the field. + Deal with the scale factor on the central meridian for transverse mercator + projections if present in the field. Currently only caters for British National Grid. """ - if field.tm_meridian_scaling != field.int_mdi: - if int(field.tm_meridian_scaling * 1e6) == MERIDIAN_SCALING_BNG: + if field.tm_meridian_scaling not in [field.float32_mdi, NIMROD_DEFAULT]: + if abs(field.tm_meridian_scaling - MERIDIAN_SCALING_BNG) < 1e-6: pass # This is the expected value for British National Grid else: - raise TranslationError("tm_meridian_scaling not yet handled: {}". - format(field.tm_meridian_scaling)) + warnings.warn("tm_meridian_scaling not yet handled: {}" + "".format(field.tm_meridian_scaling), + TranslationWarning) def british_national_grid_x(cube, field): @@ -143,10 +156,10 @@ def british_national_grid_y(cube, field): """ if field.origin_corner == 0: # top left - y_coord = DimCoord(np.arange(field.num_rows)[::-1] * - -field.row_step + field.y_origin, - standard_name="projection_y_coordinate", units="m", - coord_system=iris.coord_systems.OSGB()) + y_coord = DimCoord( + np.arange(field.num_rows)[::-1] * -field.row_step + field.y_origin, + standard_name="projection_y_coordinate", units="m", + coord_system=iris.coord_systems.OSGB()) cube.add_dim_coord(y_coord, 0) else: raise TranslationError("Corner {0} not yet implemented". @@ -216,18 +229,21 @@ def levels_below_ground_vertical_coord(cube, field): def vertical_coord(cube, field): """Add a vertical coord to the cube.""" v_type = field.vertical_coord_type - if v_type != field.int_mdi: - if field.field_code == FIELD_CODES["orography"]: + + if v_type not in [field.int_mdi, NIMROD_DEFAULT]: + if FIELD_CODES.get(field.field_code, None) == "orography": orography_vertical_coord(cube, field) - elif v_type == VERTICAL_CODES["height"]: - height_vertical_coord(cube, field) - elif v_type == VERTICAL_CODES["altitude"]: - altitude_vertical_coord(cube, field) - elif v_type == VERTICAL_CODES["levels_below_ground"]: - levels_below_ground_vertical_coord(cube, field) else: - raise TranslationError("Vertical coord type %d not yet handled" % - v_type) + vertical_code_name = VERTICAL_CODES.get(v_type, None) + if vertical_code_name == "height": + height_vertical_coord(cube, field) + elif vertical_code_name == "altitude": + altitude_vertical_coord(cube, field) + elif vertical_code_name == "levels_below_ground": + levels_below_ground_vertical_coord(cube, field) + else: + warnings.warn("Vertical coord {!r} not yet handled" + "".format(v_type), TranslationWarning) def ensemble_member(cube, field): diff --git a/lib/iris/fileformats/pp.py b/lib/iris/fileformats/pp.py index 8b629fd633..5b5f7c8a36 100644 --- a/lib/iris/fileformats/pp.py +++ b/lib/iris/fileformats/pp.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -19,40 +19,50 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + import abc import collections from copy import deepcopy -import itertools import operator import os import re import struct import warnings -import biggus +import cf_units import numpy as np import numpy.ma as ma -import netcdftime +import cftime +from iris._deprecation import warn_deprecated +from iris._lazy_data import as_concrete_data, as_lazy_data, is_lazy_data import iris.config +import iris.fileformats.pp_load_rules +from iris.fileformats.pp_save_rules import verify + +# NOTE: this is for backwards-compatitibility *ONLY* +# We could simply remove it for v2.0 ? +from iris.fileformats._pp_lbproc_pairs import (LBPROC_PAIRS, + LBPROC_MAP as lbproc_map) import iris.fileformats.rules -import iris.unit -import iris.fileformats.pp_rules import iris.coord_systems -import iris.proxy -iris.proxy.apply_proxy('iris.fileformats.pp_packing', globals()) -__all__ = ['load', 'save', 'PPField', 'add_load_rules', 'reset_load_rules', - 'add_save_rules', 'reset_save_rules', 'STASH', 'EARTH_RADIUS'] +try: + import mo_pack +except ImportError: + mo_pack = None -EARTH_RADIUS = 6371229.0 +__all__ = ['load', 'save', 'load_cubes', 'PPField', 'as_fields', + 'load_pairs_from_fields', 'save_pairs_from_cube', 'save_fields', + 'STASH', 'EARTH_RADIUS'] -# PP->Cube and Cube->PP rules are loaded on first use -_load_rules = None -_save_rules = None +EARTH_RADIUS = 6371229.0 PP_HEADER_DEPTH = 256 @@ -64,116 +74,116 @@ #: A list of (header_name, position_in_header(tuple of)) pairs for #: header release 2 - using the one-based UM/FORTRAN indexing convention. UM_HEADER_2 = [ - ('lbyr', (1, )), - ('lbmon', (2, )), - ('lbdat', (3, )), - ('lbhr', (4, )), - ('lbmin', (5, )), - ('lbday', (6, )), - ('lbyrd', (7, )), - ('lbmond', (8, )), - ('lbdatd', (9, )), - ('lbhrd', (10, )), - ('lbmind', (11, )), - ('lbdayd', (12, )), - ('lbtim', (13, )), - ('lbft', (14, )), - ('lblrec', (15, )), - ('lbcode', (16, )), - ('lbhem', (17, )), - ('lbrow', (18, )), - ('lbnpt', (19, )), - ('lbext', (20, )), - ('lbpack', (21, )), - ('lbrel', (22, )), - ('lbfc', (23, )), - ('lbcfc', (24, )), - ('lbproc', (25, )), - ('lbvc', (26, )), - ('lbrvc', (27, )), - ('lbexp', (28, )), - ('lbegin', (29, )), - ('lbnrec', (30, )), - ('lbproj', (31, )), - ('lbtyp', (32, )), - ('lblev', (33, )), - ('lbrsvd', (34, 35, 36, 37, )), - ('lbsrce', (38, )), - ('lbuser', (39, 40, 41, 42, 43, 44, 45, )), - ('brsvd', (46, 47, 48, 49, )), - ('bdatum', (50, )), - ('bacc', (51, )), - ('blev', (52, )), - ('brlev', (53, )), - ('bhlev', (54, )), - ('bhrlev', (55, )), - ('bplat', (56, )), - ('bplon', (57, )), - ('bgor', (58, )), - ('bzy', (59, )), - ('bdy', (60, )), - ('bzx', (61, )), - ('bdx', (62, )), - ('bmdi', (63, )), - ('bmks', (64, )), + ('lbyr', (1, )), + ('lbmon', (2, )), + ('lbdat', (3, )), + ('lbhr', (4, )), + ('lbmin', (5, )), + ('lbday', (6, )), + ('lbyrd', (7, )), + ('lbmond', (8, )), + ('lbdatd', (9, )), + ('lbhrd', (10, )), + ('lbmind', (11, )), + ('lbdayd', (12, )), + ('lbtim', (13, )), + ('lbft', (14, )), + ('lblrec', (15, )), + ('lbcode', (16, )), + ('lbhem', (17, )), + ('lbrow', (18, )), + ('lbnpt', (19, )), + ('lbext', (20, )), + ('lbpack', (21, )), + ('lbrel', (22, )), + ('lbfc', (23, )), + ('lbcfc', (24, )), + ('lbproc', (25, )), + ('lbvc', (26, )), + ('lbrvc', (27, )), + ('lbexp', (28, )), + ('lbegin', (29, )), + ('lbnrec', (30, )), + ('lbproj', (31, )), + ('lbtyp', (32, )), + ('lblev', (33, )), + ('lbrsvd', (34, 35, 36, 37, )), + ('lbsrce', (38, )), + ('lbuser', (39, 40, 41, 42, 43, 44, 45, )), + ('brsvd', (46, 47, 48, 49, )), + ('bdatum', (50, )), + ('bacc', (51, )), + ('blev', (52, )), + ('brlev', (53, )), + ('bhlev', (54, )), + ('bhrlev', (55, )), + ('bplat', (56, )), + ('bplon', (57, )), + ('bgor', (58, )), + ('bzy', (59, )), + ('bdy', (60, )), + ('bzx', (61, )), + ('bdx', (62, )), + ('bmdi', (63, )), + ('bmks', (64, )), ] # The header definition for header release 3. #: A list of (header_name, position_in_header(tuple of)) pairs for #: header release 3 - using the one-based UM/FORTRAN indexing convention. UM_HEADER_3 = [ - ('lbyr', (1, )), - ('lbmon', (2, )), - ('lbdat', (3, )), - ('lbhr', (4, )), - ('lbmin', (5, )), - ('lbsec', (6, )), - ('lbyrd', (7, )), - ('lbmond', (8, )), - ('lbdatd', (9, )), - ('lbhrd', (10, )), - ('lbmind', (11, )), - ('lbsecd', (12, )), - ('lbtim', (13, )), - ('lbft', (14, )), - ('lblrec', (15, )), - ('lbcode', (16, )), - ('lbhem', (17, )), - ('lbrow', (18, )), - ('lbnpt', (19, )), - ('lbext', (20, )), - ('lbpack', (21, )), - ('lbrel', (22, )), - ('lbfc', (23, )), - ('lbcfc', (24, )), - ('lbproc', (25, )), - ('lbvc', (26, )), - ('lbrvc', (27, )), - ('lbexp', (28, )), - ('lbegin', (29, )), - ('lbnrec', (30, )), - ('lbproj', (31, )), - ('lbtyp', (32, )), - ('lblev', (33, )), - ('lbrsvd', (34, 35, 36, 37, )), - ('lbsrce', (38, )), - ('lbuser', (39, 40, 41, 42, 43, 44, 45, )), - ('brsvd', (46, 47, 48, 49, )), - ('bdatum', (50, )), - ('bacc', (51, )), - ('blev', (52, )), - ('brlev', (53, )), - ('bhlev', (54, )), - ('bhrlev', (55, )), - ('bplat', (56, )), - ('bplon', (57, )), - ('bgor', (58, )), - ('bzy', (59, )), - ('bdy', (60, )), - ('bzx', (61, )), - ('bdx', (62, )), - ('bmdi', (63, )), - ('bmks', (64, )), + ('lbyr', (1, )), + ('lbmon', (2, )), + ('lbdat', (3, )), + ('lbhr', (4, )), + ('lbmin', (5, )), + ('lbsec', (6, )), + ('lbyrd', (7, )), + ('lbmond', (8, )), + ('lbdatd', (9, )), + ('lbhrd', (10, )), + ('lbmind', (11, )), + ('lbsecd', (12, )), + ('lbtim', (13, )), + ('lbft', (14, )), + ('lblrec', (15, )), + ('lbcode', (16, )), + ('lbhem', (17, )), + ('lbrow', (18, )), + ('lbnpt', (19, )), + ('lbext', (20, )), + ('lbpack', (21, )), + ('lbrel', (22, )), + ('lbfc', (23, )), + ('lbcfc', (24, )), + ('lbproc', (25, )), + ('lbvc', (26, )), + ('lbrvc', (27, )), + ('lbexp', (28, )), + ('lbegin', (29, )), + ('lbnrec', (30, )), + ('lbproj', (31, )), + ('lbtyp', (32, )), + ('lblev', (33, )), + ('lbrsvd', (34, 35, 36, 37, )), + ('lbsrce', (38, )), + ('lbuser', (39, 40, 41, 42, 43, 44, 45, )), + ('brsvd', (46, 47, 48, 49, )), + ('bdatum', (50, )), + ('bacc', (51, )), + ('blev', (52, )), + ('brlev', (53, )), + ('bhlev', (54, )), + ('bhrlev', (55, )), + ('bplat', (56, )), + ('bplon', (57, )), + ('bgor', (58, )), + ('bzy', (59, )), + ('bdy', (60, )), + ('bzx', (61, )), + ('bdx', (62, )), + ('bmdi', (63, )), + ('bmks', (64, )), ] # A map from header-release-number to header definition @@ -184,57 +194,34 @@ #: A dictionary mapping IB values to their names. EXTRA_DATA = { - 1: 'x', - 2: 'y', - 3: 'lower_y_domain', - 4: 'lower_x_domain', - 5: 'upper_y_domain', - 6: 'upper_x_domain', - 7: 'lower_z_domain', - 8: 'upper_z_domain', - 10: 'field_title', - 11: 'domain_title', - 12: 'x_lower_bound', - 13: 'x_upper_bound', - 14: 'y_lower_bound', - 15: 'y_upper_bound', - } + 1: 'x', + 2: 'y', + 3: 'lower_y_domain', + 4: 'lower_x_domain', + 5: 'upper_y_domain', + 6: 'upper_x_domain', + 7: 'lower_z_domain', + 8: 'upper_z_domain', + 10: 'field_title', + 11: 'domain_title', + 12: 'x_lower_bound', + 13: 'x_upper_bound', + 14: 'y_lower_bound', + 15: 'y_upper_bound', + } #: Maps lbuser[0] to numpy data type. "default" will be interpreted if #: no match is found, providing a warning in such a case. -LBUSER_DTYPE_LOOKUP = {1 :np.dtype('>f4'), - 2 :np.dtype('>i4'), - 3 :np.dtype('>i4'), - -1:np.dtype('>f4'), - -2:np.dtype('>i4'), - -3:np.dtype('>i4'), +LBUSER_DTYPE_LOOKUP = {1: np.dtype('>f4'), + 2: np.dtype('>i4'), + 3: np.dtype('>i4'), + -1: np.dtype('>f4'), + -2: np.dtype('>i4'), + -3: np.dtype('>i4'), 'default': np.dtype('>f4'), } -# LBPROC codes and their English equivalents -LBPROC_PAIRS = ((1, "Difference from another experiment"), - (2, "Difference from zonal (or other spatial) mean"), - (4, "Difference from time mean"), - (8, "X-derivative (d/dx)"), - (16, "Y-derivative (d/dy)"), - (32, "Time derivative (d/dt)"), - (64, "Zonal mean field"), - (128, "Time mean field"), - (256, "Product of two fields"), - (512, "Square root of a field"), - (1024, "Difference between fields at levels BLEV and BRLEV"), - (2048, "Mean over layer between levels BLEV and BRLEV"), - (4096, "Minimum value of field during time period"), - (8192, "Maximum value of field during time period"), - (16384, "Magnitude of a vector, not specifically wind speed"), - (32768, "Log10 of a field"), - (65536, "Variance of a field"), - (131072, "Mean over an ensemble of parallel runs")) - -# lbproc_map is dict mapping lbproc->English and English->lbproc essentially a one to one mapping -lbproc_map = {x : y for x,y in itertools.chain(LBPROC_PAIRS, ((y,x) for x,y in LBPROC_PAIRS))} - class STASH(collections.namedtuple('STASH', 'model section item')): """ @@ -255,9 +242,14 @@ class STASH(collections.namedtuple('STASH', 'model section item')): 3 String conversion results in the MSI format: - >>> print iris.fileformats.pp.STASH(1, 16, 203) + >>> print(iris.fileformats.pp.STASH(1, 16, 203)) m01s16i203 + A stash object can be compared directly + to its string representation: + >>> iris.fileformats.pp.STASH(1, 0, 4) == 'm01s0i004' + True + """ __slots__ = () @@ -283,13 +275,16 @@ def __new__(cls, model, section, item): @staticmethod def from_msi(msi): """Convert a STASH code MSI string to a STASH instance.""" - if not isinstance(msi, basestring): - raise TypeError('Expected STASH code MSI string, got %r' % msi) + if not isinstance(msi, six.string_types): + raise TypeError('Expected STASH code MSI string, got %r' % (msi,)) - msi_match = re.match('^\s*m(.*)s(.*)i(.*)\s*$', msi, re.IGNORECASE) + msi_match = re.match( + '^\s*m(\d+|\?+)s(\d+|\?+)i(\d+|\?+)\s*$', msi, + re.IGNORECASE) if msi_match is None: - raise ValueError('Expected STASH code MSI string "mXXsXXiXXX", got %r' % msi) + raise ValueError('Expected STASH code MSI string "mXXsXXiXXX", ' + 'got %r' % (msi,)) return STASH(*msi_match.groups()) @@ -321,7 +316,7 @@ def _format_member(self, value, num_digits): def lbuser3(self): """Return the lbuser[3] value that this stash represents.""" return (self.section or 0) * 1000 + (self.item or 0) - + def lbuser6(self): """Return the lbuser[6] value that this stash represents.""" return self.model or 0 @@ -330,8 +325,11 @@ def lbuser6(self): def is_valid(self): return '?' not in str(self) + def __hash__(self): + return super(STASH, self).__hash__() + def __eq__(self, other): - if isinstance(other, basestring): + if isinstance(other, six.string_types): return super(STASH, self).__eq__(STASH.from_msi(other)) else: return super(STASH, self).__eq__(other) @@ -342,14 +340,15 @@ def __ne__(self, other): class SplittableInt(object): """ - A class to hold integers which can easily get each decimal digit individually. + A class to hold integers which can easily get each decimal digit + individually. >>> three_six_two = SplittableInt(362) - >>> print three_six_two + >>> print(three_six_two) 362 - >>> print three_six_two[0] + >>> print(three_six_two[0]) 2 - >>> print three_six_two[2] + >>> print(three_six_two[2]) 3 .. note:: No support for negative numbers @@ -362,22 +361,25 @@ def __init__(self, value, name_mapping_dict=None): Kwargs: * name_mapping_dict - (dict) - A special mapping to provide name based access to specific integer positions: + A special mapping to provide name based access to specific integer + positions: >>> a = SplittableInt(1234, {'hundreds': 2}) - >>> print a.hundreds + >>> print(a.hundreds) 2 >>> a.hundreds = 9 - >>> print a.hundreds + >>> print(a.hundreds) 9 - >>> print a + >>> print(a) 1934 """ if value < 0: - raise ValueError('Negative numbers not supported with splittable integers object') + raise ValueError('Negative numbers not supported with splittable' + ' integers object') - # define the name lookup first (as this is the way __setattr__ is plumbed) + # define the name lookup first (as this is the way __setattr__ is + # plumbed) #: A dictionary mapping special attribute names on this object #: to the slices/indices required to access them. self._name_lookup = name_mapping_dict or {} @@ -389,7 +391,8 @@ def __int__(self): return int(self._value) def _calculate_str_value_from_value(self): - # Reverse the string to get the appropriate index when getting the sliced value + # Reverse the string to get the appropriate index when getting the + # sliced value self._strvalue = [int(c) for c in str(self._value)[::-1]] # Associate the names in the lookup table to attributes @@ -397,7 +400,8 @@ def _calculate_str_value_from_value(self): object.__setattr__(self, name, self[index]) def _calculate_value_from_str_value(self): - self._value = np.sum([ 10**i * val for i, val in enumerate(self._strvalue)]) + self._value = np.sum([10**i * val for + i, val in enumerate(self._strvalue)]) def __len__(self): return len(self._strvalue) @@ -408,40 +412,49 @@ def __getitem__(self, key): except IndexError: val = 0 - # if the key returns a list of values, then combine them together to an integer + # if the key returns a list of values, then combine them together + # to an integer if isinstance(val, list): val = sum([10**i * val for i, val in enumerate(val)]) return val def __setitem__(self, key, value): - # The setitem method has been overridden so that assignment using ``val[0] = 1`` style syntax updates + # The setitem method has been overridden so that assignment using + # ``val[0] = 1`` style syntax updates # the entire object appropriately. if (not isinstance(value, int) or value < 0): - raise ValueError('Can only set %s as a positive integer value.' % key) + raise ValueError('Can only set %s as a positive integer value.' + % key) if isinstance(key, slice): if ((key.start is not None and key.start < 0) or - (key.step is not None and key.step < 0) or - (key.stop is not None and key.stop < 0)): - raise ValueError('Cannot assign a value with slice objects containing negative indices.') + (key.step is not None and key.step < 0) or + (key.stop is not None and key.stop < 0)): + raise ValueError('Cannot assign a value with slice objects' + ' containing negative indices.') # calculate the current length of the value of this string current_length = len(range(*key.indices(len(self)))) - # get indices for as many digits as have been requested. Putting the upper limit on the number of digits at 100. + # get indices for as many digits as have been requested. Putting + # the upper limit on the number of digits at 100. indices = range(*key.indices(100)) if len(indices) < len(str(value)): - raise ValueError('Cannot put %s into %s as it has too many digits.' % (value, key)) + raise ValueError('Cannot put %s into %s as it has too many' + ' digits.' % (value, key)) - # Iterate over each of the indices in the slice, zipping them together with the associated digit - for index, digit in zip(indices, str(value).zfill(current_length)[::-1]): + # Iterate over each of the indices in the slice, + # zipping them together with the associated digit + for index, digit in zip(indices, + str(value).zfill(current_length)[::-1]): # assign each digit to the associated index self.__setitem__(index, int(digit)) else: - # If we are trying to set to an index which does not currently exist in _strvalue then extend it to the + # If we are trying to set to an index which does not currently + # exist in _strvalue then extend it to the # appropriate length if (key + 1) > len(self): new_str_value = [0] * (key + 1) @@ -457,8 +470,9 @@ def __setitem__(self, key, value): self._calculate_value_from_str_value() def __setattr__(self, name, value): - # if the attribute is a special value, update the index value which will in turn update the attribute value - if (name != '_name_lookup' and name in self._name_lookup.keys()): + # if the attribute is a special value, update the index value which + # will in turn update the attribute value + if name != '_name_lookup' and name in self._name_lookup: self[self._name_lookup[name]] = value else: object.__setattr__(self, name, value) @@ -467,7 +481,8 @@ def __str__(self): return str(self._value) def __repr__(self): - return 'SplittableInt(%r, name_mapping_dict=%r)' % (self._value, self._name_lookup) + return 'SplittableInt(%r, name_mapping_dict=%r)' % (self._value, + self._name_lookup) def __eq__(self, other): result = NotImplemented @@ -504,135 +519,116 @@ def __ge__(self, other): return self._compare(other, operator.ge) -class BitwiseInt(SplittableInt): - """ - A class to hold an integer, of fixed bit-length, which can easily get/set each bit individually. +def _make_flag_getter(value): + def getter(self): + warn_deprecated('The `flag` attributes are deprecated - please use ' + 'integer bitwise operators instead.') + return int(bool(self._value & value)) + return getter - .. note:: - Uses a fixed number of bits. - Will raise an Error when attempting to access an out-of-range flag. - - >>> a = BitwiseInt(511) - >>> a.flag1 - 1 - >>> a.flag8 - 1 - >>> a.flag128 - 1 - >>> a.flag256 - 1 - >>> a.flag512 - AttributeError: 'BitwiseInt' object has no attribute 'flag512' - >>> a.flag512 = 1 - AttributeError: Cannot set a flag that does not exist: flag512 +def _make_flag_setter(value): + def setter(self, flag): + warn_deprecated('The `flag` attributes are deprecated - please use ' + 'integer bitwise operators instead.') + if not isinstance(flag, bool): + raise TypeError('Can only set bits to True or False') + if flag: + self._value |= value + else: + self._value &= ~value + return setter - """ - def __init__(self, value, num_bits=None): - """ """ # intentionally empty docstring as all covered in the class docstring. +class _FlagMetaclass(type): + NUM_BITS = 18 - SplittableInt.__init__(self, value) - self.flags = () + def __new__(cls, classname, bases, class_dict): + for i in range(cls.NUM_BITS): + value = 2 ** i + name = 'flag{}'.format(value) + class_dict[name] = property(_make_flag_getter(value), + _make_flag_setter(value)) + class_dict['NUM_BITS'] = cls.NUM_BITS + return type.__new__(cls, classname, bases, class_dict) - #do we need to calculate the number of bits based on the given value? - self._num_bits = num_bits - if self._num_bits is None: - self._num_bits = 0 - while((value >> self._num_bits) > 0): - self._num_bits += 1 - else: - #make sure the number of bits is enough to store the given value. - if (value >> self._num_bits) > 0: - raise ValueError("Not enough bits to store value") - self._set_flags_from_value() +class _LBProc(six.with_metaclass(_FlagMetaclass, SplittableInt)): + # Use a metaclass to define the `flag1`, `flag2`, `flag4, etc. + # properties. + def __init__(self, value): + """ + Args: - def _set_flags_from_value(self): - all_flags = [] + * value (int): + The initial value which will determine the flags. - # Set attributes "flag[n]" to 0 or 1 - for i in range(self._num_bits): - flag_name = 1 << i - flag_value = ((self._value >> i) & 1) - object.__setattr__(self, 'flag%d' % flag_name, flag_value) + """ + value = int(value) + if value < 0: + raise ValueError('Negative numbers not supported with ' + 'splittable integers object') + self._value = value - # Add to list off all flags - if flag_value: - all_flags.append(flag_name) + def __setattr__(self, name, value): + object.__setattr__(self, name, value) - self.flags = tuple(all_flags) + def __iadd__(self, value): + self._value += value + return self - def _set_value_from_flags(self): - self._value = 0 - for i in range(self._num_bits): - bit_value = pow(2, i) - flag_name = "flag%i" % bit_value - flag_value = object.__getattribute__(self, flag_name) - self._value += flag_value * bit_value + def __and__(self, value): + return self._value & value def __iand__(self, value): - """Perform an &= operation.""" self._value &= value - self._set_flags_from_value() return self def __ior__(self, value): - """Perform an |= operation.""" self._value |= value - self._set_flags_from_value() return self - def __iadd__(self, value): - """Perform an inplace add operation""" - self._value += value - self._set_flags_from_value() - return self - - def __setattr__(self, name, value): - # Allow setting of the attribute flags - # Are we setting a flag? - if name.startswith("flag") and name != "flags": - #true and false become 1 and 0 - if not isinstance(value, bool): - raise TypeError("Can only set bits to True or False") - - # Setting an existing flag? - if hasattr(self, name): - #which flag? - flag_value = int(name[4:]) - #on or off? - if value: - self |= flag_value - else: - self &= ~flag_value + def __int__(self): + return self._value - # Fail if an attempt has been made to set a flag that does not exist - else: - raise AttributeError("Cannot set a flag that does not exist: %s" % name) + def __repr__(self): + return '_LBProc({})'.format(self._value) - # If we're not setting a flag, then continue as normal - else: - SplittableInt.__setattr__(self, name, value) + def __str__(self): + return str(self._value) class PPDataProxy(object): """A reference to the data payload of a single PP field.""" - __slots__ = ('shape', 'src_dtype', 'path', 'offset', 'data_len', 'lbpack', - 'mdi', 'mask') - - def __init__(self, shape, src_dtype, path, offset, data_len, lbpack, mdi, - mask): + __slots__ = ('shape', 'src_dtype', 'path', 'offset', 'data_len', + '_lbpack', 'boundary_packing', 'mdi', 'mask') + + def __init__(self, shape, src_dtype, path, offset, data_len, + lbpack, boundary_packing, mdi, mask): self.shape = shape self.src_dtype = src_dtype self.path = path self.offset = offset self.data_len = data_len self.lbpack = lbpack + self.boundary_packing = boundary_packing self.mdi = mdi self.mask = mask + # lbpack + def _lbpack_setter(self, value): + self._lbpack = value + + def _lbpack_getter(self): + value = self._lbpack + if not isinstance(self._lbpack, SplittableInt): + mapping = dict(n5=slice(4, None), n4=3, n3=2, n2=1, n1=0) + value = SplittableInt(self._lbpack, mapping) + return value + + lbpack = property(_lbpack_getter, _lbpack_setter) + @property def dtype(self): return self.src_dtype.newbyteorder('=') @@ -649,10 +645,13 @@ def __getitem__(self, keys): with open(self.path, 'rb') as pp_file: pp_file.seek(self.offset, os.SEEK_SET) data_bytes = pp_file.read(self.data_len) - data = _data_bytes_to_shaped_array(data_bytes, self.lbpack, + data = _data_bytes_to_shaped_array(data_bytes, + self.lbpack, + self.boundary_packing, self.shape, self.src_dtype, self.mdi, self.mask) - return data.__getitem__(keys) + data = data.__getitem__(keys) + return np.asanyarray(data, dtype=self.dtype) def __repr__(self): fmt = '<{self.__class__.__name__} shape={self.shape}' \ @@ -687,7 +686,8 @@ def __ne__(self, other): return result -def _data_bytes_to_shaped_array(data_bytes, lbpack, data_shape, data_type, mdi, +def _data_bytes_to_shaped_array(data_bytes, lbpack, boundary_packing, + data_shape, data_type, mdi, mask=None): """ Convert the already read binary data payload into a numpy array, unpacking @@ -697,13 +697,27 @@ def _data_bytes_to_shaped_array(data_bytes, lbpack, data_shape, data_type, mdi, if lbpack.n1 in (0, 2): data = np.frombuffer(data_bytes, dtype=data_type) elif lbpack.n1 == 1: - data = pp_packing.wgdos_unpack(data_bytes, data_shape[0], - data_shape[1], mdi) + if mo_pack is not None: + try: + decompress_wgdos = mo_pack.decompress_wgdos + except AttributeError: + decompress_wgdos = mo_pack.unpack_wgdos + else: + msg = 'Unpacking PP fields with LBPACK of {} ' \ + 'requires mo_pack to be installed'.format(lbpack.n1) + raise ValueError(msg) + data = decompress_wgdos(data_bytes, data_shape[0], data_shape[1], mdi) elif lbpack.n1 == 4: - data = pp_packing.rle_decode(data_bytes, data_shape[0], data_shape[1], mdi) + if mo_pack is not None and hasattr(mo_pack, 'decompress_rle'): + decompress_rle = mo_pack.decompress_rle + else: + msg = 'Unpacking PP fields with LBPACK of {} ' \ + 'requires mo_pack to be installed'.format(lbpack.n1) + raise ValueError(msg) + data = decompress_rle(data_bytes, data_shape[0], data_shape[1], mdi) else: raise iris.exceptions.NotYetImplementedError( - 'PP fields with LBPACK of %s are not yet supported.' % lbpack) + 'PP fields with LBPACK of %s are not yet supported.' % lbpack) # Ensure we have write permission on the data buffer. data.setflags(write=True) @@ -713,27 +727,26 @@ def _data_bytes_to_shaped_array(data_bytes, lbpack, data_shape, data_type, mdi, data.byteswap(True) data.dtype = data.dtype.newbyteorder('=') - if hasattr(lbpack, 'boundary_packing'): + if boundary_packing is not None: # Convert a long string of numbers into a "lateral boundary # condition" array, which is split into 4 quartiles, North # East, South, West and where North and South contain the corners. - - boundary_packing = lbpack.boundary_packing compressed_data = data data = np.ma.masked_all(data_shape) + data.fill_value = mdi boundary_height = boundary_packing.y_halo + boundary_packing.rim_width boundary_width = boundary_packing.x_halo + boundary_packing.rim_width y_height, x_width = data_shape # The height of the east and west components. mid_height = y_height - 2 * boundary_height - + n_s_shape = boundary_height, x_width e_w_shape = mid_height, boundary_width - + # Keep track of our current position in the array. current_posn = 0 - + north = compressed_data[:boundary_height*x_width] current_posn += len(north) data[-boundary_height:, :] = north.reshape(*n_s_shape) @@ -748,7 +761,7 @@ def _data_bytes_to_shaped_array(data_bytes, lbpack, data_shape, data_type, mdi, current_posn + boundary_height * x_width] current_posn += len(south) data[:boundary_height, :] = south.reshape(*n_s_shape) - + west = compressed_data[current_posn: current_posn + boundary_width * mid_height] current_posn += len(west) @@ -762,16 +775,15 @@ def _data_bytes_to_shaped_array(data_bytes, lbpack, data_shape, data_type, mdi, land_mask = mask.data.astype(np.bool) sea_mask = ~land_mask new_data = np.ma.masked_all(land_mask.shape) + new_data.fill_value = mdi if lbpack.n3 == 1: # Land mask packed data. - new_data.mask = sea_mask # Sometimes the data comes in longer than it should be (i.e. it # looks like the compressed data is compressed, but the trailing # data hasn't been clipped off!). new_data[land_mask] = data[:land_mask.sum()] elif lbpack.n3 == 2: # Sea mask packed data. - new_data.mask = land_mask new_data[sea_mask] = data[:sea_mask.sum()] else: raise ValueError('Unsupported mask compression.') @@ -781,26 +793,29 @@ def _data_bytes_to_shaped_array(data_bytes, lbpack, data_shape, data_type, mdi, # Reform in row-column order data.shape = data_shape - # Mask the array? + # Mask the array if mdi in data: data = ma.masked_values(data, mdi, copy=False) return data -# The special headers of the PPField classes which get some improved functionality -_SPECIAL_HEADERS = ('lbtim', 'lbcode', 'lbpack', 'lbproc', - 'data', 'stash', 't1', 't2') +# The special headers of the PPField classes which get some improved +# functionality +_SPECIAL_HEADERS = ('lbtim', 'lbcode', 'lbpack', 'lbproc', 'data', 'stash', + 't1', 't2') def _header_defn(release_number): """ - Returns the zero-indexed header definition for a particular release of a PPField. + Returns the zero-indexed header definition for a particular release of + a PPField. """ um_header = UM_HEADERS[release_number] offset = UM_TO_PP_HEADER_OFFSET - return [(name, tuple(position - offset for position in positions)) for name, positions in um_header] + return [(name, tuple(position - offset for position in positions)) + for name, positions in um_header] def _pp_attribute_names(header_defn): @@ -811,43 +826,100 @@ def _pp_attribute_names(header_defn): the possible extra data headers. """ - normal_headers = list(name for name, positions in header_defn if name not in _SPECIAL_HEADERS) + normal_headers = list(name for name, positions in header_defn + if name not in _SPECIAL_HEADERS) special_headers = list('_' + name for name in _SPECIAL_HEADERS) - extra_data = EXTRA_DATA.values() - return normal_headers + special_headers + extra_data + extra_data = list(EXTRA_DATA.values()) + special_attributes = ['_raw_header', 'raw_lbtim', 'raw_lbpack', + 'boundary_packing', '_index_in_structured_load_file'] + return normal_headers + special_headers + extra_data + special_attributes -class PPField(object): +class PPField(six.with_metaclass(abc.ABCMeta, object)): """ - A generic class for PP fields - not specific to a particular header release number. + A generic class for PP fields - not specific to a particular + header release number. - A PPField instance can easily access the PP header "words" as attributes with some added useful capabilities:: + A PPField instance can easily access the PP header "words" as attributes + with some added useful capabilities:: for field in iris.fileformats.pp.load(filename): - print field.lbyr - print field.lbuser - print field.lbuser[0] - print field.lbtim - print field.lbtim.ia - print field.t1 + print(field.lbyr) + print(field.lbuser) + print(field.lbuser[0]) + print(field.lbtim) + print(field.lbtim.ia) + print(field.t1) """ # NB. Subclasses must define the attribute HEADER_DEFN to be their # zero-based header definition. See PPField2 and PPField3 for examples. - __metaclass__ = abc.ABCMeta - __slots__ = () - def __init__(self): + def __init__(self, header=None): + # Combined header longs and floats data cache. + self._raw_header = header + self.raw_lbtim = None + self.raw_lbpack = None + self.boundary_packing = None + self._index_in_structured_load_file = None + if header is not None: + self.raw_lbtim = header[self.HEADER_DICT['lbtim'][0]] + self.raw_lbpack = header[self.HEADER_DICT['lbpack'][0]] + + def __getattr__(self, key): """ - PPField instances are always created empty, and attributes are added subsequently. - - .. seealso:: - For PP field loading see :func:`load`. + This method supports deferred attribute creation, which offers a + significant loading optimisation, particularly when not all attributes + are referenced and therefore created on the instance. + + When an 'ordinary' HEADER_DICT attribute is required, its associated + header offset is used to lookup the data value/s from the combined + header longs and floats data cache. The attribute is then set with this + value/s on the instance. Thus future lookups for this attribute will be + optimised, avoiding the __getattr__ lookup mechanism again. + + When a 'special' HEADER_DICT attribute (leading underscore) is + required, its associated 'ordinary' (no leading underscore) header + offset is used to lookup the data value/s from the combined header + longs and floats data cache. The 'ordinary' attribute is then set + with this value/s on the instance. This is required as 'special' + attributes have supporting property convenience functionality base on + the attribute value e.g. see 'lbpack' and 'lbtim'. Note that, for + 'special' attributes the interface is via the 'ordinary' attribute but + the underlying attribute value is stored within the 'special' + attribute. """ + try: + loc = self.HEADER_DICT[key] + except KeyError: + if key[0] == '_' and key[1:] in self.HEADER_DICT: + # Must be a special attribute. + loc = self.HEADER_DICT[key[1:]] + else: + cls = self.__class__.__name__ + msg = '{!r} object has no attribute {!r}'.format(cls, key) + raise AttributeError(msg) + + if len(loc) == 1: + value = self._raw_header[loc[0]] + else: + start = loc[0] + stop = loc[-1] + 1 + value = tuple(self._raw_header[start:stop]) + + # Now cache the attribute value on the instance. + if key[0] == '_': + # First we need to assign to the attribute so that the + # special attribute is calculated, then we retrieve it. + setattr(self, key[1:], value) + value = getattr(self, key) + else: + setattr(self, key, value) + return value @abc.abstractproperty def t1(self): @@ -861,67 +933,73 @@ def __repr__(self): """Return a string representation of the PP field.""" # Define an ordering on the basic header names - attribute_priority_lookup = {name: loc[0] for name, loc in self.HEADER_DEFN} - - # With the attributes sorted the order will remain stable if extra attributes are added. - public_attribute_names = attribute_priority_lookup.keys() + EXTRA_DATA.values() - self_attrs = [(name, getattr(self, name, None)) for name in public_attribute_names] - self_attrs = filter(lambda pair: pair[1] is not None, self_attrs) - - # Output any masked data as separate `data` and `mask` - # components, to avoid the standard MaskedArray output - # which causes irrelevant discrepancies between NumPy - # v1.6 and v1.7. - if ma.isMaskedArray(self._data): - # Force the fill value to zero to have the minimum - # impact on the output style. - self_attrs.append(('data.data', self._data.filled(0))) - self_attrs.append(('data.mask', self._data.mask)) - else: - self_attrs.append(('data', self._data)) + attribute_priority_lookup = {name: loc[0] for name, loc + in self.HEADER_DEFN} + + # With the attributes sorted the order will remain stable if extra + # attributes are added. + public_attribute_names = list(attribute_priority_lookup.keys()) + \ + list(EXTRA_DATA.values()) + self_attrs = [(name, getattr(self, name, None)) + for name in public_attribute_names] + self_attrs = [pair for pair in self_attrs if pair[1] is not None] - # sort the attributes by position in the pp header followed, then by alphabetical order. - attributes = sorted(self_attrs, key=lambda pair: (attribute_priority_lookup.get(pair[0], 999), pair[0]) ) + self_attrs.append(('data', self.data)) - return 'PP Field' + ''.join(['\n %s: %s' % (k, v) for k, v in attributes]) + '\n' + # sort the attributes by position in the pp header followed, + # then by alphabetical order. + attributes = sorted(self_attrs, key=lambda pair: + (attribute_priority_lookup.get(pair[0], 999), + pair[0])) + + return 'PP Field' + ''.join(['\n %s: %s' % (k, v) + for k, v in attributes]) + '\n' @property def stash(self): - """A stash property giving access to the associated STASH object, now supporting __eq__""" + """ + A stash property giving access to the associated STASH object, + now supporting __eq__ + + """ if (not hasattr(self, '_stash') or self.lbuser[6] != self._stash.lbuser6() or self.lbuser[3] != self._stash.lbuser3()): - self._stash = STASH(self.lbuser[6], self.lbuser[3] / 1000, self.lbuser[3] % 1000) + self._stash = STASH(self.lbuser[6], self.lbuser[3] // 1000, + self.lbuser[3] % 1000) return self._stash - + @stash.setter def stash(self, stash): - if isinstance(stash, basestring): + if isinstance(stash, six.string_types): self._stash = STASH.from_msi(stash) elif isinstance(stash, STASH): self._stash = stash else: raise ValueError('Cannot set stash to {!r}'.format(stash)) - + # Keep the lbuser up to date. self.lbuser = list(self.lbuser) self.lbuser[6] = self._stash.lbuser6() self.lbuser[3] = self._stash.lbuser3() - # lbtim - def _lbtim_setter(self, new_value): - if not isinstance(new_value, SplittableInt): - # add the ia/ib/ic values for lbtim - new_value = SplittableInt(new_value, {'ia':slice(2, None), 'ib':1, 'ic':0}) - self._lbtim = new_value + @property + def lbtim(self): + return self._lbtim - lbtim = property(lambda self: self._lbtim, _lbtim_setter) + @lbtim.setter + def lbtim(self, value): + value = int(value) + self.raw_lbtim = value + self._lbtim = SplittableInt(value, {'ia': slice(2, None), 'ib': 1, + 'ic': 0}) # lbcode def _lbcode_setter(self, new_value): if not isinstance(new_value, SplittableInt): # add the ix/iy values for lbcode - new_value = SplittableInt(new_value, {'iy':slice(0, 2), 'ix':slice(2, 4)}) + new_value = SplittableInt(new_value, + {'iy': slice(0, 2), 'ix': slice(2, 4)}) self._lbcode = new_value lbcode = property(lambda self: self._lbcode, _lbcode_setter) @@ -929,53 +1007,66 @@ def _lbcode_setter(self, new_value): # lbpack def _lbpack_setter(self, new_value): if not isinstance(new_value, SplittableInt): + self.raw_lbpack = new_value # add the n1/n2/n3/n4/n5 values for lbpack name_mapping = dict(n5=slice(4, None), n4=3, n3=2, n2=1, n1=0) new_value = SplittableInt(new_value, name_mapping) + else: + self.raw_lbpack = new_value._value self._lbpack = new_value lbpack = property(lambda self: self._lbpack, _lbpack_setter) - # lbproc - def _lbproc_setter(self, new_value): - if not isinstance(new_value, BitwiseInt): - new_value = BitwiseInt(new_value, num_bits=18) - self._lbproc = new_value + @property + def lbproc(self): + return self._lbproc - lbproc = property(lambda self: self._lbproc, _lbproc_setter) + @lbproc.setter + def lbproc(self, value): + if not isinstance(value, _LBProc): + value = _LBProc(value) + self._lbproc = value @property def data(self): - """The :class:`numpy.ndarray` representing the multidimensional data of the pp file""" - # Cache the real data on first use - if isinstance(self._data, biggus.Array): - data = self._data.masked_array() - if ma.count_masked(data) == 0: - data = data.data - self._data = data + """ + The :class:`numpy.ndarray` representing the multidimensional data + of the pp file + + """ + if is_lazy_data(self._data): + # Replace with real data on the first access. + self._data = as_concrete_data(self._data) return self._data @data.setter def data(self, value): self._data = value + def core_data(self): + return self._data + @property def calendar(self): """Return the calendar of the field.""" # TODO #577 What calendar to return when ibtim.ic in [0, 3] - calendar = iris.unit.CALENDAR_GREGORIAN + calendar = cf_units.CALENDAR_GREGORIAN if self.lbtim.ic == 2: - calendar = iris.unit.CALENDAR_360_DAY + calendar = cf_units.CALENDAR_360_DAY elif self.lbtim.ic == 4: - calendar = iris.unit.CALENDAR_365_DAY + calendar = cf_units.CALENDAR_365_DAY return calendar - def _read_extra_data(self, pp_file, file_reader, extra_len): + def _read_extra_data(self, pp_file, file_reader, extra_len, + little_ended=False): """Read the extra data section and update the self appropriately.""" + dtype_endian_char = '<' if little_ended else '>' # While there is still extra data to decode run this loop while extra_len > 0: - extra_int_code = struct.unpack_from('>L', file_reader(PP_WORD_DEPTH))[0] + dtype = '%cL' % dtype_endian_char + extra_int_code = struct.unpack_from(dtype, + file_reader(PP_WORD_DEPTH))[0] extra_len -= PP_WORD_DEPTH ib = extra_int_code % 1000 @@ -984,12 +1075,18 @@ def _read_extra_data(self, pp_file, file_reader, extra_len): data_len = ia * PP_WORD_DEPTH if ib == 10: - self.field_title = ''.join(struct.unpack_from('>%dc' % data_len, file_reader(data_len))).rstrip('\00') + dtype = '%c%ds' % (dtype_endian_char, data_len) + field_title = struct.unpack_from(dtype, file_reader(data_len)) + self.field_title = field_title[0].rstrip(b'\00').decode() elif ib == 11: - self.domain_title = ''.join(struct.unpack_from('>%dc' % data_len, file_reader(data_len))).rstrip('\00') + dtype = '%c%ds' % (dtype_endian_char, data_len) + domain_title = struct.unpack_from(dtype, + file_reader(data_len)) + self.domain_title = domain_title[0].rstrip(b'\00').decode() elif ib in EXTRA_DATA: attr_name = EXTRA_DATA[ib] - values = np.fromfile(pp_file, dtype=np.dtype('>f%d' % PP_WORD_DEPTH), count=ia) + dtype = np.dtype('%cf%d' % (dtype_endian_char, PP_WORD_DEPTH)) + values = np.fromfile(pp_file, dtype=dtype, count=ia) # Ensure the values are in the native byte order if not values.dtype.isnative: values.byteswap(True) @@ -1012,15 +1109,18 @@ def y_bounds(self): def save(self, file_handle): """ - Save the PPField to the given file object (typically created with :func:`open`). + Save the PPField to the given file object + (typically created with :func:`open`). :: # to append the field to a file - a_pp_field.save(open(filename, 'ab')) + with open(filename, 'ab') as fh: + a_pp_field.save(fh) # to overwrite/create a file - a_pp_field.save(open(filename, 'wb')) + with open(filename, 'wb') as fh: + a_pp_field.save(fh) .. note:: @@ -1031,22 +1131,34 @@ def save(self, file_handle): """ - # Before we can actually write to file, we need to calculate the header elements. - # First things first, make sure the data is big-endian + # Get the actual data content. data = self.data - if isinstance(data, ma.core.MaskedArray): - data = data.filled(fill_value=self.bmdi) + mdi = self.bmdi + if np.any(data == mdi): + msg = ('PPField data contains unmasked points equal to the fill ' + "value, {}. As saved, these points will read back as " + "missing data. To save these as normal values, please " + "set the field BMDI not equal to any valid data points.") + warnings.warn(msg.format(mdi)) + if isinstance(data, ma.MaskedArray): + if ma.is_masked(data): + data = data.filled(fill_value=mdi) + else: + data = data.data + # Make sure the data is big-endian if data.dtype.newbyteorder('>') != data.dtype: # take a copy of the data when byteswapping data = data.byteswap(False) data.dtype = data.dtype.newbyteorder('>') # Create the arrays which will hold the header information - lb = np.empty(shape=NUM_LONG_HEADERS, dtype=np.dtype(">u%d" % PP_WORD_DEPTH)) - b = np.empty(shape=NUM_FLOAT_HEADERS, dtype=np.dtype(">f%d" % PP_WORD_DEPTH)) + lb = np.empty(shape=NUM_LONG_HEADERS, + dtype=np.dtype(">u%d" % PP_WORD_DEPTH)) + b = np.empty(shape=NUM_FLOAT_HEADERS, + dtype=np.dtype(">f%d" % PP_WORD_DEPTH)) - # Populate the arrays from the PPField + # Fill in the header elements from the PPField for name, pos in self.HEADER_DEFN: try: header_elem = getattr(self, name) @@ -1058,31 +1170,37 @@ def save(self, file_handle): header_elem = int(header_elem) lb[index] = header_elem else: - index = slice(pos[0] - NUM_LONG_HEADERS, pos[-1] - NUM_LONG_HEADERS + 1) + index = slice(pos[0] - NUM_LONG_HEADERS, + pos[-1] - NUM_LONG_HEADERS + 1) b[index] = header_elem - # Although all of the elements are now populated, we still need to update some of the elements in case + # Although all of the elements are now populated, we still need to + # update some of the elements in case # things have changed (for example, the data length etc.) - # Set up a variable to represent the datalength of this PPField in WORDS. + # Set up a variable to represent the datalength of this PPField in + # WORDS. len_of_data_payload = 0 - # set up a list to hold the extra data which will need to be encoded at the end of the data + # set up a list to hold the extra data which will need to be encoded + # at the end of the data extra_items = [] # iterate through all of the possible extra data fields - for ib, extra_data_attr_name in EXTRA_DATA.iteritems(): - # try to get the extra data field, returning None if it doesn't exist + for ib, extra_data_attr_name in six.iteritems(EXTRA_DATA): + # try to get the extra data field, returning None if it doesn't + # exist extra_elem = getattr(self, extra_data_attr_name, None) if extra_elem is not None: # The special case of character extra data must be caught - if isinstance(extra_elem, basestring): + if isinstance(extra_elem, six.string_types): ia = len(extra_elem) - # pad any strings up to a multiple of PP_WORD_DEPTH (this length is # of bytes) + # pad any strings up to a multiple of PP_WORD_DEPTH + # (this length is # of bytes) ia = (PP_WORD_DEPTH - (ia-1) % PP_WORD_DEPTH) + (ia-1) extra_elem = extra_elem.ljust(ia, '\00') # ia is now the datalength in WORDS of the string - ia /= PP_WORD_DEPTH + ia //= PP_WORD_DEPTH else: # ia is the datalength in WORDS ia = np.product(extra_elem.shape) @@ -1092,77 +1210,103 @@ def save(self, file_handle): extra_elem = extra_elem.byteswap(False) extra_elem.dtype = extra_elem.dtype.newbyteorder('>') - # add the number of bytes to the len_of_data_payload variable + the extra integer which will encode ia/ib + # add the number of bytes to the len_of_data_payload variable + # + the extra integer which will encode ia/ib len_of_data_payload += PP_WORD_DEPTH * ia + PP_WORD_DEPTH integer_code = 1000 * ia + ib - extra_items.append( [integer_code, extra_elem] ) + extra_items.append([integer_code, extra_elem]) if ia >= 1000: - raise IOError('PP files cannot write extra data with more than ' - '1000 elements. Tried to write "%s" which has %s ' - 'elements.' % (extra_data_attr_name, ib) + raise IOError('PP files cannot write extra data with more' + ' than 1000 elements. Tried to write "%s"' + ' which has %s elements.' + % (extra_data_attr_name, ib) ) - HEADER_DICT = dict(self.HEADER_DEFN) - # populate lbext in WORDS - lb[HEADER_DICT['lbext'][0]] = len_of_data_payload / PP_WORD_DEPTH + lb[self.HEADER_DICT['lbext'][0]] = len_of_data_payload // PP_WORD_DEPTH # Put the data length of pp.data into len_of_data_payload (in BYTES) - len_of_data_payload += data.size * PP_WORD_DEPTH + lbpack = lb[self.HEADER_DICT['lbpack'][0]] + if lbpack == 0: + len_of_data_payload += data.size * PP_WORD_DEPTH + elif lbpack == 1: + if mo_pack is not None: + try: + compress_wgdos = mo_pack.compress_wgdos + except AttributeError: + compress_wgdos = mo_pack.pack_wgdos + packed_data = compress_wgdos(data.astype(np.float32), + b[self.HEADER_DICT['bacc'][0]-45], + b[self.HEADER_DICT['bmdi'][0]-45]) + len_of_data_payload += len(packed_data) + else: + msg = 'Writing packed pp data with lbpack of {} ' \ + 'requires mo_pack to be installed.'.format(lbpack) + raise NotImplementedError(msg) # populate lbrec in WORDS - lb[HEADER_DICT['lblrec'][0]] = len_of_data_payload / PP_WORD_DEPTH + lb[self.HEADER_DICT['lblrec'][0]] = len_of_data_payload // \ + PP_WORD_DEPTH # populate lbuser[0] to have the data's datatype if data.dtype == np.dtype('>f4'): - lb[HEADER_DICT['lbuser'][0]] = 1 + lb[self.HEADER_DICT['lbuser'][0]] = 1 elif data.dtype == np.dtype('>f8'): - warnings.warn("Downcasting array precision from float64 to float32 for save." - "If float64 precision is required then please save in a different format") + warnings.warn("Downcasting array precision from float64 to float32" + " for save.If float64 precision is required then" + " please save in a different format") data = data.astype('>f4') - lb[HEADER_DICT['lbuser'][0]] = 1 + lb[self.HEADER_DICT['lbuser'][0]] = 1 elif data.dtype == np.dtype('>i4'): - # NB: there is no physical difference between lbuser[0] of 2 or 3 so we encode just 2 - lb[HEADER_DICT['lbuser'][0]] = 2 + # NB: there is no physical difference between lbuser[0] of 2 or 3 + # so we encode just 2 + lb[self.HEADER_DICT['lbuser'][0]] = 2 else: - raise IOError('Unable to write data array to a PP file. The datatype was %s.' % data.dtype) + raise IOError('Unable to write data array to a PP file. ' + 'The datatype was %s.' % data.dtype) # NB: lbegin, lbnrec, lbuser[1] not set up # Now that we have done the manouvering required, write to the file... - if not isinstance(file_handle, file): - raise TypeError('The file_handle argument must be an instance of a Python file object, but got %r. \n' - 'e.g. open(filename, "wb") to open a binary file with write permission.' % type(file_handle)) + if not hasattr(file_handle, 'write'): + raise TypeError('The file_handle argument must be an instance of a' + ' Python file object, but got %r. \n e.g. ' + 'open(filename, "wb") to open a binary file with' + ' write permission.' % type(file_handle)) pp_file = file_handle # header length pp_file.write(struct.pack(">L", PP_HEADER_DEPTH)) - # 49 integers + # 45 integers lb.tofile(pp_file) - # 16 floats + # 19 floats b.tofile(pp_file) - #Header length (again) + # Header length (again) pp_file.write(struct.pack(">L", PP_HEADER_DEPTH)) # Data length (including extra data length) pp_file.write(struct.pack(">L", int(len_of_data_payload))) # the data itself - if lb[HEADER_DICT['lbpack'][0]] == 0: + if lbpack == 0: data.tofile(pp_file) + elif lbpack == 1: + pp_file.write(packed_data) else: - raise NotImplementedError('Writing packed pp data with lbpack of %s ' - 'is not supported.' % lb[HEADER_DICT['lbpack'][0]]) + msg = 'Writing packed pp data with lbpack of {} ' \ + 'is not supported.'.format(lbpack) + raise NotImplementedError(msg) # extra data elements for int_code, extra_data in extra_items: pp_file.write(struct.pack(">L", int(int_code))) - if isinstance(extra_data, basestring): - pp_file.write(struct.pack(">%sc" % len(extra_data), *extra_data)) + if isinstance(extra_data, six.string_types): + pp_file.write(struct.pack(">%ss" % len(extra_data), + extra_data.encode())) else: extra_data = extra_data.astype(np.dtype('>f4')) extra_data.tofile(pp_file) @@ -1175,82 +1319,39 @@ def save(self, file_handle): # From here on define helper methods for PP -> Cube conversion. # - def regular_points(self, xy): - """Return regular points from the PPField, or fail if not regular. - - Args: - - * xy - a string, "x" or "y" to specify the dimension for which to return points. - - .. deprecated:: 1.5 - - """ - msg = "The 'regular_points' method is deprecated." - warnings.warn(msg, UserWarning, stacklevel=2) - - if xy.lower() == "x": - bz = self.bzx - bd = self.bdx - count = self.lbnpt - elif xy.lower() == "y": - bz = self.bzy - bd = self.bdy - count = self.lbrow - else: - raise ValueError("'x' or 'y' not supplied") - - return (bz + bd) + bd * np.arange(count, dtype=np.float32) - - def regular_bounds(self, xy): - """Return regular bounds from the PPField, or fail if not regular. - - Args: - - * xy - a string, "x" or "y" to specify the dimension for which to return points. - - .. deprecated:: 1.5 - - """ - msg = "The 'regular_bounds' method is deprecated." - warnings.warn(msg, UserWarning, stacklevel=2) - - if xy.lower() == "x": - delta = 0.5 * self.bdx - elif xy.lower() == "y": - delta = 0.5 * self.bdy - else: - raise ValueError("'x' or 'y' not supplied") - - points = self.regular_points(xy) - return np.concatenate([[points - delta], [points + delta]]).T - def time_unit(self, time_unit, epoch='epoch'): - return iris.unit.Unit('%s since %s' % (time_unit, epoch), calendar=self.calendar) - - def bounds_adjusted_lbft(self, cube): - """Calculate PP-style forecast period for bounded time.""" - t2_hours_since = iris.unit.Unit("hours since epoch").date2num(self.t2) - - fp_coord = cube.coord('forecast_period') - fp_hours = fp_coord.units.convert(fp_coord.points[0], 'hours') - - t_coord = cube.coord('time') - t_dt = t_coord.units.num2date(t_coord.points[0]) - t_hours_since = iris.unit.Unit("hours since epoch").date2num(t_dt) - - r_hours_since = (t_hours_since - fp_hours) - return t2_hours_since - r_hours_since - + return cf_units.Unit('%s since %s' % (time_unit, epoch), + calendar=self.calendar) + def coord_system(self): """Return a CoordSystem for this PPField. Returns: - Currently, a :class:`~iris.coord_systems.GeogCS` or :class:`~iris.coord_systems.RotatedGeogCS`. + Currently, a :class:`~iris.coord_systems.GeogCS` or + :class:`~iris.coord_systems.RotatedGeogCS`. """ - geog_cs = iris.coord_systems.GeogCS(EARTH_RADIUS) - if self.bplat != 90.0 or self.bplon != 0.0: - geog_cs = iris.coord_systems.RotatedGeogCS(self.bplat, self.bplon, ellipsoid=geog_cs) + geog_cs = iris.coord_systems.GeogCS(EARTH_RADIUS) + + def degrees_ne(angle, ref_angle): + """ + Return whether an angle differs significantly from a set value. + + The inputs are in degrees. + The difference is judged significant if more than 0.0001 degrees. + + """ + return abs(angle - ref_angle) > 0.0001 + + if (degrees_ne(self.bplat, 90.0) or (degrees_ne(self.bplon, 0.0) and + degrees_ne(self.bplon, 180.0))): + # NOTE: when bplat,bplon=90,0 this encodes an unrotated system. + # However, the rotated system which is *equivalent* to an unrotated + # one actually has blat,bplon=90,180, due to a quirk in the + # definition equations. + # So we accept BPLON of 0 *or* 180 to mean 'unrotated'. + geog_cs = iris.coord_systems.RotatedGeogCS( + self.bplat, self.bplon, ellipsoid=geog_cs) return geog_cs @@ -1302,10 +1403,6 @@ def __eq__(self, other): if all(attrs): self_attr = getattr(self, attr) other_attr = getattr(other, attr) - if isinstance(self_attr, biggus.NumpyArrayAdapter): - self_attr = self_attr.concrete - if isinstance(other_attr, biggus.NumpyArrayAdapter): - other_attr = other_attr.concrete if not np.all(self_attr == other_attr): result = False break @@ -1323,16 +1420,19 @@ def __ne__(self, other): class PPField2(PPField): """ - A class to hold a single field from a PP file, with a header release number of 2. + A class to hold a single field from a PP file, with a + header release number of 2. """ HEADER_DEFN = _header_defn(2) + HEADER_DICT = dict(HEADER_DEFN) __slots__ = _pp_attribute_names(HEADER_DEFN) def _get_t1(self): if not hasattr(self, '_t1'): - self._t1 = netcdftime.datetime(self.lbyr, self.lbmon, self.lbdat, self.lbhr, self.lbmin) + self._t1 = cftime.datetime(self.lbyr, self.lbmon, self.lbdat, + self.lbhr, self.lbmin) return self._t1 def _set_t1(self, dt): @@ -1346,11 +1446,14 @@ def _set_t1(self, dt): delattr(self, '_t1') t1 = property(_get_t1, _set_t1, None, - "A netcdftime.datetime object consisting of the lbyr, lbmon, lbdat, lbhr, and lbmin attributes.") + "A cftime.datetime object consisting of the lbyr, lbmon," + " lbdat, lbhr, and lbmin attributes.") def _get_t2(self): if not hasattr(self, '_t2'): - self._t2 = netcdftime.datetime(self.lbyrd, self.lbmond, self.lbdatd, self.lbhrd, self.lbmind) + self._t2 = cftime.datetime(self.lbyrd, self.lbmond, + self.lbdatd, self.lbhrd, + self.lbmind) return self._t2 def _set_t2(self, dt): @@ -1364,20 +1467,25 @@ def _set_t2(self, dt): delattr(self, '_t2') t2 = property(_get_t2, _set_t2, None, - "A netcdftime.datetime object consisting of the lbyrd, lbmond, lbdatd, lbhrd, and lbmind attributes.") + "A cftime.datetime object consisting of the lbyrd, " + "lbmond, lbdatd, lbhrd, and lbmind attributes.") + class PPField3(PPField): """ - A class to hold a single field from a PP file, with a header release number of 3. + A class to hold a single field from a PP file, with a + header release number of 3. """ HEADER_DEFN = _header_defn(3) + HEADER_DICT = dict(HEADER_DEFN) __slots__ = _pp_attribute_names(HEADER_DEFN) def _get_t1(self): if not hasattr(self, '_t1'): - self._t1 = netcdftime.datetime(self.lbyr, self.lbmon, self.lbdat, self.lbhr, self.lbmin, self.lbsec) + self._t1 = cftime.datetime(self.lbyr, self.lbmon, self.lbdat, + self.lbhr, self.lbmin, self.lbsec) return self._t1 def _set_t1(self, dt): @@ -1391,11 +1499,14 @@ def _set_t1(self, dt): delattr(self, '_t1') t1 = property(_get_t1, _set_t1, None, - "A netcdftime.datetime object consisting of the lbyr, lbmon, lbdat, lbhr, lbmin, and lbsec attributes.") + "A cftime.datetime object consisting of the lbyr, lbmon," + " lbdat, lbhr, lbmin, and lbsec attributes.") def _get_t2(self): if not hasattr(self, '_t2'): - self._t2 = netcdftime.datetime(self.lbyrd, self.lbmond, self.lbdatd, self.lbhrd, self.lbmind, self.lbsecd) + self._t2 = cftime.datetime(self.lbyrd, self.lbmond, + self.lbdatd, self.lbhrd, + self.lbmind, self.lbsecd) return self._t2 def _set_t2(self, dt): @@ -1409,7 +1520,9 @@ def _set_t2(self, dt): delattr(self, '_t2') t2 = property(_get_t2, _set_t2, None, - "A netcdftime.datetime object consisting of the lbyrd, lbmond, lbdatd, lbhrd, lbmind, and lbsecd attributes.") + "A cftime.datetime object consisting of the lbyrd, " + "lbmond, lbdatd, lbhrd, lbmind, and lbsecd attributes.") + PP_CLASSES = { 2: PPField2, @@ -1417,27 +1530,19 @@ def _set_t2(self, dt): } -def make_pp_field(header_values): +def make_pp_field(header): # Choose a PP field class from the value of LBREL - lbrel = header_values[21] + lbrel = header[21] if lbrel not in PP_CLASSES: raise ValueError('Unsupported header release number: {}'.format(lbrel)) - pp_field = PP_CLASSES[lbrel]() - for name, loc in pp_field.HEADER_DEFN: - if len(loc) == 1: - value = header_values[loc[0]] - else: - value = header_values[loc[0]:loc[-1]+1] - setattr(pp_field, name, value) + pp_field = PP_CLASSES[lbrel](header) return pp_field -DeferredArrayBytes = collections.namedtuple('DeferredBytes', - 'fname, position, n_bytes, dtype') LoadedArrayBytes = collections.namedtuple('LoadedArrayBytes', 'bytes, dtype') -def load(filename, read_data=False): +def load(filename, read_data=False, little_ended=False): """ Return an iterator of PPFields given a filename. @@ -1448,16 +1553,22 @@ def load(filename, read_data=False): Kwargs: * read_data - boolean - Flag whether or not the data should be read, if False an empty data manager - will be provided which can subsequently load the data on demand. Default False. + Flag whether or not the data should be read, if False an empty + data manager will be provided which can subsequently load the data + on demand. Default False. + + * little_ended - boolean + If True, file contains all little-ended words (header and data). To iterate through all of the fields in a pp file:: for field in iris.fileformats.pp.load(filename): - print field + print(field) """ - return _interpret_fields(_field_gen(filename, read_data_bytes=read_data)) + return _interpret_fields(_field_gen(filename, + read_data_bytes=read_data, + little_ended=little_ended)) def _interpret_fields(fields): @@ -1473,12 +1584,14 @@ def _interpret_fields(fields): for field in fields: # Store the first reference to a land mask, and use this as the # definitive mask for future fields in this generator. - if land_mask is None and field.stash == 'm01s00i030': + if land_mask is None and field.lbuser[6] == 1 and \ + (field.lbuser[3] // 1000) == 0 and \ + (field.lbuser[3] % 1000) == 30: land_mask = field - # Handle land compressed data payloads. - if field.lbpack.n2 == 2: - # If we don't have the land mask yet, we shouldn't yield the field. + # Handle land compressed data payloads, + # when lbpack.n2 is 2. + if (field.raw_lbpack // 10 % 10) == 2: if land_mask is None: landmask_compressed_fields.append(field) continue @@ -1508,27 +1621,32 @@ def _interpret_fields(fields): def _create_field_data(field, data_shape, land_mask): """ Modifies a field's ``_data`` attribute either by: - * converting DeferredArrayBytes into a biggus array, + * converting DeferredArrayBytes into a lazy array, * converting LoadedArrayBytes into an actual numpy array. """ - if isinstance(field._data, LoadedArrayBytes): - loaded_bytes = field._data - field._data = _data_bytes_to_shaped_array(loaded_bytes.bytes, - field.lbpack, data_shape, - loaded_bytes.dtype, - field.bmdi, land_mask) + if isinstance(field.core_data(), LoadedArrayBytes): + loaded_bytes = field.core_data() + field.data = _data_bytes_to_shaped_array(loaded_bytes.bytes, + field.lbpack, + field.boundary_packing, + data_shape, + loaded_bytes.dtype, + field.bmdi, land_mask) else: - # Get hold of the DeferredArrayBytes instance. - deferred_bytes = field._data - proxy = PPDataProxy(data_shape, deferred_bytes.dtype, - deferred_bytes.fname, deferred_bytes.position, - deferred_bytes.n_bytes, field.lbpack, + # Wrap the reference to the data payload within a data proxy + # in order to support deferred data loading. + fname, position, n_bytes, dtype = field.core_data() + proxy = PPDataProxy(data_shape, dtype, + fname, position, n_bytes, + field.raw_lbpack, + field.boundary_packing, field.bmdi, land_mask) - field._data = biggus.NumpyArrayAdapter(proxy) + block_shape = data_shape if 0 not in data_shape else (1, 1) + field.data = as_lazy_data(proxy, chunks=block_shape) -def _field_gen(filename, read_data_bytes): +def _field_gen(filename, read_data_bytes, little_ended=False): """ Returns a generator of "half-formed" PPField instances derived from the given filename. @@ -1542,177 +1660,307 @@ def _field_gen(filename, read_data_bytes): two-dimensional shape of the data. """ - pp_file = open(filename, 'rb') - - # Get a reference to the seek method on the file - # (this is accessed 3* #number of headers so can provide a small performance boost) - pp_file_seek = pp_file.seek - pp_file_read = pp_file.read - - # Keep reading until we reach the end of file - while True: - # Move past the leading header length word - pp_file_seek(PP_WORD_DEPTH, os.SEEK_CUR) - # Get the LONG header entries - header_longs = np.fromfile(pp_file, dtype='>i%d' % PP_WORD_DEPTH, count=NUM_LONG_HEADERS) - # Nothing returned => EOF - if len(header_longs) == 0: - break - # Get the FLOAT header entries - header_floats = np.fromfile(pp_file, dtype='>f%d' % PP_WORD_DEPTH, count=NUM_FLOAT_HEADERS) - header = tuple(header_longs) + tuple(header_floats) - - # Make a PPField of the appropriate sub-class (depends on header release number) - pp_field = make_pp_field(header) - - # Skip the trailing 4-byte word containing the header length - pp_file_seek(PP_WORD_DEPTH, os.SEEK_CUR) - - # Read the word telling me how long the data + extra data is - # This value is # of bytes - len_of_data_plus_extra = struct.unpack_from('>L', pp_file_read(PP_WORD_DEPTH))[0] - if len_of_data_plus_extra != pp_field.lblrec * PP_WORD_DEPTH: - raise ValueError('LBLREC has a different value to the integer recorded after the ' - 'header in the file (%s and %s).' % (pp_field.lblrec * PP_WORD_DEPTH, - len_of_data_plus_extra)) - - # calculate the extra length in bytes - extra_len = pp_field.lbext * PP_WORD_DEPTH - - # Derive size and datatype of payload - data_len = len_of_data_plus_extra - extra_len - dtype = LBUSER_DTYPE_LOOKUP.get(pp_field.lbuser[0], - LBUSER_DTYPE_LOOKUP['default']) - - if read_data_bytes: - # Read the actual bytes. This can then be converted to a numpy array - # at a higher level. - pp_field._data = LoadedArrayBytes(pp_file.read(data_len), dtype) - else: - # Provide enough context to read the data bytes later on. - pp_field._data = DeferredArrayBytes(filename, pp_file.tell(), data_len, dtype) - # Seek over the actual data payload. - pp_file_seek(data_len, os.SEEK_CUR) + dtype_endian_char = '<' if little_ended else '>' + with open(filename, 'rb') as pp_file: + # Get a reference to the seek method on the file + # (this is accessed 3* #number of headers so can provide a small + # performance boost) + pp_file_seek = pp_file.seek + pp_file_read = pp_file.read + + field_count = 0 + # Keep reading until we reach the end of file + while True: + # Move past the leading header length word + pp_file_seek(PP_WORD_DEPTH, os.SEEK_CUR) + # Get the LONG header entries + dtype = '%ci%d' % (dtype_endian_char, PP_WORD_DEPTH) + header_longs = np.fromfile(pp_file, dtype=dtype, + count=NUM_LONG_HEADERS) + # Nothing returned => EOF + if len(header_longs) == 0: + break + # Get the FLOAT header entries + dtype = '%cf%d' % (dtype_endian_char, PP_WORD_DEPTH) + header_floats = np.fromfile(pp_file, dtype=dtype, + count=NUM_FLOAT_HEADERS) + header = tuple(header_longs) + tuple(header_floats) + + # Make a PPField of the appropriate sub-class (depends on header + # release number) + try: + pp_field = make_pp_field(header) + except ValueError as e: + msg = 'Unable to interpret field {}. {}. Skipping ' \ + 'the remainder of the file.'.format(field_count, + str(e)) + warnings.warn(msg) + break + + # Skip the trailing 4-byte word containing the header length + pp_file_seek(PP_WORD_DEPTH, os.SEEK_CUR) + + # Read the word telling me how long the data + extra data is + # This value is # of bytes + len_of_data_plus_extra = struct.unpack_from( + '%cL' % dtype_endian_char, + pp_file_read(PP_WORD_DEPTH))[0] + if len_of_data_plus_extra != pp_field.lblrec * PP_WORD_DEPTH: + wmsg = ('LBLREC has a different value to the integer recorded ' + 'after the header in the file ({} and {}). ' + 'Skipping the remainder of the file.') + warnings.warn(wmsg.format(pp_field.lblrec * PP_WORD_DEPTH, + len_of_data_plus_extra)) + break + + # calculate the extra length in bytes + extra_len = pp_field.lbext * PP_WORD_DEPTH + + # Derive size and datatype of payload + data_len = len_of_data_plus_extra - extra_len + dtype = LBUSER_DTYPE_LOOKUP.get(pp_field.lbuser[0], + LBUSER_DTYPE_LOOKUP['default']) + if little_ended: + # Change data dtype for a little-ended file. + dtype = str(dtype) + if dtype[0] != '>': + msg = ("Unexpected dtype {!r} can't be converted to " + "little-endian") + raise ValueError(msg) + + dtype = np.dtype('<' + dtype[1:]) + + if read_data_bytes: + # Read the actual bytes. This can then be converted to a numpy + # array at a higher level. + pp_field.data = LoadedArrayBytes(pp_file.read(data_len), + dtype) + else: + # Provide enough context to read the data bytes later on. + pp_field.data = (filename, pp_file.tell(), data_len, dtype) + # Seek over the actual data payload. + pp_file_seek(data_len, os.SEEK_CUR) - # Do we have any extra data to deal with? - if extra_len: - pp_field._read_extra_data(pp_file, pp_file_read, extra_len) + # Do we have any extra data to deal with? + if extra_len: + pp_field._read_extra_data(pp_file, pp_file_read, extra_len, + little_ended=little_ended) - # Skip that last 4 byte record telling me the length of the field I have already read - pp_file_seek(PP_WORD_DEPTH, os.SEEK_CUR) - yield pp_field - pp_file.close() + # Skip that last 4 byte record telling me the length of the field I + # have already read + pp_file_seek(PP_WORD_DEPTH, os.SEEK_CUR) + field_count += 1 + yield pp_field -def _ensure_load_rules_loaded(): - """Makes sure the standard conversion and verification rules are loaded.""" +# Stash codes not to be filtered (reference altitude and pressure fields). +_STASH_ALLOW = [STASH(1, 0, 33), STASH(1, 0, 1)] - # Uses these module-level variables - global _load_rules, _cross_reference_rules - rules = iris.fileformats.rules +def _convert_constraints(constraints): + """ + Converts known constraints from Iris semantics to PP semantics + ignoring all unknown constraints. - if _load_rules is None: - basepath = iris.config.CONFIG_PATH - _load_rules = rules.RulesContainer(os.path.join(basepath, 'pp_rules.txt')) + """ + constraints = iris._constraints.list_of_constraints(constraints) + pp_constraints = {} + unhandled_constraints = False - if _cross_reference_rules is None: - basepath = iris.config.CONFIG_PATH - _cross_reference_rules = rules.RulesContainer(os.path.join(basepath, 'pp_cross_reference_rules.txt'), - rule_type=rules.ObjectReturningRule) + def _make_func(stashobj): + """ + Provides unique name-space for each lambda function's stashobj + variable. + """ + return lambda stash: stash == stashobj + + for con in constraints: + if isinstance(con, iris.AttributeConstraint) and \ + list(con._attributes.keys()) == ['STASH']: + # Convert a STASH constraint. + # The attribute can be a STASH object, a stashcode string, or a + # callable. + stashobj = con._attributes['STASH'] + if callable(stashobj): + call_func = stashobj + elif isinstance(stashobj, (six.string_types, STASH)): + call_func = _make_func(stashobj) + else: + raise TypeError("STASH constraints should be either a" + " callable, string or STASH object") + if 'stash' not in pp_constraints: + pp_constraints['stash'] = [call_func] + else: + pp_constraints['stash'].append(call_func) + else: + # only keep the pp constraints set if they are all handled as + # pp constraints + unhandled_constraints = True -def add_load_rules(filename): - """ - Registers a rules file for use during the PP load process. + def pp_filter(field): + """ + return True if field is to be kept, + False if field does not match filter - Registered files are processed after the standard conversion rules, and in - the order they were registered. - - .. deprecated:: 1.5 + """ + res = True + if field.stash not in _STASH_ALLOW: + if pp_constraints.get('stash'): - """ - msg = "The 'add_load_rules' function is deprecated." - warnings.warn(msg, UserWarning, stacklevel=2) + res = False + for call_func in pp_constraints['stash']: - # Uses this module-level variable - global _load_rules + if call_func(str(field.stash)): + res = True + break + return res - if _load_rules is None: - _load_rules = iris.fileformats.rules.RulesContainer(filename) + if pp_constraints and not unhandled_constraints: + result = pp_filter else: - _load_rules.import_rules(filename) + result = None + return result -def reset_load_rules(): - """Resets the PP load process to use only the standard conversion rules.""" +def load_cubes(filenames, callback=None, constraints=None): + """ + Loads cubes from a list of pp filenames. - # Uses this module-level variable - global _load_rules + Args: - _load_rules = None + * filenames - list of pp filenames to load + Kwargs: -def _ensure_save_rules_loaded(): - """Makes sure the standard save rules are loaded.""" + * constraints - a list of Iris constraints - # Uses these module-level variables - global _save_rules + * callback - a function which can be passed on to + :func:`iris.io.run_callback` - if _save_rules is None: - # Load the pp save rules - rules_filename = os.path.join(iris.config.CONFIG_PATH, 'pp_save_rules.txt') - _save_rules = iris.fileformats.rules.RulesContainer(rules_filename, iris.fileformats.rules.ProcedureRule) + .. note:: + The resultant cubes may not be in the order that they are in the file + (order is not preserved when there is a field with orography + references) -def add_save_rules(filename): """ - Registers a rules file for use during the PP save process. + return _load_cubes_variable_loader(filenames, callback, load, + constraints=constraints) - Registered files are processed after the standard conversion rules, and in - the order they were registered. +def load_cubes_little_endian(filenames, callback=None, constraints=None): """ - _ensure_save_rules_loaded() - _save_rules.import_rules(filename) + Loads cubes from a list of pp filenames containing little-endian data. + Args: -def reset_save_rules(): - """Resets the PP save process to use only the standard conversion rules.""" + * filenames - list of pp filenames to load - # Uses this module-level variable - global _save_rules + Kwargs: - _save_rules = None + * constraints - a list of Iris constraints + * callback - a function which can be passed on to + :func:`iris.io.run_callback` -def load_cubes(filenames, callback=None): - """ - Loads cubes from a list of pp filenames. + .. note:: - Args: + The resultant cubes may not be in the order that they are in the file + (order is not preserved when there is a field with orography + references) - * filenames - list of pp filenames to load + """ + return _load_cubes_variable_loader(filenames, callback, load, + {'little_ended': True}, + constraints=constraints) - Kwargs: - * callback - a function which can be passed on to :func:`iris.io.run_callback` +def load_pairs_from_fields(pp_fields): + """ + Convert an iterable of PP fields into an iterable of tuples of + (Cubes, PPField). - .. note:: + Args: - The resultant cubes may not be in the order that they are in the file (order - is not preserved when there is a field with orography references) + * pp_fields: + An iterable of :class:`iris.fileformats.pp.PPField`. + + Returns: + An iterable of :class:`iris.cube.Cube`\ s. + + This capability can be used to filter out fields before they are passed to + the load pipeline, and amend the cubes once they are created, using + PP metadata conditions. Where this filtering + removes a significant number of fields, the speed up to load can be + significant: + + >>> import iris + >>> from iris.fileformats.pp import load_pairs_from_fields + >>> filename = iris.sample_data_path('E1.2098.pp') + >>> filtered_fields = [] + >>> for field in iris.fileformats.pp.load(filename): + ... if field.lbproc == 128: + ... filtered_fields.append(field) + >>> cube_field_pairs = load_pairs_from_fields(filtered_fields) + >>> for cube, field in cube_field_pairs: + ... cube.attributes['lbproc'] = field.lbproc + ... print(cube.attributes['lbproc']) + 128 + + This capability can also be used to alter fields before they are passed to + the load pipeline. Fields with out of specification header elements can + be cleaned up this way and cubes created: + + >>> filename = iris.sample_data_path('E1.2098.pp') + >>> cleaned_fields = list(iris.fileformats.pp.load(filename)) + >>> for field in cleaned_fields: + ... if field.lbrel == 0: + ... field.lbrel = 3 + >>> cubes_field_pairs = list(load_pairs_from_fields(cleaned_fields)) """ - return _load_cubes_variable_loader(filenames, callback, load) + load_pairs_from_fields = iris.fileformats.rules.load_pairs_from_fields + return load_pairs_from_fields(pp_fields, + iris.fileformats.pp_load_rules.convert) def _load_cubes_variable_loader(filenames, callback, loading_function, - loading_function_kwargs=None): - pp_loader = iris.fileformats.rules.Loader( - loading_function, loading_function_kwargs or {}, - iris.fileformats.pp_rules.convert, _load_rules) - return iris.fileformats.rules.load_cubes(filenames, callback, pp_loader) + loading_function_kwargs=None, + constraints=None): + import iris.fileformats.um._fast_load as um_fast_load + pp_filter = None + if constraints is not None: + pp_filter = _convert_constraints(constraints) + if um_fast_load.STRUCTURED_LOAD_CONTROLS.loads_use_structured: + # For structured loads, pass down the pp_filter function as an extra + # keyword to the low-level generator function. + loading_function_kwargs = loading_function_kwargs or {} + loading_function_kwargs['pp_filter'] = pp_filter + # Also do *not* use this filter in generic rules processing, as for + # structured loading, the 'field' of rules processing is no longer a + # PPField but a FieldCollation. + pp_filter = None + # Make a loader object for the generic rules code. + loader = iris.fileformats.rules.Loader( + um_fast_load._basic_load_function, + loading_function_kwargs, + um_fast_load._convert_collation) + else: + loader = iris.fileformats.rules.Loader( + loading_function, loading_function_kwargs or {}, + iris.fileformats.pp_load_rules.convert) + + result = iris.fileformats.rules.load_cubes(filenames, callback, loader, + pp_filter) + + if um_fast_load.STRUCTURED_LOAD_CONTROLS.loads_use_structured: + # We need an additional concatenate-like operation to combine cubes + # from different files. Unfortunately, the 'merge' call provided in + # the iris_load_xx functions cannot do this. + result = um_fast_load._combine_structured_cubes(result) + + return result def save(cube, target, append=False, field_coords=None): @@ -1721,28 +1969,59 @@ def save(cube, target, append=False, field_coords=None): Args: - * cube - A :class:`iris.cube.Cube`, :class:`iris.cube.CubeList` or list of cubes. + * cube - A :class:`iris.cube.Cube` * target - A filename or open file handle. Kwargs: - * append - Whether to start a new file afresh or add the cube(s) to the end of the file. - Only applicable when target is a filename, not a file handle. + * append - Whether to start a new file afresh or add the cube(s) + to the end of the file. + Only applicable when target is a filename, not a file + handle. Default is False. - * field_coords - list of 2 coords or coord names which are to be used for - reducing the given cube into 2d slices, which will ultimately - determine the x and y coordinates of the resulting fields. - If None, the final two dimensions are chosen for slicing. + * field_coords - list of 2 coords or coord names which are to be used + for reducing the given cube into 2d slices, + which will ultimately determine the x and y + coordinates of the resulting fields. + If None, the final two dimensions are chosen + for slicing. See also :func:`iris.io.save`. """ + fields = as_fields(cube, field_coords, target) + save_fields(fields, target, append=append) + + +def save_pairs_from_cube(cube, field_coords=None, target=None): + """ + Use the PP saving rules to convert a cube or + iterable of cubes to an iterable of (2D cube, PP field) pairs. + + Args: + + * cube: + A :class:`iris.cube.Cube` + Kwargs: + + * field_coords: + List of 2 coords or coord names which are to be used for + reducing the given cube into 2d slices, which will ultimately + determine the x and y coordinates of the resulting fields. + If None, the final two dimensions are chosen for slicing. + + * target: + A filename or open file handle. + + """ # Open issues - # Could use rules in "sections" ... e.g. to process the extensive dimensions; ...? + # Could use rules in "sections" ... e.g. to process the extensive + # dimensions; ...? # Could pre-process the cube to add extra convenient terms? - # e.g. x-coord, y-coord ... but what about multiple coordinates on the dimension? + # e.g. x-coord, y-coord ... but what about multiple coordinates on the + # dimension? # How to perform the slicing? # Do we always slice in the last two dimensions? @@ -1776,18 +2055,6 @@ def save(cube, target, append=False, field_coords=None): # On the flip side, record which Cube metadata has been "used" and flag up # unused? - _ensure_save_rules_loaded() - - # pp file - if isinstance(target, basestring): - pp_file = open(target, "ab" if append else "wb") - elif hasattr(target, "write"): - if hasattr(target, "mode") and "b" not in target.mode: - raise ValueError("Target not binary") - pp_file = target - else: - raise ValueError("Can only save pp to filename or writable") - n_dims = len(cube.shape) if n_dims < 2: raise ValueError('Unable to save a cube of fewer than 2 dimensions.') @@ -1796,12 +2063,14 @@ def save(cube, target, append=False, field_coords=None): # cast the given coord/coord names into cube coords field_coords = cube._as_list_of_coords(field_coords) if len(field_coords) != 2: - raise ValueError('Got %s coordinates in field_coords, expecting exactly 2.' % len(field_coords)) + raise ValueError('Got %s coordinates in field_coords, expecting' + ' exactly 2.' % len(field_coords)) else: - # default to the last two dimensions (if result of coords is an empty list, will - # raise an IndexError) + # default to the last two dimensions + # (if result of coords is an empty list, will raise an IndexError) # NB watch out for the ordering of the dimensions - field_coords = (cube.coords(dimensions=n_dims-2)[0], cube.coords(dimensions=n_dims-1)[0]) + field_coords = (cube.coords(dimensions=n_dims-2)[0], + cube.coords(dimensions=n_dims-1)[0]) # Save each named or latlon slice2D in the cube for slice2D in cube.slices(field_coords): @@ -1812,7 +2081,8 @@ def save(cube, target, append=False, field_coords=None): # and some others to be present before running the rules. for name, positions in pp_field.HEADER_DEFN: # Establish whether field name is integer or real - default = 0 if positions[0] <= NUM_LONG_HEADERS - UM_TO_PP_HEADER_OFFSET else 0.0 + default = 0 if positions[0] <= NUM_LONG_HEADERS - \ + UM_TO_PP_HEADER_OFFSET else 0.0 # Establish whether field position is scalar or composite if len(positions) > 1: default = [default] * len(positions) @@ -1823,22 +2093,110 @@ def save(cube, target, append=False, field_coords=None): pp_field.lbcode = 1 # Grid code. pp_field.bmks = 1.0 # Some scaley thing. pp_field.lbproc = 0 + # Set the missing-data value to the standard default value. + # The save code uses this header word to fill masked data points. + pp_field.bmdi = -1e30 # From UM doc F3: "Set to -99 if LBEGIN not known" pp_field.lbuser[1] = -99 - # Set the data - pp_field.data = slice2D.data + # Set the data, keeping it lazy where possible. + pp_field.data = slice2D.core_data() # Run the PP save rules on the slice2D, to fill the PPField, # recording the rules that were used - rules_result = _save_rules.verify(slice2D, pp_field) - verify_rules_ran = rules_result.matching_rules + pp_field = verify(slice2D, pp_field) + + yield (slice2D, pp_field) + + +def as_fields(cube, field_coords=None, target=None): + """ + Use the PP saving rules (and any user rules) to convert a cube to + an iterable of PP fields. + + Args: + + * cube: + A :class:`iris.cube.Cube` + + Kwargs: + + * field_coords: + List of 2 coords or coord names which are to be used for + reducing the given cube into 2d slices, which will ultimately + determine the x and y coordinates of the resulting fields. + If None, the final two dimensions are chosen for slicing. + + * target: + A filename or open file handle. + + """ + return (field for cube, field in save_pairs_from_cube( + cube, field_coords=field_coords, target=target)) + + +def save_fields(fields, target, append=False): + """ + Save an iterable of PP fields to a PP file. + + Args: + + * fields: + An iterable of PP fields. + * target: + A filename or open file handle. + + Kwargs: + + * append: + Whether to start a new file afresh or add the cube(s) to the end + of the file. + Only applicable when target is a filename, not a file handle. + Default is False. + * callback: + A modifier/filter function. + + See also :func:`iris.io.save`. + + """ + # Open issues + + # Deal with: + # LBLREC - Length of data record in words (incl. extra data) + # Done on save(*) + # LBUSER[0] - Data type + # Done on save(*) + # LBUSER[1] - Start address in DATA (?! or just set to "null"?) + # BLEV - Level - the value of the coordinate for LBVC - # Log the rules used - iris.fileformats.rules.log('PP_SAVE', target if isinstance(target, basestring) else target.name, verify_rules_ran) + # *) With the current on-save way of handling LBLREC and LBUSER[0] we can't + # check if they've been set correctly without *actually* saving as a binary + # PP file. That also means you can't use the same reference.txt file for + # loaded vs saved fields (unless you re-load the saved field!). - # Write to file - pp_field.save(pp_file) + # Set to (or leave as) "null": + # LBEGIN - Address of start of field in direct access dataset + # LBEXP - Experiment identification + # LBPROJ - Fields file projection number + # LBTYP - Fields file field type code + # LBLEV - Fields file level code / hybrid height model level + + if isinstance(target, six.string_types): + pp_file = open(target, "ab" if append else "wb") + filename = target + elif hasattr(target, "write"): + if hasattr(target, "mode") and "b" not in target.mode: + raise ValueError("Target not binary") + filename = target.name if hasattr(target, 'name') else None + pp_file = target + else: + raise ValueError("Can only save pp to filename or writable") - if isinstance(target, basestring): - pp_file.close() + try: + # Save each field + for pp_field in fields: + # Write to file + pp_field.save(pp_file) + finally: + if isinstance(target, six.string_types): + pp_file.close() diff --git a/lib/iris/fileformats/pp_load_rules.py b/lib/iris/fileformats/pp_load_rules.py new file mode 100644 index 0000000000..88a215546b --- /dev/null +++ b/lib/iris/fileformats/pp_load_rules.py @@ -0,0 +1,1066 @@ +# (C) British Crown Copyright 2013 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +# Historically this was auto-generated from +# SciTools/iris-code-generators:tools/gen_rules.py + +import cf_units +import numpy as np +import calendar + +from iris.aux_factory import HybridHeightFactory, HybridPressureFactory +from iris.coords import AuxCoord, CellMethod, DimCoord +from iris.fileformats.rules import (ConversionMetadata, Factory, Reference, + ReferenceTarget) +import iris.fileformats.pp +from iris.fileformats._pp_lbproc_pairs import LBPROC_MAP +from iris.fileformats.um_cf_map import (LBFC_TO_CF, STASH_TO_CF, + STASHCODE_IMPLIED_HEIGHTS) + + +############################################################################### +# +# Convert vectorisation routines. +# + +def _dim_or_aux(*args, **kwargs): + try: + result = DimCoord(*args, **kwargs) + except ValueError: + attr = kwargs.get('attributes') + if attr is not None and 'positive' in attr: + del attr['positive'] + result = AuxCoord(*args, **kwargs) + return result + + +def _convert_vertical_coords(lbcode, lbvc, blev, lblev, stash, + bhlev, bhrlev, brsvd1, brsvd2, brlev, + dim=None): + """ + Encode scalar or vector vertical level values from PP headers as CM data + components. + + Args: + + * lbcode: + Scalar field :class:`iris.fileformats.pp.SplittableInt` value. + + * lbvc: + Scalar field value. + + * blev: + Scalar field value or :class:`numpy.ndarray` vector of field values. + + * lblev: + Scalar field value or :class:`numpy.ndarray` vector of field values. + + * stash: + Scalar field :class:`iris.fileformats.pp.STASH` value. + + * bhlev: + Scalar field value or :class:`numpy.ndarray` vector of field values. + + * bhrlev: + Scalar field value or :class:`numpy.ndarray` vector of field values. + + * brsvd1: + Scalar field value or :class:`numpy.ndarray` vector of field values. + + * brsvd2: + Scalar field value or :class:`numpy.ndarray` vector of field values. + + * brlev: + Scalar field value or :class:`numpy.ndarray` vector of field values. + + Kwargs: + + * dim: + Associated dimension of the vertical coordinate. Defaults to None. + + Returns: + A tuple containing a list of coords_and_dims, and a list of factories. + + """ + factories = [] + coords_and_dims = [] + + # See Word no. 33 (LBLEV) in section 4 of UM Model Docs (F3). + BASE_RHO_LEVEL_LBLEV = 9999 + model_level_number = np.atleast_1d(lblev) + model_level_number[model_level_number == BASE_RHO_LEVEL_LBLEV] = 0 + + # Ensure to vectorise these arguments as arrays, as they participate + # in the conditions of convert rules. + blev = np.atleast_1d(blev) + brsvd1 = np.atleast_1d(brsvd1) + brlev = np.atleast_1d(brlev) + + # Height. + if (lbvc == 1) and \ + str(stash) not in STASHCODE_IMPLIED_HEIGHTS and \ + np.all(blev != -1): + coord = _dim_or_aux(blev, standard_name='height', units='m', + attributes={'positive': 'up'}) + coords_and_dims.append((coord, dim)) + + if str(stash) in STASHCODE_IMPLIED_HEIGHTS: + height = STASHCODE_IMPLIED_HEIGHTS[str(stash)] + coord = DimCoord(height, standard_name='height', units='m', + attributes={'positive': 'up'}) + coords_and_dims.append((coord, None)) + + # Model level number. + if (len(lbcode) != 5) and \ + (lbvc == 2): + coord = _dim_or_aux(model_level_number, standard_name='model_level_number', + attributes={'positive': 'down'}) + coords_and_dims.append((coord, dim)) + + # Depth - unbound. + if (len(lbcode) != 5) and \ + (lbvc == 2) and \ + np.all(brsvd1 == brlev): + coord = _dim_or_aux(blev, standard_name='depth', units='m', + attributes={'positive': 'down'}) + coords_and_dims.append((coord, dim)) + + # Depth - bound. + if (len(lbcode) != 5) and \ + (lbvc == 2) and \ + np.all(brsvd1 != brlev): + coord = _dim_or_aux(blev, standard_name='depth', units='m', + bounds=np.vstack((brsvd1, brlev)).T, + attributes={'positive': 'down'}) + coords_and_dims.append((coord, dim)) + + # Depth - unbound and bound (mixed). + if (len(lbcode) != 5) and \ + (lbvc == 2) and \ + (np.any(brsvd1 == brlev) and np.any(brsvd1 != brlev)): + lower = np.where(brsvd1 == brlev, blev, brsvd1) + upper = np.where(brsvd1 == brlev, blev, brlev) + coord = _dim_or_aux(blev, standard_name='depth', units='m', + bounds=np.vstack((lower, upper)).T, + attributes={'positive': 'down'}) + coords_and_dims.append((coord, dim)) + + # Soil level/depth. + if len(lbcode) != 5 and lbvc == 6: + if np.all(brsvd1 == 0) and np.all(brlev == 0): + # UM populates lblev, brsvd1 and brlev metadata INCORRECTLY, + # so continue to treat as a soil level. + coord = _dim_or_aux(model_level_number, + long_name='soil_model_level_number', + attributes={'positive': 'down'}) + coords_and_dims.append((coord, dim)) + elif np.any(brsvd1 != brlev): + # UM populates metadata CORRECTLY, + # so treat it as the expected (bounded) soil depth. + coord = _dim_or_aux(blev, standard_name='depth', units='m', + bounds=np.vstack((brsvd1, brlev)).T, + attributes={'positive': 'down'}) + coords_and_dims.append((coord, dim)) + + # Pressure. + if (lbvc == 8) and \ + (len(lbcode) != 5 or (len(lbcode) == 5 and + 1 not in [lbcode.ix, lbcode.iy])): + coord = _dim_or_aux(blev, long_name='pressure', units='hPa') + coords_and_dims.append((coord, dim)) + + # Air potential temperature. + if (len(lbcode) != 5) and \ + (lbvc == 19): + coord = _dim_or_aux(blev, standard_name='air_potential_temperature', units='K', + attributes={'positive': 'up'}) + coords_and_dims.append((coord, dim)) + + # Hybrid pressure levels. + if lbvc == 9: + model_level_number = _dim_or_aux(model_level_number, + standard_name='model_level_number', + attributes={'positive': 'up'}) + level_pressure = _dim_or_aux(bhlev, + long_name='level_pressure', + units='Pa', + bounds=np.vstack((bhrlev, brsvd2)).T) + sigma = AuxCoord(blev, + long_name='sigma', + bounds=np.vstack((brlev, brsvd1)).T) + coords_and_dims.extend([(model_level_number, dim), + (level_pressure, dim), + (sigma, dim)]) + factories.append(Factory(HybridPressureFactory, + [{'long_name': 'level_pressure'}, + {'long_name': 'sigma'}, + Reference('surface_air_pressure')])) + + # Hybrid height levels. + if lbvc == 65: + model_level_number = _dim_or_aux(model_level_number, + standard_name='model_level_number', + attributes={'positive': 'up'}) + level_height = _dim_or_aux(blev, + long_name='level_height', + units='m', + bounds=np.vstack((brlev, brsvd1)).T, + attributes={'positive': 'up'}) + sigma = AuxCoord(bhlev, + long_name='sigma', + bounds=np.vstack((bhrlev, brsvd2)).T) + coords_and_dims.extend([(model_level_number, dim), + (level_height, dim), + (sigma, dim)]) + factories.append(Factory(HybridHeightFactory, + [{'long_name': 'level_height'}, + {'long_name': 'sigma'}, + Reference('orography')])) + + return coords_and_dims, factories + + +def _reshape_vector_args(values_and_dims): + """ + Reshape a group of (array, dimensions-mapping) onto all dimensions. + + The resulting arrays are all mapped over the same dimensions; as many as + the maximum dimension number found in the inputs. Those dimensions not + mapped by a given input appear as length-1 dimensions in the output array. + The resulting arrays are thus all mutually compatible in arithmetic -- i.e. + can combine without broadcasting errors (provided that all inputs mapping + to a dimension define the same associated length). + + Args: + + * values_and_dims (iterable of (array-like, iterable of int)): + Input arrays with associated mapping dimension numbers. + The length of each 'dims' must match the ndims of the 'value'. + + Returns: + + * reshaped_arrays (iterable of arrays). + The inputs, transposed and reshaped onto common target dimensions. + + """ + # Find maximum dimension index, which sets ndim of results. + max_dims = [max(dims) if dims else -1 for _, dims in values_and_dims] + max_dim = max(max_dims) if max_dims else -1 + result = [] + for value, dims in values_and_dims: + value = np.asarray(value) + if len(dims) != value.ndim: + raise ValueError('Lengths of dimension-mappings must match ' + 'input array dimensions.') + # Save dim sizes in original order. + original_shape = value.shape + if dims: + # Transpose values to put its dims in the target order. + dims_order = sorted(range(len(dims)), + key=lambda i_dim: dims[i_dim]) + value = value.transpose(dims_order) + if max_dim != -1: + # Reshape to add any extra *1 dims. + shape = [1] * (max_dim + 1) + for i_dim, dim in enumerate(dims): + shape[dim] = original_shape[i_dim] + value = value.reshape(shape) + result.append(value) + return result + + +def _collapse_degenerate_points_and_bounds(points, bounds=None, rtol=1.0e-7): + """ + Collapse points (and optionally bounds) in any dimensions over which all + values are the same. + + All dimensions are tested, and if degenerate are reduced to length 1. + + Value equivalence is controlled by a tolerance, to avoid problems with + numbers from cftime.date2num, which has limited precision because of + the way it calculates with floats of days. + + Args: + + * points (:class:`numpy.ndarray`)): + Array of points values. + + Kwargs: + + * bounds (:class:`numpy.ndarray`) + Array of bounds values. This array should have an additional vertex + dimension (typically of length 2) when compared to the points array + i.e. bounds.shape = points.shape + (nvertex,) + + Returns: + + A (points, bounds) tuple. + + """ + array = points + if bounds is not None: + array = np.vstack((points, bounds.T)).T + + for i_dim in range(points.ndim): + if array.shape[i_dim] > 1: + slice_inds = [slice(None)] * points.ndim + slice_inds[i_dim] = slice(0, 1) + slice_0 = array[slice_inds] + if np.allclose(array, slice_0, rtol): + array = slice_0 + + points = array + if bounds is not None: + points = array[..., 0] + bounds = array[..., 1:] + + return points, bounds + + +def _reduce_points_and_bounds(points, lower_and_upper_bounds=None): + """ + Reduce the dimensionality of arrays of coordinate points (and optionally + bounds). + + Dimensions over which all values are the same are reduced to size 1, using + :func:`_collapse_degenerate_points_and_bounds`. + All size-1 dimensions are then removed. + If the bounds arrays are also passed in, then all three arrays must have + the same shape or be capable of being broadcast to match. + + Args: + + * points (array-like): + Coordinate point values. + + Kwargs: + + * lower_and_upper_bounds (pair of array-like, or None): + Corresponding bounds values (lower, upper), if any. + + Returns: + dims (iterable of ints), points(array), bounds(array) + + * 'dims' is the mapping from the result array dimensions to the + original dimensions. However, when 'array' is scalar, 'dims' will + be None (rather than an empty tuple). + * 'points' and 'bounds' are the reduced arrays. + If no bounds were passed, None is returned. + + """ + orig_points_dtype = np.asarray(points).dtype + bounds = None + if lower_and_upper_bounds is not None: + lower_bounds, upper_bounds = np.broadcast_arrays( + *lower_and_upper_bounds) + orig_bounds_dtype = lower_bounds.dtype + bounds = np.vstack((lower_bounds, upper_bounds)).T + + # Attempt to broadcast points to match bounds to handle scalars. + if bounds is not None and points.shape != bounds.shape[:-1]: + points, _ = np.broadcast_arrays(points, bounds[..., 0]) + + points, bounds = _collapse_degenerate_points_and_bounds(points, bounds) + + used_dims = tuple(i_dim for i_dim in range(points.ndim) + if points.shape[i_dim] > 1) + reshape_inds = tuple([points.shape[dim] for dim in used_dims]) + points = points.reshape(reshape_inds) + points = points.astype(orig_points_dtype) + if bounds is not None: + bounds = bounds.reshape(reshape_inds + (2,)) + bounds = bounds.astype(orig_bounds_dtype) + + if not used_dims: + used_dims = None + + return used_dims, points, bounds + + +def _new_coord_and_dims(is_vector_operation, + name, units, + points, lower_and_upper_bounds=None): + """ + Make a new (coordinate, cube_dims) pair with the given points, name, units + and optional bounds. + + In 'vector' style operation, the data arrays must have same number of + dimensions as the target cube, and additional operations are performed : + + * dimensions with all points and bounds values the same are removed. + * the result coordinate may be an AuxCoord if a DimCoord cannot be made + (e.g. if values are non-monotonic). + + Args: + + * is_vector_operation (bool): + If True, perform 'vector' style operation. + + * points (array-like): + Coordinate point values. + + * name (string): + Standard name of coordinate. + + * units (string or cf_unit.Unit): + Units of coordinate. + + Kwargs: + + * lower_and_upper_bounds (pair of array-like, or None): + Corresponding bounds values (lower, upper), if any. + + Returns: + a new (coordinate, dims) pair. + + """ + bounds = lower_and_upper_bounds + if is_vector_operation: + dims, points, bounds = _reduce_points_and_bounds(points, bounds) + else: + dims = None + coord = _dim_or_aux(points, bounds=bounds, standard_name=name, units=units) + return (coord, dims) + + +_HOURS_UNIT = cf_units.Unit('hours') + + +def _convert_time_coords(lbcode, lbtim, epoch_hours_unit, + t1, t2, lbft, + t1_dims=(), t2_dims=(), lbft_dims=()): + """ + Make time coordinates from the time metadata. + + Args: + + * lbcode(:class:`iris.fileformats.pp.SplittableInt`): + Scalar field value. + * lbtim (:class:`iris.fileformats.pp.SplittableInt`): + Scalar field value. + * epoch_hours_unit (:class:`cf_units.Unit`): + Epoch time reference unit. + * t1 (array-like or scalar): + Scalar field value or an array of values. + * t2 (array-like or scalar): + Scalar field value or an array of values. + * lbft (array-like or scalar): + Scalar field value or an array of values. + + Kwargs: + + * t1_dims, t2_dims, lbft_dims (tuples of int): + Cube dimension mappings for the array metadata. Each default to + to (). The length of each dims tuple should equal the dimensionality + of the corresponding array of values. + + Returns: + + A list of (coordinate, dims) tuples. The coordinates are instance of + :class:`iris.coords.DimCoord` if possible, otherwise they are instance + of :class:`iris.coords.AuxCoord`. When the coordinate is of length one, + the `dims` value is None rather than an empty tuple. + + """ + def date2hours(t): + # netcdf4python has changed it's behaviour, at version 1.2, such + # that a date2num calculation returns a python float, not + # numpy.float64. The behaviour of round is to recast this to an + # int, which is not the desired behaviour for PP files. + # So, cast the answer to numpy.float_ to be safe. + epoch_hours = np.float_(epoch_hours_unit.date2num(t)) + if t.minute == 0 and t.second == 0: + epoch_hours = round(epoch_hours) + return epoch_hours + + def date2year(t_in): + return t_in.year + + # Check whether inputs are all scalar, for faster handling of scalar cases. + do_vector = len(t1_dims) + len(t2_dims) + len(lbft_dims) > 0 + if do_vector: + # Reform the input values so they have all the same number of + # dimensions, transposing where necessary (based on the dimension + # mappings) so that the dimensions are common across each array. + # Note: this does not _guarantee_ that the arrays are broadcastable, + # but subsequent arithmetic makes this assumption. + t1, t2, lbft = _reshape_vector_args([(t1, t1_dims), (t2, t2_dims), + (lbft, lbft_dims)]) + + date2hours = np.vectorize(date2hours) + date2year = np.vectorize(date2year) + + t1_epoch_hours = date2hours(t1) + t2_epoch_hours = date2hours(t2) + hours_from_t1_to_t2 = t2_epoch_hours - t1_epoch_hours + hours_from_t2_to_t1 = t1_epoch_hours - t2_epoch_hours + coords_and_dims = [] + + if ((lbtim.ia == 0) and + (lbtim.ib == 0) and + (lbtim.ic in [1, 2, 3, 4]) and + (len(lbcode) != 5 or (len(lbcode) == 5 and + lbcode.ix not in [20, 21, 22, 23] and + lbcode.iy not in [20, 21, 22, 23]))): + coords_and_dims.append(_new_coord_and_dims( + do_vector, 'time', epoch_hours_unit, t1_epoch_hours)) + + if ((lbtim.ia == 0) and + (lbtim.ib == 1) and + (lbtim.ic in [1, 2, 3, 4]) and + (len(lbcode) != 5 or (len(lbcode) == 5 + and lbcode.ix not in [20, 21, 22, 23] + and lbcode.iy not in [20, 21, 22, 23]))): + coords_and_dims.append(_new_coord_and_dims( + do_vector, 'forecast_period', _HOURS_UNIT, hours_from_t2_to_t1)) + coords_and_dims.append(_new_coord_and_dims( + do_vector, 'time', epoch_hours_unit, t1_epoch_hours)) + coords_and_dims.append(_new_coord_and_dims( + do_vector, 'forecast_reference_time', epoch_hours_unit, + t2_epoch_hours)) + + if ((lbtim.ib == 2) and + (lbtim.ic in [1, 2, 4]) and + (np.any(date2year(t1) != 0) and np.any(date2year(t2) != 0)) and + # Note: don't add time coordinates when years are zero and + # lbtim.ib == 2. These are handled elsewhere. + ((len(lbcode) != 5) or (len(lbcode) == 5 and + lbcode.ix not in [20, 21, 22, 23] + and lbcode.iy not in [20, 21, 22, 23]))): + + coords_and_dims.append(_new_coord_and_dims( + do_vector, 'forecast_period', _HOURS_UNIT, + lbft - 0.5 * hours_from_t1_to_t2, + [lbft - hours_from_t1_to_t2, lbft])) + + coords_and_dims.append(_new_coord_and_dims( + do_vector, 'time', epoch_hours_unit, + 0.5 * (t1_epoch_hours + t2_epoch_hours), + [t1_epoch_hours, t2_epoch_hours])) + + coords_and_dims.append(_new_coord_and_dims( + do_vector, 'forecast_reference_time', epoch_hours_unit, + t2_epoch_hours - lbft)) + + if ((lbtim.ib == 3) and + (lbtim.ic in [1, 2, 4]) and + ((len(lbcode) != 5) or (len(lbcode) == 5 and + lbcode.ix not in [20, 21, 22, 23] and + lbcode.iy not in [20, 21, 22, 23]))): + coords_and_dims.append(_new_coord_and_dims( + do_vector, 'forecast_period', _HOURS_UNIT, + lbft, [lbft - hours_from_t1_to_t2, lbft])) + coords_and_dims.append(_new_coord_and_dims( + do_vector, 'time', epoch_hours_unit, + t2_epoch_hours, [t1_epoch_hours, t2_epoch_hours])) + coords_and_dims.append(_new_coord_and_dims( + do_vector, 'forecast_reference_time', epoch_hours_unit, + t2_epoch_hours - lbft)) + + if \ + (len(lbcode) == 5) and \ + (lbcode[-1] == 3) and \ + (lbtim.ib == 2) and (lbtim.ic == 2): + coords_and_dims.append(_new_coord_and_dims( + do_vector, 'forecast_reference_time', epoch_hours_unit, + t2_epoch_hours - lbft)) + + return coords_and_dims + + +############################################################################### + + +def _model_level_number(lblev): + """ + Return model level number for an LBLEV value. + + Args: + + * lblev (int): + PP field LBLEV value. + + Returns: + Model level number (integer). + + """ + # See Word no. 33 (LBLEV) in section 4 of UM Model Docs (F3). + SURFACE_AND_ZEROTH_RHO_LEVEL_LBLEV = 9999 + + if lblev == SURFACE_AND_ZEROTH_RHO_LEVEL_LBLEV: + model_level_number = 0 + else: + model_level_number = lblev + + return model_level_number + + +def _convert_scalar_realization_coords(lbrsvd4): + """ + Encode scalar 'realization' (aka ensemble) numbers as CM data. + + Returns a list of coords_and_dims. + + """ + # Realization (aka ensemble) (--> scalar coordinates) + coords_and_dims = [] + if lbrsvd4 != 0: + coords_and_dims.append( + (DimCoord(lbrsvd4, standard_name='realization'), None)) + return coords_and_dims + + +def _convert_scalar_pseudo_level_coords(lbuser5): + """ + Encode scalar pseudo-level values as CM data. + + Returns a list of coords_and_dims. + + """ + coords_and_dims = [] + if lbuser5 != 0: + coords_and_dims.append( + (DimCoord(lbuser5, long_name='pseudo_level', units='1'), None)) + return coords_and_dims + + +def convert(f): + """ + Converts a PP field into the corresponding items of Cube metadata. + + Args: + + * f: + A :class:`iris.fileformats.pp.PPField` object. + + Returns: + A :class:`iris.fileformats.rules.ConversionMetadata` object. + + """ + factories = [] + aux_coords_and_dims = [] + + # "Normal" (non-cross-sectional) Time values (--> scalar coordinates) + time_coords_and_dims = _convert_time_coords( + lbcode=f.lbcode, lbtim=f.lbtim, + epoch_hours_unit=f.time_unit('hours'), + t1=f.t1, t2=f.t2, lbft=f.lbft) + aux_coords_and_dims.extend(time_coords_and_dims) + + # "Normal" (non-cross-sectional) Vertical levels + # (--> scalar coordinates and factories) + vertical_coords_and_dims, vertical_factories = \ + _convert_vertical_coords( + lbcode=f.lbcode, + lbvc=f.lbvc, + blev=f.blev, + lblev=f.lblev, + stash=f.stash, + bhlev=f.bhlev, + bhrlev=f.bhrlev, + brsvd1=f.brsvd[0], + brsvd2=f.brsvd[1], + brlev=f.brlev) + aux_coords_and_dims.extend(vertical_coords_and_dims) + factories.extend(vertical_factories) + + # Realization (aka ensemble) (--> scalar coordinates) + aux_coords_and_dims.extend(_convert_scalar_realization_coords( + lbrsvd4=f.lbrsvd[3])) + + # Pseudo-level coordinate (--> scalar coordinates) + aux_coords_and_dims.extend(_convert_scalar_pseudo_level_coords( + lbuser5=f.lbuser[4])) + + # All the other rules. + references, standard_name, long_name, units, attributes, cell_methods, \ + dim_coords_and_dims, other_aux_coords_and_dims = _all_other_rules(f) + aux_coords_and_dims.extend(other_aux_coords_and_dims) + + return ConversionMetadata(factories, references, standard_name, long_name, + units, attributes, cell_methods, + dim_coords_and_dims, aux_coords_and_dims) + + +def _all_other_rules(f): + """ + This deals with all the other rules that have not been factored into any of + the other convert_scalar_coordinate functions above. + + """ + references = [] + standard_name = None + long_name = None + units = None + attributes = {} + cell_methods = [] + dim_coords_and_dims = [] + aux_coords_and_dims = [] + + # Season coordinates (--> scalar coordinates) + if (f.lbtim.ib == 3 and f.lbtim.ic in [1, 2, 4] and + (len(f.lbcode) != 5 or + (len(f.lbcode) == 5 and + (f.lbcode.ix not in [20, 21, 22, 23] and + f.lbcode.iy not in [20, 21, 22, 23]))) and + f.lbmon == 12 and f.lbdat == 1 and f.lbhr == 0 and f.lbmin == 0 and + f.lbmond == 3 and f.lbdatd == 1 and f.lbhrd == 0 and + f.lbmind == 0): + aux_coords_and_dims.append( + (AuxCoord('djf', long_name='season', units='no_unit'), + None)) + + if (f.lbtim.ib == 3 and f.lbtim.ic in [1, 2, 4] and + ((len(f.lbcode) != 5) or + (len(f.lbcode) == 5 and + f.lbcode.ix not in [20, 21, 22, 23] + and f.lbcode.iy not in [20, 21, 22, 23])) and + f.lbmon == 3 and f.lbdat == 1 and f.lbhr == 0 and f.lbmin == 0 and + f.lbmond == 6 and f.lbdatd == 1 and f.lbhrd == 0 and + f.lbmind == 0): + aux_coords_and_dims.append( + (AuxCoord('mam', long_name='season', units='no_unit'), + None)) + + if (f.lbtim.ib == 3 and f.lbtim.ic in [1, 2, 4] and + ((len(f.lbcode) != 5) or + (len(f.lbcode) == 5 and + f.lbcode.ix not in [20, 21, 22, 23] and + f.lbcode.iy not in [20, 21, 22, 23])) and + f.lbmon == 6 and f.lbdat == 1 and f.lbhr == 0 and f.lbmin == 0 and + f.lbmond == 9 and f.lbdatd == 1 and f.lbhrd == 0 and + f.lbmind == 0): + aux_coords_and_dims.append( + (AuxCoord('jja', long_name='season', units='no_unit'), + None)) + + if (f.lbtim.ib == 3 and f.lbtim.ic in [1, 2, 4] and + ((len(f.lbcode) != 5) or + (len(f.lbcode) == 5 and + f.lbcode.ix not in [20, 21, 22, 23] and + f.lbcode.iy not in [20, 21, 22, 23])) and + f.lbmon == 9 and f.lbdat == 1 and f.lbhr == 0 and f.lbmin == 0 and + f.lbmond == 12 and f.lbdatd == 1 and f.lbhrd == 0 and + f.lbmind == 0): + aux_coords_and_dims.append( + (AuxCoord('son', long_name='season', units='no_unit'), + None)) + + # Special case where year is zero and months match. + # Month coordinates (--> scalar coordinates) + if (f.lbtim.ib == 2 and f.lbtim.ic in [1, 2, 4] and + ((len(f.lbcode) != 5) or + (len(f.lbcode) == 5 and + f.lbcode.ix not in [20, 21, 22, 23] and + f.lbcode.iy not in [20, 21, 22, 23])) and + f.lbyr == 0 and f.lbyrd == 0 and + f.lbmon == f.lbmond): + aux_coords_and_dims.append( + (AuxCoord(f.lbmon, long_name='month_number'), + None)) + aux_coords_and_dims.append( + (AuxCoord(calendar.month_abbr[f.lbmon], long_name='month', + units='no_unit'), + None)) + aux_coords_and_dims.append( + (DimCoord(points=f.lbft, standard_name='forecast_period', units='hours'), + None)) + + # "Normal" (i.e. not cross-sectional) lats+lons (--> vector coordinates) + if (f.bdx != 0.0 and f.bdx != f.bmdi and len(f.lbcode) != 5 and + f.lbcode[0] == 1): + dim_coords_and_dims.append( + (DimCoord.from_regular(f.bzx, f.bdx, f.lbnpt, + standard_name=f._x_coord_name(), + units='degrees', + circular=(f.lbhem in [0, 4]), + coord_system=f.coord_system()), + 1)) + + if (f.bdx != 0.0 and f.bdx != f.bmdi and len(f.lbcode) != 5 and + f.lbcode[0] == 2): + dim_coords_and_dims.append( + (DimCoord.from_regular(f.bzx, f.bdx, f.lbnpt, + standard_name=f._x_coord_name(), + units='degrees', + circular=(f.lbhem in [0, 4]), + coord_system=f.coord_system(), + with_bounds=True), + 1)) + + if (f.bdy != 0.0 and f.bdy != f.bmdi and len(f.lbcode) != 5 and + f.lbcode[0] == 1): + dim_coords_and_dims.append( + (DimCoord.from_regular(f.bzy, f.bdy, f.lbrow, + standard_name=f._y_coord_name(), + units='degrees', + coord_system=f.coord_system()), + 0)) + + if (f.bdy != 0.0 and f.bdy != f.bmdi and len(f.lbcode) != 5 and + f.lbcode[0] == 2): + dim_coords_and_dims.append( + (DimCoord.from_regular(f.bzy, f.bdy, f.lbrow, + standard_name=f._y_coord_name(), + units='degrees', + coord_system=f.coord_system(), + with_bounds=True), + 0)) + + if ((f.bdy == 0.0 or f.bdy == f.bmdi) and + (len(f.lbcode) != 5 or + (len(f.lbcode) == 5 and f.lbcode.iy == 10))): + dim_coords_and_dims.append( + (DimCoord(f.y, standard_name=f._y_coord_name(), units='degrees', + bounds=f.y_bounds, coord_system=f.coord_system()), + 0)) + + if ((f.bdx == 0.0 or f.bdx == f.bmdi) and + (len(f.lbcode) != 5 or + (len(f.lbcode) == 5 and f.lbcode.ix == 11))): + dim_coords_and_dims.append( + (DimCoord(f.x, standard_name=f._x_coord_name(), units='degrees', + bounds=f.x_bounds, circular=(f.lbhem in [0, 4]), + coord_system=f.coord_system()), + 1)) + + # Cross-sectional vertical level types (--> vector coordinates) + if (len(f.lbcode) == 5 and f.lbcode.iy == 2 and + (f.bdy == 0 or f.bdy == f.bmdi)): + dim_coords_and_dims.append( + (DimCoord(f.y, standard_name='height', units='km', + bounds=f.y_bounds, attributes={'positive': 'up'}), + 0)) + + if (len(f.lbcode) == 5 and f.lbcode[-1] == 1 and f.lbcode.iy == 4): + dim_coords_and_dims.append( + (DimCoord(f.y, standard_name='depth', units='m', + bounds=f.y_bounds, attributes={'positive': 'down'}), + 0)) + + if (len(f.lbcode) == 5 and f.lbcode.ix == 10 and f.bdx != 0 and + f.bdx != f.bmdi): + dim_coords_and_dims.append( + (DimCoord.from_regular(f.bzx, f.bdx, f.lbnpt, + standard_name=f._y_coord_name(), + units='degrees', + coord_system=f.coord_system()), + 1)) + + if (len(f.lbcode) == 5 and + f.lbcode.iy == 1 and + (f.bdy == 0 or f.bdy == f.bmdi)): + dim_coords_and_dims.append( + (DimCoord(f.y, long_name='pressure', units='hPa', + bounds=f.y_bounds), + 0)) + + if (len(f.lbcode) == 5 and f.lbcode.ix == 1 and + (f.bdx == 0 or f.bdx == f.bmdi)): + dim_coords_and_dims.append((DimCoord(f.x, long_name='pressure', + units='hPa', bounds=f.x_bounds), + 1)) + + # Cross-sectional time values (--> vector coordinates) + if (len(f.lbcode) == 5 and f.lbcode[-1] == 1 and f.lbcode.iy == 23): + dim_coords_and_dims.append( + (DimCoord( + f.y, + standard_name='time', + units=cf_units.Unit('days since 0000-01-01 00:00:00', + calendar=cf_units.CALENDAR_360_DAY), + bounds=f.y_bounds), + 0)) + + if (len(f.lbcode) == 5 and f.lbcode[-1] == 1 and f.lbcode.ix == 23): + dim_coords_and_dims.append( + (DimCoord( + f.x, + standard_name='time', + units=cf_units.Unit('days since 0000-01-01 00:00:00', + calendar=cf_units.CALENDAR_360_DAY), + bounds=f.x_bounds), + 1)) + + if (len(f.lbcode) == 5 and f.lbcode[-1] == 3 and f.lbcode.iy == 23 and + f.lbtim.ib == 2 and f.lbtim.ic == 2): + epoch_days_unit = cf_units.Unit('days since 0000-01-01 00:00:00', + calendar=cf_units.CALENDAR_360_DAY) + t1_epoch_days = epoch_days_unit.date2num(f.t1) + t2_epoch_days = epoch_days_unit.date2num(f.t2) + # The end time is exclusive, not inclusive. + dim_coords_and_dims.append( + (DimCoord( + np.linspace(t1_epoch_days, t2_epoch_days, f.lbrow, + endpoint=False), + standard_name='time', + units=epoch_days_unit, + bounds=f.y_bounds), + 0)) + + # Site number (--> scalar coordinate) + if (len(f.lbcode) == 5 and f.lbcode[-1] == 1 and f.lbcode.ix == 13 and + f.bdx != 0): + dim_coords_and_dims.append( + (DimCoord.from_regular(f.bzx, f.bdx, f.lbnpt, + long_name='site_number', units='1'), + 1)) + + # Site number cross-sections (???) + if (len(f.lbcode) == 5 and + 13 in [f.lbcode.ix, f.lbcode.iy] and + 11 not in [f.lbcode.ix, f.lbcode.iy] and + hasattr(f, 'lower_x_domain') and + hasattr(f, 'upper_x_domain') and + all(f.lower_x_domain != -1.e+30) and + all(f.upper_x_domain != -1.e+30)): + aux_coords_and_dims.append( + (AuxCoord((f.lower_x_domain + f.upper_x_domain) / 2.0, + standard_name=f._x_coord_name(), units='degrees', + bounds=np.array([f.lower_x_domain, f.upper_x_domain]).T, + coord_system=f.coord_system()), + 1 if f.lbcode.ix == 13 else 0)) + + if (len(f.lbcode) == 5 and + 13 in [f.lbcode.ix, f.lbcode.iy] and + 10 not in [f.lbcode.ix, f.lbcode.iy] and + hasattr(f, 'lower_y_domain') and + hasattr(f, 'upper_y_domain') and + all(f.lower_y_domain != -1.e+30) and + all(f.upper_y_domain != -1.e+30)): + aux_coords_and_dims.append( + (AuxCoord((f.lower_y_domain + f.upper_y_domain) / 2.0, + standard_name=f._y_coord_name(), units='degrees', + bounds=np.array([f.lower_y_domain, f.upper_y_domain]).T, + coord_system=f.coord_system()), + 1 if f.lbcode.ix == 13 else 0)) + + # LBPROC codings (--> cell method + attributes) + unhandled_lbproc = True + zone_method = None + time_method = None + if f.lbproc == 0: + unhandled_lbproc = False + elif f.lbproc == 64: + zone_method = 'mean' + elif f.lbproc == 128: + time_method = 'mean' + elif f.lbproc == 4096: + time_method = 'minimum' + elif f.lbproc == 8192: + time_method = 'maximum' + elif f.lbproc == 192: + time_method = 'mean' + zone_method = 'mean' + + if time_method is not None: + if f.lbtim.ia != 0: + intervals = '{} hour'.format(f.lbtim.ia) + else: + intervals = None + + if f.lbtim.ib == 2: + # Aggregation over a period of time. + cell_methods.append(CellMethod(time_method, + coords='time', + intervals=intervals)) + unhandled_lbproc = False + elif f.lbtim.ib == 3 and f.lbproc == 128: + # Aggregation over a period of time within a year, over a number + # of years. + # Only mean (lbproc of 128) is handled as the min/max + # interpretation is ambiguous e.g. decadal mean of daily max, + # decadal max of daily mean, decadal mean of max daily mean etc. + cell_methods.append( + CellMethod('{} within years'.format(time_method), + coords='time', intervals=intervals)) + cell_methods.append( + CellMethod('{} over years'.format(time_method), + coords='time')) + unhandled_lbproc = False + else: + # Generic cell method to indicate a time aggregation. + cell_methods.append(CellMethod(time_method, + coords='time')) + unhandled_lbproc = False + + if zone_method is not None: + if f.lbcode == 1: + cell_methods.append(CellMethod(zone_method, coords='longitude')) + for coord, _dim in dim_coords_and_dims: + if coord.standard_name == 'longitude': + if len(coord.points) == 1: + coord.bounds = np.array([0. , 360.], dtype=np.float32) + else: + coord.guess_bounds() + unhandled_lbproc = False + elif f.lbcode == 101: + cell_methods.append(CellMethod(zone_method, + coords='grid_longitude')) + for coord, _dim in dim_coords_and_dims: + if coord.standard_name == 'grid_longitude': + if len(coord.points) == 1: + coord.bounds = np.array([0. , 360.], dtype=np.float32) + else: + coord.guess_bounds() + unhandled_lbproc = False + else: + unhandled_lbproc = True + + if unhandled_lbproc: + attributes["ukmo__process_flags"] = tuple(sorted( + [name + for value, name in six.iteritems(LBPROC_MAP) + if isinstance(value, int) and f.lbproc & value])) + + if (f.lbsrce % 10000) == 1111: + attributes['source'] = 'Data from Met Office Unified Model' + # Also define MO-netCDF compliant UM version. + um_major = (f.lbsrce // 10000) // 100 + if um_major != 0: + um_minor = (f.lbsrce // 10000) % 100 + attributes['um_version'] = '{:d}.{:d}'.format(um_major, um_minor) + + if (f.lbuser[6] != 0 or + (f.lbuser[3] // 1000) != 0 or + (f.lbuser[3] % 1000) != 0): + attributes['STASH'] = f.stash + + if str(f.stash) in STASH_TO_CF: + standard_name = STASH_TO_CF[str(f.stash)].standard_name + units = STASH_TO_CF[str(f.stash)].units + long_name = STASH_TO_CF[str(f.stash)].long_name + + if (not f.stash.is_valid and f.lbfc in LBFC_TO_CF): + standard_name = LBFC_TO_CF[f.lbfc].standard_name + units = LBFC_TO_CF[f.lbfc].units + long_name = LBFC_TO_CF[f.lbfc].long_name + + # Orography reference field (--> reference target) + if f.lbuser[3] == 33: + references.append(ReferenceTarget('orography', None)) + + # Surface pressure reference field (--> reference target) + if f.lbuser[3] == 409 or f.lbuser[3] == 1: + references.append(ReferenceTarget('surface_air_pressure', None)) + + return (references, standard_name, long_name, units, attributes, + cell_methods, dim_coords_and_dims, aux_coords_and_dims) diff --git a/lib/iris/fileformats/pp_rules.py b/lib/iris/fileformats/pp_rules.py deleted file mode 100644 index ab29c18956..0000000000 --- a/lib/iris/fileformats/pp_rules.py +++ /dev/null @@ -1,417 +0,0 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . - -# Historically this was auto-generated from -# SciTools/iris-code-generators:tools/gen_rules.py - -import warnings - -import numpy as np - -from iris.aux_factory import HybridHeightFactory, HybridPressureFactory -from iris.coords import AuxCoord, CellMethod, DimCoord -from iris.fileformats.rules import Factory, Reference, ReferenceTarget -from iris.fileformats.um_cf_map import LBFC_TO_CF, STASH_TO_CF -from iris.unit import Unit -import iris.fileformats.pp -import iris.unit - - -def convert(f): - factories = [] - references = [] - standard_name = None - long_name = None - units = None - attributes = {} - cell_methods = [] - dim_coords_and_dims = [] - aux_coords_and_dims = [] - - if \ - (f.lbtim.ia == 0) and \ - (f.lbtim.ib == 0) and \ - (f.lbtim.ic in [1, 2, 3, 4]) and \ - (len(f.lbcode) != 5 or (len(f.lbcode) == 5 and f.lbcode.ix not in [20, 21, 22, 23] and f.lbcode.iy not in [20, 21, 22, 23])): - aux_coords_and_dims.append((DimCoord(f.time_unit('hours').date2num(f.t1), standard_name='time', units=f.time_unit('hours')), None)) - - if \ - (f.lbtim.ia == 0) and \ - (f.lbtim.ib == 1) and \ - (f.lbtim.ic in [1, 2, 3, 4]) and \ - (len(f.lbcode) != 5 or (len(f.lbcode) == 5 and f.lbcode.ix not in [20, 21, 22, 23] and f.lbcode.iy not in [20, 21, 22, 23])): - aux_coords_and_dims.append((DimCoord(f.time_unit('hours', f.t2).date2num(f.t1), standard_name='forecast_period', units='hours'), None)) - aux_coords_and_dims.append((DimCoord(f.time_unit('hours').date2num(f.t1), standard_name='time', units=f.time_unit('hours')), None)) - aux_coords_and_dims.append((DimCoord(f.time_unit('hours').date2num(f.t2), standard_name='forecast_reference_time', units=f.time_unit('hours')), None)) - - if \ - (f.lbtim.ib == 2) and \ - (f.lbtim.ic in [1, 2, 4]) and \ - ((len(f.lbcode) != 5) or (len(f.lbcode) == 5 and f.lbcode.ix not in [20, 21, 22, 23] and f.lbcode.iy not in [20, 21, 22, 23])): - aux_coords_and_dims.append((DimCoord(f.lbft, standard_name='forecast_period', units='hours'), None)) - aux_coords_and_dims.append((DimCoord(f.time_unit('hours').date2num(f.t2), standard_name='time', units=f.time_unit('hours'), bounds=f.time_unit('hours').date2num([f.t1, f.t2])), None)) - aux_coords_and_dims.append((DimCoord(f.time_unit('hours').date2num(f.t2) - f.lbft, standard_name='forecast_reference_time', units=f.time_unit('hours')), None)) - - if \ - (f.lbtim.ib == 3) and \ - (f.lbtim.ic in [1, 2, 4]) and \ - ((len(f.lbcode) != 5) or (len(f.lbcode) == 5 and f.lbcode.ix not in [20, 21, 22, 23] and f.lbcode.iy not in [20, 21, 22, 23])): - aux_coords_and_dims.append((DimCoord(f.lbft, standard_name='forecast_period', units='hours'), None)) - aux_coords_and_dims.append((DimCoord(f.time_unit('hours').date2num(f.t2), standard_name='time', units=f.time_unit('hours'), bounds=f.time_unit('hours').date2num([f.t1, f.t2])), None)) - aux_coords_and_dims.append((DimCoord(f.time_unit('hours').date2num(f.t2) - f.lbft, standard_name='forecast_reference_time', units=f.time_unit('hours')), None)) - - if \ - (f.lbtim.ib == 3) and \ - (f.lbtim.ic in [1, 2, 4]) and \ - ((len(f.lbcode) != 5) or (len(f.lbcode) == 5 and f.lbcode.ix not in [20, 21, 22, 23] and f.lbcode.iy not in [20, 21, 22, 23])) and \ - (f.lbmon == 12 and f.lbdat == 1 and f.lbhr == 0 and f.lbmin == 0) and \ - (f.lbmond == 3 and f.lbdatd == 1 and f.lbhrd == 0 and f.lbmind == 0): - aux_coords_and_dims.append((AuxCoord('djf', long_name='season', units='no_unit'), None)) - - if \ - (f.lbtim.ib == 3) and \ - (f.lbtim.ic in [1, 2, 4]) and \ - ((len(f.lbcode) != 5) or (len(f.lbcode) == 5 and f.lbcode.ix not in [20, 21, 22, 23] and f.lbcode.iy not in [20, 21, 22, 23])) and \ - (f.lbmon == 3 and f.lbdat == 1 and f.lbhr == 0 and f.lbmin == 0) and \ - (f.lbmond == 6 and f.lbdatd == 1 and f.lbhrd == 0 and f.lbmind == 0): - aux_coords_and_dims.append((AuxCoord('mam', long_name='season', units='no_unit'), None)) - - if \ - (f.lbtim.ib == 3) and \ - (f.lbtim.ic in [1, 2, 4]) and \ - ((len(f.lbcode) != 5) or (len(f.lbcode) == 5 and f.lbcode.ix not in [20, 21, 22, 23] and f.lbcode.iy not in [20, 21, 22, 23])) and \ - (f.lbmon == 6 and f.lbdat == 1 and f.lbhr == 0 and f.lbmin == 0) and \ - (f.lbmond == 9 and f.lbdatd == 1 and f.lbhrd == 0 and f.lbmind == 0): - aux_coords_and_dims.append((AuxCoord('jja', long_name='season', units='no_unit'), None)) - - if \ - (f.lbtim.ib == 3) and \ - (f.lbtim.ic in [1, 2, 4]) and \ - ((len(f.lbcode) != 5) or (len(f.lbcode) == 5 and f.lbcode.ix not in [20, 21, 22, 23] and f.lbcode.iy not in [20, 21, 22, 23])) and \ - (f.lbmon == 9 and f.lbdat == 1 and f.lbhr == 0 and f.lbmin == 0) and \ - (f.lbmond == 12 and f.lbdatd == 1 and f.lbhrd == 0 and f.lbmind == 0): - aux_coords_and_dims.append((AuxCoord('son', long_name='season', units='no_unit'), None)) - - if \ - (f.bdx != 0.0) and \ - (f.bdx != f.bmdi) and \ - (len(f.lbcode) != 5) and \ - (f.lbcode[0] == 1): - dim_coords_and_dims.append((DimCoord.from_regular(f.bzx, f.bdx, f.lbnpt, standard_name=f._x_coord_name(), units='degrees', circular=(f.lbhem in [0, 4]), coord_system=f.coord_system()), 1)) - - if \ - (f.bdx != 0.0) and \ - (f.bdx != f.bmdi) and \ - (len(f.lbcode) != 5) and \ - (f.lbcode[0] == 2): - dim_coords_and_dims.append((DimCoord.from_regular(f.bzx, f.bdx, f.lbnpt, standard_name=f._x_coord_name(), units='degrees', circular=(f.lbhem in [0, 4]), coord_system=f.coord_system(), with_bounds=True), 1)) - - if \ - (f.bdy != 0.0) and \ - (f.bdy != f.bmdi) and \ - (len(f.lbcode) != 5) and \ - (f.lbcode[0] == 1): - dim_coords_and_dims.append((DimCoord.from_regular(f.bzy, f.bdy, f.lbrow, standard_name=f._y_coord_name(), units='degrees', coord_system=f.coord_system()), 0)) - - if \ - (f.bdy != 0.0) and \ - (f.bdy != f.bmdi) and \ - (len(f.lbcode) != 5) and \ - (f.lbcode[0] == 2): - dim_coords_and_dims.append((DimCoord.from_regular(f.bzy, f.bdy, f.lbrow, standard_name=f._y_coord_name(), units='degrees', coord_system=f.coord_system(), with_bounds=True), 0)) - - if \ - (f.bdy == 0.0 or f.bdy == f.bmdi) and \ - (len(f.lbcode) != 5 or (len(f.lbcode) == 5 and f.lbcode.iy == 10)): - dim_coords_and_dims.append((DimCoord(f.y, standard_name=f._y_coord_name(), units='degrees', bounds=f.y_bounds, coord_system=f.coord_system()), 0)) - - if \ - (f.bdx == 0.0 or f.bdx == f.bmdi) and \ - (len(f.lbcode) != 5 or (len(f.lbcode) == 5 and f.lbcode.ix == 11)): - dim_coords_and_dims.append((DimCoord(f.x, standard_name=f._x_coord_name(), units='degrees', bounds=f.x_bounds, circular=(f.lbhem in [0, 4]), coord_system=f.coord_system()), 1)) - - if \ - (len(f.lbcode) == 5) and \ - (f.lbcode[-1] == 1) and \ - (f.lbcode.iy == 4): - dim_coords_and_dims.append((DimCoord(f.y, standard_name='depth', units='m', bounds=f.y_bounds, attributes={'positive': 'down'}), 0)) - - if \ - (len(f.lbcode) == 5) and \ - (f.lbcode.ix == 10) and \ - (f.bdx != 0) and \ - (f.bdx != f.bmdi): - dim_coords_and_dims.append((DimCoord.from_regular(f.bzx, f.bdx, f.lbnpt, standard_name=f._y_coord_name(), units='degrees', coord_system=f.coord_system()), 1)) - - if \ - (len(f.lbcode) == 5) and \ - (f.lbcode.iy == 1) and \ - (f.bdy == 0 or f.bdy == f.bmdi): - dim_coords_and_dims.append((DimCoord(f.y, long_name='pressure', units='hPa', bounds=f.y_bounds), 0)) - - if \ - (len(f.lbcode) == 5) and \ - (f.lbcode.ix == 1) and \ - (f.bdx == 0 or f.bdx == f.bmdi): - dim_coords_and_dims.append((DimCoord(f.x, long_name='pressure', units='hPa', bounds=f.x_bounds), 1)) - - if \ - (len(f.lbcode) == 5) and \ - (f.lbcode[-1] == 1) and \ - (f.lbcode.iy == 23): - dim_coords_and_dims.append((DimCoord(f.y, standard_name='time', units=iris.unit.Unit('days since 0000-01-01 00:00:00', calendar=iris.unit.CALENDAR_360_DAY), bounds=f.y_bounds), 0)) - - if \ - (len(f.lbcode) == 5) and \ - (f.lbcode[-1] == 1) and \ - (f.lbcode.ix == 23): - dim_coords_and_dims.append((DimCoord(f.x, standard_name='time', units=iris.unit.Unit('days since 0000-01-01 00:00:00', calendar=iris.unit.CALENDAR_360_DAY), bounds=f.x_bounds), 1)) - - if \ - (len(f.lbcode) == 5) and \ - (f.lbcode[-1] == 1) and \ - (f.lbcode.ix == 13) and \ - (f.bdx != 0): - dim_coords_and_dims.append((DimCoord.from_regular(f.bzx, f.bdx, f.lbnpt, long_name='site_number', units='1'), 1)) - - if \ - (len(f.lbcode) == 5) and \ - (13 in [f.lbcode.ix, f.lbcode.iy]) and \ - (11 not in [f.lbcode.ix, f.lbcode.iy]) and \ - (hasattr(f, 'lower_x_domain')) and \ - (hasattr(f, 'upper_x_domain')) and \ - (all(f.lower_x_domain != -1.e+30)) and \ - (all(f.upper_x_domain != -1.e+30)): - aux_coords_and_dims.append((AuxCoord((f.lower_x_domain + f.upper_x_domain) / 2.0, standard_name=f._x_coord_name(), units='degrees', bounds=np.array([f.lower_x_domain, f.upper_x_domain]).T, coord_system=f.coord_system()), 1 if f.lbcode.ix == 13 else 0)) - - if \ - (len(f.lbcode) == 5) and \ - (13 in [f.lbcode.ix, f.lbcode.iy]) and \ - (10 not in [f.lbcode.ix, f.lbcode.iy]) and \ - (hasattr(f, 'lower_y_domain')) and \ - (hasattr(f, 'upper_y_domain')) and \ - (all(f.lower_y_domain != -1.e+30)) and \ - (all(f.upper_y_domain != -1.e+30)): - aux_coords_and_dims.append((AuxCoord((f.lower_y_domain + f.upper_y_domain) / 2.0, standard_name=f._y_coord_name(), units='degrees', bounds=np.array([f.lower_y_domain, f.upper_y_domain]).T, coord_system=f.coord_system()), 1 if f.lbcode.ix == 13 else 0)) - - if \ - (f.lbproc == 128) and \ - (f.lbtim.ib == 2) and \ - (f.lbtim.ia == 0): - cell_methods.append(CellMethod("mean", coords="time")) - - if \ - (f.lbproc == 128) and \ - (f.lbtim.ib == 2) and \ - (f.lbtim.ia != 0): - cell_methods.append(CellMethod("mean", coords="time", intervals="%d hour" % f.lbtim.ia)) - - if \ - (f.lbproc == 128) and \ - (f.lbtim.ib == 3): - cell_methods.append(CellMethod("mean", coords="time")) - - if \ - (f.lbproc == 128) and \ - (f.lbtim.ib not in [2, 3]): - cell_methods.append(CellMethod("mean", coords="time")) - - if \ - (f.lbproc == 4096) and \ - (f.lbtim.ib == 2) and \ - (f.lbtim.ia == 0): - cell_methods.append(CellMethod("minimum", coords="time")) - - if \ - (f.lbproc == 4096) and \ - (f.lbtim.ib == 2) and \ - (f.lbtim.ia != 0): - cell_methods.append(CellMethod("minimum", coords="time", intervals="%d hour" % f.lbtim.ia)) - - if \ - (f.lbproc == 4096) and \ - (f.lbtim.ib != 2): - cell_methods.append(CellMethod("minimum", coords="time")) - - if \ - (f.lbproc == 8192) and \ - (f.lbtim.ib == 2) and \ - (f.lbtim.ia == 0): - cell_methods.append(CellMethod("maximum", coords="time")) - - if \ - (f.lbproc == 8192) and \ - (f.lbtim.ib == 2) and \ - (f.lbtim.ia != 0): - cell_methods.append(CellMethod("maximum", coords="time", intervals="%d hour" % f.lbtim.ia)) - - if \ - (f.lbproc == 8192) and \ - (f.lbtim.ib != 2): - cell_methods.append(CellMethod("maximum", coords="time")) - - if f.lbproc not in [0, 128, 4096, 8192]: - attributes["ukmo__process_flags"] = tuple(sorted([iris.fileformats.pp.lbproc_map[flag] for flag in f.lbproc.flags])) - - if \ - (f.lbvc == 1) and \ - (not (str(f.stash) in ['m01s03i236', 'm01s03i237', 'm01s03i245', 'm01s03i247', 'm01s03i250'])) and \ - (f.blev != -1): - aux_coords_and_dims.append((DimCoord(f.blev, standard_name='height', units='m', attributes={'positive': 'up'}), None)) - - if str(f.stash) in ['m01s03i236', 'm01s03i237', 'm01s03i245', 'm01s03i247', 'm01s03i250']: - aux_coords_and_dims.append((DimCoord(1.5, standard_name='height', units='m', attributes={'positive': 'up'}), None)) - - if \ - (len(f.lbcode) != 5) and \ - (f.lbvc == 2): - aux_coords_and_dims.append((DimCoord(f.lblev, standard_name='model_level_number', attributes={'positive': 'down'}), None)) - - if \ - (len(f.lbcode) != 5) and \ - (f.lbvc == 2) and \ - (f.brsvd[0] == f.brlev): - aux_coords_and_dims.append((DimCoord(f.blev, standard_name='depth', units='m', attributes={'positive': 'down'}), None)) - - if \ - (len(f.lbcode) != 5) and \ - (f.lbvc == 2) and \ - (f.brsvd[0] != f.brlev): - aux_coords_and_dims.append((DimCoord(f.blev, standard_name='depth', units='m', bounds=[f.brsvd[0], f.brlev], attributes={'positive': 'down'}), None)) - - # soil level - if len(f.lbcode) != 5 and f.lbvc == 6: - aux_coords_and_dims.append((DimCoord(f.lblev, long_name='soil_model_level_number', attributes={'positive': 'down'}), None)) - - if \ - (f.lbvc == 8) and \ - (len(f.lbcode) != 5 or (len(f.lbcode) == 5 and 1 not in [f.lbcode.ix, f.lbcode.iy])): - aux_coords_and_dims.append((DimCoord(f.blev, long_name='pressure', units='hPa'), None)) - - if \ - (len(f.lbcode) != 5) and \ - (f.lbvc == 19): - aux_coords_and_dims.append((DimCoord(f.blev, standard_name='air_potential_temperature', units='K', attributes={'positive': 'up'}), None)) - - # Hybrid pressure coordinate - if f.lbvc == 9: - model_level_number = DimCoord(f.lblev, - standard_name='model_level_number', - attributes={'positive': 'up'}) - # The following match the hybrid height scheme, but data has the - # blev and bhlev values the other way around. - #level_pressure = DimCoord(f.blev, - # long_name='level_pressure', - # units='Pa', - # bounds=[f.brlev, f.brsvd[0]]) - #sigma = AuxCoord(f.bhlev, - # long_name='sigma', - # bounds=[f.bhrlev, f.brsvd[1]]) - level_pressure = DimCoord(f.bhlev, - long_name='level_pressure', - units='Pa', - bounds=[f.bhrlev, f.brsvd[1]]) - sigma = AuxCoord(f.blev, - long_name='sigma', - bounds=[f.brlev, f.brsvd[0]]) - aux_coords_and_dims.extend([(model_level_number, None), - (level_pressure, None), - (sigma, None)]) - factories.append(Factory(HybridPressureFactory, - [{'long_name': 'level_pressure'}, - {'long_name': 'sigma'}, - Reference('surface_air_pressure')])) - - if f.lbvc == 65: - aux_coords_and_dims.append((DimCoord(f.lblev, standard_name='model_level_number', attributes={'positive': 'up'}), None)) - aux_coords_and_dims.append((DimCoord(f.blev, long_name='level_height', units='m', bounds=[f.brlev, f.brsvd[0]], attributes={'positive': 'up'}), None)) - aux_coords_and_dims.append((AuxCoord(f.bhlev, long_name='sigma', bounds=[f.bhrlev, f.brsvd[1]]), None)) - factories.append(Factory(HybridHeightFactory, [{'long_name': 'level_height'}, {'long_name': 'sigma'}, Reference('orography')])) - - if f.lbrsvd[3] != 0: - aux_coords_and_dims.append((DimCoord(f.lbrsvd[3], standard_name='realization'), None)) - - if f.lbuser[4] != 0: - aux_coords_and_dims.append((DimCoord(f.lbuser[4], long_name='pseudo_level', units='1'), None)) - - if f.lbuser[6] == 1 and f.lbuser[3] == 5226: - standard_name = "precipitation_amount" - units = "kg m-2" - - if \ - (f.lbuser[6] == 2) and \ - (f.lbuser[3] == 101): - standard_name = "sea_water_potential_temperature" - units = "Celsius" - - if \ - ((f.lbsrce % 10000) == 1111) and \ - ((f.lbsrce / 10000) / 100.0 > 0): - attributes['source'] = 'Data from Met Office Unified Model %4.2f' % ((f.lbsrce / 10000) / 100.0) - - if \ - ((f.lbsrce % 10000) == 1111) and \ - ((f.lbsrce / 10000) / 100.0 == 0): - attributes['source'] = 'Data from Met Office Unified Model' - - if f.lbuser[6] != 0 or (f.lbuser[3] / 1000) != 0 or (f.lbuser[3] % 1000) != 0: - attributes['STASH'] = f.stash - - if \ - (f.lbuser[6] == 1) and \ - (f.lbuser[3] == 4205): - standard_name = "mass_fraction_of_cloud_ice_in_air" - units = "1" - - if \ - (f.lbuser[6] == 1) and \ - (f.lbuser[3] == 4206): - standard_name = "mass_fraction_of_cloud_liquid_water_in_air" - units = "1" - - if \ - (f.lbuser[6] == 1) and \ - (f.lbuser[3] == 30204): - standard_name = "air_temperature" - units = "K" - - if \ - (f.lbuser[6] == 4) and \ - (f.lbuser[3] == 6001): - standard_name = "sea_surface_wave_significant_height" - units = "m" - - if str(f.stash) in STASH_TO_CF: - standard_name = STASH_TO_CF[str(f.stash)].standard_name - units = STASH_TO_CF[str(f.stash)].units - long_name = STASH_TO_CF[str(f.stash)].long_name - - if \ - (not f.stash.is_valid) and \ - (f.lbfc in LBFC_TO_CF): - standard_name = LBFC_TO_CF[f.lbfc].standard_name - units = LBFC_TO_CF[f.lbfc].units - long_name = LBFC_TO_CF[f.lbfc].long_name - - if f.lbuser[3] == 33: - references.append(ReferenceTarget('orography', None)) - - if f.lbuser[3] == 409 or f.lbuser[3] == 1: - references.append(ReferenceTarget('surface_air_pressure', None)) - - return (factories, references, standard_name, long_name, units, attributes, - cell_methods, dim_coords_and_dims, aux_coords_and_dims) diff --git a/lib/iris/fileformats/pp_save_rules.py b/lib/iris/fileformats/pp_save_rules.py new file mode 100644 index 0000000000..5323311061 --- /dev/null +++ b/lib/iris/fileformats/pp_save_rules.py @@ -0,0 +1,814 @@ +# (C) British Crown Copyright 2017 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +import warnings + +import iris +from iris.fileformats._ff_cross_references import STASH_TRANS +from iris.aux_factory import HybridHeightFactory, HybridPressureFactory +from iris.fileformats.um_cf_map import CF_TO_LBFC +from iris.fileformats._pp_lbproc_pairs import LBPROC_MAP +from iris.fileformats.rules import (aux_factory, + has_aux_factory, + scalar_cell_method, + scalar_coord, + vector_coord) +from iris.util import is_regular, regular_step +import cftime + + +def _basic_coord_system_rules(cube, pp): + """ + Rules for setting the coord system of the PP field. + + Args: + cube: the cube being saved as a series of PP fields. + pp: the current PP field having save rules applied. + + Returns: + The PP field with updated metadata. + + """ + if (cube.coord_system("GeogCS") is not None or + cube.coord_system(None) is None): + pp.bplat = 90 + pp.bplon = 0 + elif cube.coord_system("RotatedGeogCS") is not None: + pp.bplat = cube.coord_system("RotatedGeogCS").grid_north_pole_latitude + pp.bplon = cube.coord_system("RotatedGeogCS").grid_north_pole_longitude + return pp + + +def _um_version_rules(cube, pp): + from_um_str = "Data from Met Office Unified Model" + source_attr = cube.attributes.get('source') + if source_attr is not None: + um_version = source_attr.rsplit(from_um_str, 1) + + if ('um_version' not in cube.attributes and + 'source' in cube.attributes and + len(um_version) > 1 and + len(um_version[1]) == 0): + # UM - no version number. + pp.lbsrce = 1111 + elif ('um_version' not in cube.attributes and + 'source' in cube.attributes and + len(um_version) > 1 and + len(um_version[1]) > 0): + # UM - with version number. + pp.lbsrce = int(float(um_version[1]) * 1000000) + 1111 + elif 'um_version' in cube.attributes: + # UM - from 'um_version' attribute. + um_ver_minor = int(cube.attributes['um_version'].split('.')[1]) + um_ver_major = int(cube.attributes['um_version'].split('.')[0]) + pp.lbsrce = 1111 + 10000 * um_ver_minor + 1000000 * um_ver_major + return pp + + +def _stash_rules(cube, pp): + """ + Attributes rules for setting the STASH attribute of the PP field. + + Args: + cube: the cube being saved as a series of PP fields. + pp: the current PP field having save rules applied. + + Returns: + The PP field with updated metadata. + + """ + if 'STASH' in cube.attributes: + stash = cube.attributes['STASH'] + if isinstance(stash, iris.fileformats.pp.STASH): + pp.lbuser[3] = 1000 * (stash.section or 0) + (stash.item or 0) + pp.lbuser[6] = (stash.model or 0) + return pp + + +def _general_time_rules(cube, pp): + """ + Rules for setting time metadata of the PP field. + + Args: + cube: the cube being saved as a series of PP fields. + pp: the current PP field having save rules applied. + + Returns: + The PP field with updated metadata. + + """ + time_coord = scalar_coord(cube, 'time') + fp_coord = scalar_coord(cube, 'forecast_period') + frt_coord = scalar_coord(cube, 'forecast_reference_time') + clim_season_coord = scalar_coord(cube, 'clim_season') + + cm_time_mean = scalar_cell_method(cube, 'mean', 'time') + cm_time_min = scalar_cell_method(cube, 'minimum', 'time') + cm_time_max = scalar_cell_method(cube, 'maximum', 'time') + + # No forecast. + if time_coord is not None and fp_coord is None and frt_coord is None: + pp.lbtim.ia = 0 + pp.lbtim.ib = 0 + pp.t1 = time_coord.units.num2date(time_coord.points[0]) + pp.t2 = cftime.datetime(0, 0, 0) + + # Forecast. + if (time_coord is not None and + not time_coord.has_bounds() and + fp_coord is not None): + pp.lbtim.ia = 0 + pp.lbtim.ib = 1 + pp.t1 = time_coord.units.num2date(time_coord.points[0]) + pp.t2 = time_coord.units.num2date(time_coord.points[0] - + fp_coord.points[0]) + pp.lbft = fp_coord.points[0] + + # Time mean (non-climatological). + # XXX This only works when we have a single timestep. + if (time_coord is not None and + time_coord.has_bounds() and + clim_season_coord is None and + fp_coord is not None and + fp_coord.has_bounds()): + # XXX How do we know *which* time to use if there are more than + # one? *Can* there be more than one? + pp.lbtim.ib = 2 + pp.t1 = time_coord.units.num2date(time_coord.bounds[0, 0]) + pp.t2 = time_coord.units.num2date(time_coord.bounds[0, 1]) + pp.lbft = fp_coord.units.convert(fp_coord.bounds[0, 1], 'hours') + + if (time_coord is not None and + time_coord.has_bounds() and + clim_season_coord is None and + fp_coord is None and + frt_coord is not None): + # Handle missing forecast period using time and forecast ref time. + pp.lbtim.ib = 2 + pp.t1 = time_coord.units.num2date(time_coord.bounds[0, 0]) + pp.t2 = time_coord.units.num2date(time_coord.bounds[0, 1]) + stop = time_coord.units.convert(time_coord.bounds[0, 1], + 'hours since epoch') + start = frt_coord.units.convert(frt_coord.points[0], + 'hours since epoch') + pp.lbft = stop - start + + if (time_coord is not None and + time_coord.has_bounds() and + clim_season_coord is None and + cm_time_mean is not None): + pp.lbtim.ib = 2 + pp.t1 = time_coord.units.num2date(time_coord.bounds[0, 0]) + pp.t2 = time_coord.units.num2date(time_coord.bounds[0, 1]) + + if (time_coord is not None and + time_coord.has_bounds() and + clim_season_coord is None and + cm_time_mean is not None and + cm_time_mean.intervals != () and + cm_time_mean.intervals[0].endswith('hour')): + pp.lbtim.ia = int(cm_time_mean.intervals[0][:-5]) + + if (time_coord is not None and + time_coord.has_bounds() and + clim_season_coord is None and + (fp_coord is not None or frt_coord is not None) and + (cm_time_mean is None or cm_time_mean.intervals == () or + not cm_time_mean.intervals[0].endswith('hour'))): + pp.lbtim.ia = 0 + + # If the cell methods contain a minimum then overwrite lbtim.ia with this + # interval. + if (time_coord is not None and + time_coord.has_bounds() and + clim_season_coord is None and + (fp_coord is not None or frt_coord is not None) and + cm_time_min is not None and + cm_time_min.intervals != () and + cm_time_min.intervals[0].endswith('hour')): + # Set lbtim.ia with the integer part of the cell method's interval + # e.g. if interval is '24 hour' then lbtim.ia becomes 24. + pp.lbtim.ia = int(cm_time_min.intervals[0][:-5]) + + # If the cell methods contain a maximum then overwrite lbtim.ia with this + # interval. + if (time_coord is not None and + time_coord.has_bounds() and + clim_season_coord is None and + (fp_coord is not None or frt_coord is not None) and + cm_time_max is not None and + cm_time_max.intervals != () and + cm_time_max.intervals[0].endswith('hour')): + # Set lbtim.ia with the integer part of the cell method's interval + # e.g. if interval is '1 hour' then lbtim.ia becomes 1. + pp.lbtim.ia = int(cm_time_max.intervals[0][:-5]) + + if time_coord is not None and time_coord.has_bounds(): + lower_bound_yr =\ + time_coord.units.num2date(time_coord.bounds[0, 0]).year + upper_bound_yr =\ + time_coord.units.num2date(time_coord.bounds[0, 1]).year + else: + lower_bound_yr = None + upper_bound_yr = None + + # Climatological time means. + if (time_coord is not None and + time_coord.has_bounds() and + lower_bound_yr == upper_bound_yr and + fp_coord is not None and + fp_coord.has_bounds() and + clim_season_coord is not None and + 'clim_season' in cube.cell_methods[-1].coord_names): + # Climatological time mean - single year. + pp.lbtim.ia = 0 + pp.lbtim.ib = 2 + pp.t1 = time_coord.units.num2date(time_coord.bounds[0, 0]) + pp.t2 = time_coord.units.num2date(time_coord.bounds[0, 1]) + pp.lbft = fp_coord.units.convert(fp_coord.bounds[0, 1], 'hours') + + elif (time_coord is not None and + time_coord.has_bounds() and + lower_bound_yr != upper_bound_yr and + fp_coord is not None and + fp_coord.has_bounds() and + clim_season_coord is not None and + 'clim_season' in cube.cell_methods[-1].coord_names and + clim_season_coord.points[0] == 'djf'): + # Climatological time mean - spanning years - djf. + pp.lbtim.ia = 0 + pp.lbtim.ib = 3 + pp.t1 = time_coord.units.num2date(time_coord.bounds[0, 0]) + pp.t2 = time_coord.units.num2date(time_coord.bounds[0, 1]) + if pp.t1.month == 12: + pp.t1 = cftime.datetime(pp.t1.year) + else: + pp.t1 = cftime.datetime(pp.t1.year-1, 12, 1, 0, 0, 0) + pp.t2 = cftime.datetime(pp.t2.year, 3, 1, 0, 0, 0) + _conditional_warning( + time_coord.bounds[0, 0] != time_coord.units.date2num(pp.t1), + "modified t1 for climatological seasonal mean") + _conditional_warning( + time_coord.bounds[0, 1] != time_coord.units.date2num(pp.t2), + "modified t2 for climatological seasonal mean") + pp.lbft = fp_coord.units.convert(fp_coord.bounds[0, 1], 'hours') + + elif (time_coord is not None and + time_coord.has_bounds() and + lower_bound_yr != upper_bound_yr and + fp_coord is not None and + fp_coord.has_bounds() and + clim_season_coord is not None and + 'clim_season' in cube.cell_methods[-1].coord_names and + clim_season_coord.points[0] == 'mam'): + # Climatological time mean - spanning years - mam. + pp.lbtim.ia = 0 + pp.lbtim.ib = 3 + # TODO: wut? + pp.t1 = time_coord.units.num2date(time_coord.bounds[0, 0]) + pp.t2 = time_coord.units.num2date(time_coord.bounds[0, 1]) + pp.t1 = cftime.datetime(pp.t1.year, 3, 1, 0, 0, 0) + pp.t2 = cftime.datetime(pp.t2.year, 6, 1, 0, 0, 0) + _conditional_warning( + time_coord.bounds[0, 0] != time_coord.units.date2num(pp.t1), + "modified t1 for climatological seasonal mean") + _conditional_warning( + time_coord.bounds[0, 1] != time_coord.units.date2num(pp.t2), + "modified t2 for climatological seasonal mean") + pp.lbft = fp_coord.units.convert(fp_coord.bounds[0, 1], 'hours') + + elif (time_coord is not None and + time_coord.has_bounds() and + lower_bound_yr != upper_bound_yr and + fp_coord is not None and + fp_coord.has_bounds() and + clim_season_coord is not None and + 'clim_season' in cube.cell_methods[-1].coord_names and + clim_season_coord.points[0] == 'jja'): + # Climatological time mean - spanning years - jja. + pp.lbtim.ia = 0 + pp.lbtim.ib = 3 + # TODO: wut? + pp.t1 = time_coord.units.num2date(time_coord.bounds[0, 0]) + pp.t2 = time_coord.units.num2date(time_coord.bounds[0, 1]) + pp.t1 = cftime.datetime(pp.t1.year, 6, 1, 0, 0, 0) + pp.t2 = cftime.datetime(pp.t2.year, 9, 1, 0, 0, 0) + _conditional_warning( + time_coord.bounds[0, 0] != time_coord.units.date2num(pp.t1), + "modified t1 for climatological seasonal mean") + _conditional_warning( + time_coord.bounds[0, 1] != time_coord.units.date2num(pp.t2), + "modified t2 for climatological seasonal mean") + pp.lbft = fp_coord.units.convert(fp_coord.bounds[0, 1], 'hours') + + elif (time_coord is not None and + time_coord.has_bounds() and + lower_bound_yr != upper_bound_yr and + fp_coord is not None and + fp_coord.has_bounds() and + clim_season_coord is not None and + 'clim_season' in cube.cell_methods[-1].coord_names and + clim_season_coord.points[0] == 'son'): + # Climatological time mean - spanning years - son. + pp.lbtim.ia = 0 + pp.lbtim.ib = 3 + # TODO: wut? + pp.t1 = time_coord.units.num2date(time_coord.bounds[0, 0]) + pp.t2 = time_coord.units.num2date(time_coord.bounds[0, 1]) + pp.t1 = cftime.datetime(pp.t1.year, 9, 1, 0, 0, 0) + pp.t2 = cftime.datetime(pp.t2.year, 12, 1, 0, 0, 0) + _conditional_warning( + time_coord.bounds[0, 0] != time_coord.units.date2num(pp.t1), + "modified t1 for climatological seasonal mean") + _conditional_warning( + time_coord.bounds[0, 1] != time_coord.units.date2num(pp.t2), + "modified t2 for climatological seasonal mean") + pp.lbft = fp_coord.units.convert(fp_coord.bounds[0, 1], 'hours') + + return pp + + +def _calendar_rules(cube, pp): + """ + Rules for setting the calendar of the PP field. + + Args: + cube: the cube being saved as a series of PP fields. + pp: the current PP field having save rules applied. + + Returns: + The PP field with updated metadata. + + """ + time_coord = scalar_coord(cube, 'time') + if time_coord is not None: + if time_coord.units.calendar == '360_day': + pp.lbtim.ic = 2 + elif time_coord.units.calendar == 'gregorian': + pp.lbtim.ic = 1 + elif time_coord.units.calendar == '365_day': + pp.lbtim.ic = 4 + return pp + + +def _grid_and_pole_rules(cube, pp): + """ + Rules for setting the horizontal grid and pole location of the PP field. + + Args: + cube: the cube being saved as a series of PP fields. + pp: the current PP field having save rules applied. + + Returns: + The PP field with updated metadata. + + """ + lon_coord = vector_coord(cube, 'longitude') + grid_lon_coord = vector_coord(cube, 'grid_longitude') + lat_coord = vector_coord(cube, 'latitude') + grid_lat_coord = vector_coord(cube, 'grid_latitude') + + if lon_coord and not is_regular(lon_coord): + pp.bzx = 0 + pp.bdx = 0 + pp.lbnpt = lon_coord.shape[0] + pp.x = lon_coord.points + elif grid_lon_coord and not is_regular(grid_lon_coord): + pp.bzx = 0 + pp.bdx = 0 + pp.lbnpt = grid_lon_coord.shape[0] + pp.x = grid_lon_coord.points + elif lon_coord and is_regular(lon_coord): + pp.bzx = lon_coord.points[0] - regular_step(lon_coord) + pp.bdx = regular_step(lon_coord) + pp.lbnpt = len(lon_coord.points) + elif grid_lon_coord and is_regular(grid_lon_coord): + pp.bzx = grid_lon_coord.points[0] - regular_step(grid_lon_coord) + pp.bdx = regular_step(grid_lon_coord) + pp.lbnpt = len(grid_lon_coord.points) + + if lat_coord and not is_regular(lat_coord): + pp.bzy = 0 + pp.bdy = 0 + pp.lbrow = lat_coord.shape[0] + pp.y = lat_coord.points + elif grid_lat_coord and not is_regular(grid_lat_coord): + pp.bzy = 0 + pp.bdy = 0 + pp.lbrow = grid_lat_coord.shape[0] + pp.y = grid_lat_coord.points + elif lat_coord and is_regular(lat_coord): + pp.bzy = lat_coord.points[0] - regular_step(lat_coord) + pp.bdy = regular_step(lat_coord) + pp.lbrow = len(lat_coord.points) + elif grid_lat_coord and is_regular(grid_lat_coord): + pp.bzy = grid_lat_coord.points[0] - regular_step(grid_lat_coord) + pp.bdy = regular_step(grid_lat_coord) + pp.lbrow = len(grid_lat_coord.points) + + # Check if we have a rotated coord system. + if cube.coord_system("RotatedGeogCS") is not None: + pp.lbcode = int(pp.lbcode) + 100 + + # Check if we have a circular x-coord. + for lon_coord in (lon_coord, grid_lon_coord): + if lon_coord is not None: + if lon_coord.circular: + pp.lbhem = 0 + else: + pp.lbhem = 3 + + return pp + + +def _non_std_cross_section_rules(cube, pp): + """ + Rules for applying non-standard cross-sections to the PP field. + + Args: + cube: the cube being saved as a series of PP fields. + pp: the current PP field having save rules applied. + + Returns: + The PP field with updated metadata. + + """ + # Define commonly-used coords. + air_pres_coord = vector_coord(cube, 'air_pressure') + depth_coord = vector_coord(cube, 'depth') + eta_coord = vector_coord(cube, 'eta') + lat_coord = vector_coord(cube, 'latitude') + time_coord = vector_coord(cube, 'time') + + # Non-standard cross-section with bounds - x=latitude, y=air_pressure. + if (air_pres_coord is not None and + not air_pres_coord.circular and + air_pres_coord.has_bounds() and + lat_coord is not None and + not lat_coord.circular and + lat_coord.has_bounds()): + pp.lbcode = 10000 + int(100*10) + 1 + pp.bgor = 0 + pp.y = air_pres_coord.points + pp.y_lower_bound = air_pres_coord.bounds[:, 0] + pp.y_upper_bound = air_pres_coord.bounds[:, 1] + pp.x = lat_coord.points + pp.x_lower_bound = lat_coord.bounds[:, 0] + pp.x_upper_bound = lat_coord.bounds[:, 1] + pp.lbrow = air_pres_coord.shape[0] + pp.lbnpt = lat_coord.shape[0] + pp.bzx = pp.bzy = pp.bdx = pp.bdy = 0 + + # Non-standard cross-section with bounds - x=latitude, y=depth. + if (depth_coord is not None and + not depth_coord.circular and + depth_coord.has_bounds() and + lat_coord is not None and + not lat_coord.circular and + lat_coord.has_bounds()): + pp.lbcode = 10000 + int(100*10) + 4 + pp.bgor = 0 + pp.y = depth_coord.points + pp.y_lower_bound = depth_coord.bounds[:, 0] + pp.y_upper_bound = depth_coord.bounds[:, 1] + pp.x = lat_coord.points + pp.x_lower_bound = lat_coord.bounds[:, 0] + pp.x_upper_bound = lat_coord.bounds[:, 1] + pp.lbrow = depth_coord.shape[0] + pp.lbnpt = lat_coord.shape[0] + pp.bzx = pp.bzy = pp.bdx = pp.bdy = 0 + + # Non-standard cross-section with bounds - x=latitude, y=eta. + if (eta_coord is not None and + not eta_coord.circular and + eta_coord.has_bounds() and + lat_coord is not None and + not lat_coord.circular and + lat_coord.has_bounds()): + pp.lbcode = 10000 + int(100*10) + 3 + pp.bgor = 0 + pp.y = eta_coord.points + pp.y_lower_bound = eta_coord.bounds[:, 0] + pp.y_upper_bound = eta_coord.bounds[:, 1] + pp.x = lat_coord.points + pp.x_lower_bound = lat_coord.bounds[:, 0] + pp.x_upper_bound = lat_coord.bounds[:, 1] + pp.lbrow = eta_coord.shape[0] + pp.lbnpt = lat_coord.shape[0] + pp.bzx = pp.bzy = pp.bdx = pp.bdy = 0 + + # Non-standard cross-section with bounds - x=days (360 calendar), y=depth. + if (depth_coord is not None and + not depth_coord.circular and + depth_coord.has_bounds() and + time_coord is not None and + not time_coord.circular and + time_coord.has_bounds()): + pp.lbcode = 10000 + int(100*23) + 4 + pp.bgor = 0 + pp.y = depth_coord.points + pp.y_lower_bound = depth_coord.bounds[:, 0] + pp.y_upper_bound = depth_coord.bounds[:, 1] + pp.x = time_coord.points + pp.x_lower_bound = time_coord.bounds[:, 0] + pp.x_upper_bound = time_coord.bounds[:, 1] + pp.lbrow = depth_coord.shape[0] + pp.lbnpt = time_coord.shape[0] + pp.bzx = pp.bzy = pp.bdx = pp.bdy = 0 + + # Non-standard cross-section with bounds - + # x=days (360 calendar), y=air_pressure. + if (air_pres_coord is not None and + not air_pres_coord.circular and + air_pres_coord.has_bounds() and + time_coord is not None and + not time_coord.circular and + time_coord.has_bounds()): + pp.lbcode = 10000 + int(100*23) + 1 + pp.bgor = 0 + pp.y = air_pres_coord.points + pp.y_lower_bound = air_pres_coord.bounds[:, 0] + pp.y_upper_bound = air_pres_coord.bounds[:, 1] + pp.x = time_coord.points + pp.x_lower_bound = time_coord.bounds[:, 0] + pp.x_upper_bound = time_coord.bounds[:, 1] + pp.lbrow = air_pres_coord.shape[0] + pp.lbnpt = time_coord.shape[0] + pp.bzx = pp.bzy = pp.bdx = pp.bdy = 0 + + return pp + + +def _lbproc_rules(cube, pp): + """ + Rules for setting the horizontal grid and pole location of the PP field. + + Note: `pp.lbproc` must be set to 0 before these rules are run. + + Args: + cube: the cube being saved as a series of PP fields. + pp: the current PP field having save rules applied. + + Returns: + The PP field with updated metadata. + + """ + # Basic setting (this may be overridden by subsequent rules). + pp.lbproc = 0 + + if cube.attributes.get("ukmo__process_flags", None): + pp.lbproc += sum([LBPROC_MAP[name] + for name in cube.attributes["ukmo__process_flags"]]) + + # Zonal-mean: look for a CellMethod which is a "mean" over "longitude" or + # "grid_longitude". + if (scalar_cell_method(cube, 'mean', 'longitude') is not None or + scalar_cell_method(cube, 'mean', 'grid_longitude') is not None): + pp.lbproc += 64 + + # Time-mean: look for a CellMethod which is a "mean" over "time". + if scalar_cell_method(cube, 'mean', 'time') is not None: + pp.lbproc += 128 + + # Time-minimum: look for a CellMethod which is a "minimum" over "time". + if scalar_cell_method(cube, 'minimum', 'time') is not None: + pp.lbproc += 4096 + + # Time-maximum: look for a CellMethod which is a "maximum" over "time". + if scalar_cell_method(cube, 'maximum', 'time') is not None: + pp.lbproc += 8192 + + return pp + + +def _vertical_rules(cube, pp): + """ + Rules for setting vertical levels for the PP field. + + Args: + cube: the cube being saved as a series of PP fields. + pp: the current PP field having save rules applied. + + Returns: + The PP field with updated metadata. + + """ + # Define commonly-used coords. + air_pres_coord = scalar_coord(cube, 'air_pressure') + apt_coord = scalar_coord(cube, 'air_potential_temperature') + depth_coord = scalar_coord(cube, 'depth') + height_coord = scalar_coord(cube, 'height') + level_height_coord = scalar_coord(cube, 'level_height') + mln_coord = scalar_coord(cube, 'model_level_number') + pressure_coord = scalar_coord(cube, 'pressure') + pseudo_level_coord = scalar_coord(cube, 'pseudo_level') + sigma_coord = scalar_coord(cube, 'sigma') + soil_mln_coord = scalar_coord(cube, 'soil_model_level_number') + + # Define commonly-used aux factories. + try: + height_factory = aux_factory(cube, HybridHeightFactory) + except ValueError: + height_factory = None + try: + pressure_factory = aux_factory(cube, HybridPressureFactory) + except ValueError: + pressure_factory = None + + # Set `lbuser[5]`. + if (pseudo_level_coord is not None and + not pseudo_level_coord.bounds): + pp.lbuser[4] = pseudo_level_coord.points[0] + + # Single height level. + if (height_coord is not None and + not height_coord.bounds and + height_coord.points[0] == 1.5 and + cube.name() == 'air_temperature'): + pp.lbvc = 129 + pp.blev = -1 + + if pp.lbvc == 0 and height_coord is not None and not height_coord.bounds: + pp.lbvc = 1 + pp.blev = cube.coord('height').points[0] + + # Single air_pressure level. + if air_pres_coord is not None and not air_pres_coord.bounds: + pp.lbvc = 8 + pp.blev = air_pres_coord.points[0] + + # Single pressure level. + if pressure_coord is not None and not pressure_coord.bounds: + pp.lbvc = 8 + pp.blev = pressure_coord.points[0] + + # Single depth level (non cross-section). + if (mln_coord is not None and + not mln_coord.bounds and + depth_coord is not None and + not depth_coord.bounds): + pp.lbvc = 2 + pp.lblev = mln_coord.points[0] + pp.blev = depth_coord.points[0] + + # Single depth level (Non-dimensional soil model level). + if (soil_mln_coord is not None and + not soil_mln_coord.has_bounds() and + air_pres_coord is None and + depth_coord is None and + height_coord is None and + pressure_coord is None and + cube.standard_name is not None and + 'soil' in cube.standard_name): + pp.lbvc = 6 + pp.lblev = soil_mln_coord.points[0] + pp.blev = pp.lblev + pp.brsvd[0] = 0 + pp.brlev = 0 + + # Single depth level (soil depth). + if (depth_coord is not None and + depth_coord.has_bounds() and + air_pres_coord is None and + soil_mln_coord is None and + mln_coord is None and + height_coord is None and + pressure_coord is None and + cube.standard_name is not None and + 'soil' in cube.standard_name): + pp.lbvc = 6 + pp.blev = depth_coord.points[0] + pp.brsvd[0] = depth_coord.bounds[0, 0] + pp.brlev = depth_coord.bounds[0, 1] + + # Single potential-temperature level. + if (apt_coord is not None and + not apt_coord.bounds and + air_pres_coord is None and + depth_coord is None and + height_coord is None and + pressure_coord is None and + mln_coord is None): + pp.lbvc = 19 + pp.lblev = apt_coord.points[0] + pp.blev = apt_coord.points[0] + + # Single hybrid_height level + # (without aux factory e.g. due to missing orography). + if (not has_aux_factory(cube, HybridHeightFactory) and + mln_coord is not None and + mln_coord.bounds is None and + level_height_coord is not None and + level_height_coord.bounds is not None and + sigma_coord is not None and + sigma_coord.bounds is not None): + pp.lbvc = 65 + pp.lblev = mln_coord.points[0] + pp.blev = level_height_coord.points[0] + pp.brlev = level_height_coord.bounds[0, 0] + pp.brsvd[0] = level_height_coord.bounds[0, 1] + pp.bhlev = sigma_coord.points[0] + pp.bhrlev = sigma_coord.bounds[0, 0] + pp.brsvd[1] = sigma_coord.bounds[0, 1] + + # Single hybrid_height level (with aux factory). + if (has_aux_factory(cube, HybridHeightFactory) and + mln_coord is not None and + mln_coord.bounds is None and + height_factory.dependencies['delta'] is not None and + height_factory.dependencies['delta'].bounds is not None and + height_factory.dependencies['sigma'] is not None and + height_factory.dependencies['sigma'].bounds is not None): + pp.lbvc = 65 + pp.lblev = mln_coord.points[0] + pp.blev = height_factory.dependencies['delta'].points[0] + pp.brlev = height_factory.dependencies['delta'].bounds[0, 0] + pp.brsvd[0] = height_factory.dependencies['delta'].bounds[0, 1] + pp.bhlev = height_factory.dependencies['sigma'].points[0] + pp.bhrlev = height_factory.dependencies['sigma'].bounds[0, 0] + pp.brsvd[1] = height_factory.dependencies['sigma'].bounds[0, 1] + + # Single hybrid pressure level. + if (has_aux_factory(cube, HybridPressureFactory) and + mln_coord is not None and + mln_coord.bounds is None and + pressure_factory.dependencies['delta'] is not None and + pressure_factory.dependencies['delta'].bounds is not None and + pressure_factory.dependencies['sigma'] is not None and + pressure_factory.dependencies['sigma'].bounds is not None): + pp.lbvc = 9 + pp.lblev = mln_coord.points[0] + pp.blev = pressure_factory.dependencies['sigma'].points[0] + pp.brlev = pressure_factory.dependencies['sigma'].bounds[0, 0] + pp.brsvd[0] = pressure_factory.dependencies['sigma'].bounds[0, 1] + pp.bhlev = pressure_factory.dependencies['delta'].points[0] + pp.bhrlev = pressure_factory.dependencies['delta'].bounds[0, 0] + pp.brsvd[1] = pressure_factory.dependencies['delta'].bounds[0, 1] + + return pp + + +def _all_other_rules(cube, pp): + """ + Rules for setting the horizontal grid and pole location of the PP field. + + Args: + cube: the cube being saved as a series of PP fields. + pp: the current PP field having save rules applied. + + Returns: + The PP field with updated metadata. + + """ + # "CFNAME mega-rule." + check_items = (cube.standard_name, cube.long_name, str(cube.units)) + if check_items in CF_TO_LBFC: + pp.lbfc = CF_TO_LBFC[check_items] + + # Set STASH code. + if ('STASH' in cube.attributes and + str(cube.attributes['STASH']) in STASH_TRANS): + pp.lbfc = STASH_TRANS[str(cube.attributes['STASH'])].field_code + + return pp + + +def verify(cube, field): + # Rules functions. + field = _basic_coord_system_rules(cube, field) + field = _um_version_rules(cube, field) + field = _stash_rules(cube, field) + field = _general_time_rules(cube, field) + field = _calendar_rules(cube, field) + field = _grid_and_pole_rules(cube, field) + field = _non_std_cross_section_rules(cube, field) + field = _lbproc_rules(cube, field) + field = _vertical_rules(cube, field) + field = _all_other_rules(cube, field) + + return field + + +# Helper functions used when running the rules. + +def _conditional_warning(condition, warning): + if condition: + warnings.warn(warning) diff --git a/lib/iris/fileformats/rules.py b/lib/iris/fileformats/rules.py index 67780c6835..86e134d51f 100644 --- a/lib/iris/fileformats/rules.py +++ b/lib/iris/fileformats/rules.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -15,34 +15,24 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """ -Processing of simple IF-THEN rules. +Generalised mechanisms for metadata translation and cube construction. """ -import abc +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + import collections -import getpass -import logging -import logging.handlers as handlers -import operator -import os -import os.path -import platform -import sys -import types import warnings -import numpy as np -import numpy.ma as ma +import cf_units -import iris.config as config +from iris.analysis import Linear import iris.cube import iris.exceptions import iris.fileformats.um_cf_map -import iris.unit -from iris.util import is_regular, regular_step -RuleResult = collections.namedtuple('RuleResult', ['cube', 'matching_rules', 'factories']) Factory = collections.namedtuple('Factory', ['factory_class', 'args']) ReferenceTarget = collections.namedtuple('ReferenceTarget', ('name', 'transform')) @@ -68,7 +58,7 @@ def as_cube(self): if len(src_cubes) > 1: # Merge the reference cubes to allow for # time-varying surface pressure in hybrid-presure. - src_cubes = src_cubes.merge() + src_cubes = src_cubes.merge(unique=False) if len(src_cubes) > 1: warnings.warn('Multiple reference cubes for {}' .format(self.name)) @@ -79,154 +69,13 @@ def as_cube(self): else: final_cube = src_cube.copy() attributes = self.transform(final_cube) - for name, value in attributes.iteritems(): + for name, value in six.iteritems(attributes): setattr(final_cube, name, value) self._final_cube = final_cube return self._final_cube -# Controls the deferred import of all the symbols from iris.coords. -# This import all is used as the rules file does not use fully qualified class names. -_import_pending = True - - -# Dummy logging routine for when we don't want to do any logging. -def _dummy_log(format, filename, rules): - pass - - -# Genuine logging routine -def _real_log(format, filename, rules): - # Replace "\" with "\\", and "," with "\," - filename = filename.replace('\\', '\\\\').replace(',', '\\,') - _rule_logger.info("%s,%s,%s" % (format, filename, ','.join([rule.id for rule in rules]))) - - -# Debug logging routine (more informative that just object ids) -def _verbose_log(format, filename, rules): - # Replace "\" with "\\", and "," with "\," - filename = filename.replace('\\', '\\\\').replace(',', '\\,') - _rule_logger.info("\n\n-----\n\n%s,%s,%s" % (format, filename, '\n\n'.join([str(rule) for rule in rules]))) - - -# Prepares a logger for file-based logging of rule usage -def _prepare_rule_logger(verbose=False): - # Default to the dummy logger that does nothing - logger = _dummy_log - - # Only do real logging if we've been told the directory to use ... - log_dir = config.RULE_LOG_DIR - if log_dir is not None: - user = getpass.getuser() - - # .. and if we haven't been told to ignore the current invocation. - ignore = False - ignore_users = config.RULE_LOG_IGNORE - if ignore_users is not None: - ignore_users = ignore_users.split(',') - ignore = user in ignore_users - - if not ignore: - try: - hostname = platform.node() or 'UNKNOWN' - log_path = os.path.join(log_dir, '_'.join([hostname, user])) - file_handler = handlers.RotatingFileHandler(log_path, maxBytes=1e7, backupCount=5) - format = '%%(asctime)s,%s,%%(message)s' % getpass.getuser() - file_handler.setFormatter(logging.Formatter(format, '%Y-%m-%d %H:%M:%S')) - - global _rule_logger - _rule_logger = logging.getLogger('iris.fileformats.rules') - _rule_logger.setLevel(logging.INFO) - _rule_logger.addHandler(file_handler) - _rule_logger.propagate = False - - if verbose: - logger = _verbose_log - else: - logger = _real_log - - except IOError: - # If we can't create the log file for some reason then it's fine to just silently - # ignore the error and fallback to using the dummy logging routine. - pass - - return logger - - -# Defines the "log" function for this module -log = _prepare_rule_logger() - - -class DebugString(str): - """ - Used by the rules for debug purposes - - """ - - -class CMAttribute(object): - """ - Used by the rules for defining attributes on the Cube in a consistent manner. - - """ - __slots__ = ('name', 'value') - def __init__(self, name, value): - self.name = name - self.value = value - - -class CMCustomAttribute(object): - """ - Used by the rules for defining custom attributes on the Cube in a consistent manner. - - """ - __slots__ = ('name', 'value') - def __init__(self, name, value): - self.name = name - self.value = value - - -class CoordAndDims(object): - """ - Used within rules to represent a mapping of coordinate to data dimensions. - - """ - def __init__(self, coord, dims=None): - self.coord = coord - if dims is None: - dims = [] - if not isinstance(dims, list): - dims = [dims] - self.dims = dims - - def add_coord(self, cube): - added = False - - # Try to add to dim_coords? - if isinstance(self.coord, iris.coords.DimCoord) and self.dims: - if len(self.dims) > 1: - raise Exception("Only 1 dim allowed for a DimCoord") - - # Does the cube already have a coord for this dim? - already_taken = False - for coord, coord_dim in cube._dim_coords_and_dims: - if coord_dim == self.dims[0]: - already_taken = True - break - - if not already_taken: - cube.add_dim_coord(self.coord, self.dims[0]) - added = True - - # If we didn't add it to dim_coords, add it to aux_coords. - if not added: - cube.add_aux_coord(self.coord, self.dims) - - def __repr__(self): - return "" % (self.coord.name, self.dims) - - class Reference(iris.util._OrderedHashable): _names = ('name',) """ @@ -235,333 +84,6 @@ class Reference(iris.util._OrderedHashable): """ -def calculate_forecast_period(time, forecast_reference_time): - """ - Return the forecast period in hours derived from time and - forecast_reference_time scalar coordinates. - - """ - if time.points.size != 1: - raise ValueError('Expected a time coordinate with a single ' - 'point. {!r} has {} points.'.format(time.name(), - time.points.size)) - - if not time.has_bounds(): - raise ValueError('Expected a time coordinate with bounds.') - - if forecast_reference_time.points.size != 1: - raise ValueError('Expected a forecast_reference_time coordinate ' - 'with a single point. {!r} has {} ' - 'points.'.format(forecast_reference_time.name(), - forecast_reference_time.points.size)) - - origin = time.units.origin.replace(time.units.origin.split()[0], 'hours') - units = iris.unit.Unit(origin, calendar=time.units.calendar) - - # Determine start and eof of period in hours since a common epoch. - end = time.units.convert(time.bounds[0, 1], units) - start = forecast_reference_time.units.convert( - forecast_reference_time.points[0], units) - forecast_period = end - start - - return forecast_period - - -class Rule(object): - """ - A collection of condition expressions and their associated action expressions. - - Example rule:: - - IF - f.lbuser[6] == 2 - f.lbuser[3] == 101 - THEN - CMAttribute('standard_name', 'sea_water_potential_temperature') - CMAttribute('units', 'Celsius') - - """ - def __init__(self, conditions, actions): - """Create instance methods from our conditions and actions.""" - if not hasattr(conditions, '__iter__'): - raise TypeError('Variable conditions should be iterable, got: '+ type(conditions)) - if not hasattr(actions, '__iter__'): - raise TypeError('Variable actions should be iterable, got: '+ type(actions)) - - self._conditions = conditions - self._actions = actions - self._exec_actions = [] - - self.id = str(hash((tuple(self._conditions), tuple(self._actions)))) - - for i, condition in enumerate(conditions): - self._conditions[i] = condition - - # Create the conditions method. - self._create_conditions_method() - - # Create the action methods. - for i, action in enumerate(self._actions): - if not action: - action = 'None' - self._create_action_method(i, action) - - def _create_conditions_method(self): - # Bundle all the conditions into one big string. - conditions = '(%s)' % ') and ('.join(self._conditions) - if not conditions: - conditions = 'None' - # Create a method to evaluate the conditions. - # NB. This creates the name '_exec_conditions' in the local - # namespace, which is then used below. - code = 'def _exec_conditions(self, field, f, pp, grib, cm): return %s' - exec compile(code % conditions, '', 'exec') - # Make it a method of ours. - self._exec_conditions = types.MethodType(_exec_conditions, self, type(self)) - - @abc.abstractmethod - def _create_action_method(self, i, action): - pass - - @abc.abstractmethod - def _process_action_result(self, obj, cube): - pass - - def __repr__(self): - string = "IF\n" - string += '\n'.join(self._conditions) - string += "\nTHEN\n" - string += '\n'.join(self._actions) - return string - - def evaluates_true(self, cube, field): - """Returns True if and only if all the conditions evaluate to True for the given field.""" - field = field - f = field - pp = field - grib = field - cm = cube - - try: - result = self._exec_conditions(field, f, pp, grib, cm) - except Exception, err: - print >> sys.stderr, 'Condition failed to run conditions: %s : %s' % (self._conditions, err) - raise err - - return result - - def _matches_field(self, field): - """Simple wrapper onto evaluates_true in the case where cube is None.""" - return self.evaluates_true(None, field) - - def run_actions(self, cube, field): - """ - Adds to the given cube based on the return values of all the actions. - - """ - # Deferred import of all the symbols from iris.coords. - # This import all is used as the rules file does not use fully qualified class names. - global _import_pending - if _import_pending: - globals().update(iris.aux_factory.__dict__) - globals().update(iris.coords.__dict__) - globals().update(iris.coord_systems.__dict__) - globals().update(iris.fileformats.um_cf_map.__dict__) - globals().update(iris.unit.__dict__) - _import_pending = False - - # Define the variables which the eval command should be able to see - f = field - pp = field - grib = field - cm = cube - - factories = [] - for i, action in enumerate(self._actions): - try: - # Run this action. - obj = self._exec_actions[i](field, f, pp, grib, cm) - # Process the return value (if any), e.g a CM object or None. - action_factory = self._process_action_result(obj, cube) - if action_factory: - factories.append(action_factory) - - except iris.exceptions.CoordinateNotFoundError, err: - print >> sys.stderr, 'Failed (msg:%(error)s) to find coordinate, perhaps consider running last: %(command)s' % {'command':action, 'error': err} - except AttributeError, err: - print >> sys.stderr, 'Failed to get value (%(error)s) to execute: %(command)s' % {'command':action, 'error': err} - except Exception, err: - print >> sys.stderr, 'Failed (msg:%(error)s) to run:\n %(command)s\nFrom the rule:\n%(me)r' % {'me':self, 'command':action, 'error': err} - raise err - - return factories - - -class FunctionRule(Rule): - """A Rule with values returned by its actions.""" - def _create_action_method(self, i, action): - # CM loading style action. Returns an object, such as a coord. - exec compile('def _exec_action_%d(self, field, f, pp, grib, cm): return %s' % (i, action), '', 'exec') - # Make it a method of ours. - exec 'self._exec_action_%d = types.MethodType(_exec_action_%d, self, type(self))' % (i, i) - # Add to our list of actions. - exec 'self._exec_actions.append(self._exec_action_%d)' % i - - def _process_action_result(self, obj, cube): - """Process the result of an action.""" - - factory = None - - # NB. The names such as 'CoordAndDims' and 'CellMethod' are defined by - # the "deferred import" performed by Rule.run_actions() above. - if isinstance(obj, CoordAndDims): - obj.add_coord(cube) - - #cell methods - not yet implemented - elif isinstance(obj, CellMethod): - cube.add_cell_method(obj) - - elif isinstance(obj, CMAttribute): - # Temporary code to deal with invalid standard names from the translation table. - # TODO: when name is "standard_name" force the value to be a real standard name - if obj.name == 'standard_name' and obj.value is not None: - cube.rename(obj.value) - elif obj.name == 'units': - # Graceful loading of units. - try: - setattr(cube, obj.name, obj.value) - except ValueError: - msg = 'Ignoring PP invalid units {!r}'.format(obj.value) - warnings.warn(msg) - cube.attributes['invalid_units'] = obj.value - cube.units = iris.unit._UNKNOWN_UNIT_STRING - else: - setattr(cube, obj.name, obj.value) - - elif isinstance(obj, CMCustomAttribute): - cube.attributes[obj.name] = obj.value - - elif isinstance(obj, Factory): - factory = obj - - elif isinstance(obj, DebugString): - print obj - - # The function returned nothing, like the pp save actions, "lbft = 3" - elif obj is None: - pass - - else: - raise Exception("Object could not be added to cube. Unknown type: " + obj.__class__.__name__) - - return factory - - -class ProcedureRule(Rule): - """A Rule with nothing returned by its actions.""" - def _create_action_method(self, i, action): - # PP saving style action. No return value, e.g. "pp.lbft = 3". - exec compile('def _exec_action_%d(self, field, f, pp, grib, cm): %s' % (i, action), '', 'exec') - # Make it a method of ours. - exec 'self._exec_action_%d = types.MethodType(_exec_action_%d, self, type(self))' % (i, i) - # Add to our list of actions. - exec 'self._exec_actions.append(self._exec_action_%d)' % i - - def _process_action_result(self, obj, cube): - # This should always be None, as our rules won't create anything. - pass - - def conditional_warning(self, condition, warning): - pass # without this pass statement it alsp print, " Args:" on a new line. - if condition: - warnings.warn(warning) - - -class RulesContainer(object): - """ - A collection of :class:`Rule` instances, with the ability to read rule - definitions from files and run the rules against given fields. - - """ - def __init__(self, filepath=None, rule_type=FunctionRule): - """Create a new rule set, optionally adding rules from the specified file. - - The rule_type defaults to :class:`FunctionRule`, - e.g for CM loading actions that return objects, such as *AuxCoord(...)* - - rule_type can also be set to :class:`ProcedureRule` - e.g for PP saving actions that do not return anything, such as *pp.lbuser[3] = 16203* - """ - self._rules = [] - self.rule_type = rule_type - if filepath is not None: - self.import_rules(filepath) - - def import_rules(self, filepath): - """Extend the rule collection with the rules defined in the specified file.""" - # Define state constants - IN_CONDITION = 1 - IN_ACTION = 2 - - rule_file = os.path.expanduser(filepath) - file = open(rule_file, 'r') - - conditions = [] - actions = [] - state = None - for line in file: - line = line.rstrip() - if line == "IF": - if conditions and actions: - self._rules.append(self.rule_type(conditions, actions)) - conditions = [] - actions = [] - state = IN_CONDITION - elif line == "THEN": - state = IN_ACTION - elif len(line) == 0: - pass - elif line.strip().startswith('#'): - pass - elif state == IN_CONDITION: - conditions.append(line) - elif state == IN_ACTION: - actions.append(line) - else: - raise Exception('Rule file not read correctly at line: ' + line) - if conditions and actions: - self._rules.append(self.rule_type(conditions, actions)) - file.close() - - def verify(self, cube, field): - """ - Add to the given :class:`iris.cube.Cube` by running this set of - rules with the given field. - - Args: - - * cube: - An instance of :class:`iris.cube.Cube`. - * field: - A field object relevant to the rule set. - - Returns: (cube, matching_rules) - - * cube - the resultant cube - * matching_rules - a list of rules which matched - - """ - matching_rules = [] - factories = [] - for rule in self._rules: - if rule.evaluates_true(cube, field): - matching_rules.append(rule) - rule_factories = rule.run_actions(cube, field) - if rule_factories: - factories.extend(rule_factories) - return RuleResult(cube, matching_rules, factories) - - def scalar_coord(cube, coord_name): """Try to find a single-valued coord with the given name.""" found_coord = None @@ -588,9 +110,10 @@ def scalar_cell_method(cube, method, coord_name): for cell_method in cube.cell_methods: if cell_method.method == method and len(cell_method.coord_names) == 1: name = cell_method.coord_names[0] - coords = cube.coords(name) - if len(coords) == 1: - found_cell_method = cell_method + if name == coord_name: + coords = cube.coords(name) + if len(coords) == 1: + found_cell_method = cell_method return found_cell_method @@ -653,8 +176,8 @@ def _dereference_args(factory, reference_targets, regrid_cache, cube): raise _ReferenceError('Unable to regrid reference for' ' {!r}'.format(arg.name)) else: - raise _ReferenceError("The file(s) {{filenames}} don't contain" - " field(s) for {!r}.".format(arg.name)) + raise _ReferenceError("The source data contains no " + "field(s) for {!r}.".format(arg.name)) else: # If it wasn't a Reference, then arg is a dictionary # of keyword arguments for cube.coord(...). @@ -665,7 +188,7 @@ def _dereference_args(factory, reference_targets, regrid_cache, cube): def _regrid_to_target(src_cube, target_coords, target_cube): # Interpolate onto the target grid. sample_points = [(coord, coord.points) for coord in target_coords] - result_cube = iris.analysis.interpolate.linear(src_cube, sample_points) + result_cube = src_cube.interpolate(sample_points, Linear()) # Any scalar coords on the target_cube will have become vector # coords on the resample src_cube (i.e. result_cube). @@ -703,7 +226,7 @@ def _ensure_aligned(regrid_cache, src_cube, target_cube): # ensure each target coord is either a scalar or maps to a # single, distinct dimension. target_dims = [target_cube.coord_dims(coord) for coord in target_coords] - target_dims = filter(None, target_dims) + target_dims = list(filter(None, target_dims)) unique_dims = set() for dims in target_dims: unique_dims.update(dims) @@ -732,95 +255,176 @@ def _ensure_aligned(regrid_cache, src_cube, target_cube): return result_cube -Loader = collections.namedtuple('Loader', - ('field_generator', 'field_generator_kwargs', - 'converter', 'legacy_custom_rules')) +_loader_attrs = ('field_generator', 'field_generator_kwargs', + 'converter') +class Loader(collections.namedtuple('Loader', _loader_attrs)): + def __new__(cls, field_generator, field_generator_kwargs, converter): + """ + Create a definition of a field-based Cube loader. + + Args: + + * field_generator + A callable that accepts a filename as its first argument and + returns an iterable of field objects. + + * field_generator_kwargs + Additional arguments to be passed to the field_generator. + + * converter + A callable that converts a field object into a Cube. + + """ + return tuple.__new__(cls, (field_generator, field_generator_kwargs, + converter)) + + +ConversionMetadata = collections.namedtuple('ConversionMetadata', + ('factories', 'references', + 'standard_name', 'long_name', + 'units', 'attributes', + 'cell_methods', + 'dim_coords_and_dims', + 'aux_coords_and_dims')) def _make_cube(field, converter): # Convert the field to a Cube. - (factories, references, standard_name, long_name, units, attributes, - cell_methods, dim_coords_and_dims, aux_coords_and_dims) = converter(field) - - try: - data = field._data - except AttributeError: - data = field.data + metadata = converter(field) - cube = iris.cube.Cube(data, - attributes=attributes, - cell_methods=cell_methods, - dim_coords_and_dims=dim_coords_and_dims, - aux_coords_and_dims=aux_coords_and_dims) + cube_data = field.core_data() + cube = iris.cube.Cube(cube_data, + attributes=metadata.attributes, + cell_methods=metadata.cell_methods, + dim_coords_and_dims=metadata.dim_coords_and_dims, + aux_coords_and_dims=metadata.aux_coords_and_dims) # Temporary code to deal with invalid standard names in the # translation table. - if standard_name is not None: - cube.rename(standard_name) - if long_name is not None: - cube.long_name = long_name - if units is not None: + if metadata.standard_name is not None: + cube.rename(metadata.standard_name) + if metadata.long_name is not None: + cube.long_name = metadata.long_name + if metadata.units is not None: # Temporary code to deal with invalid units in the translation # table. try: - cube.units = units + cube.units = metadata.units except ValueError: - msg = 'Ignoring PP invalid units {!r}'.format(units) + msg = 'Ignoring PP invalid units {!r}'.format(metadata.units) warnings.warn(msg) - cube.attributes['invalid_units'] = units - cube.units = iris.unit._UNKNOWN_UNIT_STRING + cube.attributes['invalid_units'] = metadata.units + cube.units = cf_units._UNKNOWN_UNIT_STRING - return cube, factories, references + return cube, metadata.factories, metadata.references + + +def _resolve_factory_references(cube, factories, concrete_reference_targets, + regrid_cache={}): + # Attach the factories for a cube, building them from references. + # Note: the regrid_cache argument lets us share and reuse regridded data + # across multiple result cubes. + for factory in factories: + try: + args = _dereference_args(factory, concrete_reference_targets, + regrid_cache, cube) + except _ReferenceError as e: + msg = 'Unable to create instance of {factory}. ' + str(e) + factory_name = factory.factory_class.__name__ + warnings.warn(msg.format(factory=factory_name)) + else: + aux_factory = factory.factory_class(*args) + cube.add_aux_factory(aux_factory) -def load_cubes(filenames, user_callback, loader): +def _load_pairs_from_fields_and_filenames(fields_and_filenames, converter, + user_callback_wrapper=None): + # The underlying mechanism for the public 'load_pairs_from_fields' and + # 'load_cubes'. + # Slightly more complicated than 'load_pairs_from_fields', only because it + # needs a filename associated with each field to support the load callback. concrete_reference_targets = {} results_needing_reference = [] + for field, filename in fields_and_filenames: + # Convert the field to a Cube, passing down the 'converter' function. + cube, factories, references = _make_cube(field, converter) + + # Post modify the new cube with a user-callback. + # This is an ordinary Iris load callback, so it takes the filename. + cube = iris.io.run_callback(user_callback_wrapper, + cube, field, filename) + # Callback mechanism may return None, which must not be yielded. + if cube is None: + continue + + # Cross referencing. + for reference in references: + name = reference.name + # Register this cube as a source cube for the named reference. + target = concrete_reference_targets.get(name) + if target is None: + target = ConcreteReferenceTarget(name, reference.transform) + concrete_reference_targets[name] = target + target.add_cube(cube) + + if factories: + results_needing_reference.append((cube, factories, field)) + else: + yield (cube, field) + + regrid_cache = {} + for (cube, factories, field) in results_needing_reference: + _resolve_factory_references( + cube, factories, concrete_reference_targets, regrid_cache) + yield (cube, field) + + +def load_pairs_from_fields(fields, converter): + """ + Convert an iterable of fields into an iterable of Cubes using the + provided convertor. + + Args: + + * fields: + An iterable of fields. + + * convertor: + An Iris convertor function, suitable for use with the supplied fields. + See the description in :class:`iris.fileformats.rules.Loader`. - if isinstance(filenames, basestring): + Returns: + An iterable of (:class:`iris.cube.Cube`, field) pairs. + + """ + return _load_pairs_from_fields_and_filenames( + ((field, None) for field in fields), + converter) + + +def load_cubes(filenames, user_callback, loader, filter_function=None): + if isinstance(filenames, six.string_types): filenames = [filenames] - for filename in filenames: - for field in loader.field_generator(filename, **loader.field_generator_kwargs): - # Convert the field to a Cube. - cube, factories, references = _make_cube(field, loader.converter) - - # Run any custom user-provided rules. - if loader.legacy_custom_rules: - loader.legacy_custom_rules.verify(cube, field) - - cube = iris.io.run_callback(user_callback, cube, field, filename) - - if cube is None: - continue - # Cross referencing - for reference in references: - name = reference.name - # Register this cube as a source cube for the named - # reference. - target = concrete_reference_targets.get(name) - if target is None: - target = ConcreteReferenceTarget(name, reference.transform) - concrete_reference_targets[name] = target - target.add_cube(cube) - - if factories: - results_needing_reference.append((cube, factories)) - else: - yield cube + def _generate_all_fields_and_filenames(): + for filename in filenames: + for field in loader.field_generator( + filename, **loader.field_generator_kwargs): + # evaluate field against format specific desired attributes + # load if no format specific desired attributes are violated + if filter_function is None or filter_function(field): + yield (field, filename) + + def loadcubes_user_callback_wrapper(cube, field, filename): + # Run user-provided original callback function. + result = cube + if user_callback is not None: + result = user_callback(cube, field, filename) + return result - regrid_cache = {} - for cube, factories in results_needing_reference: - for factory in factories: - try: - args = _dereference_args(factory, concrete_reference_targets, - regrid_cache, cube) - except _ReferenceError as e: - msg = 'Unable to create instance of {factory}. ' + e.message - factory_name = factory.factory_class.__name__ - warnings.warn(msg.format(filenames=filenames, - factory=factory_name)) - else: - aux_factory = factory.factory_class(*args) - cube.add_aux_factory(aux_factory) + all_fields_and_filenames = _generate_all_fields_and_filenames() + for cube, field in _load_pairs_from_fields_and_filenames( + all_fields_and_filenames, + converter=loader.converter, + user_callback_wrapper=loadcubes_user_callback_wrapper): yield cube diff --git a/lib/iris/fileformats/um/__init__.py b/lib/iris/fileformats/um/__init__.py new file mode 100644 index 0000000000..746087b2f6 --- /dev/null +++ b/lib/iris/fileformats/um/__init__.py @@ -0,0 +1,32 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Provides iris loading support for UM Fieldsfile-like file types, and PP. + +At present, the only UM file types supported are true FieldsFiles and LBCs. +Other types of UM file may fail to load correctly (or at all). + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Publish the FF-replacement features here, and include documentation. +from ._ff_replacement import um_to_pp, load_cubes, load_cubes_32bit_ieee +from ._fast_load import structured_um_loading, FieldCollation +__all__ = ['um_to_pp', 'load_cubes', 'load_cubes_32bit_ieee', + 'structured_um_loading', 'FieldCollation'] diff --git a/lib/iris/fileformats/um/_fast_load.py b/lib/iris/fileformats/um/_fast_load.py new file mode 100644 index 0000000000..bb0bb933d6 --- /dev/null +++ b/lib/iris/fileformats/um/_fast_load.py @@ -0,0 +1,505 @@ +# (C) British Crown Copyright 2016 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Support for "fast" loading of structured UM files in iris load functions, +i.e. :meth:`iris.load` and its associates. + +This provides a context manager to enable structured loading via all the iris +load function variants. It is made public in :mod:`iris.fileformats.um`. + +This works with either PP or Fieldsfiles. +The various existing PP and FF format loaders all call into +:meth:`iris.fileformats.pp._load_cubes_variable_loader`. +When enabled, that function calls private functions in this module, to replace +the 'normal' calls with 'structured' loading. + +At present, there is *no* public low-level fields-to-cube interface, equivalent +to the pp "as_pairs" functions. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +from contextlib import contextmanager +import threading +import os.path + +import numpy as np + +# Be minimal about what we import from iris, to avoid circular imports. +# Below, other parts of iris.fileformats are accessed via deferred imports. +import iris +from iris.coords import DimCoord +from iris.cube import CubeList +from iris.exceptions import TranslationError +from iris.fileformats.um._fast_load_structured_fields import \ + BasicFieldCollation, group_structured_fields + +# Strings to identify the PP and FF file format handler specs. +_FF_SPEC_NAME = 'UM Fieldsfile' +_PP_SPEC_NAME = 'UM Post Processing file' + + +class FieldCollation(BasicFieldCollation): + # This class specialises the BasicFieldCollation by adding the file-index + # and file-path concepts. + # This preserves the more abstract scope of the original 'FieldCollation' + # class, now renamed 'BasicFieldCollation'. + + def __init__(self, fields, filepath): + """ + Args: + + * fields (iterable of :class:`iris.fileformats.pp.PPField`): + The fields in the collation. + + * filepath (string): + The path of the file the collation is loaded from. + + """ + super(FieldCollation, self).__init__(fields) + self._load_filepath = filepath + + @property + def data_filepath(self): + return self._load_filepath + + @property + def data_field_indices(self): + """ + Field indices of the contained PPFields in the input file. + + This records the original file location of the individual data fields + contained, within the input datafile. + + Returns: + An integer array of shape `self.vector_dims_shape`. + + """ + # Get shape : N.B. this calculates (and caches) the structure. + vector_dims_shape = self.vector_dims_shape + # Get index-in-file of each contained field. + indices = np.array([field._index_in_structured_load_file + for field in self._fields], + dtype=np.int64) + return indices.reshape(vector_dims_shape) + + +def _basic_load_function(filename, pp_filter=None, **kwargs): + # The low-level 'fields from filename' loader. + # + # This is the 'loader.generator' in the control structure passed to the + # generic rules code, :meth:`iris.fileformats.rules.load_cubes`. + # + # As called by generic rules code, this replaces pp.load (and the like). + # It yields a sequence of "fields", but in this case the 'fields' are + # :class:`iris.fileformats.um._fast_load_structured_fields.FieldCollation` + # objects. + # + # NOTE: so, a FieldCollation is passed as the 'field' in user callbacks. + # + # Also in our case, we need to support the basic single-field filtering + # operation that speeds up phenomenon selection. + # Therefore, the actual loader will pass this as the 'pp_filter' keyword, + # when it is present. + # Additional load keywords are 'passed on' to the lower-level function. + + # Helper function to select the correct fields loader call. + def _select_raw_fields_loader(fname): + # Return the PPfield loading function for a file name. + # + # This decides whether the underlying file is an FF or PP file. + # Because it would be too awkward to modify the whole iris loading + # callchain to "pass down" the file format, this function instead + # 'recreates' that information by calling the format picker again. + # NOTE: this may be inefficient, especially for web resources. + from iris.fileformats import FORMAT_AGENT + from iris.fileformats.pp import load as pp_load + from iris.fileformats.um import um_to_pp + with open(fname, 'rb') as fh: + spec = FORMAT_AGENT.get_spec(os.path.basename(fname), fh) + if spec.name.startswith(_FF_SPEC_NAME): + loader = um_to_pp + elif spec.name.startswith(_PP_SPEC_NAME): + loader = pp_load + else: + emsg = 'Require {!r} to be a structured FieldsFile or a PP file.' + raise ValueError(emsg.format(fname)) + return loader + + loader = _select_raw_fields_loader(filename) + + def iter_fields_decorated_with_load_indices(fields_iter): + for i_field, field in enumerate(fields_iter): + field._index_in_structured_load_file = i_field + yield field + + fields = iter_fields_decorated_with_load_indices( + field + for field in loader(filename, **kwargs) + if pp_filter is None or pp_filter(field)) + + return group_structured_fields(fields, + collation_class=FieldCollation, + filepath=filename) + + +# Define the preferred order of candidate dimension coordinates, as used by +# _convert_collation. +_HINT_COORDS = ['time', 'forecast_reference_time', 'model_level_number'] +_HINTS = {name: i for i, name in zip(range(len(_HINT_COORDS)), _HINT_COORDS)} + + +def _convert_collation(collation): + """ + Converts a FieldCollation into the corresponding items of Cube + metadata. + + Args: + + * collation: + A FieldCollation object. + + Returns: + A :class:`iris.fileformats.rules.ConversionMetadata` object. + + .. note: + This is the 'loader.converter', in the control structure passed to the + generic rules code, :meth:`iris.fileformats.rules.load_cubes`. + + """ + from iris.fileformats.rules import ConversionMetadata + from iris.fileformats.pp_load_rules import \ + (_convert_time_coords, + _convert_vertical_coords, + _convert_scalar_realization_coords, + _convert_scalar_pseudo_level_coords, + _all_other_rules) + + # For all the scalar conversions, all fields in the collation will + # give the same result, so the choice is arbitrary. + field = collation.fields[0] + + # Call "all other" rules. + (references, standard_name, long_name, units, attributes, cell_methods, + dim_coords_and_dims, aux_coords_and_dims) = _all_other_rules(field) + + # Adjust any dimension bindings to account for the extra leading + # dimensions added by the collation. + if collation.vector_dims_shape: + def _adjust_dims(coords_and_dims, n_dims): + def adjust(dims): + if dims is not None: + dims += n_dims + return dims + return [(coord, adjust(dims)) for coord, dims in coords_and_dims] + + n_collation_dims = len(collation.vector_dims_shape) + dim_coords_and_dims = _adjust_dims(dim_coords_and_dims, + n_collation_dims) + aux_coords_and_dims = _adjust_dims(aux_coords_and_dims, + n_collation_dims) + + # Dimensions to which we've already assigned dimension coordinates. + dim_coord_dims = set() + + # Helper call to choose which coords are dimensions and which auxiliary. + def _bind_coords(coords_and_dims, dim_coord_dims, dim_coords_and_dims, + aux_coords_and_dims): + def key_func(item): + return _HINTS.get(item[0].name(), len(_HINTS)) + # Target the first DimCoord for a dimension at dim_coords, + # and target everything else at aux_coords. + for coord, dims in sorted(coords_and_dims, key=key_func): + if (isinstance(coord, DimCoord) and dims is not None and + len(dims) == 1 and dims[0] not in dim_coord_dims): + dim_coords_and_dims.append((coord, dims)) + dim_coord_dims.add(dims[0]) + else: + aux_coords_and_dims.append((coord, dims)) + + # Call "time" rules. + # + # For "normal" (non-cross-sectional) time values. + vector_headers = collation.element_arrays_and_dims + # If the collation doesn't define a vector of values for a + # particular header then it must be constant over all fields in the + # collation. In which case it's safe to get the value from any field. + t1, t1_dims = vector_headers.get('t1', (field.t1, ())) + t2, t2_dims = vector_headers.get('t2', (field.t2, ())) + lbft, lbft_dims = vector_headers.get('lbft', (field.lbft, ())) + coords_and_dims = _convert_time_coords(field.lbcode, field.lbtim, + field.time_unit('hours'), + t1, t2, lbft, + t1_dims, t2_dims, lbft_dims) + # Bind resulting coordinates to dimensions, where suitable. + _bind_coords(coords_and_dims, dim_coord_dims, dim_coords_and_dims, + aux_coords_and_dims) + + # Call "vertical" rules. + # + # "Normal" (non-cross-sectional) vertical levels + blev, blev_dims = vector_headers.get('blev', (field.blev, ())) + lblev, lblev_dims = vector_headers.get('lblev', (field.lblev, ())) + bhlev, bhlev_dims = vector_headers.get('bhlev', (field.bhlev, ())) + bhrlev, bhrlev_dims = vector_headers.get('bhrlev', (field.bhrlev, ())) + brsvd1, brsvd1_dims = vector_headers.get('brsvd1', (field.brsvd[0], ())) + brsvd2, brsvd2_dims = vector_headers.get('brsvd2', (field.brsvd[1], ())) + brlev, brlev_dims = vector_headers.get('brlev', (field.brlev, ())) + # Find all the non-trivial dimension values + dims = set(filter(None, [blev_dims, lblev_dims, bhlev_dims, bhrlev_dims, + brsvd1_dims, brsvd2_dims, brlev_dims])) + if len(dims) > 1: + raise TranslationError('Unsupported multiple values for vertical ' + 'dimension.') + if dims: + v_dims = dims.pop() + if len(v_dims) > 1: + raise TranslationError('Unsupported multi-dimension vertical ' + 'headers.') + else: + v_dims = () + coords_and_dims, factories = _convert_vertical_coords(field.lbcode, + field.lbvc, + blev, lblev, + field.stash, + bhlev, bhrlev, + brsvd1, brsvd2, + brlev, v_dims) + # Bind resulting coordinates to dimensions, where suitable. + _bind_coords(coords_and_dims, dim_coord_dims, dim_coords_and_dims, + aux_coords_and_dims) + + # Realization (aka ensemble) (--> scalar coordinates) + aux_coords_and_dims.extend(_convert_scalar_realization_coords( + lbrsvd4=field.lbrsvd[3])) + + # Pseudo-level coordinate (--> scalar coordinates) + aux_coords_and_dims.extend(_convert_scalar_pseudo_level_coords( + lbuser5=field.lbuser[4])) + + return ConversionMetadata(factories, references, standard_name, long_name, + units, attributes, cell_methods, + dim_coords_and_dims, aux_coords_and_dims) + + +def _combine_structured_cubes(cubes): + # Combine structured cubes from different sourcefiles, in the style of + # merge/concatenate. + # + # Because standard Cube.merge employed in loading can't do this. + if STRUCTURED_LOAD_CONTROLS.structured_load_is_raw: + # Cross-file concatenate is disabled, during a "load_raw" call. + result = cubes + else: + result = iter(CubeList(cubes).concatenate()) + return result + + +class StructuredLoadFlags(threading.local): + # A thread-safe object to control structured loading operations. + # The object properties are the control flags. + # + # Inheriting from 'threading.local' provides a *separate* set of the + # object properties for each thread. + def __init__(self): + # Control whether iris load functions do structured loads. + self.loads_use_structured = False + # Control whether structured load 'combine' is enabled. + self.structured_load_is_raw = False + + @contextmanager + def context(self, + loads_use_structured=None, + structured_load_is_raw=None): + # Snapshot current states, for restoration afterwards. + old_structured = self.loads_use_structured + old_raw_load = self.structured_load_is_raw + try: + # Set flags for duration, as requested. + if loads_use_structured is not None: + self.loads_use_structured = loads_use_structured + if structured_load_is_raw is not None: + self.structured_load_is_raw = structured_load_is_raw + # Yield to caller operation. + yield + finally: + # Restore entry state of flags. + self.loads_use_structured = old_structured + self.structured_load_is_raw = old_raw_load + + +# A singleton structured-load-control object. +# Used in :meth:`iris.fileformats.pp._load_cubes_variable_loader`. +STRUCTURED_LOAD_CONTROLS = StructuredLoadFlags() + + +@contextmanager +def structured_um_loading(): + """ + Load cubes from structured UM Fieldsfile and PP files. + + "Structured" loading is a streamlined, fast load operation, to be used + **only** on fieldsfiles or PP files whose fields repeat regularly over + the same vertical levels and times (see full details below). + + This method is a context manager which enables an alternative loading + mechanism for 'structured' UM files, providing much faster load times. + Within the scope of the context manager, this affects all standard Iris + load functions (:func:`~iris.load`, :func:`~iris.load_cube`, + :func:`~iris.load_cubes` and :func:`~iris.load_raw`), when loading from UM + format files (PP or fieldsfiles). + + For example: + + >>> import iris + >>> filepath = iris.sample_data_path('uk_hires.pp') + >>> from iris.fileformats.um import structured_um_loading + >>> with structured_um_loading(): + ... cube = iris.load_cube(filepath, 'air_potential_temperature') + ... + >>> cube + + + The results from this are normally equivalent to those generated by + :func:`iris.load`, but the operation is substantially faster for input + which is structured. + + For calls other than :meth:`~iris.load_raw`, the resulting cubes are + concatenated over all the input files, so there is normally just one + output cube per phenomenon. + + However, actual loaded results are somewhat different from non-structured + loads in many cases, and in a variety of ways. Most commonly, dimension + ordering and the choice of dimension coordinates are often different. + + Use of load callbacks: + + When a user callback function is used with structured-loading, it is + called in a somewhat different way than in a 'normal' load : + The callback is called once for each basic *structured* cube loaded, + which is normally the whole of one phenomenon from a single input file. + In particular, the callback's "field" argument is a + :class:`~iris.fileformats.um.FieldCollation`, from which "field.fields" + gives a *list* of PPFields from which that cube was built, and the + properties "field.load_filepath" and "field.load_file_indices" + reference the original file locations of the cube data. + The code required is therefore different from a 'normal' callback. + For an example of this, see `this example in the Iris test code + `_. + + Notes on applicability: + + For results to be **correct and reliable**, the input files must + conform to the following requirements : + + * the file must contain fields for all possible combinations of the + vertical levels and time points found in the file. + + * the fields must occur in a regular repeating order within the file, + within the fields of each phenomenon. + + For example: a sequence of fields for NV vertical levels, repeated + for NP different forecast periods, repeated for NT different + forecast times. + + * all other metadata must be identical across all fields of the same + phenomenon. + + Each group of fields with the same values of LBUSER4, LBUSER7 and + LBPROC is identified as a separate phenomenon: These groups are + processed independently and returned as separate result cubes. + The need for a regular sequence of fields applies separately to the + fields of each phenomenon, such that different phenomena may have + different field structures, and can be interleaved in any way at all. + + .. note:: + + At present, fields with different values of 'LBUSER5' + (pseudo-level) are *also* treated internally as different + phenomena, yielding a raw cube per level. + The effects of this are not normally noticed, as the resulting + multiple raw cubes merge together again in a 'normal' load. + However, it is not an ideal solution as operation is less + efficient (in particular, slower) : it is done to avoid a + limitation in the underlying code which would otherwise load data + on pseudo-levels incorrectly. In future, this may be corrected. + + Known current shortcomings: + + * orography fields may be returned with extra dimensions, e.g. time, + where multiple fields exist in an input file. + + * if some input files contain a *single* coordinate value while others + contain *multiple* values, these will not be merged into a single + cube over all input files : Instead, the single- and multiple-valued + sets will typically produce two separate cubes with overlapping + coordinates. + + * this can be worked around by loading files individually, or with + :meth:`~iris.load_raw`, and merging/concatenating explicitly. + + .. note:: + + The resulting time-related coordinates ('time', 'forecast_time' and + 'forecast_period') may be mapped to shared cube dimensions and in some + cases can also be multidimensional. However, the vertical level + information *must* have a simple one-dimensional structure, independent + of the time points, otherwise an error will be raised. + + .. note:: + + Where input data does *not* have a fully regular arrangement, the + corresponding result cube will have a single anonymous extra dimension + which indexes over all the input fields. + + This can happen if, for example, some fields are missing; or have + slightly different metadata; or appear out of order in the file. + + .. warning:: + + Restrictions and limitations: + + Any non-regular metadata variation in the input should be strictly + avoided, as not all irregularities are detected, which can cause + erroneous results. + + Various field header words which can in some cases vary are assumed to + have a constant value throughout a given phenomenon. This is **not** + checked, and can lead to erroneous results if it is not the case. + Header elements of potential concern include LBTIM, LBCODE, LBVC and + LBRSVD4 (ensemble number). + + """ + with STRUCTURED_LOAD_CONTROLS.context(loads_use_structured=True): + yield + + +@contextmanager +def _raw_structured_loading(): + """ + Private context manager called by :func:`iris.load_raw` to prevent + structured loading from concatenating its result cubes in that case. + + """ + with STRUCTURED_LOAD_CONTROLS.context(structured_load_is_raw=True): + yield diff --git a/lib/iris/fileformats/um/_fast_load_structured_fields.py b/lib/iris/fileformats/um/_fast_load_structured_fields.py new file mode 100644 index 0000000000..60546cc0d8 --- /dev/null +++ b/lib/iris/fileformats/um/_fast_load_structured_fields.py @@ -0,0 +1,309 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Code for fast loading of structured UM data. + +This module defines which pp-field elements take part in structured loading, +and provides creation of :class:`BasicFieldCollation` objects from lists of +:class:`iris.fileformats.pp.PPField`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import itertools + +import cftime +import numpy as np + +from iris._lazy_data import as_lazy_data, multidim_lazy_stack +from iris.fileformats.um._optimal_array_structuring import \ + optimal_array_structure + + +class BasicFieldCollation(object): + """ + An object representing a group of UM fields with array structure that can + be vectorized into a single cube. + + For example: + + Suppose we have a set of 28 fields repeating over 7 vertical levels for + each of 4 different data times. If a BasicFieldCollation is created to + contain these, it can identify that this is a 4*7 regular array structure. + + This BasicFieldCollation will then have the following properties: + + * within 'element_arrays_and_dims' : + Element 'blev' have the array shape (7,) and dims of (1,). + Elements 't1' and 't2' have shape (4,) and dims (0,). + The other elements (lbft, lbrsvd4 and lbuser5) all have scalar array + values and dims=None. + + .. note:: + + If no array structure is found, the element values are all + either scalar or full-length 1-D vectors. + + """ + def __init__(self, fields): + """ + Args: + + * fields (iterable of :class:`iris.fileformats.pp.PPField`): + The fields in the collation. + + """ + self._fields = tuple(fields) + self._data_cache = None + assert len(self.fields) > 0 + self._structure_calculated = False + self._vector_dims_shape = None + self._primary_dimension_elements = None + self._element_arrays_and_dims = None + + @property + def fields(self): + return self._fields + + @property + def data(self): + if not self._structure_calculated: + self._calculate_structure() + if self._data_cache is None: + stack = np.empty(self.vector_dims_shape, 'object') + for nd_index, field in zip(np.ndindex(self.vector_dims_shape), + self.fields): + stack[nd_index] = as_lazy_data(field._data) + self._data_cache = multidim_lazy_stack(stack) + return self._data_cache + + def core_data(self): + return self.data + + @property + def realised_dtype(self): + return np.result_type(*[field.realised_dtype + for field in self._fields]) + + @property + def data_proxy(self): + return self.data + + @property + def bmdi(self): + bmdis = set([f.bmdi for f in self.fields]) + if len(bmdis) != 1: + raise ValueError('Multiple bmdi values defined in FieldCollection') + return bmdis.pop() + + @property + def vector_dims_shape(self): + """The shape of the array structure.""" + if not self._structure_calculated: + self._calculate_structure() + return self._vector_dims_shape + + @property + def _UNUSED_primary_dimension_elements(self): + """A set of names of the elements which are array dimensions.""" + if not self._structure_calculated: + self._calculate_structure() + return self._primary_dimension_elements + + @property + def element_arrays_and_dims(self): + """ + Value arrays for vector metadata elements. + + A dictionary mapping element_name: (value_array, dims). + + The arrays are reduced to their minimum dimensions. A scalar array + has an associated 'dims' of None (instead of an empty tuple). + + """ + if not self._structure_calculated: + self._calculate_structure() + return self._element_arrays_and_dims + + def _field_vector_element_arrays(self): + """Define the field components used in the structure analysis.""" + # Define functions to make t1 and t2 values as date-time tuples. + # These depend on header version (PPField2 has no seconds values). + def t1_fn(fld): + return (fld.lbyr, fld.lbmon, fld.lbdat, fld.lbhr, fld.lbmin, + getattr(fld, 'lbsec', 0)) + + def t2_fn(fld): + return (fld.lbyrd, fld.lbmond, fld.lbdatd, fld.lbhrd, fld.lbmind, + getattr(fld, 'lbsecd', 0)) + + # Return a list of (name, array) for the vectorizable elements. + component_arrays = [ + ('t1', np.array([t1_fn(fld) for fld in self.fields])), + ('t2', np.array([t2_fn(fld) for fld in self.fields])), + ('lbft', np.array([fld.lbft for fld in self.fields])), + ('blev', np.array([fld.blev for fld in self.fields])), + ('lblev', np.array([fld.lblev for fld in self.fields])), + ('bhlev', np.array([fld.bhlev for fld in self.fields])), + ('bhrlev', np.array([fld.bhrlev for fld in self.fields])), + ('brsvd1', np.array([fld.brsvd[0] for fld in self.fields])), + ('brsvd2', np.array([fld.brsvd[1] for fld in self.fields])), + ('brlev', np.array([fld.brlev for fld in self.fields])) + ] + return component_arrays + + # Static factors for the _time_comparable_int routine (seconds per period). + _TIME_ELEMENT_MULTIPLIERS = np.cumprod([1, 60, 60, 24, 31, 12])[::-1] + + def _time_comparable_int(self, yr, mon, dat, hr, min, sec): + """ + Return a single unique number representing a date-time tuple. + + This calculation takes no account of the time field's real calendar, + instead giving every month 31 days, which preserves the required + time ordering. + + """ + elements = np.array((yr, mon, dat, hr, min, sec)) + return np.sum(elements * self._TIME_ELEMENT_MULTIPLIERS) + + def _calculate_structure(self): + # Make value arrays for the vectorisable field elements. + element_definitions = self._field_vector_element_arrays() + + # Identify the vertical elements and payload. + blev_array = dict(element_definitions).get('blev') + vertical_elements = ('lblev', 'bhlev', 'bhrlev', + 'brsvd1', 'brsvd2', 'brlev') + + # Make an ordering copy. + ordering_definitions = element_definitions[:] + # Replace time value tuples with integers and bind the vertical + # elements to the (expected) primary vertical element "blev". + for index, (name, array) in enumerate(ordering_definitions): + if name in ('t1', 't2'): + array = np.array( + [self._time_comparable_int(*tuple(val)) for val in array]) + ordering_definitions[index] = (name, array) + if name in vertical_elements and blev_array is not None: + ordering_definitions[index] = (name, blev_array) + + # Perform the main analysis: get vector dimensions, elements, arrays. + dims_shape, primary_elements, vector_element_arrays_and_dims = \ + optimal_array_structure(ordering_definitions, + element_definitions) + + # Replace time tuples in the result with real datetime-like values. + # N.B. so we *don't* do this on the whole (expanded) input arrays. + for name in ('t1', 't2'): + if name in vector_element_arrays_and_dims: + arr, dims = vector_element_arrays_and_dims[name] + arr_shape = arr.shape[:-1] + extra_length = arr.shape[-1] + # Flatten out the array apart from the last dimension, + # convert to cftime objects, then reshape back. + arr = np.array([cftime.datetime(*args) + for args in arr.reshape(-1, extra_length)] + ).reshape(arr_shape) + vector_element_arrays_and_dims[name] = (arr, dims) + + # Write the private cache values, exposed as public properties. + self._vector_dims_shape = dims_shape + self._primary_dimension_elements = primary_elements + self._element_arrays_and_dims = vector_element_arrays_and_dims + # Do all this only once. + self._structure_calculated = True + + +def _um_collation_key_function(field): + """ + Standard collation key definition for fast structured field loading. + + The elements used here are the minimum sufficient to define the + 'phenomenon', as described for :meth:`group_structured_fields`. + + """ + return (field.lbuser[3], # stashcode first + field.lbproc, # then stats processing + field.lbuser[6], # then model + field.lbuser[4] # then pseudo-level : this one is a KLUDGE. + ) + # NOTE: including pseudo-level here makes it treat different pseudo-levels + # as different phenomena. These will later be merged in the "ordinary" + # post-load merge. + # The current structured-load code fails to handle multiple pseudo-levels + # correctly: because pseudo-level is not on in its list of "things that may + # vary within a phenomenon", it will create a scalar pseudo-level + # coordinate when it should have been a vector of values. + # This kludge fixes that error, but it is inefficient because it bypasses + # the structured load, producing n-levels times more 'raw' cubes. + # It will also fail if any phenomenon occurs with multiple 'normal' levels + # (i.e. lblev) *and* pseudo-levels (lbuser[4]). + # TODO: it should be fairly easy to do this properly -- i.e. create a + # vector pseudo-level coordinate directly in the structured load analysis. + + +def group_structured_fields(field_iterator, + collation_class=BasicFieldCollation, + **collation_kwargs): + """ + Collect structured fields into identified groups whose fields can be + combined to form a single cube. + + Args: + + * field_iterator (iterator of :class:`iris.fileformats.pp.PPField`): + A source of PP or FF fields. N.B. order is significant. + + Kwargs: + + * collation_class (class): + Type of collation wrapper to create from each group of fields. + * collation_kwargs (dict): + Additional constructor keywords for collation creation. + + The function sorts and collates on phenomenon-relevant metadata only, + defined as the field components: 'lbuser[3]' (stash), 'lbproc' (statistic), + 'lbuser[6]' (model). + Each distinct combination of these defines a specific phenomenon (or + statistical aggregation of one), and those fields appear as a single + iteration result. + + Implicitly, within each result group, *all* other metadata components + should be either: + + * the same for all fields, + * completely irrelevant, or + * used by a vectorised rule function (such as + :func:`iris.fileformats.pp_load_rules._convert_time_coords`). + + Returns: + A generator of 'collation_class' objects, each of which contains a + single collated group from the input fields. + + .. note:: + + At present, fields with different values of 'lbuser[4]' (pseudo-level) + are *also* treated as different phenomena. This is a temporary fix, + standing in place for a more correct handling of pseudo-levels. + + """ + _fields = sorted(field_iterator, key=_um_collation_key_function) + for _, fields in itertools.groupby(_fields, _um_collation_key_function): + yield collation_class(tuple(fields), **collation_kwargs) diff --git a/lib/iris/fileformats/um/_ff_replacement.py b/lib/iris/fileformats/um/_ff_replacement.py new file mode 100644 index 0000000000..9f379d097b --- /dev/null +++ b/lib/iris/fileformats/um/_ff_replacement.py @@ -0,0 +1,108 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Support for UM "fieldsfile-like" files. + +At present, the only UM file types supported are true FieldsFiles and LBCs. +Other types of UM file may fail to load correctly (or at all). + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +from iris.fileformats._ff import FF2PP +from iris.fileformats.pp import _load_cubes_variable_loader + + +def um_to_pp(filename, read_data=False, word_depth=None): + """ + Extract individual PPFields from within a UM Fieldsfile-like file. + + Returns an iterator over the fields contained within the FieldsFile, + returned as :class:`iris.fileformats.pp.PPField` instances. + + Args: + + * filename (string): + Specify the name of the FieldsFile. + + Kwargs: + + * read_data (boolean): + Specify whether to read the associated PPField data within + the FieldsFile. Default value is False. + + Returns: + Iteration of :class:`iris.fileformats.pp.PPField`\s. + + For example:: + + >>> for field in um.um_to_pp(filename): + ... print(field) + + """ + if word_depth is None: + ff2pp = FF2PP(filename, read_data=read_data) + else: + ff2pp = FF2PP(filename, read_data=read_data, + word_depth=word_depth) + + # Note: unlike the original wrapped case, we will return an actual + # iterator, rather than an object that can provide an iterator. + return iter(ff2pp) + + +def load_cubes(filenames, callback, constraints=None, + _loader_kwargs=None): + """ + Loads cubes from filenames of UM fieldsfile-like files. + + Args: + + * filenames - list of filenames to load + + Kwargs: + + * callback - a function which can be passed on to + :func:`iris.io.run_callback` + + .. note:: + + The resultant cubes may not be in the order that they are in the + file (order is not preserved when there is a field with + orography references). + + """ + return _load_cubes_variable_loader( + filenames, callback, FF2PP, constraints=constraints, + loading_function_kwargs=_loader_kwargs) + + +def load_cubes_32bit_ieee(filenames, callback, constraints=None): + """ + Loads cubes from filenames of 32bit ieee converted UM fieldsfile-like + files. + + .. seealso:: + + :func:`load_cubes` for keyword details + + """ + return load_cubes(filenames, callback, constraints=constraints, + _loader_kwargs={'word_depth': 4}) diff --git a/lib/iris/fileformats/um/_optimal_array_structuring.py b/lib/iris/fileformats/um/_optimal_array_structuring.py new file mode 100644 index 0000000000..d0dd829355 --- /dev/null +++ b/lib/iris/fileformats/um/_optimal_array_structuring.py @@ -0,0 +1,181 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""A module to provide an optimal array structure calculation.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +import itertools + +import numpy as np + +from iris.fileformats._structured_array_identification import \ + GroupStructure + + +def _optimal_dimensioning_structure(structure, element_priorities): + """ + Uses the structure options provided by the + :class:`~iris.fileformats._structured_array_identification.GroupStructure` + to determine the optimal array structure for the :class:`FieldCollation`. + + The optimal structure is that which generates the greatest number of + non-trivial dimensions. If the number of non-trivial dimensions is equal + in more than one structure options then dimension priorities as specified + by `element_priorities` are used to determine optimal structure. + + Args: + + * structure: + A set of structure options, as provided by :class:\ + `~iris.fileformats._structured_array_identification.GroupStructure`. + + * element_priorities: + A dictionary mapping structure element names to their priority as + defined by their input order to :func:`~optimal_array_structure`. + + Returns: + + The determined optimal array structure or an empty list if no structure + options were determined. + + """ + permitted_structures = structure.possible_structures() + if not permitted_structures: + result = [] + else: + result = max(permitted_structures, + key=lambda candidate: ( + len(candidate), + [element_priorities[name] + for (name, struct) in candidate]) + ) + return result + + +def optimal_array_structure(ordering_elements, actual_values_elements=None): + """ + Calculate an optimal array replication structure for a set of vectors. + + Args: + + * ordering_elements (iterable of (name, 1-d array)): + Input element names and value-vectors. Must all be the same length + (but not necessarily type). Must have at least one. + + Kwargs: + + * actual_values_elements (iterable of (name, 1-d array)): + The 'real' values used to construct the result arrays, if different + from 'ordering_elements'. Must contain all the same names (but not + necessarily in the same order). + + The 'ordering_elements' arg contains the pattern used to deduce a + structure. The order of this is significant, in that earlier elements get + priority when associating dimensions with specific elements. + + Returns: + + dims_shape, primary_elements, element_arrays_and_dims, where: + + * 'dims_shape' is the shape of the vector dimensions chosen. + + * 'primary_elements' is a set of dimension names; the names of input + elements that are identified as dimensions. At most one for each + dimension. + + * 'element_arrays_and_dims' is a dictionary [name: (array, dims)], + for all elements that are not dimensionless. Each array is reduced + to the shape of its mapped dimension. + + For example:: + + >>> import iris.fileformats.um._optimal_array_structuring as optdims + >>> elements_structure = [('a', np.array([1, 1, 1, 2, 2, 2])), + ... ('b', np.array([0, 1, 2, 0, 1, 2])), + ... ('c', np.array([11, 12, 13, 14, 15, 16]))] + >>> elements_values = [('a', np.array([10, 10, 10, 12, 12, 12])), + ... ('b', np.array([15, 16, 17, 15, 16, 17])), + ... ('c', np.array([9, 3, 5, 2, 7, 1]))] + >>> dims_shape, dim_names, arrays_and_dims = \ + ... optdims.optimal_array_structure(elements_structure, + ... elements_values) + >>> print dims_shape + (2, 3) + >>> print dim_names + set(['a', 'b']) + >>> print arrays_and_dims + {'a': (array([10, 12]), (0,)), 'c': (array([[9, 3, 5], + [2, 7, 1]]), (0, 1)), 'b': (array([15, 16, 17]), (1,))} + + """ + # Convert the inputs to dicts. + element_ordering_arrays = dict(ordering_elements) + if actual_values_elements is None: + actual_values_elements = element_ordering_arrays + actual_value_arrays = dict(actual_values_elements) + if set(actual_value_arrays.keys()) != set(element_ordering_arrays.keys()): + msg = 'Names in values arrays do not match those in ordering arrays.' + raise ValueError(msg) + + # Define element priorities from ordering, to choose between equally good + # structures, as structure code does not recognise any element ordering. + n_elements = len(ordering_elements) + element_priorities = { + name: n_elements - index + for index, (name, array) in enumerate(ordering_elements)} + + # Calculate the basic fields-group array structure. + base_structure = GroupStructure.from_component_arrays( + element_ordering_arrays) + + # Work out the target cube structure. + target_structure = _optimal_dimensioning_structure(base_structure, + element_priorities) + + # Work out result cube dimensions. + if not target_structure: + # Get the length of an input array (they are all the same). + # Note that no elements map to multiple dimensions. + elements_length = len(ordering_elements[0][1]) + vector_dims_shape = (elements_length,) + else: + vector_dims_shape = tuple( + struct.size for (_, struct) in target_structure) + + # Build arrays of element values mapped onto the vectorised dimensions. + elements_and_dimensions = base_structure.build_arrays( + vector_dims_shape, actual_value_arrays) + + # Filter out the trivial (scalar) ones. + elements_and_dimensions = { + name: (array, dims) + for name, (array, dims) in six.iteritems(elements_and_dimensions) + if len(dims)} + + # Make a list of 'primary' elements; i.e. those in the target structure. + primary_dimension_elements = set( + name for (name, _) in target_structure) + + if vector_dims_shape == (1,): + shape = () + else: + shape = vector_dims_shape + + # Return all the information. + return (shape, primary_dimension_elements, elements_and_dimensions) diff --git a/lib/iris/fileformats/um_cf_map.py b/lib/iris/fileformats/um_cf_map.py index 05f22ac88c..cc568d7ccf 100644 --- a/lib/iris/fileformats/um_cf_map.py +++ b/lib/iris/fileformats/um_cf_map.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2018, Met Office # # This file is part of Iris. # @@ -16,6 +16,19 @@ # along with Iris. If not, see . # # DO NOT EDIT: AUTO-GENERATED +# Created on 01 June 2018 13:06 from +# http://www.metarelate.net/metOcean +# at commit c07efb7ba0442332cbd5514c9d661c4f84a635c6 + +# https://github.com/metarelate/metOcean/commit/c07efb7ba0442332cbd5514c9d661c4f84a635c6 + +""" +Provides UM/CF phenomenon translations. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa from collections import namedtuple @@ -25,11 +38,14 @@ LBFC_TO_CF = { 5: CFName('atmosphere_boundary_layer_thickness', None, 'm'), + 16: CFName('air_temperature', None, 'K'), 23: CFName('soil_temperature', None, 'K'), 27: CFName('air_density', None, 'kg m-3'), 36: CFName('land_area_fraction', None, '1'), 37: CFName('sea_ice_area_fraction', None, '1'), 50: CFName('wind_speed', None, 'm s-1'), + 56: CFName('x_wind', None, 'm s-1'), + 57: CFName('y_wind', None, 'm s-1'), 73: CFName('atmosphere_relative_vorticity', None, 's-1'), 74: CFName('divergence_of_wind', None, 's-1'), 83: CFName('potential_vorticity_of_atmosphere_layer', None, 'Pa-1 s-1'), @@ -84,8 +100,8 @@ 'm01s00i003': CFName('y_wind', None, 'm s-1'), 'm01s00i004': CFName('air_potential_temperature', None, 'K'), 'm01s00i009': CFName('moisture_content_of_soil_layer', None, 'kg m-2'), - 'm01s00i010': CFName('specific_humidity', None, '1'), - 'm01s00i012': CFName('mass_fraction_of_cloud_ice_in_air', None, '1'), + 'm01s00i010': CFName('specific_humidity', None, 'kg kg-1'), + 'm01s00i012': CFName('mass_fraction_of_cloud_ice_in_air', None, 'kg kg-1'), 'm01s00i013': CFName('convective_cloud_area_fraction', None, '1'), 'm01s00i020': CFName('soil_temperature', None, 'K'), 'm01s00i023': CFName('snowfall_amount', None, 'kg m-2'), @@ -110,13 +126,47 @@ 'm01s00i051': CFName('root_depth', None, 'm'), 'm01s00i052': CFName('surface_albedo_assuming_no_snow', None, '1'), 'm01s00i053': CFName('surface_albedo_assuming_deep_snow', None, '1'), + 'm01s00i058': CFName(None, 'tendency_of_atmosphere_mass_content_of_sulfur_dioxide_expressed_as_sulfur_due_to_low_level_emission', 'kg/m2/s'), + 'm01s00i059': CFName(None, 'tendency_of_atmosphere_mass_content_of_dimethyl_sulfide_expressed_as_sulfur_due_to_emission', 'kg/m2/s'), 'm01s00i060': CFName('mass_fraction_of_ozone_in_air', None, '1'), - 'm01s00i101': CFName('mass_fraction_of_sulfur_dioxide_in_air', None, '1'), - 'm01s00i102': CFName('mass_fraction_of_dimethyl_sulfide_in_air', None, '1'), + 'm01s00i095': CFName(None, 'Snow amount on sea ice', 'kg/m^2'), + 'm01s00i101': CFName(None, 'mass_fraction_of_sulfur_dioxide_expressed_as_sulfur_in_air', 'kg/kg'), + 'm01s00i102': CFName(None, 'mass_fraction_of_dimethyl_sulfide_expressed_as_sulfur_in_air', 'kg/kg'), + 'm01s00i103': CFName(None, 'mass_fraction_of_aitken_mode_sulfate_dry_aerosol_expressed_as_sulfur_in_air', 'kg/kg'), + 'm01s00i104': CFName(None, 'mass_fraction_of_accumulation_mode_sulfate_dry_aerosol_expressed_as_sulfur_in_air', 'kg/kg'), + 'm01s00i105': CFName(None, 'mass_fraction_of_dissolved_sulfate_dry_aerosol_expressed_as_sulfur_in_air', 'kg/kg'), + 'm01s00i106': CFName('mass_fraction_of_hydrogen_peroxide_in_air', None, 'kg kg-1'), + 'm01s00i107': CFName(None, 'mass_fraction_of_ammonia_expressed_as_nitrogen_in_air', 'kg/kg'), + 'm01s00i108': CFName(None, 'mass_fraction_of_fresh_black_carbon_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i109': CFName(None, 'mass_fraction_of_aged_black_carbon_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i110': CFName(None, 'mass_fraction_of_cloud_black_carbon_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i111': CFName(None, 'mass_fraction_of_fresh_biomass_burning_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i112': CFName(None, 'mass_fraction_of_aged_biomass_burning_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i113': CFName(None, 'mass_fraction_of_cloud_biomass_burning_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i114': CFName(None, 'mass_fraction_of_fresh_organic_carbon_from_fossil_fuel_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i115': CFName(None, 'mass_fraction_of_aged_organic_carbon_from_fossil_fuel_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i116': CFName(None, 'mass_fraction_of_cloud_organic_carbon_from_fossil_fuel_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i117': CFName(None, 'mass_fraction_of_accumulation_mode_nitrate_dry_aerosol_expressed_as_nitrogen_in_air', 'kg/kg'), + 'm01s00i118': CFName(None, 'mass_fraction_of_dissolved_nitrate_dry_aerosol_expressed_as_nitrogen_in_air', 'kg/kg'), + 'm01s00i121': CFName(None, '3D NATURAL SO2 EMISSIONS', 'kg m-2 s-1'), + 'm01s00i122': CFName(None, 'molecular_concentration_of_hydroxyl_radical_in_air', 'cm-3'), + 'm01s00i123': CFName(None, 'molecular_concentration_of_hydroperoxyl_radical_in_air', 'cm-3'), + 'm01s00i124': CFName('mass_fraction_of_hydrogen_peroxide_in_air', None, 'kg kg-1'), + 'm01s00i125': CFName('mass_fraction_of_ozone_in_air', None, 'kg kg-1'), + 'm01s00i126': CFName(None, 'tendency_of_atmosphere_mass_content_of_sulfur_dioxide_expressed_as_sulfur_due_to_high_level_emission', 'kg/m2/s'), + 'm01s00i127': CFName(None, 'tendency_of_atmosphere_mass_content_of_ammonia_expressed_as_nitrogen_due_to_emission', 'kg/m2/s'), + 'm01s00i128': CFName(None, 'tendency_of_atmosphere_mass_content_of_black_carbon_dry_aerosol_due_to_low_level_emission', 'kg/m2/s'), + 'm01s00i129': CFName(None, 'tendency_of_atmosphere_mass_content_of_black_carbon_dry_aerosol_due_to_high_level_emission', 'kg/m2/s'), + 'm01s00i130': CFName(None, 'tendency_of_atmosphere_mass_content_of_biomass_burning_dry_aerosol_due_to_low_level_emission', 'kg/m2/s'), + 'm01s00i131': CFName(None, 'tendency_of_atmosphere_mass_content_of_biomass_burning_dry_aerosol_due_to_high_level_emission', 'kg/m2/s'), + 'm01s00i132': CFName('mole_concentration_of_dimethyl_sulfide_in_sea_water', None, 'nanomole/l'), + 'm01s00i134': CFName(None, 'tendency_of_atmosphere_mass_content_of_organic_carbon_from_fossil_fuel_dry_aerosol_due_to_low_level_emission', 'kg/m2/s'), + 'm01s00i135': CFName(None, 'tendency_of_atmosphere_mass_content_of_organic_carbon_from_fossil_fuel_dry_aerosol_due_to_high_level_emission', 'kg/m2/s'), 'm01s00i150': CFName('upward_air_velocity', None, 'm s-1'), 'm01s00i205': CFName('land_area_fraction', None, '1'), 'm01s00i208': CFName('leaf_area_index', None, '1'), 'm01s00i209': CFName('canopy_height', None, 'm'), + 'm01s00i211': CFName(None, 'Convective cloud amount with anvil', '1'), 'm01s00i214': CFName('mass_fraction_of_unfrozen_water_in_soil_moisture', None, '1'), 'm01s00i215': CFName('mass_fraction_of_frozen_water_in_soil_moisture', None, '1'), 'm01s00i217': CFName('leaf_area_index', None, '1'), @@ -124,21 +174,99 @@ 'm01s00i220': CFName('soil_albedo', None, '1'), 'm01s00i223': CFName('soil_carbon_content', None, 'kg m-2'), 'm01s00i231': CFName('snow_grain_size', None, '1e-6 m'), + 'm01s00i243': CFName(None, 'surface_diffuse_albedo_assuming_no_snow', '1'), + 'm01s00i244': CFName(None, 'surface_diffuse_albedo_of_photosynthetically_active_radiation_assuming_no_snow', '1'), + 'm01s00i245': CFName(None, 'surface_diffuse_albedo_of_near_infra_red_radiation_assuming_no_snow', '1'), 'm01s00i252': CFName('mass_fraction_of_carbon_dioxide_in_air', None, '1'), - 'm01s00i254': CFName('mass_fraction_of_cloud_liquid_water_in_air', None, '1'), + 'm01s00i254': CFName('mass_fraction_of_cloud_liquid_water_in_air', None, 'kg kg-1'), 'm01s00i255': CFName('dimensionless_exner_function', None, '1'), + 'm01s00i265': CFName('cloud_area_fraction_in_atmosphere_layer', None, '1'), + 'm01s00i266': CFName(None, 'cloud_volume_fraction_in_atmosphere_layer', '1'), + 'm01s00i267': CFName(None, 'liquid_cloud_volume_fraction_in_atmosphere_layer', '1'), + 'm01s00i268': CFName(None, 'ice_cloud_volume_fraction_in_atmosphere_layer', '1'), 'm01s00i269': CFName('surface_eastward_sea_water_velocity', None, 'm s-1'), 'm01s00i270': CFName('surface_northward_sea_water_velocity', None, 'm s-1'), + 'm01s00i272': CFName('mass_fraction_of_rain_in_air', None, 'kg kg-1'), + 'm01s00i273': CFName('mass_fraction_of_graupel_in_air', None, 'kg kg-1'), + 'm01s00i351': CFName(None, 'mass_concentration_of_biogenic_nmvoc_in_air', 'kg/kg'), + 'm01s00i352': CFName(None, 'mass_fraction_of_fresh_biomass_burning_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i353': CFName(None, 'mass_fraction_of_aged_biomass_burning_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i354': CFName(None, 'mass_fraction_of_cloud_biomass_burning_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i355': CFName(None, 'mass_fraction_of_fresh_black_carbon_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i356': CFName(None, 'mass_fraction_of_aged_black_carbon_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i357': CFName(None, 'atmosphere_number_concentration_of_film_mode_sea_salt_particles', 'kg/kg'), + 'm01s00i358': CFName(None, 'atmosphere_number_concentration_of_jet_mode_sea_salt_particles', 'kg/kg'), + 'm01s00i359': CFName(None, 'mass_fraction_of_aitken_mode_sulfate_dry_aerosol_in_air_expressed_as_sulfur', 'kg/kg'), + 'm01s00i360': CFName(None, 'mass_fraction_of_accumulation_mode_sulfate_dry_aerosol_in_air_expressed_as_sulfur', 'kg/kg'), + 'm01s00i361': CFName(None, 'mass_fraction_of_dissolved_sulfate_dry_aerosol_in_air_expressed_as_sulfur', 'kg/kg'), + 'm01s00i362': CFName(None, 'mass_fraction_of_dust_ukmo_division_1_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i363': CFName(None, 'mass_fraction_of_dust_ukmo_division_2_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i364': CFName(None, 'mass_fraction_of_dust_ukmo_division_3_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i365': CFName(None, 'mass_fraction_of_dust_ukmo_division_4_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i366': CFName(None, 'mass_fraction_of_dust_ukmo_division_5_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i367': CFName(None, 'mass_fraction_of_dust_ukmo_division_6_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i368': CFName(None, 'mass_fraction_of_fresh_organic_carbon_from_fossil_fuel_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i369': CFName(None, 'mass_fraction_of_aged_organic_carbon_from_fossil_fuel_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i370': CFName(None, 'mass_fraction_of_cloud_organic_carbon_from_fossil_fuel_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i371': CFName(None, 'mass_concentration_of_unspecified_aerosol_in_air', 'kg/kg'), + 'm01s00i388': CFName(None, 'virtual_potential_temperature', 'K'), + 'm01s00i389': CFName('air_density', None, 'kg m-3'), + 'm01s00i391': CFName('humidity_mixing_ratio', None, 'kg kg-1'), + 'm01s00i392': CFName('cloud_liquid_water_mixing_ratio', None, 'kg kg-1'), + 'm01s00i393': CFName('cloud_ice_mixing_ratio', None, 'kg kg-1'), + 'm01s00i394': CFName(None, 'rain_mixing_ratio', 'kg kg-1'), + 'm01s00i395': CFName(None, 'graupel_mixing_ratio', 'kg kg-1'), 'm01s00i406': CFName('dimensionless_exner_function', None, '1'), 'm01s00i407': CFName('air_pressure', None, 'Pa'), 'm01s00i408': CFName('air_pressure', None, 'Pa'), 'm01s00i409': CFName('surface_air_pressure', None, 'Pa'), + 'm01s00i413': CFName(None, 'Sea ice concentration by categories', '1'), + 'm01s00i414': CFName(None, 'Sea ice thickness GBM by categories', 'm'), + 'm01s00i415': CFName('sea_ice_surface_temperature', None, 'K'), + 'm01s00i416': CFName(None, 'Snow thickness on sea ice', 'm'), + 'm01s00i418': CFName('volume_fraction_of_clay_in_soil', None, 'm3 m-3'), + 'm01s00i419': CFName('volume_fraction_of_silt_in_soil', None, 'm3 m-3'), + 'm01s00i420': CFName('volume_fraction_of_sand_in_soil', None, 'm3 m-3'), + 'm01s00i421': CFName(None, 'mass_fraction_of_soil_particles_in_ukmo_division1', 'kg/kg'), + 'm01s00i422': CFName(None, 'mass_fraction_of_soil_particles_in_ukmo_division2', 'kg/kg'), + 'm01s00i423': CFName(None, 'mass_fraction_of_soil_particles_in_ukmo_division3', 'kg/kg'), + 'm01s00i424': CFName(None, 'mass_fraction_of_soil_particles_in_ukmo_division4', 'kg/kg'), + 'm01s00i425': CFName(None, 'mass_fraction_of_soil_particles_in_ukmo_division5', 'kg/kg'), + 'm01s00i426': CFName(None, 'mass_fraction_of_soil_particles_in_ukmo_division6', 'kg/kg'), + 'm01s00i431': CFName(None, 'mass_fraction_of_dust_ukmo_division_1_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i432': CFName(None, 'mass_fraction_of_dust_ukmo_division_2_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i433': CFName(None, 'mass_fraction_of_dust_ukmo_division_3_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i434': CFName(None, 'mass_fraction_of_dust_ukmo_division_4_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i435': CFName(None, 'mass_fraction_of_dust_ukmo_division_5_dry_aerosol_in_air', 'kg/kg'), + 'm01s00i436': CFName(None, 'mass_fraction_of_dust_ukmo_division_6_dry_aerosol_in_air', 'kg/kg'), 'm01s00i505': CFName('land_area_fraction', None, '1'), 'm01s00i506': CFName('surface_temperature', None, 'K'), 'm01s00i507': CFName('surface_temperature', None, 'K'), 'm01s00i508': CFName('surface_temperature', None, 'K'), - 'm01s00i509': CFName('sea_ice_albedo', None, '1'), + 'm01s00i509': CFName(None, 'product_of_sea_ice_albedo_and_sunlit_binary_mask', '1'), + 'm01s00i510': CFName(None, 'product_of_land_albedo_and_sunlit_binary_mask', '1'), 'm01s01i004': CFName('air_temperature', None, 'K'), + 'm01s01i101': CFName(None, 'northward_horizon_angle_from_zenith', 'rad'), + 'm01s01i102': CFName(None, 'northeastward_horizon_angle_from_zenith', 'rad'), + 'm01s01i103': CFName(None, 'eastward_horizon_angle_from_zenith', 'rad'), + 'm01s01i104': CFName(None, 'southeastward_horizon_angle_from_zenith', 'rad'), + 'm01s01i105': CFName(None, 'southward_horizon_angle_from_zenith', 'rad'), + 'm01s01i106': CFName(None, 'southwestward_horizon_angle_from_zenith', 'rad'), + 'm01s01i107': CFName(None, 'westward_horizon_angle_from_zenith', 'rad'), + 'm01s01i108': CFName(None, 'northwestward_horizon_angle_from_zenith', 'rad'), + 'm01s01i109': CFName(None, 'northnortheastward_horizon_angle_from_zenith', 'rad'), + 'm01s01i110': CFName(None, 'eastnortheastward_horizon_angle_from_zenith', 'rad'), + 'm01s01i111': CFName(None, 'eastsoutheastward_horizon_angle_from_zenith', 'rad'), + 'm01s01i112': CFName(None, 'southsoutheastward_horizon_angle_from_zenith', 'rad'), + 'm01s01i113': CFName(None, 'southsouthwestward_horizon_angle_from_zenith', 'rad'), + 'm01s01i114': CFName(None, 'westsouthwestward_horizon_angle_from_zenith', 'rad'), + 'm01s01i115': CFName(None, 'westnorthwestward_horizon_angle_from_zenith', 'rad'), + 'm01s01i116': CFName(None, 'northnorthwestward_horizon_angle_from_zenith', 'rad'), + 'm01s01i181': CFName(None, 'change_over_time_in_air_temperature_due_to_shortwave_heating', 'K'), + 'm01s01i182': CFName(None, 'change_over_time_in_specific_humidity_due_to_shortwave_heating', 'kg kg-1'), + 'm01s01i183': CFName(None, 'change_over_time_in_mass_fraction_of_cloud_liquid_water_in_air_due_to_shortwave_heating', 'kg kg-1'), + 'm01s01i192': CFName(None, 'change_over_time_in_cloud_volume_fraction_in_atmosphere_layer_due_to_shortwave_heating', '1'), + 'm01s01i193': CFName(None, 'change_over_time_in_liquid_water_cloud_volume_fraction_in_atmosphere_layer_due_to_shortwave_heating', '1'), 'm01s01i201': CFName('surface_net_downward_shortwave_flux', None, 'W m-2'), 'm01s01i203': CFName('surface_net_downward_shortwave_flux', None, 'W m-2'), 'm01s01i205': CFName('toa_outgoing_shortwave_flux', None, 'W m-2'), @@ -147,15 +275,47 @@ 'm01s01i209': CFName('toa_outgoing_shortwave_flux_assuming_clear_sky', None, 'W m-2'), 'm01s01i210': CFName('surface_downwelling_shortwave_flux_in_air_assuming_clear_sky', None, 'W m-2'), 'm01s01i211': CFName('surface_upwelling_shortwave_flux_in_air_assuming_clear_sky', None, 'W m-2'), - 'm01s01i232': CFName('tendency_of_air_temperature_due_to_shortwave_heating', None, 'unknown'), - 'm01s01i233': CFName('tendency_of_air_temperature_due_to_shortwave_heating_assuming_clear_sky', None, 'unknown'), + 'm01s01i217': CFName('upwelling_shortwave_flux_in_air', None, 'W m-2'), + 'm01s01i218': CFName('downwelling_shortwave_flux_in_air', None, 'W m-2'), + 'm01s01i219': CFName('upwelling_shortwave_flux_in_air_assuming_clear_sky', None, 'W m-2'), + 'm01s01i220': CFName('downwelling_shortwave_flux_in_air_assuming_clear_sky', None, 'W m-2'), + 'm01s01i221': CFName(None, 'product_of_effective_radius_of_stratiform_cloud_liquid_water_particle_and_stratiform_cloud_liquid_water_area_fraction_and_sunlit_binary_mask', 'um'), + 'm01s01i223': CFName(None, 'product_of_stratiform_cloud_liquid_water_area_fraction_and_sunlit_binary_mask', '1'), + 'm01s01i224': CFName(None, 'product_of_stratiform_cloud_liquid_water_path_and_stratiform_cloud_liquid_water_area_fraction_and_sunlit_binary_mask', 'kg m-2'), + 'm01s01i225': CFName(None, 'product_of_effective_radius_of_convective_cloud_liquid_water_particle_and_convective_cloud_liquid_water_area_fraction_and_sunlit_binary_mask', 'um'), + 'm01s01i226': CFName(None, 'product_of_convective_cloud_liquid_water_area_fraction_and_sunlit_binary_mask', '1'), + 'm01s01i232': CFName('tendency_of_air_temperature_due_to_shortwave_heating', None, 'K s-1'), + 'm01s01i233': CFName('tendency_of_air_temperature_due_to_shortwave_heating_assuming_clear_sky', None, 'K s-1'), 'm01s01i235': CFName('surface_downwelling_shortwave_flux_in_air', None, 'W m-2'), 'm01s01i237': CFName('net_downward_shortwave_flux_in_air', None, 'W m-2'), - 'm01s01i238': CFName('tropopause_upwelling_shortwave_flux', None, 'unknown'), - 'm01s01i242': CFName(None, 'large_scale_cloud_liquid_water_content_of_atmosphere_layer', 'unknown'), + 'm01s01i238': CFName('tropopause_upwelling_shortwave_flux', None, 'W m-2'), + 'm01s01i241': CFName(None, 'product_of_number_concentration_of_stratiform_cloud_liquid_water_particles_and_stratiform_cloud_liquid_water_area_fraction_and_sunlit_binary_mask', 'cm-3'), + 'm01s01i242': CFName(None, 'product_of_stratiform_cloud_liquid_water_content_and_stratiform_cloud_liquid_water_area_fraction_and_sunlit_binary_mask', 'g cm-3'), + 'm01s01i243': CFName(None, 'product_of_mass_concentration_of_sulfate_ion_and_sunlit_binary_mask', 'ug m-3'), + 'm01s01i244': CFName(None, 'sunlit_binary_mask_in_atmosphere_layer_below_cloud_top', '1'), + 'm01s01i245': CFName(None, 'product_of_effective_radius_of_cloud_liquid_water_particle_and_cloud_liquid_water_area_fraction_exposed_to_space_and_sunlit_binary_mask', 'um'), + 'm01s01i246': CFName(None, 'product_of_cloud_liquid_water_area_fraction_exposed_to_space_and_sunlit_binary_mask', '1'), + 'm01s01i247': CFName(None, 'atmosphere_number_concentration_of_film_mode_sea_salt_particles', 'm-3'), + 'm01s01i248': CFName(None, 'atmosphere_number_concentration_of_jet_mode_sea_salt_particles', 'm-3'), + 'm01s01i254': CFName(None, 'product_of_effective_radius_of_warm_cloud_liquid_water_particle_and_warm_cloud_liquid_water_area_fraction_exposed_to_space_and_sunlit_binary_mask', 'um'), + 'm01s01i255': CFName(None, 'product_of_warm_cloud_liquid_water_area_fraction_exposed_to_space_and_sunlit_binary_mask', '1'), + 'm01s01i268': CFName(None, 'surface_direct_beam_albedo_assuming_no_snow', '1'), + 'm01s01i269': CFName(None, 'surface_diffuse_albedo_assuming_no_snow', '1'), + 'm01s01i270': CFName(None, 'scaling_factor_for_surface_diffuse_albedo_of_photosynthetically_active_radiation_assuming_no_snow', '1'), + 'm01s01i271': CFName(None, 'scaling_factor_for_surface_diffuse_albedo_of_near_infra_red_radiation_assuming_no_snow', '1'), + 'm01s01i280': CFName(None, 'product_of_atmosphere_number_content_of_cloud_droplets_and_warm_cloud_area_fraction_and_sunlit_binary_mask', 'm-2'), + 'm01s01i281': CFName(None, 'product_of_warm_cloud_area_fraction_and_sunlit_binary_mask', '1'), + 'm01s01i294': CFName(None, 'surface_mean_slope_angle', 'rad'), + 'm01s01i295': CFName(None, 'orographic_correction_factor_to_surface_direct_downwelling_shortwave_flux', '1'), 'm01s01i410': CFName('surface_downwelling_shortwave_flux_in_air_assuming_clear_sky', None, 'W m-2'), 'm01s01i435': CFName('surface_downwelling_shortwave_flux_in_air', None, 'W m-2'), 'm01s02i004': CFName('air_temperature', None, 'K'), + 'm01s02i101': CFName(None, 'ratio_of_skyview_factor_to_cosine_of_surface_mean_slope_angle', '1'), + 'm01s02i181': CFName(None, 'change_over_time_in_air_temperature_due_to_longwave_heating', 'K'), + 'm01s02i182': CFName(None, 'change_over_time_in_specific_humidity_due_to_longwave_heating', 'kg kg-1'), + 'm01s02i183': CFName(None, 'change_over_time_in_mass_fraction_of_cloud_liquid_water_in_air_due_to_longwave_heating', 'kg kg-1'), + 'm01s02i192': CFName(None, 'change_over_time_in_cloud_volume_fraction_in_atmosphere_layer_due_to_longwave_heating', '1'), + 'm01s02i193': CFName(None, 'change_over_time_in_liquid_water_cloud_volume_fraction_in_atmosphere_layer_due_to_longwave_heating', '1'), 'm01s02i201': CFName('surface_net_downward_longwave_flux', None, 'W m-2'), 'm01s02i203': CFName('surface_net_downward_longwave_flux', None, 'W m-2'), 'm01s02i204': CFName('cloud_area_fraction', None, '1'), @@ -163,20 +323,97 @@ 'm01s02i206': CFName('toa_outgoing_longwave_flux_assuming_clear_sky', None, 'W m-2'), 'm01s02i207': CFName('surface_downwelling_longwave_flux_in_air', None, 'W m-2'), 'm01s02i208': CFName('surface_downwelling_longwave_flux_in_air_assuming_clear_sky', None, 'W m-2'), + 'm01s02i217': CFName('upwelling_longwave_flux_in_air', None, 'W m-2'), + 'm01s02i218': CFName('downwelling_longwave_flux_in_air', None, 'W m-2'), + 'm01s02i219': CFName('upwelling_longwave_flux_in_air_assuming_clear_sky', None, 'W m-2'), + 'm01s02i220': CFName('downwelling_longwave_flux_in_air_assuming_clear_sky', None, 'W m-2'), 'm01s02i232': CFName('tendency_of_air_temperature_due_to_longwave_heating', None, 'K s-1'), - 'm01s02i233': CFName('tendency_of_air_temperature_due_to_longwave_heating_assuming_clear_sky', None, 'unknown'), - 'm01s02i237': CFName('tropopause_net_downward_longwave_flux', None, 'unknown'), - 'm01s02i238': CFName('tropopause_downwelling_longwave_flux', None, 'unknown'), + 'm01s02i233': CFName('tendency_of_air_temperature_due_to_longwave_heating_assuming_clear_sky', None, 'K s-1'), + 'm01s02i237': CFName('tropopause_net_downward_longwave_flux', None, 'W m-2'), + 'm01s02i238': CFName('tropopause_downwelling_longwave_flux', None, 'W m-2'), 'm01s02i260': CFName('mass_fraction_of_ozone_in_air', None, '1'), 'm01s02i261': CFName('cloud_area_fraction_in_atmosphere_layer', None, '1'), - 'm01s03i004': CFName('air_temperature', None, 'm s-1'), + 'm01s02i262': CFName(None, 'product_of_mass_absorption_coefficient_due_to_cloud_and_upwelling_longwave_flux_assuming_clear_sky_and_cloud_area_fraction_in_atmosphere_layer', 'W kg-1'), + 'm01s02i263': CFName(None, 'product_of_upwelling_longwave_flux_assuming_clear_sky_and_cloud_area_fraction_in_atmosphere_layer', 'W m-2'), + 'm01s02i264': CFName(None, 'product_of_mass_absorption_coefficient_due_to_stratiform_cloud_and_upwelling_longwave_flux_assuming_clear_sky_and_stratiform_cloud_area_fraction_in_atmosphere_layer', 'W kg-1'), + 'm01s02i265': CFName(None, 'product_of_upwelling_longwave_flux_assuming_clear_sky_and_stratiform_cloud_area_fraction_in_atmosphere_layer', 'W m-2'), + 'm01s02i266': CFName(None, 'product_of_mass_absorption_coefficient_due_to_convective_cloud_and_upwelling_longwave_flux_assuming_clear_sky_and_convective_cloud_area_fraction_in_atmosphere_layer', 'W kg-1'), + 'm01s02i267': CFName(None, 'product_of_upwelling_longwave_flux_assuming_clear_sky_and_convective_cloud_area_fraction_in_atmosphere_layer', 'W m-2'), + 'm01s02i280': CFName(None, 'model_level_number_at_ozone_tropopause', '1'), + 'm01s02i281': CFName(None, 'ozone_tropopause_altitude', 'm'), + 'm01s02i282': CFName(None, 'model_level_number_at_thermal_tropopause', '1'), + 'm01s02i283': CFName(None, 'thermal_tropopause_altitude', 'm'), + 'm01s02i284': CFName(None, 'atmosphere_optical_thickness_due_to_sulphate_ambient_aerosol', '1'), + 'm01s02i285': CFName('atmosphere_optical_thickness_due_to_dust_ambient_aerosol', None, '1'), + 'm01s02i286': CFName('atmosphere_optical_thickness_due_to_seasalt_ambient_aerosol', None, '1'), + 'm01s02i287': CFName('atmosphere_optical_thickness_due_to_black_carbon_ambient_aerosol', None, '1'), + 'm01s02i288': CFName(None, 'atmosphere_optical_thickness_due_to_biomass_burning_ambient_aerosol', '1'), + 'm01s02i289': CFName(None, 'atmosphere_optical_thickness_due_to_biogenic_aerosol', '1'), + 'm01s02i295': CFName(None, 'atmosphere_optical_thickness_due_to_fossil_fuel_organic_carbon_ambient_aerosol', '1'), + 'm01s02i296': CFName(None, 'atmosphere_optical_thickness_due_to_unspecified_aerosol', '1'), + 'm01s02i297': CFName(None, 'atmosphere_optical_thickness_due_to_ammonium_nitrate_ambient_aerosol', '1'), + 'm01s02i298': CFName(None, 'atmosphere_optical_thickness_due_all_ambient_aerosol', '1'), + 'm01s02i299': CFName('angstrom_exponent_of_ambient_aerosol_in_air', None, '1'), + 'm01s02i300': CFName(None, 'atmosphere_optical_thickness_due_to_soluble_aitken_mode_sulphate_aerosol', '1'), + 'm01s02i301': CFName(None, 'atmosphere_optical_thickness_due_to_soluble_accumulation_mode_sulphate_aerosol', '1'), + 'm01s02i302': CFName(None, 'atmosphere_optical_thickness_due_to_soluble_coarse_mode_sulphate_aerosol', '1'), + 'm01s02i303': CFName(None, 'atmosphere_optical_thickness_due_to_insoluble_aitken_mode_sulphate_aerosol', '1'), + 'm01s02i304': CFName(None, 'atmosphere_optical_thickness_due_to_unsoluble_accumulation_mode_sulphate_aerosol', '1'), + 'm01s02i305': CFName(None, 'atmosphere_optical_thickness_due_to_unsoluble_coarse_mode_sulphate_aerosol', '1'), + 'm01s02i308': CFName('mass_fraction_of_stratiform_cloud_liquid_water_in_air', None, '1'), + 'm01s02i309': CFName('mass_fraction_of_stratiform_cloud_ice_in_air', None, '1'), + 'm01s02i310': CFName('mass_fraction_of_convective_cloud_liquid_water_in_air', None, '1'), + 'm01s02i311': CFName('mass_fraction_of_convective_cloud_ice_in_air', None, '1'), + 'm01s02i312': CFName(None, 'stratiform_cloud_liquid_water_area_fraction_in_atmosphere_layer', '1'), + 'm01s02i313': CFName(None, 'stratiform_cloud_ice_area_fraction_in_atmosphere_layer', '1'), + 'm01s02i314': CFName(None, 'convective_cloud_liquid_water_area_fraction_in_atmosphere_layer', '1'), + 'm01s02i315': CFName(None, 'convective_cloud_ice_area_fraction_in_atmosphere_layer', '1'), + 'm01s02i348': CFName('toa_bidirectional_reflectance', None, '1'), + 'm01s02i351': CFName('equivalent_reflectivity_factor', None, 'dBZ'), + 'm01s02i370': CFName('histogram_of_backscattering_ratio_over_height_above_reference_ellipsoid', None, '1'), + 'm01s02i372': CFName('histogram_of_equivalent_reflectivity_factor_over_height_above_reference_ellipsoid', None, '1'), + 'm01s02i375': CFName('atmosphere_optical_thickness_due_to_stratiform_cloud', None, '1'), + 'm01s02i376': CFName('stratiform_cloud_longwave_emissivity', None, '1'), + 'm01s02i377': CFName('atmosphere_optical_thickness_due_to_convective_cloud', None, '1'), + 'm01s02i378': CFName('convective_cloud_longwave_emissivity', None, '1'), + 'm01s02i380': CFName('effective_radius_of_stratiform_cloud_liquid_water_particle', None, 'm'), + 'm01s02i381': CFName('effective_radius_of_stratiform_cloud_ice_particle', None, 'm'), + 'm01s02i382': CFName('effective_radius_of_stratiform_cloud_rain_particle', None, 'm'), + 'm01s02i383': CFName('effective_radius_of_stratiform_cloud_snow_particle', None, 'm'), + 'm01s02i384': CFName('effective_radius_of_convective_cloud_liquid_water_particle', None, 'm'), + 'm01s02i385': CFName('effective_radius_of_convective_cloud_ice_particle', None, 'm'), + 'm01s02i386': CFName('effective_radius_of_convective_cloud_rain_particle', None, 'm'), + 'm01s02i387': CFName('effective_radius_of_convective_cloud_snow_particle', None, 'm'), + 'm01s02i388': CFName('effective_radius_of_stratiform_cloud_graupel_particle', None, 'm'), + 'm01s02i421': CFName(None, 'atmosphere_optical_thickness_due_to_sulphate_ambient_aerosol', '1'), + 'm01s02i422': CFName('atmosphere_optical_thickness_due_to_dust_ambient_aerosol', None, '1'), + 'm01s02i423': CFName('atmosphere_optical_thickness_due_to_seasalt_ambient_aerosol', None, '1'), + 'm01s02i424': CFName('atmosphere_optical_thickness_due_to_black_carbon_ambient_aerosol', None, '1'), + 'm01s02i425': CFName(None, 'atmosphere_optical_thickness_due_to_biomass_burning_ambient_aerosol', '1'), + 'm01s02i426': CFName(None, 'atmosphere_optical_thickness_due_to_fossil_fuel_organic_carbon_ambient_aerosol', '1'), + 'm01s02i427': CFName(None, 'atmosphere_optical_thickness_due_to_ammonium_nitrate_ambient_aerosol', '1'), + 'm01s03i004': CFName('air_temperature', None, 'K'), 'm01s03i010': CFName('specific_humidity', None, '1'), 'm01s03i025': CFName('atmosphere_boundary_layer_thickness', None, 'm'), + 'm01s03i181': CFName(None, 'change_over_time_in_air_temperature_due_to_boundary_layer_mixing', 'K'), + 'm01s03i182': CFName(None, 'change_over_time_in_specific_humidity_due_to_boundary_layer_mixing', 'kg kg-1'), + 'm01s03i183': CFName(None, 'change_over_time_in_mass_fraction_of_cloud_liquid_water_in_air_due_to_boundary_layer_mixing', 'kg kg-1'), + 'm01s03i184': CFName(None, 'change_over_time_in_mass_fraction_of_cloud_ice_in_air_due_to_boundary_layer_mixing', 'kg kg-1'), + 'm01s03i185': CFName(None, 'change_over_time_in_x_wind_due_to_boundary_layer_mixing', 'm s-1'), + 'm01s03i186': CFName(None, 'change_over_time_in_y_wind_due_to_boundary_layer_mixing', 'm s-1'), + 'm01s03i187': CFName(None, 'change_over_time_in_upward_air_velocity_due_to_boundary_layer_mixing', 'm s-1'), + 'm01s03i192': CFName(None, 'change_over_time_in_cloud_volume_fraction_in_atmosphere_layer_due_to_boundary_layer_mixing', '1'), + 'm01s03i193': CFName(None, 'change_over_time_in_liquid_water_cloud_volume_fraction_in_atmosphere_layer_due_to_boundary_layer_mixing', '1'), + 'm01s03i194': CFName(None, 'change_over_time_in_ice_cloud_volume_fraction_in_atmosphere_layer_due_to_boundary_layer_mixing', '1'), 'm01s03i201': CFName('downward_heat_flux_in_sea_ice', None, 'W m-2'), - 'm01s03i202': CFName('downward_heat_flux_in_soil', None, 'unknown'), + 'm01s03i202': CFName('downward_heat_flux_in_soil', None, 'W m-2'), + 'm01s03i209': CFName('x_wind', None, 'm s-1'), + 'm01s03i210': CFName('y_wind', None, 'm s-1'), + 'm01s03i216': CFName('upward_heat_flux_in_air', None, 'W m-2'), 'm01s03i217': CFName('surface_upward_sensible_heat_flux', None, 'W m-2'), - 'm01s03i219': CFName('surface_downward_eastward_stress', None, 'Pa'), - 'm01s03i220': CFName('surface_downward_northward_stress', None, 'Pa'), + 'm01s03i219': CFName(None, 'atmosphere_downward_eastward_stress', 'Pa'), + 'm01s03i220': CFName(None, 'atmosphere_downward_northward_stress', 'Pa'), + 'm01s03i222': CFName('upward_water_vapor_flux_in_air', None, 'kg m-2 s-1'), 'm01s03i223': CFName('surface_upward_water_flux', None, 'kg m-2 s-1'), 'm01s03i224': CFName('wind_mixing_energy_flux_into_sea_water', None, 'W m-2'), 'm01s03i225': CFName('x_wind', None, 'm s-1'), @@ -184,85 +421,254 @@ 'm01s03i227': CFName('wind_speed', None, 'm s-1'), 'm01s03i228': CFName('surface_upward_sensible_heat_flux', None, 'W m-2'), 'm01s03i230': CFName('wind_speed', None, 'm s-1'), + 'm01s03i231': CFName(None, 'water_sublimation_flux_in_timestep', 'kg m-2'), + 'm01s03i232': CFName(None, 'Evaporation flux from open sea', 'kg/m^2/s'), 'm01s03i234': CFName('surface_upward_latent_heat_flux', None, 'W m-2'), + 'm01s03i235': CFName(None, 'Latent heat flux from sea ice top melt', 'W/m^2'), 'm01s03i236': CFName('air_temperature', None, 'K'), 'm01s03i237': CFName('specific_humidity', None, '1'), 'm01s03i238': CFName('soil_temperature', None, 'K'), 'm01s03i245': CFName('relative_humidity', None, '%'), + 'm01s03i247': CFName('visibility_in_air', None, 'm'), + 'm01s03i248': CFName('fog_area_fraction', None, '1'), 'm01s03i249': CFName('wind_speed', None, 'm s-1'), 'm01s03i250': CFName('dew_point_temperature', None, 'K'), + 'm01s03i256': CFName(None, 'Heat flux through sea ice', 'W/m^2'), + 'm01s03i257': CFName(None, 'Heat flux in sea ice surface melt', 'W/m^2'), 'm01s03i258': CFName('surface_snow_melt_heat_flux', None, 'W m-2'), 'm01s03i261': CFName('gross_primary_productivity_of_carbon', None, 'kg m-2 s-1'), 'm01s03i262': CFName('net_primary_productivity_of_carbon', None, 'kg m-2 s-1'), + 'm01s03i263': CFName('plant_respiration_carbon_flux', None, 'kg m-2 s-1'), + 'm01s03i270': CFName('tendency_of_atmosphere_mass_content_of_sulfur_dioxide_due_to_dry_deposition', None, 'kg m-2 s-1'), + 'm01s03i281': CFName('visibility_in_air', None, 'm'), + 'm01s03i293': CFName('soil_respiration_carbon_flux', None, 'kg m-2 s-1'), 'm01s03i295': CFName(None, 'surface_snow_area_fraction_where_land', '%'), + 'm01s03i296': CFName(None, 'Evaporation from soil surface', 'kg/m^2/s'), + 'm01s03i297': CFName(None, 'Evaporation from canopy', 'kg/m^2/s'), 'm01s03i298': CFName('water_sublimation_flux', None, 'kg m-2 s-1'), + 'm01s03i300': CFName('tendency_of_atmosphere_mass_content_of_ammonia_due_to_dry_deposition', None, 'kg m-2 s-1'), + 'm01s03i304': CFName(None, 'Turbulent mixing height after boundary layer', 'm'), + 'm01s03i305': CFName(None, 'Stable boundary layer indicator', '1'), + 'm01s03i306': CFName(None, 'Stratocumulus over stable boundary layer indicator', '1'), + 'm01s03i307': CFName(None, 'Well-mixed boundary layer indicator', '1'), + 'm01s03i308': CFName(None, 'Decoupled stratocumulus not over cumulus indicator', '1'), + 'm01s03i309': CFName(None, 'Decoupled stratocumulus over cumulus indicator', '1'), + 'm01s03i310': CFName(None, 'Cumulus capped boundary layer indicator', '1'), 'm01s03i313': CFName('soil_moisture_content_at_field_capacity', None, 'kg m-2'), + 'm01s03i321': CFName(None, 'Canopy water on tiles', 'kg/m^2'), + 'm01s03i331': CFName(None, 'Sublimation moisture flux on tiles', 'kg/m^2/s'), 'm01s03i332': CFName('toa_outgoing_longwave_flux', None, 'W m-2'), 'm01s03i334': CFName('water_potential_evaporation_flux', None, 'kg m-2 s-1'), 'm01s03i337': CFName('downward_heat_flux_in_soil', None, 'W m-2'), + 'm01s03i339': CFName(None, 'bulk_richardson_number', '1'), + 'm01s03i340': CFName(None, 'Shear driven boundary layer indicator', '1'), + 'm01s03i353': CFName(None, 'Sublimation of sea ice meaned over sea portion of grid box', 'kg/m^2/s'), + 'm01s03i365': CFName('x_wind', None, 'm s-1'), + 'm01s03i366': CFName('y_wind', None, 'm s-1'), + 'm01s03i380': CFName('surface_net_downward_radiative_flux', None, 'W m-2'), + 'm01s03i390': CFName('wind_speed_shear', None, 'm s-1'), 'm01s03i391': CFName('surface_downward_eastward_stress', None, 'Pa'), 'm01s03i392': CFName('surface_downward_eastward_stress', None, 'Pa'), 'm01s03i393': CFName('surface_downward_northward_stress', None, 'Pa'), 'm01s03i394': CFName('surface_downward_northward_stress', None, 'Pa'), + 'm01s03i395': CFName('land_area_fraction', None, '1'), + 'm01s03i401': CFName(None, 'Dust emissions division 1', 'kg/m^2/s'), + 'm01s03i402': CFName(None, 'Dust emissions division 2', 'kg/m^2/s'), + 'm01s03i403': CFName(None, 'Dust emissions division 3', 'kg/m^2/s'), + 'm01s03i404': CFName(None, 'Dust emissions division 4', 'kg/m^2/s'), + 'm01s03i405': CFName(None, 'Dust emissions division 5', 'kg/m^2/s'), + 'm01s03i406': CFName(None, 'Dust emissions division 6', 'kg/m^2/s'), + 'm01s03i430': CFName(None, 'Dust friction velocity', 'm/s'), + 'm01s03i441': CFName(None, 'Dust dry deposition flux division 1 from level 1', 'kg/m^2/s'), + 'm01s03i442': CFName(None, 'Dust dry deposition flux division 2 from level 1', 'kg/m^2/s'), + 'm01s03i443': CFName(None, 'Dust dry deposition flux division 3 from level 1', 'kg/m^2/s'), + 'm01s03i444': CFName(None, 'Dust dry deposition flux division 4 from level 1', 'kg/m^2/s'), + 'm01s03i445': CFName(None, 'Dust dry deposition flux division 5 from level 1', 'kg/m^2/s'), + 'm01s03i446': CFName(None, 'Dust dry deposition flux division 6 from level 1', 'kg/m^2/s'), + 'm01s03i451': CFName(None, 'Dust dry deposition flux division 1 from level 2', 'kg/m^2/s'), + 'm01s03i452': CFName(None, 'Dust dry deposition flux division 2 from level 2', 'kg/m^2/s'), + 'm01s03i453': CFName(None, 'Dust dry deposition flux division 3 from level 2', 'kg/m^2/s'), + 'm01s03i454': CFName(None, 'Dust dry deposition flux division 4 from level 2', 'kg/m^2/s'), + 'm01s03i455': CFName(None, 'Dust dry deposition flux division 5 from level 2', 'kg/m^2/s'), + 'm01s03i456': CFName(None, 'Dust dry deposition flux division 6 from level 2', 'kg/m^2/s'), 'm01s03i460': CFName('surface_downward_eastward_stress', None, 'Pa'), 'm01s03i461': CFName('surface_downward_northward_stress', None, 'Pa'), + 'm01s03i463': CFName('wind_speed_of_gust', None, 'm s-1'), + 'm01s03i471': CFName('atmosphere_momentum_diffusivity', None, 'm2 s-1'), + 'm01s03i472': CFName('atmosphere_heat_diffusivity', None, 'm2 s-1'), + 'm01s03i491': CFName('surface_carbon_dioxide_mole_flux', None, 'mol m-2 s-1'), + 'm01s03i538': CFName('surface_drag_coefficient_for_momentum_in_air', None, '1'), + 'm01s03i541': CFName('surface_drag_coefficient_for_heat_in_air', None, '1'), 'm01s04i004': CFName('air_temperature', None, 'K'), 'm01s04i010': CFName('specific_humidity', None, '1'), + 'm01s04i141': CFName(None, 'change_over_time_in_air_temperature_due_to_pc2_checks', 'K'), + 'm01s04i142': CFName(None, 'change_over_time_in_specific_humidity_due_to_pc2_checks', 'kg kg-1'), + 'm01s04i143': CFName(None, 'change_over_time_in_mass_fraction_of_cloud_liquid_water_in_air_due_to_pc2_checks', 'kg kg-1'), + 'm01s04i144': CFName(None, 'change_over_time_in_mass_fraction_of_cloud_ice_in_air_due_to_pc2_checks', 'kg kg-1'), + 'm01s04i152': CFName(None, 'change_over_time_in_cloud_volume_fraction_in_atmosphere_layer_due_to_pc2_checks', '1'), + 'm01s04i153': CFName(None, 'change_over_time_in_liquid_water_cloud_volume_fraction_in_atmosphere_layer_due_to_pc2_checks', '1'), + 'm01s04i154': CFName(None, 'change_over_time_in_ice_cloud_volume_fraction_in_atmosphere_layer_due_to_pc2_checks', '1'), + 'm01s04i181': CFName(None, 'change_over_time_in_air_temperature_due_to_stratiform_precipitation', 'K'), + 'm01s04i182': CFName(None, 'change_over_time_in_specific_humidity_due_to_stratiform_precipitation', 'kg kg-1'), + 'm01s04i183': CFName(None, 'change_over_time_in_mass_fraction_of_cloud_liquid_water_in_air_due_to_stratiform_precipitation', 'kg kg-1'), + 'm01s04i184': CFName(None, 'change_over_time_in_mass_fraction_of_cloud_ice_in_air_due_to_stratiform_precipitation', 'kg kg-1'), + 'm01s04i189': CFName(None, 'change_over_time_in_mass_fraction_of_rain_in_air_due_to_stratiform_precipitation', 'kg kg-1'), + 'm01s04i191': CFName(None, 'change_over_time_in_mass_fraction_of_graupel_in_air_due_to_stratiform_precipitation', 'kg kg-1'), + 'm01s04i192': CFName(None, 'change_over_time_in_cloud_volume_fraction_in_atmosphere_layer_due_to_stratiform_precipitation', '1'), + 'm01s04i193': CFName(None, 'change_over_time_in_liquid_water_cloud_volume_fraction_in_atmosphere_layer_due_to_stratiform_precipitation', '1'), + 'm01s04i194': CFName(None, 'change_over_time_in_ice_cloud_volume_fraction_in_atmosphere_layer_due_to_stratiform_precipitation', '1'), 'm01s04i201': CFName('stratiform_rainfall_amount', None, 'kg m-2'), 'm01s04i202': CFName('stratiform_snowfall_amount', None, 'kg m-2'), - 'm01s04i203': CFName('stratiform_rainfall_rate', None, 'kg m-2 s-1'), - 'm01s04i204': CFName(None, 'stratiform_snowfall_rate', 'kg m-2 s-1'), + 'm01s04i203': CFName('stratiform_rainfall_flux', None, 'kg m-2 s-1'), + 'm01s04i204': CFName('stratiform_snowfall_flux', None, 'kg m-2 s-1'), + 'm01s04i205': CFName('mass_fraction_of_cloud_liquid_water_in_air', None, '1'), + 'm01s04i206': CFName('mass_fraction_of_cloud_ice_in_air', None, '1'), + 'm01s04i222': CFName('large_scale_rainfall_flux', None, 'kg m-2 s-1'), + 'm01s04i223': CFName('large_scale_snowfall_flux', None, 'kg m-2 s-1'), + 'm01s04i231': CFName(None, 'Dust wet deposition flux due to large scale precipitation division 1', 'kg/m^2/s'), + 'm01s04i232': CFName(None, 'Dust wet deposition flux due to large scale precipitation division 2', 'kg/m^2/s'), + 'm01s04i233': CFName(None, 'Dust wet deposition flux due to large scale precipitation division 3', 'kg/m^2/s'), + 'm01s04i234': CFName(None, 'Dust wet deposition flux due to large scale precipitation division 4', 'kg/m^2/s'), + 'm01s04i235': CFName(None, 'Dust wet deposition flux due to large scale precipitation division 5', 'kg/m^2/s'), + 'm01s04i236': CFName(None, 'Dust wet deposition flux due to large scale precipitation division 6', 'kg/m^2/s'), + 'm01s04i240': CFName('tendency_of_mass_fraction_of_stratiform_cloud_ice_in_air_due_to_homogeneous_nucleation', None, 's-1'), + 'm01s04i242': CFName('tendency_of_mass_fraction_of_stratiform_cloud_ice_in_air_due_to_heterogeneous_nucleation_from_cloud_liquid', None, 's-1'), + 'm01s04i247': CFName('tendency_of_mass_fraction_of_stratiform_cloud_ice_in_air_due_to_riming_from_cloud_liquid', None, 's-1'), + 'm01s04i982': CFName(None, 'change_over_time_in_specific_humidity_due_to_methane_oxidation', 'kg kg-1'), 'm01s05i010': CFName('specific_humidity', None, '1'), - 'm01s05i181': CFName('tendency_of_air_temperature_due_to_convection', None, 'K s-1'), - 'm01s05i182': CFName('tendency_of_specific_humidity_due_to_convection', None, 's-1'), - 'm01s05i185': CFName('tendency_of_eastward_wind_due_to_convection', None, 'm s-2'), - 'm01s05i186': CFName('tendency_of_northward_wind_due_to_convection', None, 'm s-2'), + 'm01s05i181': CFName(None, 'change_over_time_in_air_temperature_due_to_convection', 'K'), + 'm01s05i182': CFName(None, 'change_over_time_in_specific_humidity_due_to_convection', 'kg kg-1'), + 'm01s05i185': CFName(None, 'change_over_time_in_x_wind_due_to_convection', 'm s-1'), + 'm01s05i186': CFName(None, 'change_over_time_in_y_wind_due_to_convection', 'm s-1'), 'm01s05i201': CFName('convective_rainfall_amount', None, 'kg m-2'), 'm01s05i202': CFName('convective_snowfall_amount', None, 'kg m-2'), - 'm01s05i205': CFName('convective_rainfall_rate', None, 'kg m-2 s-1'), + 'm01s05i205': CFName('convective_rainfall_flux', None, 'kg m-2 s-1'), 'm01s05i206': CFName('convective_snowfall_flux', None, 'kg m-2 s-1'), + 'm01s05i207': CFName('air_pressure_at_convective_cloud_base', None, 'Pa'), + 'm01s05i208': CFName('air_pressure_at_convective_cloud_top', None, 'Pa'), 'm01s05i209': CFName('air_temperature', None, 'K'), - 'm01s05i212': CFName('convective_cloud_area_fraction_in_atmosphere_layer', None, 'unknown'), + 'm01s05i212': CFName('convective_cloud_area_fraction_in_atmosphere_layer', None, '1'), 'm01s05i213': CFName('mass_fraction_of_convective_cloud_liquid_water_in_air', None, '1'), 'm01s05i214': CFName('rainfall_flux', None, 'kg m-2 s-1'), 'm01s05i215': CFName('snowfall_flux', None, 'kg m-2 s-1'), 'm01s05i216': CFName('precipitation_flux', None, 'kg m-2 s-1'), - 'm01s05i233': CFName('mass_fraction_of_convective_cloud_liquid_water_in_air', None, '1'), - 'm01s06i185': CFName('tendency_of_eastward_wind_due_to_gravity_wave_drag', None, 'm s-2'), - 'm01s06i186': CFName('tendency_of_northward_wind_due_to_gravity_wave_drag', None, 'm s-2'), + 'm01s05i222': CFName('air_pressure_at_convective_cloud_base', None, 'Pa'), + 'm01s05i226': CFName('precipitation_amount', None, 'kg m-2'), + 'm01s05i227': CFName('convective_rainfall_flux', None, 'kg m-2 s-1'), + 'm01s05i228': CFName('convective_snowfall_flux', None, 'kg m-2 s-1'), + 'm01s05i231': CFName(None, 'Cape time scale (deep)', 's'), + 'm01s05i232': CFName(None, 'reduced cape time scale indicator', '1'), + 'm01s05i233': CFName(None, 'undilute_cape', 'J kg-1'), + 'm01s05i269': CFName(None, 'deep convection indicator', '1'), + 'm01s05i270': CFName(None, 'shallow convection indicator', '1'), + 'm01s05i272': CFName(None, 'mid level convection indicator', '1'), + 'm01s05i277': CFName(None, 'deep convective precipitation rate', 'kg/m^2/s'), + 'm01s05i278': CFName(None, 'shallow convective precipitation rate', 'kg/m^2/s'), + 'm01s05i279': CFName(None, 'mid level convective precipitation rate', 'kg/m^2/s'), + 'm01s05i281': CFName(None, 'Dust wet deposition flux due to convective precipitation division 1', 'kg/m^2/s'), + 'm01s05i282': CFName(None, 'Dust wet deposition flux due to convective precipitation division 2', 'kg/m^2/s'), + 'm01s05i283': CFName(None, 'Dust wet deposition flux due to convective precipitation division 3', 'kg/m^2/s'), + 'm01s05i284': CFName(None, 'Dust wet deposition flux due to convective precipitation division 4', 'kg/m^2/s'), + 'm01s05i285': CFName(None, 'Dust wet deposition flux due to convective precipitation division 5', 'kg/m^2/s'), + 'm01s05i286': CFName(None, 'Dust wet deposition flux due to convective precipitation division 6', 'kg/m^2/s'), + 'm01s06i111': CFName('upward_eastward_momentum_flux_in_air_due_to_nonorographic_eastward_gravity_waves', None, 'Pa'), + 'm01s06i113': CFName('upward_eastward_momentum_flux_in_air_due_to_nonorographic_westward_gravity_waves', None, 'Pa'), + 'm01s06i115': CFName('tendency_of_eastward_wind_due_to_nonorographic_gravity_wave_drag', None, 'm s-2'), + 'm01s06i181': CFName(None, 'change_over_time_in_air_temperature_due_to_gravity_wave_drag', 'K'), + 'm01s06i185': CFName(None, 'change_over_time_in_x_wind_due_to_gravity_wave_drag', 'm s-1'), + 'm01s06i186': CFName(None, 'change_over_time_in_y_wind_due_to_gravity_wave_drag', 'm s-1'), 'm01s06i201': CFName('atmosphere_eastward_stress_due_to_gravity_wave_drag', None, 'Pa'), 'm01s06i202': CFName('atmosphere_northward_stress_due_to_gravity_wave_drag', None, 'Pa'), + 'm01s06i241': CFName('upward_eastward_momentum_flux_in_air_due_to_orographic_gravity_waves', None, 'Pa'), + 'm01s06i247': CFName('tendency_of_eastward_wind_due_to_orographic_gravity_wave_drag', None, 'm s-2'), 'm01s08i023': CFName('surface_snow_amount', None, 'kg m-2'), - 'm01s08i202': CFName(None, 'surface_snow_melt_flux_where_land', 'kg m-2 s-1'), + 'm01s08i202': CFName(None, 'surface_snow_melt_flux_where_land', 'W m-2'), 'm01s08i204': CFName('surface_runoff_amount', None, 'kg m-2'), 'm01s08i205': CFName('subsurface_runoff_amount', None, 'kg m-2'), - 'm01s08i208': CFName('soil_moisture_content', None, 'unknown'), - 'm01s08i209': CFName('canopy_water_amount', None, 'unknown'), + 'm01s08i208': CFName('soil_moisture_content', None, 'kg m-2'), + 'm01s08i209': CFName('canopy_water_amount', None, 'kg m-2'), 'm01s08i223': CFName('moisture_content_of_soil_layer', None, 'kg m-2'), 'm01s08i225': CFName('soil_temperature', None, 'K'), - 'm01s08i229': CFName('mass_fraction_of_unfrozen_water_in_soil_moisture', None, 'unknown'), - 'm01s08i230': CFName('mass_fraction_of_frozen_water_in_soil_moisture', None, 'unknown'), + 'm01s08i229': CFName('mass_fraction_of_unfrozen_water_in_soil_moisture', None, 'kg kg-1'), + 'm01s08i230': CFName('mass_fraction_of_frozen_water_in_soil_moisture', None, 'kg kg-1'), 'm01s08i231': CFName(None, 'surface_snow_melt_flux_where_land', 'kg m-2 s-1'), + 'm01s08i233': CFName('canopy_throughfall_flux', None, 'kg m-2 s-1'), 'm01s08i234': CFName('surface_runoff_flux', None, 'kg m-2 s-1'), 'm01s08i235': CFName('subsurface_runoff_flux', None, 'kg m-2 s-1'), + 'm01s08i245': CFName(None, 'Inland basin flow on atmospheric grid', 'kg/m^2/s'), + 'm01s08i258': CFName('surface_runoff_flux', None, 'kg m-2 s-1'), 'm01s09i004': CFName('air_temperature', None, 'K'), 'm01s09i010': CFName('specific_humidity', None, '1'), 'm01s09i201': CFName('stratiform_cloud_area_fraction_in_atmosphere_layer', None, '1'), + 'm01s09i203': CFName('low_type_cloud_area_fraction', None, '1'), + 'm01s09i204': CFName('medium_type_cloud_area_fraction', None, '1'), + 'm01s09i205': CFName('high_type_cloud_area_fraction', None, '1'), + 'm01s09i208': CFName(None, 'cloud_base_altitude_assuming_only_consider_cloud_area_fraction_greater_than_0p1_oktas', 'kft'), + 'm01s09i209': CFName(None, 'cloud_base_altitude_assuming_only_consider_cloud_area_fraction_greater_than_1p5_oktas', 'kft'), + 'm01s09i210': CFName(None, 'cloud_base_altitude_assuming_only_consider_cloud_area_fraction_greater_than_2p5_oktas', 'kft'), + 'm01s09i211': CFName(None, 'cloud_base_altitude_assuming_only_consider_cloud_area_fraction_greater_than_3p5_oktas', 'kft'), + 'm01s09i212': CFName(None, 'cloud_base_altitude_assuming_only_consider_cloud_area_fraction_greater_than_4p5_oktas', 'kft'), + 'm01s09i213': CFName(None, 'cloud_base_altitude_assuming_only_consider_cloud_area_fraction_greater_than_5p5_oktas', 'kft'), + 'm01s09i214': CFName(None, 'cloud_base_altitude_assuming_only_consider_cloud_area_fraction_greater_than_6p5_oktas', 'kft'), + 'm01s09i215': CFName(None, 'cloud_base_altitude_assuming_only_consider_cloud_area_fraction_greater_than_7p5_oktas', 'kft'), + 'm01s09i216': CFName(None, 'cloud_area_fraction_assuming_random_overlap', '1'), + 'm01s09i217': CFName(None, 'cloud_area_fraction_assuming_maximum_random_overlap', '1'), + 'm01s09i218': CFName(None, 'cloud_area_fraction_assuming_only_consider_surface_to_1000_feet_asl', '1'), + 'm01s09i219': CFName('cloud_base_altitude', None, 'ft'), + 'm01s09i221': CFName(None, 'wet_bulb_freezing_level_altitude', 'm'), + 'm01s09i222': CFName('wet_bulb_temperature', None, 'K'), + 'm01s09i226': CFName(None, 'binary_mask_where_cloud_area_fraction_in_atmosphere_layer_gt_0', '1'), + 'm01s09i228': CFName(None, 'relative_humidity_at_which_cloud_assumed_to_form', '%'), + 'm01s09i229': CFName('relative_humidity', None, '%'), + 'm01s09i230': CFName(None, 'visibility_in_atmosphere_layer', 'm'), + 'm01s10i181': CFName(None, 'change_over_time_in_air_temperature_due_to_pressure_solver', 'K'), + 'm01s10i185': CFName(None, 'change_over_time_in_x_wind_due_to_pressure_solver', 'm s-1'), + 'm01s10i186': CFName(None, 'change_over_time_in_y_wind_due_to_pressure_solver', 'm s-1'), + 'm01s10i187': CFName(None, 'change_over_time_in_upward_air_velocity_due_to_pressure_solver', 'm s-1'), 'm01s12i004': CFName('air_temperature', None, 'K'), 'm01s12i010': CFName('specific_humidity', None, '1'), 'm01s12i012': CFName('mass_fraction_of_cloud_ice_in_air', None, '1'), - 'm01s12i181': CFName('tendency_of_air_temperature_due_to_advection', None, 'K s-1'), - 'm01s12i182': CFName('tendency_of_specific_humidity_due_to_advection', None, 's-1'), - 'm01s12i183': CFName('tendency_of_mass_fraction_of_cloud_liquid_water_in_air_due_to_advection', None, 's-1'), - 'm01s12i184': CFName('tendency_of_mass_fraction_of_cloud_ice_in_air_due_to_advection', None, 's-1'), - 'm01s12i185': CFName('tendency_of_eastward_wind_due_to_advection', None, 'm s-1'), - 'm01s12i186': CFName('tendency_of_northward_wind_due_to_advection', None, 'm s-1'), - 'm01s12i187': CFName('tendency_of_upward_air_velocity_due_to_advection', None, 'm s-1'), + 'm01s12i181': CFName(None, 'change_over_time_in_air_temperature_due_to_advection', 'K'), + 'm01s12i182': CFName(None, 'change_over_time_in_specific_humidity_due_to_advection', 'kg kg-1'), + 'm01s12i183': CFName(None, 'change_over_time_in_mass_fraction_of_cloud_liquid_water_in_air_due_to_advection', 'kg kg-1'), + 'm01s12i184': CFName(None, 'change_over_time_in_mass_fraction_of_cloud_ice_in_air_due_to_advection', 'kg kg-1'), + 'm01s12i185': CFName(None, 'change_over_time_in_x_wind_due_to_advection', 'm s-1'), + 'm01s12i186': CFName(None, 'change_over_time_in_y_wind_due_to_advection', 'm s-1'), + 'm01s12i187': CFName(None, 'change_over_time_in_upward_air_velocity_due_to_advection', 'm s-1'), + 'm01s12i189': CFName(None, 'change_over_time_in_mass_fraction_of_rain_in_air_due_to_advection', 'kg kg-1'), + 'm01s12i190': CFName(None, 'change_over_time_in_mass_fraction_of_graupel_in_air_due_to_advection', 'kg kg-1'), + 'm01s12i192': CFName(None, 'change_over_time_in_cloud_volume_fraction_in_atmosphere_layer_due_to_advection', '1'), + 'm01s12i193': CFName(None, 'change_over_time_in_liquid_water_cloud_volume_fraction_in_atmosphere_layer_due_to_advection', '1'), + 'm01s12i194': CFName(None, 'change_over_time_in_ice_cloud_volume_fraction_in_atmosphere_layer_due_to_advection', '1'), + 'm01s12i195': CFName(None, 'change_over_time_in_humidity_mixing_ratio_due_to_advection', 'kg kg-1'), + 'm01s12i196': CFName(None, 'change_over_time_in_cloud_liquid_water_mixing_ratio_due_to_advection', 'kg kg-1'), + 'm01s12i197': CFName(None, 'change_over_time_in_cloud_ice_mixing_ratio_due_to_advection', 'kg kg-1'), + 'm01s12i198': CFName(None, 'change_over_time_in_rain_mixing_ratio_due_to_advection', 'kg kg-1'), + 'm01s12i199': CFName(None, 'change_over_time_in_graupel_mixing_ratio_due_to_advection', 'kg kg-1'), 'm01s12i201': CFName('lagrangian_tendency_of_air_pressure', None, 'Pa s-1'), - 'm01s13i181': CFName('tendency_of_air_temperature_due_to_diffusion', None, 'K s-1'), - 'm01s13i182': CFName('tendency_of_specific_humidity_due_to_diffusion', None, 's-1'), - 'm01s13i185': CFName('tendency_of_eastward_wind_due_to_diffusion', None, 'm s-1'), - 'm01s13i186': CFName('tendency_of_northward_wind_due_to_diffusion', None, 'm s-1'), + 'm01s12i202': CFName('lagrangian_tendency_of_air_pressure', None, 'Pa s-1'), + 'm01s12i381': CFName(None, 'change_over_time_in_air_temperature_due_to_advection_corrections', 'K'), + 'm01s12i382': CFName(None, 'change_over_time_in_specific_humidity_due_to_advection_corrections', 'kg kg-1'), + 'm01s12i383': CFName(None, 'change_over_time_in_mass_fraction_of_cloud_liquid_water_in_air_due_to_advection_corrections', 'kg kg-1'), + 'm01s12i384': CFName(None, 'change_over_time_in_mass_fraction_of_cloud_ice_in_air_due_to_advection_corrections', 'kg kg-1'), + 'm01s12i389': CFName(None, 'change_over_time_in_mass_fraction_of_rain_in_air_due_to_advection_corrections', 'kg kg-1'), + 'm01s12i391': CFName(None, 'change_over_time_in_mass_fraction_of_graupel_in_air_due_to_advection_corrections', 'kg kg-1'), + 'm01s12i395': CFName(None, 'change_over_time_in_humidity_mixing_ratio_due_to_advection_corrections', 'kg kg-1'), + 'm01s12i396': CFName(None, 'change_over_time_in_cloud_liquid_water_mixing_ratio_due_to_advection_corrections', 'kg kg-1'), + 'm01s12i397': CFName(None, 'change_over_time_in_cloud_ice_mixing_ratio_due_to_advection_corrections', 'kg kg-1'), + 'm01s12i398': CFName(None, 'change_over_time_in_rain_mixing_ratio_due_to_advection_corrections', 'kg kg-1'), + 'm01s12i399': CFName(None, 'change_over_time_in_graupel_mixing_ratio_due_to_advection_corrections', 'kg kg-1'), + 'm01s13i002': CFName('eastward_wind', None, 'm s-1'), + 'm01s13i003': CFName('northward_wind', None, 'm s-1'), + 'm01s13i004': CFName('air_temperature', None, 'K'), + 'm01s13i181': CFName(None, 'change_over_time_in_air_temperature_due_to_diffusion', 'K'), + 'm01s13i182': CFName(None, 'change_over_time_in_specific_humidity_due_to_diffusion', 'kg kg-1'), + 'm01s13i185': CFName(None, 'change_over_time_in_x_wind_due_to_diffusion', 'm s-1'), + 'm01s13i186': CFName(None, 'change_over_time_in_y_wind_due_to_diffusion', 'm s-1'), + 'm01s13i187': CFName(None, 'change_over_time_in_upward_air_velocity_due_to_diffusion', 'm s-1'), + 'm01s14i181': CFName(None, 'change_over_time_in_air_temperature_due_to_energy_correction', 'K'), + 'm01s15i101': CFName('height_above_reference_ellipsoid', None, 'm'), + 'm01s15i102': CFName('height_above_reference_ellipsoid', None, 'm'), 'm01s15i108': CFName('air_pressure', None, 'Pa'), 'm01s15i119': CFName('air_potential_temperature', None, 'K'), 'm01s15i127': CFName('air_density', None, 'kg m-3'), @@ -271,37 +677,75 @@ 'm01s15i144': CFName('y_wind', None, 'm s-1'), 'm01s15i201': CFName('x_wind', None, 'm s-1'), 'm01s15i202': CFName('y_wind', None, 'm s-1'), + 'm01s15i212': CFName('x_wind', None, 'm s-1'), + 'm01s15i213': CFName('y_wind', None, 'm s-1'), 'm01s15i214': CFName('ertel_potential_vorticity', None, 'K m2 kg-1 s-1'), 'm01s15i215': CFName('air_potential_temperature', None, 'K'), 'm01s15i216': CFName('air_potential_temperature', None, 'K'), 'm01s15i217': CFName('potential_vorticity_of_atmosphere_layer', None, 'Pa-1 s-1'), 'm01s15i218': CFName('potential_vorticity_of_atmosphere_layer', None, 'Pa-1 s-1'), - 'm01s15i219': CFName('square_of_air_temperature', None, 'unknown'), - 'm01s15i220': CFName('square_of_eastward_wind', None, 'unknown'), - 'm01s15i221': CFName('square_of_northward_wind', None, 'unknown'), + 'm01s15i219': CFName('square_of_air_temperature', None, 'K2'), + 'm01s15i220': CFName(None, 'square_of_x_wind', 'm2 s-2'), + 'm01s15i221': CFName(None, 'square_of_y_wind', 'm2 s-2'), 'm01s15i222': CFName('lagrangian_tendency_of_air_pressure', None, 'Pa s-1'), - 'm01s15i223': CFName('product_of_omega_and_air_temperature', None, 'unknown'), - 'm01s15i224': CFName('product_of_eastward_wind_and_omega', None, 'unknown'), - 'm01s15i225': CFName('product_of_northward_wind_and_omega', None, 'unknown'), - 'm01s15i226': CFName('specific_humidity', None, 'unknown'), - 'm01s15i227': CFName('product_of_eastward_wind_and_specific_humidity', None, 'unknown'), - 'm01s15i228': CFName('product_of_northward_wind_and_specific_humidity', None, 'unknown'), - 'm01s15i235': CFName('product_of_omega_and_specific_humidity', None, 'unknown'), - 'm01s15i238': CFName('geopotential_height', None, 'unknown'), - 'm01s15i239': CFName('product_of_eastward_wind_and_geopotential_height', None, 'unknown'), - 'm01s15i240': CFName('product_of_northward_wind_and_geopotential_height', None, 'unknown'), + 'm01s15i223': CFName('product_of_omega_and_air_temperature', None, 'K Pa s-1'), + 'm01s15i224': CFName(None, 'product_of_x_wind_and_omega', 'Pa m s-2'), + 'm01s15i225': CFName(None, 'product_of_y_wind_and_omega', 'Pa m s-2'), + 'm01s15i226': CFName('specific_humidity', None, 'kg kg-1'), + 'm01s15i227': CFName(None, 'product_of_x_wind_and_specific_humidity', 'm s-1'), + 'm01s15i228': CFName(None, 'product_of_y_wind_and_specific_humidity', 'm s-1'), + 'm01s15i235': CFName('product_of_omega_and_specific_humidity', None, 'Pa s-1'), + 'm01s15i238': CFName('geopotential_height', None, 'm'), + 'm01s15i239': CFName(None, 'product_of_x_wind_and_geopotential_height', 'm2 s-1'), + 'm01s15i240': CFName(None, 'product_of_y_wind_and_geopotential_height', 'm2 s-1'), 'm01s15i242': CFName('upward_air_velocity', None, 'm s-1'), 'm01s15i243': CFName('x_wind', None, 'm s-1'), 'm01s15i244': CFName('y_wind', None, 'm s-1'), 'm01s16i004': CFName('air_temperature', None, 'K'), + 'm01s16i161': CFName(None, 'change_over_time_in_air_temperature_due_to_pc2_initialisation', 'K'), + 'm01s16i162': CFName(None, 'change_over_time_in_specific_humidity_due_to_pc2_initialisation', 'kg kg-1'), + 'm01s16i163': CFName(None, 'change_over_time_in_mass_fraction_of_cloud_liquid_water_in_air_due_to_pc2_initialisation', 'kg kg-1'), + 'm01s16i164': CFName(None, 'change_over_time_in_mass_fraction_of_cloud_ice_in_air_due_to_pc2_initialisation', 'kg kg-1'), + 'm01s16i172': CFName(None, 'change_over_time_in_cloud_volume_fraction_in_atmosphere_layer_due_to_pc2_initialisation', '1'), + 'm01s16i173': CFName(None, 'change_over_time_in_liquid_water_cloud_volume_fraction_in_atmosphere_layer_due_to_pc2_initialisation', '1'), + 'm01s16i174': CFName(None, 'change_over_time_in_ice_cloud_volume_fraction_in_atmosphere_layer_due_to_pc2_initialisation', '1'), + 'm01s16i181': CFName(None, 'change_over_time_in_air_temperature_due_to_pc2_pressure_change', 'K'), + 'm01s16i182': CFName(None, 'change_over_time_in_specific_humidity_due_to_pc2_pressure_change', 'kg kg-1'), + 'm01s16i183': CFName(None, 'change_over_time_in_mass_fraction_of_cloud_liquid_water_in_air_due_to_pc2_pressure_change', 'kg kg-1'), + 'm01s16i184': CFName(None, 'change_over_time_in_mass_fraction_of_cloud_ice_in_air_due_to_pc2_pressure_change', 'kg kg-1'), + 'm01s16i192': CFName(None, 'change_over_time_in_cloud_volume_fraction_in_atmosphere_layer_due_to_pc2_pressure_change', '1'), + 'm01s16i193': CFName(None, 'change_over_time_in_liquid_water_cloud_volume_fraction_in_atmosphere_layer_due_to_pc2_pressure_change', '1'), + 'm01s16i194': CFName(None, 'change_over_time_in_ice_cloud_volume_fraction_in_atmosphere_layer_due_to_pc2_pressure_change', '1'), 'm01s16i201': CFName('geopotential_height', None, 'm'), 'm01s16i202': CFName('geopotential_height', None, 'm'), 'm01s16i203': CFName('air_temperature', None, 'K'), 'm01s16i204': CFName('relative_humidity', None, '%'), + 'm01s16i205': CFName(None, 'wet_bulb_potential_temperature', 'K'), 'm01s16i222': CFName('air_pressure_at_sea_level', None, 'Pa'), 'm01s16i224': CFName(None, 'square_of_height', 'm2'), 'm01s16i255': CFName('geopotential_height', None, 'm'), 'm01s16i256': CFName('relative_humidity', None, '%'), + 'm01s17i220': CFName(None, 'mass_concentration_of_pm10_dry_aerosol_in_air', 'ug m-3'), + 'm01s17i221': CFName(None, 'mass_concentration_of_pm2p5_dry_aerosol_in_air', 'ug m-3'), + 'm01s17i222': CFName(None, 'mass_concentration_of_ammonium_sulfate_in_pm10_dry_aerosol_in_air', 'ug m-3'), + 'm01s17i223': CFName(None, 'mass_concentration_of_ammonium_sulfate_in_pm2p5_dry_aerosol_in_air', 'ug m-3'), + 'm01s17i224': CFName(None, 'mass_concentration_of_black_carbon_in_pm10_dry_aerosol_in_air', 'ug m-3'), + 'm01s17i225': CFName(None, 'mass_concentration_of_black_carbon_in_pm2p5_dry_aerosol_in_air', 'ug m-3'), + 'm01s17i226': CFName(None, 'mass_concentration_of_biomass_burning_aerosol_in_pm10_dry_aerosol_in_air', 'ug m-3'), + 'm01s17i227': CFName(None, 'mass_concentration_of_biomass_burning_aerosol_in_pm2p5_dry_aerosol_in_air', 'ug m-3'), + 'm01s17i228': CFName(None, 'mass_concentration_of_organic_carbon_from_fossil_fuel_combustion_in_pm10_dry_aerosol_in_air', 'ug m-3'), + 'm01s17i229': CFName(None, 'mass_concentration_of_organic_carbon_from_fossil_fuel_combustion_in_pm2p5_dry_aerosol_in_air', 'ug m-3'), + 'm01s17i230': CFName(None, 'mass_concentration_of_secondary_particulate_organic_matter_in_pm10_dry_aerosol_in_air', 'ug m-3'), + 'm01s17i231': CFName(None, 'mass_concentration_of_secondary_particulate_organic_matter_in_pm2p5_dry_aerosol_in_air', 'ug m-3'), + 'm01s17i232': CFName(None, 'mass_concentration_of_seasalt_in_pm10_dry_aerosol_in_air', 'ug m-3'), + 'm01s17i233': CFName(None, 'mass_concentration_of_seasalt_in_pm2p5_dry_aerosol_in_air', 'ug m-3'), + 'm01s17i234': CFName(None, 'mass_concentration_of_dust_in_pm10_dry_aerosol_in_air', 'ug m-3'), + 'm01s17i235': CFName(None, 'mass_concentration_of_dust_in_pm2p5_dry_aerosol_in_air', 'ug m-3'), + 'm01s17i236': CFName(None, 'mass_concentration_of_ammonium_nitrate_in_pm10_dry_aerosol_in_air', 'ug m-3'), + 'm01s17i237': CFName(None, 'mass_concentration_of_ammonium_nitrate_in_pm2p5_dry_aerosol_in_air', 'ug m-3'), + 'm01s17i257': CFName('mass_concentration_of_dust_dry_aerosol_in_air', None, 'ug m-3'), + 'm01s19i002': CFName('vegetation_carbon_content', None, 'kg m-2'), + 'm01s19i016': CFName('soil_carbon_content', None, 'kg m-2'), 'm01s20i003': CFName('wind_speed', None, 'm s-1'), 'm01s20i004': CFName('wind_speed', None, 'm s-1'), 'm01s20i005': CFName('divergence_of_wind', None, 's-1'), @@ -313,25 +757,42 @@ 'm01s20i064': CFName('tropopause_air_pressure', None, 'Pa'), 'm01s20i065': CFName('tropopause_air_temperature', None, 'K'), 'm01s20i066': CFName('tropopause_altitude', None, 'm'), + 'm01s26i001': CFName(None, 'river water storage', 'kg'), + 'm01s26i002': CFName(None, 'gridbox outflow', 'kg/s'), + 'm01s26i003': CFName(None, 'gridbox inflow', 'kg/s'), + 'm01s26i004': CFName('water_flux_into_sea_water_from_rivers', None, 'kg m-2 s-1'), + 'm01s26i006': CFName(None, 'Inland basin flow on trip grid', 'kg/s'), 'm01s30i003': CFName('upward_air_velocity', None, 'm s-1'), 'm01s30i004': CFName('air_temperature', None, 'K'), 'm01s30i005': CFName('specific_humidity', None, '1'), 'm01s30i007': CFName('specific_kinetic_energy_of_air', None, 'm2 s-2'), + 'm01s30i008': CFName('lagrangian_tendency_of_air_pressure', None, 'Pa s-1'), 'm01s30i111': CFName('air_temperature', None, 'K'), 'm01s30i113': CFName('relative_humidity', None, '%'), - 'm01s30i181': CFName('tendency_of_air_temperature', None, 'K s-1'), - 'm01s30i182': CFName('tendency_of_specific_humidity', None, 's-1'), - 'm01s30i183': CFName('tendency_of_mass_fraction_of_cloud_liquid_water_in_air', None, 's-1'), - 'm01s30i184': CFName('tendency_of_mass_fraction_of_cloud_ice_in_air', None, 's-1'), - 'm01s30i185': CFName('tendency_of_eastward_wind', None, 'm s-1'), - 'm01s30i186': CFName('tendency_of_northward_wind', None, 'm s-1'), - 'm01s30i187': CFName('tendency_of_upward_air_velocity', None, 'm s-1'), + 'm01s30i181': CFName(None, 'change_over_time_in_air_temperature', 'K'), + 'm01s30i182': CFName(None, 'change_over_time_in_specific_humidity', 'kg kg-1'), + 'm01s30i183': CFName(None, 'change_over_time_in_mass_fraction_of_cloud_liquid_water_in_air', 'kg kg-1'), + 'm01s30i184': CFName(None, 'change_over_time_in_mass_fraction_of_cloud_ice_in_air', 'kg kg-1'), + 'm01s30i185': CFName(None, 'change_over_time_in_x_wind', 'm s-1'), + 'm01s30i186': CFName(None, 'change_over_time_in_y_wind', 'm s-1'), + 'm01s30i187': CFName(None, 'change_over_time_in_upward_air_velocity', 'm s-1'), 'm01s30i188': CFName('tendency_of_air_density', None, 'kg m-3 s-1'), + 'm01s30i189': CFName(None, 'change_over_time_in_mass_fraction_of_rain_in_air', 'kg kg-1'), + 'm01s30i191': CFName(None, 'change_over_time_in_mass_fraction_of_graupel_in_air', 'kg kg-1'), + 'm01s30i192': CFName(None, 'change_over_time_in_cloud_volume_fraction_in_atmosphere_layer', '1'), + 'm01s30i193': CFName(None, 'change_over_time_in_liquid_water_cloud_volume_fraction_in_atmosphere_layer', '1'), + 'm01s30i194': CFName(None, 'change_over_time_in_ice_cloud_volume_fraction_in_atmosphere_layer', '1'), + 'm01s30i195': CFName(None, 'change_over_time_in_humidity_mixing_ratio', 'kg kg-1'), + 'm01s30i196': CFName(None, 'change_over_time_in_cloud_liquid_water_mixing_ratio', 'kg kg-1'), + 'm01s30i197': CFName(None, 'change_over_time_in_cloud_ice_mixing_ratio', 'kg kg-1'), + 'm01s30i198': CFName(None, 'change_over_time_in_rain_mixing_ratio', 'kg kg-1'), + 'm01s30i199': CFName(None, 'change_over_time_in_graupel_mixing_ratio', 'kg kg-1'), 'm01s30i201': CFName('x_wind', None, 'm s-1'), 'm01s30i202': CFName('y_wind', None, 'm s-1'), 'm01s30i203': CFName('upward_air_velocity', None, 'm s-1'), 'm01s30i204': CFName('air_temperature', None, 'K'), 'm01s30i205': CFName('specific_humidity', None, '1'), + 'm01s30i206': CFName('relative_humidity', None, '%'), 'm01s30i207': CFName('geopotential_height', None, 'm'), 'm01s30i208': CFName('lagrangian_tendency_of_air_pressure', None, 'Pa s-1'), 'm01s30i211': CFName('square_of_eastward_wind', None, 'm2 s-2'), @@ -340,13 +801,13 @@ 'm01s30i214': CFName('product_of_eastward_wind_and_air_temperature', None, 'K m s-1'), 'm01s30i215': CFName('product_of_eastward_wind_and_specific_humidity', None, 'm s-1'), 'm01s30i217': CFName('product_of_eastward_wind_and_geopotential_height', None, 'm2 s-1'), - 'm01s30i218': CFName('product_of_eastward_wind_and_omega', None, 'Pa m s-1'), + 'm01s30i218': CFName(None, 'product_of_x_wind_and_omega', 'Pa m s-2'), 'm01s30i222': CFName('square_of_northward_wind', None, 'm2 s-2'), 'm01s30i223': CFName('product_of_northward_wind_and_upward_air_velocity', None, 'm2 s-2'), 'm01s30i224': CFName('product_of_northward_wind_and_air_temperature', None, 'K m s-1'), 'm01s30i225': CFName('product_of_northward_wind_and_specific_humidity', None, 'm s-1'), 'm01s30i227': CFName('product_of_northward_wind_and_geopotential_height', None, 'm2 s-1'), - 'm01s30i228': CFName('product_of_northward_wind_and_omega', None, 'Pa m s-1'), + 'm01s30i228': CFName(None, 'product_of_y_wind_and_omega', 'Pa m s-2'), 'm01s30i233': CFName('square_of_upward_air_velocity', None, 'm2 s-2'), 'm01s30i234': CFName('product_of_upward_air_velocity_and_air_temperature', None, 'K m s-1'), 'm01s30i235': CFName('product_of_upward_air_velocity_and_specific_humidity', None, 'm s-1'), @@ -357,13 +818,15 @@ 'm01s30i277': CFName('square_of_geopotential_height', None, 'm2'), 'm01s30i278': CFName('product_of_geopotential_height_and_omega', None, 'Pa m s-1'), 'm01s30i288': CFName('square_of_lagrangian_tendency_of_air_pressure', None, 'Pa2 s-2'), + 'm01s30i301': CFName(None, 'Heavyside function on pressure levels', '1'), 'm01s30i302': CFName('virtual_temperature', None, 'K'), - 'm01s30i310': CFName('northward_transformed_eulerian_mean_air_velocity', None, 'MKS'), - 'm01s30i311': CFName('northward_transformed_eulerian_mean_air_velocity', None, 'MKS'), - 'm01s30i312': CFName('northward_eliassen_palm_flux_in_air', None, 'MKS'), - 'm01s30i313': CFName('upward_eliassen_palm_flux_in_air', None, 'MKS'), - 'm01s30i314': CFName('tendency_of_eastward_wind_due_to_eliassen_palm_flux_divergence', None, 'MKS'), + 'm01s30i310': CFName('northward_transformed_eulerian_mean_air_velocity', None, 'm s-1'), + 'm01s30i311': CFName('northward_transformed_eulerian_mean_air_velocity', None, 'm s-1'), + 'm01s30i312': CFName('northward_eliassen_palm_flux_in_air', None, 'kg s-2'), + 'm01s30i313': CFName('upward_eliassen_palm_flux_in_air', None, 'kg s-2'), + 'm01s30i314': CFName('tendency_of_eastward_wind_due_to_eliassen_palm_flux_divergence', None, 'm s-2'), 'm01s30i401': CFName('atmosphere_kinetic_energy_content', None, 'J m-2'), + 'm01s30i404': CFName('atmosphere_mass_per_unit_area', None, 'kg m-2'), 'm01s30i405': CFName('atmosphere_cloud_liquid_water_content', None, 'kg m-2'), 'm01s30i406': CFName('atmosphere_cloud_ice_content', None, 'kg m-2'), 'm01s30i417': CFName('surface_air_pressure', None, 'Pa'), @@ -371,6 +834,9 @@ 'm01s30i451': CFName('tropopause_air_pressure', None, 'Pa'), 'm01s30i452': CFName('tropopause_air_temperature', None, 'K'), 'm01s30i453': CFName('tropopause_altitude', None, 'm'), + 'm01s30i901': CFName(None, 'change_over_time_in_air_potential_temperature', 'K'), + 'm01s30i902': CFName(None, 'change_over_time_in_virtual_potential_temperature', 'K'), + 'm01s30i903': CFName(None, 'change_over_time_in_air_density', 'kg m-3'), 'm01s33i001': CFName('mole_fraction_of_ozone_in_air', None, 'mole mole-1'), 'm01s33i004': CFName(None, 'mole_fraction_of_nitrogen_trioxide_in_air', 'mole mole-1'), 'm01s33i005': CFName('mole_fraction_of_dinitrogen_pentoxide_in_air', None, 'mole mole-1'), @@ -389,87 +855,138 @@ 'm01s33i055': CFName('mole_fraction_of_cfc11_in_air', None, '1'), 'm01s33i056': CFName('mole_fraction_of_cfc12_in_air', None, '1'), 'm01s33i058': CFName('mole_fraction_of_atomic_nitrogen_in_air', None, '1'), - 'm01s33i150': CFName('age_of_stratospheric_air', None, '1'), - 'm01s34i001': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i002': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i003': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i004': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i005': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i006': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i007': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i008': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i009': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i010': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i011': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i012': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i013': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i014': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i015': CFName(None, 'mass_fraction_of_ethyl_hydroperoxide_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i016': CFName(None, 'mass_fraction_of_acetaldehyde_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i017': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i018': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i019': CFName(None, 'mass_fraction_of_n-propyl_hydroperoxide_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i020': CFName(None, 'mass_fraction_of_i-propyl_hydroperoxide_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i021': CFName(None, 'mass_fraction_of_propanal_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i022': CFName(None, 'mass_fraction_of_acetone_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i023': CFName(None, 'mass_fraction_of_acetonylhydroperoxide_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i024': CFName(None, 'mass_fraction_of_peroxypropionyl_nitrate_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i025': CFName(None, 'mass_fraction_of_methyl_nitrate_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i026': CFName(None, 'mass_fraction_of_stratospheric_ozone_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i027': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i028': CFName(None, 'mass_fraction_of_isoprene_hydroperoxide_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i030': CFName(None, 'mass_fraction_of_methacrolein_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i031': CFName(None, 'mass_fraction_of_methacroyl_hydroperoxide_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i032': CFName(None, 'mass_fraction_of_methacryloylperoxy_nitrate_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i033': CFName(None, 'mass_fraction_of_hydroxyacetone_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i034': CFName(None, 'mass_fraction_of_methlyglyoxal_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i035': CFName(None, 'mass_fraction_of_second_generation_isoprene_nitrate_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i036': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i037': CFName(None, 'mass_fraction_of_peracetic_acid_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i038': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i041': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i042': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i043': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i044': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i045': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i047': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i048': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i049': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i051': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i052': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i053': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i054': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i055': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i056': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i057': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i058': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i059': CFName(None, 'mass_fraction_of_ground_state_atomic_oxygen_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i070': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i071': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i072': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i073': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i074': CFName(None, 'mass_fraction_of_methanesulfonic_acid_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i075': CFName(None, 'mass_fraction_of_dimethyl_sulfoxide', 'Mass mixing ratio (kg/kg)'), - 'm01s34i076': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i077': CFName(None, 'mass_fraction_of_carbon_disulfide_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i078': CFName(None, 'mass_fraction_of_carbonyl_sulfide_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i079': CFName(None, 'mass_fraction_of_hydrogen_sulfide_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i080': CFName(None, 'mass_fraction_of_atomic_hydrogen_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i081': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i082': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i083': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i084': CFName(None, 'mass_fraction_of_ethyl_peroxy_radical_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i085': CFName(None, 'mass_fraction_of_peroxyacetyl_radical_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i086': CFName(None, 'mass_fraction_of_n-propylperoxy_radical_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i087': CFName(None, 'mass_fraction_of_isopropylperoxy_radical_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i088': CFName(None, 'mass_fraction_of_peroxypropanoyl_radical_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i089': CFName(None, 'mass_fraction_of_acetonyl_peroxy_radical_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i093': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i096': CFName(None, 'mass_fraction_of_methyl_ethyl_ketone_in_air', 'Mass mixing ratio (kg/kg)'), - 'm01s34i097': CFName(None, None, 'Mass mixing ratio (kg/kg)'), - 'm01s34i100': CFName(None, 'mass_fraction_of_lumped_chlorine_expressed_as_hydrogen_chloride', 'Mass mixing ratio (kg/kg)'), + 'm01s33i150': CFName('age_of_stratospheric_air', None, 's'), + 'm01s34i001': CFName('mass_fraction_of_ozone_in_air', None, 'kg kg-1'), + 'm01s34i002': CFName('mass_fraction_of_nitrogen_monoxide_in_air', None, 'kg kg-1'), + 'm01s34i003': CFName('mass_fraction_of_nitrate_radical_in_air', None, 'kg kg-1'), + 'm01s34i004': CFName('mass_fraction_of_nitrogen_dioxide_in_air', None, 'kg kg-1'), + 'm01s34i005': CFName('mass_fraction_of_dinitrogen_pentoxide_in_air', None, 'kg kg-1'), + 'm01s34i006': CFName('mass_fraction_of_peroxynitric_acid_in_air', None, 'kg kg-1'), + 'm01s34i007': CFName('mass_fraction_of_nitric_acid_in_air', None, 'kg kg-1'), + 'm01s34i008': CFName('mass_fraction_of_hydrogen_peroxide_in_air', None, 'kg kg-1'), + 'm01s34i009': CFName('mass_fraction_of_methane_in_air', None, 'kg kg-1'), + 'm01s34i010': CFName('mass_fraction_of_carbon_monoxide_in_air', None, 'kg kg-1'), + 'm01s34i011': CFName('mass_fraction_of_formaldehyde_in_air', None, 'kg kg-1'), + 'm01s34i012': CFName('mass_fraction_of_methyl_hydroperoxide_in_air', None, 'kg kg-1'), + 'm01s34i013': CFName('mass_fraction_of_nitrous_acid_in_air', None, 'kg kg-1'), + 'm01s34i014': CFName('mass_fraction_of_ethane_in_air', None, 'kg kg-1'), + 'm01s34i015': CFName(None, 'mass_fraction_of_ethyl_hydroperoxide_in_air', 'kg kg-1'), + 'm01s34i016': CFName(None, 'mass_fraction_of_acetaldehyde_in_air', 'kg kg-1'), + 'm01s34i017': CFName('mass_fraction_of_peroxyacetyl_nitrate_in_air', None, 'kg kg-1'), + 'm01s34i018': CFName('mass_fraction_of_propane_in_air', None, 'kg kg-1'), + 'm01s34i019': CFName(None, 'mass_fraction_of_n-propyl_hydroperoxide_in_air', 'kg kg-1'), + 'm01s34i020': CFName(None, 'mass_fraction_of_i-propyl_hydroperoxide_in_air', 'kg kg-1'), + 'm01s34i021': CFName(None, 'mass_fraction_of_propanal_in_air', 'kg kg-1'), + 'm01s34i022': CFName(None, 'mass_fraction_of_acetone_in_air', 'kg kg-1'), + 'm01s34i023': CFName(None, 'mass_fraction_of_acetonylhydroperoxide_in_air', 'kg kg-1'), + 'm01s34i024': CFName(None, 'mass_fraction_of_peroxypropionyl_nitrate_in_air', 'kg kg-1'), + 'm01s34i025': CFName(None, 'mass_fraction_of_methyl_nitrate_in_air', 'kg kg-1'), + 'm01s34i026': CFName(None, 'mass_fraction_of_stratospheric_ozone_in_air', 'kg kg-1'), + 'm01s34i027': CFName('mass_fraction_of_isoprene_in_air', None, 'kg kg-1'), + 'm01s34i028': CFName(None, 'mass_fraction_of_isoprene_hydroperoxide_in_air', 'kg kg-1'), + 'm01s34i030': CFName(None, 'mass_fraction_of_methacrolein_in_air', 'kg kg-1'), + 'm01s34i031': CFName(None, 'mass_fraction_of_methacroyl_hydroperoxide_in_air', 'kg kg-1'), + 'm01s34i032': CFName(None, 'mass_fraction_of_methacryloylperoxy_nitrate_in_air', 'kg kg-1'), + 'm01s34i033': CFName(None, 'mass_fraction_of_hydroxyacetone_in_air', 'kg kg-1'), + 'm01s34i034': CFName(None, 'mass_fraction_of_methlyglyoxal_in_air', 'kg kg-1'), + 'm01s34i035': CFName(None, 'mass_fraction_of_second_generation_isoprene_nitrate_in_air', 'kg kg-1'), + 'm01s34i036': CFName('mass_fraction_of_formic_acid_in_air', None, 'kg kg-1'), + 'm01s34i037': CFName(None, 'mass_fraction_of_peracetic_acid_in_air', 'kg kg-1'), + 'm01s34i038': CFName('mass_fraction_of_acetic_acid_in_air', None, 'kg kg-1'), + 'm01s34i041': CFName('mass_fraction_of_atomic_chlorine_in_air', None, 'kg kg-1'), + 'm01s34i042': CFName('mass_fraction_of_chlorine_monoxide_in_air', None, 'kg kg-1'), + 'm01s34i043': CFName('mass_fraction_of_dichlorine_peroxide_in_air', None, 'kg kg-1'), + 'm01s34i044': CFName('mass_fraction_of_chlorine_dioxide_in_air', None, 'kg kg-1'), + 'm01s34i045': CFName('mass_fraction_of_atomic_bromine_in_air', None, 'kg kg-1'), + 'm01s34i047': CFName('mass_fraction_of_bromine_chloride_in_air', None, 'kg kg-1'), + 'm01s34i048': CFName('mass_fraction_of_bromine_nitrate_in_air', None, 'kg kg-1'), + 'm01s34i049': CFName('mass_fraction_of_nitrous_oxide_in_air', None, 'kg kg-1'), + 'm01s34i051': CFName('mass_fraction_of_hypochlorous_acid_in_air', None, 'kg kg-1'), + 'm01s34i052': CFName('mass_fraction_of_hydrogen_bromide_in_air', None, 'kg kg-1'), + 'm01s34i053': CFName('mole_fraction_of_hypobromous_acid_in_air', None, 'kg kg-1'), + 'm01s34i054': CFName('mass_fraction_of_chlorine_nitrate_in_air', None, 'kg kg-1'), + 'm01s34i055': CFName('mass_fraction_of_cfc11_in_air', None, 'kg kg-1'), + 'm01s34i056': CFName('mass_fraction_of_cfc12_in_air', None, 'kg kg-1'), + 'm01s34i057': CFName('mass_fraction_of_methyl_bromide_in_air', None, 'kg kg-1'), + 'm01s34i058': CFName('mass_fraction_of_atomic_nitrogen_in_air', None, 'kg kg-1'), + 'm01s34i059': CFName(None, 'mass_fraction_of_ground_state_atomic_oxygen_in_air', 'kg kg-1'), + 'm01s34i070': CFName('mass_fraction_of_molecular_hydrogen_in_air', None, 'kg kg-1'), + 'm01s34i071': CFName('mass_fraction_of_dimethyl_sulfide_in_air', None, 'kg kg-1'), + 'm01s34i072': CFName('mass_fraction_of_sulfur_dioxide_in_air', None, 'kg kg-1'), + 'm01s34i073': CFName('mass_fraction_of_sulfuric_acid_in_air', None, 'kg kg-1'), + 'm01s34i074': CFName(None, 'mass_fraction_of_methanesulfonic_acid_in_air', 'kg kg-1'), + 'm01s34i075': CFName(None, 'mass_fraction_of_dimethyl_sulfoxide', 'kg kg-1'), + 'm01s34i076': CFName('mass_fraction_of_ammonia_in_air', None, 'kg kg-1'), + 'm01s34i077': CFName(None, 'mass_fraction_of_carbon_disulfide_in_air', 'kg kg-1'), + 'm01s34i078': CFName(None, 'mass_fraction_of_carbonyl_sulfide_in_air', 'kg kg-1'), + 'm01s34i079': CFName(None, 'mass_fraction_of_hydrogen_sulfide_in_air', 'kg kg-1'), + 'm01s34i080': CFName(None, 'mass_fraction_of_atomic_hydrogen_in_air', 'kg kg-1'), + 'm01s34i081': CFName('mass_fraction_of_hydroxyl_radical_in_air', None, 'kg kg-1'), + 'm01s34i082': CFName('mass_fraction_of_hydroperoxyl_radical_in_air', None, 'kg kg-1'), + 'm01s34i083': CFName('mass_fraction_of_methyl_peroxy_radical_in_air', None, 'kg kg-1'), + 'm01s34i084': CFName(None, 'mass_fraction_of_ethyl_peroxy_radical_in_air', 'kg kg-1'), + 'm01s34i085': CFName(None, 'mass_fraction_of_peroxyacetyl_radical_in_air', 'kg kg-1'), + 'm01s34i086': CFName(None, 'mass_fraction_of_n-propylperoxy_radical_in_air', 'kg kg-1'), + 'm01s34i087': CFName(None, 'mass_fraction_of_isopropylperoxy_radical_in_air', 'kg kg-1'), + 'm01s34i088': CFName(None, 'mass_fraction_of_peroxypropanoyl_radical_in_air', 'kg kg-1'), + 'm01s34i089': CFName(None, 'mass_fraction_of_acetonyl_peroxy_radical_in_air', 'kg kg-1'), + 'm01s34i093': CFName('mass_fraction_of_propene_in_air', None, 'kg kg-1'), + 'm01s34i096': CFName(None, 'mass_fraction_of_methyl_ethyl_ketone_in_air', 'kg kg-1'), + 'm01s34i097': CFName('mass_fraction_of_toluene_in_air', None, 'kg kg-1'), + 'm01s34i100': CFName(None, 'mass_fraction_of_lumped_chlorine_expressed_as_hydrogen_chloride', 'kg kg-1'), + 'm01s34i101': CFName(None, 'number_of_particles_per_air_molecule_of_soluble_nucleation_mode_aerosol_in_air', '1'), + 'm01s34i102': CFName(None, 'mass_fraction_of_sulfuric_acid_in_soluble_nucleation_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i103': CFName(None, 'number_of_particles_per_air_molecule_of_soluble_aitken_mode_aerosol_in_air', '1'), + 'm01s34i104': CFName(None, 'mass_fraction_of_sulfuric_acid_in_soluble_aitken_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i105': CFName(None, 'mass_fraction_of_black_carbon_in_soluble_aitken_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i106': CFName(None, 'mass_fraction_of_particulate_organic_matter_in_soluble_aitken_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i107': CFName(None, 'number_of_particles_per_air_molecule_of_soluble_accumulation_mode_aerosol_in_air', '1'), + 'm01s34i108': CFName(None, 'mass_fraction_of_sulfuric_acid_in_soluble_accumulation_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i109': CFName(None, 'mass_fraction_of_black_carbon_in_soluble_accumulation_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i110': CFName(None, 'mass_fraction_of_particulate_organic_matter_in_soluble_accumulation_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i111': CFName(None, 'mass_fraction_of_seasalt_in_soluble_accumulation_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i112': CFName(None, 'mass_fraction_of_dust_in_soluble_accumulation_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i113': CFName(None, 'number_of_particles_per_air_molecule_of_soluble_coarse_mode_aerosol_in_air', '1'), + 'm01s34i114': CFName(None, 'mass_fraction_of_sulfuric_acid_in_soluble_coarse_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i115': CFName(None, 'mass_fraction_of_black_carbon_in_soluble_coarse_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i116': CFName(None, 'mass_fraction_of_particulate_organic_matter_in_soluble_coarse_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i117': CFName(None, 'mass_fraction_of_seasalt_in_soluble_coarse_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i118': CFName(None, 'mass_fraction_of_dust_in_soluble_coarse_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i119': CFName(None, 'number_of_particles_per_air_molecule_of_insoluble_aitken_mode_aerosol_in_air', '1'), + 'm01s34i120': CFName(None, 'mass_fraction_of_black_carbon_in_insoluble_aitken_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i121': CFName(None, 'mass_fraction_of_particulate_organic_matter_in_insoluble_aitken_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i122': CFName(None, 'number_of_particles_per_air_molecule_of_insoluble_accumulation_mode_aerosol_in_air', '1'), + 'm01s34i123': CFName(None, 'mass_fraction_of_dust_in_insoluble_accumulation_mode_aerosol_in_air', 'kg kg-1'), + 'm01s34i124': CFName(None, 'number_of_particles_per_air_molecule_of_insoluble_coarse_mode_aerosol_in_air', '1'), + 'm01s34i125': CFName(None, 'mass_fraction_of_dust_in_insoluble_coarse_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i126': CFName(None, 'mass_fraction_of_particulate_organic_matter_in_soluble_nucleation_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i127': CFName(None, 'mass_fraction_of_seasalt_in_soluble_aitken_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i128': CFName(None, 'mass_fraction_of_secondary_particulate_organic_matter_in_soluble_nucleation_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i129': CFName(None, 'mass_fraction_of_secondary_particulate_organic_matter_in_soluble_aitken_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i130': CFName(None, 'mass_fraction_of_secondary_particulate_organic_matter_in_soluble_accumulation_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i131': CFName(None, 'mass_fraction_of_secondary_particulate_organic_matter_in_soluble_coarse_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i132': CFName(None, 'mass_fraction_of_ammonium_in_soluble_nucleation_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i133': CFName(None, 'mass_fraction_of_ammonium_in_soluble_aitken_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i134': CFName(None, 'mass_fraction_of_ammonium_in_soluble_accumulation_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i135': CFName(None, 'mass_fraction_of_ammonium_in_soluble_coarse_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i136': CFName(None, 'mass_fraction_of_nitrate_in_soluble_nucleation_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i137': CFName(None, 'mass_fraction_of_nitrate_in_soluble_aitken_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i138': CFName(None, 'mass_fraction_of_nitrate_in_soluble_accumulation_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i139': CFName(None, 'mass_fraction_of_nitrate_in_soluble_coarse_mode_dry_aerosol_in_air', 'kg kg-1'), + 'm01s34i150': CFName('age_of_stratospheric_air', None, 's'), + 'm01s34i159': CFName('equivalent_thickness_at_stp_of_atmosphere_ozone_content', None, 'DU'), + 'm01s35i003': CFName(None, 'change_over_time_in_x_wind_due_to_stochastic_kinetic_energy_backscatter', 'm s-1'), + 'm01s35i004': CFName(None, 'change_over_time_in_y_wind_due_to_stochastic_kinetic_energy_backscatter', 'm s-1'), + 'm01s35i024': CFName(None, 'change_over_time_in_air_potential_temperature_due_to_stochastic_perturbation_of_tendencies', 'K'), + 'm01s35i025': CFName(None, 'change_over_time_in_specific_humidity_due_to_stochastic_perturbation_of_tendencies', 'kg kg-1'), + 'm01s35i026': CFName(None, 'change_over_time_in_x_wind_due_to_stochastic_perturbation_of_tendencies', 'm s-1'), + 'm01s35i027': CFName(None, 'change_over_time_in_y_wind_due_to_stochastic_perturbation_of_tendencies', 'm s-1'), + 'm01s35i029': CFName(None, 'change_over_time_in_air_temperature_due_to_stochastic_perturbation_of_tendencies', 'K'), + 'm01s50i228': CFName('photolysis_rate_of_ozone_to_1D_oxygen_atom', None, 's-1'), + 'm01s50i229': CFName('photolysis_rate_of_nitrogen_dioxide', None, 's-1'), + 'm01s50i230': CFName('mass_concentration_of_nmvoc_expressed_as_carbon_in_air', None, 'ug m-3'), 'm02s00i101': CFName('sea_water_potential_temperature', None, 'degC'), - 'm02s00i102': CFName('sea_water_salinity', None, '1e3 psu @0.035'), + 'm02s00i102': CFName('sea_water_salinity', None, '1e3 @0.035'), 'm02s00i121': CFName('baroclinic_eastward_sea_water_velocity', None, 'cm s-1'), 'm02s00i122': CFName('baroclinic_northward_sea_water_velocity', None, 'cm s-1'), 'm02s00i130': CFName('ocean_barotropic_streamfunction', None, 'cm3 s-1'), @@ -493,14 +1010,16 @@ 'm02s00i152': CFName('wind_mixing_energy_flux_into_sea_water', None, 'W m-2'), 'm02s00i166': CFName('water_flux_into_sea_water_from_rivers', None, 'kg m-2 s-1'), 'm02s00i171': CFName('snowfall_flux', None, 'kg m-2 s-1'), + 'm02s00i172': CFName('surface_snow_and_ice_sublimation_flux', None, 'kg m-2 s-1'), 'm02s00i180': CFName('sea_surface_temperature', None, 'K'), - 'm02s00i181': CFName('sea_surface_salinity', None, '1e3 psu @0.035'), + 'm02s00i181': CFName('sea_surface_salinity', None, '1e3 @0.035'), 'm02s00i182': CFName('air_temperature', None, 'K'), 'm02s00i183': CFName('sea_ice_thickness', None, 'm'), 'm02s00i185': CFName('heat_flux_correction', None, 'W m-2'), - 'm02s00i186': CFName('water_flux_correction', None, 'Kg m-2 s-1'), + 'm02s00i186': CFName('water_flux_correction', None, 'kg m-2 s-1'), 'm02s00i190': CFName('surface_snow_and_ice_melt_heat_flux', None, 'W m-2'), 'm02s00i191': CFName('downward_heat_flux_in_sea_ice', None, 'W m-2'), + 'm02s00i192': CFName('water_flux_into_sea_water_due_to_sea_ice_thermodynamics', None, 'kg m-2 s-1'), 'm02s30i201': CFName('upward_sea_water_velocity', None, 'cm s-1'), 'm02s30i202': CFName('ocean_mixed_layer_thickness', None, 'm'), 'm02s30i211': CFName('northward_ocean_heat_transport', None, 'PW'), @@ -508,15 +1027,38 @@ 'm02s30i320': CFName('eastward_sea_water_velocity', None, 'cm s-1'), 'm02s30i321': CFName('northward_sea_water_velocity', None, 'cm s-1'), 'm02s30i324': CFName('ocean_mixed_layer_thickness', None, 'm'), + 'm02s30i406': CFName(None, 'mole_concentration_of_dimethyl_sulphide_in_seawater', 'mol m-3'), 'm02s32i201': CFName('tendency_of_sea_ice_area_fraction_due_to_dynamics', None, 's-1'), 'm02s32i202': CFName('tendency_of_sea_ice_thickness_due_to_dynamics', None, 'm s-1'), 'm02s32i209': CFName('eastward_sea_ice_velocity', None, 'm s-1'), 'm02s32i210': CFName('northward_sea_ice_velocity', None, 'm s-1'), 'm02s32i211': CFName('tendency_of_sea_ice_area_fraction_due_to_thermodynamics', None, 's-1'), 'm02s32i212': CFName('tendency_of_sea_ice_thickness_due_to_thermodynamics', None, 'm s-1'), + 'm02s32i215': CFName('snowfall_flux', None, 'kg m-2 s-1'), 'm02s32i219': CFName('downward_eastward_stress_at_sea_ice_base', None, 'Pa'), 'm02s32i220': CFName('downward_northward_stress_at_sea_ice_base', None, 'Pa'), 'm03s00i177': CFName(None, 'prescribed_heat_flux_into_slab_ocean', 'W m-2'), + 'm04s06i001': CFName('sea_surface_wind_wave_significant_height', None, 'm'), + } + +STASHCODE_IMPLIED_HEIGHTS = { + 'm01s03i209': (10.0,), + 'm01s03i210': (10.0,), + 'm01s03i225': (10.0,), + 'm01s03i226': (10.0,), + 'm01s03i227': (10.0,), + 'm01s03i230': (10.0,), + 'm01s03i236': (1.5,), + 'm01s03i237': (1.5,), + 'm01s03i245': (1.5,), + 'm01s03i247': (1.5,), + 'm01s03i250': (1.5,), + 'm01s03i281': (1.5,), + 'm01s03i365': (10.0,), + 'm01s03i366': (10.0,), + 'm01s03i463': (10.0,), + 'm01s15i212': (50.0,), + 'm01s15i213': (50.0,), } CF_TO_LBFC = { @@ -527,6 +1069,7 @@ CFName('air_pressure', None, 'Pa'): 8, CFName('air_pressure_at_freezing_level', None, 'Pa'): 8, CFName('air_pressure_at_sea_level', None, 'Pa'): 8, + CFName('air_temperature', None, 'K'): 16, CFName('atmosphere_boundary_layer_thickness', None, 'm'): 5, CFName('atmosphere_eastward_stress_due_to_gravity_wave_drag', None, 'Pa'): 61, CFName('atmosphere_kinetic_energy_content', None, 'J m-2'): 63, @@ -541,10 +1084,12 @@ CFName('divergence_of_wind', None, 's-1'): 74, CFName('downward_heat_flux_in_sea_ice', None, 'W m-2'): 261, CFName('downward_heat_flux_in_soil', None, 'W m-2'): 1564, + CFName('eastward_wind', None, 'm s-1'): 56, CFName('ertel_potential_vorticity', None, 'K m2 kg-1 s-1'): 82, CFName('geopotential_height', None, 'm'): 1, CFName('lagrangian_tendency_of_air_pressure', None, 'Pa s-1'): 40, CFName('land_binary_mask', None, '1'): 395, + CFName('large_scale_rainfall_rate', None, 'm s-1'): 99, CFName('mass_fraction_of_carbon_dioxide_in_air', None, '1'): 1564, CFName('mass_fraction_of_cloud_liquid_water_in_air', None, '1'): 79, CFName('mass_fraction_of_dimethyl_sulfide_in_air', None, '1'): 1373, @@ -565,6 +1110,7 @@ CFName('mole_fraction_of_dichlorine_peroxide_in_air', None, '1'): 501, CFName('mole_fraction_of_hypochlorous_acid_in_air', None, '1'): 501, CFName('mole_fraction_of_nitrous_oxide_in_air', None, '1'): 501, + CFName('northward_wind', None, 'm s-1'): 57, CFName('rainfall_flux', None, 'kg m-2 s-1'): 97, CFName('relative_humidity', None, '%'): 88, CFName('root_depth', None, 'm'): 321, @@ -572,6 +1118,7 @@ CFName('sea_ice_area_fraction', None, '1'): 37, CFName('sea_ice_temperature', None, 'K'): 209, CFName('sea_ice_thickness', None, 'm'): 687, + CFName('sea_surface_elevation', None, 'm'): 608, CFName('snow_grain_size', None, '1e-6 m'): 1507, CFName('snowfall_amount', None, 'kg m-2'): 93, CFName('snowfall_flux', None, 'kg m-2 s-1'): 108, @@ -636,4 +1183,7 @@ CFName('volume_fraction_of_condensed_water_in_soil_at_wilting_point', None, '1'): 329, CFName('water_potential_evaporation_flux', None, 'kg m-2 s-1'): 115, CFName('wind_mixing_energy_flux_into_sea_water', None, 'W m-2'): 182, + CFName('wind_speed', None, 'm s-1'): 50, + CFName('x_wind', None, 'm s-1'): 56, + CFName('y_wind', None, 'm s-1'): 57, } diff --git a/lib/iris/io/__init__.py b/lib/iris/io/__init__.py index 25fd249ecd..6c739ffbc1 100644 --- a/lib/iris/io/__init__.py +++ b/lib/iris/io/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -18,15 +18,18 @@ Provides an interface to manage URI scheme support in iris. """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +from collections import OrderedDict import glob import os.path -import types import re -import warnings import collections import iris.fileformats -import iris.fileformats.dot import iris.cube import iris.exceptions @@ -35,9 +38,9 @@ class _SaversDict(dict): """A dictionary that can only have string keys with no overlap.""" def __setitem__(self, key, value): - if not isinstance(key, basestring): + if not isinstance(key, six.string_types): raise ValueError("key is not a string") - if key in self.keys(): + if key in self: raise ValueError("A saver already exists for", key) for k in self.keys(): if k.endswith(key) or key.endswith(k): @@ -57,6 +60,7 @@ def run_callback(callback, cube, field, filename): * callback: A function to add metadata from the originating field and/or URI which obeys the following rules: + 1. Function signature must be: ``(cube, field, filename)``. 2. Modifies the given cube inplace, unless a new cube is returned by the function. @@ -101,22 +105,22 @@ def decode_uri(uri, default='file'): Examples: >>> from iris.io import decode_uri - >>> print decode_uri('http://www.thing.com:8080/resource?id=a:b') + >>> print(decode_uri('http://www.thing.com:8080/resource?id=a:b')) ('http', '//www.thing.com:8080/resource?id=a:b') - >>> print decode_uri('file:///data/local/dataZoo/...') + >>> print(decode_uri('file:///data/local/dataZoo/...')) ('file', '///data/local/dataZoo/...') - >>> print decode_uri('/data/local/dataZoo/...') + >>> print(decode_uri('/data/local/dataZoo/...')) ('file', '/data/local/dataZoo/...') - >>> print decode_uri('file:///C:\data\local\dataZoo\...') + >>> print(decode_uri('file:///C:\data\local\dataZoo\...')) ('file', '///C:\\data\\local\\dataZoo\\...') - >>> print decode_uri('C:\data\local\dataZoo\...') + >>> print(decode_uri('C:\data\local\dataZoo\...')) ('file', 'C:\\data\\local\\dataZoo\\...') - >>> print decode_uri('dataZoo/...') + >>> print(decode_uri('dataZoo/...')) ('file', 'dataZoo/...') ''' @@ -144,31 +148,41 @@ def expand_filespecs(file_specs): File paths which may contain '~' elements or wildcards. Returns: - A list of matching file paths. If any of the file-specs matches no - existing files, an exception is raised. + A well-ordered list of matching absolute file paths. + If any of the file-specs match no existing files, an + exception is raised. """ # Remove any hostname component - currently unused - filenames = [os.path.expanduser(fn[2:] if fn.startswith('//') else fn) + filenames = [os.path.abspath(os.path.expanduser( + fn[2:] if fn.startswith('//') else fn)) for fn in file_specs] # Try to expand all filenames as globs - glob_expanded = {fn : sorted(glob.glob(fn)) for fn in filenames} + glob_expanded = OrderedDict([[fn, sorted(glob.glob(fn))] + for fn in filenames]) # If any of the specs expanded to an empty list then raise an error - value_lists = glob_expanded.viewvalues() - if not all(value_lists): - raise IOError("One or more of the files specified did not exist %s." % - ["%s expanded to %s" % (pattern, expanded if expanded else "empty") - for pattern, expanded in glob_expanded.iteritems()]) + all_expanded = glob_expanded.values() - return sum(value_lists, []) + if not all(all_expanded): + msg = "One or more of the files specified did not exist:" + for pattern, expanded in six.iteritems(glob_expanded): + if expanded: + msg += '\n - "{}" matched {} file(s)'.format(pattern, + len(expanded)) + else: + msg += '\n * "{}" didn\'t match any files'.format(pattern) + raise IOError(msg) + return [fname for fnames in all_expanded for fname in fnames] -def load_files(filenames, callback): + +def load_files(filenames, callback, constraints=None): """ Takes a list of filenames which may also be globs, and optionally a - callback function, and returns a generator of Cubes from the given files. + constraint set and a callback function, and returns a + generator of Cubes from the given files. .. note:: @@ -181,14 +195,20 @@ def load_files(filenames, callback): # Create default dict mapping iris format handler to its associated filenames handler_map = collections.defaultdict(list) for fn in all_file_paths: - with open(fn) as fh: + with open(fn, 'rb') as fh: handling_format_spec = iris.fileformats.FORMAT_AGENT.get_spec(os.path.basename(fn), fh) handler_map[handling_format_spec].append(fn) # Call each iris format handler with the approriate filenames - for handling_format_spec, fnames in handler_map.iteritems(): - for cube in handling_format_spec.handler(fnames, callback): - yield cube + for handling_format_spec in sorted(handler_map): + fnames = handler_map[handling_format_spec] + if handling_format_spec.constraint_aware_handler: + for cube in handling_format_spec.handler(fnames, callback, + constraints): + yield cube + else: + for cube in handling_format_spec.handler(fnames, callback): + yield cube def load_http(urls, callback): @@ -209,20 +229,49 @@ def load_http(urls, callback): handler_map[handling_format_spec].append(url) # Call each iris format handler with the appropriate filenames - for handling_format_spec, fnames in handler_map.iteritems(): + for handling_format_spec in sorted(handler_map): + fnames = handler_map[handling_format_spec] for cube in handling_format_spec.handler(fnames, callback): yield cube +def _dot_save(cube, target): + # A simple wrapper for `iris.fileformats.dot.save` which allows the + # saver to be registered without triggering the import of + # `iris.fileformats.dot`. + import iris.fileformats.dot + return iris.fileformats.dot.save(cube, target) + + +def _dot_save_png(cube, target, **kwargs): + # A simple wrapper for `iris.fileformats.dot.save_png` which allows the + # saver to be registered without triggering the import of + # `iris.fileformats.dot`. + import iris.fileformats.dot + return iris.fileformats.dot.save_png(cube, target, **kwargs) + + +def _grib_save(cube, target, append=False, **kwargs): + # A simple wrapper for the grib save routine, which allows the saver to be + # registered without having the grib implementation installed. + try: + from iris_grib import save_grib2 + except ImportError: + raise RuntimeError('Unable to save GRIB file - ' + '"iris_grib" package is not installed.') + + save_grib2(cube, target, append, **kwargs) + + def _check_init_savers(): # TODO: Raise a ticket to resolve the cyclic import error that requires # us to initialise this on first use. Probably merge io and fileformats. if "pp" not in _savers: _savers.update({"pp": iris.fileformats.pp.save, "nc": iris.fileformats.netcdf.save, - "dot": iris.fileformats.dot.save, - "dotpng": iris.fileformats.dot.save_png, - "grib2": iris.fileformats.grib.save_grib2}) + "dot": _dot_save, + "dotpng": _dot_save_png, + "grib2": _grib_save}) def add_saver(file_extension, new_saver): @@ -279,9 +328,9 @@ def save(source, target, saver=None, **kwargs): * netCDF - the Unidata network Common Data Format: * see :func:`iris.fileformats.netcdf.save` - * GRIB2 - the WMO GRIdded Binary data format; - * see :func:`iris.fileformats.grib.save_grib2` - * PP - the Met Office UM Post Processing Format. + * GRIB2 - the WMO GRIdded Binary data format: + * see :func:`iris_grib.save_grib2`. + * PP - the Met Office UM Post Processing Format: * see :func:`iris.fileformats.pp.save` A custom saver can be provided to the function to write to a different @@ -297,11 +346,12 @@ def save(source, target, saver=None, **kwargs): Kwargs: - * saver - Optional. Specifies the save function to use. + * saver - Optional. Specifies the file format to save. If omitted, Iris will attempt to determine the format. - This keyword can be used to implement a custom save - format. Function form must be: + If a string, this is the recognised filename extension + (where the actual filename may not have it). + Otherwise the value is a saver function, of the form: ``my_saver(cube, target)`` plus any custom keywords. It is assumed that a saver will accept an ``append`` keyword if it's file format can handle multiple cubes. See also @@ -322,16 +372,33 @@ def save(source, target, saver=None, **kwargs): # Save a cube to netCDF, defaults to NETCDF4 file format iris.save(my_cube, "myfile.nc") - # Save a cube list to netCDF, using the NETCDF4_CLASSIC storage option + # Save a cube list to netCDF, using the NETCDF3_CLASSIC storage option iris.save(my_cube_list, "myfile.nc", netcdf_format="NETCDF3_CLASSIC") + .. warning:: + + Saving a cube whose data has been loaded lazily + (if `cube.has_lazy_data()` returns `True`) to the same file it expects + to load data from will cause both the data in-memory and the data on + disk to be lost. + + .. code-block:: python + + cube = iris.load_cube('somefile.nc') + # The next line causes data loss in 'somefile.nc' and the cube. + iris.save(cube, 'somefile.nc') + + In general, overwriting a file which is the source for any lazily loaded + data can result in corruption. Users should proceed with caution when + attempting to overwrite an existing file. + """ # Determine format from filename - if isinstance(target, basestring) and saver is None: + if isinstance(target, six.string_types) and saver is None: saver = find_saver(target) - elif isinstance(target, types.FileType) and saver is None: + elif hasattr(target, 'name') and saver is None: saver = find_saver(target.name) - elif isinstance(saver, basestring): + elif isinstance(saver, six.string_types): saver = find_saver(saver) if saver is None: raise ValueError("Cannot save; no saver") @@ -343,7 +410,7 @@ def save(source, target, saver=None, **kwargs): # CubeList or sequence of cubes? elif (isinstance(source, iris.cube.CubeList) or (isinstance(source, (list, tuple)) and - all([type(i) == iris.cube.Cube for i in source]))): + all([isinstance(i, iris.cube.Cube) for i in source]))): # Only allow cubelist saving for those fileformats that are capable. if not 'iris.fileformats.netcdf' in saver.__module__: # Make sure the saver accepts an append keyword diff --git a/lib/iris/io/format_picker.py b/lib/iris/io/format_picker.py index e5f169cc88..1eafcefe1b 100644 --- a/lib/iris/io/format_picker.py +++ b/lib/iris/io/format_picker.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -33,7 +33,8 @@ To identify a specific format from a file:: - handling_spec = fagent.get_spec(png_filename, open(png_filename, 'rb')) + with open(png_filename, 'rb') as png_fh: + handling_spec = fagent.get_spec(png_filename, png_fh) In the example, handling_spec will now be the png_spec previously added to the agent. @@ -49,7 +50,13 @@ """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + import collections +import functools import os import struct @@ -135,7 +142,7 @@ def get_spec(self, basename, buffer_obj): return format_spec printable_values = {} - for key, value in element_cache.iteritems(): + for key, value in six.iteritems(element_cache): value = str(value) if len(value) > 50: value = value[:50] + '...' @@ -145,6 +152,7 @@ def get_spec(self, basename, buffer_obj): raise ValueError(msg) +@functools.total_ordering class FormatSpecification(object): """ Provides the base class for file type definition. @@ -153,7 +161,8 @@ class FormatSpecification(object): a FileElement, such as filename extension or 32-bit magic number, with an associated value for format identification. """ - def __init__(self, format_name, file_element, file_element_value, handler=None, priority=0): + def __init__(self, format_name, file_element, file_element_value, + handler=None, priority=0, constraint_aware_handler=False): """ Constructs a new FormatSpecification given the format_name and particular FileElements @@ -179,6 +188,7 @@ def __init__(self, format_name, file_element, file_element_value, handler=None, self._format_name = format_name self._handler = handler self.priority = priority + self.constraint_aware_handler = constraint_aware_handler def __hash__(self): # Hashed by specification for consistent ordering in FormatAgent (including self._handler in this hash @@ -203,11 +213,23 @@ def handler(self): """The handler function of this FileFormat. (Read only)""" return self._handler - def __cmp__(self, other): + def _sort_key(self): + return (-self.priority, self.name, self.file_element) + + def __lt__(self, other): + if not isinstance(other, FormatSpecification): + return NotImplemented + + return self._sort_key() < other._sort_key() + + def __eq__(self, other): if not isinstance(other, FormatSpecification): return NotImplemented - return cmp( (-self.priority, hash(self)), (-other.priority, hash(other)) ) + return self._sort_key() == other._sort_key() + + def __ne__(self, other): + return not (self == other) def __repr__(self): # N.B. loader is not always going to provide a nice repr if it is a lambda function, hence a prettier version is available in __str__ diff --git a/lib/iris/iterate.py b/lib/iris/iterate.py index 6f03e6f54f..9828d8670d 100644 --- a/lib/iris/iterate.py +++ b/lib/iris/iterate.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -19,6 +19,9 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + import collections import itertools import warnings @@ -93,7 +96,7 @@ def izip(*cubes, **kwargs): # For each input cube, generate the union of all describing dimensions for # the resulting subcube. requested_dims_by_cube = [] - for coords, cube in itertools.izip(coords_by_cube, cubes): + for coords, cube in zip(coords_by_cube, cubes): requested_dims = set() for coord in coords: requested_dims.update(cube.coord_dims(coord)) @@ -113,10 +116,10 @@ def izip(*cubes, **kwargs): # dimensioned coordinates that will be iterated over (i.e exclude slice # coords). dimensioned_iter_coords_by_cube = [] - for requested_dims, cube in itertools.izip(requested_dims_by_cube, cubes): + for requested_dims, cube in zip(requested_dims_by_cube, cubes): dimensioned_iter_coords = set() # Loop over dimensioned coords in each cube. - for dim in xrange(len(cube.shape)): + for dim in range(len(cube.shape)): if dim not in requested_dims: dimensioned_iter_coords.update( cube.coords(contains_dimension=dim)) @@ -146,10 +149,10 @@ def izip(*cubes, **kwargs): for definition_coord in common: # Extract matching coord from dimensioned_iter_coords_a and # dimensioned_iter_coords_b to access shape. - coord_a = (coord for coord in dimensioned_iter_coords_a if - definition_coord == coord).next() - coord_b = (coord for coord in dimensioned_iter_coords_b if - definition_coord == coord).next() + coord_a = next(coord for coord in dimensioned_iter_coords_a if + definition_coord == coord) + coord_b = next(coord for coord in dimensioned_iter_coords_b if + definition_coord == coord) if coord_a.shape != coord_b.shape: raise ValueError("Shape of common dimensioned coordinate '%s' " "does not match across all cubes. Unable " @@ -193,8 +196,7 @@ def __init__(self, cubes, requested_dims_by_cube, ordered, coords_by_cube): master_dimensioned_coord_list = [] master_dims_index = [] self._offsets_by_cube = [] - for requested_dims, cube in itertools.izip(requested_dims_by_cube, - cubes): + for requested_dims, cube in zip(requested_dims_by_cube, cubes): # Create a list of the shape of each cube, and set the dimensions # which have been requested to length 1. dims_index = list(cube.shape) @@ -202,7 +204,7 @@ def __init__(self, cubes, requested_dims_by_cube, ordered, coords_by_cube): dims_index[dim] = 1 offsets = [] # Loop over dimensions in each cube. - for i in xrange(len(cube.shape)): + for i in range(len(cube.shape)): # Obtain the coordinates for this dimension. cube_coords = cube.coords(dimensions=i) found = False @@ -240,12 +242,12 @@ def __init__(self, cubes, requested_dims_by_cube, ordered, coords_by_cube): # (1, 0, 1), (1, 0, 2)] self._ndindex = np.ndindex(*master_dims_index) - def next(self): + def __next__(self): # When self._ndindex runs out it will raise StopIteration for us. - master_index_tuple = self._ndindex.next() + master_index_tuple = next(self._ndindex) subcubes = [] - for offsets, requested_dims, coords, cube in itertools.izip( + for offsets, requested_dims, coords, cube in zip( self._offsets_by_cube, self._requested_dims_by_cube, self._coords_by_cube, self._cubes): # Extract the index_list for each cube from the master index using @@ -263,14 +265,16 @@ def next(self): transpose_order = [] for coord in coords: transpose_order += sorted(subcube.coord_dims(coord)) - if transpose_order != range(subcube.ndim): + if transpose_order != list(range(subcube.ndim)): subcube.transpose(transpose_order) subcubes.append(subcube) return tuple(subcubes) + next = __next__ + -class _CoordWrapper: +class _CoordWrapper(object): """ Class for creating a coordinate wrapper that allows the use of an alternative equality function based on metadata rather than diff --git a/lib/iris/palette.py b/lib/iris/palette.py index b2d7fad32f..84fd665eab 100644 --- a/lib/iris/palette.py +++ b/lib/iris/palette.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -20,24 +20,26 @@ """ -from __future__ import with_statement +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six from functools import wraps import os import os.path import re +import cf_units import matplotlib.cm as mpl_cm import matplotlib.colors as mpl_colors import numpy as np import iris.cube import iris.config -import iris.unit # Symmetric normalization function pivot points by SI unit. -PIVOT_BY_UNIT = {iris.unit.Unit('K'): 273.15} +PIVOT_BY_UNIT = {cf_units.Unit('K'): 273.15} # Color map names by palette file metadata field value. CMAP_BREWER = set() @@ -99,7 +101,7 @@ def _default_cmap_norm(args, kwargs): if len(cmaps) == 0: # Check for a fuzzy match against a keyword. - for keyword in _CMAP_BY_KEYWORD.iterkeys(): + for keyword in six.iterkeys(_CMAP_BY_KEYWORD): if keyword in std_name: cmaps.update(_CMAP_BY_KEYWORD[keyword]) diff --git a/lib/iris/pandas.py b/lib/iris/pandas.py index 01582df36a..798e034017 100644 --- a/lib/iris/pandas.py +++ b/lib/iris/pandas.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office +# (C) British Crown Copyright 2013 - 2018, Met Office # # This file is part of Iris. # @@ -20,18 +20,26 @@ See also: http://pandas.pydata.org/ """ -from __future__ import absolute_import + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa import datetime -import netcdftime +import cf_units +from cf_units import Unit +import cftime import numpy as np +import numpy.ma as ma import pandas +try: + from pandas.core.indexes.datetimes import DatetimeIndex # pandas >=0.20 +except ImportError: + from pandas.tseries.index import DatetimeIndex # pandas <0.20 import iris from iris.coords import AuxCoord, DimCoord from iris.cube import Cube -from iris.unit import Unit def _add_iris_coord(cube, name, points, dim, calendar=None): @@ -43,15 +51,15 @@ def _add_iris_coord(cube, name, points, dim, calendar=None): """ units = Unit("unknown") if calendar is None: - calendar = iris.unit.CALENDAR_GREGORIAN + calendar = cf_units.CALENDAR_GREGORIAN # Convert pandas datetime objects to python datetime obejcts. - if isinstance(points, pandas.tseries.index.DatetimeIndex): - points = np.array([i.to_datetime() for i in points]) + if isinstance(points, DatetimeIndex): + points = np.array([i.to_pydatetime() for i in points]) # Convert datetime objects to Iris' current datetime representation. if points.dtype == object: - dt_types = (datetime.datetime, netcdftime.datetime) + dt_types = (datetime.datetime, cftime.datetime) if all([isinstance(i, dt_types) for i in points]): units = Unit("hours since epoch", calendar=calendar) points = units.date2num(points) @@ -86,8 +94,8 @@ def as_cube(pandas_array, copy=True, calendars=None): Example usage:: - as_cube(series, calendars={0: iris.unit.CALENDAR_360_DAY}) - as_cube(data_frame, calendars={1: iris.unit.CALENDAR_GREGORIAN}) + as_cube(series, calendars={0: cf_units.CALENDAR_360_DAY}) + as_cube(data_frame, calendars={1: cf_units.CALENDAR_GREGORIAN}) .. note:: This function will copy your data by default. @@ -107,7 +115,7 @@ def as_cube(pandas_array, copy=True, calendars=None): _add_iris_coord(cube, "index", pandas_array.index, 0, calendars.get(0, None)) if pandas_array.ndim == 2: - _add_iris_coord(cube, "columns", pandas_array.columns, 1, + _add_iris_coord(cube, "columns", pandas_array.columns.values, 1, calendars.get(1, None)) return cube @@ -122,19 +130,20 @@ def _as_pandas_coord(coord): def _assert_shared(np_obj, pandas_obj): """Ensure the pandas object shares memory.""" - if hasattr(pandas_obj, 'base'): - base = pandas_obj.base - else: - base = pandas_obj[0].base - # Chase the stack of NumPy `base` references back to see if any of - # them are our original array. - while base is not None: - if base is np_obj: - return - # Take the next step up the stack of `base` references. - base = base.base - msg = 'Pandas {} does not share memory'.format(type(pandas_obj).__name__) - raise AssertionError(msg) + values = pandas_obj.values + + def _get_base(array): + # Chase the stack of NumPy `base` references back to the original array + while array.base is not None: + array = array.base + return array + + base = _get_base(values) + np_base = _get_base(np_obj) + if base is not np_base: + msg = ('Pandas {} does not share memory' + .format(type(pandas_obj).__name__)) + raise AssertionError(msg) def as_series(cube, copy=True): @@ -158,7 +167,7 @@ def as_series(cube, copy=True): """ data = cube.data - if isinstance(data, np.ma.MaskedArray): + if ma.isMaskedArray(data): if not copy: raise ValueError("Masked arrays must always be copied.") data = data.astype('f').filled(np.nan) @@ -204,7 +213,7 @@ def as_data_frame(cube, copy=True): """ data = cube.data - if isinstance(data, np.ma.MaskedArray): + if ma.isMaskedArray(data): if not copy: raise ValueError("Masked arrays must always be copied.") data = data.astype('f').filled(np.nan) diff --git a/lib/iris/plot.py b/lib/iris/plot.py index 25bf417de6..88f89cc79a 100644 --- a/lib/iris/plot.py +++ b/lib/iris/plot.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -22,71 +22,96 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + import collections import datetime -import functools -import warnings +import cartopy.crs as ccrs +import cartopy.mpl.geoaxes +from cartopy.geodesic import Geodesic +import cftime import matplotlib.axes import matplotlib.collections as mpl_collections import matplotlib.dates as mpl_dates -import matplotlib.transforms as mpl_transforms import matplotlib.pyplot as plt -from mpl_toolkits.axes_grid.anchored_artists import AnchoredText +from matplotlib.offsetbox import AnchoredText +import matplotlib.ticker as mpl_ticker +import matplotlib.transforms as mpl_transforms import numpy as np import numpy.ma as ma -import cartopy.crs -import cartopy.mpl.geoaxes - import iris.cube -import iris.coord_systems import iris.analysis.cartography as cartography import iris.coords +import iris.coord_systems +from iris.exceptions import IrisError +# Importing iris.palette to register the brewer palettes. import iris.palette -import iris.unit - +from iris.util import _meshgrid # Cynthia Brewer citation text. BREWER_CITE = 'Colours based on ColorBrewer.org' - PlotDefn = collections.namedtuple('PlotDefn', ('coords', 'transpose')) def _get_plot_defn_custom_coords_picked(cube, coords, mode, ndims=2): + def names(coords): + result = [] + for coord in coords: + if isinstance(coord, int): + result.append('dim={}'.format(coord)) + else: + result.append(coord.name()) + return ', '.join(result) + def as_coord(coord): - coord = cube.coord(coord) + if isinstance(coord, int): + # Pass through valid dimension indexes. + if coord >= ndims: + emsg = ('The data dimension ({}) is out of range for ' + 'the dimensionality of the required plot ({})') + raise IndexError(emsg.format(coord, ndims)) + else: + coord = cube.coord(coord) return coord - coords = map(as_coord, coords) - # Check that we were given the right number of coordinates + coords = list(map(as_coord, coords)) + + # Check that we were given the right number of coordinates/dimensions. if len(coords) != ndims: - coord_names = ', '.join([coord.name() for coord in coords]) raise ValueError('The list of coordinates given (%s) should have the' ' same length (%s) as the dimensionality of the' - ' required plot (%s)' % (coord_names, + ' required plot (%s)' % (names(coords), len(coords), ndims)) # Check which dimensions are spanned by each coordinate. - get_span = lambda coord: set(cube.coord_dims(coord)) - spans = map(get_span, coords) + def get_span(coord): + if isinstance(coord, int): + span = set([coord]) + else: + span = set(cube.coord_dims(coord)) + return span + + spans = list(map(get_span, coords)) for span, coord in zip(spans, coords): if not span: msg = 'The coordinate {!r} doesn\'t span a data dimension.' raise ValueError(msg.format(coord.name())) - if mode == iris.coords.BOUND_MODE and len(span) != 1: - raise ValueError('The coordinate {!r} is multi-dimensional and' - ' cannot be used in a cell-based plot.' - .format(coord.name())) + if mode == iris.coords.BOUND_MODE and len(span) not in [1, 2]: + raise ValueError('The coordinate {!r} has {} dimensions.' + 'Cell-based plotting is only supported for' + 'coordinates with one or two dimensions.' + .format(coord.name(), len(span))) # Check the combination of coordinates spans enough (ndims) data # dimensions. total_span = set().union(*spans) if len(total_span) != ndims: - coord_names = ', '.join([coord.name() for coord in coords]) raise ValueError('The given coordinates ({}) don\'t span the {} data' - ' dimensions.'.format(coord_names, ndims)) + ' dimensions.'.format(names(coords), ndims)) # If we have 2-dimensional data, and one or more 1-dimensional # coordinates, check if we need to transpose. @@ -105,7 +130,7 @@ def as_coord(coord): return PlotDefn(plot_coords, transpose) -def _valid_bound_coord(coord): +def _valid_bound_dim_coord(coord): result = None if coord and coord.ndim == 1 and coord.nbounds: result = coord @@ -130,7 +155,7 @@ def _get_plot_defn(cube, mode, ndims=2): # When appropriate, restrict to 1D with bounds. if mode == iris.coords.BOUND_MODE: - coords = map(_valid_bound_coord, coords) + coords = list(map(_valid_bound_dim_coord, coords)) def guess_axis(coord): axis = None @@ -142,20 +167,31 @@ def guess_axis(coord): for dim, coord in enumerate(coords): if coord is None: aux_coords = cube.coords(dimensions=dim) - aux_coords = filter(lambda coord: - isinstance(coord, iris.coords.DimCoord), - aux_coords) + aux_coords = [coord for coord in aux_coords + if isinstance(coord, iris.coords.DimCoord)] if aux_coords: - key_func = lambda coord: coord._as_defn() - aux_coords.sort(key=key_func) + aux_coords.sort(key=lambda coord: coord._as_defn()) coords[dim] = aux_coords[0] + # If plotting a 2 dimensional plot, check for 2d coordinates + if ndims == 2: + missing_dims = [dim for dim, coord in enumerate(coords) if + coord is None] + if missing_dims: + # Note that this only picks up coordinates that span the dims + two_dim_coords = cube.coords(dimensions=missing_dims) + two_dim_coords = [coord for coord in two_dim_coords + if coord.ndim == 2] + if len(two_dim_coords) >= 2: + two_dim_coords.sort(key=lambda coord: coord._as_defn()) + coords = two_dim_coords[:2] + if mode == iris.coords.POINT_MODE: # Allow multi-dimensional aux_coords to override the dim_coords # along the Z axis. This results in a preference for using the # derived altitude over model_level_number or level_height. # Limit to Z axis to avoid preferring latitude over grid_latitude etc. - axes = map(guess_axis, coords) + axes = list(map(guess_axis, coords)) axis = 'Z' if axis in axes: for coord in cube.coords(dim_coords=False): @@ -164,19 +200,25 @@ def guess_axis(coord): coords[axes.index(axis)] = coord # Re-order the coordinates to achieve the preferred - # horizontal/vertical associations. + # horizontal/vertical associations. If we can't associate + # an axis to order the coordinates, fall back to using the cube dimension + # followed by the name of the coordinate. def sort_key(coord): order = {'X': 2, 'T': 1, 'Y': -1, 'Z': -2} axis = guess_axis(coord) - return (order.get(axis, 0), coord and coord.name()) + return (order.get(axis, 0), + coords.index(coord), + coord and coord.name()) + sorted_coords = sorted(coords, key=sort_key) transpose = (sorted_coords != coords) return PlotDefn(sorted_coords, transpose) -def _can_draw_map(plot_coords): - std_names = [coord and coord.standard_name for coord in plot_coords] +def _can_draw_map(coords): + std_names = [c and c.standard_name for c in coords + if isinstance(c, iris.coords.Coord)] valid_std_names = [ ['latitude', 'longitude'], ['grid_latitude', 'grid_longitude'], @@ -195,7 +237,19 @@ def _broadcast_2d(u, v): return u, v -def _invert_yaxis(v_coord): +def _string_coord_axis_tick_labels(string_axes, axes=None): + """Apply tick labels for string coordinates.""" + + ax = axes if axes else plt.gca() + for axis, ticks in string_axes.items(): + formatter = mpl_ticker.IndexFormatter(ticks) + locator = mpl_ticker.MaxNLocator(integer=True) + this_axis = getattr(ax, axis) + this_axis.set_major_formatter(formatter) + this_axis.set_major_locator(locator) + + +def _invert_yaxis(v_coord, axes=None): """ Inverts the y-axis of the current plot based on conditions: @@ -209,11 +263,101 @@ def _invert_yaxis(v_coord): * v_coord - the coord to be plotted on the y-axis """ - yaxis_is_inverted = plt.gca().yaxis_inverted() - if not yaxis_is_inverted and v_coord is not None: + axes = axes if axes else plt.gca() + yaxis_is_inverted = axes.yaxis_inverted() + if not yaxis_is_inverted and isinstance(v_coord, iris.coords.Coord): attr_pve = v_coord.attributes.get('positive') if attr_pve is not None and attr_pve.lower() == 'down': - plt.gca().invert_yaxis() + axes.invert_yaxis() + + +def _check_bounds_contiguity_and_mask(coord, data, atol=None, rtol=None): + """ + Checks that any discontiguities in the bounds of the given coordinate only + occur where the data is masked. + + Where a discontinuity occurs the grid created for plotting will not be + correct. This does not matter if the data is masked in that location as + this is not plotted. + + If a discontiguity occurs where the data is *not* masked, an error is + raised. + + Args: + coord: (iris.coord.Coord) + Coordinate the bounds of which will be checked for contiguity + data: (array) + Data of the the cube we are plotting + atol: + Absolute tolerance when checking the contiguity. Defaults to None. + If an absolute tolerance is not set, 1D coords are not checked (so + as to not introduce a breaking change without a major release) but + 2D coords are always checked, by calling + :meth:`iris.coords.Coord._discontiguity_in_bounds` with its default + tolerance. + + """ + kwargs = {} + data_is_masked = hasattr(data, 'mask') + if data_is_masked: + # When checking the location of the discontiguities, we check against + # the opposite of the mask, which is True where data exists. + mask_invert = np.logical_not(data.mask) + + if coord.ndim == 1: + # 1D coords are only checked if an absolute tolerance is set, to avoid + # introducing a breaking change. + if atol: + contiguous, diffs = coord._discontiguity_in_bounds(atol=atol) + + if not contiguous and data_is_masked: + not_masked_at_discontiguity = np.any( + np.logical_and(mask_invert[:-1], diffs)) + else: + return + + elif coord.ndim == 2: + if atol: + kwargs['atol'] = atol + if rtol: + kwargs['rtol'] = rtol + contiguous, diffs = coord._discontiguity_in_bounds(**kwargs) + + if not contiguous and data_is_masked: + diffs_along_x, diffs_along_y = diffs + + # Check along both dimensions that any discontiguous + # points are correctly masked. + not_masked_at_discontiguity_along_x = np.any( + np.logical_and(mask_invert[:, :-1], diffs_along_x)) + + not_masked_at_discontiguity_along_y = np.any( + np.logical_and(mask_invert[:-1, ], diffs_along_y)) + + not_masked_at_discontiguity = not_masked_at_discontiguity_along_x \ + or not_masked_at_discontiguity_along_y + + # If any discontiguity occurs where the data is not masked the grid will be + # created incorrectly, so raise an error. + if not contiguous: + if not data_is_masked: + raise ValueError('The bounds of the {} coordinate are not ' + 'contiguous. Not able to create a suitable grid' + 'to plot. You can use ' + 'iris.util.find_discontiguities() to identify ' + 'discontiguities in your x and y coordinate ' + 'bounds arrays.'.format(coord.name())) + if not_masked_at_discontiguity: + raise ValueError('The bounds of the {} coordinate are not ' + 'contiguous and data is not masked where the ' + 'discontiguity occurs. Not able to create a ' + 'suitable grid to plot. You can use ' + 'iris.util.find_discontiguities() to identify ' + 'discontiguities in your x and y coordinate ' + 'bounds arrays, and then mask them with ' + 'iris.util.mask_cube()' + ''.format( + coord.name())) def _draw_2d_from_bounds(draw_method_name, cube, *args, **kwargs): @@ -223,10 +367,18 @@ def _draw_2d_from_bounds(draw_method_name, cube, *args, **kwargs): # Get & remove the coords entry from kwargs. coords = kwargs.pop('coords', None) if coords is not None: - plot_defn = _get_plot_defn_custom_coords_picked(cube, coords, mode) + plot_defn = _get_plot_defn_custom_coords_picked(cube, coords, mode, + ndims=2) else: plot_defn = _get_plot_defn(cube, mode, ndims=2) + contig_tol = kwargs.pop('contiguity_tolerance', None) + + for coord in plot_defn.coords: + if hasattr(coord, 'has_bounds') and coord.has_bounds(): + _check_bounds_contiguity_and_mask(coord, data=cube.data, + atol=contig_tol) + if _can_draw_map(plot_defn.coords): result = _map_common(draw_method_name, None, iris.coords.BOUND_MODE, cube, plot_defn, *args, **kwargs) @@ -239,26 +391,54 @@ def _draw_2d_from_bounds(draw_method_name, cube, *args, **kwargs): # Obtain U and V coordinates v_coord, u_coord = plot_defn.coords - # XXX: Watch out for non-contiguous bounds. - if u_coord: - u = u_coord.contiguous_bounds() - else: - u = np.arange(data.shape[1] + 1) - if v_coord: - v = v_coord.contiguous_bounds() - else: - v = np.arange(data.shape[0] + 1) - - if plot_defn.transpose: - u = u.T - v = v.T - - u, v = _broadcast_2d(u, v) - draw_method = getattr(plt, draw_method_name) + # Track numpy arrays to use for the actual plotting. + plot_arrays = [] + + # Map axis name to associated values. + string_axes = {} + + for coord, axis_name, data_dim in zip([u_coord, v_coord], + ['xaxis', 'yaxis'], + [1, 0]): + if coord is None: + values = np.arange(data.shape[data_dim] + 1) + elif isinstance(coord, int): + dim = 1 - coord if plot_defn.transpose else coord + values = np.arange(data.shape[dim] + 1) + else: + if coord.points.dtype.char in 'SU': + if coord.points.ndim != 1: + msg = 'Coord {!r} must be one-dimensional.' + raise ValueError(msg.format(coord)) + if coord.bounds is not None: + msg = 'Cannot plot bounded string coordinate.' + raise ValueError(msg) + string_axes[axis_name] = coord.points + values = np.arange(data.shape[data_dim] + 1) - 0.5 + else: + values = coord.contiguous_bounds() + + plot_arrays.append(values) + + u, v = plot_arrays + + # If the data is transposed, 2D coordinates will also need to be + # transposed. + if plot_defn.transpose is True: + u, v = [coord.T if coord.ndim == 2 else coord for coord in [u, v]] + + if u.ndim == v.ndim == 1: + u, v = _broadcast_2d(u, v) + + axes = kwargs.pop('axes', None) + draw_method = getattr(axes if axes else plt, draw_method_name) result = draw_method(u, v, data, *args, **kwargs) + # Apply tick labels for string coordinates. + _string_coord_axis_tick_labels(string_axes, axes) + # Invert y-axis if necessary. - _invert_yaxis(v_coord) + _invert_yaxis(v_coord, axes) return result @@ -283,49 +463,99 @@ def _draw_2d_from_points(draw_method_name, arg_func, cube, *args, **kwargs): data = cube.data if plot_defn.transpose: data = data.T + # Also transpose the scatter marker color array, + # as now mpl 2.x does not do this for free. + if draw_method_name == 'scatter' and 'c' in kwargs: + c = kwargs['c'] + if hasattr(c, 'T') and cube.data.shape == c.shape: + kwargs['c'] = c.T # Obtain U and V coordinates v_coord, u_coord = plot_defn.coords - if u_coord: + if u_coord is None: + u = np.arange(data.shape[1]) + elif isinstance(u_coord, int): + dim = 1 - u_coord if plot_defn.transpose else u_coord + u = np.arange(data.shape[dim]) + else: u = u_coord.points u = _fixup_dates(u_coord, u) + + if v_coord is None: + v = np.arange(data.shape[0]) + elif isinstance(v_coord, int): + dim = 1 - v_coord if plot_defn.transpose else v_coord + v = np.arange(data.shape[dim]) else: - u = np.arange(data.shape[1]) - if v_coord: v = v_coord.points v = _fixup_dates(v_coord, v) - else: - v = np.arange(data.shape[0]) if plot_defn.transpose: u = u.T v = v.T - if u.dtype == np.dtype(object) and isinstance(u[0], datetime.datetime): - u = mpl_dates.date2num(u) - - if v.dtype == np.dtype(object) and isinstance(v[0], datetime.datetime): - v = mpl_dates.date2num(v) - + # Track numpy arrays to use for the actual plotting. + plot_arrays = [] + + # Map axis name to associated values. + string_axes = {} + + for values, axis_name in zip([u, v], ['xaxis', 'yaxis']): + # Replace any string coordinates with "index" coordinates. + if values.dtype.char in 'SU': + if values.ndim != 1: + raise ValueError('Multi-dimensional string coordinates ' + 'not supported.') + plot_arrays.append(np.arange(values.size)) + string_axes[axis_name] = values + elif (values.dtype == np.dtype(object) and + isinstance(values[0], datetime.datetime)): + plot_arrays.append(mpl_dates.date2num(values)) + else: + plot_arrays.append(values) + + u, v = plot_arrays u, v = _broadcast_2d(u, v) - draw_method = getattr(plt, draw_method_name) + axes = kwargs.pop('axes', None) + draw_method = getattr(axes if axes else plt, draw_method_name) if arg_func is not None: args, kwargs = arg_func(u, v, data, *args, **kwargs) result = draw_method(*args, **kwargs) else: result = draw_method(u, v, data, *args, **kwargs) + # Apply tick labels for string coordinates. + _string_coord_axis_tick_labels(string_axes, axes) + # Invert y-axis if necessary. - _invert_yaxis(v_coord) + _invert_yaxis(v_coord, axes) return result def _fixup_dates(coord, values): if coord.units.calendar is not None and values.ndim == 1: - r = [datetime.datetime(*(coord.units.num2date(val).timetuple()[0:6])) - for val in values] + # Convert coordinate values into tuples of + # (year, month, day, hour, min, sec) + dates = [coord.units.num2date(val).timetuple()[0:6] + for val in values] + if coord.units.calendar == 'gregorian': + r = [datetime.datetime(*date) for date in dates] + else: + try: + import nc_time_axis + except ImportError: + msg = ('Cannot plot against time in a non-gregorian ' + 'calendar, because "nc_time_axis" is not available : ' + 'Install the package from ' + 'https://github.com/SciTools/nc-time-axis to enable ' + 'this usage.') + raise IrisError(msg) + + r = [nc_time_axis.CalendarDateTime( + cftime.datetime(*date), coord.units.calendar) + for date in dates] values = np.empty(len(r), dtype=object) values[:] = r return values @@ -347,7 +577,6 @@ def _uv_from_u_object_v_object(u_object, v_object): raise ValueError(ndim_msg.format(u_object.ndim)) if v_object.ndim > 1: raise ValueError(ndim_msg.format(v_object.ndim)) - type_msg = 'Plot arguments must be cubes or coordinates.' v = _data_from_coord_or_cube(v_object) if u_object is None: u = np.arange(v.shape[0]) @@ -369,7 +598,7 @@ def _get_plot_objects(args): (iris.cube.Cube, iris.coords.Coord)): # two arguments u_object, v_object = args[:2] - u, v = _uv_from_u_object_v_object(*args[:2]) + u, v = _uv_from_u_object_v_object(u_object, v_object) args = args[2:] if len(u) != len(v): msg = "The x and y-axis objects are not compatible. They should " \ @@ -385,6 +614,79 @@ def _get_plot_objects(args): return u_object, v_object, u, v, args +def _get_geodesic_params(globe): + # Derive the semimajor axis and flattening values for a given globe from + # its attributes. If the values are under specified, raise a ValueError + flattening = globe.flattening + semimajor = globe.semimajor_axis + try: + if semimajor is None: + # Has semiminor or raises error + if flattening is None: + # Has inverse flattening or raises error + flattening = 1. / globe.inverse_flattening + semimajor = globe.semiminor_axis / (1. - flattening) + elif flattening is None: + if globe.semiminor_axis is not None: + flattening = ((semimajor - globe.semiminor_axis) / + float(semimajor)) + else: + # Has inverse flattening or raises error + flattening = 1. / globe.inverse_flattening + except TypeError: + # One of the required attributes was None + raise ValueError('The globe was underspecified.') + + return semimajor, flattening + + +def _shift_plot_sections(u_object, u, v): + """ + Shifts subsections of u by multiples of 360 degrees within ranges + defined by the points where the line should cross over the 0/360 degree + longitude boundary. + + e.g. [ 300, 100, 200, 300, 100, 300 ] => [ 300, 460, 560, 660, 820, 660 ] + + """ + # Convert coordinates to true lat-lon + src_crs = u_object.coord_system.as_cartopy_crs() \ + if u_object.coord_system is not None else ccrs.Geodetic() + tgt_crs = ccrs.Geodetic(globe=src_crs.globe) + tgt_proj = ccrs.PlateCarree(globe=src_crs.globe) + + points = tgt_crs.transform_points(src_crs, u, v) + startpoints = points[:-1, :2] + endpoints = points[1:, :2] + proj_x, proj_y, _ = tgt_proj.transform_points(src_crs, u, v).T + + # Calculate the inverse geodesic for each pair of points in turn, and + # convert the start point's azimuth into a vector in the source coordinate + # system. + try: + radius, flattening = _get_geodesic_params(src_crs.globe) + geodesic = Geodesic(radius, flattening) + except ValueError: + geodesic = Geodesic() + dists, azms, _ = geodesic.inverse(startpoints, endpoints).T + azms_lon = np.sin(np.deg2rad(azms)) + azms_lat = np.cos(np.deg2rad(azms)) + azms_u, _ = src_crs.transform_vectors(tgt_proj, proj_x[:-1], proj_y[:-1], + azms_lon, azms_lat) + + # Use the grid longitude values and the geodesic azimuth to determine + # the points where the line should cross the 0/360 degree boundary, and + # in which direction + lwraps = np.logical_and(u[1:] > u[:-1], azms_u < 0) + rwraps = np.logical_and(u[1:] < u[:-1], azms_u > 0) + shifts = np.where(rwraps, 1, 0) - np.where(lwraps, 1, 0) + shift_vals = shifts.cumsum() * u_object.units.modulus + new_u = np.empty_like(u) + new_u[0] = u[0] + new_u[1:] = u[1:] + shift_vals + return new_u + + def _draw_1d_from_points(draw_method_name, arg_func, *args, **kwargs): # NB. In the interests of clarity we use "u" to refer to the horizontal # axes on the matplotlib plot and "v" for the vertical axes. @@ -394,6 +696,25 @@ def _draw_1d_from_points(draw_method_name, arg_func, *args, **kwargs): # argument tuple with these objects removed u_object, v_object, u, v, args = _get_plot_objects(args) + # Track numpy arrays to use for the actual plotting. + plot_arrays = [] + + # Map axis name to associated values. + string_axes = {} + + for values, axis_name in zip([u, v], ['xaxis', 'yaxis']): + # Replace any string coordinates with "index" coordinates. + if values.dtype.char in 'SU': + if values.ndim != 1: + msg = 'Multi-dimensional string coordinates are not supported.' + raise ValueError(msg) + plot_arrays.append(np.arange(values.size)) + string_axes[axis_name] = values + else: + plot_arrays.append(values) + + u, v = plot_arrays + # if both u_object and v_object are coordinates then check if a map # should be drawn if isinstance(u_object, iris.coords.Coord) and \ @@ -401,28 +722,38 @@ def _draw_1d_from_points(draw_method_name, arg_func, *args, **kwargs): _can_draw_map([v_object, u_object]): # Replace non-cartopy subplot/axes with a cartopy alternative and set # the transform keyword. - draw_method, kwargs = _geoaxes_draw_method_and_kwargs(u_object, - v_object, - draw_method_name, - kwargs) - else: - # just use a pyplot function to draw - draw_method = getattr(plt, draw_method_name) - + kwargs = _ensure_cartopy_axes_and_determine_kwargs(u_object, v_object, + kwargs) + if draw_method_name == 'plot' and \ + u_object.standard_name not in ('projection_x_coordinate', + 'projection_y_coordinate'): + u = _shift_plot_sections(u_object, u, v) + + axes = kwargs.pop('axes', None) + draw_method = getattr(axes if axes else plt, draw_method_name) if arg_func is not None: args, kwargs = arg_func(u, v, *args, **kwargs) result = draw_method(*args, **kwargs) else: result = draw_method(u, v, *args, **kwargs) + # Apply tick labels for string coordinates. + _string_coord_axis_tick_labels(string_axes, axes) + # Invert y-axis if necessary. _invert_yaxis(v_object) return result -def _get_cartopy_axes(cartopy_proj): - # Replace non-cartopy subplot/axes with a cartopy alternative. +def _replace_axes_with_cartopy_axes(cartopy_proj): + """ + Replace non-cartopy subplot/axes with a cartopy alternative + based on the provided projection. If the current axes are already an + instance of :class:`cartopy.mpl.geoaxes.GeoAxes` then no action is taken. + + """ + ax = plt.gca() if not isinstance(ax, cartopy.mpl.geoaxes.GeoAxes): @@ -441,17 +772,16 @@ def _get_cartopy_axes(cartopy_proj): # delete the axes which didn't have a cartopy projection fig.delaxes(ax) - ax = new_ax - return ax -def _geoaxes_draw_method_and_kwargs(x_coord, y_coord, draw_method_name, - kwargs): +def _ensure_cartopy_axes_and_determine_kwargs(x_coord, y_coord, kwargs): """ - Retrieve a GeoAxes draw method and appropriate keyword arguments for - calling it given the coordinates and existing keywords. + Replace the current non-cartopy axes with :class:`cartopy.mpl.GeoAxes` + and return the appropriate kwargs dict based on the provided coordinates + and kwargs. """ + # Determine projection. if x_coord.coord_system != y_coord.coord_system: raise ValueError('The X and Y coordinates must have equal coordinate' ' systems.') @@ -459,15 +789,36 @@ def _geoaxes_draw_method_and_kwargs(x_coord, y_coord, draw_method_name, if cs is not None: cartopy_proj = cs.as_cartopy_projection() else: - cartopy_proj = cartopy.crs.PlateCarree() - ax = _get_cartopy_axes(cartopy_proj) - draw_method = getattr(ax, draw_method_name) + cartopy_proj = ccrs.PlateCarree() + + # Ensure the current axes are a cartopy.mpl.GeoAxes instance. + axes = kwargs.get('axes') + if axes is None: + if (isinstance(cs, iris.coord_systems.RotatedGeogCS) and + x_coord.points.max() > 180 and x_coord.points.max() < 360 and + x_coord.points.min() > 0): + # The RotatedGeogCS has 0 - 360 extent, different from the + # assumptions made by Cartopy: rebase longitudes for the map axes + # to set the datum longitude to the International Date Line. + cs_kwargs = cs._ccrs_kwargs() + cs_kwargs['central_rotated_longitude'] = 180.0 + adapted_cartopy_proj = ccrs.RotatedPole(**cs_kwargs) + _replace_axes_with_cartopy_axes(adapted_cartopy_proj) + else: + _replace_axes_with_cartopy_axes(cartopy_proj) + elif axes and not isinstance(axes, cartopy.mpl.geoaxes.GeoAxes): + raise TypeError("The supplied axes instance must be a cartopy " + "GeoAxes instance.") + # Set the "from transform" keyword. + if 'transform' in kwargs: + raise ValueError("The 'transform' keyword is not allowed as it " + "automatically determined from the coordinate " + "metadata.") new_kwargs = kwargs.copy() - assert 'transform' not in new_kwargs, 'Transform keyword is not allowed.' new_kwargs['transform'] = cartopy_proj - return draw_method, new_kwargs + return new_kwargs def _map_common(draw_method_name, arg_func, mode, cube, plot_defn, @@ -483,24 +834,29 @@ def _map_common(draw_method_name, arg_func, mode, cube, plot_defn, y_coord, x_coord = plot_defn.coords if mode == iris.coords.POINT_MODE: if x_coord.ndim == y_coord.ndim == 1: - x, y = np.meshgrid(x_coord.points, y_coord.points) + x, y = _meshgrid(x_coord.points, y_coord.points) elif x_coord.ndim == y_coord.ndim == 2: x = x_coord.points y = y_coord.points else: raise ValueError("Expected 1D or 2D XY coords") else: - try: - x, y = np.meshgrid(x_coord.contiguous_bounds(), - y_coord.contiguous_bounds()) - # Exception translation. - except iris.exceptions.CoordinateMultiDimError: - raise ValueError("Could not get XY grid from bounds. " - "X or Y coordinate not 1D.") - except ValueError: - raise ValueError("Could not get XY grid from bounds. " - "X or Y coordinate doesn't have 2 bounds " - "per point.") + if not x_coord.ndim == y_coord.ndim == 2: + try: + x, y = _meshgrid(x_coord.contiguous_bounds(), + y_coord.contiguous_bounds()) + # Exception translation. + except iris.exceptions.CoordinateMultiDimError: + raise ValueError("Expected two 1D coords. Could not get XY" + " grid from bounds. X or Y coordinate not" + " 1D.") + except ValueError: + raise ValueError("Could not get XY grid from bounds. " + "X or Y coordinate doesn't have 2 bounds " + "per point.") + else: + x = x_coord.contiguous_bounds() + y = y_coord.contiguous_bounds() # Obtain the data array. data = cube.data @@ -520,9 +876,8 @@ def _map_common(draw_method_name, arg_func, mode, cube, plot_defn, # Replace non-cartopy subplot/axes with a cartopy alternative and set the # transform keyword. - draw_method, kwargs = _geoaxes_draw_method_and_kwargs(x_coord, y_coord, - draw_method_name, - kwargs) + kwargs = _ensure_cartopy_axes_and_determine_kwargs(x_coord, y_coord, + kwargs) if arg_func is not None: new_args, kwargs = arg_func(x, y, data, *args, **kwargs) @@ -530,7 +885,9 @@ def _map_common(draw_method_name, arg_func, mode, cube, plot_defn, new_args = (x, y, data) + args # Draw the contour lines/filled contours. - return draw_method(*new_args, **kwargs) + axes = kwargs.pop('axes', None) + plotfn = getattr(axes if axes else plt, draw_method_name) + return plotfn(*new_args, **kwargs) def contour(cube, *args, **kwargs): @@ -539,14 +896,18 @@ def contour(cube, *args, **kwargs): Kwargs: - * coords: list of :class:`~iris.coords.Coord` objects or coordinate names - Use the given coordinates as the axes for the plot. The order of the - given coordinates indicates which axis to use for each, where the first - element is the horizontal axis of the plot and the second element is - the vertical axis of the plot. + * coords: list of :class:`~iris.coords.Coord` objects or + coordinate names. Use the given coordinates as the axes for the + plot. The order of the given coordinates indicates which axis + to use for each, where the first element is the horizontal + axis of the plot and the second element is the vertical axis + of the plot. + + * axes: the :class:`matplotlib.axes.Axes` to use for drawing. + Defaults to the current axes if none provided. - See :func:`matplotlib.pyplot.contour` for details of other valid keyword - arguments. + See :func:`matplotlib.pyplot.contour` for details of other valid + keyword arguments. """ result = _draw_2d_from_points('contour', None, cube, *args, **kwargs) @@ -559,14 +920,18 @@ def contourf(cube, *args, **kwargs): Kwargs: - * coords: list of :class:`~iris.coords.Coord` objects or coordinate names - Use the given coordinates as the axes for the plot. The order of the - given coordinates indicates which axis to use for each, where the first - element is the horizontal axis of the plot and the second element is - the vertical axis of the plot. + * coords: list of :class:`~iris.coords.Coord` objects or + coordinate names. Use the given coordinates as the axes for the + plot. The order of the given coordinates indicates which axis + to use for each, where the first element is the horizontal + axis of the plot and the second element is the vertical axis + of the plot. - See :func:`matplotlib.pyplot.contourf` for details of other valid keyword - arguments. + * axes: the :class:`matplotlib.axes.Axes` to use for drawing. + Defaults to the current axes if none provided. + + See :func:`matplotlib.pyplot.contourf` for details of other valid + keyword arguments. """ coords = kwargs.get('coords') @@ -602,8 +967,15 @@ def contourf(cube, *args, **kwargs): # Draw the lines just *below* the polygons to ensure we minimise # any boundary shift. zorder = result.collections[0].zorder - .1 + axes = kwargs.get('axes', None) contour(cube, levels=levels, colors=colors, antialiased=True, - zorder=zorder, coords=coords) + zorder=zorder, coords=coords, axes=axes) + # Restore the current "image" to 'result' rather than the mappable + # resulting from the additional call to contour(). + if axes: + axes._sci(result) + else: + plt.sci(result) return result @@ -668,7 +1040,7 @@ def _fill_orography(cube, coords, mode, vert_plot, horiz_plot, style_args): return result -def orography_at_bounds(cube, facecolor='#888888', coords=None): +def orography_at_bounds(cube, facecolor='#888888', coords=None, axes=None): """Plots orography defined at cell boundaries from the given Cube.""" # XXX Needs contiguous orography corners to work. @@ -683,20 +1055,22 @@ def vert_plot(u_coord, orography, style_args): left = u[:-1] height = orography.points width = u[1:] - left - return plt.bar(left, height, width, **style_args) + plotfn = axes.bar if axes else plt.bar + return plotfn(left, height, width, **style_args) def horiz_plot(v_coord, orography, style_args): v = v_coord.contiguous_bounds() bottom = v[:-1] width = orography.points height = v[1:] - bottom - return plt.barh(bottom, width, height, **style_args) + plotfn = axes.barh if axes else plt.barh + return plotfn(bottom, width, height, **style_args) return _fill_orography(cube, coords, iris.coords.BOUND_MODE, vert_plot, horiz_plot, style_args) -def orography_at_points(cube, facecolor='#888888', coords=None): +def orography_at_points(cube, facecolor='#888888', coords=None, axes=None): """Plots orography defined at sample points from the given Cube.""" style_args = {'facecolor': facecolor} @@ -704,33 +1078,48 @@ def orography_at_points(cube, facecolor='#888888', coords=None): def vert_plot(u_coord, orography, style_args): x = u_coord.points y = orography.points - return plt.fill_between(x, y, **style_args) + plotfn = axes.fill_between if axes else plt.fill_between + return plotfn(x, y, **style_args) def horiz_plot(v_coord, orography, style_args): y = v_coord.points x = orography.points - return plt.fill_betweenx(y, x, **style_args) + plotfn = axes.fill_betweenx if axes else plt.fill_betweenx + return plotfn(y, x, **style_args) return _fill_orography(cube, coords, iris.coords.POINT_MODE, vert_plot, horiz_plot, style_args) -def outline(cube, coords=None): +def outline(cube, coords=None, color='k', linewidth=None, axes=None): """ Draws cell outlines based on the given Cube. Kwargs: - * coords: list of :class:`~iris.coords.Coord` objects or coordinate names - Use the given coordinates as the axes for the plot. The order of the - given coordinates indicates which axis to use for each, where the first - element is the horizontal axis of the plot and the second element is - the vertical axis of the plot. + * coords: list of :class:`~iris.coords.Coord` objects or + coordinate names. Use the given coordinates as the axes for the + plot. The order of the given coordinates indicates which axis + to use for each, where the first element is the horizontal + axis of the plot and the second element is the vertical axis + of the plot. + + * color: None or mpl color The color of the cell outlines. If + None, the matplotlibrc setting patch.edgecolor is used by + default. + + * linewidth: None or number The width of the lines showing the + cell outlines. If None, the default width in patch.linewidth + in matplotlibrc is used. + + * axes: the :class:`matplotlib.axes.Axes` to use for drawing. + Defaults to the current axes if none provided. """ result = _draw_2d_from_bounds('pcolormesh', cube, facecolors='none', - edgecolors='k', antialiased=True, - coords=coords) + edgecolors=color, linewidth=linewidth, + antialiased=True, coords=coords, axes=axes) + # set the _is_stroked property to get a single color grid. # See https://github.com/matplotlib/matplotlib/issues/1302 result._is_stroked = False @@ -741,18 +1130,28 @@ def outline(cube, coords=None): def pcolor(cube, *args, **kwargs): """ - Draws a pseudocolor plot based on the given Cube. + Draws a pseudocolor plot based on the given 2-dimensional Cube. + + The cube must have either two 1-dimensional coordinates or two + 2-dimensional coordinates with contiguous bounds to plot the cube against. Kwargs: - * coords: list of :class:`~iris.coords.Coord` objects or coordinate names - Use the given coordinates as the axes for the plot. The order of the - given coordinates indicates which axis to use for each, where the first - element is the horizontal axis of the plot and the second element is - the vertical axis of the plot. + * coords: list of :class:`~iris.coords.Coord` objects or + coordinate names. Use the given coordinates as the axes for the + plot. The order of the given coordinates indicates which axis + to use for each, where the first element is the horizontal + axis of the plot and the second element is the vertical axis + of the plot. + + * axes: the :class:`matplotlib.axes.Axes` to use for drawing. + Defaults to the current axes if none provided. + + * contiguity_tolerance: The absolute tolerance used when checking for + contiguity between the bounds of the cells. Defaults to None. - See :func:`matplotlib.pyplot.pcolor` for details of other valid keyword - arguments. + See :func:`matplotlib.pyplot.pcolor` for details of other valid + keyword arguments. """ kwargs.setdefault('antialiased', True) @@ -763,18 +1162,29 @@ def pcolor(cube, *args, **kwargs): def pcolormesh(cube, *args, **kwargs): """ - Draws a pseudocolor plot based on the given Cube. + Draws a pseudocolor plot based on the given 2-dimensional Cube. + + The cube must have either two 1-dimensional coordinates or two + 2-dimensional coordinates with contiguous bounds to plot against each + other. Kwargs: - * coords: list of :class:`~iris.coords.Coord` objects or coordinate names - Use the given coordinates as the axes for the plot. The order of the - given coordinates indicates which axis to use for each, where the first - element is the horizontal axis of the plot and the second element is - the vertical axis of the plot. + * coords: list of :class:`~iris.coords.Coord` objects or + coordinate names. Use the given coordinates as the axes for the + plot. The order of the given coordinates indicates which axis + to use for each, where the first element is the horizontal + axis of the plot and the second element is the vertical axis + of the plot. + + * axes: the :class:`matplotlib.axes.Axes` to use for drawing. + Defaults to the current axes if none provided. + + * contiguity_tolerance: The absolute tolerance used when checking for + contiguity between the bounds of the cells. Defaults to None. - See :func:`matplotlib.pyplot.pcolormesh` for details of other valid keyword - arguments. + See :func:`matplotlib.pyplot.pcolormesh` for details of other + valid keyword arguments. """ result = _draw_2d_from_bounds('pcolormesh', cube, *args, **kwargs) @@ -787,53 +1197,114 @@ def points(cube, *args, **kwargs): Kwargs: - * coords: list of :class:`~iris.coords.Coord` objects or coordinate names - Use the given coordinates as the axes for the plot. The order of the - given coordinates indicates which axis to use for each, where the first - element is the horizontal axis of the plot and the second element is - the vertical axis of the plot. + * coords: list of :class:`~iris.coords.Coord` objects or + coordinate names. Use the given coordinates as the axes for the + plot. The order of the given coordinates indicates which axis + to use for each, where the first element is the horizontal + axis of the plot and the second element is the vertical axis + of the plot. - See :func:`matplotlib.pyplot.scatter` for details of other valid keyword - arguments. + * axes: the :class:`matplotlib.axes.Axes` to use for drawing. + Defaults to the current axes if none provided. + + See :func:`matplotlib.pyplot.scatter` for details of other valid + keyword arguments. """ - _scatter_args = lambda u, v, data, *args, **kwargs: ((u, v) + args, kwargs) + + def _scatter_args(u, v, data, *args, **kwargs): + return ((u, v) + args, kwargs) + return _draw_2d_from_points('scatter', _scatter_args, cube, *args, **kwargs) -def _1d_coords_deprecation_handler(func): - """ - Manage the deprecation of the coords keyword argument to 1d plot - functions. - - """ - @functools.wraps(func) - def _wrapper(*args, **kwargs): - coords = kwargs.pop('coords', None) - if coords is not None: - # issue a deprecation warning and check to see if the old - # interface should be mimicked for the deprecation period - warnings.warn('The coords keyword argument is deprecated.', - stacklevel=2) - if len(coords) != 1: - msg = 'The list of coordinates given should have length 1 ' \ - 'but it has length {}.' - raise ValueError(msg.format(len(coords))) - if isinstance(args[0], iris.cube.Cube): - if len(args) < 2 or not isinstance(args[1], (iris.cube.Cube, - iris.coords.Coord)): - coord = args[0].coord(coords[0]) - if not args[0].coord_dims(coord): - raise ValueError("The coordinate {!r} doesn't " - "span a data dimension." - "".format(coord.name())) - args = (coord,) + args - return func(*args, **kwargs) - return _wrapper - - -@_1d_coords_deprecation_handler +def _vector_component_args(x_points, y_points, u_data, *args, **kwargs): + """ + Callback from _draw_2d_from_points for 'quiver' and 'streamlines'. + + Returns arguments (x, y, u, v), to be passed to the underlying matplotlib + call. + + "u_data" will always be "u_cube.data". + The matching "v_cube.data" component is stored in kwargs['_v_data']. + + """ + v_data = kwargs.pop('_v_data') + + # Rescale u+v values for plot distortion. + crs = kwargs.get('transform', None) + if crs: + if not isinstance(crs, (ccrs.PlateCarree, ccrs.RotatedPole)): + msg = ('Can only plot vectors provided in a lat-lon ' + 'projection, i.e. equivalent to "cartopy.crs.PlateCarree" ' + 'or "cartopy.crs.RotatedPole". This ' + "cube coordinate system translates as Cartopy {}.") + raise ValueError(msg.format(crs)) + # Given the above check, the Y points must be latitudes. + # We therefore **assume** they are in degrees : I'm not sure this + # is wise, but all the rest of this plot code does that, e.g. in + # _map_common. + # TODO: investigate degree units assumptions, here + elsewhere. + + # Implement a latitude scaling, but preserve the given magnitudes. + u_data, v_data = [arr.copy() for arr in (u_data, v_data)] + mags = np.sqrt(u_data * u_data + v_data * v_data) + v_data *= np.cos(np.deg2rad(y_points)) + scales = mags / np.sqrt(u_data * u_data + v_data * v_data) + u_data *= scales + v_data *= scales + + return ((x_points, y_points, u_data, v_data), kwargs) + + +def quiver(u_cube, v_cube, *args, **kwargs): + """ + Draws an arrow plot from two vector component cubes. + + Args: + + * u_cube, v_cube : (:class:`~iris.cube.Cube`) + u and v vector components. Must have same shape and units. + If the cubes have geographic coordinates, the values are treated as + true distance differentials, e.g. windspeeds, and *not* map coordinate + vectors. The components are aligned with the North and East of the + cube coordinate system. + + .. Note: + + At present, if u_cube and v_cube have geographic coordinates, then they + must be in a lat-lon coordinate system, though it may be a rotated one. + To transform wind values between coordinate systems, use + :func:`iris.analysis.cartography.rotate_vectors`. + To transform coordinate grid points, you will need to create + 2-dimensional arrays of x and y values. These can be transformed with + :meth:`cartopy.crs.CRS.transform_points`. + + Kwargs: + + * coords: (list of :class:`~iris.coords.Coord` or string) + Coordinates or coordinate names. Use the given coordinates as the axes + for the plot. The order of the given coordinates indicates which axis + to use for each, where the first element is the horizontal + axis of the plot and the second element is the vertical axis + of the plot. + + * axes: the :class:`matplotlib.axes.Axes` to use for drawing. + Defaults to the current axes if none provided. + + See :func:`matplotlib.pyplot.quiver` for details of other valid + keyword arguments. + + """ + # + # TODO: check u + v cubes for compatibility. + # + kwargs['_v_data'] = v_cube.data + return _draw_2d_from_points('quiver', _vector_component_args, u_cube, + *args, **kwargs) + + def plot(*args, **kwargs): """ Draws a line plot based on the given cube(s) or coordinate(s). @@ -863,21 +1334,17 @@ def plot(*args, **kwargs): Kwargs: - * coords: list of :class:`~iris.coords.Coord` objects or coordinate names - Use the given coordinates as the axes for the plot. The order of the - given coordinates indicates which axis to use for each, where the first - element is the horizontal axis of the plot and the second element is - the vertical axis of the plot. - - .. deprecated:: 1.5 + * axes: the :class:`matplotlib.axes.Axes` to use for drawing. + Defaults to the current axes if none provided. - The plot coordinates can be specified explicitly as in the - above examples, so this keyword is no longer needed. - - See :func:`matplotlib.pyplot.plot` for details of valid keyword - arguments. + See :func:`matplotlib.pyplot.plot` for details of additional valid + keyword arguments. """ + if 'coords' in kwargs: + raise TypeError('"coords" is not a valid plot keyword. Coordinates ' + 'and cubes may be passed as arguments for ' + 'full control of the plot axes.') _plot_args = None return _draw_1d_from_points('plot', _plot_args, *args, **kwargs) @@ -894,8 +1361,13 @@ def scatter(x, y, *args, **kwargs): * y: :class:`~iris.cube.Cube` or :class:`~iris.coords.Coord` A cube or a coordinate to plot on the y-axis. - See :func:`matplotlib.pyplot.scatter` for details of valid keyword - arguments. + Kwargs: + + * axes: the :class:`matplotlib.axes.Axes` to use for drawing. + Defaults to the current axes if none provided. + + See :func:`matplotlib.pyplot.scatter` for details of additional + valid keyword arguments. """ # here we are more specific about argument types than generic 1d plotting @@ -934,9 +1406,8 @@ def symbols(x, y, symbols, size, axes=None, units='inches'): Kwargs: - * axes: - The :class:`matplotlib.axes.Axes` in which the symbols will be added. - Defaults to the current axes. + * axes: the :class:`matplotlib.axes.Axes` to use for drawing. + Defaults to the current axes if none provided. * units: ['inches', 'points'] The unit for the symbol size. @@ -945,15 +1416,15 @@ def symbols(x, y, symbols, size, axes=None, units='inches'): if axes is None: axes = plt.gca() - offsets = np.array(zip(x, y)) + offsets = np.array(list(zip(x, y))) # XXX "match_original" doesn't work ... so brute-force it instead. # PatchCollection constructor ignores all non-style keywords when using # match_original # See matplotlib.collections.PatchCollection.__init__ # Specifically matplotlib/collections line 1053 - #pc = PatchCollection(symbols, offsets=offsets, transOffset=ax.transData, - # match_original=True) + # pc = PatchCollection(symbols, offsets=offsets, transOffset=ax.transData, + # match_original=True) facecolors = [p.get_facecolor() for p in symbols] edgecolors = [p.get_edgecolor() for p in symbols] linewidths = [p.get_linewidth() for p in symbols] @@ -976,7 +1447,7 @@ def symbols(x, y, symbols, size, axes=None, units='inches'): axes.autoscale_view() -def citation(text, figure=None): +def citation(text, figure=None, axes=None): """ Add a text citation to a plot. @@ -994,11 +1465,15 @@ def citation(text, figure=None): Target :class:`matplotlib.figure.Figure` instance. Defaults to the current figure if none provided. + * axes: the :class:`matplotlib.axes.Axes` to use for drawing. + Defaults to the current axes if none provided. + """ if text is not None and len(text): - if figure is None: + if figure is None and not axes: figure = plt.gcf() anchor = AnchoredText(text, prop=dict(size=6), frameon=True, loc=4) anchor.patch.set_boxstyle('round, pad=0, rounding_size=0.2') - figure.gca().add_artist(anchor) + axes = axes if axes else figure.gca() + axes.add_artist(anchor) diff --git a/lib/iris/proxy.py b/lib/iris/proxy.py deleted file mode 100644 index 8a5d912d36..0000000000 --- a/lib/iris/proxy.py +++ /dev/null @@ -1,57 +0,0 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -""" -Provision of a service to handle missing packages at runtime. -Current just a very thin layer but gives the option to extend -handling as much as needed - -""" - -import sys - - -class FakeModule(object): - __slots__ = ('_name',) - - def __init__(self, name): - self._name = name - - def __setattr__(self, name, value): - object.__setattr__(self, name, value) - - def __getattr__(self, name): - raise AttributeError( - 'Module "{}" not available or not installed'.format(self._name)) - - -def apply_proxy(module_name, dic): - """ - Attempt the import else use the proxy module. - It is important to note that '__import__()' must be used - instead of the higher-level 'import' as we need to - ensure the scope of the import can be propagated out of this package. - Also, note the splitting of name - this is because '__import__()' - requires full package path, unlike 'import' (this issue is - explicitly seen in lib/iris/fileformats/pp.py importing pp_packing) - - """ - name = module_name.split('.')[-1] - try: - __import__(module_name) - dic[name] = sys.modules[module_name] - except ImportError: - dic[name] = sys.modules[name] = FakeModule(name) diff --git a/lib/iris/quickplot.py b/lib/iris/quickplot.py index 750a5e7fe9..16e8f2a753 100644 --- a/lib/iris/quickplot.py +++ b/lib/iris/quickplot.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -23,8 +23,11 @@ See also: :ref:`matplotlib `. """ -import warnings # deprecation of coords keyword in plot +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import cf_units import matplotlib.pyplot as plt import iris.config @@ -42,14 +45,14 @@ def _use_symbol(units): def _title(cube_or_coord, with_units): - if cube_or_coord is None: + if cube_or_coord is None or isinstance(cube_or_coord, int): title = '' else: title = cube_or_coord.name().replace('_', ' ').capitalize() units = cube_or_coord.units if with_units and not (units.is_unknown() or units.is_no_unit() or - units == iris.unit.Unit('1')): + units == cf_units.Unit('1')): if _use_symbol(units): units = units.symbol @@ -58,10 +61,13 @@ def _title(cube_or_coord, with_units): return title -def _label(cube, mode, result=None, ndims=2, coords=None): +def _label(cube, mode, result=None, ndims=2, coords=None, axes=None): """Puts labels on the current plot using the given cube.""" - plt.title(_title(cube, with_units=False)) + if axes is None: + axes = plt.gca() + + axes.set_title(_title(cube, with_units=False)) if result is not None: draw_edges = mode == iris.coords.POINT_MODE @@ -69,7 +75,7 @@ def _label(cube, mode, result=None, ndims=2, coords=None): drawedges=draw_edges) has_known_units = not (cube.units.is_unknown() or cube.units.is_no_unit()) - if has_known_units and cube.units != iris.unit.Unit('1'): + if has_known_units and cube.units != cf_units.Unit('1'): # Use shortest unit representation for anything other than time if _use_symbol(cube.units): bar.set_label(cube.units.symbol) @@ -86,22 +92,23 @@ def _label(cube, mode, result=None, ndims=2, coords=None): if ndims == 2: if not iplt._can_draw_map(plot_defn.coords): - plt.ylabel(_title(plot_defn.coords[0], with_units=True)) - plt.xlabel(_title(plot_defn.coords[1], with_units=True)) + axes.set_ylabel(_title(plot_defn.coords[0], with_units=True)) + axes.set_xlabel(_title(plot_defn.coords[1], with_units=True)) elif ndims == 1: - plt.xlabel(_title(plot_defn.coords[0], with_units=True)) - plt.ylabel(_title(cube, with_units=True)) + axes.set_xlabel(_title(plot_defn.coords[0], with_units=True)) + axes.set_ylabel(_title(cube, with_units=True)) else: - msg = 'Unexpected number of dimensions (%s) given to _label.' % ndims + msg = 'Unexpected number of dimensions ({}) given to ' \ + '_label.'.format(ndims) raise ValueError(msg) -def _label_with_bounds(cube, result=None, ndims=2, coords=None): - _label(cube, iris.coords.BOUND_MODE, result, ndims, coords) +def _label_with_bounds(cube, result=None, ndims=2, coords=None, axes=None): + _label(cube, iris.coords.BOUND_MODE, result, ndims, coords, axes) -def _label_with_points(cube, result=None, ndims=2, coords=None): - _label(cube, iris.coords.POINT_MODE, result, ndims, coords) +def _label_with_points(cube, result=None, ndims=2, coords=None, axes=None): + _label(cube, iris.coords.POINT_MODE, result, ndims, coords, axes) def _get_titles(u_object, v_object): @@ -123,15 +130,26 @@ def _get_titles(u_object, v_object): return xlabel, ylabel, title -def _label_1d_plot(*args): +def _label_1d_plot(*args, **kwargs): if len(args) > 1 and isinstance(args[1], (iris.cube.Cube, iris.coords.Coord)): xlabel, ylabel, title = _get_titles(*args[:2]) else: xlabel, ylabel, title = _get_titles(None, args[0]) - plt.title(title) - plt.xlabel(xlabel) - plt.ylabel(ylabel) + + axes = kwargs.pop('axes', None) + + if len(kwargs) != 0: + msg = 'Unexpected kwargs {} given to _label_1d_plot'.format( + kwargs.keys()) + raise ValueError(msg) + + if axes is None: + axes = plt.gca() + + axes.set_title(title) + axes.set_xlabel(xlabel) + axes.set_ylabel(ylabel) def contour(cube, *args, **kwargs): @@ -155,8 +173,9 @@ def contour(cube, *args, **kwargs): """ coords = kwargs.get('coords') + axes = kwargs.get('axes') result = iplt.contour(cube, *args, **kwargs) - _label_with_points(cube, coords=coords) + _label_with_points(cube, coords=coords, axes=axes) return result @@ -181,15 +200,37 @@ def contourf(cube, *args, **kwargs): """ coords = kwargs.get('coords') + axes = kwargs.get('axes') result = iplt.contourf(cube, *args, **kwargs) - _label_with_points(cube, result, coords=coords) + _label_with_points(cube, result, coords=coords, axes=axes) return result -def outline(cube, coords=None): - """Draws cell outlines on a labelled plot based on the given Cube.""" - result = iplt.outline(cube, coords=coords) - _label_with_bounds(cube, coords=coords) +def outline(cube, coords=None, color='k', linewidth=None, axes=None): + """ + Draws cell outlines on a labelled plot based on the given Cube. + + Kwargs: + + * coords: list of :class:`~iris.coords.Coord` objects or coordinate names + Use the given coordinates as the axes for the plot. The order of the + given coordinates indicates which axis to use for each, where the first + element is the horizontal axis of the plot and the second element is + the vertical axis of the plot. + + * color: None or mpl color + The color of the cell outlines. If None, the matplotlibrc setting + patch.edgecolor is used by default. + + * linewidth: None or number + The width of the lines showing the cell outlines. If None, the default + width in patch.linewidth in matplotlibrc is used. + + """ + result = iplt.outline(cube, color=color, linewidth=linewidth, + coords=coords, axes=axes) + + _label_with_bounds(cube, coords=coords, axes=axes) return result @@ -201,8 +242,9 @@ def pcolor(cube, *args, **kwargs): """ coords = kwargs.get('coords') + axes = kwargs.get('axes') result = iplt.pcolor(cube, *args, **kwargs) - _label_with_bounds(cube, result, coords=coords) + _label_with_bounds(cube, result, coords=coords, axes=axes) return result @@ -214,8 +256,9 @@ def pcolormesh(cube, *args, **kwargs): """ coords = kwargs.get('coords') + axes = kwargs.get('axes') result = iplt.pcolormesh(cube, *args, **kwargs) - _label_with_bounds(cube, result, coords=coords) + _label_with_bounds(cube, result, coords=coords, axes=axes) return result @@ -227,12 +270,12 @@ def points(cube, *args, **kwargs): """ coords = kwargs.get('coords') + axes = kwargs.get('axes') result = iplt.points(cube, *args, **kwargs) - _label_with_points(cube, coords=coords) + _label_with_points(cube, coords=coords, axes=axes) return result -@iplt._1d_coords_deprecation_handler def plot(*args, **kwargs): """ Draws a labelled line plot based on the given cube(s) or @@ -242,8 +285,9 @@ def plot(*args, **kwargs): keyword arguments. """ + axes = kwargs.get('axes') result = iplt.plot(*args, **kwargs) - _label_1d_plot(*args) + _label_1d_plot(*args, axes=axes) return result @@ -256,8 +300,9 @@ def scatter(x, y, *args, **kwargs): keyword arguments. """ + axes = kwargs.get('axes') result = iplt.scatter(x, y, *args, **kwargs) - _label_1d_plot(x, y) + _label_1d_plot(x, y, axes=axes) return result diff --git a/lib/iris/symbols.py b/lib/iris/symbols.py index 5e3d953700..e5439974bb 100644 --- a/lib/iris/symbols.py +++ b/lib/iris/symbols.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -19,6 +19,10 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + import itertools import math @@ -54,7 +58,7 @@ def _make_merged_patch(paths): all_vertices[i_vertices:i_vertices + n_vertices] = vertices i_vertices += n_vertices - n_codes = n_vertices / 2 + n_codes = n_vertices // 2 if code == Path.STOP: code = Path.MOVETO all_codes[i_codes:i_codes + n_codes] = code @@ -219,7 +223,7 @@ def _wedge_fix(wedge_path): def _convert_paths_to_patches(): # Convert the symbols defined as lists-of-paths into patches. - for code, symbol in CLOUD_COVER.iteritems(): + for code, symbol in six.iteritems(CLOUD_COVER): CLOUD_COVER[code] = _make_merged_patch(symbol) diff --git a/lib/iris/tests/__init__.py b/lib/iris/tests/__init__.py index 4add70cede..84d4614c0e 100644 --- a/lib/iris/tests/__init__.py +++ b/lib/iris/tests/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -29,69 +29,142 @@ graphical test results. """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +import codecs import collections import contextlib +import datetime import difflib import filecmp +import functools import gzip import inspect -import logging +import json +import io +import math import os import os.path import re import shutil -import StringIO import subprocess import sys import unittest +import threading import warnings import xml.dom.minidom import zlib -import matplotlib -import matplotlib.testing.compare as mcompare -import matplotlib.pyplot as plt +try: + from unittest import mock +except ImportError: + import mock + +import filelock import numpy as np import numpy.ma as ma +import requests import iris.cube import iris.config import iris.util +# Test for availability of matplotlib. +# (And remove matplotlib as an iris.tests dependency.) +try: + import matplotlib + matplotlib.use('agg') + matplotlib.rcdefaults() + # Standardise the figure size across matplotlib versions. + # This permits matplotlib png image comparison. + matplotlib.rcParams['figure.figsize'] = [8.0, 6.0] + import matplotlib.testing.compare as mcompare + import matplotlib.pyplot as plt +except ImportError: + MPL_AVAILABLE = False +else: + MPL_AVAILABLE = True + +try: + from osgeo import gdal +except ImportError: + GDAL_AVAILABLE = False +else: + GDAL_AVAILABLE = True + +try: + from iris_grib.message import GribMessage + GRIB_AVAILABLE = True +except ImportError: + GRIB_AVAILABLE = False + +try: + import iris_sample_data +except ImportError: + SAMPLE_DATA_AVAILABLE = False +else: + SAMPLE_DATA_AVAILABLE = True + +try: + import nc_time_axis + NC_TIME_AXIS_AVAILABLE = True +except ImportError: + NC_TIME_AXIS_AVAILABLE = False + +try: + requests.get('https://github.com/SciTools/iris') + INET_AVAILABLE = True +except requests.exceptions.ConnectionError: + INET_AVAILABLE = False + +try: + import stratify + STRATIFY_AVAILABLE = True +except ImportError: + STRATIFY_AVAILABLE = False #: Basepath for test results. _RESULT_PATH = os.path.join(os.path.dirname(__file__), 'results') +#: Default perceptual hash size. +_HASH_SIZE = 16 +#: Default maximum perceptual hash hamming distance. +_HAMMING_DISTANCE = 2 if '--data-files-used' in sys.argv: sys.argv.remove('--data-files-used') fname = '/var/tmp/all_iris_test_resource_paths.txt' - print 'saving list of files used by tests to %s' % fname + print('saving list of files used by tests to %s' % fname) _EXPORT_DATAPATHS_FILE = open(fname, 'w') else: _EXPORT_DATAPATHS_FILE = None -# A shared logger for use by unit tests -logger = logging.getLogger('tests') +if '--create-missing' in sys.argv: + sys.argv.remove('--create-missing') + print('Allowing creation of missing test results.') + os.environ['IRIS_TEST_CREATE_MISSING'] = 'true' + # Whether to display matplotlib output to the screen. _DISPLAY_FIGURES = False -if '-d' in sys.argv: +if (MPL_AVAILABLE and '-d' in sys.argv): sys.argv.remove('-d') plt.switch_backend('tkagg') _DISPLAY_FIGURES = True -else: - plt.switch_backend('agg') -_DEFAULT_IMAGE_TOLERANCE = 10.0 +# Threading non re-entrant blocking lock to ensure thread-safe plotting. +_lock = threading.Lock() def main(): """A wrapper for unittest.main() which adds iris.test specific options to the help (-h) output.""" if '-h' in sys.argv or '--help' in sys.argv: stdout = sys.stdout - buff = StringIO.StringIO() + buff = io.StringIO() # NB. unittest.main() raises an exception after it's shown the help text try: sys.stdout = buff @@ -104,7 +177,9 @@ def main(): lines.insert(11, ' NOTE: To compare results of failing tests, ') lines.insert(12, ' use idiff.py instead') lines.insert(13, ' --data-files-used Save a list of files used to a temporary file') - print '\n'.join(lines) + lines.insert( + 14, ' -m Create missing test results') + print('\n'.join(lines)) else: unittest.main() @@ -115,34 +190,38 @@ def get_data_path(relative_path): as a string, or sequence of strings. """ - if not isinstance(relative_path, basestring): + if not isinstance(relative_path, six.string_types): relative_path = os.path.join(*relative_path) - data_path = os.path.join(iris.config.TEST_DATA_DIR, relative_path) + test_data_dir = iris.config.TEST_DATA_DIR + if test_data_dir is None: + test_data_dir = '' + data_path = os.path.join(test_data_dir, relative_path) if _EXPORT_DATAPATHS_FILE is not None: _EXPORT_DATAPATHS_FILE.write(data_path + '\n') - if isinstance(data_path, basestring) and not os.path.exists(data_path): + if isinstance(data_path, six.string_types) and not os.path.exists(data_path): # if the file is gzipped, ungzip it and return the path of the ungzipped # file. gzipped_fname = data_path + '.gz' if os.path.exists(gzipped_fname): with gzip.open(gzipped_fname, 'rb') as gz_fh: - with open(data_path, 'wb') as fh: - fh.writelines(gz_fh) + try: + with open(data_path, 'wb') as fh: + fh.writelines(gz_fh) + except IOError: + # Put ungzipped data file in a temporary path, since we + # can't write to the original path (maybe it is owned by + # the system.) + _, ext = os.path.splitext(data_path) + data_path = iris.util.create_temp_filename(suffix=ext) + with open(data_path, 'wb') as fh: + fh.writelines(gz_fh) return data_path -def get_result_path(relative_path): - """Returns the absolute path to a result file when given the relative path - as a string, or sequence of strings.""" - if not isinstance(relative_path, basestring): - relative_path = os.path.join(*relative_path) - return os.path.abspath(os.path.join(_RESULT_PATH, relative_path)) - - -class IrisTest(unittest.TestCase): +class IrisTest_nometa(unittest.TestCase): """A subclass of unittest.TestCase which provides Iris specific testing functionality.""" _assertion_counts = collections.defaultdict(int) @@ -158,8 +237,26 @@ def _assert_str_same(self, reference_str, test_str, reference_filename, type_com 'Reference', 'Test result', '', '', 0)) self.fail("%s do not match: %s\n%s" % (type_comparison_name, reference_filename, diff)) - def _assert_cml(self, cube_xml, reference_xml, reference_filename): - self._assert_str_same(reference_xml, cube_xml, reference_filename, 'CML') + @staticmethod + def get_result_path(relative_path): + """ + Returns the absolute path to a result file when given the relative path + as a string, or sequence of strings. + + """ + if not isinstance(relative_path, six.string_types): + relative_path = os.path.join(*relative_path) + return os.path.abspath(os.path.join(_RESULT_PATH, relative_path)) + + def assertStringEqual(self, reference_str, test_str, + type_comparison_name='strings'): + if reference_str != test_str: + diff = '\n'.join(difflib.unified_diff(reference_str.splitlines(), + test_str.splitlines(), + 'Reference', 'Test result', + '', '', 0)) + self.fail("{} do not match:\n{}".format(type_comparison_name, + diff)) def result_path(self, basename=None, ext=''): """ @@ -190,46 +287,68 @@ def result_path(self, basename=None, ext=''): break filename = basename + ext - result = os.path.join(get_result_path(''), + result = os.path.join(self.get_result_path(''), sub_path.replace('test_', ''), self.__class__.__name__.replace('Test_', ''), filename) return result - def assertCMLApproxData(self, cubes, reference_filename, *args, **kwargs): + def assertCMLApproxData(self, cubes, reference_filename=None, **kwargs): # passes args and kwargs on to approx equal if isinstance(cubes, iris.cube.Cube): cubes = [cubes] + if reference_filename is None: + reference_filename = self.result_path(None, 'cml') + reference_filename = [self.get_result_path(reference_filename)] for i, cube in enumerate(cubes): fname = list(reference_filename) - # don't want the ".cml" for the numpy data file + # don't want the ".cml" for the json stats file if fname[-1].endswith(".cml"): fname[-1] = fname[-1][:-4] - fname[-1] += '.data.%d.npy' % i - self.assertCubeDataAlmostEqual(cube, fname, *args, **kwargs) - + fname[-1] += '.data.%d.json' % i + self.assertDataAlmostEqual(cube.data, fname, **kwargs) self.assertCML(cubes, reference_filename, checksum=False) - def assertCDL(self, netcdf_filename, reference_filename=None, flags='-h', - basename=None): + def assertCDL(self, netcdf_filename, reference_filename=None, flags='-h'): """ - Converts the given CF-netCDF file to CDL for comparison with - the reference CDL file, or creates the reference file if it - doesn't exist. + Test that the CDL for the given netCDF file matches the contents + of the reference file. + + If the environment variable IRIS_TEST_CREATE_MISSING is + non-empty, the reference file is created if it doesn't exist. + + Args: + + * netcdf_filename: + The path to the netCDF file. + + Kwargs: + + * reference_filename: + The relative path (relative to the test results directory). + If omitted, the result is generated from the calling + method's name, class, and module using + :meth:`iris.tests.IrisTest.result_path`. + + * flags: + Command-line flags for `ncdump`, as either a whitespace + separated string or an iterable. Defaults to '-h'. """ if reference_filename is None: - reference_filename = self.result_path(basename, "cdl") + reference_path = self.result_path(None, 'cdl') + else: + reference_path = self.get_result_path(reference_filename) # Convert the netCDF file to CDL file format. cdl_filename = iris.util.create_temp_filename(suffix='.cdl') if flags is None: flags = [] - elif isinstance(flags, basestring): + elif isinstance(flags, six.string_types): flags = flags.split() else: - flags = map(str, flags) + flags = list(map(str, flags)) with open(cdl_filename, 'w') as cdl_file: subprocess.check_call(['ncdump'] + flags + [netcdf_filename], @@ -248,27 +367,46 @@ def assertCDL(self, netcdf_filename, reference_filename=None, flags='-h', cdl = ''.join(lines) os.remove(cdl_filename) - reference_path = get_result_path(reference_filename) - self._check_same(cdl, reference_path, reference_filename, type_comparison_name='CDL') + self._check_same(cdl, reference_path, type_comparison_name='CDL') - def assertCML(self, cubes, reference_filename=None, checksum=True, - basename=None): + def assertCML(self, cubes, reference_filename=None, checksum=True): """ - Checks the given cubes match the reference file, or creates the - reference file if it doesn't exist. + Test that the CML for the given cubes matches the contents of + the reference file. + + If the environment variable IRIS_TEST_CREATE_MISSING is + non-empty, the reference file is created if it doesn't exist. + + Args: + + * cubes: + Either a Cube or a sequence of Cubes. + + Kwargs: + + * reference_filename: + The relative path (relative to the test results directory). + If omitted, the result is generated from the calling + method's name, class, and module using + :meth:`iris.tests.IrisTest.result_path`. + + * checksum: + When True, causes the CML to include a checksum for each + Cube's data. Defaults to True. """ if isinstance(cubes, iris.cube.Cube): cubes = [cubes] if reference_filename is None: - reference_filename = self.result_path(basename, "cml") + reference_filename = self.result_path(None, 'cml') if isinstance(cubes, (list, tuple)): - xml = iris.cube.CubeList(cubes).xml(checksum=checksum, order=False) + xml = iris.cube.CubeList(cubes).xml(checksum=checksum, order=False, + byteorder=False) else: - xml = cubes.xml(checksum=checksum, order=False) - reference_path = get_result_path(reference_filename) - self._check_same(xml, reference_path, reference_filename) + xml = cubes.xml(checksum=checksum, order=False, byteorder=False) + reference_path = self.get_result_path(reference_filename) + self._check_same(xml, reference_path) def assertTextFile(self, source_filename, reference_filename, desc="text file"): """Check if two text files are the same, printing any diffs.""" @@ -280,62 +418,91 @@ def assertTextFile(self, source_filename, reference_filename, desc="text file"): diff = ''.join(difflib.unified_diff(reference_text, source_text, 'Reference', 'Test result', '', '', 0)) self.fail("%s does not match reference file: %s\n%s" % (desc, reference_filename, diff)) - def assertCubeDataAlmostEqual(self, cube, reference_filename, *args, **kwargs): - reference_path = get_result_path(reference_filename) - if os.path.isfile(reference_path): + def assertDataAlmostEqual(self, data, reference_filename, **kwargs): + reference_path = self.get_result_path(reference_filename) + if self._check_reference_file(reference_path): kwargs.setdefault('err_msg', 'Reference file %s' % reference_path) - - result = np.load(reference_path) - if isinstance(result, np.lib.npyio.NpzFile): - self.assertIsInstance(cube.data, ma.MaskedArray, 'Cube data was not a masked array.') - # Avoid comparing any non-initialised array data. - data = cube.data.filled() - np.testing.assert_array_almost_equal(data, result['data'], - *args, **kwargs) - np.testing.assert_array_equal(cube.data.mask, result['mask']) - else: - np.testing.assert_array_almost_equal(cube.data, result, *args, **kwargs) + with open(reference_path, 'r') as reference_file: + stats = json.load(reference_file) + self.assertEqual(stats.get('shape', []), list(data.shape)) + self.assertEqual(stats.get('masked', False), + ma.is_masked(data)) + nstats = np.array((stats.get('mean', 0.), stats.get('std', 0.), + stats.get('max', 0.), stats.get('min', 0.)), + dtype=np.float_) + if math.isnan(stats.get('mean', 0.)): + self.assertTrue(math.isnan(data.mean())) + else: + data_stats = np.array((data.mean(), data.std(), + data.max(), data.min()), + dtype=np.float_) + self.assertArrayAllClose(nstats, data_stats, **kwargs) else: self._ensure_folder(reference_path) - logger.warning('Creating result file: %s', reference_path) - if isinstance(cube.data, ma.MaskedArray): - # Avoid recording any non-initialised array data. - data = cube.data.filled() - np.savez(file(reference_path, 'wb'), data=data, mask=cube.data.mask) - else: - np.save(file(reference_path, 'wb'), cube.data) + stats = collections.OrderedDict([ + ('std', np.float_(data.std())), + ('min', np.float_(data.min())), + ('max', np.float_(data.max())), + ('shape', data.shape), + ('masked', ma.is_masked(data)), + ('mean', np.float_(data.mean()))]) + with open(reference_path, 'w') as reference_file: + reference_file.write(json.dumps(stats)) def assertFilesEqual(self, test_filename, reference_filename): - reference_path = get_result_path(reference_filename) - if os.path.isfile(reference_path): - self.assertTrue(filecmp.cmp(test_filename, reference_path)) + reference_path = self.get_result_path(reference_filename) + if self._check_reference_file(reference_path): + fmt = 'test file {!r} does not match reference {!r}.' + self.assertTrue(filecmp.cmp(test_filename, reference_path), + fmt.format(test_filename, reference_path)) else: self._ensure_folder(reference_path) - logger.warning('Creating result file: %s', reference_path) shutil.copy(test_filename, reference_path) - def assertString(self, string, reference_filename): - reference_path = get_result_path(reference_filename) - # If the test string is a unicode string, encode as - # utf-8 before comparison to the reference string. - if isinstance(string, unicode): - string = string.encode('utf-8') - self._check_same(string, reference_path, reference_filename, + def assertString(self, string, reference_filename=None): + """ + Test that `string` matches the contents of the reference file. + + If the environment variable IRIS_TEST_CREATE_MISSING is + non-empty, the reference file is created if it doesn't exist. + + Args: + + * string: + The string to check. + + Kwargs: + + * reference_filename: + The relative path (relative to the test results directory). + If omitted, the result is generated from the calling + method's name, class, and module using + :meth:`iris.tests.IrisTest.result_path`. + + """ + if reference_filename is None: + reference_path = self.result_path(None, 'txt') + else: + reference_path = self.get_result_path(reference_filename) + self._check_same(string, reference_path, type_comparison_name='Strings') def assertRepr(self, obj, reference_filename): self.assertString(repr(obj), reference_filename) - def _check_same(self, item, reference_path, reference_filename, type_comparison_name='CML'): - if os.path.isfile(reference_path): - reference = ''.join(open(reference_path, 'r').readlines()) - self._assert_str_same(reference, item, reference_filename, type_comparison_name) + def _check_same(self, item, reference_path, type_comparison_name='CML'): + if self._check_reference_file(reference_path): + with open(reference_path, 'rb') as reference_fh: + reference = ''.join(part.decode('utf-8') + for part in reference_fh.readlines()) + self._assert_str_same(reference, item, reference_path, + type_comparison_name) else: self._ensure_folder(reference_path) - logger.warning('Creating result file: %s', reference_path) - open(reference_path, 'w').writelines( - part.encode('utf-8') if isinstance(part, unicode) else part - for part in item) + with open(reference_path, 'wb') as reference_fh: + reference_fh.writelines( + part.encode('utf-8') + for part in item) def assertXMLElement(self, obj, reference_filename): """ @@ -345,35 +512,137 @@ def assertXMLElement(self, obj, reference_filename): doc = xml.dom.minidom.Document() doc.appendChild(obj.xml_element(doc)) pretty_xml = doc.toprettyxml(indent=" ") - reference_path = get_result_path(reference_filename) - self._check_same(pretty_xml, reference_path, reference_filename, type_comparison_name='XML') + reference_path = self.get_result_path(reference_filename) + self._check_same(pretty_xml, reference_path, + type_comparison_name='XML') def assertArrayEqual(self, a, b, err_msg=''): np.testing.assert_array_equal(a, b, err_msg=err_msg) - def assertMaskedArrayEqual(self, a, b): + def assertRaisesRegexp(self, *args, **kwargs): + """ + Emulate the old :meth:`unittest.TestCase.assertRaisesRegexp`. + + Because the original function is now deprecated in Python 3. + Now calls :meth:`six.assertRaisesRegex()` (no final "p") instead. + It is the same, except for providing an additional 'msg' argument. + + """ + # Note: invoke via parent class to avoid recursion as, in Python 2, + # "six.assertRaisesRegex" calls getattr(self, 'assertRaisesRegexp'). + return six.assertRaisesRegex(super(IrisTest_nometa, self), + *args, **kwargs) + + @contextlib.contextmanager + def _recordWarningMatches(self, expected_regexp=''): + # Record warnings raised matching a given expression. + matches = [] + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + yield matches + messages = [str(warning.message) for warning in w] + expr = re.compile(expected_regexp) + matches.extend(message for message in messages + if expr.search(message)) + + @contextlib.contextmanager + def assertWarnsRegexp(self, expected_regexp=''): + # Check that a warning is raised matching a given expression. + with self._recordWarningMatches(expected_regexp) as matches: + yield + + msg = "Warning matching '{}' not raised." + msg = msg.format(expected_regexp) + self.assertTrue(matches, msg) + + @contextlib.contextmanager + def assertNoWarningsRegexp(self, expected_regexp=''): + # Check that no warning matching the given expression is raised. + with self._recordWarningMatches(expected_regexp) as matches: + yield + + msg = "Unexpected warning(s) raised, matching '{}' : {!r}." + msg = msg.format(expected_regexp, matches) + self.assertFalse(matches, msg) + + def _assertMaskedArray(self, assertion, a, b, strict, **kwargs): + # Define helper function to extract unmasked values as a 1d + # array. + def unmasked_data_as_1d_array(array): + array = ma.asarray(array) + if array.ndim == 0: + if array.mask: + data = np.array([]) + else: + data = np.array([array.data]) + else: + data = array.data[~ma.getmaskarray(array)] + return data + + # Compare masks. This will also check that the array shapes + # match, which is not tested when comparing unmasked values if + # strict is False. + a_mask, b_mask = ma.getmaskarray(a), ma.getmaskarray(b) + np.testing.assert_array_equal(a_mask, b_mask) + + if strict: + assertion(a.data, b.data, **kwargs) + else: + assertion(unmasked_data_as_1d_array(a), + unmasked_data_as_1d_array(b), + **kwargs) + + def assertMaskedArrayEqual(self, a, b, strict=False): """ Check that masked arrays are equal. This requires the unmasked values and masks to be identical. + Args: + + * a, b (array-like): + Two arrays to compare. + + Kwargs: + + * strict (bool): + If True, perform a complete mask and data array equality check. + If False (default), the data array equality considers only unmasked + elements. + """ - np.testing.assert_array_equal(a.mask, b.mask) - np.testing.assert_array_equal(a[~a.mask].data, b[~b.mask].data) + self._assertMaskedArray(np.testing.assert_array_equal, a, b, strict) - def assertArrayAlmostEqual(self, a, b): - np.testing.assert_array_almost_equal(a, b) + def assertArrayAlmostEqual(self, a, b, decimal=6): + np.testing.assert_array_almost_equal(a, b, decimal=decimal) - def assertMaskedArrayAlmostEqual(self, a, b): + def assertMaskedArrayAlmostEqual(self, a, b, decimal=6, strict=False): """ Check that masked arrays are almost equal. This requires the masks to be identical, and the unmasked values to be almost equal. + Args: + + * a, b (array-like): + Two arrays to compare. + + Kwargs: + + * strict (bool): + If True, perform a complete mask and data array equality check. + If False (default), the data array equality considers only unmasked + elements. + + * decimal (int): + Equality tolerance level for + :meth:`numpy.testing.assert_array_almost_equal`, with the meaning + 'abs(desired-actual) < 0.5 * 10**(-decimal)' + """ - np.testing.assert_array_equal(a.mask, b.mask) - np.testing.assert_array_almost_equal(a[~a.mask].data, b[~b.mask].data) + self._assertMaskedArray(np.testing.assert_array_almost_equal, a, b, + strict, decimal=decimal) - def assertArrayAllClose(self, a, b, rtol=1.0e-7, atol=0.0, **kwargs): + def assertArrayAllClose(self, a, b, rtol=1.0e-7, atol=1.0e-8, **kwargs): """ Check arrays are equal, within given relative + absolute tolerances. @@ -391,23 +660,50 @@ def assertArrayAllClose(self, a, b, rtol=1.0e-7, atol=0.0, **kwargs): Performs pointwise toleranced comparison, and raises an assertion if the two are not equal 'near enough'. - For full details see underlying routine numpy.testing.assert_allclose. + For full details see underlying routine numpy.allclose. """ - np.testing.assert_allclose(a, b, rtol=rtol, atol=atol, **kwargs) + # Handle the 'err_msg' kwarg, which is the only API difference + # between np.allclose and np.testing_assert_allclose. + msg = kwargs.pop('err_msg', None) + ok = np.allclose(a, b, rtol=rtol, atol=atol, **kwargs) + if not ok: + # Calculate errors above a pointwise tolerance : The method is + # taken from "numpy.core.numeric.isclose". + a, b = np.broadcast_arrays(a, b) + errors = (np.abs(a-b) - atol + rtol * np.abs(b)) + worst_inds = np.unravel_index(np.argmax(errors.flat), errors.shape) + + if msg is None: + # Build a more useful message than np.testing.assert_allclose. + msg = ( + '\nARRAY CHECK FAILED "assertArrayAllClose" :' + '\n with shapes={} {}, atol={}, rtol={}' + '\n worst at element {} : a={} b={}' + '\n absolute error ~{:.3g}, equivalent to rtol ~{:.3e}') + aval, bval = a[worst_inds], b[worst_inds] + absdiff = np.abs(aval - bval) + equiv_rtol = absdiff / bval + msg = msg.format( + a.shape, b.shape, atol, rtol, worst_inds, aval, bval, + absdiff, equiv_rtol) + + raise AssertionError(msg) @contextlib.contextmanager def temp_filename(self, suffix=''): filename = iris.util.create_temp_filename(suffix) - yield filename - os.remove(filename) + try: + yield filename + finally: + os.remove(filename) def file_checksum(self, file_path): """ Generate checksum from file. """ - in_file = open(file_path, "rb") - return zlib.crc32(in_file.read()) + with open(file_path, "rb") as in_file: + return zlib.crc32(in_file.read()) def _unique_id(self): """ @@ -427,16 +723,21 @@ def _unique_id(self): """ # Obtain a consistent ID for the current test. - # NB. unittest.TestCase.id() returns different values depending on # whether the test has been run explicitly, or via test discovery. # For example: # python tests/test_plot.py => '__main__.TestContourf.test_tx' # ird -t => 'iris.tests.test_plot.TestContourf.test_tx' - bits = self.id().split('.')[-3:] + bits = self.id().split('.') if bits[0] == '__main__': - file_name = os.path.basename(sys.modules['__main__'].__file__) + floc = sys.modules['__main__'].__file__ + path, file_name = os.path.split(os.path.abspath(floc)) bits[0] = os.path.splitext(file_name)[0] + folder, location = os.path.split(path) + bits = [location] + bits + while location not in ['iris', 'example_tests']: + folder, location = os.path.split(folder) + bits = [location] + bits test_id = '.'.join(bits) # Derive the sequential assertion ID within the test @@ -445,27 +746,40 @@ def _unique_id(self): return test_id + '.' + str(assertion_id) + def _check_reference_file(self, reference_path): + reference_exists = os.path.isfile(reference_path) + if not (reference_exists or + os.environ.get('IRIS_TEST_CREATE_MISSING')): + msg = 'Missing test result: {}'.format(reference_path) + raise AssertionError(msg) + return reference_exists + def _ensure_folder(self, path): dir_path = os.path.dirname(path) if not os.path.exists(dir_path): - logger.warning('Creating folder: %s', dir_path) os.makedirs(dir_path) - def check_graphic(self, tol=_DEFAULT_IMAGE_TOLERANCE): - """Checks the CRC matches for the current matplotlib.pyplot figure, and closes the figure.""" - - unique_id = self._unique_id() + def check_graphic(self): + """ + Check the hash of the current matplotlib figure matches the expected + image hash for the current graphic test. - figure = plt.gcf() + To create missing image test results, set the IRIS_TEST_CREATE_MISSING + environment variable before running the tests. This will result in new + and appropriately ".png" image files being generated in the image + output directory, and the imagerepo.json file being updated. - try: - expected_fname = os.path.join(os.path.dirname(__file__), - 'results', 'visual_tests', - unique_id + '.png') + """ + import imagehash + from PIL import Image - if not os.path.isdir(os.path.dirname(expected_fname)): - os.makedirs(os.path.dirname(expected_fname)) + dev_mode = os.environ.get('IRIS_TEST_CREATE_MISSING') + unique_id = self._unique_id() + repo_fname = os.path.join(_RESULT_PATH, 'imagerepo.json') + with open(repo_fname, 'rb') as fi: + repo = json.load(codecs.getreader('utf-8')(fi)) + try: #: The path where the images generated by the tests should go. image_output_directory = os.path.join(os.path.dirname(__file__), 'result_image_comparison') @@ -481,42 +795,348 @@ def check_graphic(self, tol=_DEFAULT_IMAGE_TOLERANCE): result_fname = os.path.join(image_output_directory, 'result-' + unique_id + '.png') - if not os.path.isdir(os.path.dirname(result_fname)): + if not os.path.isdir(image_output_directory): # Handle race-condition where the directories are # created sometime between the check above and the # creation attempt below. try: - os.makedirs(os.path.dirname(result_fname)) + os.makedirs(image_output_directory) except OSError as err: # Don't care about "File exists" if err.errno != 17: raise - figure.savefig(result_fname) - - if not os.path.exists(expected_fname): - warnings.warn('Created image for test %s' % unique_id) - shutil.copy2(result_fname, expected_fname) - - err = mcompare.compare_images(expected_fname, result_fname, tol=tol) + def _create_missing(): + fname = '{}.png'.format(phash) + base_uri = ('https://scitools.github.io/test-iris-imagehash/' + 'images/v4/{}') + uri = base_uri.format(fname) + hash_fname = os.path.join(image_output_directory, fname) + uris = repo.setdefault(unique_id, []) + uris.append(uri) + print('Creating image file: {}'.format(hash_fname)) + figure.savefig(hash_fname) + msg = 'Creating imagerepo entry: {} -> {}' + print(msg.format(unique_id, uri)) + lock = filelock.FileLock(os.path.join(_RESULT_PATH, + 'imagerepo.lock')) + # The imagerepo.json file is a critical resource, so ensure + # thread safe read/write behaviour via platform independent + # file locking. + with lock.acquire(timeout=600): + with open(repo_fname, 'wb') as fo: + json.dump(repo, codecs.getwriter('utf-8')(fo), + indent=4, sort_keys=True) + + # Calculate the test result perceptual image hash. + buffer = io.BytesIO() + figure = plt.gcf() + figure.savefig(buffer, format='png') + buffer.seek(0) + phash = imagehash.phash(Image.open(buffer), hash_size=_HASH_SIZE) + + if unique_id not in repo: + if dev_mode: + _create_missing() + else: + figure.savefig(result_fname) + emsg = 'Missing image test result: {}.' + raise AssertionError(emsg.format(unique_id)) + else: + uris = repo[unique_id] + # Extract the hex basename strings from the uris. + hexes = [os.path.splitext(os.path.basename(uri))[0] + for uri in uris] + # Create the expected perceptual image hashes from the uris. + to_hash = imagehash.hex_to_hash + expected = [to_hash(uri_hex) for uri_hex in hexes] + + # Calculate hamming distance vector for the result hash. + distances = [e - phash for e in expected] + + if np.all([hd > _HAMMING_DISTANCE for hd in distances]): + if dev_mode: + _create_missing() + else: + figure.savefig(result_fname) + msg = ('Bad phash {} with hamming distance {} ' + 'for test {}.') + msg = msg.format(phash, distances, unique_id) + if _DISPLAY_FIGURES: + emsg = 'Image comparison would have failed: {}' + print(emsg.format(msg)) + else: + emsg = 'Image comparison failed: {}' + raise AssertionError(emsg.format(msg)) if _DISPLAY_FIGURES: - if err: - print 'Image comparison would have failed. Message: %s' % err plt.show() - else: - assert not err, 'Image comparison failed. Message: %s' % err finally: plt.close() + def _remove_testcase_patches(self): + """Helper to remove per-testcase patches installed by :meth:`patch`.""" + # Remove all patches made, ignoring errors. + for p in self.testcase_patches: + p.stop() + # Reset per-test patch control variable. + self.testcase_patches.clear() + + def patch(self, *args, **kwargs): + """ + Install a mock.patch, to be removed after the current test. + + The patch is created with mock.patch(*args, **kwargs). + + Returns: + The substitute object returned by patch.start(). + + For example:: + + mock_call = self.patch('module.Class.call', return_value=1) + module_Class_instance.call(3, 4) + self.assertEqual(mock_call.call_args_list, [mock.call(3, 4)]) + + """ + # Make the new patch and start it. + patch = mock.patch(*args, **kwargs) + start_result = patch.start() + + # Create the per-testcases control variable if it does not exist. + # NOTE: this mimics a setUp method, but continues to work when a + # subclass defines its own setUp. + if not hasattr(self, 'testcase_patches'): + self.testcase_patches = {} + + # When installing the first patch, schedule remove-all at cleanup. + if not self.testcase_patches: + self.addCleanup(self._remove_testcase_patches) + + # Record the new patch and start object for reference. + self.testcase_patches[patch] = start_result + + # Return patch replacement object. + return start_result + + def assertArrayShapeStats(self, result, shape, mean, std_dev, rtol=1e-6): + """ + Assert that the result, a cube, has the provided shape and that the + mean and standard deviation of the data array are also as provided. + Thus build confidence that a cube processing operation, such as a + cube.regrid, has maintained its behaviour. + + """ + self.assertEqual(result.shape, shape) + self.assertArrayAllClose(result.data.mean(), mean, rtol=rtol) + self.assertArrayAllClose(result.data.std(), std_dev, rtol=rtol) + + +# An environment variable controls whether test timings are output. +# +# NOTE: to run tests with timing output, nosetests cannot be used. +# At present, that includes not using "python setup.py test" +# The typically best way is like this : +# $ export IRIS_TEST_TIMINGS=1 +# $ python -m unittest discover -s iris.tests +# and commonly adding ... +# | grep "TIMING TEST" >iris_test_output.txt +# +_PRINT_TEST_TIMINGS = bool(int(os.environ.get('IRIS_TEST_TIMINGS', 0))) + + +def _method_path(meth): + cls = meth.im_class + return '.'.join([cls.__module__, cls.__name__, meth.__name__]) + + +def _testfunction_timing_decorator(fn): + # Function decorator for making a testcase print its execution time. + @functools.wraps(fn) + def inner(*args, **kwargs): + start_time = datetime.datetime.now() + try: + result = fn(*args, **kwargs) + finally: + end_time = datetime.datetime.now() + elapsed_time = (end_time - start_time).total_seconds() + msg = '\n TEST TIMING -- "{}" took : {:12.6f} sec.' + name = _method_path(fn) + print(msg.format(name, elapsed_time)) + return result + return inner + + +def iristest_timing_decorator(cls): + # Class decorator to make all "test_.." functions print execution timings. + if _PRINT_TEST_TIMINGS: + # NOTE: 'dir' scans *all* class properties, including inherited ones. + attr_names = dir(cls) + for attr_name in attr_names: + attr = getattr(cls, attr_name) + if callable(attr) and attr_name.startswith('test'): + attr = _testfunction_timing_decorator(attr) + setattr(cls, attr_name, attr) + return cls + + +class _TestTimingsMetaclass(type): + # An alternative metaclass for IrisTest subclasses, which makes + # them print execution timings for all the testcases. + # This is equivalent to applying the @iristest_timing_decorator to + # every test class that inherits from IrisTest. + # NOTE: however, it means you *cannot* specify a different metaclass for + # your test class inheriting from IrisTest. + # See below for how to solve that where needed. + def __new__(cls, clsname, base_classes, attrs): + result = type.__new__(cls, clsname, base_classes, attrs) + if _PRINT_TEST_TIMINGS: + result = iristest_timing_decorator(result) + return result + + +class IrisTest(six.with_metaclass(_TestTimingsMetaclass, IrisTest_nometa)): + # Derive the 'ordinary' IrisTest from IrisTest_nometa, but add the + # metaclass that enables test timings output. + # This means that all subclasses also get the timing behaviour. + # However, if a different metaclass is *wanted* for an IrisTest subclass, + # this would cause a metaclass conflict. + # Instead, you can inherit from IrisTest_nometa and apply the + # @iristest_timing_decorator explicitly to your new testclass. + pass -class GraphicsTest(IrisTest): + +get_result_path = IrisTest.get_result_path + + +class GraphicsTestMixin(object): + + # nose directive: dispatch tests concurrently. + _multiprocess_can_split_ = True + + def setUp(self): + # Acquire threading non re-entrant blocking lock to ensure + # thread-safe plotting. + _lock.acquire() + # Make sure we have no unclosed plots from previous tests before + # generating this one. + if MPL_AVAILABLE: + plt.close('all') def tearDown(self): # If a plotting test bombs out it can leave the current figure # in an odd state, so we make sure it's been disposed of. - plt.close() + if MPL_AVAILABLE: + plt.close('all') + # Release the non re-entrant blocking lock. + _lock.release() + + +class GraphicsTest(GraphicsTestMixin, IrisTest): + pass + + +class GraphicsTest_nometa(GraphicsTestMixin, IrisTest_nometa): + # Graphicstest without the metaclass providing test timings. + pass + + +class TestGribMessage(IrisTest): + def assertGribMessageContents(self, filename, contents): + """ + Evaluate whether all messages in a GRIB2 file contain the provided + contents. + + * filename (string) + The path on disk of an existing GRIB file + + * contents + An iterable of GRIB message keys and expected values. + + """ + messages = GribMessage.messages_from_filename(filename) + for message in messages: + for element in contents: + section, key, val = element + self.assertEqual(message.sections[section][key], val) + + def assertGribMessageDifference(self, filename1, filename2, diffs, + skip_keys=(), skip_sections=()): + """ + Evaluate that the two messages only differ in the ways specified. + + * filename[0|1] (string) + The path on disk of existing GRIB files + + * diffs + An dictionary of GRIB message keys and expected diff values: + {key: (m1val, m2val),...} . + + * skip_keys + An iterable of key names to ignore during comparison. + + * skip_sections + An iterable of section numbers to ignore during comparison. + + """ + messages1 = list(GribMessage.messages_from_filename(filename1)) + messages2 = list(GribMessage.messages_from_filename(filename2)) + self.assertEqual(len(messages1), len(messages2)) + for m1, m2 in zip(messages1, messages2): + m1_sect = set(m1.sections.keys()) + m2_sect = set(m2.sections.keys()) + + for missing_section in (m1_sect ^ m2_sect): + what = ('introduced' + if missing_section in m1_sect else 'removed') + # Assert that an introduced section is in the diffs. + self.assertIn(missing_section, skip_sections, + msg='Section {} {}'.format(missing_section, + what)) + + for section in (m1_sect & m2_sect): + # For each section, check that the differences are + # known diffs. + m1_keys = set(m1.sections[section]._keys) + m2_keys = set(m2.sections[section]._keys) + + difference = m1_keys ^ m2_keys + unexpected_differences = difference - set(skip_keys) + if unexpected_differences: + self.fail("There were keys in section {} which \n" + "weren't in both messages and which weren't " + "skipped.\n{}" + "".format(section, + ', '.join(unexpected_differences))) + + keys_to_compare = m1_keys & m2_keys - set(skip_keys) + + for key in keys_to_compare: + m1_value = m1.sections[section][key] + m2_value = m2.sections[section][key] + msg = '{} {} != {}' + if key not in diffs: + # We have a key which we expect to be the same for + # both messages. + if isinstance(m1_value, np.ndarray): + # A large tolerance appears to be required for + # gribapi 1.12, but not for 1.14. + self.assertArrayAlmostEqual(m1_value, m2_value, + decimal=2) + else: + self.assertEqual(m1_value, m2_value, + msg=msg.format(key, m1_value, + m2_value)) + else: + # We have a key which we expect to be different + # for each message. + self.assertEqual(m1_value, diffs[key][0], + msg=msg.format(key, m1_value, + diffs[key][0])) + + self.assertEqual(m2_value, diffs[key][1], + msg=msg.format(key, m2_value, + diffs[key][1])) def skip_data(fn): @@ -539,3 +1159,80 @@ class MyDataTests(tests.IrisTest): reason='Test(s) require external data.') return skip(fn) + + +def skip_gdal(fn): + """ + Decorator to choose whether to run tests, based on the availability of the + GDAL library. + + Example usage: + @skip_gdal + class MyGeoTiffTests(test.IrisTest): + ... + + """ + skip = unittest.skipIf( + condition=not GDAL_AVAILABLE, + reason="Test requires 'gdal'.") + return skip(fn) + + +def skip_plot(fn): + """ + Decorator to choose whether to run tests, based on the availability of the + matplotlib library. + + Example usage: + @skip_plot + class MyPlotTests(test.GraphicsTest): + ... + + """ + skip = unittest.skipIf( + condition=not MPL_AVAILABLE, + reason='Graphics tests require the matplotlib library.') + + return skip(fn) + + +skip_grib = unittest.skipIf(not GRIB_AVAILABLE, + 'Test(s) require "iris-grib" package, ' + 'which is not available.') + + +skip_sample_data = unittest.skipIf(not SAMPLE_DATA_AVAILABLE, + ('Test(s) require "iris-sample-data", ' + 'which is not available.')) + + +skip_nc_time_axis = unittest.skipIf( + not NC_TIME_AXIS_AVAILABLE, + 'Test(s) require "nc_time_axis", which is not available.') + + +skip_inet = unittest.skipIf(not INET_AVAILABLE, + ('Test(s) require an "internet connection", ' + 'which is not available.')) + + +skip_stratify = unittest.skipIf( + not STRATIFY_AVAILABLE, + 'Test(s) require "python-stratify", which is not available.') + + +def no_warnings(func): + """ + Provides a decorator to ensure that there are no warnings raised + within the test, otherwise the test will fail. + + """ + @functools.wraps(func) + def wrapped(self, *args, **kwargs): + with mock.patch('warnings.warn') as warn: + result = func(self, *args, **kwargs) + self.assertEqual(0, warn.call_count, + ('Got unexpected warnings.' + ' \n{}'.format(warn.call_args_list))) + return result + return wrapped diff --git a/lib/iris/tests/analysis/__init__.py b/lib/iris/tests/analysis/__init__.py deleted file mode 100644 index c382fa7b10..0000000000 --- a/lib/iris/tests/analysis/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -# (C) British Crown Copyright 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -""" -Package for testing the iris.analysis package. - -""" diff --git a/lib/iris/tests/analysis/test_interpolate.py b/lib/iris/tests/analysis/test_interpolate.py deleted file mode 100644 index 9f4d41aff4..0000000000 --- a/lib/iris/tests/analysis/test_interpolate.py +++ /dev/null @@ -1,65 +0,0 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -""" -Test the iris.analysis.interpolate module. - -""" -# Import iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -import numpy as np - -import iris.analysis.interpolate as interpolate -from iris.coords import DimCoord -from iris.cube import Cube -from iris.tests.test_interpolation import normalise_order - - -class Test_linear__circular_wrapping(tests.IrisTest): - def _create_cube(self, longitudes): - # Return a Cube with circular longitude with the given values. - data = np.arange(12).reshape((3, 4)) * 0.1 - cube = Cube(data) - lon = DimCoord(longitudes, standard_name='longitude', - units='degrees', circular=True) - cube.add_dim_coord(lon, 1) - return cube - - def test_symmetric(self): - # Check we can interpolate from a Cube defined over [-180, 180). - cube = self._create_cube([-180, -90, 0, 90]) - samples = [('longitude', range(-360, 720, 45))] - result = interpolate.linear(cube, samples) - normalise_order(result) - self.assertCMLApproxData(result, ('analysis', 'interpolation', - 'linear', 'circular_wrapping', - 'symmetric')) - - def test_positive(self): - # Check we can interpolate from a Cube defined over [0, 360). - cube = self._create_cube([0, 90, 180, 270]) - samples = [('longitude', range(-360, 720, 45))] - result = interpolate.linear(cube, samples) - normalise_order(result) - self.assertCMLApproxData(result, ('analysis', 'interpolation', - 'linear', 'circular_wrapping', - 'positive')) - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/analysis/test_maths.py b/lib/iris/tests/analysis/test_maths.py deleted file mode 100644 index db8eb0112c..0000000000 --- a/lib/iris/tests/analysis/test_maths.py +++ /dev/null @@ -1,61 +0,0 @@ -# (C) British Crown Copyright 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -""" -Test the iris.analysis.maths module. - -""" -# Import iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -import iris.analysis -import iris.tests.stock as stock - - -class Test_maths_broadcasting(tests.IrisTest): - """ - Additional tests for iris.analysis.maths to test simple cube - cube.data broadcasting in_add_subtract_common() - - """ - def setUp(self): - self.cube1 = stock.simple_3d() - iris.analysis.clear_phenomenon_identity(self.cube1) - self.cube2 = stock.simple_3d_w_multidim_coords() - iris.analysis.clear_phenomenon_identity(self.cube2) - - def test_same(self): - # Addition/subtraction when both cubes are the same - other = self.cube1 - new_cube = self.cube1 + other - other - self.assertEqual(new_cube, self.cube1) - - def test_collapse_outer_dim_addsub(self): - # Collapse other's outer dim (wibble: 0) - other = self.cube1.collapsed('wibble', iris.analysis.MIN) - new_cube = self.cube1 + other - other - self.assertEqual(new_cube, self.cube1) - - def test_collapse_inner_dim(self): - # Collapse an inner dim (latitude: 0) - other = self.cube1.collapsed('latitude', iris.analysis.MIN) - with self.assertRaises(ValueError): - new_cube = self.cube1 + other - other - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/analysis/test_stats.py b/lib/iris/tests/analysis/test_stats.py deleted file mode 100644 index 875c8ab32d..0000000000 --- a/lib/iris/tests/analysis/test_stats.py +++ /dev/null @@ -1,103 +0,0 @@ -# (C) British Crown Copyright 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -""" -Test the iris.analysis.stats module. - -""" -# Import iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -import numpy as np - -import iris -import iris.analysis.stats as stats - - -@iris.tests.skip_data -class Test_corr(tests.IrisTest): - def setUp(self): - self.cube_a = iris.load_cube(iris.sample_data_path('GloSea4', - 'ensemble_001.pp')) - self.cube_b = iris.load_cube(iris.sample_data_path('GloSea4', - 'ensemble_002.pp')) - - def test_perfect_corr(self): - r = stats.pearsonr(self.cube_a, self.cube_a, - ['latitude', 'longitude']) - self.assertArrayEqual(r.data, np.array([1.]*6)) - - def test_perfect_corr_all_dims(self): - r = stats.pearsonr(self.cube_a, self.cube_a) - self.assertArrayEqual(r.data, np.array([1.])) - - def test_incompatible_cubes(self): - with self.assertRaises(ValueError): - stats.pearsonr(self.cube_a, self.cube_b[0, :, :], 'time') - - def test_compatible_cubes(self): - r = stats.pearsonr(self.cube_a, self.cube_b, ['latitude', 'longitude']) - self.assertArrayAlmostEqual(r.data, [0.99733591, - 0.99501693, - 0.99674225, - 0.99495268, - 0.99217004, - 0.99362189]) - - def test_4d_cube_2_dims(self): - real_0_c = iris.coords.AuxCoord(np.int32(0), 'realization') - real_1_c = iris.coords.AuxCoord(np.int32(1), 'realization') - - # Make cubes merge-able. - self.cube_a.add_aux_coord(real_0_c) - self.cube_b.add_aux_coord(real_1_c) - self.cube_a.remove_coord('forecast_period') - self.cube_a.remove_coord('forecast_reference_time') - self.cube_b.remove_coord('forecast_period') - self.cube_b.remove_coord('forecast_reference_time') - four_d_cube_a = iris.cube\ - .CubeList([self.cube_a, self.cube_b]).merge()[0] - self.cube_a.remove_coord('realization') - self.cube_b.remove_coord('realization') - self.cube_a.add_aux_coord(real_1_c) - self.cube_b.add_aux_coord(real_0_c) - four_d_cube_b = iris.cube\ - .CubeList([self.cube_a, self.cube_b]).merge()[0] - - r = stats.pearsonr(four_d_cube_a, four_d_cube_b, - ['latitude', 'longitude']) - expected_corr = [[0.99733591, - 0.99501693, - 0.99674225, - 0.99495268, - 0.99217004, - 0.99362189], - [0.99733591, - 0.99501693, - 0.99674225, - 0.99495268, - 0.99217004, - 0.99362189]] - self.assertArrayAlmostEqual(r.data, expected_corr) - - def test_non_existent_coord(self): - with self.assertRaises(ValueError): - stats.pearsonr(self.cube_a, self.cube_b, 'bad_coord') - - -if __name__ == '__main__': - tests.main() diff --git a/lib/iris/tests/experimental/__init__.py b/lib/iris/tests/experimental/__init__.py index c7ca31fee8..ae127f0615 100644 --- a/lib/iris/tests/experimental/__init__.py +++ b/lib/iris/tests/experimental/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -18,3 +18,6 @@ Experimental code is tested in this package. """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/experimental/regrid/__init__.py b/lib/iris/tests/experimental/regrid/__init__.py index 19ed289813..f6cdfa815a 100644 --- a/lib/iris/tests/experimental/regrid/__init__.py +++ b/lib/iris/tests/experimental/regrid/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -18,3 +18,6 @@ Regridding code is tested in this package. """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/experimental/regrid/test_regrid_area_weighted_rectilinear_src_and_grid.py b/lib/iris/tests/experimental/regrid/test_regrid_area_weighted_rectilinear_src_and_grid.py index ed86770fc4..cce1c0e671 100644 --- a/lib/iris/tests/experimental/regrid/test_regrid_area_weighted_rectilinear_src_and_grid.py +++ b/lib/iris/tests/experimental/regrid/test_regrid_area_weighted_rectilinear_src_and_grid.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2018, Met Office # # This file is part of Iris. # @@ -18,6 +18,10 @@ Test area weighted regridding. """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised # before importing anything else. import iris.tests as tests @@ -25,16 +29,14 @@ import copy import random -import matplotlib.pyplot as plt import numpy as np import numpy.ma as ma from iris.experimental.regrid import \ regrid_area_weighted_rectilinear_src_and_grid as regrid_area_weighted -import iris.quickplot as qplt +import iris.analysis._interpolation import iris.tests.stock - RESULT_DIR = ('experimental', 'regrid', 'regrid_area_weighted_rectilinear_src_and_grid') @@ -46,7 +48,7 @@ def _scaled_and_offset_grid(cube, x_scalefactor, y_scalefactor, from the horizontal grid of `src`. """ - x, y = iris.experimental.regrid._get_xy_dim_coords(cube) + x, y = iris.analysis._interpolation.get_xy_dim_coords(cube) new_cube = cube.copy() new_cube.replace_coord(x * x_scalefactor + x_offset) new_cube.replace_coord(y * y_scalefactor + y_offset) @@ -84,7 +86,7 @@ def _subsampled_grid(cube, x_subsamplefactor, y_subsamplefactor): .. note:: The data of the returned cube is populated with zeros. """ - x, y = iris.experimental.regrid._get_xy_dim_coords(cube) + x, y = iris.analysis._interpolation.get_xy_dim_coords(cube) x_dim = cube.coord_dims(x)[0] y_dim = cube.coord_dims(y)[0] new_x = _subsampled_coord(x, x_subsamplefactor) @@ -137,7 +139,7 @@ def _resampled_grid(cube, x_samplefactor, y_samplefactor): .. note:: The data of the returned cube is populated with zeros. """ - x, y = iris.experimental.regrid._get_xy_dim_coords(cube) + x, y = iris.analysis._interpolation.get_xy_dim_coords(cube) x_dim = cube.coord_dims(x)[0] y_dim = cube.coord_dims(y)[0] new_x = _resampled_coord(x, x_samplefactor) @@ -153,7 +155,8 @@ def _resampled_grid(cube, x_samplefactor, y_samplefactor): return new_cube -class TestAreaWeightedRegrid(tests.GraphicsTest): +@tests.skip_data +class TestAreaWeightedRegrid(tests.IrisTest): def setUp(self): # A cube with a hybrid height derived coordinate. self.realistic_cube = iris.tests.stock.realistic_4d()[:2, :5, :20, :30] @@ -364,19 +367,6 @@ def test_hybrid_height(self): dest = _resampled_grid(src, 0.7, 0.8) res = regrid_area_weighted(src, dest) self.assertCMLApproxData(res, RESULT_DIR + ('hybridheight.cml',)) - # Consider a single slice to allow visual tests of altitudes. - src = src[1, 2] - res = res[1, 2] - qplt.pcolormesh(res) - self.check_graphic() - plt.contourf(res.coord('grid_longitude').points, - res.coord('grid_latitude').points, - res.coord('altitude').points) - self.check_graphic() - plt.contourf(res.coord('grid_longitude').points, - res.coord('grid_latitude').points, - res.coord('surface_altitude').points) - self.check_graphic() def test_missing_data(self): src = self.simple_cube.copy() @@ -448,10 +438,6 @@ def test_cross_section(self): res = regrid_area_weighted(src, dest) self.assertCMLApproxData(res, RESULT_DIR + ('const_lat_cross_section.cml',)) - # Plot a single slice. - qplt.plot(res[0]) - qplt.plot(src[0], 'r') - self.check_graphic() # Constant longitude src = self.realistic_cube[0, :, :, 10] @@ -465,10 +451,6 @@ def test_cross_section(self): res = regrid_area_weighted(src, dest) self.assertCMLApproxData(res, RESULT_DIR + ('const_lon_cross_section.cml',)) - # Plot a single slice. - qplt.plot(res[0]) - qplt.plot(src[0], 'r') - self.check_graphic() def test_scalar_source_cube(self): src = self.simple_cube[1, 2] @@ -491,8 +473,7 @@ def test_global_data_reduce_res(self): src.coord('longitude').guess_bounds() dest = _resampled_grid(src, 0.4, 0.3) res = regrid_area_weighted(src, dest) - qplt.pcolormesh(res) - self.check_graphic() + self.assertArrayShapeStats(res, (21, 38), 280.484932, 15.831545) @tests.skip_data def test_global_data_increase_res(self): @@ -501,8 +482,7 @@ def test_global_data_increase_res(self): src.coord('longitude').guess_bounds() dest = _resampled_grid(src, 1.5, 1.5) res = regrid_area_weighted(src, dest) - qplt.pcolormesh(res) - self.check_graphic() + self.assertArrayShapeStats(res, (109, 144), 280.349625, 16.073397) @tests.skip_data def test_global_data_same_res(self): @@ -510,8 +490,7 @@ def test_global_data_same_res(self): src.coord('latitude').guess_bounds() src.coord('longitude').guess_bounds() res = regrid_area_weighted(src, src) - qplt.pcolormesh(res) - self.check_graphic() + self.assertArrayShapeStats(res, (73, 96), 279.945160, 16.345842) @tests.skip_data def test_global_data_subset(self): @@ -531,9 +510,7 @@ def test_global_data_subset(self): dest.add_dim_coord(dest_lon, 1) res = regrid_area_weighted(src, dest) - qplt.pcolormesh(res) - plt.gca().coastlines() - self.check_graphic() + self.assertArrayShapeStats(res, (40, 30), 280.979310, 16.640421) @tests.skip_data def test_circular_subset(self): @@ -553,9 +530,7 @@ def test_circular_subset(self): dest.add_dim_coord(dest_lon, 1) res = regrid_area_weighted(src, dest) - qplt.pcolormesh(res) - plt.gca().coastlines() - self.check_graphic() + self.assertArrayShapeStats(res, (40, 7), 285.653960, 15.212710) @tests.skip_data def test_non_circular_subset(self): @@ -576,9 +551,7 @@ def test_non_circular_subset(self): dest.add_dim_coord(dest_lon, 1) res = regrid_area_weighted(src, dest) - qplt.pcolormesh(res) - plt.gca().coastlines() - self.check_graphic() + self.assertArrayShapeStats(res, (40, 7), 285.550814, 15.190245) if __name__ == "__main__": diff --git a/lib/iris/tests/experimental/regrid/test_regrid_bilinear_rectilinear_src_and_grid.py b/lib/iris/tests/experimental/regrid/test_regrid_bilinear_rectilinear_src_and_grid.py deleted file mode 100644 index 078d276853..0000000000 --- a/lib/iris/tests/experimental/regrid/test_regrid_bilinear_rectilinear_src_and_grid.py +++ /dev/null @@ -1,401 +0,0 @@ -# (C) British Crown Copyright 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . - -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -import numpy as np - -import iris -import iris.quickplot as qplt -from iris.experimental.regrid import \ - regrid_bilinear_rectilinear_src_and_grid as regrid -from iris.aux_factory import HybridHeightFactory -from iris.coord_systems import GeogCS, OSGB -from iris.coords import AuxCoord, DimCoord -from iris.cube import Cube -from iris.tests.stock import global_pp, realistic_4d - - -RESULT_DIR = ('experimental', 'regrid', - 'regrid_bilinear_rectilinear_src_and_grid') - - -@tests.skip_data -class TestInvalid(tests.IrisTest): - def test_non_cube(self): - array = np.zeros((3, 4)) - cube = global_pp() - with self.assertRaises(TypeError): - regrid(array, cube) - with self.assertRaises(TypeError): - regrid(cube, array) - with self.assertRaises(TypeError): - regrid(42, cube) - with self.assertRaises(TypeError): - regrid(cube, 42) - - def test_non_rectilinear_src(self): - ok = global_pp() - - # Lat and/or lon missing - bad = global_pp() - bad.remove_coord('latitude') - with self.assertRaises(ValueError): - regrid(bad, ok) - with self.assertRaises(ValueError): - regrid(ok, bad) - - bad = global_pp() - bad.remove_coord('longitude') - with self.assertRaises(ValueError): - regrid(bad, ok) - with self.assertRaises(ValueError): - regrid(ok, bad) - - bad = global_pp() - bad.remove_coord('latitude') - bad.remove_coord('longitude') - with self.assertRaises(ValueError): - regrid(bad, ok) - with self.assertRaises(ValueError): - regrid(ok, bad) - - # Lat/lon not a DimCoord - def demote_coord(coord_name): - bad = global_pp() - coord = bad.coord(coord_name) - dims = bad.coord_dims(coord) - bad.remove_coord(coord_name) - aux_coord = AuxCoord.from_coord(coord) - bad.add_aux_coord(aux_coord, dims) - with self.assertRaises(ValueError): - regrid(bad, ok) - with self.assertRaises(ValueError): - regrid(ok, bad) - demote_coord('latitude') - demote_coord('longitude') - - # Lat/lon share a single dimension - bad = global_pp() - lat = bad.coord('latitude') - bad = bad[0, :lat.shape[0]] - bad.remove_coord('latitude') - bad.add_aux_coord(lat, 0) - with self.assertRaises(ValueError): - regrid(bad, ok) - with self.assertRaises(ValueError): - regrid(ok, bad) - - def test_bad_georeference(self): - ok = global_pp() - - bad = global_pp() - bad.coord('latitude').coord_system = None - bad.coord('longitude').coord_system = None - with self.assertRaises(ValueError): - regrid(bad, ok) - with self.assertRaises(ValueError): - regrid(ok, bad) - - bad = global_pp() - bad.coord('latitude').coord_system = None - bad.coord('longitude').coord_system = GeogCS(6371000) - with self.assertRaises(ValueError): - regrid(bad, ok) - with self.assertRaises(ValueError): - regrid(ok, bad) - - bad = global_pp() - bad.coord('latitude').coord_system = GeogCS(6370000) - bad.coord('longitude').coord_system = GeogCS(6371000) - with self.assertRaises(ValueError): - regrid(bad, ok) - with self.assertRaises(ValueError): - regrid(ok, bad) - - def test_bad_units(self): - ok = global_pp() - - bad = global_pp() - bad.coord('longitude').units = 'radians' - with self.assertRaises(ValueError): - regrid(bad, ok) - with self.assertRaises(ValueError): - regrid(ok, bad) - - bad = Cube(np.arange(12, dtype=np.float32).reshape(3, 4)) - cs = OSGB() - y_coord = DimCoord(range(3), 'projection_y_coordinate', units='m', - coord_system=cs) - x_coord = DimCoord(range(4), 'projection_x_coordinate', units='km', - coord_system=cs) - bad.add_dim_coord(y_coord, 0) - bad.add_dim_coord(x_coord, 1) - with self.assertRaises(ValueError): - regrid(bad, ok) - with self.assertRaises(ValueError): - regrid(ok, bad) - - -@tests.skip_data -class TestRotatedToLatLon(tests.IrisTest): - def setUp(self): - self.src = realistic_4d()[:5, :2, ::40, ::30] - - def test_single_point(self): - src = self.src[0, 0] - grid = global_pp()[:1, :1] - # These coordinate values have been derived by converting the - # rotated coordinates of src[1, 1] into lat/lon by using cs2cs. - grid.coord('longitude').points = -3.144870 - grid.coord('latitude').points = 52.406444 - result = regrid(src, grid) - self.assertEqual(src.data[1, 1], result.data) - - def test_transposed_src(self): - # The source dimensions are in a non-standard order. - src = self.src - src.transpose([3, 1, 2, 0]) - grid = self._grid_subset() - result = regrid(src, grid) - result.transpose([3, 1, 2, 0]) - self.assertCMLApproxData(result, RESULT_DIR + ('subset.cml',)) - - def _grid_subset(self): - # The destination grid points are entirely contained within the - # src grid points. - grid = global_pp()[:4, :5] - grid.coord('longitude').points = np.linspace(-3.182, -3.06, 5) - grid.coord('latitude').points = np.linspace(52.372, 52.44, 4) - return grid - - def test_reversed(self): - src = self.src - grid = self._grid_subset() - result = regrid(src, grid[::-1]) - self.assertCMLApproxData(result[:, :, ::-1], - RESULT_DIR + ('subset.cml',)) - result = regrid(src[:, :, ::-1], grid[::-1]) - self.assertCMLApproxData(result[:, :, ::-1], - RESULT_DIR + ('subset.cml',)) - result = regrid(src[:, :, :, ::-1], grid[::-1]) - self.assertCMLApproxData(result[:, :, ::-1], - RESULT_DIR + ('subset.cml',)) - result = regrid(src[:, :, ::-1, ::-1], grid[::-1]) - self.assertCMLApproxData(result[:, :, ::-1], - RESULT_DIR + ('subset.cml',)) - - result = regrid(src, grid[:, ::-1]) - self.assertCMLApproxData(result[:, :, :, ::-1], - RESULT_DIR + ('subset.cml',)) - result = regrid(src[:, :, ::-1], grid[:, ::-1]) - self.assertCMLApproxData(result[:, :, :, ::-1], - RESULT_DIR + ('subset.cml',)) - result = regrid(src[:, :, :, ::-1], grid[:, ::-1]) - self.assertCMLApproxData(result[:, :, :, ::-1], - RESULT_DIR + ('subset.cml',)) - result = regrid(src[:, :, ::-1, ::-1], grid[:, ::-1]) - self.assertCMLApproxData(result[:, :, :, ::-1], - RESULT_DIR + ('subset.cml',)) - - result = regrid(src, grid[::-1, ::-1]) - self.assertCMLApproxData(result[:, :, ::-1, ::-1], - RESULT_DIR + ('subset.cml',)) - result = regrid(src[:, :, ::-1], grid[::-1, ::-1]) - self.assertCMLApproxData(result[:, :, ::-1, ::-1], - RESULT_DIR + ('subset.cml',)) - result = regrid(src[:, :, :, ::-1], grid[::-1, ::-1]) - self.assertCMLApproxData(result[:, :, ::-1, ::-1], - RESULT_DIR + ('subset.cml',)) - result = regrid(src[:, :, ::-1, ::-1], grid[::-1, ::-1]) - self.assertCMLApproxData(result[:, :, ::-1, ::-1], - RESULT_DIR + ('subset.cml',)) - - def test_grid_subset(self): - # The destination grid points are entirely contained within the - # src grid points. - grid = self._grid_subset() - result = regrid(self.src, grid) - self.assertCMLApproxData(result, RESULT_DIR + ('subset.cml',)) - - def _big_grid(self): - grid = self._grid_subset() - big_grid = Cube(np.zeros((5, 10, 3, 4, 5))) - big_grid.add_dim_coord(grid.coord('latitude'), 3) - big_grid.add_dim_coord(grid.coord('longitude'), 4) - return big_grid - - def test_grid_subset_big(self): - # Add some extra dimensions to the destination Cube and - # these should be safely ignored. - big_grid = self._big_grid() - result = regrid(self.src, big_grid) - self.assertCMLApproxData(result, RESULT_DIR + ('subset.cml',)) - - def test_grid_subset_big_transposed(self): - # The order of the grid's dimensions (including the X and Y - # dimensions) must not affect the result. - big_grid = self._big_grid() - big_grid.transpose([4, 0, 3, 1, 2]) - result = regrid(self.src, big_grid) - self.assertCMLApproxData(result, RESULT_DIR + ('subset.cml',)) - - def test_grid_subset_anon(self): - # Must cope OK with anonymous source dimensions. - src = self.src - src.remove_coord('time') - grid = self._grid_subset() - result = regrid(src, grid) - self.assertCMLApproxData(result, RESULT_DIR + ('subset_anon.cml',)) - - def test_grid_subset_missing_data_1(self): - # The destination grid points are entirely contained within the - # src grid points AND we have missing data. - src = self.src - src.data = np.ma.MaskedArray(src.data) - src.data[:, :, 0, 0] = np.ma.masked - grid = self._grid_subset() - result = regrid(src, grid) - self.assertCMLApproxData(result, RESULT_DIR + ('subset_masked_1.cml',)) - - def test_grid_subset_missing_data_2(self): - # The destination grid points are entirely contained within the - # src grid points AND we have missing data. - src = self.src - src.data = np.ma.MaskedArray(src.data) - src.data[:, :, 1, 2] = np.ma.masked - grid = self._grid_subset() - result = regrid(src, grid) - self.assertCMLApproxData(result, RESULT_DIR + ('subset_masked_2.cml',)) - - def test_grid_partial_overlap(self): - # The destination grid points are partially contained within the - # src grid points. - grid = global_pp()[:4, :4] - grid.coord('longitude').points = np.linspace(-3.3, -3.06, 4) - grid.coord('latitude').points = np.linspace(52.377, 52.43, 4) - result = regrid(self.src, grid) - self.assertCMLApproxData(result, RESULT_DIR + ('partial_overlap.cml',)) - - def test_grid_no_overlap(self): - # The destination grid points are NOT contained within the - # src grid points. - grid = global_pp()[:4, :4] - grid.coord('longitude').points = np.linspace(-3.3, -3.2, 4) - grid.coord('latitude').points = np.linspace(52.377, 52.43, 4) - result = regrid(self.src, grid) - self.assertCMLApproxData(result, RESULT_DIR + ('no_overlap.cml',)) - - -class TestNOP(tests.IrisTest): - def test_nop(self): - # The destination grid points are exactly the same as the - # src grid points. - src = realistic_4d()[:5, :2, ::40, ::30] - grid = src.copy() - result = regrid(src, grid) - self.assertEqual(result, src) - - -@tests.skip_data -class TestCircular(tests.IrisTest): - def setUp(self): - src = global_pp()[::10, ::10] - level_height = AuxCoord(0, long_name='level_height', units='m', - attributes={'positive': 'up'}) - sigma = AuxCoord(1, long_name='sigma') - surface_altitude = AuxCoord((src.data - src.data.min()) * 50, - 'surface_altitude', units='m') - src.add_aux_coord(level_height) - src.add_aux_coord(sigma) - src.add_aux_coord(surface_altitude, [0, 1]) - hybrid_height = HybridHeightFactory(level_height, sigma, - surface_altitude) - src.add_aux_factory(hybrid_height) - self.src = src - - grid = global_pp()[:4, :4] - grid.coord('longitude').points = grid.coord('longitude').points - 5 - self.grid = grid - - def test_non_circular(self): - # Non-circular src -> non-circular grid - result = regrid(self.src, self.grid) - self.assertFalse(result.coord('longitude').circular) - self.assertCMLApproxData(result, RESULT_DIR + ('non_circular.cml',)) - - def test_circular_src(self): - # Circular src -> non-circular grid - src = self.src - src.coord('longitude').circular = True - result = regrid(src, self.grid) - self.assertFalse(result.coord('longitude').circular) - self.assertCMLApproxData(result, RESULT_DIR + ('circular_src.cml',)) - - def test_circular_grid(self): - # Non-circular src -> circular grid - grid = self.grid - grid.coord('longitude').circular = True - result = regrid(self.src, grid) - self.assertTrue(result.coord('longitude').circular) - self.assertCMLApproxData(result, RESULT_DIR + ('circular_grid.cml',)) - - def test_circular_src_and_grid(self): - # Circular src -> circular grid - src = self.src - src.coord('longitude').circular = True - grid = self.grid - grid.coord('longitude').circular = True - result = regrid(src, grid) - self.assertTrue(result.coord('longitude').circular) - self.assertCMLApproxData(result, RESULT_DIR + ('both_circular.cml',)) - - -@tests.skip_data -class TestVisual(tests.GraphicsTest): - def test_osgb_to_latlon(self): - path = tests.get_data_path( - ('NIMROD', 'uk2km', 'WO0000000003452', - '201007020900_u1096_ng_ey00_visibility0180_screen_2km')) - src = iris.load_cube(path)[0] - src.data = src.data.astype(np.float32) - grid = Cube(np.empty((73, 96))) - cs = GeogCS(6370000) - lat = DimCoord(np.linspace(46, 65, 73), 'latitude', units='degrees', - coord_system=cs) - lon = DimCoord(np.linspace(-14, 8, 96), 'longitude', units='degrees', - coord_system=cs) - grid.add_dim_coord(lat, 0) - grid.add_dim_coord(lon, 1) - result = regrid(src, grid) - qplt.pcolor(result, antialiased=False) - qplt.plt.gca().coastlines() - self.check_graphic() - - def test_subsample(self): - src = global_pp() - grid = src[::2, ::3] - result = regrid(src, grid) - qplt.pcolormesh(result) - qplt.plt.gca().coastlines() - self.check_graphic() - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/experimental/regrid/test_regrid_conservative_via_esmpy.py b/lib/iris/tests/experimental/regrid/test_regrid_conservative_via_esmpy.py index c6fa132c0d..1e1de2ba9f 100644 --- a/lib/iris/tests/experimental/regrid/test_regrid_conservative_via_esmpy.py +++ b/lib/iris/tests/experimental/regrid/test_regrid_conservative_via_esmpy.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -19,6 +19,9 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised # before importing anything else. import iris.tests as tests @@ -27,14 +30,13 @@ import os import unittest +import cf_units import numpy as np # Import ESMF if installed, else fail quietly + disable all the tests. try: import ESMF - # Check it *is* the real module, and not an iris.proxy FakeModule. - ESMF.Manager -except ImportError, AttributeError: +except ImportError as AttributeError: ESMF = None skip_esmf = unittest.skipIf( condition=ESMF is None, @@ -77,13 +79,13 @@ def _make_test_cube(shape, xlims, ylims, pole_latlon=None): co_x = iris.coords.DimCoord(xvals, standard_name=coordname_prefix + 'longitude', - units=iris.unit.Unit('degrees'), + units=cf_units.Unit('degrees'), coord_system=cs) co_x.guess_bounds() cube.add_dim_coord(co_x, 1) co_y = iris.coords.DimCoord(yvals, standard_name=coordname_prefix + 'latitude', - units=iris.unit.Unit('degrees'), + units=cf_units.Unit('degrees'), coord_system=cs) co_y.guess_bounds() cube.add_dim_coord(co_y, 0) @@ -126,22 +128,6 @@ def _donothing_context_manager(): @skip_esmf class TestConservativeRegrid(tests.IrisTest): - @classmethod - def setUpClass(cls): - # Pre-initialise ESMF, just to avoid warnings about no logfile. - # NOTE: noisy if logging is off, and no control of filepath. Boo!! - if ESMF is not None: - # WARNING: nosetest calls class setUp/tearDown even when "skipped". - cls._emsf_logfile_path = os.path.join(os.getcwd(), 'ESMF_LogFile') - ESMF.Manager(logkind=ESMF.LogKind.SINGLE, debug=False) - - @classmethod - def tearDownClass(cls): - # remove the logfile if we can, just to be tidy - if ESMF is not None: - # WARNING: nosetest calls class setUp/tearDown even when "skipped". - if os.path.exists(cls._emsf_logfile_path): - os.remove(cls._emsf_logfile_path) def setUp(self): # Compute basic test data cubes. @@ -238,6 +224,7 @@ def test_simple_missing_data(self): [True, False, False, False, True], [True, True, True, True, True]]) + @tests.skip_data def test_multidimensional(self): """ Check valid operation on a multidimensional cube. @@ -265,8 +252,8 @@ def test_multidimensional(self): ylims = _minmax(c1.coord(axis='y').contiguous_bounds()) # Reduce the dimensions slightly to avoid NaNs in regridded orography delta = 0.05 - # NOTE: this is *not* a small amount. Think there is a bug. - # NOTE: See https://github.com/SciTools/iris/issues/458 + # || NOTE: this is *not* a small amount. Think there is a bug. + # || NOTE: See https://github.com/SciTools/iris/issues/458 xlims = np.interp([delta, 1.0 - delta], [0, 1], xlims) ylims = np.interp([delta, 1.0 - delta], [0, 1], ylims) pole_latlon = (c1_cs.grid_north_pole_latitude, @@ -373,7 +360,7 @@ def test_global_collapse(self): c2.add_dim_coord(x_coord_2, 1) # NOTE: at present, this causes an error inside ESMF ... - context = self.assertRaises(NameError) + context = self.assertRaises(ValueError) global_cell_supported = False if global_cell_supported: context = _donothing_context_manager() @@ -409,12 +396,10 @@ def test_single_cells(self): c1x1 = regrid_conservative_via_esmpy(c1, c1x1_gridcube) c1x1_areasum = _cube_area_sum(c1x1) # Check the total area sum is still the same - # NOTE: at present, this causes an error inside ESMF ... - context = self.assertRaises(AssertionError) condense_to_1x1_supported = False + # NOTE: currently disabled (ESMF gets this wrong) + # NOTE ALSO: call hits numpy 1.7 bug in testing.assert_array_compare. if condense_to_1x1_supported: - context = _donothing_context_manager() - with context: self.assertArrayAllClose(c1x1_areasum, c1_areasum) # Condense entire region onto a single cell covering the area of 'c2' @@ -422,11 +407,11 @@ def test_single_cells(self): ylims2 = _minmax(c2.coord(axis='y').bounds) x_c2x1 = iris.coords.DimCoord(xlims2[0], bounds=xlims2, standard_name='longitude', - units=iris.unit.Unit('degrees'), + units=cf_units.Unit('degrees'), coord_system=_PLAIN_GEODETIC_CS) y_c2x1 = iris.coords.DimCoord(ylims2[0], bounds=ylims2, standard_name='latitude', - units=iris.unit.Unit('degrees'), + units=cf_units.Unit('degrees'), coord_system=_PLAIN_GEODETIC_CS) c2x1_gridcube = iris.cube.Cube([[0.0]]) c2x1_gridcube.add_dim_coord(y_c2x1, 0) @@ -495,7 +480,7 @@ def test_longitude_wraps(self): c1toc2 = regrid_conservative_via_esmpy(c1, c2) # Now redo with dst longitudes rotated, so 'seam' is somewhere else. - x2_shift_steps = int(shape2[0] / 3) + x2_shift_steps = shape2[0] // 3 xlims2_shifted = np.array(xlims_2) + 360.0 * x2_shift_steps / shape2[0] c2_shifted = _make_test_cube(shape2, xlims2_shifted, ylims_2, pole_latlon=(47.4, 25.7)) @@ -506,7 +491,7 @@ def test_longitude_wraps(self): self.assertArrayAllClose(rolled_data, c1toc2.data) # Repeat with rolled *source* data : result should be identical - x1_shift_steps = int(shape1[0] / 3) + x1_shift_steps = shape1[0] // 3 x_shift_degrees = 360.0 * x1_shift_steps / shape1[0] xlims1_shifted = [x - x_shift_degrees for x in xlims1] c1_shifted = _make_test_cube(shape1, xlims1_shifted, ylims1) diff --git a/lib/iris/tests/experimental/test_animate.py b/lib/iris/tests/experimental/test_animate.py index 01ca682ba0..2342ecc557 100644 --- a/lib/iris/tests/experimental/test_animate.py +++ b/lib/iris/tests/experimental/test_animate.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2016, Met Office # # This file is part of Iris. # @@ -19,22 +19,28 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised before # importing anything else import iris.tests as tests -import itertools - import numpy as np import iris from iris.coord_systems import GeogCS -import iris.experimental.animate as animate -import iris.plot as iplt + +# Run tests in no graphics mode if matplotlib is not available. +if tests.MPL_AVAILABLE: + import iris.experimental.animate as animate + import iris.plot as iplt +@tests.skip_plot class IntegrationTest(tests.GraphicsTest): def setUp(self): + super(IntegrationTest, self).setUp() cube = iris.cube.Cube(np.arange(36, dtype=np.int32).reshape((3, 3, 4))) cs = GeogCS(6371229) @@ -69,7 +75,7 @@ def test_cube_animation(self): ani = [ani] # Extract frame data - for data in itertools.izip(*[a.new_saved_frame_seq() for a in ani]): + for data in zip(*[a.new_saved_frame_seq() for a in ani]): # Draw each frame for anim, d in zip(ani, data): anim._draw_next_frame(d, blit=False) diff --git a/lib/iris/tests/experimental/test_raster.py b/lib/iris/tests/experimental/test_raster.py index 152e7893a9..25fe54b269 100644 --- a/lib/iris/tests/experimental/test_raster.py +++ b/lib/iris/tests/experimental/test_raster.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2014 - 2016, Met Office # # This file is part of Iris. # @@ -14,38 +14,57 @@ # # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + import iris.tests as tests -import iris.experimental.raster +import iris import numpy as np import PIL.Image -@iris.tests.skip_data -class TestGeoTiffExport(tests.GraphicsTest): - def check_tiff_header(self, geotiff_fh, reference_filename): +@tests.skip_gdal +@tests.skip_data +class TestGeoTiffExport(tests.IrisTest): + def check_tiff_header(self, tiff_filename, expect_keys, expect_entries): """ - Checks the given tiff file handle's metadata matches the - reference file contents. + Checks the given tiff file's metadata contains the expected keys, + and some matching values (not all). """ - im = PIL.Image.open(geotiff_fh) - tiff_header = '\n'.join(str((tag, val)) - for tag, val in sorted(im.tag.items())) - - reference_path = tests.get_result_path(reference_filename) - - self._check_same(tiff_header, reference_path, reference_filename, - type_comparison_name='Tiff header') - - def check_tiff(self, cube, tif_header): + with open(tiff_filename, 'rb') as fh: + im = PIL.Image.open(fh) + file_keys = im.tag.keys() + + missing_keys = sorted(set(expect_keys) - set(file_keys)) + msg_nokeys = "Tiff header has missing keys : {}." + self.assertEqual(missing_keys, [], + msg_nokeys.format(missing_keys)) + + extra_keys = sorted(set(file_keys) - set(expect_keys)) + msg_extrakeys = "Tiff header has extra unexpected keys : {}." + self.assertEqual(extra_keys, [], + msg_extrakeys.format(extra_keys)) + + msg_badval = "Tiff header entry {} has value {} != {}." + for key, value in expect_entries.items(): + content = im.tag[key] + self.assertEqual(content, value, + msg_badval.format(key, content, value)) + + def check_tiff(self, cube, header_keys, header_items): + # Check that the cube saves correctly to TIFF : + # * the header contains expected keys and (some) values + # * the data array retrives correctly + import iris.experimental.raster with self.temp_filename('.tif') as temp_filename: iris.experimental.raster.export_geotiff(cube, temp_filename) # Check the metadata is correct. - with open(temp_filename) as fh: - self.check_tiff_header(fh, ('experimental', 'raster', - tif_header)) + self.check_tiff_header(temp_filename, header_keys, header_items) # Ensure that north is at the top then check the data is correct. coord_y = cube.coord(axis='Y', dim_coords=True) @@ -59,8 +78,28 @@ def check_tiff(self, cube, tif_header): np.testing.assert_array_equal(im_data, data.astype(np.float32)) - def test_unmasked(self): + def _check_tiff_export(self, masked, inverted=False): tif_header = 'SMALL_total_column_co2.nc.tif_header.txt' + tif_header_keys = [256, 257, 258, 259, 262, 273, + 277, 278, 279, 284, 339, 33550, 33922] + tif_header_entries = { + 256: (160,), + 257: (159,), + 258: (32,), + 259: (1,), + 262: (1,), + # Skip this one: behaviour is not consistent across gdal versions. + # 273: (354, 8034, 15714, 23394, 31074, 38754, 46434, + # 54114, 61794, 69474, 77154, 84834, 92514, 100194), + 277: (1,), + 278: (12,), + 279: (7680, 7680, 7680, 7680, 7680, 7680, 7680, + 7680, 7680, 7680, 7680, 7680, 7680, 1920), + 284: (1,), + 339: (3,), + 33550: (1.125, 1.125, 0.0), + 33922: (0.0, 0.0, 0.0, -0.5625, 89.4375, 0.0) + } fin = tests.get_data_path(('NetCDF', 'global', 'xyt', 'SMALL_total_column_co2.nc')) cube = iris.load_cube(fin)[0] @@ -75,34 +114,37 @@ def test_unmasked(self): cube = cube.extract(east & non_edge) cube.coord('longitude').guess_bounds() cube.coord('latitude').guess_bounds() - self.check_tiff(cube, tif_header) - # Check again with the latitude coordinate (and the corresponding - # cube.data) inverted. The output should be the same as before. - coord = cube.coord('latitude') - coord.points = coord.points[::-1] - coord.bounds = None - coord.guess_bounds() - cube.data = cube.data[::-1, :] - self.check_tiff(cube, tif_header) + if masked: + # Mask some of the data + expect a slightly different header... + cube.data = np.ma.masked_where(cube.data <= 380, cube.data) + + # There is an additional key.. + tif_header_keys += [42113] + # Don't add a check entry for this, as coding changed between gdal + # version 1 and 2, *and* between Python2 and Python3. + # tif_header_entries[42113] = (u'1e+20',) + + if inverted: + # Check with the latitude coordinate (and the corresponding + # cube.data) inverted. + # The output should be exactly the same. + coord = cube.coord('latitude') + coord.points = coord.points[::-1] + coord.bounds = None + coord.guess_bounds() + cube.data = cube.data[::-1, :] + + self.check_tiff(cube, tif_header_keys, tif_header_entries) + + def test_unmasked(self): + self._check_tiff_export(masked=False) def test_masked(self): - tif_header = 'SMALL_total_column_co2.nc.ma.tif_header.txt' - fin = tests.get_data_path(('NetCDF', 'global', 'xyt', - 'SMALL_total_column_co2.nc')) - cube = iris.load_cube(fin)[0] - # PIL doesn't support float64 - cube.data = cube.data.astype('f4') + self._check_tiff_export(masked=True) - # Repeat the same data extract as above - east = iris.Constraint(longitude=lambda cell: cell < 180) - non_edge = iris.Constraint(latitude=lambda cell: -90 < cell < 90) - cube = cube.extract(east & non_edge) - cube.coord('longitude').guess_bounds() - cube.coord('latitude').guess_bounds() - # Mask some of the data - cube.data = np.ma.masked_where(cube.data <= 380, cube.data) - self.check_tiff(cube, tif_header) + def test_inverted(self): + self._check_tiff_export(masked=False, inverted=True) if __name__ == "__main__": diff --git a/lib/iris/tests/experimental/ugrid/__init__.py b/lib/iris/tests/experimental/ugrid/__init__.py new file mode 100644 index 0000000000..dcc2b27f2a --- /dev/null +++ b/lib/iris/tests/experimental/ugrid/__init__.py @@ -0,0 +1,23 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Ugrid code is tested in this package. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/experimental/ugrid/test_ugrid.py b/lib/iris/tests/experimental/ugrid/test_ugrid.py new file mode 100644 index 0000000000..617f826bd2 --- /dev/null +++ b/lib/iris/tests/experimental/ugrid/test_ugrid.py @@ -0,0 +1,56 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test the :func:`iris.experimental.ugrid.ugrid` function. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import iris.tests as tests + +import unittest + +# Import pyugrid if installed, else fail quietly + disable all the tests. +try: + import pyugrid +except (ImportError, AttributeError): + pyugrid = None +skip_pyugrid = unittest.skipIf( + condition=pyugrid is None, + reason='Requires pyugrid, which is not available.') + +import iris.experimental.ugrid + + +data_path = ("NetCDF", "ugrid", ) +file21 = "21_triangle_example.nc" +long_name = "volume flux between cells" + + +@skip_pyugrid +@tests.skip_data +class TestUgrid(tests.IrisTest): + def test_ugrid(self): + path = tests.get_data_path(data_path + (file21, )) + cube = iris.experimental.ugrid.ugrid(path, long_name) + self.assertTrue(hasattr(cube, 'mesh')) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/idiff.py b/lib/iris/tests/idiff.py index 3ed3fd6189..3c0e4f9c2e 100755 --- a/lib/iris/tests/idiff.py +++ b/lib/iris/tests/idiff.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -22,17 +22,58 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import argparse +import codecs +import contextlib +from glob import glob +import json import os.path import shutil import sys +import warnings + +# Force iris.tests to use the ```tkagg``` backend by using the '-d' +# command-line argument as idiff is an interactive tool that requires a +# gui interface. +sys.argv.append('-d') +import iris.tests # noqa + +from PIL import Image # noqa +import filelock # noqa +import imagehash # noqa +import matplotlib.pyplot as plt # noqa +import matplotlib.image as mimg # noqa +import matplotlib.testing.compare as mcompare # noqa +from matplotlib.testing.exceptions import ImageComparisonFailure # noqa +import matplotlib.widgets as mwidget # noqa +import numpy as np # noqa +import requests # noqa + +import iris.util as iutil # noqa + -import matplotlib.pyplot as plt -import matplotlib.image as mimg -import matplotlib.widgets as mwidget +_POSTFIX_DIFF = '-failed-diff.png' +_POSTFIX_JSON = os.path.join('results', 'imagerepo.json') +_POSTFIX_LOCK = os.path.join('results', 'imagerepo.lock') -def diff_viewer(expected_fname, result_fname, diff_fname): - plt.figure(figsize=(16, 16)) +@contextlib.contextmanager +def temp_png(suffix=''): + if suffix: + suffix = '-{}'.format(suffix) + fname = iutil.create_temp_filename(suffix+'.png') + try: + yield fname + finally: + os.remove(fname) + + +def diff_viewer(repo, key, repo_fname, phash, status, + expected_fname, result_fname, diff_fname): + fig = plt.figure(figsize=(14, 12)) plt.suptitle(os.path.basename(expected_fname)) ax = plt.subplot(221) ax.imshow(mimg.imread(expected_fname)) @@ -41,49 +82,219 @@ def diff_viewer(expected_fname, result_fname, diff_fname): ax = plt.subplot(223, sharex=ax, sharey=ax) ax.imshow(mimg.imread(diff_fname)) + result_dir = os.path.dirname(result_fname) + fname = '{}.png'.format(phash) + base_uri = 'https://scitools.github.io/test-iris-imagehash/images/v4/{}' + uri = base_uri.format(fname) + phash_fname = os.path.join(result_dir, fname) + def accept(event): - # removes the expected result, and move the most recent result in - print 'ACCEPTED NEW FILE: %s' % (os.path.basename(expected_fname), ) - os.remove(expected_fname) - shutil.copy2(result_fname, expected_fname) + if uri not in repo[key]: + # Ensure to maintain strict time order where the first uri + # associated with the repo key is the oldest, and the last + # uri is the youngest + repo[key].append(uri) + # Update the image repo. + with open(repo_fname, 'wb') as fo: + json.dump(repo, codecs.getwriter('utf-8')(fo), + indent=4, sort_keys=True) + os.rename(result_fname, phash_fname) + msg = 'ACCEPTED: {} -> {}' + print(msg.format(os.path.basename(result_fname), + os.path.basename(phash_fname))) + else: + msg = 'DUPLICATE: {} -> {} (ignored)' + print(msg.format(os.path.basename(result_fname), + os.path.basename(phash_fname))) + os.remove(result_fname) os.remove(diff_fname) plt.close() def reject(event): - print 'REJECTED: %s' % (os.path.basename(expected_fname), ) + if uri not in repo[key]: + print('REJECTED: {}'.format(os.path.basename(result_fname))) + else: + msg = 'DUPLICATE: {} -> {} (ignored)' + print(msg.format(os.path.basename(result_fname), + os.path.basename(phash_fname))) + os.remove(result_fname) + os.remove(diff_fname) plt.close() - ax_accept = plt.axes([0.7, 0.05, 0.1, 0.075]) - ax_reject = plt.axes([0.81, 0.05, 0.1, 0.075]) - bnext = mwidget.Button(ax_accept, 'Accept change') - bnext.on_clicked(accept) - bprev = mwidget.Button(ax_reject, 'Reject') - bprev.on_clicked(reject) + def skip(event): + # Let's keep both the result and the diff files. + print('SKIPPED: {}'.format(os.path.basename(result_fname))) + plt.close() + ax_accept = plt.axes([0.59, 0.05, 0.1, 0.075]) + ax_reject = plt.axes([0.7, 0.05, 0.1, 0.075]) + ax_skip = plt.axes([0.81, 0.05, 0.1, 0.075]) + baccept = mwidget.Button(ax_accept, 'Accept') + baccept.on_clicked(accept) + breject = mwidget.Button(ax_reject, 'Reject') + breject.on_clicked(reject) + bskip = mwidget.Button(ax_skip, 'Skip') + bskip.on_clicked(skip) + plt.text(0.59, 0.15, status, transform=fig.transFigure) plt.show() -def step_over_diffs(): - import iris.tests - image_dir = os.path.join(os.path.dirname(iris.tests.__file__), - 'results', 'visual_tests') - diff_dir = os.path.join(os.path.dirname(iris.tests.__file__), - 'result_image_comparison') +def _calculate_hit(uris, phash, action): + # Extract the hex basename strings from the uris. + hexes = [os.path.splitext(os.path.basename(uri))[0] for uri in uris] + # Create the expected perceptual image hashes from the uris. + to_hash = imagehash.hex_to_hash + expected = [to_hash(uri_hex) for uri_hex in hexes] + # Calculate the hamming distance vector for the result hash. + distances = [e - phash for e in expected] - for expected_fname in sorted(os.listdir(image_dir)): - result_path = os.path.join(diff_dir, 'result-' + expected_fname) - diff_path = result_path[:-4] + '-failed-diff.png' + if action == 'first': + index = 0 + elif action == 'last': + index = -1 + elif action == 'similar': + index = np.argmin(distances) + elif action == 'different': + index = np.argmax(distances) + else: + emsg = 'Unknown action: {!r}' + raise ValueError(emsg.format(action)) - # if the test failed, there will be a diff file - if os.path.exists(diff_path): - expected_path = os.path.join(image_dir, expected_fname) - diff_viewer(expected_path, result_path, diff_path) + return index, distances[index] -if __name__ == '__main__': - # Force iris.tests to use the ```tkagg``` backend by using the '-d' - # command-line argument as idiff is an interactive tool that requires a - # gui interface. - sys.argv.append('-d') +def step_over_diffs(result_dir, action, display=True): + processed = False + dname = os.path.dirname(iris.tests.__file__) + lock = filelock.FileLock(os.path.join(dname, _POSTFIX_LOCK)) + if action in ['first', 'last']: + kind = action + elif action in ['similar', 'different']: + kind = 'most {}'.format(action) + else: + emsg = 'Unknown action: {!r}' + raise ValueError(emsg.format(action)) + if display: + msg = ('\nComparing the {!r} expected image with ' + 'the test result image.') + print(msg.format(kind)) + + # Remove old image diff results. + target = os.path.join(result_dir, '*{}'.format(_POSTFIX_DIFF)) + for fname in glob(target): + os.remove(fname) + + with lock.acquire(timeout=30): + # Load the imagerepo. + repo_fname = os.path.join(dname, _POSTFIX_JSON) + with open(repo_fname, 'rb') as fi: + repo = json.load(codecs.getreader('utf-8')(fi)) + + # Filter out all non-test result image files. + target_glob = os.path.join(result_dir, 'result-*.png') + results = [] + for fname in sorted(glob(target_glob)): + # We only care about PNG images. + try: + im = Image.open(fname) + if im.format != 'PNG': + # Ignore - it's not a png image. + continue + except IOError: + # Ignore - it's not an image. + continue + results.append(fname) + + count = len(results) - step_over_diffs() + for count_index, result_fname in enumerate(results): + key = os.path.splitext('-'.join(result_fname.split('-')[1:]))[0] + try: + # Calculate the test result perceptual image hash. + phash = imagehash.phash(Image.open(result_fname), + hash_size=iris.tests._HASH_SIZE) + uris = repo[key] + hash_index, distance = _calculate_hit(uris, phash, action) + uri = uris[hash_index] + except KeyError: + wmsg = 'Ignoring unregistered test result {!r}.' + warnings.warn(wmsg.format(key)) + continue + with temp_png(key) as expected_fname: + processed = True + resource = requests.get(uri) + if resource.status_code == 200: + with open(expected_fname, 'wb') as fo: + fo.write(resource.content) + else: + # Perhaps the uri has not been pushed into the repo yet, + # so check if a local "developer" copy is available ... + local_fname = os.path.join(result_dir, + os.path.basename(uri)) + if not os.path.isfile(local_fname): + emsg = 'Bad URI {!r} for test {!r}.' + raise ValueError(emsg.format(uri, key)) + else: + # The temporary expected filename has the test name + # baked into it, and is used in the diff plot title. + # So copy the local file to the exected file to + # maintain this helpfulness. + shutil.copy(local_fname, expected_fname) + try: + mcompare.compare_images(expected_fname, result_fname, + tol=0) + except Exception as e: + if isinstance(e, ValueError) or \ + isinstance(e, ImageComparisonFailure): + print('Could not compare {}: {}'.format(result_fname, + e)) + continue + else: + # Propagate the exception, keeping the stack trace + raise + diff_fname = os.path.splitext(result_fname)[0] + _POSTFIX_DIFF + args = expected_fname, result_fname, diff_fname + if display: + msg = ('Image {} of {}: hamming distance = {} ' + '[{!r}]') + status = msg.format(count_index+1, count, distance, kind) + prefix = repo, key, repo_fname, phash, status + yield prefix + args + else: + yield args + if display and not processed: + print('\nThere are no iris test result images to process.\n') + + +if __name__ == '__main__': + default = os.path.join(os.path.dirname(iris.tests.__file__), + 'result_image_comparison') + description = 'Iris graphic test difference tool.' + formatter_class = argparse.RawTextHelpFormatter + parser = argparse.ArgumentParser(description=description, + formatter_class=formatter_class) + help = 'path to iris tests result image directory (default: %(default)s)' + parser.add_argument('--resultdir', '-r', + default=default, + help=help) + help = 'force "iris.tests" to use the tkagg backend (default: %(default)s)' + parser.add_argument('-d', + action='store_true', + default=True, + help=help) + help = """ +first - compare result image with first (oldest) expected image +last - compare result image with last (youngest) expected image +similar - compare result image with most similar expected image (default) +different - compare result image with most unsimilar expected image +""" + choices = ('first', 'last', 'similar', 'different') + parser.add_argument('action', nargs='?', choices=choices, + default='similar', help=help) + args = parser.parse_args() + result_dir = args.resultdir + if not os.path.isdir(result_dir): + emsg = 'Invalid results directory: {}' + raise ValueError(emsg.format(result_dir)) + for args in step_over_diffs(result_dir, args.action): + diff_viewer(*args) diff --git a/lib/iris/tests/integration/__init__.py b/lib/iris/tests/integration/__init__.py index 9a20fb3482..abb8fc8ba1 100644 --- a/lib/iris/tests/integration/__init__.py +++ b/lib/iris/tests/integration/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Integration tests for the :mod:`iris` package.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/integration/aux_factory/__init__.py b/lib/iris/tests/integration/aux_factory/__init__.py new file mode 100644 index 0000000000..f49ea330c1 --- /dev/null +++ b/lib/iris/tests/integration/aux_factory/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for the :mod:`iris.aux_factory` package.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/integration/aux_factory/test_OceanSigmaZFactory.py b/lib/iris/tests/integration/aux_factory/test_OceanSigmaZFactory.py new file mode 100644 index 0000000000..a9245e0333 --- /dev/null +++ b/lib/iris/tests/integration/aux_factory/test_OceanSigmaZFactory.py @@ -0,0 +1,189 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Integratation tests for the +`iris.aux_factory.OceanSigmaZFactory` class. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import itertools + +import numpy as np + +from iris._lazy_data import as_lazy_data +from iris.tests.stock import ocean_sigma_z as stock_sample_osz +import iris.util + + +class Test_sample(tests.IrisTest): + def setUp(self): + self.cube = stock_sample_osz() + # Snapshot result, printed with ... + # >>> np.set_printoptions(linewidth=180, + # formatter={'float':lambda x:'{:-09.3f}'.format(x)}) + # >>> print repr(coord.points) + self.basic_derived_result = np.array( + [[[[-0000.632, -0000.526, -0000.421, -0000.316], + [-0000.789, -0000.684, -0000.579, -0000.474], + [-0000.947, -0000.842, -0000.737, -0000.632]], + [[-0014.358, -0014.264, -0014.169, -0014.074], + [-0014.501, -0014.406, -0014.311, -0014.216], + [-0014.643, -0014.548, -0014.453, -0014.358]], + [[-0082.993, -0082.951, -0082.908, -0082.866], + [-0083.056, -0083.014, -0082.972, -0082.929], + [-0083.119, -0083.077, -0083.035, -0082.993]], + [[-0368.400, -0368.400, -0368.400, -0368.400], + [-0368.400, -0368.400, -0368.400, -0368.400], + [-0368.400, -0368.400, -0368.400, -0368.400]], + [[-1495.600, -1495.600, -1495.600, -1495.600], + [-1495.600, -1495.600, -1495.600, -1495.600], + [-1495.600, -1495.600, -1495.600, -1495.600]]], + + [[[-0000.842, -0000.737, -0000.632, -0000.526], + [-0001.000, -0000.895, -0000.789, -0000.684], + [-0001.158, -0001.053, -0000.947, -0000.842]], + [[-0014.548, -0014.453, -0014.358, -0014.264], + [-0014.690, -0014.595, -0014.501, -0014.406], + [-0014.832, -0014.737, -0014.643, -0014.548]], + [[-0083.077, -0083.035, -0082.993, -0082.951], + [-0083.140, -0083.098, -0083.056, -0083.014], + [-0083.203, -0083.161, -0083.119, -0083.077]], + [[-0368.400, -0368.400, -0368.400, -0368.400], + [-0368.400, -0368.400, -0368.400, -0368.400], + [-0368.400, -0368.400, -0368.400, -0368.400]], + [[-1495.600, -1495.600, -1495.600, -1495.600], + [-1495.600, -1495.600, -1495.600, -1495.600], + [-1495.600, -1495.600, -1495.600, -1495.600]]]]) + + self.derived_coord_name = \ + 'sea_surface_height_above_reference_ellipsoid' + + def _check_result(self, cube, expected_result=None, **kwargs): + if expected_result is None: + expected_result = self.basic_derived_result + coord = cube.coord(self.derived_coord_name) + result = coord.points + self.assertArrayAllClose(result, expected_result, atol=0.005, **kwargs) + + def test_basic(self): + self._check_result(self.cube) + + def _lazy_testcube(self): + cube = self.cube + for dep_name in ('depth', 'layer_depth', 'ocean_sigma_z_coordinate'): + coord = cube.coord(dep_name) + coord.points = as_lazy_data(coord.points, coord.shape) + return cube + + def test_nonlazy_cube_has_lazy_derived(self): + # Check same results when key coords are made lazy. + cube = self.cube + self.assertEqual( + cube.coord('depth').has_lazy_points(), + False) + self.assertEqual( + cube.coord(self.derived_coord_name).has_lazy_points(), + True) + + def test_lazy_cube_same_result(self): + cube = self._lazy_testcube() + self.assertEqual( + cube.coord('depth').has_lazy_points(), + True) + self.assertEqual( + cube.coord(self.derived_coord_name).has_lazy_points(), + True) + self._check_result(cube) + + def test_transpose(self): + # Check it works with all possible dimension orders. + for dims_list in itertools.permutations(range(self.cube.ndim)): + cube = self.cube.copy() + cube.transpose(dims_list) + expected = self.basic_derived_result.transpose(dims_list) + msg = 'Unexpected result when cube transposed by {}' + msg = msg.format(dims_list) + self._check_result(cube, expected, + err_msg=msg) + + def test_lazy_transpose(self): + # Check lazy calc works with all possible dimension orders. + for dims_list in itertools.permutations(range(self.cube.ndim)): + cube = self._lazy_testcube().copy() + cube.transpose(dims_list) + expected = self.basic_derived_result.transpose(dims_list) + msg = 'Unexpected result when cube transposed by {}' + msg = msg.format(dims_list) + self._check_result(cube, expected, + err_msg=msg) + + def test_extra_dims(self): + # Insert some extra cube dimensions + check it still works. + cube = self.cube + cube = iris.util.new_axis(cube) + cube = iris.util.new_axis(cube) + cube = iris.util.new_axis(cube) + # N.B. shape is now (1, 1, 1, t, z, y, x) + cube.transpose((0, 3, 1, 4, 5, 2, 6)) + # N.B. shape is now (1, t, 1, z, y, 1, x) + # Should get same original result, as derived dims are the same. + self._check_result(cube) + + def test_no_sigma(self): + # Check it still works when 'sigma' is removed. + # NOTE: the unit test for this does not cover all cases because it + # doesn't provide a time dimension. + + # Set all sigma points to zero + snapshot the resulting derived points. + trial_cube = self.cube.copy() + trial_cube.coord('ocean_sigma_z_coordinate').points[:] = 0.0 + expected = trial_cube.coord(self.derived_coord_name).points + + # Remove sigma altogether + check the result is the same. + cube = self.cube + cube.remove_coord('ocean_sigma_z_coordinate') + self._check_result(cube, expected) + + def test_no_eta(self): + # Check it still works when 'eta' is removed. + # NOTE: the unit test for this does not cover all cases because it + # doesn't provide a time dimension. + + # Set all sigma points to zero + snapshot the resulting derived points. + trial_cube = self.cube.copy() + trial_cube.coord('sea_surface_height').points[:] = 0.0 + expected = trial_cube.coord(self.derived_coord_name).points + # Check this has no variation between the two timepoints. + self.assertArrayAllClose(expected[0], expected[1]) + # Take first time, as no sigma --> result *has* no time dimension. + expected = expected[0] + + # Remove eta altogether + check the result is the same. + cube = self.cube + cube.remove_coord('sea_surface_height') + self._check_result(cube, expected) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/integration/concatenate/__init__.py b/lib/iris/tests/integration/concatenate/__init__.py new file mode 100644 index 0000000000..d72f4ee8eb --- /dev/null +++ b/lib/iris/tests/integration/concatenate/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for the :mod:`iris._concatenate` package.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/integration/concatenate/test_concatenate.py b/lib/iris/tests/integration/concatenate/test_concatenate.py new file mode 100644 index 0000000000..321e4fafd7 --- /dev/null +++ b/lib/iris/tests/integration/concatenate/test_concatenate.py @@ -0,0 +1,240 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Integration tests for concatenating cubes with differing time coord epochs +using :func:`iris.util.unify_time_units`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised +# before importing anything else. +import iris.tests as tests + +import cf_units +import numpy as np + +import iris.coords +from iris._concatenate import concatenate +import iris.cube +import iris.tests.stock as stock +from iris.util import unify_time_units + + +class Test_concatenate__epoch(tests.IrisTest): + def simple_1d_time_cubes(self, reftimes, coords_points): + cubes = [] + data_points = [273, 275, 278, 277, 274] + for reftime, coord_points in zip(reftimes, coords_points): + cube = iris.cube.Cube(np.array(data_points, dtype=np.float32), + standard_name='air_temperature', + units='K') + unit = cf_units.Unit(reftime, calendar='gregorian') + coord = iris.coords.DimCoord(points=np.array(coord_points, + dtype=np.float32), + standard_name='time', + units=unit) + cube.add_dim_coord(coord, 0) + cubes.append(cube) + return cubes + + def test_concat_1d_with_differing_time_units(self): + reftimes = ['hours since 1970-01-01 00:00:00', + 'hours since 1970-01-02 00:00:00'] + coords_points = [[1, 2, 3, 4, 5], [1, 2, 3, 4, 5]] + cubes = self.simple_1d_time_cubes(reftimes, coords_points) + unify_time_units(cubes) + result = concatenate(cubes) + self.assertEqual(len(result), 1) + self.assertEqual(result[0].shape, (10,)) + + +class Test_cubes_with_aux_coord(tests.IrisTest): + def create_cube(self): + data = np.arange(4).reshape(2, 2) + + lat = iris.coords.DimCoord([0, 30], standard_name='latitude', + units='degrees') + lon = iris.coords.DimCoord([0, 15], standard_name='longitude', + units='degrees') + height = iris.coords.AuxCoord([1.5], standard_name='height', units='m') + t_unit = cf_units.Unit('hours since 1970-01-01 00:00:00', + calendar='gregorian') + time = iris.coords.DimCoord([0, 6], standard_name='time', units=t_unit) + + cube = iris.cube.Cube(data, standard_name='air_temperature', units='K') + cube.add_dim_coord(time, 0) + cube.add_dim_coord(lat, 1) + cube.add_aux_coord(lon, 1) + cube.add_aux_coord(height) + return cube + + def test_diff_aux_coord(self): + cube_a = self.create_cube() + cube_b = cube_a.copy() + cube_b.coord('time').points = [12, 18] + cube_b.coord('longitude').points = [120, 150] + + result = concatenate([cube_a, cube_b]) + self.assertEqual(len(result), 2) + + def test_ignore_diff_aux_coord(self): + cube_a = self.create_cube() + cube_b = cube_a.copy() + cube_b.coord('time').points = [12, 18] + cube_b.coord('longitude').points = [120, 150] + + result = concatenate([cube_a, cube_b], check_aux_coords=False) + self.assertEqual(len(result), 1) + self.assertEqual(result[0].shape, (4, 2)) + + +class Test_anonymous_dims(tests.IrisTest): + def setUp(self): + data = np.arange(12).reshape(2, 3, 2) + self.cube = iris.cube.Cube(data, standard_name='air_temperature', + units='K') + + # Time coord + t_unit = cf_units.Unit('hours since 1970-01-01 00:00:00', + calendar='gregorian') + t_coord = iris.coords.DimCoord([0, 6], + standard_name='time', + units=t_unit) + self.cube.add_dim_coord(t_coord, 0) + + # Lats and lons + self.x_coord = iris.coords.DimCoord([15, 30], + standard_name='longitude', + units='degrees') + self.y_coord = iris.coords.DimCoord([0, 30, 60], + standard_name='latitude', + units='degrees') + self.x_coord_2D = iris.coords.AuxCoord([[0, 15], [30, 45], [60, 75]], + standard_name='longitude', + units='degrees') + self.y_coord_non_monotonic = iris.coords.AuxCoord( + [0, 30, 15], standard_name='latitude', units='degrees') + + def test_matching_2d_longitudes(self): + cube1 = self.cube + cube1.add_dim_coord(self.y_coord, 1) + cube1.add_aux_coord(self.x_coord_2D, (1, 2)) + + cube2 = cube1.copy() + cube2.coord('time').points = [12, 18] + result = concatenate([cube1, cube2]) + self.assertEqual(len(result), 1) + + def test_differing_2d_longitudes(self): + cube1 = self.cube + cube1.add_aux_coord(self.y_coord, 1) + cube1.add_aux_coord(self.x_coord_2D, (1, 2)) + + cube2 = cube1.copy() + cube2.coord('time').points = [12, 18] + cube2.coord('longitude').points = [[-30, -15], [0, 15], [30, 45]] + + result = concatenate([cube1, cube2]) + self.assertEqual(len(result), 2) + + def test_matching_non_monotonic_latitudes(self): + cube1 = self.cube + cube1.add_aux_coord(self.y_coord_non_monotonic, 1) + cube1.add_aux_coord(self.x_coord, 2) + + cube2 = cube1.copy() + cube2.coord('time').points = [12, 18] + + result = concatenate([cube1, cube2]) + self.assertEqual(len(result), 1) + + def test_differing_non_monotonic_latitudes(self): + cube1 = self.cube + cube1.add_aux_coord(self.y_coord_non_monotonic, 1) + cube1.add_aux_coord(self.x_coord, 2) + + cube2 = cube1.copy() + cube2.coord('time').points = [12, 18] + cube2.coord('latitude').points = [30, 0, 15] + + result = concatenate([cube1, cube2]) + self.assertEqual(len(result), 2) + + def test_concatenate_along_anon_dim(self): + cube1 = self.cube + cube1.add_aux_coord(self.y_coord_non_monotonic, 1) + cube1.add_aux_coord(self.x_coord, 2) + + cube2 = cube1.copy() + cube2.coord('latitude').points = [30, 0, 15] + + result = concatenate([cube1, cube2]) + self.assertEqual(len(result), 2) + + +class Test_anonymous_dims_alternate_mapping(tests.IrisTest): + # Ensure that anonymous concatenation is not sensitive to dimension mapping + # of the anonymous dimension. + def setUp(self): + self.cube = stock.simple_3d() + coord = self.cube.coord('wibble') + self.cube.remove_coord(coord) + self.cube.add_aux_coord(coord, 0) + + def test_concatenate_anom_1st_dim(self): + # Check that concatenation along a non anonymous dimension is + # insensitive to the dimension which is anonymous. + # Concatenate along longitude. + # DIM: cube(--, lat, lon) & cube(--, lat, lon') + # AUX: cube(wibble, --, --) & cube(wibble, --, --) + cube1 = self.cube[..., :2] + cube2 = self.cube[..., 2:] + result = concatenate([cube1, cube2]) + self.assertEqual(len(result), 1) + + def test_concatenate_anom_2nd_dim(self): + # Check that concatenation along a non anonymous dimension is + # insensitive to the dimension which is anonymous. + # Concatenate along longitude. + # DIM: cube(lon, --, lat) & cube(lon', ---, lat) + # AUX: cube(--, wibble, --) & cube(--, wibble, --) + cube1 = self.cube[..., :2] + cube2 = self.cube[..., 2:] + cube1.transpose((2, 0, 1)) + cube2.transpose((2, 0, 1)) + result = concatenate([cube1, cube2]) + self.assertEqual(len(result), 1) + + def test_concatenate_anom_3rd_dim(self): + # Check that concatenation along a non anonymous dimension is + # insensitive to the dimension which is anonymous. + # Concatenate along longitude. + # DIM: cube(lat, lon, --) & cube(lat, lon', --) + # AUX: cube(--, --, wibble) & cube(--, --, wibble) + cube1 = self.cube[..., :2] + cube2 = self.cube[..., 2:] + cube1.transpose((1, 2, 0)) + cube2.transpose((1, 2, 0)) + result = concatenate([cube1, cube2]) + self.assertEqual(len(result), 1) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/integration/experimental/__init__.py b/lib/iris/tests/integration/experimental/__init__.py new file mode 100644 index 0000000000..4384c94152 --- /dev/null +++ b/lib/iris/tests/integration/experimental/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for the :mod:`iris.experimental` package.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/integration/experimental/test_CubeRepresentation.py b/lib/iris/tests/integration/experimental/test_CubeRepresentation.py new file mode 100644 index 0000000000..fa01ab37a7 --- /dev/null +++ b/lib/iris/tests/integration/experimental/test_CubeRepresentation.py @@ -0,0 +1,176 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for cube html representation.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.cube import Cube +import iris.tests.stock as stock +import numpy as np + +from iris.experimental.representation import CubeRepresentation + + +@tests.skip_data +class TestNoMetadata(tests.IrisTest): + # Test the situation where we have a cube with no metadata at all. + def setUp(self): + self.shape = (2, 3, 4) + self.cube = Cube(np.arange(24).reshape(self.shape)) + self.representer = CubeRepresentation(self.cube) + self.representer.repr_html() + + def test_cube_name(self): + expected = 'Unknown' # This cube has no metadata. + result = self.representer.name + self.assertEqual(expected, result) + + def test_cube_units(self): + expected = 'unknown' # This cube has no metadata. + result = self.representer.units + self.assertEqual(expected, result) + + def test_dim_names(self): + expected = ['--'] * len(self.shape) + result = self.representer.names + self.assertEqual(expected, result) + + def test_shape(self): + result = self.representer.shapes + self.assertEqual(result, self.shape) + + +@tests.skip_data +class TestMissingMetadata(tests.IrisTest): + def setUp(self): + self.cube = stock.realistic_3d() + + def test_no_coords(self): + all_coords = [coord.name() for coord in self.cube.coords()] + for coord in all_coords: + self.cube.remove_coord(coord) + representer = CubeRepresentation(self.cube) + result = representer.repr_html().lower() + self.assertNotIn('dimension coordinates', result) + self.assertNotIn('auxiliary coordinates', result) + self.assertNotIn('scalar coordinates', result) + self.assertIn('attributes', result) + + def test_no_dim_coords(self): + dim_coords = [c.name() for c in self.cube.coords(dim_coords=True)] + for coord in dim_coords: + self.cube.remove_coord(coord) + representer = CubeRepresentation(self.cube) + result = representer.repr_html().lower() + self.assertNotIn('dimension coordinates', result) + self.assertIn('auxiliary coordinates', result) + self.assertIn('scalar coordinates', result) + self.assertIn('attributes', result) + + def test_no_aux_coords(self): + aux_coords = ['forecast_period'] + for coord in aux_coords: + self.cube.remove_coord(coord) + representer = CubeRepresentation(self.cube) + result = representer.repr_html().lower() + self.assertIn('dimension coordinates', result) + self.assertNotIn('auxiliary coordinates', result) + self.assertIn('scalar coordinates', result) + self.assertIn('attributes', result) + + def test_no_scalar_coords(self): + aux_coords = ['air_pressure'] + for coord in aux_coords: + self.cube.remove_coord(coord) + representer = CubeRepresentation(self.cube) + result = representer.repr_html().lower() + self.assertIn('dimension coordinates', result) + self.assertIn('auxiliary coordinates', result) + self.assertNotIn('scalar coordinates', result) + self.assertIn('attributes', result) + + def test_no_attrs(self): + self.cube.attributes = {} + representer = CubeRepresentation(self.cube) + result = representer.repr_html().lower() + self.assertIn('dimension coordinates', result) + self.assertIn('auxiliary coordinates', result) + self.assertIn('scalar coordinates', result) + self.assertNotIn('attributes', result) + + def test_no_cell_methods(self): + representer = CubeRepresentation(self.cube) + result = representer.repr_html().lower() + self.assertNotIn('cell methods', result) + + +@tests.skip_data +class TestScalarCube(tests.IrisTest): + def setUp(self): + self.cube = stock.realistic_3d()[0, 0, 0] + self.representer = CubeRepresentation(self.cube) + self.representer.repr_html() + + def test_identfication(self): + # Is this scalar cube accurately identified? + self.assertTrue(self.representer.scalar_cube) + + def test_header__name(self): + header = self.representer._make_header() + expected_name = self.cube.name().title().replace('_', ' ') + self.assertIn(expected_name, header) + + def test_header__units(self): + header = self.representer._make_header() + expected_units = self.cube.units.symbol + self.assertIn(expected_units, header) + + def test_header__scalar_str(self): + # Check that 'scalar cube' is placed in the header. + header = self.representer._make_header() + expected_str = '(scalar cube)' + self.assertIn(expected_str, header) + + def test_content__scalars(self): + # Check an element "Scalar coordinates" is present in the main content. + content = self.representer._make_content() + expected_str = 'Scalar coordinates' + self.assertIn(expected_str, content) + + def test_content__specific_scalar_coord(self): + # Check a specific scalar coord is present in the main content. + content = self.representer._make_content() + expected_coord = self.cube.coords()[0] + expected_coord_name = expected_coord.name() + self.assertIn(expected_coord_name, content) + expected_coord_val = str(expected_coord.points[0]) + self.assertIn(expected_coord_val, content) + + def test_content__attributes(self): + # Check an element "attributes" is present in the main content. + content = self.representer._make_content() + expected_str = 'Attributes' + self.assertIn(expected_str, content) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/integration/experimental/test_regrid_ProjectedUnstructured.py b/lib/iris/tests/integration/experimental/test_regrid_ProjectedUnstructured.py new file mode 100644 index 0000000000..12a02abef6 --- /dev/null +++ b/lib/iris/tests/integration/experimental/test_regrid_ProjectedUnstructured.py @@ -0,0 +1,126 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for experimental regridding.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import cartopy.crs as ccrs +from cf_units import Unit +import numpy as np + +import iris +import iris.aux_factory +from iris.coord_systems import GeogCS +from iris.tests.stock import global_pp +from iris.experimental.regrid import (ProjectedUnstructuredLinear, + ProjectedUnstructuredNearest) + + +@tests.skip_data +class TestProjectedUnstructured(tests.IrisTest): + def setUp(self): + path = tests.get_data_path(('NetCDF', 'unstructured_grid', + 'theta_nodal_xios.nc')) + self.src = iris.load_cube(path, 'Potential Temperature') + + src_lat = self.src.coord('latitude') + src_lon = self.src.coord('longitude') + src_lat.coord_system = src_lon.coord_system = GeogCS(6370000) + src_lat.convert_units(Unit('degrees')) + src_lon.convert_units(Unit('degrees')) + + self.global_grid = global_pp() + + def test_nearest(self): + res = self.src.regrid(self.global_grid, ProjectedUnstructuredNearest()) + self.assertArrayShapeStats(res, (1, 6, 73, 96), + 315.8913582, 11.00063922733, rtol=1e-8) + self.assertArrayShapeStats(res[:, 0], (1, 73, 96), + 299.99993826, 3.9226378869e-5) + + def test_nearest_sinusoidal(self): + crs = ccrs.Sinusoidal() + res = self.src.regrid(self.global_grid, + ProjectedUnstructuredNearest(crs)) + self.assertArrayShapeStats(res, (1, 6, 73, 96), + 315.891358296, 11.000639227, rtol=1e-8) + self.assertArrayShapeStats(res[:, 0], (1, 73, 96), + 299.99993826, 3.9223839688e-5) + + def test_nearest_gnomonic_uk_domain(self): + crs = ccrs.Gnomonic(central_latitude=60.0) + uk_grid = self.global_grid.intersection(longitude=(-20, 20), + latitude=(40, 80)) + res = self.src.regrid(uk_grid, ProjectedUnstructuredNearest(crs)) + + self.assertArrayShapeStats(res, (1, 6, 17, 11), + 315.8873266, 11.0006664668, rtol=1e-8) + self.assertArrayShapeStats(res[:, 0], (1, 17, 11), + 299.99993826, 4.1356150388e-5) + expected_subset = np.array([[318.936829, 318.936829, 318.936829], + [318.936829, 318.936829, 318.936829], + [318.935163, 318.935163, 318.935163]]) + self.assertArrayAlmostEqual(expected_subset, + res.data[0, 3, 5:8, 4:7].data) + + def test_nearest_aux_factories(self): + src = self.src + + xy_dim_len, = src.coord(axis='X').shape + z_dim_len, = src.coord('levels').shape + + src.add_aux_coord(iris.coords.AuxCoord(np.arange(z_dim_len)+40, + long_name="level_height", + units="m"), 1) + src.add_aux_coord(iris.coords.AuxCoord(np.arange(z_dim_len)+50, + long_name="sigma", + units="1"), 1) + src.add_aux_coord(iris.coords.AuxCoord(np.arange(xy_dim_len)+100, + long_name="surface_altitude", + units="m"), 2) + src.add_aux_factory(iris.aux_factory.HybridHeightFactory( + delta=src.coord("level_height"), + sigma=src.coord("sigma"), + orography=src.coord("surface_altitude"))) + res = src.regrid(self.global_grid, ProjectedUnstructuredNearest()) + + self.assertArrayShapeStats(res, (1, 6, 73, 96), + 315.8913582, 11.000639227334, rtol=1e-8) + self.assertArrayShapeStats(res[:, 0], (1, 73, 96), + 299.99993826, 3.9226378869e-5) + self.assertEqual(res.coord('altitude').shape, (6, 73, 96)) + + def test_linear_sinusoidal(self): + res = self.src.regrid(self.global_grid, ProjectedUnstructuredLinear()) + self.assertArrayShapeStats(res, (1, 6, 73, 96), + 315.8914839, 11.0006338412, rtol=1e-8) + self.assertArrayShapeStats(res[:, 0], (1, 73, 96), + 299.99993826, 3.775024069e-5) + expected_subset = np.array([[299.999987, 299.999996, 299.999999], + [299.999984, 299.999986, 299.999988], + [299.999973, 299.999977, 299.999982]]) + self.assertArrayAlmostEqual(expected_subset, + res.data[0, 0, 20:23, 40:43].data) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/integration/fast_load/__init__.py b/lib/iris/tests/integration/fast_load/__init__.py new file mode 100644 index 0000000000..263abe4855 --- /dev/null +++ b/lib/iris/tests/integration/fast_load/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for :mod:`iris.fileformats.um` fast load functions.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/integration/fast_load/test_fast_load.py b/lib/iris/tests/integration/fast_load/test_fast_load.py new file mode 100644 index 0000000000..a9bb53a2e8 --- /dev/null +++ b/lib/iris/tests/integration/fast_load/test_fast_load.py @@ -0,0 +1,678 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for fast-loading FF and PP files.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised +# before importing anything else. +import iris.tests as tests + +from collections import Iterable + +import os.path +import tempfile +import shutil +import os + +from cf_units import Unit +import numpy as np +import six + +import iris.coords +from iris.coords import DimCoord, AuxCoord, CellMethod +from iris.coord_systems import GeogCS +from iris.cube import Cube, CubeList +from iris.exceptions import IgnoreCubeException +from iris.fileformats.pp import EARTH_RADIUS, STASH +from iris.fileformats.um._fast_load import STRUCTURED_LOAD_CONTROLS + +import iris +from iris.fileformats.um import structured_um_loading + + +class Mixin_FieldTest(object): + # A mixin providing common facilities for fast-load testing : + # * create 'raw' cubes to produce the desired PP fields in a test file. + # * save 'raw' cubes to temporary PP files that get deleted afterwards. + # * control whether tests run with 'normal' or 'fast' loading. + + def setUp(self): + # Create a private temporary directory. + self.temp_dir_path = tempfile.mkdtemp() + # Initialise temporary filename generation. + self.tempfile_count = 0 + self.tempfile_path_fmt = \ + '{dir_path}/tempfile_{prefix}_{file_number:06d}{suffix}' + # Enable fast loading, if the inheritor enables it. + # N.B. *requires* the user to define "self.do_fast_loads" (no default). + if self.do_fast_loads: + # Enter a 'structured load' context. + self.load_context = STRUCTURED_LOAD_CONTROLS.context( + loads_use_structured=True) + # N.B. we can't use a 'with', so issue separate 'enter' and 'exit' + # calls instead. + self.load_context.__enter__() + + def tearDown(self): + # Delete temporary directory. + shutil.rmtree(self.temp_dir_path) + if self.do_fast_loads: + # End the 'fast loading' context. + self.load_context.__exit__(None, None, None) + + def _temp_filepath(self, user_name='', suffix='.pp'): + # Return the filepath for a new temporary file. + self.tempfile_count += 1 + file_path = self.tempfile_path_fmt.format( + dir_path=self.temp_dir_path, + prefix=user_name, + file_number=self.tempfile_count, + suffix=suffix) + return file_path + + def save_fieldcubes(self, cubes, basename=''): + # Save cubes to a temporary file, and return its filepath. + file_path = self._temp_filepath(user_name=basename, suffix='.pp') + iris.save(cubes, file_path) + return file_path + + def fields(self, c_t=None, cft=None, ctp=None, + c_h=None, c_p=None, phn=0, mmm=None, pse=None): + # Return a list of 2d cubes representing raw PPFields, from args + # specifying sequences of (scalar) coordinate values. + # TODO? : add bounds somehow ? + # + # Arguments 'c' are either a single int value, making a scalar + # coord, or a string of characters : '0'-'9' (index) or '-' (missing). + # The indexes select point values from fixed list of possibles. + # + # Argument 'c_h' and 'c_p' represent height or pressure values, so + # ought to be mutually exclusive -- these control LBVC. + # + # Argument 'phn' indexes phenomenon types. + # + # Argument 'mmm' denotes existence (or not) of a cell method of type + # 'average' or 'min' or 'max' (values '012' respectively), applying to + # the time values -- ultimately, this controls LBTIM. + # + # Argument 'pse' denotes pseudo-level numbers. + # These translate into 'LBUSER5' values. + + # Get the number of result cubes, defined by the 'longest' arg. + def arglen(arg): + # Get the 'length' of a control argument. + if arg is None: + result = 0 + elif isinstance(arg, six.string_types): + result = len(arg) + else: + result = 1 + return result + + n_flds = max(arglen(x) + for x in (c_t, cft, ctp, c_h, c_p, mmm)) + + # Make basic anonymous test cubes. + ny, nx = 3, 5 + data = np.arange(n_flds * ny * nx, dtype=np.float32) + data = data.reshape((n_flds, ny, nx)) + cubes = [Cube(data[i]) for i in range(n_flds)] + + # Define test point values for making coordinates. + time_unit = 'hours since 1970-01-01' + period_unit = 'hours' + height_unit = 'm' + pressure_unit = 'hPa' + time_values = 24.0 * np.arange(10) + height_values = 100.0 * np.arange(1, 11) + pressure_values = [100.0, 150.0, 200.0, 250.0, + 300.0, 500.0, 850.0, 1000.0] + pseudolevel_values = range(1, 11) # A valid value is >= 1. + + # Test phenomenon details. + # NOTE: in order to write/readback as identical, these also contain a + # canonical unit and matching STASH attribute. + # Those could in principle be looked up, but it's a bit awkward. + phenomenon_values = [ + ('air_temperature', 'K', 'm01s01i004'), + ('x_wind', 'm s-1', 'm01s00i002'), + ('y_wind', 'm s-1', 'm01s00i003'), + ('specific_humidity', 'kg kg-1', 'm01s00i010'), + ] + + # Test cell-methods. + # NOTE: if you add an *interval* to any of these cell-methods, it is + # not saved into the PP file (?? or maybe not loaded back again ??). + # This could be a PP save/load bug, or maybe just because no bounds ? + cell_method_values = [ + CellMethod('mean', 'time'), + CellMethod('maximum', 'time'), + CellMethod('minimum', 'time'), + ] + + # Define helper to decode an argument as a list of test values. + def arg_vals(arg, vals): + # Decode an argument to a list of 'n_flds' coordinate point values. + # (or 'None' where missing) + + # First get a list of value indices from the argument. + # Can be: a single index value; a list of indices; or a string. + if (isinstance(arg, Iterable) and + not isinstance(arg, six.string_types)): + # Can also just pass a simple iterable of values. + inds = [int(val) for val in arg] + else: + n_vals = arglen(arg) + if n_vals == 0: + inds = [None] * n_flds + elif n_vals == 1: + inds = [int(arg)] * n_flds + else: + assert isinstance(arg, six.string_types) + inds = [None if char == '-' else int(char) + for char in arg] + + # Convert indices to selected point values. + values = [None if ind is None else vals[int(ind)] + for ind in inds] + + return values + + # Apply phenomenon_values definitions. + phenomena = arg_vals(phn, phenomenon_values) + for cube, (name, units, stash) in zip(cubes, phenomena): + cube.rename(name) + # NOTE: in order to get a cube that will write+readback the same, + # the units must be the canonical one. + cube.units = units + # NOTE: in order to get a cube that will write+readback the same, + # we must include a STASH attribute. + cube.attributes['STASH'] = STASH.from_msi(stash) + cube.fill_value = np.float32(-1e30) + + # Add x and y coords. + cs = GeogCS(EARTH_RADIUS) + xvals = np.linspace(0.0, 180.0, nx) + co_x = DimCoord(np.array(xvals, dtype=np.float32), + standard_name='longitude', units='degrees', + coord_system=cs) + yvals = np.linspace(-45.0, 45.0, ny) + co_y = DimCoord(np.array(yvals, dtype=np.float32), + standard_name='latitude', units='degrees', + coord_system=cs) + for cube in cubes: + cube.add_dim_coord(co_y, 0) + cube.add_dim_coord(co_x, 1) + + # Add multiple scalar coordinates as defined by the arguments. + def arg_coords(arg, name, unit, vals=None): + # Decode an argument to a list of scalar coordinates. + if vals is None: + vals = np.arange(n_flds + 2) # Note allowance + vals = arg_vals(arg, vals) + coords = [None if val is None else DimCoord([val], units=unit) + for val in vals] + # Apply names separately, as 'pressure' is not a standard name. + for coord in coords: + if coord: + coord.rename(name) + # Also fix heights to match what comes from a PP file. + if name == 'height': + coord.attributes['positive'] = 'up' + return coords + + def add_arg_coords(arg, name, unit, vals=None): + # Add scalar coordinates to each cube, for one argument. + coords = arg_coords(arg, name, unit, vals) + for cube, coord in zip(cubes, coords): + if coord: + cube.add_aux_coord(coord) + + add_arg_coords(c_t, 'time', time_unit, time_values) + add_arg_coords(cft, 'forecast_reference_time', time_unit) + add_arg_coords(ctp, 'forecast_period', period_unit, time_values) + add_arg_coords(c_h, 'height', height_unit, height_values) + add_arg_coords(c_p, 'pressure', pressure_unit, pressure_values) + add_arg_coords(pse, 'pseudo_level', '1', pseudolevel_values) + + # Add cell methods as required. + methods = arg_vals(mmm, cell_method_values) + for cube, method in zip(cubes, methods): + if method: + cube.add_cell_method(method) + + return cubes + + +class MixinBasic(object): + # A mixin of tests that can be applied to *either* standard or fast load. + # The "real" test classes must inherit this, and Mixin_FieldTest, + # and define 'self.do_fast_loads' as True or False. + # + # Basic functional tests. + + def test_basic(self): + # Show that basic load merging works. + flds = self.fields(c_t='123', cft='000', ctp='123', c_p=0) + file = self.save_fieldcubes(flds) + results = iris.load(file) + expected = CubeList(flds).merge() + self.assertEqual(results, expected) + + def test_phenomena(self): + # Show that different phenomena are merged into distinct cubes. + flds = self.fields(c_t='1122', phn='0101') + file = self.save_fieldcubes(flds) + results = iris.load(file) + expected = CubeList(flds).merge() + self.assertEqual(results, expected) + + def test_cross_file_concatenate(self): + # Combine vector dimensions (i.e. concatenate) across multiple files. + fldset_1 = self.fields(c_t='12') + fldset_2 = self.fields(c_t='34') + file_1 = self.save_fieldcubes(fldset_1) + file_2 = self.save_fieldcubes(fldset_2) + results = iris.load((file_1, file_2)) + expected = CubeList(fldset_1 + fldset_2).merge() + self.assertEqual(results, expected) + + def test_cell_method(self): + # Check that cell methods (i.e. LBPROC values) produce distinct + # phenomena. + flds = self.fields(c_t='000111222', + mmm='-01-01-01') + file = self.save_fieldcubes(flds) + results = iris.load(file) + expected = CubeList(CubeList(flds[i_start::3]).merge_cube() + for i_start in range(3)) + self.assertEqual(results, expected) + + +class MixinCallDetails(object): + # A mixin of tests that can be applied to *either* standard or fast load. + # The "real" test classes must inherit this, and Mixin_FieldTest, + # and define 'self.do_fast_loads' as True or False. + # + # Tests for different load calls and load-call arguments. + + def test_stash_constraint(self): + # Check that an attribute constraint functions correctly. + # Note: this is a special case in "fileformats.pp". + flds = self.fields(c_t='1122', phn='0101') + file = self.save_fieldcubes(flds) + airtemp_flds = [fld for fld in flds + if fld.name() == 'air_temperature'] + stash_attribute = airtemp_flds[0].attributes['STASH'] + results = iris.load( + file, + iris.AttributeConstraint(STASH=stash_attribute)) + expected = CubeList(airtemp_flds).merge() + self.assertEqual(results, expected) + + def test_ordinary_constraint(self): + # Check that a 'normal' constraint functions correctly. + # Note: *should* be independent of structured loading. + flds = self.fields(c_h='0123') + file = self.save_fieldcubes(flds) + height_constraint = iris.Constraint( + height=lambda h: 150.0 < h < 350.0) + results = iris.load(file, height_constraint) + expected = CubeList(flds[1:3]).merge() + self.assertEqual(results, expected) + + def test_callback(self): + # Use 2 timesteps each of (air-temp on height) and (rh on pressure). + flds = self.fields(c_t='0011', + phn='0303', + c_h='0-1-', + c_p='-2-3') + file = self.save_fieldcubes(flds) + + if not self.do_fast_loads: + def callback(cube, field, filename): + self.assertEqual(filename, file) + lbvc = field.lbvc + if lbvc == 1: + # reject the height level data (accept only pressure). + raise IgnoreCubeException() + else: + # Record the LBVC value. + cube.attributes['LBVC'] = lbvc + else: + def callback(cube, collation, filename): + self.assertEqual(filename, file) + lbvcs = [fld.lbvc + for fld in collation.fields] + lbvc0 = lbvcs[0] + if not np.all(lbvcs == lbvc0): + msg = 'Fields have different LBVCs : {}' + raise ValueError(msg.format(set(lbvcs))) + if lbvc0 == 1: + # reject the height level data (accept only pressure). + raise IgnoreCubeException() + else: + # Record the LBVC values. + cube.attributes['A_LBVC'] = lbvcs + + results = iris.load(file, callback=callback) + + # Make an 'expected' from selected fields, with the expected attribute. + expected = CubeList([flds[1], flds[3]]).merge() + if not self.do_fast_loads: + expected[0].attributes['LBVC'] = 8 + else: + expected[0].attributes['A_LBVC'] = [8, 8] + + self.assertEqual(results, expected) + + def test_load_cube(self): + flds = self.fields(c_t='123', cft='000', ctp='123', c_p=0) + file = self.save_fieldcubes(flds) + results = iris.load_cube(file) + expected = CubeList(flds).merge_cube() + self.assertEqual(results, expected) + + def test_load_cubes(self): + flds = self.fields(c_h='0123') + file = self.save_fieldcubes(flds) + height_constraints = [ + iris.Constraint(height=300.0), + iris.Constraint(height=lambda h: 150.0 < h < 350.0), + iris.Constraint('air_temperature')] + results = iris.load_cubes(file, height_constraints) + expected = CubeList([flds[2], + CubeList(flds[1:3]).merge_cube(), + CubeList(flds).merge_cube()]) + self.assertEqual(results, expected) + + def test_load_raw(self): + fldset_1 = self.fields(c_t='015', phn='001') + fldset_2 = self.fields(c_t='234') + file_1 = self.save_fieldcubes(fldset_1) + file_2 = self.save_fieldcubes(fldset_2) + results = iris.load_raw((file_1, file_2)) + if not self.do_fast_loads: + # Each 'raw' cube is just one field. + expected = CubeList(fldset_1 + fldset_2) + else: + # 'Raw' cubes have combined (vector) times within each file. + # The 'other' phenomenon appears seperately. + expected = CubeList([ + CubeList(fldset_1[:2]).merge_cube(), + CubeList(fldset_2).merge_cube(), + fldset_1[2], + ]) + + # Again here, the order of these results is not stable : + # It varies with random characters in the temporary filepath. + # + # ***************************************************************** + # *** Here, this is clearly ALSO the case for "standard" loads. *** + # ***************************************************************** + # + # E.G. run "test_fast_load.py -v TestCallDetails__Iris.test_load_raw" : + # If you remove the sort operations, this fails "sometimes". + # + # To fix this, sort both expected and results by (first) timepoint + # - for which purpose we made all the time values different. + + def timeorder(cube): + return cube.coord('time').points[0] + + expected = sorted(expected, key=timeorder) + results = sorted(results, key=timeorder) + + self.assertEqual(results, expected) + + +class MixinDimsAndOrdering(object): + # A mixin of tests that can be applied to *either* standard or fast load. + # The "real" test classes must inherit this, and Mixin_FieldTest, + # and define 'self.do_fast_loads' as True or False. + # + # Tests for multidimensional results and dimension orderings. + + def test_multidim(self): + # Check that a full 2-phenom * 2d structure all works properly. + flds = self.fields(c_t='00001111', + c_h='00110011', + phn='01010101') + file = self.save_fieldcubes(flds) + results = iris.load(file) + expected = CubeList(flds).merge() + self.assertEqual(results, expected) + + def test_odd_order(self): + # Show that an erratic interleaving of phenomena fields still works. + # N.B. field sequences *within* each phenomenon are properly ordered. + flds = self.fields(c_t='00010111', + c_h='00101101', + phn='01001011') + file = self.save_fieldcubes(flds) + results = iris.load(file) + expected = CubeList(flds).merge() + self.assertEqual(results, expected) + + def test_v_t_order(self): + # With height varying faster than time, first dimension is time, + # which matches the 'normal' load behaviour. + flds = self.fields(c_t='000111', + c_h='012012') + file = self.save_fieldcubes(flds) + results = iris.load(file) + expected = CubeList(flds).merge() + # Order is (t, h, y, x), which is "standard". + self.assertEqual(expected[0].coord_dims('time'), (0,)) + self.assertEqual(expected[0].coord_dims('height'), (1,)) + self.assertEqual(results, expected) + + def test_t_v_order(self): + # With time varying faster than height, first dimension is height, + # which does not match the 'normal' load. + flds = self.fields(c_t='010101', + c_h='001122') + file = self.save_fieldcubes(flds) + results = iris.load(file) + expected = CubeList(flds).merge() + if not self.do_fast_loads: + # Order is (t, h, y, x), which is "standard". + self.assertEqual(results[0].coord_dims('time'), (0,)) + self.assertEqual(results[0].coord_dims('height'), (1,)) + else: + # Order is (h, t, y, x), which is *not* "standard". + self.assertEqual(results[0].coord_dims('time'), (1,)) + self.assertEqual(results[0].coord_dims('height'), (0,)) + expected[0].transpose((1, 0, 2, 3)) + self.assertEqual(results, expected) + + def test_missing_combination(self): + # A case where one field is 'missing' to make a 2d result. + flds = self.fields(c_t='00011', + c_h='01202') + file = self.save_fieldcubes(flds) + results = iris.load(file) + expected = CubeList(flds).merge() + self.assertEqual(expected[0].coord_dims('time'), (0,)) + self.assertEqual(expected[0].coord_dims('height'), (0,)) + if self.do_fast_loads: + # Something a bit weird happens to the 'height' coordinate in this + # case (and not for standard load). + for cube in expected: + cube.coord('height').points = np.array( + cube.coord('height').points, + dtype=np.float32) + cube.coord('height').attributes = {} + self.assertEqual(results, expected) + + +class MixinProblemCases(object): + def test_FAIL_scalar_vector_concatenate(self): + # Structured load can produce a scalar coordinate from one file, and a + # matching vector one from another file, but these won't "combine". + # We'd really like to fix this one... + single_timepoint_fld, = self.fields(c_t='1') + multi_timepoint_flds = self.fields(c_t='23') + file_single = self.save_fieldcubes([single_timepoint_fld], + basename='single') + file_multi = self.save_fieldcubes(multi_timepoint_flds, + basename='multi') + + results = iris.load((file_single, file_multi)) + if not self.do_fast_loads: + # This is what we'd LIKE to get (what iris.load gives). + expected = CubeList(multi_timepoint_flds + + [single_timepoint_fld]).merge() + else: + # This is what we ACTUALLY get at present. + # It can't combine the scalar and vector time coords. + expected = CubeList([CubeList(multi_timepoint_flds).merge_cube(), + single_timepoint_fld]) + # NOTE: in this case, we need to sort the results to ensure a + # repeatable ordering, because ??somehow?? the random temporary + # directory name affects the ordering of the cubes in the result ! + results = CubeList(sorted(results, + key=lambda cube: cube.shape)) + self.assertEqual(results, expected) + + def test_FAIL_phenomena_nostash(self): + # If we remove the 'STASH' attributes, certain phenomena can still be + # successfully encoded+decoded by standard load using LBFC values. + # Structured loading gets this wrong, because it does not use LBFC in + # characterising phenomena. + flds = self.fields(c_t='1122', phn='0101') + for fld in flds: + del fld.attributes['STASH'] + file = self.save_fieldcubes(flds) + results = iris.load(file) + if not self.do_fast_loads: + # This is what we'd LIKE to get (what iris.load gives). + expected = CubeList(flds).merge() + else: + # At present, we get a cube incorrectly combined together over all + # 4 timepoints, with the same phenomenon for all (!wrong!). + # It's a bit tricky to arrange the existing data like that. + # Do it by hacking the time values to allow merge, and then fixing + # up the time + old_t1, old_t2 = (fld.coord('time').points[0] + for fld in (flds[0], flds[2])) + for i_fld, fld in enumerate(flds): + # Hack the phenomena to all look like the first one. + fld.rename('air_temperature') + fld.units = 'K' + # Hack the time points so the 4 cube can merge into one. + fld.coord('time').points = [old_t1 + i_fld] + one_cube = CubeList(flds).merge_cube() + # Replace time dim with an anonymous dim. + co_t_fake = one_cube.coord('time') + one_cube.remove_coord(co_t_fake) + # Reconstruct + add back the expected auxiliary time coord. + co_t_new = AuxCoord([old_t1, old_t1, old_t2, old_t2], + standard_name='time', units=co_t_fake.units) + one_cube.add_aux_coord(co_t_new, 0) + expected = [one_cube] + self.assertEqual(results, expected) + + def test_FAIL_pseudo_levels(self): + # Show how pseudo levels are handled. + flds = self.fields(c_t='000111222', + pse='123123123') + file = self.save_fieldcubes(flds) + results = iris.load(file) + expected = CubeList(flds).merge() + +# NOTE: this problem is now fixed : Structured load gives the same answer. +# +# if not self.do_fast_loads: +# expected = CubeList(flds).merge() +# else: +# # Structured loading doesn't understand pseudo-level. +# # The result is rather horrible... +# +# # First get a cube over 9 timepoints. +# flds = self.fields(c_t='012345678', +# pse=1) # result gets level==2, not clear why. +# +# # Replace the time coord with an AUX coord. +# nine_timepoints_cube = CubeList(flds).merge_cube() +# co_time = nine_timepoints_cube.coord('time') +# nine_timepoints_cube.remove_coord(co_time) +# nine_timepoints_cube.add_aux_coord(AuxCoord.from_coord(co_time), +# 0) +# # Set the expected timepoints equivalent to '000111222'. +# nine_timepoints_cube.coord('time').points = \ +# np.array([0.0, 0.0, 0.0, 24.0, 24.0, 24.0, 48.0, 48.0, 48.0]) +# # Make a cubelist with this single cube. +# expected = CubeList([nine_timepoints_cube]) + + self.assertEqual(results, expected) + + +class TestBasic__Iris(Mixin_FieldTest, MixinBasic, tests.IrisTest): + # Finally, an actual test-class (unittest.TestCase) : + # run the 'basic' tests with *normal* loading. + do_fast_loads = False + + +class TestBasic__Fast(Mixin_FieldTest, MixinBasic, tests.IrisTest): + # Finally, an actual test-class (unittest.TestCase) : + # run the 'basic' tests with *FAST* loading. + do_fast_loads = True + + +class TestCallDetails__Iris(Mixin_FieldTest, MixinCallDetails, tests.IrisTest): + # Finally, an actual test-class (unittest.TestCase) : + # run the 'call details' tests with *normal* loading. + do_fast_loads = False + + +class TestCallDetails__Fast(Mixin_FieldTest, MixinCallDetails, tests.IrisTest): + # Finally, an actual test-class (unittest.TestCase) : + # run the 'call details' tests with *FAST* loading. + do_fast_loads = True + + +class TestDimsAndOrdering__Iris(Mixin_FieldTest, MixinDimsAndOrdering, + tests.IrisTest): + # Finally, an actual test-class (unittest.TestCase) : + # run the 'dimensions and ordering' tests with *normal* loading. + do_fast_loads = False + + +class TestDimsAndOrdering__Fast(Mixin_FieldTest, MixinDimsAndOrdering, + tests.IrisTest): + # Finally, an actual test-class (unittest.TestCase) : + # run the 'dimensions and ordering' tests with *FAST* loading. + do_fast_loads = True + + +class TestProblems__Iris(Mixin_FieldTest, MixinProblemCases, tests.IrisTest): + # Finally, an actual test-class (unittest.TestCase) : + # run the 'failure cases' tests with *normal* loading. + do_fast_loads = False + + +class TestProblems__Fast(Mixin_FieldTest, MixinProblemCases, tests.IrisTest): + # Finally, an actual test-class (unittest.TestCase) : + # run the 'failure cases' tests with *FAST* loading. + do_fast_loads = True + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/integration/format_interop/__init__.py b/lib/iris/tests/integration/format_interop/__init__.py index 742815bdaa..a4bacaed91 100644 --- a/lib/iris/tests/integration/format_interop/__init__.py +++ b/lib/iris/tests/integration/format_interop/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Integration tests for format interoperability.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/integration/format_interop/test_name_grib.py b/lib/iris/tests/integration/format_interop/test_name_grib.py index 976f2ccd16..6fd4ae4b41 100644 --- a/lib/iris/tests/integration/format_interop/test_name_grib.py +++ b/lib/iris/tests/integration/format_interop/test_name_grib.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -16,22 +16,42 @@ # along with Iris. If not, see . """Integration tests for NAME to GRIB2 interoperability.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests +from distutils.version import StrictVersion + +import cf_units import numpy as np +import warnings import iris -from iris.coords import DimCoord -import iris.unit + +if tests.GRIB_AVAILABLE: + import gribapi def name_cb(cube, field, filename): - t_coord = cube.coord("time") - t_coord.points = [t_coord.bounds[0][1]] + # NAME files give the time point at the end of the range but Iris' + # GRIB loader creates it in the middle (the GRIB file itself doesn't + # encode a time point). Here we make them consistent so we can + # easily compare them. + t_coord = cube.coord('time') + t_coord.points = t_coord.bounds[0][1] + fp_coord = cube.coord('forecast_period') + fp_coord.points = fp_coord.bounds[0][1] + # NAME contains extra vertical meta-data. + z_coord = cube.coords('height') + if z_coord: + z_coord[0].standard_name = 'height' + z_coord[0].long_name = 'height above ground level' +@tests.skip_grib class TestNameToGRIB(tests.IrisTest): def check_common(self, name_cube, grib_cube): @@ -48,20 +68,34 @@ def check_common(self, name_cube, grib_cube): self.assertEqual(name_cube.coord(c), grib_cube.coord(c)) + @tests.skip_data def test_name2_field(self): filepath = tests.get_data_path(('NAME', 'NAMEII_field.txt')) name_cubes = iris.load(filepath) + + # There is a known load/save problem with numerous + # gribapi/eccodes versions and + # zero only data, where min == max. + # This may be a problem with data scaling. for i, name_cube in enumerate(name_cubes): + data = name_cube.data + if np.min(data) == np.max(data): + msg = ('NAMEII cube #{}, "{}" has empty data : ' + 'SKIPPING test for this cube, as save/load will ' + 'not currently work.') + warnings.warn(msg.format(i, name_cube.name())) + continue + with self.temp_filename('.grib2') as temp_filename: iris.save(name_cube, temp_filename) grib_cube = iris.load_cube(temp_filename, callback=name_cb) - self.check_common(name_cube, grib_cube) self.assertCML( grib_cube, tests.get_result_path( ('integration', 'name_grib', 'NAMEII', '{}_{}.cml'.format(i, name_cube.name())))) + @tests.skip_data def test_name3_field(self): filepath = tests.get_data_path(('NAME', 'NAMEIII_field.txt')) name_cubes = iris.load(filepath) diff --git a/lib/iris/tests/integration/format_interop/test_pp_grib.py b/lib/iris/tests/integration/format_interop/test_pp_grib.py new file mode 100644 index 0000000000..3a2607ea23 --- /dev/null +++ b/lib/iris/tests/integration/format_interop/test_pp_grib.py @@ -0,0 +1,57 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for PP/GRIB interoperability.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import iris + + +@tests.skip_grib +class TestBoundedTime(tests.IrisTest): + @tests.skip_data + def test_time_and_forecast_period_round_trip(self): + pp_path = tests.get_data_path(('PP', 'meanMaxMin', + '200806081200__qwpb.T24.pp')) + # Choose the first time-bounded Cube in the PP dataset. + original = [cube for cube in iris.load(pp_path) if + cube.coord('time').has_bounds()][0] + # Save it to GRIB2 and re-load. + with self.temp_filename('.grib2') as grib_path: + iris.save(original, grib_path) + from_grib = iris.load_cube(grib_path) + # Avoid the downcasting warning when saving to PP. + from_grib.data = from_grib.data.astype('f4') + # Re-save to PP and re-load. + with self.temp_filename('.pp') as pp_path: + iris.save(from_grib, pp_path) + from_pp = iris.load_cube(pp_path) + self.assertEqual(original.coord('time'), from_grib.coord('time')) + self.assertEqual(original.coord('forecast_period'), + from_grib.coord('forecast_period')) + self.assertEqual(original.coord('time'), from_pp.coord('time')) + self.assertEqual(original.coord('forecast_period'), + from_pp.coord('forecast_period')) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/integration/plot/__init__.py b/lib/iris/tests/integration/plot/__init__.py new file mode 100644 index 0000000000..fb405492cf --- /dev/null +++ b/lib/iris/tests/integration/plot/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for the :mod:`iris.plot` package.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/integration/plot/test_colorbar.py b/lib/iris/tests/integration/plot/test_colorbar.py new file mode 100644 index 0000000000..5e59bb4330 --- /dev/null +++ b/lib/iris/tests/integration/plot/test_colorbar.py @@ -0,0 +1,104 @@ +# (C) British Crown Copyright 2014 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test interaction between :mod:`iris.plot` and +:func:`matplotlib.pyplot.colorbar` + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import numpy as np + +from iris.coords import AuxCoord +import iris.tests.stock + +# Run tests in no graphics mode if matplotlib is not available. +if tests.MPL_AVAILABLE: + import matplotlib.pyplot as plt + from iris.plot import contour, contourf, pcolormesh, pcolor,\ + points, scatter + + +@tests.skip_plot +class TestColorBarCreation(tests.GraphicsTest): + def setUp(self): + super(TestColorBarCreation, self).setUp() + self.draw_functions = (contour, contourf, pcolormesh, pcolor) + self.cube = iris.tests.stock.lat_lon_cube() + self.cube.coord('longitude').guess_bounds() + self.cube.coord('latitude').guess_bounds() + self.traj_lon = AuxCoord(np.linspace(-180, 180, 50), + standard_name='longitude', + units='degrees') + self.traj_lat = AuxCoord(np.sin(np.deg2rad(self.traj_lon.points))*30.0, + standard_name='latitude', + units='degrees') + + def test_common_draw_functions(self): + for draw_function in self.draw_functions: + mappable = draw_function(self.cube) + cbar = plt.colorbar() + self.assertIs( + cbar.mappable, mappable, + msg='Problem with draw function iris.plot.{}'.format( + draw_function.__name__)) + + def test_common_draw_functions_specified_mappable(self): + for draw_function in self.draw_functions: + mappable_initial = draw_function(self.cube, cmap='cool') + mappable = draw_function(self.cube) + cbar = plt.colorbar(mappable_initial) + self.assertIs( + cbar.mappable, mappable_initial, + msg='Problem with draw function iris.plot.{}'.format( + draw_function.__name__)) + + def test_points_with_c_kwarg(self): + mappable = points(self.cube, c=self.cube.data) + cbar = plt.colorbar() + self.assertIs(cbar.mappable, mappable) + + def test_points_with_c_kwarg_specified_mappable(self): + mappable_initial = points(self.cube, c=self.cube.data, cmap='cool') + mappable = points(self.cube, c=self.cube.data) + cbar = plt.colorbar(mappable_initial) + self.assertIs(cbar.mappable, mappable_initial) + + def test_scatter_with_c_kwarg(self): + mappable = scatter(self.traj_lon, self.traj_lat, + c=self.traj_lon.points) + cbar = plt.colorbar() + self.assertIs(cbar.mappable, mappable) + + def test_scatter_with_c_kwarg_specified_mappable(self): + mappable_initial = scatter(self.traj_lon, self.traj_lat, + c=self.traj_lon.points) + mappable = scatter(self.traj_lon, self.traj_lat, + c=self.traj_lon.points, + cmap='cool') + cbar = plt.colorbar(mappable_initial) + self.assertIs(cbar.mappable, mappable_initial) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/integration/plot/test_netcdftime.py b/lib/iris/tests/integration/plot/test_netcdftime.py new file mode 100644 index 0000000000..b4c19bd3e5 --- /dev/null +++ b/lib/iris/tests/integration/plot/test_netcdftime.py @@ -0,0 +1,65 @@ +# (C) British Crown Copyright 2016 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test plot of time coord with non-gregorian calendar. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import cftime +import numpy as np + +from iris.coords import AuxCoord + +from cf_units import Unit +if tests.NC_TIME_AXIS_AVAILABLE: + from nc_time_axis import CalendarDateTime + + +# Run tests in no graphics mode if matplotlib is not available. +if tests.MPL_AVAILABLE: + import matplotlib.pyplot as plt + import iris.plot as iplt + + +@tests.skip_nc_time_axis +@tests.skip_plot +class Test(tests.GraphicsTest): + def test_360_day_calendar(self): + n = 360 + calendar = '360_day' + time_unit = Unit('days since 1970-01-01 00:00', calendar=calendar) + time_coord = AuxCoord(np.arange(n), 'time', units=time_unit) + times = [time_unit.num2date(point) for point in time_coord.points] + times = [cftime.datetime(atime.year, atime.month, atime.day, + atime.hour, atime.minute, atime.second) + for atime in times] + expected_ydata = np.array([CalendarDateTime(time, calendar) + for time in times]) + line1, = iplt.plot(time_coord) + result_ydata = line1.get_ydata() + self.assertArrayEqual(expected_ydata, result_ydata) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/integration/plot/test_nzdateline.py b/lib/iris/tests/integration/plot/test_nzdateline.py new file mode 100644 index 0000000000..42c58bc550 --- /dev/null +++ b/lib/iris/tests/integration/plot/test_nzdateline.py @@ -0,0 +1,52 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test set up of limited area map extents which bridge the date line. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import iris +# Run tests in no graphics mode if matplotlib is not available. +if tests.MPL_AVAILABLE: + import matplotlib.pyplot as plt + from iris.plot import contour, contourf, pcolormesh, pcolor,\ + points, scatter + + +@tests.skip_plot +@tests.skip_data +class TestExtent(tests.IrisTest): + def test_dateline(self): + dpath = tests.get_data_path(['PP', 'nzgust.pp']) + cube = iris.load_cube(dpath) + pcolormesh(cube) + # Ensure that the limited area expected for NZ is set. + # This is set in longitudes with the datum set to the + # International Date Line. + self.assertTrue(-10 < plt.gca().get_xlim()[0] < -5 and + 5 < plt.gca().get_xlim()[1] < 10) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/integration/plot/test_plot_2d_coords.py b/lib/iris/tests/integration/plot/test_plot_2d_coords.py new file mode 100644 index 0000000000..420430afc6 --- /dev/null +++ b/lib/iris/tests/integration/plot/test_plot_2d_coords.py @@ -0,0 +1,95 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test plots with two dimensional coordinates. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import cartopy.crs as ccrs +import matplotlib.pyplot as plt +import numpy as np + +import iris +from iris.analysis.cartography import unrotate_pole +from iris.cube import Cube +from iris.coords import AuxCoord + + +# Run tests in no graphics mode if matplotlib is not available. +if tests.MPL_AVAILABLE: + import iris.quickplot as qplt + + +@tests.skip_data +def simple_cube_w_2d_coords(): + path = tests.get_data_path(('NetCDF', 'ORCA2', 'votemper.nc')) + cube = iris.load_cube(path) + return cube + + +@tests.skip_plot +@tests.skip_data +class Test(tests.GraphicsTest): + def test_2d_coord_bounds_platecarree(self): + # To avoid a problem with Cartopy smearing the data where the + # longitude wraps, we set the central_longitude + cube = simple_cube_w_2d_coords()[0, 0] + ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=180)) + qplt.pcolormesh(cube) + ax.coastlines(color='red') + self.check_graphic() + + def test_2d_coord_bounds_northpolarstereo(self): + cube = simple_cube_w_2d_coords()[0, 0] + ax = plt.axes(projection=ccrs.NorthPolarStereo()) + qplt.pcolormesh(cube) + ax.coastlines(color='red') + self.check_graphic() + + +@tests.skip_plot +class Test2dContour(tests.GraphicsTest): + def test_2d_coords_contour(self): + ny, nx = 4, 6 + x1 = np.linspace(-20, 70, nx) + y1 = np.linspace(10, 60, ny) + data = np.zeros((ny, nx)) + data.flat[:] = np.arange(nx * ny) % 7 + cube = Cube(data, long_name='Odd data') + x2, y2 = np.meshgrid(x1, y1) + true_lons, true_lats = unrotate_pole(x2, y2, -130., 77.) + co_x = AuxCoord(true_lons, standard_name='longitude', units='degrees') + co_y = AuxCoord(true_lats, standard_name='latitude', units='degrees') + cube.add_aux_coord(co_y, (0, 1)) + cube.add_aux_coord(co_x, (0, 1)) + ax = plt.axes(projection=ccrs.PlateCarree()) + qplt.contourf(cube) + ax.coastlines(color='red') + ax.gridlines(draw_labels=True) + ax.set_extent((0, 180, 0, 90)) + self.check_graphic() + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/integration/plot/test_vector_plots.py b/lib/iris/tests/integration/plot/test_vector_plots.py new file mode 100644 index 0000000000..00d9d48e8d --- /dev/null +++ b/lib/iris/tests/integration/plot/test_vector_plots.py @@ -0,0 +1,180 @@ +# (C) British Crown Copyright 2014 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test some key usages of :func:`iris.plot.quiver`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import numpy as np + +import cartopy.crs as ccrs +from iris.coords import AuxCoord, DimCoord +from iris.coord_systems import Mercator +from iris.cube import Cube +from iris.tests.stock import sample_2d_latlons + +# Run tests in no graphics mode if matplotlib is not available. +if tests.MPL_AVAILABLE: + import matplotlib.pyplot as plt + from iris.plot import quiver + + +@tests.skip_plot +class MixinVectorPlotCases(object): + """ + Test examples mixin, used by separate quiver + streamplot classes. + + NOTE: at present for quiver only, as streamplot does not support arbitrary + coordinates. + + """ + + def plot(self, plotname, *args, **kwargs): + plot_function = self.plot_function_to_test() + plot_function(*args, **kwargs) + plt.suptitle(plotname) + + @staticmethod + def _nonlatlon_xyuv(): + # Create common x, y, u, v arrays for quiver/streamplot testing. + x = np.array([0., 2, 3, 5]) + y = np.array([0., 2.5, 4]) + uv = np.array([[(0., 0), (0, 1), (0, -1), (2, 1)], + [(-1, 0), (-1, -1), (-1, 1), (-2, 1)], + [(1., 0), (1, -1), (1, 1), (-2, 2)]]) + uv = np.array(uv) + u, v = uv[..., 0], uv[..., 1] + return x, y, u, v + + @staticmethod + def _nonlatlon_uv_cubes(x, y, u, v): + # Create u and v test cubes from x, y, u, v arrays. + coord_cls = DimCoord if x.ndim == 1 else AuxCoord + x_coord = coord_cls(x, long_name='x') + y_coord = coord_cls(y, long_name='y') + u_cube = Cube(u, long_name='u', units='ms-1') + if x.ndim == 1: + u_cube.add_dim_coord(y_coord, 0) + u_cube.add_dim_coord(x_coord, 1) + else: + u_cube.add_aux_coord(y_coord, (0, 1)) + u_cube.add_aux_coord(x_coord, (0, 1)) + v_cube = u_cube.copy() + v_cube.rename('v') + v_cube.data = v + return u_cube, v_cube + + def test_non_latlon_1d_coords(self): + # Plot against simple 1D x and y coords. + x, y, u, v = self._nonlatlon_xyuv() + u_cube, v_cube = self._nonlatlon_uv_cubes(x, y, u, v) + self.plot('nonlatlon, 1-d coords', u_cube, v_cube) + plt.xlim(x.min() - 1, x.max() + 2) + plt.ylim(y.min() - 1, y.max() + 2) + self.check_graphic() + + def test_non_latlon_2d_coords(self): + # Plot against expanded 2D x and y coords. + x, y, u, v = self._nonlatlon_xyuv() + x, y = np.meshgrid(x, y) + u_cube, v_cube = self._nonlatlon_uv_cubes(x, y, u, v) + # Call plot : N.B. default gives wrong coords order. + self.plot('nonlatlon_2d', u_cube, v_cube, coords=('x', 'y')) + plt.xlim(x.min() - 1, x.max() + 2) + plt.ylim(y.min() - 1, y.max() + 2) + self.check_graphic() + + @staticmethod + def _latlon_uv_cubes(grid_cube): + # Make a sample grid into u and v data for quiver/streamplot testing. + u_cube = grid_cube.copy() + u_cube.rename('dx') + u_cube.units = 'ms-1' + v_cube = u_cube.copy() + v_cube.rename('dy') + ny, nx = u_cube.shape + nn = nx * ny + angles = np.arange(nn).reshape((ny, nx)) + angles = (angles * 360.0 / 5.5) % 360. + scale = np.arange(nn) % 5 + scale = (scale + 4) / 4 + scale = scale.reshape((ny, nx)) + u_cube.data = scale * np.cos(np.deg2rad(angles)) + v_cube.data = scale * np.sin(np.deg2rad(angles)) + return u_cube, v_cube + + def test_2d_plain_latlon(self): + # Test 2d vector plotting with implicit (PlateCarree) coord system. + u_cube, v_cube = self._latlon_uv_cubes(sample_2d_latlons()) + ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=180)) + self.plot('latlon_2d', u_cube, v_cube, + coords=('longitude', 'latitude')) + ax.coastlines(color='red') + ax.set_global() + self.check_graphic() + + def test_2d_plain_latlon_on_polar_map(self): + # Test 2d vector plotting onto a different projection. + u_cube, v_cube = self._latlon_uv_cubes(sample_2d_latlons()) + ax = plt.axes(projection=ccrs.NorthPolarStereo()) + self.plot('latlon_2d_polar', u_cube, v_cube, + coords=('longitude', 'latitude')) + ax.coastlines(color='red') + self.check_graphic() + + def test_2d_rotated_latlon(self): + # Test plotting vectors in a rotated latlon coord system. + u_cube, v_cube = self._latlon_uv_cubes( + sample_2d_latlons(rotated=True)) + ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=180)) + self.plot('2d_rotated', u_cube, v_cube, + coords=('longitude', 'latitude')) + ax.coastlines(color='red') + ax.set_global() + self.check_graphic() + + def test_fail_unsupported_coord_system(self): + # Test plotting vectors in a rotated latlon coord system. + u_cube, v_cube = self._latlon_uv_cubes(sample_2d_latlons()) + patch_coord_system = Mercator() + for cube in u_cube, v_cube: + for coord in cube.coords(): + coord.coord_system = patch_coord_system + re_msg = ('Can only plot .* lat-lon projection, .* ' + 'This .* translates as Cartopy.*Mercator') + with self.assertRaisesRegexp(ValueError, re_msg): + self.plot('2d_rotated', u_cube, v_cube, + coords=('longitude', 'latitude')) + + +class TestQuiver(MixinVectorPlotCases, tests.GraphicsTest): + def setUp(self): + super(TestQuiver, self).setUp() + + def plot_function_to_test(self): + return quiver + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/integration/test_PartialDateTime.py b/lib/iris/tests/integration/test_PartialDateTime.py new file mode 100644 index 0000000000..706cf49f22 --- /dev/null +++ b/lib/iris/tests/integration/test_PartialDateTime.py @@ -0,0 +1,46 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for :class:`iris.time.PartialDateTime`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import iris +from iris.time import PartialDateTime + + +class Test(tests.IrisTest): + + @tests.skip_data + def test_cftime_interface(self): + # The `netcdf4` Python module introduced new calendar classes by v1.2.7 + # This test is primarily of this interface, so the + # final test assertion is simple. + filename = tests.get_data_path(('PP', 'structured', 'small.pp')) + cube = iris.load_cube(filename) + pdt = PartialDateTime(year=1992, month=10, day=1, hour=2) + time_constraint = iris.Constraint(time=lambda cell: cell < pdt) + sub_cube = cube.extract(time_constraint) + self.assertEqual(sub_cube.coord('time').points.shape, (1,)) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/integration/test_cube.py b/lib/iris/tests/integration/test_cube.py new file mode 100644 index 0000000000..d20738382d --- /dev/null +++ b/lib/iris/tests/integration/test_cube.py @@ -0,0 +1,77 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for :class:`iris.cube.Cube`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +import iris +from iris.analysis import MEAN +from iris.cube import Cube + +from iris._lazy_data import is_lazy_data, as_lazy_data + + +class Test_aggregated_by(tests.IrisTest): + @tests.skip_data + def test_agg_by_aux_coord(self): + problem_test_file = tests.get_data_path(('NetCDF', 'testing', + 'small_theta_colpex.nc')) + cube = iris.load_cube(problem_test_file, 'air_potential_temperature') + + # Test aggregating by aux coord, notably the `forecast_period` aux + # coord on `cube`, whose `_points` attribute is a lazy array. + # This test then ensures that aggregating using `points` instead is + # successful. + + # First confirm we've got a lazy array. + # NB. This checks the merge process in `load_cube()` hasn't + # triggered the load of the coordinate's data. + forecast_period_coord = cube.coord('forecast_period') + + self.assertTrue(is_lazy_data(forecast_period_coord.core_points())) + + # Now confirm we can aggregate along this coord. + res_cube = cube.aggregated_by('forecast_period', MEAN) + res_cell_methods = res_cube.cell_methods[0] + self.assertEqual(res_cell_methods.coord_names, ('forecast_period',)) + self.assertEqual(res_cell_methods.method, 'mean') + + +class TestDataFillValue(tests.IrisTest): + def test_real(self): + data = np.ma.masked_array([1, 2, 3], [0, 1, 0], fill_value=10) + cube = Cube(data) + cube.data.fill_value = 20 + self.assertEqual(cube.data.fill_value, 20) + + def test_lazy(self): + data = np.ma.masked_array([1, 2, 3], [0, 1, 0], fill_value=10) + data = as_lazy_data(data) + cube = Cube(data) + cube.data.fill_value = 20 + self.assertEqual(cube.data.fill_value, 20) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/integration/test_ff.py b/lib/iris/tests/integration/test_ff.py new file mode 100644 index 0000000000..ead3df9e27 --- /dev/null +++ b/lib/iris/tests/integration/test_ff.py @@ -0,0 +1,101 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for loading LBC fieldsfiles.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +import iris +from iris.tests import mock + + +@tests.skip_data +class TestLBC(tests.IrisTest): + def setUp(self): + # Load multiple cubes from a test file. + file_path = tests.get_data_path(('FF', 'lbc', 'small_lbc')) + self.all_cubes = iris.load(file_path) + # Select the second cube for detailed checks (the first is orography). + self.test_cube = self.all_cubes[1] + + def test_various_cubes_shapes(self): + # Check a few aspects of the loaded cubes. + cubes = self.all_cubes + self.assertEqual(len(cubes), 10) + self.assertEqual(cubes[0].shape, (16, 16)) + self.assertEqual(cubes[1].shape, (2, 4, 16, 16)) + self.assertEqual(cubes[3].shape, (2, 5, 16, 16)) + + def test_cube_coords(self): + # Check coordinates of one cube. + cube = self.test_cube + self.assertEqual(len(cube.coords()), 8) + for name, shape in [ + ('forecast_reference_time', (1,)), + ('time', (2,)), + ('forecast_period', (2,)), + ('model_level_number', (4,)), + ('level_height', (1,)), + ('sigma', (1,)), + ('grid_latitude', (16,)), + ('grid_longitude', (16,))]: + coords = cube.coords(name) + self.assertEqual(len(coords), 1, + 'expected one {!r} coord, found {}'.format( + name, len(coords))) + coord, = coords + self.assertEqual(coord.shape, shape, + 'coord {!r} shape is {} instead of {!r}.'.format( + name, coord.shape, shape)) + + def test_cube_data(self): + # Check just a few points of the data. + cube = self.test_cube + self.assertArrayAllClose( + cube.data[:, ::2, 6, 13], + np.array([[4.218922, 10.074577], + [4.626897, 6.520156]]), + atol=1.0e-6) + + def test_cube_mask(self): + # Check the data mask : should be just the centre 6x2 section. + cube = self.test_cube + mask = np.zeros((2, 4, 16, 16), dtype=bool) + mask[:, :, 7:9, 5:11] = True + self.assertArrayEqual(cube.data.mask, mask) + + +@tests.skip_data +class TestSkipField(tests.IrisTest): + def test_missing_lbrel(self): + infile = tests.get_data_path(('FF', 'lbrel_missing')) + with mock.patch('warnings.warn') as warn_fn: + fields = iris.load(infile) + self.assertIn("Input field skipped as PPField creation failed : " + "error = 'Unsupported header release number: -32768'", + warn_fn.call_args[0][0]) + self.assertEqual(len(fields), 2) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/integration/test_grib2.py b/lib/iris/tests/integration/test_grib2.py new file mode 100644 index 0000000000..71e80147b9 --- /dev/null +++ b/lib/iris/tests/integration/test_grib2.py @@ -0,0 +1,339 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for loading and saving GRIB2 files.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from cf_units import Unit +import numpy.ma as ma + +import iris +from iris import load_cube, save +from iris.coords import CellMethod, DimCoord +from iris.coord_systems import RotatedGeogCS +from iris.fileformats.pp import EARTH_RADIUS as UM_DEFAULT_EARTH_RADIUS +import iris.tests.stock as stock +from iris.util import is_regular + +# Grib support is optional. +if tests.GRIB_AVAILABLE: + from iris_grib import load_pairs_from_fields + from iris_grib.message import GribMessage + + +@tests.skip_data +@tests.skip_grib +class TestImport(tests.IrisTest): + def test_gdt1(self): + path = tests.get_data_path(('GRIB', 'rotated_nae_t', + 'sensible_pole.grib2')) + cube = load_cube(path) + self.assertCMLApproxData(cube) + + def test_gdt90_with_bitmap(self): + path = tests.get_data_path(('GRIB', 'umukv', 'ukv_chan9.grib2')) + cube = load_cube(path) + # Pay particular attention to the orientation. + self.assertIsNot(cube.data[0, 0], ma.masked) + self.assertIs(cube.data[-1, 0], ma.masked) + self.assertIs(cube.data[0, -1], ma.masked) + self.assertIs(cube.data[-1, -1], ma.masked) + x = cube.coord('projection_x_coordinate').points + y = cube.coord('projection_y_coordinate').points + self.assertGreater(x[0], x[-1]) # Decreasing X coordinate + self.assertLess(y[0], y[-1]) # Increasing Y coordinate + # Check everything else. + self.assertCMLApproxData(cube) + + +@tests.skip_data +@tests.skip_grib +class TestPDT8(tests.IrisTest): + def setUp(self): + # Load from the test file. + file_path = tests.get_data_path(('GRIB', 'time_processed', + 'time_bound.grib2')) + self.cube = load_cube(file_path) + + def test_coords(self): + # Check the result has main coordinates as expected. + for name, shape, is_bounded in [ + ('forecast_reference_time', (1,), False), + ('time', (1,), True), + ('forecast_period', (1,), True), + ('pressure', (1,), False), + ('latitude', (73,), False), + ('longitude', (96,), False)]: + coords = self.cube.coords(name) + self.assertEqual(len(coords), 1, + 'expected one {!r} coord, found {}'.format( + name, len(coords))) + coord, = coords + self.assertEqual(coord.shape, shape, + 'coord {!r} shape is {} instead of {!r}.'.format( + name, coord.shape, shape)) + self.assertEqual(coord.has_bounds(), is_bounded, + 'coord {!r} has_bounds={}, expected {}.'.format( + name, coord.has_bounds(), is_bounded)) + + def test_cell_method(self): + # Check the result has the expected cell method. + cell_methods = self.cube.cell_methods + self.assertEqual(len(cell_methods), 1, + 'result has {} cell methods, expected one.'.format( + len(cell_methods))) + cell_method, = cell_methods + self.assertEqual(cell_method.coord_names, ('time',)) + + +@tests.skip_data +@tests.skip_grib +class TestPDT11(tests.TestGribMessage): + def test_perturbation(self): + path = tests.get_data_path(('NetCDF', 'global', 'xyt', + 'SMALL_hires_wind_u_for_ipcc4.nc')) + cube = load_cube(path) + # trim to 1 time and regular lats + cube = cube[0, 12:144, :] + crs = iris.coord_systems.GeogCS(6371229) + cube.coord('latitude').coord_system = crs + cube.coord('longitude').coord_system = crs + # add a realization coordinate + cube.add_aux_coord(iris.coords.DimCoord(points=1, + standard_name='realization', + units='1')) + with self.temp_filename('testPDT11.GRIB2') as temp_file_path: + iris.save(cube, temp_file_path) + + # Check that various aspects of the saved file are as expected. + expect_values = ( + (0, 'editionNumber', 2), + (3, 'gridDefinitionTemplateNumber', 0), + (4, 'productDefinitionTemplateNumber', 11), + (4, 'perturbationNumber', 1), + (4, 'typeOfStatisticalProcessing', 0), + (4, 'numberOfForecastsInEnsemble', 255)) + self.assertGribMessageContents(temp_file_path, expect_values) + + +@tests.skip_grib +class TestPDT40(tests.IrisTest): + def test_save_load(self): + cube = stock.lat_lon_cube() + cube.rename('atmosphere_mole_content_of_ozone') + cube.units = Unit('Dobson') + tcoord = DimCoord(23, 'time', + units=Unit('days since epoch', calendar='standard')) + fpcoord = DimCoord(24, 'forecast_period', units=Unit('hours')) + cube.add_aux_coord(tcoord) + cube.add_aux_coord(fpcoord) + cube.attributes['WMO_constituent_type'] = 0 + + with self.temp_filename('test_grib_pdt40.grib2') as temp_file_path: + save(cube, temp_file_path) + loaded = load_cube(temp_file_path) + self.assertEqual(loaded.attributes, cube.attributes) + + +@tests.skip_data +@tests.skip_grib +class TestGDT5(tests.TestGribMessage): + def test_save_load(self): + # Load sample UKV data (variable-resolution rotated grid). + path = tests.get_data_path(('PP', 'ukV1', 'ukVpmslont.pp')) + cube = load_cube(path) + + # Extract a single 2D field, for simplicity. + self.assertEqual(cube.ndim, 3) + self.assertEqual(cube.coord_dims('time'), (0,)) + cube = cube[0] + + # FOR NOW: **also** fix the data so that it is square, i.e. nx=ny. + # This is needed because of a bug in the gribapi. + # See : https://software.ecmwf.int/issues/browse/SUP-1096 + ny, nx = cube.shape + nn = min(nx, ny) + cube = cube[:nn, :nn] + + # Check that it has a rotated-pole variable-spaced grid, as expected. + x_coord = cube.coord(axis='x') + self.assertIsInstance(x_coord.coord_system, RotatedGeogCS) + self.assertFalse(is_regular(x_coord)) + + # Write to temporary file, check that key contents are in the file, + # then load back in. + with self.temp_filename('ukv_sample.grib2') as temp_file_path: + save(cube, temp_file_path) + + # Check that various aspects of the saved file are as expected. + expect_values = ( + (0, 'editionNumber', 2), + (3, 'gridDefinitionTemplateNumber', 5), + (3, 'Ni', cube.shape[-1]), + (3, 'Nj', cube.shape[-2]), + (3, 'shapeOfTheEarth', 1), + (3, 'scaledValueOfRadiusOfSphericalEarth', + int(UM_DEFAULT_EARTH_RADIUS)), + (3, 'resolutionAndComponentFlags', 0), + (3, 'latitudeOfSouthernPole', -37500000), + (3, 'longitudeOfSouthernPole', 357500000), + (3, 'angleOfRotation', 0)) + self.assertGribMessageContents(temp_file_path, expect_values) + + # Load the Grib file back into a new cube. + cube_loaded_from_saved = load_cube(temp_file_path) + # Also load data, before the temporary file gets deleted. + cube_loaded_from_saved.data + + # The re-loaded result will not match the original in every respect: + # * cube attributes are discarded + # * horizontal coordinates are rounded to an integer representation + # * bounds on horizontal coords are lost + # Thus the following "equivalence tests" are rather piecemeal.. + + # Check those re-loaded properties which should match the original. + for test_cube in (cube, cube_loaded_from_saved): + self.assertEqual(test_cube.standard_name, + 'air_pressure_at_sea_level') + self.assertEqual(test_cube.units, 'Pa') + self.assertEqual(test_cube.shape, (744, 744)) + self.assertEqual(test_cube.cell_methods, ()) + + # Check no cube attributes on the re-loaded cube. + # Note: this does *not* match the original, but is as expected. + self.assertEqual(cube_loaded_from_saved.attributes, {}) + + # Now remaining to check: coordinates + data... + + # Check they have all the same coordinates. + co_names = [coord.name() for coord in cube.coords()] + co_names_reload = [coord.name() + for coord in cube_loaded_from_saved.coords()] + self.assertEqual(sorted(co_names_reload), sorted(co_names)) + + # Check all the coordinates. + for coord_name in co_names: + try: + co_orig = cube.coord(coord_name) + co_load = cube_loaded_from_saved.coord(coord_name) + + # Check shape. + self.assertEqual(co_load.shape, co_orig.shape, + 'Shape of re-loaded "{}" coord is {} ' + 'instead of {}'.format(coord_name, + co_load.shape, + co_orig.shape)) + + # Check coordinate points equal, within a tolerance. + self.assertArrayAllClose(co_load.points, co_orig.points, + rtol=1.0e-6) + + # Check all coords are unbounded. + # (NOTE: this is not so for the original X and Y coordinates, + # but Grib does not store those bounds). + self.assertIsNone(co_load.bounds) + + except AssertionError as err: + self.assertTrue(False, + 'Failed on coordinate "{}" : {}'.format( + coord_name, str(err))) + + # Check that main data array also matches. + self.assertArrayAllClose(cube.data, cube_loaded_from_saved.data) + + +@tests.skip_data +@tests.skip_grib +class TestGDT30(tests.IrisTest): + + def test_lambert(self): + path = tests.get_data_path(('GRIB', 'lambert', 'lambert.grib2')) + cube = load_cube(path) + self.assertCMLApproxData(cube) + + +@tests.skip_data +@tests.skip_grib +class TestGDT40(tests.IrisTest): + + def test_regular(self): + path = tests.get_data_path(('GRIB', 'gaussian', 'regular_gg.grib2')) + cube = load_cube(path) + self.assertCMLApproxData(cube) + + def test_reduced(self): + path = tests.get_data_path(('GRIB', 'reduced', 'reduced_gg.grib2')) + cube = load_cube(path) + self.assertCMLApproxData(cube) + + +@tests.skip_data +@tests.skip_grib +class TestDRT3(tests.IrisTest): + + def test_grid_complex_spatial_differencing(self): + path = tests.get_data_path(('GRIB', 'missing_values', + 'missing_values.grib2')) + cube = load_cube(path) + self.assertCMLApproxData(cube) + + +@tests.skip_data +@tests.skip_grib +class TestAsCubes(tests.IrisTest): + def setUp(self): + # Load from the test file. + self.file_path = tests.get_data_path(('GRIB', 'time_processed', + 'time_bound.grib2')) + + def test_year_filter(self): + msgs = GribMessage.messages_from_filename(self.file_path) + chosen_messages = [] + for gmsg in msgs: + if gmsg.sections[1]['year'] == 1998: + chosen_messages.append(gmsg) + cubes_msgs = list(load_pairs_from_fields(chosen_messages)) + self.assertEqual(len(cubes_msgs), 1) + + def test_year_filter_none(self): + msgs = GribMessage.messages_from_filename(self.file_path) + chosen_messages = [] + for gmsg in msgs: + if gmsg.sections[1]['year'] == 1958: + chosen_messages.append(gmsg) + cubes_msgs = list(load_pairs_from_fields(chosen_messages)) + self.assertEqual(len(cubes_msgs), 0) + + def test_as_pairs(self): + messages = GribMessage.messages_from_filename(self.file_path) + cubes = [] + cube_msg_pairs = load_pairs_from_fields(messages) + for cube, gmsg in cube_msg_pairs: + if gmsg.sections[1]['year'] == 1998: + cube.attributes['the year is'] = gmsg.sections[1]['year'] + cubes.append(cube) + self.assertEqual(len(cubes), 1) + self.assertEqual(cubes[0].attributes['the year is'], 1998) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/integration/test_grib_load.py b/lib/iris/tests/integration/test_grib_load.py new file mode 100644 index 0000000000..2cf18154fc --- /dev/null +++ b/lib/iris/tests/integration/test_grib_load.py @@ -0,0 +1,222 @@ +# (C) British Crown Copyright 2010 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Integration tests for grib2 file loading. + +This code used to be part of 'tests/test_grib_load.py', but these integration- +style tests have been split out of there. + +The remainder of the old 'tests/test_grib_load.py' is now renamed as +'tests/test_grib_load_translations.py'. Those tests are implementation- +specific, and target the module 'iris_grib'. + +""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import iris +import iris.exceptions +import iris.tests.stock +import iris.util +from unittest import skipIf + +# Skip out some tests that fail now that grib edition 2 files no longer use +# the GribWrapper. +# TODO: either fix these problems, or remove the tests. +skip_irisgrib_fails = skipIf(True, + 'Test(s) are not currently usable with the new ' + 'grib 2 loader.') + + +@tests.skip_data +@tests.skip_grib +class TestBasicLoad(tests.GraphicsTest): + def test_load_rotated(self): + cubes = iris.load(tests.get_data_path(('GRIB', 'rotated_uk', + "uk_wrongparam.grib1"))) + self.assertCML(cubes, ("grib_load", "rotated.cml")) + + def test_load_time_bound(self): + cubes = iris.load(tests.get_data_path(('GRIB', "time_processed", + "time_bound.grib1"))) + self.assertCML(cubes, ("grib_load", "time_bound_grib1.cml")) + + def test_load_time_processed(self): + cubes = iris.load(tests.get_data_path(('GRIB', "time_processed", + "time_bound.grib2"))) + self.assertCML(cubes, ("grib_load", "time_bound_grib2.cml")) + + def test_load_3_layer(self): + cubes = iris.load(tests.get_data_path(('GRIB', "3_layer_viz", + "3_layer.grib2"))) + cubes = iris.cube.CubeList([cubes[1], cubes[0], cubes[2]]) + self.assertCML(cubes, ("grib_load", "3_layer.cml")) + + def test_load_masked(self): + gribfile = tests.get_data_path( + ('GRIB', 'missing_values', 'missing_values.grib2')) + cubes = iris.load(gribfile) + self.assertCML(cubes, ('grib_load', 'missing_values_grib2.cml')) + + @skip_irisgrib_fails + def test_y_fastest(self): + cubes = iris.load(tests.get_data_path(("GRIB", "y_fastest", + "y_fast.grib2"))) + self.assertCML(cubes, ("grib_load", "y_fastest.cml")) + + def test_polar_stereo_grib1(self): + cube = iris.load_cube(tests.get_data_path( + ("GRIB", "polar_stereo", "ST4.2013052210.01h"))) + self.assertCML(cube, ("grib_load", "polar_stereo_grib1.cml")) + + def test_polar_stereo_grib2_grid_definition(self): + cube = iris.load_cube(tests.get_data_path( + ("GRIB", "polar_stereo", + "CMC_glb_TMP_ISBL_1015_ps30km_2013052000_P006.grib2"))) + self.assertEqual(cube.shape, (200, 247)) + pxc = cube.coord('projection_x_coordinate') + self.assertAlmostEqual(pxc.points.max(), 4769905.5125, places=4) + self.assertAlmostEqual(pxc.points.min(), -2610094.4875, places=4) + pyc = cube.coord('projection_y_coordinate') + self.assertAlmostEqual(pyc.points.max(), -216.1459, places=4) + self.assertAlmostEqual(pyc.points.min(), -5970216.1459, places=4) + self.assertEqual(pyc.coord_system, pxc.coord_system) + self.assertEqual(pyc.coord_system.grid_mapping_name, 'stereographic') + self.assertEqual(pyc.coord_system.central_lat, 90.0) + self.assertEqual(pyc.coord_system.central_lon, 249.0) + self.assertEqual(pyc.coord_system.false_easting, 0.0) + self.assertEqual(pyc.coord_system.false_northing, 0.0) + self.assertEqual(pyc.coord_system.true_scale_lat, 60.0) + + def test_lambert_grib1(self): + cube = iris.load_cube(tests.get_data_path( + ("GRIB", "lambert", "lambert.grib1"))) + self.assertCML(cube, ("grib_load", "lambert_grib1.cml")) + + def test_lambert_grib2(self): + cube = iris.load_cube(tests.get_data_path( + ("GRIB", "lambert", "lambert.grib2"))) + self.assertCML(cube, ("grib_load", "lambert_grib2.cml")) + + def test_regular_gg_grib1(self): + cube = iris.load_cube(tests.get_data_path( + ('GRIB', 'gaussian', 'regular_gg.grib1'))) + self.assertCML(cube, ('grib_load', 'regular_gg_grib1.cml')) + + def test_regular_gg_grib2(self): + cube = iris.load_cube(tests.get_data_path( + ('GRIB', 'gaussian', 'regular_gg.grib2'))) + self.assertCML(cube, ('grib_load', 'regular_gg_grib2.cml')) + + def test_reduced_ll(self): + cube = iris.load_cube(tests.get_data_path( + ("GRIB", "reduced", "reduced_ll.grib1"))) + self.assertCML(cube, ("grib_load", "reduced_ll_grib1.cml")) + + def test_reduced_gg(self): + cube = iris.load_cube(tests.get_data_path( + ("GRIB", "reduced", "reduced_gg.grib2"))) + self.assertCML(cube, ("grib_load", "reduced_gg_grib2.cml")) + + +@tests.skip_data +@tests.skip_grib +class TestIjDirections(tests.GraphicsTest): + @staticmethod + def _old_compat_load(name): + cube = iris.load(tests.get_data_path(('GRIB', 'ij_directions', + name)))[0] + return [cube] + + def test_ij_directions_ipos_jpos(self): + cubes = self._old_compat_load("ipos_jpos.grib2") + self.assertCML(cubes, ("grib_load", "ipos_jpos.cml")) + + def test_ij_directions_ipos_jneg(self): + cubes = self._old_compat_load("ipos_jneg.grib2") + self.assertCML(cubes, ("grib_load", "ipos_jneg.cml")) + + def test_ij_directions_ineg_jneg(self): + cubes = self._old_compat_load("ineg_jneg.grib2") + self.assertCML(cubes, ("grib_load", "ineg_jneg.cml")) + + def test_ij_directions_ineg_jpos(self): + cubes = self._old_compat_load("ineg_jpos.grib2") + self.assertCML(cubes, ("grib_load", "ineg_jpos.cml")) + + +@tests.skip_data +@tests.skip_grib +class TestShapeOfEarth(tests.GraphicsTest): + @staticmethod + def _old_compat_load(name): + cube = iris.load(tests.get_data_path(('GRIB', 'shape_of_earth', + name)))[0] + return cube + + def test_shape_of_earth_basic(self): + # pre-defined sphere + cube = self._old_compat_load("0.grib2") + self.assertCML(cube, ("grib_load", "earth_shape_0.cml")) + + def test_shape_of_earth_custom_1(self): + # custom sphere + cube = self._old_compat_load("1.grib2") + self.assertCML(cube, ("grib_load", "earth_shape_1.cml")) + + def test_shape_of_earth_IAU65(self): + # IAU65 oblate sphere + cube = self._old_compat_load("2.grib2") + self.assertCML(cube, ("grib_load", "earth_shape_2.cml")) + + def test_shape_of_earth_custom_3(self): + # custom oblate spheroid (km) + cube = self._old_compat_load("3.grib2") + self.assertCML(cube, ("grib_load", "earth_shape_3.cml")) + + def test_shape_of_earth_IAG_GRS80(self): + # IAG-GRS80 oblate spheroid + cube = self._old_compat_load("4.grib2") + self.assertCML(cube, ("grib_load", "earth_shape_4.cml")) + + def test_shape_of_earth_WGS84(self): + # WGS84 + cube = self._old_compat_load("5.grib2") + self.assertCML(cube, ("grib_load", "earth_shape_5.cml")) + + def test_shape_of_earth_pre_6(self): + # pre-defined sphere + cube = self._old_compat_load("6.grib2") + self.assertCML(cube, ("grib_load", "earth_shape_6.cml")) + + def test_shape_of_earth_custom_7(self): + # custom oblate spheroid (m) + cube = self._old_compat_load("7.grib2") + self.assertCML(cube, ("grib_load", "earth_shape_7.cml")) + + def test_shape_of_earth_grib1(self): + # grib1 - same as grib2 shape 6, above + cube = self._old_compat_load("global.grib1") + self.assertCML(cube, ("grib_load", "earth_shape_grib1.cml")) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/integration/test_netcdf.py b/lib/iris/tests/integration/test_netcdf.py new file mode 100644 index 0000000000..5351e615d8 --- /dev/null +++ b/lib/iris/tests/integration/test_netcdf.py @@ -0,0 +1,433 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for loading and saving netcdf files.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from contextlib import contextmanager +from itertools import repeat +import os.path +import shutil +import tempfile +import warnings + +import netCDF4 as nc +import numpy as np +import numpy.ma as ma + +import iris +from iris.coords import CellMethod +from iris.cube import Cube, CubeList +from iris.fileformats.netcdf import CF_CONVENTIONS_VERSION +from iris.fileformats.netcdf import Saver +from iris.fileformats.netcdf import UnknownCellMethodWarning +from iris.tests import mock +import iris.tests.stock as stock + + +@tests.skip_data +class TestHybridPressure(tests.IrisTest): + def setUp(self): + # Modify stock cube so it is suitable to have a + # hybrid pressure factory added to it. + cube = stock.realistic_4d_no_derived() + cube.coord('surface_altitude').rename('surface_air_pressure') + cube.coord('surface_air_pressure').units = 'Pa' + cube.coord('level_height').rename('level_pressure') + cube.coord('level_pressure').units = 'Pa' + # Construct and add hybrid pressure factory. + factory = iris.aux_factory.HybridPressureFactory( + cube.coord('level_pressure'), + cube.coord('sigma'), + cube.coord('surface_air_pressure')) + cube.add_aux_factory(factory) + self.cube = cube + + def test_save(self): + with self.temp_filename(suffix='.nc') as filename: + iris.save(self.cube, filename) + self.assertCDL(filename) + + def test_save_load_loop(self): + # Tests an issue where the variable names in the formula + # terms changed to the standard_names instead of the variable names + # when loading a previously saved cube. + with self.temp_filename(suffix='.nc') as filename, \ + self.temp_filename(suffix='.nc') as other_filename: + iris.save(self.cube, filename) + cube = iris.load_cube(filename, 'air_potential_temperature') + iris.save(cube, other_filename) + other_cube = iris.load_cube(other_filename, + 'air_potential_temperature') + self.assertEqual(cube, other_cube) + + +@tests.skip_data +class TestSaveMultipleAuxFactories(tests.IrisTest): + def test_hybrid_height_and_pressure(self): + cube = stock.realistic_4d() + cube.add_aux_coord(iris.coords.DimCoord( + 1200.0, long_name='level_pressure', units='hPa')) + cube.add_aux_coord(iris.coords.DimCoord( + 0.5, long_name='other sigma')) + cube.add_aux_coord(iris.coords.DimCoord( + 1000.0, long_name='surface_air_pressure', units='hPa')) + factory = iris.aux_factory.HybridPressureFactory( + cube.coord('level_pressure'), + cube.coord('other sigma'), + cube.coord('surface_air_pressure')) + cube.add_aux_factory(factory) + with self.temp_filename(suffix='.nc') as filename: + iris.save(cube, filename) + self.assertCDL(filename) + + def test_shared_primary(self): + cube = stock.realistic_4d() + factory = iris.aux_factory.HybridHeightFactory( + cube.coord('level_height'), + cube.coord('sigma'), + cube.coord('surface_altitude')) + factory.rename('another altitude') + cube.add_aux_factory(factory) + with self.temp_filename(suffix='.nc') as filename, \ + self.assertRaisesRegexp(ValueError, 'multiple aux factories'): + iris.save(cube, filename) + + def test_hybrid_height_cubes(self): + hh1 = stock.simple_4d_with_hybrid_height() + hh1.attributes['cube'] = 'hh1' + hh2 = stock.simple_4d_with_hybrid_height() + hh2.attributes['cube'] = 'hh2' + sa = hh2.coord('surface_altitude') + sa.points = sa.points * 10 + with self.temp_filename('.nc') as fname: + iris.save([hh1, hh2], fname) + cubes = iris.load(fname, 'air_temperature') + cubes = sorted(cubes, key=lambda cube: cube.attributes['cube']) + self.assertCML(cubes) + + def test_hybrid_height_cubes_on_dimension_coordinate(self): + hh1 = stock.hybrid_height() + hh2 = stock.hybrid_height() + sa = hh2.coord('surface_altitude') + sa.points = sa.points * 10 + emsg = 'Unable to create dimensonless vertical coordinate.' + with self.temp_filename('.nc') as fname, \ + self.assertRaisesRegexp(ValueError, emsg): + iris.save([hh1, hh2], fname) + + +class TestUmVersionAttribute(tests.IrisTest): + def test_single_saves_as_global(self): + cube = Cube([1.0], standard_name='air_temperature', units='K', + attributes={'um_version': '4.3'}) + with self.temp_filename('.nc') as nc_path: + iris.save(cube, nc_path) + self.assertCDL(nc_path) + + def test_multiple_same_saves_as_global(self): + cube_a = Cube([1.0], standard_name='air_temperature', units='K', + attributes={'um_version': '4.3'}) + cube_b = Cube([1.0], standard_name='air_pressure', units='hPa', + attributes={'um_version': '4.3'}) + with self.temp_filename('.nc') as nc_path: + iris.save(CubeList([cube_a, cube_b]), nc_path) + self.assertCDL(nc_path) + + def test_multiple_different_saves_on_variables(self): + cube_a = Cube([1.0], standard_name='air_temperature', units='K', + attributes={'um_version': '4.3'}) + cube_b = Cube([1.0], standard_name='air_pressure', units='hPa', + attributes={'um_version': '4.4'}) + with self.temp_filename('.nc') as nc_path: + iris.save(CubeList([cube_a, cube_b]), nc_path) + self.assertCDL(nc_path) + + +@contextmanager +def _patch_site_configuration(): + def cf_patch_conventions(conventions): + return ', '.join([conventions, 'convention1, convention2']) + + def update(config): + config['cf_profile'] = mock.Mock(name='cf_profile') + config['cf_patch'] = mock.Mock(name='cf_patch') + config['cf_patch_conventions'] = cf_patch_conventions + + orig_site_config = iris.site_configuration.copy() + update(iris.site_configuration) + yield + iris.site_configuration = orig_site_config + + +class TestConventionsAttributes(tests.IrisTest): + def test_patching_conventions_attribute(self): + # Ensure that user defined conventions are wiped and those which are + # saved patched through site_config can be loaded without an exception + # being raised. + cube = Cube([1.0], standard_name='air_temperature', units='K', + attributes={'Conventions': + 'some user defined conventions'}) + + # Patch the site configuration dictionary. + with _patch_site_configuration(), self.temp_filename('.nc') as nc_path: + iris.save(cube, nc_path) + res = iris.load_cube(nc_path) + + self.assertEqual(res.attributes['Conventions'], + '{}, {}, {}'.format(CF_CONVENTIONS_VERSION, + 'convention1', 'convention2')) + + +class TestLazySave(tests.IrisTest): + + @tests.skip_data + def test_lazy_preserved_save(self): + fpath = tests.get_data_path(('NetCDF', 'label_and_climate', + 'small_FC_167_mon_19601101.nc')) + acube = iris.load_cube(fpath, 'air_temperature') + self.assertTrue(acube.has_lazy_data()) + with self.temp_filename('.nc') as nc_path: + with Saver(nc_path, 'NETCDF4') as saver: + saver.write(acube) + self.assertTrue(acube.has_lazy_data()) + + +@tests.skip_data +class TestCellMeasures(tests.IrisTest): + def setUp(self): + self.fname = tests.get_data_path(('NetCDF', 'ORCA2', 'votemper.nc')) + + def test_load_raw(self): + cube, = iris.load_raw(self.fname) + self.assertEqual(len(cube.cell_measures()), 1) + self.assertEqual(cube.cell_measures()[0].measure, 'area') + + def test_load(self): + cube = iris.load_cube(self.fname) + self.assertEqual(len(cube.cell_measures()), 1) + self.assertEqual(cube.cell_measures()[0].measure, 'area') + + def test_merge_cell_measure_aware(self): + cube1, = iris.load_raw(self.fname) + cube2, = iris.load_raw(self.fname) + cube2._cell_measures_and_dims[0][0].var_name = 'not_areat' + cubes = CubeList([cube1, cube2]).merge() + self.assertEqual(len(cubes), 2) + + def test_concatenate_cell_measure_aware(self): + cube1, = iris.load_raw(self.fname) + cube1 = cube1[:, :, 0, 0] + cm_and_dims = cube1._cell_measures_and_dims + cube2, = iris.load_raw(self.fname) + cube2 = cube2[:, :, 0, 0] + cube2._cell_measures_and_dims[0][0].var_name = 'not_areat' + cube2.coord('time').points = cube2.coord('time').points + 1 + cubes = CubeList([cube1, cube2]).concatenate() + self.assertEqual(cubes[0]._cell_measures_and_dims, cm_and_dims) + self.assertEqual(len(cubes), 2) + + def test_concatenate_cell_measure_match(self): + cube1, = iris.load_raw(self.fname) + cube1 = cube1[:, :, 0, 0] + cm_and_dims = cube1._cell_measures_and_dims + cube2, = iris.load_raw(self.fname) + cube2 = cube2[:, :, 0, 0] + cube2.coord('time').points = cube2.coord('time').points + 1 + cubes = CubeList([cube1, cube2]).concatenate() + self.assertEqual(cubes[0]._cell_measures_and_dims, cm_and_dims) + self.assertEqual(len(cubes), 1) + + def test_round_trip(self): + cube, = iris.load(self.fname) + with self.temp_filename(suffix='.nc') as filename: + iris.save(cube, filename, unlimited_dimensions=[]) + round_cube, = iris.load_raw(filename) + self.assertEqual(len(round_cube.cell_measures()), 1) + self.assertEqual(round_cube.cell_measures()[0].measure, 'area') + + def test_print(self): + cube = iris.load_cube(self.fname) + printed = cube.__str__() + self.assertTrue(('\n Cell Measures:\n cell_area' + ' - - ' + ' x x') in printed) + + +class TestCellMethod_unknown(tests.IrisTest): + def test_unknown_method(self): + cube = Cube([1, 2], long_name='odd_phenomenon') + cube.add_cell_method(CellMethod(method='oddity', coords=('x',))) + temp_dirpath = tempfile.mkdtemp() + try: + temp_filepath = os.path.join(temp_dirpath, 'tmp.nc') + iris.save(cube, temp_filepath) + with warnings.catch_warnings(record=True) as warning_records: + iris.load(temp_filepath) + # Filter to get the warning we are interested in. + warning_messages = [record.message for record in warning_records] + warning_messages = [warn for warn in warning_messages + if isinstance(warn, UnknownCellMethodWarning)] + self.assertEqual(len(warning_messages), 1) + message = warning_messages[0].args[0] + msg = ("NetCDF variable 'odd_phenomenon' contains unknown cell " + "method 'oddity'") + self.assertIn(msg, message) + finally: + shutil.rmtree(temp_dirpath) + + +@tests.skip_data +class TestCoordSystem(tests.IrisTest): + def test_load_laea_grid(self): + cube = iris.load_cube( + tests.get_data_path(('NetCDF', 'lambert_azimuthal_equal_area', + 'euro_air_temp.nc'))) + self.assertCML(cube, ('netcdf', 'netcdf_laea.cml')) + + +def _get_scale_factor_add_offset(cube, datatype): + """Utility function used by netCDF data packing tests.""" + if isinstance(datatype, dict): + dt = np.dtype(datatype['dtype']) + else: + dt = np.dtype(datatype) + cmax = cube.data.max() + cmin = cube.data.min() + n = dt.itemsize * 8 + if ma.isMaskedArray(cube.data): + masked = True + else: + masked = False + if masked: + scale_factor = (cmax - cmin)/(2**n-2) + else: + scale_factor = (cmax - cmin)/(2**n-1) + if dt.kind == 'u': + add_offset = cmin + elif dt.kind == 'i': + if masked: + add_offset = (cmax + cmin)/2 + else: + add_offset = cmin + 2**(n-1)*scale_factor + return (scale_factor, add_offset) + + +@tests.skip_data +class TestPackedData(tests.IrisTest): + def _single_test(self, datatype, CDLfilename, manual=False): + # Read PP input file. + file_in = tests.get_data_path( + ('PP', 'cf_processing', + '000003000000.03.236.000128.1990.12.01.00.00.b.pp')) + cube = iris.load_cube(file_in) + scale_factor, offset = _get_scale_factor_add_offset(cube, datatype) + if manual: + packspec = dict(dtype=datatype, scale_factor=scale_factor, + add_offset=offset) + else: + packspec = datatype + # Write Cube to netCDF file. + with self.temp_filename(suffix='.nc') as file_out: + iris.save(cube, file_out, packing=packspec) + decimal = int(-np.log10(scale_factor)) + packedcube = iris.load_cube(file_out) + # Check that packed cube is accurate to expected precision + self.assertArrayAlmostEqual(cube.data, packedcube.data, + decimal=decimal) + # Check the netCDF file against CDL expected output. + self.assertCDL(file_out, ('integration', 'netcdf', + 'TestPackedData', CDLfilename)) + + def test_single_packed_signed(self): + """Test saving a single CF-netCDF file with packing.""" + self._single_test('i2', 'single_packed_signed.cdl') + + def test_single_packed_unsigned(self): + """Test saving a single CF-netCDF file with packing into unsigned. """ + self._single_test('u1', 'single_packed_unsigned.cdl') + + def test_single_packed_manual_scale(self): + """Test saving a single CF-netCDF file with packing with scale + factor and add_offset set manually.""" + self._single_test('i2', 'single_packed_manual.cdl', manual=True) + + def _multi_test(self, CDLfilename, multi_dtype=False): + """Test saving multiple packed cubes with pack_dtype list.""" + # Read PP input file. + file_in = tests.get_data_path(('PP', 'cf_processing', + 'abcza_pa19591997_daily_29.b.pp')) + cubes = iris.load(file_in) + # ensure cube order is the same: + cubes.sort(key=lambda cube: cube.cell_methods[0].method) + datatype = 'i2' + scale_factor, offset = _get_scale_factor_add_offset(cubes[0], + datatype) + if multi_dtype: + packdict = dict(dtype=datatype, scale_factor=scale_factor, + add_offset=offset) + packspec = [packdict, None, 'u2'] + dtypes = packspec + else: + packspec = datatype + dtypes = repeat(packspec) + + # Write Cube to netCDF file. + with self.temp_filename(suffix='.nc') as file_out: + iris.save(cubes, file_out, packing=packspec) + # Check the netCDF file against CDL expected output. + self.assertCDL(file_out, ('integration', 'netcdf', + 'TestPackedData', CDLfilename)) + packedcubes = iris.load(file_out) + packedcubes.sort(key=lambda cube: cube.cell_methods[0].method) + for cube, packedcube, dtype in zip(cubes, packedcubes, dtypes): + if dtype: + sf, ao = _get_scale_factor_add_offset(cube, dtype) + decimal = int(-np.log10(sf)) + # Check that packed cube is accurate to expected precision + self.assertArrayAlmostEqual(cube.data, packedcube.data, + decimal=decimal) + else: + self.assertArrayEqual(cube.data, packedcube.data) + + def test_multi_packed_single_dtype(self): + """Test saving multiple packed cubes with the same pack_dtype.""" + # Read PP input file. + self._multi_test('multi_packed_single_dtype.cdl') + + def test_multi_packed_multi_dtype(self): + """Test saving multiple packed cubes with pack_dtype list.""" + # Read PP input file. + self._multi_test('multi_packed_multi_dtype.cdl', multi_dtype=True) + + +class TestScalarCube(tests.IrisTest): + def test_scalar_cube_save_load(self): + cube = iris.cube.Cube(1, long_name='scalar_cube') + with self.temp_filename(suffix='.nc') as fout: + iris.save(cube, fout) + scalar_cube = iris.load_cube(fout) + self.assertEqual(scalar_cube.name(), 'scalar_cube') + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/integration/test_new_axis.py b/lib/iris/tests/integration/test_new_axis.py new file mode 100644 index 0000000000..b62d01fa3a --- /dev/null +++ b/lib/iris/tests/integration/test_new_axis.py @@ -0,0 +1,43 @@ +# (C) British Crown Copyright 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for :func:`iris.util.new_axis`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import iris +from iris.util import new_axis + + +class Test(tests.IrisTest): + + @tests.skip_data + def test_lazy_data(self): + filename = tests.get_data_path(('PP', 'globClim1', 'theta.pp')) + cube = iris.load_cube(filename) + new_cube = new_axis(cube, 'time') + self.assertTrue(cube.has_lazy_data()) + self.assertTrue(new_cube.has_lazy_data()) + self.assertEqual(new_cube.shape, (1,) + cube.shape) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/integration/test_pickle.py b/lib/iris/tests/integration/test_pickle.py new file mode 100644 index 0000000000..a6506ea91e --- /dev/null +++ b/lib/iris/tests/integration/test_pickle.py @@ -0,0 +1,88 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for pickling things.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import six.moves.cPickle as pickle + +import iris +if tests.GRIB_AVAILABLE: + import gribapi + from iris_grib.message import GribMessage + + +@tests.skip_data +@tests.skip_grib +class TestGribMessage(tests.IrisTest): + def test(self): + # Check that a GribMessage pickles without errors. + path = tests.get_data_path(('GRIB', 'fp_units', 'hours.grib2')) + messages = GribMessage.messages_from_filename(path) + message = next(messages) + with self.temp_filename('.pkl') as filename: + with open(filename, 'wb') as f: + pickle.dump(message, f) + + def test_data(self): + # Check that GribMessage.data pickles without errors. + path = tests.get_data_path(('GRIB', 'fp_units', 'hours.grib2')) + messages = GribMessage.messages_from_filename(path) + message = next(messages) + with self.temp_filename('.pkl') as filename: + with open(filename, 'wb') as f: + pickle.dump(message.data, f) + + +class Common(object): + # Ensure that data proxies are pickleable. + def pickle_cube(self, path): + cube = iris.load(path)[0] + with self.temp_filename('.pkl') as filename: + with open(filename, 'wb') as f: + pickle.dump(cube, f) + + +@tests.skip_data +class test_netcdf(Common, tests.IrisTest): + def test(self): + path = tests.get_data_path(('NetCDF', 'global', 'xyt', + 'SMALL_hires_wind_u_for_ipcc4.nc')) + self.pickle_cube(path) + + +@tests.skip_data +class test_pp(Common, tests.IrisTest): + def test(self): + path = tests.get_data_path(('PP', 'aPPglob1', 'global.pp')) + self.pickle_cube(path) + + +@tests.skip_data +class test_ff(Common, tests.IrisTest): + def test(self): + path = tests.get_data_path(('FF', 'n48_multi_field')) + self.pickle_cube(path) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/integration/test_pp.py b/lib/iris/tests/integration/test_pp.py index bfd3f73674..0cc0868b1d 100644 --- a/lib/iris/tests/integration/test_pp.py +++ b/lib/iris/tests/integration/test_pp.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -16,18 +16,27 @@ # along with Iris. If not, see . """Integration tests for loading and saving PP files.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import mock import numpy as np +import os +from cf_units import Unit from iris.aux_factory import HybridHeightFactory, HybridPressureFactory -from iris.coords import AuxCoord +from iris.coords import AuxCoord, CellMethod, DimCoord from iris.cube import Cube import iris.fileformats.pp -import iris.fileformats.pp_rules +import iris.fileformats.pp_load_rules +from iris.fileformats.pp_save_rules import verify +from iris.exceptions import IgnoreCubeException +from iris.tests import mock +from iris.fileformats.pp import load_pairs_from_fields +import iris.util class TestVertical(tests.IrisTest): @@ -44,9 +53,14 @@ def test_soil_level_round_trip(self): # NB. Use MagicMock so that SplittableInt header items, such as # LBCODE, support len(). soil_level = 1234 + mock_data = np.zeros(1) + mock_core_data = mock.MagicMock(return_value=mock_data) field = mock.MagicMock(lbvc=6, lblev=soil_level, stash=iris.fileformats.pp.STASH(1, 0, 9), - lbuser=[0] * 7, lbrsvd=[0] * 4) + lbuser=[0] * 7, lbrsvd=[0] * 4, + brsvd=[0] * 4, brlev=0, + core_data=mock_core_data, + realised_dtype=mock_data.dtype) load = mock.Mock(return_value=iter([field])) with mock.patch('iris.fileformats.pp.load', new=load) as load: cube = next(iris.fileformats.pp.load_cubes('DUMMY')) @@ -58,12 +72,52 @@ def test_soil_level_round_trip(self): field = iris.fileformats.pp.PPField3() field.lbfc = 0 field.lbvc = 0 - iris.fileformats.pp._ensure_save_rules_loaded() - iris.fileformats.pp._save_rules.verify(cube, field) + field.brsvd = [None] * 4 + field.brlev = None + field = verify(cube, field) # Check the vertical coordinate is as originally specified. self.assertEqual(field.lbvc, 6) self.assertEqual(field.lblev, soil_level) + self.assertEqual(field.blev, soil_level) + self.assertEqual(field.brsvd[0], 0) + self.assertEqual(field.brlev, 0) + + def test_soil_depth_round_trip(self): + # Use pp.load_cubes() to convert a fake PPField into a Cube. + # NB. Use MagicMock so that SplittableInt header items, such as + # LBCODE, support len(). + lower, point, upper = 1.2, 3.4, 5.6 + brsvd = [lower, 0, 0, 0] + mock_data = np.zeros(1) + mock_core_data = mock.MagicMock(return_value=mock_data) + field = mock.MagicMock(lbvc=6, blev=point, + stash=iris.fileformats.pp.STASH(1, 0, 9), + lbuser=[0] * 7, lbrsvd=[0] * 4, + brsvd=brsvd, brlev=upper, + core_data=mock_core_data, + realised_dtype=mock_data.dtype) + load = mock.Mock(return_value=iter([field])) + with mock.patch('iris.fileformats.pp.load', new=load) as load: + cube = next(iris.fileformats.pp.load_cubes('DUMMY')) + + self.assertIn('soil', cube.standard_name) + self._test_coord(cube, point, bounds=[lower, upper], + standard_name='depth') + + # Now use the save rules to convert the Cube back into a PPField. + field = iris.fileformats.pp.PPField3() + field.lbfc = 0 + field.lbvc = 0 + field.brlev = None + field.brsvd = [None] * 4 + field = verify(cube, field) + + # Check the vertical coordinate is as originally specified. + self.assertEqual(field.lbvc, 6) + self.assertEqual(field.blev, point) + self.assertEqual(field.brsvd[0], lower) + self.assertEqual(field.brlev, upper) def test_potential_temperature_level_round_trip(self): # Check save+load for data on 'potential temperature' levels. @@ -72,10 +126,14 @@ def test_potential_temperature_level_round_trip(self): # NB. Use MagicMock so that SplittableInt header items, such as # LBCODE, support len(). potm_value = 22.5 + mock_data = np.zeros(1) + mock_core_data = mock.MagicMock(return_value=mock_data) field = mock.MagicMock(lbvc=19, blev=potm_value, - lbuser=[0] * 7, lbrsvd=[0] * 4) + lbuser=[0] * 7, lbrsvd=[0] * 4, + core_data=mock_core_data, + realised_dtype=mock_data.dtype) load = mock.Mock(return_value=iter([field])) - with mock.patch('iris.fileformats.pp.load', new=load) as load: + with mock.patch('iris.fileformats.pp.load', new=load): cube = next(iris.fileformats.pp.load_cubes('DUMMY')) self._test_coord(cube, potm_value, @@ -85,8 +143,7 @@ def test_potential_temperature_level_round_trip(self): field = iris.fileformats.pp.PPField3() field.lbfc = 0 field.lbvc = 0 - iris.fileformats.pp._ensure_save_rules_loaded() - iris.fileformats.pp._save_rules.verify(cube, field) + field = verify(cube, field) # Check the vertical coordinate is as originally specified. self.assertEqual(field.lbvc, 19) @@ -98,10 +155,15 @@ def test_hybrid_pressure_round_trip(self): # LBCODE, support len(). def field_with_data(scale=1): x, y = 40, 30 - field = mock.MagicMock(_data=np.arange(1200).reshape(y, x) * scale, - lbcode=[1], lbnpt=x, lbrow=y, - bzx=350, bdx=1.5, bzy=40, bdy=1.5, - lbuser=[0] * 7, lbrsvd=[0] * 4) + mock_data = np.arange(1200).reshape(y, x) * scale + mock_core_data = mock.MagicMock(return_value=mock_data) + field = mock.MagicMock(core_data=mock_core_data, + realised_dtype=mock_data.dtype, + lbcode=[1], + lbnpt=x, lbrow=y, bzx=350, bdx=1.5, + bzy=40, bdy=1.5, lbuser=[0] * 7, + lbrsvd=[0] * 4) + field._x_coord_name = lambda: 'longitude' field._y_coord_name = lambda: 'latitude' field.coord_system = lambda: None @@ -150,15 +212,14 @@ def field_with_data(scale=1): pressure_field.lbvc = 0 pressure_field.brsvd = [None, None] pressure_field.lbuser = [None] * 7 - iris.fileformats.pp._ensure_save_rules_loaded() - iris.fileformats.pp._save_rules.verify(pressure_cube, pressure_field) + pressure_field = verify(pressure_cube, pressure_field) data_field = iris.fileformats.pp.PPField3() data_field.lbfc = 0 data_field.lbvc = 0 data_field.brsvd = [None, None] data_field.lbuser = [None] * 7 - iris.fileformats.pp._save_rules.verify(data_cube, data_field) + data_field = verify(data_cube, data_field) # The reference surface field should have STASH=409 self.assertArrayEqual(pressure_field.lbuser, @@ -174,6 +235,47 @@ def field_with_data(scale=1): self.assertEqual(data_field.brlev, sigma_lower) self.assertEqual(data_field.brsvd, [sigma_upper, delta_upper]) + def test_hybrid_pressure_with_duplicate_references(self): + def field_with_data(scale=1): + x, y = 40, 30 + mock_data = np.arange(1200).reshape(y, x) * scale + mock_core_data = mock.MagicMock(return_value=mock_data) + field = mock.MagicMock(core_data=mock_core_data, + realised_dtype=mock_data.dtype, + lbcode=[1], + lbnpt=x, lbrow=y, bzx=350, bdx=1.5, + bzy=40, bdy=1.5, lbuser=[0] * 7, + lbrsvd=[0] * 4) + field._x_coord_name = lambda: 'longitude' + field._y_coord_name = lambda: 'latitude' + field.coord_system = lambda: None + return field + + # Make a fake reference surface field. + pressure_field = field_with_data(10) + pressure_field.stash = iris.fileformats.pp.STASH(1, 0, 409) + pressure_field.lbuser[3] = 409 + + # Make a fake data field which needs the reference surface. + model_level = 5678 + sigma_lower, sigma, sigma_upper = 0.85, 0.9, 0.95 + delta_lower, delta, delta_upper = 0.05, 0.1, 0.15 + data_field = field_with_data() + data_field.configure_mock(lbvc=9, lblev=model_level, + bhlev=delta, bhrlev=delta_lower, + blev=sigma, brlev=sigma_lower, + brsvd=[sigma_upper, delta_upper]) + + # Convert both fields to cubes. + load = mock.Mock(return_value=iter([data_field, + pressure_field, + pressure_field])) + msg = 'Multiple reference cubes for surface_air_pressure' + with mock.patch('iris.fileformats.pp.load', + new=load) as load, mock.patch('warnings.warn') as warn: + _, _, _ = iris.fileformats.pp.load_cubes('DUMMY') + warn.assert_called_with(msg) + def test_hybrid_height_with_non_standard_coords(self): # Check the save rules are using the AuxFactory to find the # hybrid height coordinates and not relying on their names. @@ -201,8 +303,7 @@ def test_hybrid_height_with_non_standard_coords(self): field.lbvc = 0 field.brsvd = [None, None] field.lbuser = [None] * 7 - iris.fileformats.pp._ensure_save_rules_loaded() - iris.fileformats.pp._save_rules.verify(cube, field) + field = verify(cube, field) self.assertEqual(field.blev, delta) self.assertEqual(field.brlev, delta_lower) @@ -238,8 +339,7 @@ def test_hybrid_pressure_with_non_standard_coords(self): field.lbvc = 0 field.brsvd = [None, None] field.lbuser = [None] * 7 - iris.fileformats.pp._ensure_save_rules_loaded() - iris.fileformats.pp._save_rules.verify(cube, field) + field = verify(cube, field) self.assertEqual(field.bhlev, delta) self.assertEqual(field.bhrlev, delta_lower) @@ -247,6 +347,156 @@ def test_hybrid_pressure_with_non_standard_coords(self): self.assertEqual(field.brlev, sigma_lower) self.assertEqual(field.brsvd, [sigma_upper, delta_upper]) + def test_hybrid_height_round_trip_no_reference(self): + # Use pp.load_cubes() to convert fake PPFields into Cubes. + # NB. Use MagicMock so that SplittableInt header items, such as + # LBCODE, support len(). + def field_with_data(scale=1): + x, y = 40, 30 + mock_data = np.arange(1200).reshape(y, x) * scale + mock_core_data = mock.MagicMock(return_value=mock_data) + field = mock.MagicMock(core_data=mock_core_data, + realised_dtype=mock_data.dtype, + lbcode=[1], + lbnpt=x, lbrow=y, bzx=350, bdx=1.5, + bzy=40, bdy=1.5, lbuser=[0] * 7, + lbrsvd=[0] * 4) + field._x_coord_name = lambda: 'longitude' + field._y_coord_name = lambda: 'latitude' + field.coord_system = lambda: None + return field + + # Make a fake data field which needs the reference surface. + model_level = 5678 + sigma_lower, sigma, sigma_upper = 0.85, 0.9, 0.95 + delta_lower, delta, delta_upper = 0.05, 0.1, 0.15 + data_field = field_with_data() + data_field.configure_mock(lbvc=65, lblev=model_level, + bhlev=sigma, bhrlev=sigma_lower, + blev=delta, brlev=delta_lower, + brsvd=[delta_upper, sigma_upper]) + + # Convert field to a cube. + load = mock.Mock(return_value=iter([data_field])) + with mock.patch('iris.fileformats.pp.load', new=load) as load, \ + mock.patch('warnings.warn') as warn: + data_cube, = iris.fileformats.pp.load_cubes('DUMMY') + + msg = "Unable to create instance of HybridHeightFactory. " \ + "The source data contains no field(s) for 'orography'." + warn.assert_called_once_with(msg) + + # Check the data cube is set up to use hybrid height. + self._test_coord(data_cube, model_level, + standard_name='model_level_number') + self._test_coord(data_cube, delta, [delta_lower, delta_upper], + long_name='level_height') + self._test_coord(data_cube, sigma, [sigma_lower, sigma_upper], + long_name='sigma') + # Check that no aux factory is created (due to missing + # reference surface). + aux_factories = data_cube.aux_factories + self.assertEqual(len(aux_factories), 0) + + # Now use the save rules to convert the Cube back into a PPField. + data_field = iris.fileformats.pp.PPField3() + data_field.lbfc = 0 + data_field.lbvc = 0 + data_field.brsvd = [None, None] + data_field.lbuser = [None] * 7 + data_field = verify(data_cube, data_field) + + # Check the data field has the vertical coordinate as originally + # specified. + self.assertEqual(data_field.lbvc, 65) + self.assertEqual(data_field.lblev, model_level) + self.assertEqual(data_field.bhlev, sigma) + self.assertEqual(data_field.bhrlev, sigma_lower) + self.assertEqual(data_field.blev, delta) + self.assertEqual(data_field.brlev, delta_lower) + self.assertEqual(data_field.brsvd, [delta_upper, sigma_upper]) + + +class TestSaveLBFT(tests.IrisTest): + def create_cube(self, fp_min, fp_mid, fp_max, ref_offset, season=None): + cube = Cube(np.zeros((3, 4))) + cube.add_aux_coord(AuxCoord(standard_name='forecast_period', + units='hours', + points=fp_mid, bounds=[fp_min, fp_max])) + cube.add_aux_coord(AuxCoord(standard_name='time', + units='hours since epoch', + points=ref_offset + fp_mid, + bounds=[ref_offset + fp_min, + ref_offset + fp_max])) + if season: + cube.add_aux_coord(AuxCoord(long_name='clim_season', + points=season)) + cube.add_cell_method(CellMethod('DUMMY', 'clim_season')) + return cube + + def convert_cube_to_field(self, cube): + # Use the save rules to convert the Cube back into a PPField. + field = iris.fileformats.pp.PPField3() + field.lbfc = 0 + field.lbvc = 0 + field.lbtim = 0 + field = verify(cube, field) + return field + + def test_time_mean_from_forecast_period(self): + cube = self.create_cube(24, 36, 48, 72) + field = self.convert_cube_to_field(cube) + self.assertEqual(field.lbft, 48) + + def test_time_mean_from_forecast_reference_time(self): + cube = Cube(np.zeros((3, 4))) + cube.add_aux_coord(AuxCoord(standard_name='forecast_reference_time', + units='hours since epoch', + points=72)) + cube.add_aux_coord(AuxCoord(standard_name='time', + units='hours since epoch', + points=72 + 36, bounds=[72 + 24, 72 + 48])) + field = self.convert_cube_to_field(cube) + self.assertEqual(field.lbft, 48) + + def test_climatological_mean_single_year(self): + cube = Cube(np.zeros((3, 4))) + cube.add_aux_coord(AuxCoord(standard_name='forecast_period', + units='hours', + points=36, bounds=[24, 4 * 24])) + cube.add_aux_coord(AuxCoord(standard_name='time', + units='hours since epoch', + points=240 + 36, bounds=[240 + 24, + 240 + 4 * 24])) + cube.add_aux_coord(AuxCoord(long_name='clim_season', points='DUMMY')) + cube.add_cell_method(CellMethod('DUMMY', 'clim_season')) + field = self.convert_cube_to_field(cube) + self.assertEqual(field.lbft, 4 * 24) + + def test_climatological_mean_multi_year_djf(self): + delta_start = 24 + delta_mid = 36 + delta_end = 369 * 24 + ref_offset = 10 * 24 + cube = self.create_cube(24, 36, 369 * 24, 240, 'djf') + field = self.convert_cube_to_field(cube) + self.assertEqual(field.lbft, 369 * 24) + + def test_climatological_mean_multi_year_mam(self): + cube = self.create_cube(24, 36, 369 * 24, 240, 'mam') + field = self.convert_cube_to_field(cube) + self.assertEqual(field.lbft, 369 * 24) + + def test_climatological_mean_multi_year_jja(self): + cube = self.create_cube(24, 36, 369 * 24, 240, 'jja') + field = self.convert_cube_to_field(cube) + self.assertEqual(field.lbft, 369 * 24) + + def test_climatological_mean_multi_year_son(self): + cube = self.create_cube(24, 36, 369 * 24, 240, 'son') + field = self.convert_cube_to_field(cube) + self.assertEqual(field.lbft, 369 * 24) + class TestCoordinateForms(tests.IrisTest): def _common(self, x_coord): @@ -268,7 +518,7 @@ def _common(self, x_coord): with self.temp_filename('.pp') as pp_filepath: iris.save(test_cube, pp_filepath) pp_loader = iris.fileformats.pp.load(pp_filepath) - pp_field = pp_loader.next() + pp_field = next(pp_loader) return pp_field def test_save_awkward_case_is_regular(self): @@ -302,5 +552,187 @@ def test_save_irregular(self): self.assertEqual(pp_field.lbnpt, nx) +@tests.skip_data +class TestLoadLittleendian(tests.IrisTest): + def test_load_sample(self): + file_path = tests.get_data_path( + ('PP', 'little_endian', 'qrparm.orog.pp')) + # Ensure it just loads. + cube = iris.load_cube(file_path, 'surface_altitude') + self.assertEqual(cube.shape, (110, 160)) + + # Check for sensible floating point numbers. + def check_minmax(array, expect_min, expect_max): + found = np.array([np.min(array), np.max(array)]) + expected = np.array([expect_min, expect_max]) + self.assertArrayAlmostEqual(found, expected, decimal=2) + + lons = cube.coord('grid_longitude').points + lats = cube.coord('grid_latitude').points + data = cube.data + check_minmax(lons, 342.0, 376.98) + check_minmax(lats, -10.48, 13.5) + check_minmax(data, -30.48, 6029.1) + + +@tests.skip_data +class TestAsCubes(tests.IrisTest): + def setUp(self): + dpath = tests.get_data_path(['PP', 'meanMaxMin', + '200806081200__qwpb.T24.pp']) + self.ppfs = iris.fileformats.pp.load(dpath) + + def test_pseudo_level_filter(self): + chosen_ppfs = [] + for ppf in self.ppfs: + if ppf.lbuser[4] == 3: + chosen_ppfs.append(ppf) + cubes_fields = list(load_pairs_from_fields(chosen_ppfs)) + self.assertEqual(len(cubes_fields), 8) + + def test_pseudo_level_filter_none(self): + chosen_ppfs = [] + for ppf in self.ppfs: + if ppf.lbuser[4] == 30: + chosen_ppfs.append(ppf) + cubes = list(load_pairs_from_fields(chosen_ppfs)) + self.assertEqual(len(cubes), 0) + + def test_as_pairs(self): + cube_ppf_pairs = load_pairs_from_fields(self.ppfs) + cubes = [] + for cube, ppf in cube_ppf_pairs: + if ppf.lbuser[4] == 3: + cube.attributes['pseudo level'] = ppf.lbuser[4] + cubes.append(cube) + for cube in cubes: + self.assertEqual(cube.attributes['pseudo level'], 3) + + +class TestSaveLBPROC(tests.IrisTest): + + def create_cube(self, longitude_coord='longitude'): + cube = Cube(np.zeros((2, 3, 4))) + tunit = Unit('days since epoch', calendar='gregorian') + tcoord = DimCoord(np.arange(2), standard_name='time', units=tunit) + xcoord = DimCoord(np.arange(3), standard_name=longitude_coord, + units='degrees') + ycoord = DimCoord(points=np.arange(4)) + cube.add_dim_coord(tcoord, 0) + cube.add_dim_coord(xcoord, 1) + cube.add_dim_coord(ycoord, 2) + return cube + + def convert_cube_to_field(self, cube): + field = iris.fileformats.pp.PPField3() + field.lbvc = 0 + return verify(cube, field) + + def test_time_mean_only(self): + cube = self.create_cube() + cube.add_cell_method(CellMethod(method='mean', coords='time')) + field = self.convert_cube_to_field(cube) + self.assertEqual(int(field.lbproc), 128) + + def test_longitudinal_mean_only(self): + cube = self.create_cube() + cube.add_cell_method(CellMethod(method=u'mean', coords=u'longitude')) + field = self.convert_cube_to_field(cube) + self.assertEqual(int(field.lbproc), 64) + + def test_grid_longitudinal_mean_only(self): + cube = self.create_cube(longitude_coord='grid_longitude') + cube.add_cell_method(CellMethod(method=u'mean', + coords=u'grid_longitude')) + field = self.convert_cube_to_field(cube) + self.assertEqual(int(field.lbproc), 64) + + def test_time_mean_and_zonal_mean(self): + cube = self.create_cube() + cube.add_cell_method(CellMethod(method=u'mean', coords=u'time')) + cube.add_cell_method(CellMethod(method=u'mean', coords=u'longitude')) + field = self.convert_cube_to_field(cube) + self.assertEqual(int(field.lbproc), 192) + + +@tests.skip_data +class TestCallbackLoad(tests.IrisTest): + def setUp(self): + self.pass_name = 'air_potential_temperature' + + def callback_wrapper(self): + # Wrap the `iris.exceptions.IgnoreCubeException`-calling callback. + def callback_ignore_cube_exception(cube, field, filename): + if cube.name() != self.pass_name: + raise IgnoreCubeException + return callback_ignore_cube_exception + + def test_ignore_cube_callback(self): + test_dataset = tests.get_data_path( + ['PP', 'globClim1', 'dec_subset.pp']) + exception_callback = self.callback_wrapper() + result_cubes = iris.load(test_dataset, callback=exception_callback) + n_result_cubes = len(result_cubes) + # We ignore all but one cube (the `air_potential_temperature` cube). + self.assertEqual(n_result_cubes, 1) + self.assertEqual(result_cubes[0].name(), self.pass_name) + + +@tests.skip_data +class TestZonalMeanBounds(tests.IrisTest): + def test_mulitple_longitude(self): + # test that bounds are set for a zonal mean file with many longitude + # values + orig_file = tests.get_data_path(('PP', 'aPPglob1', 'global.pp')) + + f = next(iris.fileformats.pp.load(orig_file)) + f.lbproc = 192 # time and zonal mean + + # Write out pp file + temp_filename = iris.util.create_temp_filename(".pp") + with open(temp_filename, 'wb') as temp_fh: + f.save(temp_fh) + + # Load pp file + cube = iris.load_cube(temp_filename) + + self.assertTrue(cube.coord('longitude').has_bounds()) + + os.remove(temp_filename) + + def test_singular_longitude(self): + # test that bounds are set for a zonal mean file with a single + # longitude value + + pp_file = tests.get_data_path(('PP', 'zonal_mean', 'zonal_mean.pp')) + + # Load pp file + cube = iris.load_cube(pp_file) + + self.assertTrue(cube.coord('longitude').has_bounds()) + + +@tests.skip_data +class TestLoadPartialMask(tests.IrisTest): + def test_data(self): + # Ensure that fields merge correctly where one has a mask and one + # doesn't. + filename = tests.get_data_path(['PP', 'simple_pp', 'partial_mask.pp']) + + expected_data = np.ma.masked_array([[[0, 1], + [11, 12]], + [[99, 100], + [-1, -1]]], + [[[0, 0], + [0, 0]], + [[0, 0], + [1, 1]]], + dtype=np.int32) + cube = iris.load_cube(filename) + + self.assertEqual(expected_data.dtype, cube.data.dtype) + self.assertMaskedArrayEqual(expected_data, cube.data, strict=False) + + if __name__ == "__main__": tests.main() diff --git a/lib/iris/tests/integration/test_pp_constrained_load_cubes.py b/lib/iris/tests/integration/test_pp_constrained_load_cubes.py new file mode 100644 index 0000000000..ac3d02ea51 --- /dev/null +++ b/lib/iris/tests/integration/test_pp_constrained_load_cubes.py @@ -0,0 +1,62 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for :func:`iris.fileformats.rules.load_cubes`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import iris +from iris.fileformats import pp +from iris.fileformats.pp_load_rules import convert +from iris.fileformats.rules import load_cubes + + +class Test(tests.IrisTest): + @tests.skip_data + def test_pp_with_stash_constraint(self): + filenames = [tests.get_data_path(('PP', 'globClim1', 'dec_subset.pp'))] + stcon = iris.AttributeConstraint(STASH='m01s00i004') + pp_constraints = pp._convert_constraints(stcon) + pp_loader = iris.fileformats.rules.Loader(pp.load, {}, convert) + cubes = list(load_cubes(filenames, None, pp_loader, pp_constraints)) + self.assertEqual(len(cubes), 38) + + @tests.skip_data + def test_pp_with_stash_constraints(self): + filenames = [tests.get_data_path(('PP', 'globClim1', 'dec_subset.pp'))] + stcon1 = iris.AttributeConstraint(STASH='m01s00i004') + stcon2 = iris.AttributeConstraint(STASH='m01s00i010') + pp_constraints = pp._convert_constraints([stcon1, stcon2]) + pp_loader = iris.fileformats.rules.Loader(pp.load, {}, convert) + cubes = list(load_cubes(filenames, None, pp_loader, pp_constraints)) + self.assertEqual(len(cubes), 76) + + @tests.skip_data + def test_pp_no_constraint(self): + filenames = [tests.get_data_path(('PP', 'globClim1', 'dec_subset.pp'))] + pp_constraints = pp._convert_constraints(None) + pp_loader = iris.fileformats.rules.Loader(pp.load, {}, convert) + cubes = list(load_cubes(filenames, None, pp_loader, pp_constraints)) + self.assertEqual(len(cubes), 152) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/integration/test_regrid_equivalence.py b/lib/iris/tests/integration/test_regrid_equivalence.py new file mode 100644 index 0000000000..a87c3684cd --- /dev/null +++ b/lib/iris/tests/integration/test_regrid_equivalence.py @@ -0,0 +1,239 @@ +# (C) British Crown Copyright 2016 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Tests to check the validity of replacing +"iris.analysis._interpolate.regrid`('nearest')" with +"iris.cube.Cube.regrid(scheme=iris.analysis.Nearest())". + +""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +import iris +from iris.analysis import Nearest +from iris.cube import Cube +from iris.coords import AuxCoord, DimCoord + + +def grid_cube(xx, yy, data=None): + nx, ny = len(xx), len(yy) + if data is not None: + data = np.array(data).reshape((ny, nx)) + else: + data = np.zeros((ny, nx)) + cube = Cube(data) + y_coord = DimCoord(yy, standard_name='latitude', units='degrees') + x_coord = DimCoord(xx, standard_name='longitude', units='degrees') + cube.add_dim_coord(y_coord, 0) + cube.add_dim_coord(x_coord, 1) + return cube + + +ENABLE_DEBUG_OUTPUT = False + + +def _debug_data(cube, test_id): + if ENABLE_DEBUG_OUTPUT: + print + data = cube.data + print('CUBE: {}'.format(test_id)) + print(' x={!r}'.format(cube.coord('longitude').points)) + print(' y={!r}'.format(cube.coord('latitude').points)) + print('data[{}]:'.format(type(data))) + print(repr(data)) + + +class MixinCheckingCode(object): + def test_basic(self): + src_x = [30., 40., 50.] + dst_x = [32., 42.] + src_y = [-10., 0., 10.] + dst_y = [-8., 2.] + data = [[3., 4., 5.], + [23., 24., 25.], + [43., 44., 45.]] + expected_result = [[3., 4.], + [23., 24.]] + src_cube = grid_cube(src_x, src_y, data) + _debug_data(src_cube, "basic SOURCE") + dst_cube = grid_cube(dst_x, dst_y) + result_cube = self.regrid(src_cube, dst_cube) + _debug_data(result_cube, "basic RESULT") + self.assertArrayAllClose(result_cube.data, expected_result) + + def test_src_extrapolation(self): + src_x = [30., 40., 50.] + dst_x = [0., 29.0, 39.0] + src_y = [-10., 0., 10.] + dst_y = [-50., -9., -1.] + data = [[3., 4., 5.], + [23., 24., 25.], + [43., 44., 45.]] + expected_result = [[3., 3., 4.], + [3., 3., 4.], + [23., 23., 24.]] + src_cube = grid_cube(src_x, src_y, data) + _debug_data(src_cube, "extrapolate SOURCE") + dst_cube = grid_cube(dst_x, dst_y) + result_cube = self.regrid(src_cube, dst_cube) + _debug_data(result_cube, "extrapolate RESULT") + self.assertArrayAllClose(result_cube.data, expected_result) + + def test_exact_matching_points(self): + src_x = [10.0, 20.0, 30.0] + src_y = [10.0, 20.0, 30.0] + dst_x = [14.9, 15.1, 20.0, 24.9, 25.1] + dst_y = [14.9, 15.1, 20.0, 24.9, 25.1] + data = [[3., 4., 5.], + [23., 24., 25.], + [43., 44., 45.]] + expected_result = [[3., 4., 4., 4., 5.], + [23., 24., 24., 24., 25.], + [23., 24., 24., 24., 25.], + [23., 24., 24., 24., 25.], + [43., 44., 44., 44., 45.]] + src_cube = grid_cube(src_x, src_y, data) + _debug_data(src_cube, "matching SOURCE") + dst_cube = grid_cube(dst_x, dst_y) + result_cube = self.regrid(src_cube, dst_cube) + _debug_data(result_cube, "matching RESULt") + self.assertArrayAllClose(result_cube.data, expected_result) + + def test_source_mask(self): + src_x = [40.0, 50.0, 60.0] + src_y = [40.0, 50.0, 60.0] + dst_x = [44.99, 45.01, 48.0, 50.0, 52.0, 54.99, 55.01] + dst_y = [44.99, 45.01, 48.0, 50.0, 52.0, 54.99, 55.01] + data = np.ma.masked_equal([[3., 4., 5.], + [23., 999, 25.], + [43., 44., 45.]], + 999) + expected_result = np.ma.masked_equal( + [[3., 4., 4., 4., 4., 4., 5.], + [23., 999, 999, 999, 999, 999, 25.], + [23., 999, 999, 999, 999, 999, 25.], + [23., 999, 999, 999, 999, 999, 25.], + [23., 999, 999, 999, 999, 999, 25.], + [23., 999, 999, 999, 999, 999, 25.], + [43., 44., 44., 44., 44., 44., 45.]], + 999) + src_cube = grid_cube(src_x, src_y, data) + src_cube.data = np.ma.masked_array(src_cube.data) + src_cube.data[1, 1] = np.ma.masked + _debug_data(src_cube, "masked SOURCE") + dst_cube = grid_cube(dst_x, dst_y) + result_cube = self.regrid(src_cube, dst_cube, + translate_nans_to_mask=True) + _debug_data(result_cube, "masked RESULT") + self.assertMaskedArrayEqual(result_cube.data, expected_result) + + def test_wrapping_non_circular(self): + src_x = [-10., 0., 10.] + dst_x = [-360.0, -170., -1.0, 1.0, 50.0, 170.0, 352.0, 720.0] + src_y = [0., 10.] + dst_y = [0., 10.] + data = [[3., 4., 5.], + [3., 4., 5.]] + src_cube = grid_cube(src_x, src_y, data) + dst_cube = grid_cube(dst_x, dst_y) + expected_result = [[4., 3., 4., 4., 5., 5., 3., 4.], + [4., 3., 4., 4., 5., 5., 3., 4.]] + _debug_data(src_cube, "noncircular SOURCE") + result_cube = self.regrid(src_cube, dst_cube) + _debug_data(result_cube, "noncircular RESULT") + self.assertArrayAllClose(result_cube.data, expected_result) + + def test_wrapping_circular(self): + # When x-coord is "circular", the above distinction does not apply : + # results are the same for both calculations. + src_x = [-10., 0., 10.] + dst_x = [-360.0, -170., -1.0, 1.0, 50.0, 170.0, 352.0, 720.0] + src_y = [0., 10.] + dst_y = [0., 10.] + data = [[3., 4., 5.], + [3., 4., 5.]] + src_cube = grid_cube(src_x, src_y, data) + dst_cube = grid_cube(dst_x, dst_y) + src_cube.coord('longitude').circular = True + expected_result = [[4., 3., 4., 4., 5., 5., 3., 4.], + [4., 3., 4., 4., 5., 5., 3., 4.]] + _debug_data(src_cube, "circular SOURCE") + result_cube = self.regrid(src_cube, dst_cube) + _debug_data(result_cube, "circular RESULT") + self.assertArrayAllClose(result_cube.data, expected_result) + + def test_wrapping_non_angular(self): + src_x = [-10., 0., 10.] + dst_x = [-360.0, -170., -1.0, 1.0, 50.0, 170.0, 352.0, 720.0] + src_y = [0., 10.] + dst_y = [0., 10.] + data = [[3., 4., 5.], + [3., 4., 5.]] + src_cube = grid_cube(src_x, src_y, data) + dst_cube = grid_cube(dst_x, dst_y) + for co_name in ('longitude', 'latitude'): + for cube in (src_cube, dst_cube): + coord = cube.coord(co_name) + coord.coord_system = None + coord.convert_units('1') + # interpolate.regrid --> Wrapping-free results (non-circular). + expected_result = [[3., 3., 4., 4., 5., 5., 5., 5.], + [3., 3., 4., 4., 5., 5., 5., 5.]] + _debug_data(src_cube, "non-angle-lons SOURCE") + result_cube = self.regrid(src_cube, dst_cube) + _debug_data(result_cube, "non-angle-lons RESULT") + self.assertArrayAllClose(result_cube.data, expected_result) + + def test_source_nan(self): + src_x = [40.0, 50.0, 60.0] + src_y = [40.0, 50.0, 60.0] + dst_x = [44.99, 45.01, 48.0, 50.0, 52.0, 54.99, 55.01] + dst_y = [44.99, 45.01, 48.0, 50.0, 52.0, 54.99, 55.01] + nan = np.nan + data = [[3., 4., 5.], + [23., nan, 25.], + [43., 44., 45.]] + expected_result = [[3., 4., 4., 4., 4., 4., 5.], + [23., nan, nan, nan, nan, nan, 25.], + [23., nan, nan, nan, nan, nan, 25.], + [23., nan, nan, nan, nan, nan, 25.], + [23., nan, nan, nan, nan, nan, 25.], + [23., nan, nan, nan, nan, nan, 25.], + [43., 44., 44., 44., 44., 44., 45.]] + src_cube = grid_cube(src_x, src_y, data) + _debug_data(src_cube, "nan SOURCE") + dst_cube = grid_cube(dst_x, dst_y) + result_cube = self.regrid(src_cube, dst_cube) + _debug_data(result_cube, "nan RESULT") + self.assertArrayEqual(result_cube.data, expected_result) + + +class TestCubeRegridNearest(MixinCheckingCode, tests.IrisTest): + scheme = Nearest(extrapolation_mode='extrapolate') + + def regrid(self, src_cube, dst_cube, **kwargs): + return src_cube.regrid(dst_cube, scheme=self.scheme) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/integration/test_regridding.py b/lib/iris/tests/integration/test_regridding.py new file mode 100644 index 0000000000..80878c21b5 --- /dev/null +++ b/lib/iris/tests/integration/test_regridding.py @@ -0,0 +1,224 @@ +# (C) British Crown Copyright 2013 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for regridding.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +import iris +from iris.analysis._regrid import RectilinearRegridder as Regridder +from iris.coord_systems import GeogCS +from iris.coords import DimCoord +from iris.cube import Cube +from iris.tests.stock import global_pp, simple_3d +from iris.analysis import UnstructuredNearest + + +@tests.skip_data +class TestOSGBToLatLon(tests.IrisTest): + def setUp(self): + path = tests.get_data_path( + ('NIMROD', 'uk2km', 'WO0000000003452', + '201007020900_u1096_ng_ey00_visibility0180_screen_2km')) + self.src = iris.load_cube(path)[0] + # Cast up to float64, to work around numpy<=1.8 bug with means of + # arrays of 32bit floats. + self.src.data = self.src.data.astype(np.float64) + self.grid = Cube(np.empty((73, 96))) + cs = GeogCS(6370000) + lat = DimCoord(np.linspace(46, 65, 73), 'latitude', units='degrees', + coord_system=cs) + lon = DimCoord(np.linspace(-14, 8, 96), 'longitude', units='degrees', + coord_system=cs) + self.grid.add_dim_coord(lat, 0) + self.grid.add_dim_coord(lon, 1) + + def _regrid(self, method): + regridder = Regridder(self.src, self.grid, method, 'mask') + result = regridder(self.src) + return result + + def test_linear(self): + res = self._regrid('linear') + self.assertArrayShapeStats(res, (73, 96), -16100.351951, 5603.850769) + + def test_nearest(self): + res = self._regrid('nearest') + self.assertArrayShapeStats(res, (73, 96), -16095.965585, 5612.657155) + + +@tests.skip_data +class TestGlobalSubsample(tests.IrisTest): + def setUp(self): + self.src = global_pp() + _ = self.src.data + # Cast up to float64, to work around numpy<=1.8 bug with means of + # arrays of 32bit floats. + self.src.data = self.src.data.astype(np.float64) + # Subsample and shift the target grid so that we can see a visual + # difference between regridding scheme methods. + grid = self.src[1::2, 1::3] + grid.coord('latitude').points = grid.coord('latitude').points + 1 + grid.coord('longitude').points = grid.coord('longitude').points + 1 + self.grid = grid + + def _regrid(self, method): + regridder = Regridder(self.src, self.grid, method, 'mask') + result = regridder(self.src) + return result + + def test_linear(self): + res = self._regrid('linear') + self.assertArrayShapeStats(res, (36, 32), 280.35907, 15.997223) + + def test_nearest(self): + res = self._regrid('nearest') + self.assertArrayShapeStats(res, (36, 32), 280.33726, 16.064001) + + +@tests.skip_data +class TestUnstructured(tests.IrisTest): + def setUp(self): + path = tests.get_data_path(('NetCDF', 'unstructured_grid', + 'theta_nodal_xios.nc')) + self.src = iris.load_cube(path, 'Potential Temperature') + self.grid = simple_3d()[0, :, :] + + def test_nearest(self): + res = self.src.regrid(self.grid, UnstructuredNearest()) + self.assertArrayShapeStats(res, (1, 6, 3, 4), 315.890808, 11.000724) + + +class TestZonalMean_global(tests.IrisTest): + def setUp(self): + np.random.seed(0) + self.src = iris.cube.Cube(np.random.random_integers(0, 10, (140, 1))) + s_crs = iris.coord_systems.GeogCS(6371229.0) + sy_coord = iris.coords.DimCoord( + np.linspace(-90, 90, 140), standard_name='latitude', + units='degrees', coord_system=s_crs) + sx_coord = iris.coords.DimCoord( + -180, bounds=[-180, 180], standard_name='longitude', + units='degrees', circular=True, coord_system=s_crs) + self.src.add_dim_coord(sy_coord, 0) + self.src.add_dim_coord(sx_coord, 1) + + def test_linear_same_crs_global(self): + # Regrid the zonal mean onto an identical coordinate system target, but + # on a different set of longitudes - which should result in no change. + points = [-150, -90, -30, 30, 90, 150] + bounds = [[-180, -120], [-120, -60], [-60, 0], [0, 60], [60, 120], + [120, 180]] + sx_coord = self.src.coord(axis='x') + sy_coord = self.src.coord(axis='y') + x_coord = sx_coord.copy(points, bounds=bounds) + grid = iris.cube.Cube( + np.zeros([sy_coord.points.size, x_coord.points.size])) + grid.add_dim_coord(sy_coord, 0) + grid.add_dim_coord(x_coord, 1) + + res = self.src.regrid(grid, iris.analysis.Linear()) + + # Ensure data remains unchanged. + # (the same along each column) + self.assertTrue( + np.array([(res.data[:, 0]-res.data[:, i]).max() for i in + range(1, res.shape[1])]).max() < 1e-10) + self.assertArrayAlmostEqual(res.data[:, 0], self.src.data.reshape(-1)) + + +class TestZonalMean_regional(TestZonalMean_global, tests.IrisTest): + def setUp(self): + super(TestZonalMean_regional, self).setUp() + + # Define a target grid and a target result (what we expect the + # regridder to return). + sx_coord = self.src.coord(axis='x') + sy_coord = self.src.coord(axis='y') + grid_crs = iris.coord_systems.RotatedGeogCS( + 37.5, 177.5, ellipsoid=iris.coord_systems.GeogCS(6371229.0)) + grid_x = sx_coord.copy(np.linspace(350, 370, 100)) + grid_x.circular = False + grid_x.coord_system = grid_crs + grid_y = sy_coord.copy(np.linspace(-10, 10, 100)) + grid_y.coord_system = grid_crs + grid = iris.cube.Cube( + np.zeros([grid_y.points.size, grid_x.points.size])) + grid.add_dim_coord(grid_y, 0) + grid.add_dim_coord(grid_x, 1) + + # The target result is derived by regridding a multi-column version of + # the source to the target (i.e. turning a zonal mean regrid into a + # conventional regrid). + self.tar = self.zonal_mean_as_multi_column(self.src).regrid( + grid, iris.analysis.Linear()) + self.grid = grid + + def zonal_mean_as_multi_column(self, src_cube): + # Munge the source (duplicate source latitudes) so that we can + # utilise linear regridding as a conventional problem (that is, to + # duplicate columns so that it is no longer a zonal mean problem). + src_cube2 = src_cube.copy() + src_cube2.coord(axis='x').points = -90 + src_cube2.coord(axis='x').bounds = [-180, 0] + src_cube.coord(axis='x').points = 90 + src_cube.coord(axis='x').bounds = [0, 180] + src_cubes = iris.cube.CubeList([src_cube, src_cube2]) + return src_cubes.concatenate_cube() + + def test_linear_rotated_regional(self): + # Ensure that zonal mean source data is linearly interpolated onto a + # high resolution target. + regridder = iris.analysis.Linear() + res = self.src.regrid(self.grid, regridder) + self.assertArrayAlmostEqual(res.data, self.tar.data) + + def test_linear_rotated_regional_no_extrapolation(self): + # Capture the case where our source remains circular but we don't use + # extrapolation. + regridder = iris.analysis.Linear(extrapolation_mode='nan') + res = self.src.regrid(self.grid, regridder) + self.assertArrayAlmostEqual(res.data, self.tar.data) + + def test_linear_rotated_regional_not_circular(self): + # Capture the case where our source is not circular but we utilise + # extrapolation. + regridder = iris.analysis.Linear() + self.src.coord(axis='x').circular = False + res = self.src.regrid(self.grid, regridder) + self.assertArrayAlmostEqual(res.data, self.tar.data) + + def test_linear_rotated_regional_no_extrapolation_not_circular(self): + # Confirm how zonal mean actually works in so far as, that + # extrapolation and circular source handling is the means by which + # these usecases are supported. + # In the case where the source is neither using extrapolation and is + # not circular, then 'nan' values will result (as we would expect). + regridder = iris.analysis.Linear(extrapolation_mode='nan') + self.src.coord(axis='x').circular = False + res = self.src.regrid(self.grid, regridder) + self.assertTrue(np.isnan(res.data).all()) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/integration/test_subset.py b/lib/iris/tests/integration/test_subset.py new file mode 100644 index 0000000000..30f58569e6 --- /dev/null +++ b/lib/iris/tests/integration/test_subset.py @@ -0,0 +1,56 @@ +# (C) British Crown Copyright 2015 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for subset.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +import iris +from iris.coords import DimCoord +from iris.cube import Cube + + +def _make_test_cube(): + data = np.zeros((4, 4, 1)) + lats, longs = [0, 10, 20, 30], [5, 15, 25, 35] + lat_coord = DimCoord(lats, standard_name='latitude', units='degrees') + lon_coord = DimCoord(longs, standard_name='longitude', units='degrees') + vrt_coord = DimCoord([850], long_name='pressure', units='hPa') + return Cube(data, + long_name='test_cube', units='1', attributes=None, + dim_coords_and_dims=[(lat_coord, 0), (lon_coord, 1)], + aux_coords_and_dims=[(vrt_coord, None)]) + + +class TestSubset(tests.IrisTest): + def setUp(self): + self.cube = _make_test_cube() + + def test_coordinate_subset(self): + coord = self.cube.coord('pressure') + subsetted = self.cube.subset(coord) + self.assertEqual(self.cube, subsetted) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/integration/test_trajectory.py b/lib/iris/tests/integration/test_trajectory.py new file mode 100644 index 0000000000..c4945333ed --- /dev/null +++ b/lib/iris/tests/integration/test_trajectory.py @@ -0,0 +1,249 @@ +# (C) British Crown Copyright 2010 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for :mod:`iris.analysis.trajectory`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import numpy as np + +import iris +import iris.tests.stock as istk +from iris._lazy_data import as_lazy_data + +from iris.analysis.trajectory import (Trajectory, + interpolate as traj_interpolate) + + +@tests.skip_data +class TestColpex(tests.IrisTest): + def setUp(self): + # Load the COLPEX data => TZYX + path = tests.get_data_path(['PP', 'COLPEX', + 'theta_and_orog_subset.pp']) + cube = iris.load_cube(path, 'air_potential_temperature') + cube.coord('grid_latitude').bounds = None + cube.coord('grid_longitude').bounds = None + # TODO: Workaround until regrid can handle factories + cube.remove_aux_factory(cube.aux_factories[0]) + cube.remove_coord('surface_altitude') + self.cube = cube + + def test_trajectory_extraction(self): + # Pull out a single point - no interpolation required + single_point = traj_interpolate(self.cube, + [('grid_latitude', [-0.1188]), + ('grid_longitude', [359.57958984])]) + expected = self.cube[..., 10, 0].data + self.assertArrayAllClose(single_point[..., 0].data, + expected, rtol=2.0e-7) + self.assertCML(single_point, ('trajectory', 'single_point.cml'), + checksum=False) + + def test_trajectory_extraction_calc(self): + # Pull out another point and test against a manually calculated result. + single_point = [['grid_latitude', [-0.1188]], + ['grid_longitude', [359.584090412]]] + scube = self.cube[0, 0, 10:11, 4:6] + x0 = scube.coord('grid_longitude')[0].points + x1 = scube.coord('grid_longitude')[1].points + y0 = scube.data[0, 0] + y1 = scube.data[0, 1] + expected = y0 + ((y1 - y0) * ((359.584090412 - x0)/(x1 - x0))) + trajectory_cube = traj_interpolate(scube, single_point) + self.assertArrayAllClose(trajectory_cube.data, expected, rtol=2.0e-7) + + def _traj_to_sample_points(self, trajectory): + sample_points = [] + src_points = trajectory.sampled_points + for name in six.iterkeys(src_points[0]): + values = [point[name] for point in src_points] + sample_points.append((name, values)) + return sample_points + + def test_trajectory_extraction_axis_aligned(self): + # Extract a simple, axis-aligned trajectory that is similar to an + # indexing operation. + # (It's not exactly the same because the source cube doesn't have + # regular spacing.) + waypoints = [ + {'grid_latitude': -0.1188, 'grid_longitude': 359.57958984}, + {'grid_latitude': -0.1188, 'grid_longitude': 359.66870117} + ] + trajectory = Trajectory(waypoints, sample_count=100) + sample_points = self._traj_to_sample_points(trajectory) + trajectory_cube = traj_interpolate(self.cube, sample_points) + self.assertCML(trajectory_cube, ('trajectory', + 'constant_latitude.cml')) + + def test_trajectory_extraction_zigzag(self): + # Extract a zig-zag trajectory + waypoints = [ + {'grid_latitude': -0.1188, 'grid_longitude': 359.5886}, + {'grid_latitude': -0.0828, 'grid_longitude': 359.6606}, + {'grid_latitude': -0.0468, 'grid_longitude': 359.6246}, + ] + trajectory = Trajectory(waypoints, sample_count=20) + sample_points = self._traj_to_sample_points(trajectory) + trajectory_cube = traj_interpolate( + self.cube[0, 0], sample_points) + expected = np.array([287.95953369, 287.9190979, 287.95550537, + 287.93240356, 287.83850098, 287.87869263, + 287.90942383, 287.9463501, 287.74365234, + 287.68856812, 287.75588989, 287.54611206, + 287.48522949, 287.53356934, 287.60217285, + 287.43795776, 287.59701538, 287.52468872, + 287.45025635, 287.52716064], dtype=np.float32) + + self.assertCML(trajectory_cube, ('trajectory', 'zigzag.cml'), + checksum=False) + self.assertArrayAllClose(trajectory_cube.data, expected, rtol=2.0e-7) + + def test_colpex__nearest(self): + # Check a smallish nearest-neighbour interpolation against a result + # snapshot. + test_cube = self.cube[0][0] + # Test points on a regular grid, a bit larger than the source region. + xmin, xmax = [fn(test_cube.coord(axis='x').points) + for fn in (np.min, np.max)] + ymin, ymax = [fn(test_cube.coord(axis='x').points) + for fn in (np.min, np.max)] + fractions = [-0.23, -0.01, 0.27, 0.624, 0.983, 1.052, 1.43] + x_points = [xmin + frac * (xmax - xmin) for frac in fractions] + y_points = [ymin + frac * (ymax - ymin) for frac in fractions] + x_points, y_points = np.meshgrid(x_points, y_points) + sample_points = [('grid_longitude', x_points.flatten()), + ('grid_latitude', y_points.flatten())] + result = traj_interpolate(test_cube, sample_points, + method='nearest') + expected = [ + 288.07168579, 288.07168579, 287.9367981, 287.82736206, + 287.78564453, 287.8374939, 287.8374939, 288.07168579, + 288.07168579, 287.9367981, 287.82736206, 287.78564453, + 287.8374939, 287.8374939, 288.07168579, 288.07168579, + 287.9367981, 287.82736206, 287.78564453, 287.8374939, + 287.8374939, 288.07168579, 288.07168579, 287.9367981, + 287.82736206, 287.78564453, 287.8374939, 287.8374939, + 288.07168579, 288.07168579, 287.9367981, 287.82736206, + 287.78564453, 287.8374939, 287.8374939, 288.07168579, + 288.07168579, 287.9367981, 287.82736206, 287.78564453, + 287.8374939, 287.8374939, 288.07168579, 288.07168579, + 287.9367981, 287.82736206, 287.78564453, 287.8374939, + 287.8374939] + self.assertArrayAllClose(result.data, expected) + + +@tests.skip_data +class TestTriPolar(tests.IrisTest): + def setUp(self): + # load data + cubes = iris.load(tests.get_data_path(['NetCDF', 'ORCA2', + 'votemper.nc'])) + cube = cubes[0] + # The netCDF file has different data types for the points and + # bounds of 'depth'. This wasn't previously supported, so we + # emulate that old behaviour. + b32 = cube.coord('depth').bounds.astype(np.float32) + cube.coord('depth').bounds = b32 + self.cube = cube + # define a latitude trajectory (put coords in a different order + # to the cube, just to be awkward) + latitudes = list(range(-90, 90, 2)) + longitudes = [-90]*len(latitudes) + self.sample_points = [('longitude', longitudes), + ('latitude', latitudes)] + + def test_tri_polar(self): + # extract + sampled_cube = traj_interpolate(self.cube, self.sample_points) + self.assertCML(sampled_cube, ('trajectory', + 'tri_polar_latitude_slice.cml')) + + def test_tri_polar_method_linear_fails(self): + # Try to request linear interpolation. + # Not allowed, as we have multi-dimensional coords. + self.assertRaises(iris.exceptions.CoordinateMultiDimError, + traj_interpolate, self.cube, + self.sample_points, method="linear") + + def test_tri_polar_method_unknown_fails(self): + # Try to request unknown interpolation. + self.assertRaises(ValueError, traj_interpolate, + self.cube, self.sample_points, method="linekar") + + def test_tri_polar__nearest(self): + # Check a smallish nearest-neighbour interpolation against a result + # snapshot. + test_cube = self.cube + # Use just one 2d layer, just to be faster. + test_cube = test_cube[0][0] + # Fix the fill value of the data to zero, just so that we get the same + # result under numpy < 1.11 as with 1.11. + # NOTE: numpy<1.11 *used* to assign missing data points into an + # unmasked array as =0.0, now =fill-value. + # TODO: arguably, we should support masked data properly in the + # interpolation routine. In the legacy code, that is unfortunately + # just not the case. + test_cube.data.fill_value = 0 + + # Test points on a regular global grid, with unrelated steps + offsets + # and an extended range of longitude values. + x_points = np.arange(-185.23, +360.0, 73.123) + y_points = np.arange(-89.12, +90.0, 42.847) + x_points, y_points = np.meshgrid(x_points, y_points) + sample_points = [('longitude', x_points.flatten()), + ('latitude', y_points.flatten())] + result = traj_interpolate(test_cube, sample_points, + method='nearest') + expected = [ + 0., 0., 0., 0., + 0., 0., 0., 0., + 12.13186264, 10.69991493, 9.86881161, 7.08723927, + 9.04308414, 12.56258678, 10.63761806, 9.19426727, + 28.93525505, 23.85289955, 26.94649506, 0., + 27.88831711, 28.65439224, 23.39414215, 26.78363228, + 13.53453922, 0., 17.41485596, 0., + 0., 13.0413475, 0., 17.10849571, + -1.67040622, -1.64783156, 0., -1.97898054, + -1.67642927, -1.65173221, -1.623945, 0.] + + self.assertArrayAllClose(result.data, expected) + + +class TestLazyData(tests.IrisTest): + def test_hybrid_height(self): + cube = istk.simple_4d_with_hybrid_height() + # Put a lazy array into the cube so we can test deferred loading. + cube.data = as_lazy_data(cube.data) + + traj = (('grid_latitude', [20.5, 21.5, 22.5, 23.5]), + ('grid_longitude', [31, 32, 33, 34])) + xsec = traj_interpolate(cube, traj, method='nearest') + + # Check that creating the trajectory hasn't led to the original + # data being loaded. + self.assertTrue(cube.has_lazy_data()) + self.assertCML([cube, xsec], ('trajectory', 'hybrid_height.cml')) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/integration/um/__init__.py b/lib/iris/tests/integration/um/__init__.py new file mode 100644 index 0000000000..e012485f2c --- /dev/null +++ b/lib/iris/tests/integration/um/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2016 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for :mod:`iris.fileformats.um` fast load functions.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/integration/um/test_fieldsfile.py b/lib/iris/tests/integration/um/test_fieldsfile.py new file mode 100644 index 0000000000..2364411b17 --- /dev/null +++ b/lib/iris/tests/integration/um/test_fieldsfile.py @@ -0,0 +1,56 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test the fast loading of structured Fieldsfiles. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests +from iris.cube import CubeList + +from iris.fileformats.um import load_cubes as load + + +@tests.skip_data +class TestStructuredLoadFF(tests.IrisTest): + def setUp(self): + self.fname = tests.get_data_path(('FF', 'structured', 'small')) + + def _merge_cubes(self, cubes): + # Merge the 2D cubes returned by `iris.fileformats.um.load_cubes`. + return CubeList(cubes).merge_cube() + + def test_simple(self): + list_of_cubes = list(load(self.fname, None)) + cube = self._merge_cubes(list_of_cubes) + self.assertCML(cube) + + def test_simple_callback(self): + def callback(cube, field, filename): + cube.attributes['processing'] = 'fast-ff' + list_of_cubes = list(load(self.fname, callback=callback)) + cube = self._merge_cubes(list_of_cubes) + self.assertCML(cube) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/pp.py b/lib/iris/tests/pp.py index c5551aaae3..02f72e80b9 100644 --- a/lib/iris/tests/pp.py +++ b/lib/iris/tests/pp.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -15,6 +15,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa import contextlib import os.path @@ -56,7 +58,6 @@ def cube_save_test(self, reference_txt_path, reference_cubes=None, reference_pp_ """ # Watch out for a missing reference text file if not os.path.isfile(reference_txt_path): - tests.logger.warning('Creating result file: %s', reference_txt_path) if reference_cubes: temp_pp_path = iris.util.create_temp_filename(".pp") try: @@ -78,8 +79,8 @@ def cube_save_test(self, reference_txt_path, reference_cubes=None, reference_pp_ pp_fields = list(iris.fileformats.pp.load(temp_pp_path)) for pp_field in pp_fields: pp_field.data - - reference = ''.join(open(reference_txt_path, 'r')) + with open(reference_txt_path, 'r') as reference_fh: + reference = ''.join(reference_fh) self._assert_str_same(reference + '\n', str(pp_fields) + '\n', reference_txt_path, type_comparison_name='PP files') finally: diff --git a/lib/iris/tests/results/COLPEX/small_colpex_theta_p_alt.cml b/lib/iris/tests/results/COLPEX/small_colpex_theta_p_alt.cml index 7b5386c107..0139d1d2fb 100644 --- a/lib/iris/tests/results/COLPEX/small_colpex_theta_p_alt.cml +++ b/lib/iris/tests/results/COLPEX/small_colpex_theta_p_alt.cml @@ -1,405 +1,406 @@ - + - + + + 476.751, 445.735], + [534.494, 574.562, 720.976, ..., 507.224, + 470.836, 518.705], + [727.317, 800.517, 595.591, ..., 465.849, + 476.977, 486.773], + ..., + [687.474, 753.275, 707.277, ..., 446.561, + 452.217, 488.646], + [567.94, 686.381, 848.409, ..., 461.055, + 455.619, 468.224], + [698.235, 812.745, 675.237, ..., 517.086, + 475.494, 508.362]]]" shape="(10, 83, 83)" standard_name="altitude" units="Unit('m')" value_type="float32"> - + - + @@ -474,7 +475,7 @@ - + @@ -490,437 +491,439 @@ [0.979362, 0.973288], [0.973288, 0.966478], [0.966478, 0.958939], - [0.958939, 0.95068]]" id="5f88ebd6" long_name="sigma" points="[0.999424, 0.997504, 0.99482, 0.991375, 0.987171, + [0.958939, 0.95068]]" id="a5c170db" long_name="sigma" points="[0.999424, 0.997504, 0.99482, 0.991375, 0.987171, 0.982215, 0.976512, 0.970069, 0.962893, 0.954993]" shape="(10,)" units="Unit('1')" value_type="float32"/> - + 84.2878, 118.704]]" shape="(83, 83)" standard_name="surface_altitude" units="Unit('m')" value_type="float32"> - + + - - + - + - + + + 476.751, 445.735], + [534.494, 574.562, 720.976, ..., 507.224, + 470.836, 518.705], + [727.317, 800.517, 595.591, ..., 465.849, + 476.977, 486.773], + ..., + [687.474, 753.275, 707.277, ..., 446.561, + 452.217, 488.646], + [567.94, 686.381, 848.409, ..., 461.055, + 455.619, 468.224], + [698.235, 812.745, 675.237, ..., 517.086, + 475.494, 508.362]]]" shape="(10, 83, 83)" standard_name="altitude" units="Unit('m')" value_type="float32"> - + - + @@ -995,7 +998,7 @@ - + @@ -1011,51 +1014,53 @@ [0.979362, 0.973288], [0.973288, 0.966478], [0.966478, 0.958939], - [0.958939, 0.95068]]" id="5f88ebd6" long_name="sigma" points="[0.999424, 0.997504, 0.99482, 0.991375, 0.987171, + [0.958939, 0.95068]]" id="a5c170db" long_name="sigma" points="[0.999424, 0.997504, 0.99482, 0.991375, 0.987171, 0.982215, 0.976512, 0.970069, 0.962893, 0.954993]" shape="(10,)" units="Unit('1')" value_type="float32"/> - + 84.2878, 118.704]]" shape="(83, 83)" standard_name="surface_altitude" units="Unit('m')" value_type="float32"> - + + - - + - + - + + - + - + - - + - + diff --git a/lib/iris/tests/results/FF/air_temperature_1.cml b/lib/iris/tests/results/FF/air_temperature_1.cml index 1e1a850230..267aa88d23 100644 --- a/lib/iris/tests/results/FF/air_temperature_1.cml +++ b/lib/iris/tests/results/FF/air_temperature_1.cml @@ -1,26 +1,27 @@ - + - + + - + - + - + - - + - + - + diff --git a/lib/iris/tests/results/FF/air_temperature_2.cml b/lib/iris/tests/results/FF/air_temperature_2.cml index 42703aa8f3..307c58fe72 100644 --- a/lib/iris/tests/results/FF/air_temperature_2.cml +++ b/lib/iris/tests/results/FF/air_temperature_2.cml @@ -1,26 +1,27 @@ - + - + + - + - + - + - - + - + @@ -47,6 +48,6 @@ - + diff --git a/lib/iris/tests/results/FF/ffheader.txt b/lib/iris/tests/results/FF/ffheader.txt index 550262fd9f..247b877d1e 100644 --- a/lib/iris/tests/results/FF/ffheader.txt +++ b/lib/iris/tests/results/FF/ffheader.txt @@ -16,170 +16,163 @@ FF Header: first_validity_time: (2011, 7, 10, 18, 0, 0, 191) last_validity_time: (2011, 7, 10, 21, 0, 0, 191) misc_validity_time: (2012, 4, 30, 18, 12, 13, -32768) - integer_constants: [ nan nan nan nan - nan 4.74303020e-322 3.60667921e-322 3.45845952e-322 - 3.45845952e-322 1.97626258e-323 nan 3.45845952e-322 - 2.47032823e-322 nan nan nan - 9.88131292e-324 nan nan nan - nan nan nan 2.47032823e-322 - 1.17637030e-320 nan nan 1.97626258e-323 - nan nan nan nan - nan nan nan nan - nan nan nan nan - nan nan nan nan - nan nan] - real_constants: [ 3.75000000e+00 2.50000000e+00 -9.00000000e+01 0.00000000e+00 - 9.00000000e+01 0.00000000e+00 -1.07374182e+09 -1.07374182e+09 - -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 - -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 8.00000000e+04 - -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 - -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 - -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 - -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 - -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 - -1.07374182e+09 -1.07374182e+09] - level_dependent_constants: [[ 0.00000000e+00 1.25000000e-04 9.20000000e-01 1.00000000e-01 - 0.00000000e+00 1.00000000e+00 1.00000000e+01 9.98861280e-01] - [ 2.50000000e-04 4.58300000e-04 9.18000000e-01 2.50000000e-01 - 2.00000000e+01 9.97723208e-01 3.66640000e+01 9.95828167e-01] - [ 6.66700000e-04 9.58300000e-04 9.16000000e-01 6.50000000e-01 - 5.33360000e+01 9.93934019e-01 7.66640000e+01 9.91286693e-01] - [ 1.25000000e-03 1.62500000e-03 9.12000000e-01 2.00000000e+00 - 1.00000000e+02 9.88641990e-01 1.30000000e+02 9.85247237e-01] - [ 2.00000000e-03 2.45830000e-03 9.08000000e-01 -1.07374182e+09 - 1.60000000e+02 9.81858323e-01 1.96664000e+02 9.77724545e-01] - [ 2.91670000e-03 3.45830000e-03 9.03000000e-01 -1.07374182e+09 - 2.33336000e+02 9.73598588e-01 2.76664000e+02 9.68735010e-01] - [ 4.00000000e-03 4.62500000e-03 8.98000000e-01 -1.07374182e+09 - 3.20000000e+02 9.63882715e-01 3.70000000e+02 9.58299395e-01] - [ 5.25000000e-03 5.95830000e-03 8.91000000e-01 -1.07374182e+09 - 4.20000000e+02 9.52732293e-01 4.76664000e+02 9.46442811e-01] - [ 6.66670000e-03 7.45830000e-03 8.85000000e-01 -1.07374182e+09 - 5.33336000e+02 9.40173275e-01 5.96664000e+02 9.33192045e-01] - [ 8.25000000e-03 9.12500000e-03 8.77000000e-01 -1.07374182e+09 - 6.60000000e+02 9.26235954e-01 7.30000000e+02 9.18578240e-01] - [ 1.00000000e-02 1.09583000e-02 8.69000000e-01 -1.07374182e+09 - 8.00000000e+02 9.10952313e-01 8.76664000e+02 9.02636868e-01] - [ 1.19167000e-02 1.29583000e-02 8.59000000e-01 -1.07374182e+09 - 9.53336000e+02 8.94358689e-01 1.03666400e+03 8.85405114e-01] - [ 1.40000000e-02 1.51250000e-02 8.50000000e-01 -1.07374182e+09 - 1.12000000e+03 8.76495729e-01 1.21000000e+03 8.66924502e-01] - [ 1.62500000e-02 1.74583000e-02 8.39000000e-01 -1.07374182e+09 - 1.30000000e+03 8.57405821e-01 1.39666400e+03 8.47240859e-01] - [ 1.86667000e-02 1.99583000e-02 8.28000000e-01 -1.07374182e+09 - 1.49333600e+03 8.37135679e-01 1.59666400e+03 8.26401774e-01] - [ 2.12500000e-02 2.26250000e-02 8.15000000e-01 -1.07374182e+09 - 1.70000000e+03 8.15736307e-01 1.81000000e+03 8.04459154e-01] - [ 2.40000000e-02 2.54583000e-02 8.03000000e-01 -1.07374182e+09 - 1.92000000e+03 7.93260495e-01 2.03666400e+03 7.81469172e-01] - [ 2.69167000e-02 2.84583000e-02 8.00000000e-01 -1.07374182e+09 - 2.15333600e+03 7.69765343e-01 2.27666400e+03 7.57489828e-01] - [ 3.00000000e-02 3.16250000e-02 8.00000000e-01 -1.07374182e+09 - 2.40000000e+03 7.45312195e-01 2.53000000e+03 7.32583412e-01] - [ 3.32500000e-02 3.49583000e-02 8.00000000e-01 -1.07374182e+09 - 2.66000000e+03 7.19964260e-01 2.79666400e+03 7.06816437e-01] - [ 3.66667000e-02 3.84583000e-02 8.00000000e-01 -1.07374182e+09 - 2.93333600e+03 6.93789016e-01 3.07666400e+03 6.80257322e-01] - [ 4.02500000e-02 4.21250000e-02 8.00000000e-01 -1.07374182e+09 - 3.22000000e+03 6.66858148e-01 3.37000000e+03 6.52978735e-01] - [ 4.40000000e-02 4.59583000e-02 8.00000000e-01 -1.07374182e+09 - 3.52000000e+03 6.39245282e-01 3.67666400e+03 6.25057529e-01] - [ 4.79167000e-02 4.99583000e-02 8.00000000e-01 -1.07374182e+09 - 3.83333600e+03 6.11028280e-01 3.99666400e+03 5.96572542e-01] - [ 5.20000000e-02 5.41250000e-02 8.00000000e-01 -1.07374182e+09 - 4.16000000e+03 5.82289159e-01 4.33000000e+03 5.67606827e-01] - [ 5.62500000e-02 5.84584000e-02 8.00000000e-01 -1.07374182e+09 - 4.50000000e+03 5.53111972e-01 4.67667200e+03 5.38246895e-01] - [ 6.06667000e-02 6.29583000e-02 8.00000000e-01 -1.07374182e+09 - 4.85333600e+03 5.23584960e-01 5.03666400e+03 5.08584021e-01] - [ 6.52500000e-02 6.76250000e-02 8.00000000e-01 -1.07374182e+09 - 5.22000000e+03 4.93800468e-01 5.41000000e+03 4.78709633e-01] - [ 7.00000000e-02 7.24583000e-02 8.00000000e-01 -1.07374182e+09 - 5.60000000e+03 4.63852981e-01 5.79666400e+03 4.48721902e-01] - [ 7.49167000e-02 7.74583000e-02 8.00000000e-01 -1.07374182e+09 - 5.99333600e+03 4.33841123e-01 6.19666400e+03 4.18720534e-01] - [ 8.00000000e-02 8.26250000e-02 8.00000000e-01 -1.07374182e+09 - 6.40000000e+03 4.03867558e-01 6.61000000e+03 3.88809342e-01] - [ 8.52500000e-02 8.79584000e-02 8.00000000e-01 -1.07374182e+09 - 6.82000000e+03 3.74037208e-01 7.03667200e+03 3.59095602e-01] - [ 9.06668000e-02 9.34586000e-02 8.00000000e-01 -1.07374182e+09 - 7.25334400e+03 3.44458545e-01 7.47668800e+03 3.29689529e-01] - [ 9.62505000e-02 9.91261000e-02 8.00000000e-01 -1.07374182e+09 - 7.70004000e+03 3.15243594e-01 7.93008800e+03 3.00702891e-01] - [ 1.02001700e-01 1.04961500e-01 8.00000000e-01 -1.07374182e+09 - 8.16013600e+03 2.86505500e-01 8.39692000e+03 2.72250934e-01] - [ 1.07921300e-01 1.10966300e-01 8.00000000e-01 -1.07374182e+09 - 8.63370400e+03 2.58360079e-01 8.87730400e+03 2.44448932e-01] - [ 1.14011300e-01 1.17142900e-01 8.00000000e-01 -1.07374182e+09 - 9.12090400e+03 2.30922736e-01 9.37143200e+03 2.17413383e-01] - [ 1.20274500e-01 1.23495000e-01 8.00000000e-01 -1.07374182e+09 - 9.62196000e+03 2.04311190e-01 9.87960000e+03 1.91261711e-01] - [ 1.26715400e-01 1.30028000e-01 8.00000000e-01 -1.07374182e+09 - 1.01372320e+04 1.78643222e-01 1.04022400e+04 1.66112710e-01] - [ 1.33340600e-01 1.36749900e-01 8.00000000e-01 -1.07374182e+09 - 1.06672480e+04 1.54037783e-01 1.09399920e+04 1.42086098e-01] - [ 1.40159200e-01 1.43671500e-01 8.00000000e-01 -1.07374182e+09 - 1.12127360e+04 1.30616984e-01 1.14937200e+04 1.19306033e-01] - [ 1.47183800e-01 1.50807600e-01 8.00000000e-01 -1.07374182e+09 - 1.17747040e+04 1.08507252e-01 1.20646080e+04 9.79024742e-02] - [ 1.54431300e-01 1.58177600e-01 8.00000000e-01 -1.07374182e+09 - 1.23545040e+04 8.78431720e-02 1.26542080e+04 7.80166893e-02] - [ 1.61923800e-01 1.65806700e-01 8.00000000e-01 -1.07374182e+09 - 1.29539040e+04 6.87731341e-02 1.32645360e+04 5.98072162e-02] - [ 1.69689500e-01 1.73726900e-01 8.00000000e-01 -1.07374182e+09 - 1.35751600e+04 5.14674609e-02 1.38981520e+04 4.34594479e-02] - [ 1.77764300e-01 1.81978600e-01 8.00000000e-01 -1.07374182e+09 - 1.42211440e+04 3.61281953e-02 1.45582880e+04 2.91976102e-02] - [ 1.86192900e-01 1.90611800e-01 8.00000000e-01 -1.07374182e+09 - 1.48954320e+04 2.30043897e-02 1.52489440e+04 1.73024257e-02] - [ 1.95030700e-01 1.99687900e-01 8.00000000e-01 -1.07374182e+09 - 1.56024560e+04 1.24111608e-02 1.59750320e+04 8.13357895e-03] - [ 2.04345100e-01 2.09281500e-01 8.00000000e-01 -1.07374182e+09 - 1.63476080e+04 4.75649178e-03 1.67425200e+04 2.16003775e-03] - [ 2.14217800e-01 2.19482200e-01 8.00000000e-01 -1.07374182e+09 - 1.71374240e+04 5.75306329e-04 1.75585760e+04 0.00000000e+00] - [ 2.24746600e-01 2.30397300e-01 8.00000000e-01 -1.07374182e+09 - 1.79797280e+04 0.00000000e+00 1.84317840e+04 0.00000000e+00] - [ 2.36048000e-01 2.42153800e-01 8.00000000e-01 -1.07374182e+09 - 1.88838400e+04 0.00000000e+00 1.93723040e+04 0.00000000e+00] - [ 2.48259700e-01 2.54901400e-01 8.00000000e-01 -1.07374182e+09 - 1.98607760e+04 0.00000000e+00 2.03921120e+04 0.00000000e+00] - [ 2.61543200e-01 2.68815000e-01 8.00000000e-01 -1.07374182e+09 - 2.09234560e+04 0.00000000e+00 2.15052000e+04 0.00000000e+00] - [ 2.76086800e-01 2.84098100e-01 8.00000000e-01 -1.07374182e+09 - 2.20869440e+04 0.00000000e+00 2.27278480e+04 0.00000000e+00] - [ 2.92109400e-01 3.00986200e-01 8.00000000e-01 -1.07374182e+09 - 2.33687520e+04 0.00000000e+00 2.40788960e+04 0.00000000e+00] - [ 3.09863100e-01 3.19750500e-01 8.00000000e-01 -1.07374182e+09 - 2.47890480e+04 0.00000000e+00 2.55800400e+04 0.00000000e+00] - [ 3.29637800e-01 3.40701400e-01 8.00000000e-01 -1.07374182e+09 - 2.63710240e+04 0.00000000e+00 2.72561120e+04 0.00000000e+00] - [ 3.51765100e-01 3.64193600e-01 8.00000000e-01 -1.07374182e+09 - 2.81412080e+04 0.00000000e+00 2.91354880e+04 0.00000000e+00] - [ 3.76622200e-01 3.90629700e-01 8.00000000e-01 -1.07374182e+09 - 3.01297760e+04 0.00000000e+00 3.12503760e+04 0.00000000e+00] - [ 4.04637300e-01 4.20465800e-01 8.00000000e-01 -1.07374182e+09 - 3.23709840e+04 0.00000000e+00 3.36372640e+04 0.00000000e+00] - [ 4.36294300e-01 4.54216100e-01 8.00000000e-01 -1.07374182e+09 - 3.49035440e+04 0.00000000e+00 3.63372880e+04 0.00000000e+00] - [ 4.72137900e-01 4.92458900e-01 8.00000000e-01 -1.07374182e+09 - 3.77710320e+04 0.00000000e+00 3.93967120e+04 0.00000000e+00] - [ 5.12779800e-01 5.35842200e-01 8.00000000e-01 -1.07374182e+09 - 4.10223840e+04 0.00000000e+00 4.28673760e+04 0.00000000e+00] - [ 5.58904500e-01 5.85090200e-01 8.00000000e-01 -1.07374182e+09 - 4.47123600e+04 0.00000000e+00 4.68072160e+04 0.00000000e+00] - [ 6.11275900e-01 6.41009600e-01 8.00000000e-01 -1.07374182e+09 - 4.89020720e+04 0.00000000e+00 5.12807680e+04 0.00000000e+00] - [ 6.70743200e-01 7.04496600e-01 8.00000000e-01 -1.07374182e+09 - 5.36594560e+04 0.00000000e+00 5.63597280e+04 0.00000000e+00] - [ 7.38250000e-01 7.76545100e-01 8.00000000e-01 -1.07374182e+09 - 5.90600000e+04 0.00000000e+00 6.21236080e+04 0.00000000e+00] - [ 8.14840300e-01 8.58253500e-01 8.00000000e-01 -1.07374182e+09 - 6.51872240e+04 0.00000000e+00 6.86602800e+04 0.00000000e+00] - [ 9.01666800e-01 9.50833400e-01 8.00000000e-01 -1.07374182e+09 - 7.21333440e+04 0.00000000e+00 7.60666720e+04 0.00000000e+00] - [ 1.00000000e+00 -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 - 8.00000000e+04 0.00000000e+00 -1.07374182e+09 -1.07374182e+09]] + integer_constants: [-32768 -32768 -32768 -32768 -32768 96 73 70 70 4 + -32768 70 50 -32768 -32768 -32768 2 -32768 -32768 -32768 + -32768 -32768 -32768 50 2381 -32768 -32768 4 -32768 -32768 + -32768 -32768 -32768 -32768 -32768 -32768 -32768 -32768 -32768 -32768 + -32768 -32768 -32768 -32768 -32768 -32768] + real_constants: [ 3.75000000e+00 2.50000000e+00 -9.00000000e+01 0.00000000e+00 + 9.00000000e+01 0.00000000e+00 -1.07374182e+09 -1.07374182e+09 + -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 + -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 8.00000000e+04 + -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 + -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 + -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 + -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 + -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 + -1.07374182e+09 -1.07374182e+09] + level_dependent_constants: [[ 0.00000000e+00 1.25000000e-04 9.20000000e-01 1.00000000e-01 + 0.00000000e+00 1.00000000e+00 1.00000000e+01 9.98861280e-01] + [ 2.50000000e-04 4.58300000e-04 9.18000000e-01 2.50000000e-01 + 2.00000000e+01 9.97723208e-01 3.66640000e+01 9.95828167e-01] + [ 6.66700000e-04 9.58300000e-04 9.16000000e-01 6.50000000e-01 + 5.33360000e+01 9.93934019e-01 7.66640000e+01 9.91286693e-01] + [ 1.25000000e-03 1.62500000e-03 9.12000000e-01 2.00000000e+00 + 1.00000000e+02 9.88641990e-01 1.30000000e+02 9.85247237e-01] + [ 2.00000000e-03 2.45830000e-03 9.08000000e-01 -1.07374182e+09 + 1.60000000e+02 9.81858323e-01 1.96664000e+02 9.77724545e-01] + [ 2.91670000e-03 3.45830000e-03 9.03000000e-01 -1.07374182e+09 + 2.33336000e+02 9.73598588e-01 2.76664000e+02 9.68735010e-01] + [ 4.00000000e-03 4.62500000e-03 8.98000000e-01 -1.07374182e+09 + 3.20000000e+02 9.63882715e-01 3.70000000e+02 9.58299395e-01] + [ 5.25000000e-03 5.95830000e-03 8.91000000e-01 -1.07374182e+09 + 4.20000000e+02 9.52732293e-01 4.76664000e+02 9.46442811e-01] + [ 6.66670000e-03 7.45830000e-03 8.85000000e-01 -1.07374182e+09 + 5.33336000e+02 9.40173275e-01 5.96664000e+02 9.33192045e-01] + [ 8.25000000e-03 9.12500000e-03 8.77000000e-01 -1.07374182e+09 + 6.60000000e+02 9.26235954e-01 7.30000000e+02 9.18578240e-01] + [ 1.00000000e-02 1.09583000e-02 8.69000000e-01 -1.07374182e+09 + 8.00000000e+02 9.10952313e-01 8.76664000e+02 9.02636868e-01] + [ 1.19167000e-02 1.29583000e-02 8.59000000e-01 -1.07374182e+09 + 9.53336000e+02 8.94358689e-01 1.03666400e+03 8.85405114e-01] + [ 1.40000000e-02 1.51250000e-02 8.50000000e-01 -1.07374182e+09 + 1.12000000e+03 8.76495729e-01 1.21000000e+03 8.66924502e-01] + [ 1.62500000e-02 1.74583000e-02 8.39000000e-01 -1.07374182e+09 + 1.30000000e+03 8.57405821e-01 1.39666400e+03 8.47240859e-01] + [ 1.86667000e-02 1.99583000e-02 8.28000000e-01 -1.07374182e+09 + 1.49333600e+03 8.37135679e-01 1.59666400e+03 8.26401774e-01] + [ 2.12500000e-02 2.26250000e-02 8.15000000e-01 -1.07374182e+09 + 1.70000000e+03 8.15736307e-01 1.81000000e+03 8.04459154e-01] + [ 2.40000000e-02 2.54583000e-02 8.03000000e-01 -1.07374182e+09 + 1.92000000e+03 7.93260495e-01 2.03666400e+03 7.81469172e-01] + [ 2.69167000e-02 2.84583000e-02 8.00000000e-01 -1.07374182e+09 + 2.15333600e+03 7.69765343e-01 2.27666400e+03 7.57489828e-01] + [ 3.00000000e-02 3.16250000e-02 8.00000000e-01 -1.07374182e+09 + 2.40000000e+03 7.45312195e-01 2.53000000e+03 7.32583412e-01] + [ 3.32500000e-02 3.49583000e-02 8.00000000e-01 -1.07374182e+09 + 2.66000000e+03 7.19964260e-01 2.79666400e+03 7.06816437e-01] + [ 3.66667000e-02 3.84583000e-02 8.00000000e-01 -1.07374182e+09 + 2.93333600e+03 6.93789016e-01 3.07666400e+03 6.80257322e-01] + [ 4.02500000e-02 4.21250000e-02 8.00000000e-01 -1.07374182e+09 + 3.22000000e+03 6.66858148e-01 3.37000000e+03 6.52978735e-01] + [ 4.40000000e-02 4.59583000e-02 8.00000000e-01 -1.07374182e+09 + 3.52000000e+03 6.39245282e-01 3.67666400e+03 6.25057529e-01] + [ 4.79167000e-02 4.99583000e-02 8.00000000e-01 -1.07374182e+09 + 3.83333600e+03 6.11028280e-01 3.99666400e+03 5.96572542e-01] + [ 5.20000000e-02 5.41250000e-02 8.00000000e-01 -1.07374182e+09 + 4.16000000e+03 5.82289159e-01 4.33000000e+03 5.67606827e-01] + [ 5.62500000e-02 5.84584000e-02 8.00000000e-01 -1.07374182e+09 + 4.50000000e+03 5.53111972e-01 4.67667200e+03 5.38246895e-01] + [ 6.06667000e-02 6.29583000e-02 8.00000000e-01 -1.07374182e+09 + 4.85333600e+03 5.23584960e-01 5.03666400e+03 5.08584021e-01] + [ 6.52500000e-02 6.76250000e-02 8.00000000e-01 -1.07374182e+09 + 5.22000000e+03 4.93800468e-01 5.41000000e+03 4.78709633e-01] + [ 7.00000000e-02 7.24583000e-02 8.00000000e-01 -1.07374182e+09 + 5.60000000e+03 4.63852981e-01 5.79666400e+03 4.48721902e-01] + [ 7.49167000e-02 7.74583000e-02 8.00000000e-01 -1.07374182e+09 + 5.99333600e+03 4.33841123e-01 6.19666400e+03 4.18720534e-01] + [ 8.00000000e-02 8.26250000e-02 8.00000000e-01 -1.07374182e+09 + 6.40000000e+03 4.03867558e-01 6.61000000e+03 3.88809342e-01] + [ 8.52500000e-02 8.79584000e-02 8.00000000e-01 -1.07374182e+09 + 6.82000000e+03 3.74037208e-01 7.03667200e+03 3.59095602e-01] + [ 9.06668000e-02 9.34586000e-02 8.00000000e-01 -1.07374182e+09 + 7.25334400e+03 3.44458545e-01 7.47668800e+03 3.29689529e-01] + [ 9.62505000e-02 9.91261000e-02 8.00000000e-01 -1.07374182e+09 + 7.70004000e+03 3.15243594e-01 7.93008800e+03 3.00702891e-01] + [ 1.02001700e-01 1.04961500e-01 8.00000000e-01 -1.07374182e+09 + 8.16013600e+03 2.86505500e-01 8.39692000e+03 2.72250934e-01] + [ 1.07921300e-01 1.10966300e-01 8.00000000e-01 -1.07374182e+09 + 8.63370400e+03 2.58360079e-01 8.87730400e+03 2.44448932e-01] + [ 1.14011300e-01 1.17142900e-01 8.00000000e-01 -1.07374182e+09 + 9.12090400e+03 2.30922736e-01 9.37143200e+03 2.17413383e-01] + [ 1.20274500e-01 1.23495000e-01 8.00000000e-01 -1.07374182e+09 + 9.62196000e+03 2.04311190e-01 9.87960000e+03 1.91261711e-01] + [ 1.26715400e-01 1.30028000e-01 8.00000000e-01 -1.07374182e+09 + 1.01372320e+04 1.78643222e-01 1.04022400e+04 1.66112710e-01] + [ 1.33340600e-01 1.36749900e-01 8.00000000e-01 -1.07374182e+09 + 1.06672480e+04 1.54037783e-01 1.09399920e+04 1.42086098e-01] + [ 1.40159200e-01 1.43671500e-01 8.00000000e-01 -1.07374182e+09 + 1.12127360e+04 1.30616984e-01 1.14937200e+04 1.19306033e-01] + [ 1.47183800e-01 1.50807600e-01 8.00000000e-01 -1.07374182e+09 + 1.17747040e+04 1.08507252e-01 1.20646080e+04 9.79024742e-02] + [ 1.54431300e-01 1.58177600e-01 8.00000000e-01 -1.07374182e+09 + 1.23545040e+04 8.78431720e-02 1.26542080e+04 7.80166893e-02] + [ 1.61923800e-01 1.65806700e-01 8.00000000e-01 -1.07374182e+09 + 1.29539040e+04 6.87731341e-02 1.32645360e+04 5.98072162e-02] + [ 1.69689500e-01 1.73726900e-01 8.00000000e-01 -1.07374182e+09 + 1.35751600e+04 5.14674609e-02 1.38981520e+04 4.34594479e-02] + [ 1.77764300e-01 1.81978600e-01 8.00000000e-01 -1.07374182e+09 + 1.42211440e+04 3.61281953e-02 1.45582880e+04 2.91976102e-02] + [ 1.86192900e-01 1.90611800e-01 8.00000000e-01 -1.07374182e+09 + 1.48954320e+04 2.30043897e-02 1.52489440e+04 1.73024257e-02] + [ 1.95030700e-01 1.99687900e-01 8.00000000e-01 -1.07374182e+09 + 1.56024560e+04 1.24111608e-02 1.59750320e+04 8.13357895e-03] + [ 2.04345100e-01 2.09281500e-01 8.00000000e-01 -1.07374182e+09 + 1.63476080e+04 4.75649178e-03 1.67425200e+04 2.16003775e-03] + [ 2.14217800e-01 2.19482200e-01 8.00000000e-01 -1.07374182e+09 + 1.71374240e+04 5.75306329e-04 1.75585760e+04 0.00000000e+00] + [ 2.24746600e-01 2.30397300e-01 8.00000000e-01 -1.07374182e+09 + 1.79797280e+04 0.00000000e+00 1.84317840e+04 0.00000000e+00] + [ 2.36048000e-01 2.42153800e-01 8.00000000e-01 -1.07374182e+09 + 1.88838400e+04 0.00000000e+00 1.93723040e+04 0.00000000e+00] + [ 2.48259700e-01 2.54901400e-01 8.00000000e-01 -1.07374182e+09 + 1.98607760e+04 0.00000000e+00 2.03921120e+04 0.00000000e+00] + [ 2.61543200e-01 2.68815000e-01 8.00000000e-01 -1.07374182e+09 + 2.09234560e+04 0.00000000e+00 2.15052000e+04 0.00000000e+00] + [ 2.76086800e-01 2.84098100e-01 8.00000000e-01 -1.07374182e+09 + 2.20869440e+04 0.00000000e+00 2.27278480e+04 0.00000000e+00] + [ 2.92109400e-01 3.00986200e-01 8.00000000e-01 -1.07374182e+09 + 2.33687520e+04 0.00000000e+00 2.40788960e+04 0.00000000e+00] + [ 3.09863100e-01 3.19750500e-01 8.00000000e-01 -1.07374182e+09 + 2.47890480e+04 0.00000000e+00 2.55800400e+04 0.00000000e+00] + [ 3.29637800e-01 3.40701400e-01 8.00000000e-01 -1.07374182e+09 + 2.63710240e+04 0.00000000e+00 2.72561120e+04 0.00000000e+00] + [ 3.51765100e-01 3.64193600e-01 8.00000000e-01 -1.07374182e+09 + 2.81412080e+04 0.00000000e+00 2.91354880e+04 0.00000000e+00] + [ 3.76622200e-01 3.90629700e-01 8.00000000e-01 -1.07374182e+09 + 3.01297760e+04 0.00000000e+00 3.12503760e+04 0.00000000e+00] + [ 4.04637300e-01 4.20465800e-01 8.00000000e-01 -1.07374182e+09 + 3.23709840e+04 0.00000000e+00 3.36372640e+04 0.00000000e+00] + [ 4.36294300e-01 4.54216100e-01 8.00000000e-01 -1.07374182e+09 + 3.49035440e+04 0.00000000e+00 3.63372880e+04 0.00000000e+00] + [ 4.72137900e-01 4.92458900e-01 8.00000000e-01 -1.07374182e+09 + 3.77710320e+04 0.00000000e+00 3.93967120e+04 0.00000000e+00] + [ 5.12779800e-01 5.35842200e-01 8.00000000e-01 -1.07374182e+09 + 4.10223840e+04 0.00000000e+00 4.28673760e+04 0.00000000e+00] + [ 5.58904500e-01 5.85090200e-01 8.00000000e-01 -1.07374182e+09 + 4.47123600e+04 0.00000000e+00 4.68072160e+04 0.00000000e+00] + [ 6.11275900e-01 6.41009600e-01 8.00000000e-01 -1.07374182e+09 + 4.89020720e+04 0.00000000e+00 5.12807680e+04 0.00000000e+00] + [ 6.70743200e-01 7.04496600e-01 8.00000000e-01 -1.07374182e+09 + 5.36594560e+04 0.00000000e+00 5.63597280e+04 0.00000000e+00] + [ 7.38250000e-01 7.76545100e-01 8.00000000e-01 -1.07374182e+09 + 5.90600000e+04 0.00000000e+00 6.21236080e+04 0.00000000e+00] + [ 8.14840300e-01 8.58253500e-01 8.00000000e-01 -1.07374182e+09 + 6.51872240e+04 0.00000000e+00 6.86602800e+04 0.00000000e+00] + [ 9.01666800e-01 9.50833400e-01 8.00000000e-01 -1.07374182e+09 + 7.21333440e+04 0.00000000e+00 7.60666720e+04 0.00000000e+00] + [ 1.00000000e+00 -1.07374182e+09 -1.07374182e+09 -1.07374182e+09 + 8.00000000e+04 0.00000000e+00 -1.07374182e+09 -1.07374182e+09]] row_dependent_constants: None column_dependent_constants: None fields_of_constants: None diff --git a/lib/iris/tests/results/FF/soil_temperature_1.cml b/lib/iris/tests/results/FF/soil_temperature_1.cml index ecf1bd73a9..e555a3f5b9 100644 --- a/lib/iris/tests/results/FF/soil_temperature_1.cml +++ b/lib/iris/tests/results/FF/soil_temperature_1.cml @@ -1,19 +1,20 @@ - + - + + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/FF/surface_altitude_1.cml b/lib/iris/tests/results/FF/surface_altitude_1.cml index e17a9af473..27cfad3d09 100644 --- a/lib/iris/tests/results/FF/surface_altitude_1.cml +++ b/lib/iris/tests/results/FF/surface_altitude_1.cml @@ -1,19 +1,20 @@ - + - + + - + - + - - + - + - + diff --git a/lib/iris/tests/results/PP/extra_char_data.pp.txt b/lib/iris/tests/results/PP/extra_char_data.pp.txt index 24c93dc0f8..9e1bfa95bf 100644 --- a/lib/iris/tests/results/PP/extra_char_data.pp.txt +++ b/lib/iris/tests/results/PP/extra_char_data.pp.txt @@ -35,12 +35,12 @@ lbrsvd: (0, 0, 0, 0) lbsrce: 6061111 lbuser: (1, 897024, 0, 2, 0, 0, 1) - brsvd: (20.000338, 0.99771649, 0.0, 0.0) + brsvd: (20.000338, 0.9977165, 0.0, 0.0) bdatum: 0.0 bacc: -12.0 - blev: 9.99821 + blev: 9.998206 brlev: 0.0 - bhlev: 0.998858 + bhlev: 0.99885815 bhrlev: 1.0 bplat: 90.0 bplon: 0.0 @@ -49,20 +49,21 @@ bdy: 1.25 bzx: -0.9375 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 0.85620117 0.90942383 0.96142578 ..., 0.69165039 0.74731445 - 0.80224609] - [-0.29174805 -0.23974609 -0.18725586 ..., -0.36645508 -0.34594727 + data: [[ 0.8562012 0.9094238 0.9614258 ... 0.6916504 0.74731445 + 0.8022461 ] + [-0.29174805 -0.2397461 -0.18725586 ... -0.36645508 -0.34594727 -0.32763672] - [-0.76000977 -0.68334961 -0.63476562 ..., -0.92431641 -0.89111328 - -0.76757812] - ..., - [-4.64746094 -4.74560547 -4.81713867 ..., -4.32226562 -4.42895508 - -4.53613281] - [-4.45776367 -4.51831055 -4.58007812 ..., -4.28320312 -4.3503418 - -4.40380859] - [-4.22265625 -4.28466797 -4.34204102 ..., -4.01000977 -4.08520508 -4.15625 ]] + [-0.76000977 -0.6833496 -0.6347656 ... -0.9243164 -0.8911133 + -0.7675781 ] + ... + [-4.647461 -4.7456055 -4.8171387 ... -4.3222656 -4.428955 + -4.536133 ] + [-4.4577637 -4.5183105 -4.580078 ... -4.283203 -4.350342 + -4.4038086 ] + [-4.2226562 -4.284668 -4.342041 ... -4.01001 -4.085205 + -4.15625 ]] field_title: AJHQA Time mean !C Atmos u compnt of wind after timestep at 9.998 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 , PP Field lbyr: 2007 @@ -101,12 +102,12 @@ lbrsvd: (0, 0, 0, 0) lbsrce: 6061111 lbuser: (1, 1208320, 0, 3, 0, 0, 1) - brsvd: (20.000338, 0.99771649, 0.0, 0.0) + brsvd: (20.000338, 0.9977165, 0.0, 0.0) bdatum: 0.0 bacc: -12.0 - blev: 9.99821 + blev: 9.998206 brlev: 0.0 - bhlev: 0.998858 + bhlev: 0.99885815 bhrlev: 1.0 bplat: 90.0 bplon: 0.0 @@ -115,21 +116,21 @@ bdy: 1.25 bzx: -1.875 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[-1.23046875 -1.22021484 -1.20776367 ..., -1.25463867 -1.24658203 - -1.23876953] - [-1.00268555 -1.01196289 -1.01953125 ..., -0.96630859 -0.98022461 - -0.99047852] - [-0.76538086 -0.88452148 -1.01416016 ..., -0.72143555 -0.70117188 + data: [[-1.2304688 -1.2202148 -1.2077637 ... -1.2546387 -1.246582 + -1.2387695 ] + [-1.0026855 -1.0119629 -1.0195312 ... -0.9663086 -0.9802246 + -0.9904785 ] + [-0.76538086 -0.8845215 -1.0141602 ... -0.72143555 -0.7011719 -0.71118164] - ..., - [-2.10131836 -1.94702148 -1.78930664 ..., -2.56420898 -2.41772461 + ... + [-2.1013184 -1.9470215 -1.7893066 ... -2.564209 -2.4177246 -2.2590332 ] - [-2.09228516 -1.93603516 -1.77563477 ..., -2.52880859 -2.38647461 + [-2.0922852 -1.9360352 -1.7756348 ... -2.5288086 -2.3864746 -2.2421875 ] - [-2.09594727 -1.95239258 -1.80712891 ..., -2.50927734 -2.37475586 - -2.23681641]] + [-2.0959473 -1.9523926 -1.8071289 ... -2.5092773 -2.3747559 + -2.2368164 ]] field_title: AJHQA Time mean !C Atmos v compnt of wind after timestep at 9.998 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 , PP Field lbyr: 2007 @@ -171,9 +172,9 @@ brsvd: (49.998882, 0.99429625, 0.0, 0.0) bdatum: 0.0 bacc: -10.0 - blev: 20.0003 + blev: 20.000338 brlev: 0.0 - bhlev: 0.997716 + bhlev: 0.9977165 bhrlev: 1.0 bplat: 90.0 bplon: 0.0 @@ -182,21 +183,15 @@ bdy: 1.25 bzx: -1.875 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 282.46191406 282.46191406 282.46191406 ..., 282.46191406 - 282.46191406 282.46191406] - [ 282.35058594 282.37597656 282.40234375 ..., 282.2734375 282.29882812 - 282.32519531] - [ 281.95507812 282.03417969 282.109375 ..., 281.7578125 281.81347656 - 281.87988281] - ..., - [ 245.83203125 245.84277344 245.83398438 ..., 245.8203125 245.82128906 - 245.82324219] - [ 244.4296875 244.42480469 244.42382812 ..., 244.453125 244.45214844 - 244.44042969] - [ 243.26757812 243.26757812 243.26757812 ..., 243.26757812 - 243.26757812 243.26757812]] + data: [[282.4619 282.4619 282.4619 ... 282.4619 282.4619 282.4619 ] + [282.3506 282.37598 282.40234 ... 282.27344 282.29883 282.3252 ] + [281.95508 282.03418 282.10938 ... 281.7578 281.81348 281.87988] + ... + [245.83203 245.84277 245.83398 ... 245.82031 245.82129 245.82324] + [244.42969 244.4248 244.42383 ... 244.45312 244.45215 244.44043] + [243.26758 243.26758 243.26758 ... 243.26758 243.26758 243.26758]] field_title: AJHQA Time mean !C Atmos theta after timestep at 20.00 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 , PP Field lbyr: 2007 @@ -238,9 +233,9 @@ brsvd: (49.998882, 0.99429625, 0.0, 0.0) bdatum: 0.0 bacc: -99.0 - blev: 20.0003 + blev: 20.000338 brlev: 0.0 - bhlev: 0.997716 + bhlev: 0.9977165 bhrlev: 1.0 bplat: 90.0 bplon: 0.0 @@ -249,21 +244,15 @@ bdy: 1.25 bzx: -1.875 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 0.00079939 0.00079939 0.00079939 ..., 0.00079939 0.00079939 - 0.00079939] - [ 0.00087261 0.00087106 0.00086934 ..., 0.00087724 0.00087613 - 0.00087428] - [ 0.00093523 0.00092579 0.00091752 ..., 0.00095657 0.00094989 - 0.00094373] - ..., - [ 0.00037911 0.0003811 0.00038037 ..., 0.00037897 0.00037865 - 0.0003793 ] - [ 0.00033554 0.0003354 0.00033541 ..., 0.0003389 0.00033855 - 0.00033566] - [ 0.00030907 0.00030907 0.00030907 ..., 0.00030907 0.00030907 - 0.00030907]] + data: [[0.00079939 0.00079939 0.00079939 ... 0.00079939 0.00079939 0.00079939] + [0.00087261 0.00087106 0.00086934 ... 0.00087724 0.00087613 0.00087428] + [0.00093523 0.00092579 0.00091752 ... 0.00095657 0.00094989 0.00094373] + ... + [0.00037911 0.0003811 0.00038037 ... 0.00037897 0.00037865 0.0003793 ] + [0.00033554 0.0003354 0.00033541 ... 0.0003389 0.00033855 0.00033566] + [0.00030907 0.00030907 0.00030907 ... 0.00030907 0.00030907 0.00030907]] field_title: AJHQA Time mean !C Atmos specific humidity after timestep at 20.00 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 , PP Field lbyr: 2007 @@ -305,10 +294,10 @@ brsvd: (80.00135, 0.9908815, 0.0, 0.0) bdatum: 0.0 bacc: -12.0 - blev: 49.9989 - brlev: 20.0003 - bhlev: 0.994296 - bhrlev: 0.997716 + blev: 49.998882 + brlev: 20.000338 + bhlev: 0.99429625 + bhrlev: 0.9977165 bplat: 90.0 bplon: 0.0 bgor: 0.0 @@ -316,21 +305,21 @@ bdy: 1.25 bzx: -0.9375 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 1.03320312 1.09912109 1.16381836 ..., 0.82910156 0.89819336 + data: [[ 1.0332031 1.0991211 1.1638184 ... 0.82910156 0.89819336 0.96606445] - [-0.46777344 -0.41455078 -0.35766602 ..., -0.59326172 -0.55175781 + [-0.46777344 -0.41455078 -0.35766602 ... -0.5932617 -0.5517578 -0.51293945] - [-1.07299805 -1.00512695 -0.9387207 ..., -1.3034668 -1.22631836 - -1.15234375] - ..., - [-5.99414062 -6.09936523 -6.18164062 ..., -5.63793945 -5.75756836 - -5.87451172] - [-5.89135742 -5.9609375 -6.02783203 ..., -5.67553711 -5.75585938 - -5.82397461] - [-5.72705078 -5.79101562 -5.84863281 ..., -5.49926758 -5.58129883 - -5.65722656]] + [-1.072998 -1.005127 -0.9387207 ... -1.3034668 -1.2263184 + -1.1523438 ] + ... + [-5.9941406 -6.099365 -6.1816406 ... -5.6379395 -5.7575684 + -5.8745117 ] + [-5.8913574 -5.9609375 -6.027832 ... -5.675537 -5.7558594 + -5.8239746 ] + [-5.727051 -5.7910156 -5.848633 ... -5.4992676 -5.581299 + -5.6572266 ]] field_title: AJHQA Time mean !C Atmos u compnt of wind after timestep at 50.00 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 , PP Field lbyr: 2007 @@ -372,10 +361,10 @@ brsvd: (80.00135, 0.9908815, 0.0, 0.0) bdatum: 0.0 bacc: -12.0 - blev: 49.9989 - brlev: 20.0003 - bhlev: 0.994296 - bhrlev: 0.997716 + blev: 49.998882 + brlev: 20.000338 + bhlev: 0.99429625 + bhrlev: 0.9977165 bplat: 90.0 bplon: 0.0 bgor: 0.0 @@ -383,21 +372,21 @@ bdy: 1.25 bzx: -1.875 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[-1.53613281 -1.52490234 -1.51171875 ..., -1.56103516 -1.55371094 - -1.54541016] - [-1.27148438 -1.2890625 -1.30786133 ..., -1.21948242 -1.2355957 - -1.25268555] - [-1.03491211 -1.18554688 -1.34765625 ..., -0.96240234 -0.94018555 + data: [[-1.5361328 -1.5249023 -1.5117188 ... -1.5610352 -1.5537109 + -1.5454102 ] + [-1.2714844 -1.2890625 -1.3078613 ... -1.2194824 -1.2355957 + -1.2526855 ] + [-1.0349121 -1.1855469 -1.3476562 ... -0.96240234 -0.94018555 -0.9621582 ] - ..., - [-2.33325195 -2.14306641 -1.95629883 ..., -2.88891602 -2.70825195 - -2.52197266] - [-2.24414062 -2.04272461 -1.83837891 ..., -2.8112793 -2.62524414 - -2.43823242] - [-2.1965332 -2.00415039 -1.80908203 ..., -2.75512695 -2.57202148 - -2.38598633]] + ... + [-2.333252 -2.1430664 -1.9562988 ... -2.888916 -2.708252 + -2.5219727 ] + [-2.2441406 -2.0427246 -1.8383789 ... -2.8112793 -2.6252441 + -2.4382324 ] + [-2.1965332 -2.0041504 -1.809082 ... -2.755127 -2.5720215 + -2.3859863 ]] field_title: AJHQA Time mean !C Atmos v compnt of wind after timestep at 50.00 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 , PP Field lbyr: 2007 @@ -439,10 +428,10 @@ brsvd: (130.00023, 0.98520386, 0.0, 0.0) bdatum: 0.0 bacc: -10.0 - blev: 80.0014 - brlev: 49.9989 - bhlev: 0.990882 - bhrlev: 0.994296 + blev: 80.00135 + brlev: 49.998882 + bhlev: 0.9908815 + bhrlev: 0.99429625 bplat: 90.0 bplon: 0.0 bgor: 0.0 @@ -450,21 +439,15 @@ bdy: 1.25 bzx: -1.875 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 282.49609375 282.49609375 282.49609375 ..., 282.49609375 - 282.49609375 282.49609375] - [ 282.38671875 282.41210938 282.4375 ..., 282.31152344 282.3359375 - 282.36132812] - [ 282.09570312 282.16992188 282.2421875 ..., 281.91210938 - 281.96582031 282.02734375] - ..., - [ 246.62597656 246.63085938 246.625 ..., 246.59863281 246.609375 - 246.61816406] - [ 245.46386719 245.46582031 245.47070312 ..., 245.45703125 - 245.46191406 245.46386719] - [ 244.5625 244.5625 244.5625 ..., 244.5625 244.5625 - 244.5625 ]] + data: [[282.4961 282.4961 282.4961 ... 282.4961 282.4961 282.4961 ] + [282.38672 282.4121 282.4375 ... 282.31152 282.33594 282.36133] + [282.0957 282.16992 282.2422 ... 281.9121 281.96582 282.02734] + ... + [246.62598 246.63086 246.625 ... 246.59863 246.60938 246.61816] + [245.46387 245.46582 245.4707 ... 245.45703 245.46191 245.46387] + [244.5625 244.5625 244.5625 ... 244.5625 244.5625 244.5625 ]] field_title: AJHQA Time mean !C Atmos theta after timestep at 80.00 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 , PP Field lbyr: 2007 @@ -506,10 +489,10 @@ brsvd: (130.00023, 0.98520386, 0.0, 0.0) bdatum: 0.0 bacc: -99.0 - blev: 80.0014 - brlev: 49.9989 - bhlev: 0.990882 - bhrlev: 0.994296 + blev: 80.00135 + brlev: 49.998882 + bhlev: 0.9908815 + bhrlev: 0.99429625 bplat: 90.0 bplon: 0.0 bgor: 0.0 @@ -517,21 +500,15 @@ bdy: 1.25 bzx: -1.875 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 0.00077913 0.00077913 0.00077913 ..., 0.00077913 0.00077913 - 0.00077913] - [ 0.00085118 0.0008495 0.00084755 ..., 0.00085498 0.00085392 - 0.00085248] - [ 0.00091165 0.00090317 0.00089486 ..., 0.00092995 0.00092435 - 0.00091926] - ..., - [ 0.00038609 0.00038648 0.00038594 ..., 0.00038624 0.00038616 - 0.00038646] - [ 0.00034904 0.00034909 0.0003492 ..., 0.0003502 0.00035007 - 0.00034903] - [ 0.00032891 0.00032891 0.00032891 ..., 0.00032891 0.00032891 - 0.00032891]] + data: [[0.00077913 0.00077913 0.00077913 ... 0.00077913 0.00077913 0.00077913] + [0.00085118 0.0008495 0.00084755 ... 0.00085498 0.00085392 0.00085248] + [0.00091165 0.00090317 0.00089486 ... 0.00092995 0.00092435 0.00091926] + ... + [0.00038609 0.00038648 0.00038594 ... 0.00038624 0.00038616 0.00038646] + [0.00034904 0.00034909 0.0003492 ... 0.0003502 0.00035007 0.00034903] + [0.00032891 0.00032891 0.00032891 ... 0.00032891 0.00032891 0.00032891]] field_title: AJHQA Time mean !C Atmos specific humidity after timestep at 80.00 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 , PP Field lbyr: 2007 @@ -573,10 +550,10 @@ brsvd: (179.99911, 0.97954255, 0.0, 0.0) bdatum: 0.0 bacc: -12.0 - blev: 130.0 - brlev: 80.0014 - bhlev: 0.985204 - bhrlev: 0.990882 + blev: 130.00023 + brlev: 80.00135 + bhlev: 0.98520386 + bhrlev: 0.9908815 bplat: 90.0 bplon: 0.0 bgor: 0.0 @@ -584,21 +561,21 @@ bdy: 1.25 bzx: -0.9375 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 1.05249023 1.12524414 1.19677734 ..., 0.82739258 0.90356445 - 0.97851562] - [-0.66943359 -0.61328125 -0.55297852 ..., -0.81958008 -0.76855469 + data: [[ 1.0524902 1.1252441 1.1967773 ... 0.8273926 0.90356445 + 0.9785156 ] + [-0.6694336 -0.61328125 -0.5529785 ... -0.8195801 -0.7685547 -0.72021484] - [-1.32250977 -1.23583984 -1.14599609 ..., -1.57714844 -1.49536133 - -1.41308594] - ..., - [-6.96875 -7.02783203 -7.07763672 ..., -6.74145508 -6.82568359 - -6.90087891] - [-7.01049805 -7.0480957 -7.07763672 ..., -6.84472656 -6.90673828 - -6.96313477] - [-6.97167969 -7.01025391 -7.04125977 ..., -6.81201172 -6.87255859 - -6.92578125]] + [-1.3225098 -1.2358398 -1.1459961 ... -1.5771484 -1.4953613 + -1.4130859 ] + ... + [-6.96875 -7.027832 -7.0776367 ... -6.741455 -6.8256836 + -6.900879 ] + [-7.010498 -7.0480957 -7.0776367 ... -6.8447266 -6.9067383 + -6.963135 ] + [-6.9716797 -7.010254 -7.04126 ... -6.8120117 -6.8725586 + -6.9257812 ]] field_title: AJHQA Time mean !C Atmos u compnt of wind after timestep at 130.0 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 , PP Field lbyr: 2007 @@ -640,10 +617,10 @@ brsvd: (179.99911, 0.97954255, 0.0, 0.0) bdatum: 0.0 bacc: -12.0 - blev: 130.0 - brlev: 80.0014 - bhlev: 0.985204 - bhrlev: 0.990882 + blev: 130.00023 + brlev: 80.00135 + bhlev: 0.98520386 + bhrlev: 0.9908815 bplat: 90.0 bplon: 0.0 bgor: 0.0 @@ -651,20 +628,14 @@ bdy: 1.25 bzx: -1.875 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[-1.74145508 -1.73217773 -1.72119141 ..., -1.7590332 -1.75463867 - -1.74853516] - [-1.48266602 -1.5065918 -1.53271484 ..., -1.41625977 -1.43725586 - -1.45898438] - [-1.36010742 -1.52270508 -1.69897461 ..., -1.27148438 -1.25146484 - -1.27539062] - ..., - [-1.72167969 -1.46435547 -1.2097168 ..., -2.43481445 -2.19848633 - -1.96484375] - [-1.52954102 -1.29516602 -1.06396484 ..., -2.24023438 -2.00488281 - -1.76708984] - [-1.47485352 -1.25024414 -1.02319336 ..., -2.13720703 -1.91772461 - -1.69702148]] + data: [[-1.7414551 -1.7321777 -1.7211914 ... -1.7590332 -1.7546387 -1.7485352] + [-1.482666 -1.5065918 -1.5327148 ... -1.4162598 -1.4372559 -1.4589844] + [-1.3601074 -1.5227051 -1.6989746 ... -1.2714844 -1.2514648 -1.2753906] + ... + [-1.7216797 -1.4643555 -1.2097168 ... -2.4348145 -2.1984863 -1.9648438] + [-1.529541 -1.295166 -1.0639648 ... -2.2402344 -2.0048828 -1.7670898] + [-1.4748535 -1.2502441 -1.0231934 ... -2.137207 -1.9177246 -1.6970215]] field_title: AJHQA Time mean !C Atmos v compnt of wind after timestep at 130.0 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 ] \ No newline at end of file diff --git a/lib/iris/tests/results/PP/extra_char_data.w_data_loaded.pp.txt b/lib/iris/tests/results/PP/extra_char_data.w_data_loaded.pp.txt index 24c93dc0f8..9e1bfa95bf 100644 --- a/lib/iris/tests/results/PP/extra_char_data.w_data_loaded.pp.txt +++ b/lib/iris/tests/results/PP/extra_char_data.w_data_loaded.pp.txt @@ -35,12 +35,12 @@ lbrsvd: (0, 0, 0, 0) lbsrce: 6061111 lbuser: (1, 897024, 0, 2, 0, 0, 1) - brsvd: (20.000338, 0.99771649, 0.0, 0.0) + brsvd: (20.000338, 0.9977165, 0.0, 0.0) bdatum: 0.0 bacc: -12.0 - blev: 9.99821 + blev: 9.998206 brlev: 0.0 - bhlev: 0.998858 + bhlev: 0.99885815 bhrlev: 1.0 bplat: 90.0 bplon: 0.0 @@ -49,20 +49,21 @@ bdy: 1.25 bzx: -0.9375 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 0.85620117 0.90942383 0.96142578 ..., 0.69165039 0.74731445 - 0.80224609] - [-0.29174805 -0.23974609 -0.18725586 ..., -0.36645508 -0.34594727 + data: [[ 0.8562012 0.9094238 0.9614258 ... 0.6916504 0.74731445 + 0.8022461 ] + [-0.29174805 -0.2397461 -0.18725586 ... -0.36645508 -0.34594727 -0.32763672] - [-0.76000977 -0.68334961 -0.63476562 ..., -0.92431641 -0.89111328 - -0.76757812] - ..., - [-4.64746094 -4.74560547 -4.81713867 ..., -4.32226562 -4.42895508 - -4.53613281] - [-4.45776367 -4.51831055 -4.58007812 ..., -4.28320312 -4.3503418 - -4.40380859] - [-4.22265625 -4.28466797 -4.34204102 ..., -4.01000977 -4.08520508 -4.15625 ]] + [-0.76000977 -0.6833496 -0.6347656 ... -0.9243164 -0.8911133 + -0.7675781 ] + ... + [-4.647461 -4.7456055 -4.8171387 ... -4.3222656 -4.428955 + -4.536133 ] + [-4.4577637 -4.5183105 -4.580078 ... -4.283203 -4.350342 + -4.4038086 ] + [-4.2226562 -4.284668 -4.342041 ... -4.01001 -4.085205 + -4.15625 ]] field_title: AJHQA Time mean !C Atmos u compnt of wind after timestep at 9.998 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 , PP Field lbyr: 2007 @@ -101,12 +102,12 @@ lbrsvd: (0, 0, 0, 0) lbsrce: 6061111 lbuser: (1, 1208320, 0, 3, 0, 0, 1) - brsvd: (20.000338, 0.99771649, 0.0, 0.0) + brsvd: (20.000338, 0.9977165, 0.0, 0.0) bdatum: 0.0 bacc: -12.0 - blev: 9.99821 + blev: 9.998206 brlev: 0.0 - bhlev: 0.998858 + bhlev: 0.99885815 bhrlev: 1.0 bplat: 90.0 bplon: 0.0 @@ -115,21 +116,21 @@ bdy: 1.25 bzx: -1.875 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[-1.23046875 -1.22021484 -1.20776367 ..., -1.25463867 -1.24658203 - -1.23876953] - [-1.00268555 -1.01196289 -1.01953125 ..., -0.96630859 -0.98022461 - -0.99047852] - [-0.76538086 -0.88452148 -1.01416016 ..., -0.72143555 -0.70117188 + data: [[-1.2304688 -1.2202148 -1.2077637 ... -1.2546387 -1.246582 + -1.2387695 ] + [-1.0026855 -1.0119629 -1.0195312 ... -0.9663086 -0.9802246 + -0.9904785 ] + [-0.76538086 -0.8845215 -1.0141602 ... -0.72143555 -0.7011719 -0.71118164] - ..., - [-2.10131836 -1.94702148 -1.78930664 ..., -2.56420898 -2.41772461 + ... + [-2.1013184 -1.9470215 -1.7893066 ... -2.564209 -2.4177246 -2.2590332 ] - [-2.09228516 -1.93603516 -1.77563477 ..., -2.52880859 -2.38647461 + [-2.0922852 -1.9360352 -1.7756348 ... -2.5288086 -2.3864746 -2.2421875 ] - [-2.09594727 -1.95239258 -1.80712891 ..., -2.50927734 -2.37475586 - -2.23681641]] + [-2.0959473 -1.9523926 -1.8071289 ... -2.5092773 -2.3747559 + -2.2368164 ]] field_title: AJHQA Time mean !C Atmos v compnt of wind after timestep at 9.998 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 , PP Field lbyr: 2007 @@ -171,9 +172,9 @@ brsvd: (49.998882, 0.99429625, 0.0, 0.0) bdatum: 0.0 bacc: -10.0 - blev: 20.0003 + blev: 20.000338 brlev: 0.0 - bhlev: 0.997716 + bhlev: 0.9977165 bhrlev: 1.0 bplat: 90.0 bplon: 0.0 @@ -182,21 +183,15 @@ bdy: 1.25 bzx: -1.875 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 282.46191406 282.46191406 282.46191406 ..., 282.46191406 - 282.46191406 282.46191406] - [ 282.35058594 282.37597656 282.40234375 ..., 282.2734375 282.29882812 - 282.32519531] - [ 281.95507812 282.03417969 282.109375 ..., 281.7578125 281.81347656 - 281.87988281] - ..., - [ 245.83203125 245.84277344 245.83398438 ..., 245.8203125 245.82128906 - 245.82324219] - [ 244.4296875 244.42480469 244.42382812 ..., 244.453125 244.45214844 - 244.44042969] - [ 243.26757812 243.26757812 243.26757812 ..., 243.26757812 - 243.26757812 243.26757812]] + data: [[282.4619 282.4619 282.4619 ... 282.4619 282.4619 282.4619 ] + [282.3506 282.37598 282.40234 ... 282.27344 282.29883 282.3252 ] + [281.95508 282.03418 282.10938 ... 281.7578 281.81348 281.87988] + ... + [245.83203 245.84277 245.83398 ... 245.82031 245.82129 245.82324] + [244.42969 244.4248 244.42383 ... 244.45312 244.45215 244.44043] + [243.26758 243.26758 243.26758 ... 243.26758 243.26758 243.26758]] field_title: AJHQA Time mean !C Atmos theta after timestep at 20.00 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 , PP Field lbyr: 2007 @@ -238,9 +233,9 @@ brsvd: (49.998882, 0.99429625, 0.0, 0.0) bdatum: 0.0 bacc: -99.0 - blev: 20.0003 + blev: 20.000338 brlev: 0.0 - bhlev: 0.997716 + bhlev: 0.9977165 bhrlev: 1.0 bplat: 90.0 bplon: 0.0 @@ -249,21 +244,15 @@ bdy: 1.25 bzx: -1.875 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 0.00079939 0.00079939 0.00079939 ..., 0.00079939 0.00079939 - 0.00079939] - [ 0.00087261 0.00087106 0.00086934 ..., 0.00087724 0.00087613 - 0.00087428] - [ 0.00093523 0.00092579 0.00091752 ..., 0.00095657 0.00094989 - 0.00094373] - ..., - [ 0.00037911 0.0003811 0.00038037 ..., 0.00037897 0.00037865 - 0.0003793 ] - [ 0.00033554 0.0003354 0.00033541 ..., 0.0003389 0.00033855 - 0.00033566] - [ 0.00030907 0.00030907 0.00030907 ..., 0.00030907 0.00030907 - 0.00030907]] + data: [[0.00079939 0.00079939 0.00079939 ... 0.00079939 0.00079939 0.00079939] + [0.00087261 0.00087106 0.00086934 ... 0.00087724 0.00087613 0.00087428] + [0.00093523 0.00092579 0.00091752 ... 0.00095657 0.00094989 0.00094373] + ... + [0.00037911 0.0003811 0.00038037 ... 0.00037897 0.00037865 0.0003793 ] + [0.00033554 0.0003354 0.00033541 ... 0.0003389 0.00033855 0.00033566] + [0.00030907 0.00030907 0.00030907 ... 0.00030907 0.00030907 0.00030907]] field_title: AJHQA Time mean !C Atmos specific humidity after timestep at 20.00 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 , PP Field lbyr: 2007 @@ -305,10 +294,10 @@ brsvd: (80.00135, 0.9908815, 0.0, 0.0) bdatum: 0.0 bacc: -12.0 - blev: 49.9989 - brlev: 20.0003 - bhlev: 0.994296 - bhrlev: 0.997716 + blev: 49.998882 + brlev: 20.000338 + bhlev: 0.99429625 + bhrlev: 0.9977165 bplat: 90.0 bplon: 0.0 bgor: 0.0 @@ -316,21 +305,21 @@ bdy: 1.25 bzx: -0.9375 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 1.03320312 1.09912109 1.16381836 ..., 0.82910156 0.89819336 + data: [[ 1.0332031 1.0991211 1.1638184 ... 0.82910156 0.89819336 0.96606445] - [-0.46777344 -0.41455078 -0.35766602 ..., -0.59326172 -0.55175781 + [-0.46777344 -0.41455078 -0.35766602 ... -0.5932617 -0.5517578 -0.51293945] - [-1.07299805 -1.00512695 -0.9387207 ..., -1.3034668 -1.22631836 - -1.15234375] - ..., - [-5.99414062 -6.09936523 -6.18164062 ..., -5.63793945 -5.75756836 - -5.87451172] - [-5.89135742 -5.9609375 -6.02783203 ..., -5.67553711 -5.75585938 - -5.82397461] - [-5.72705078 -5.79101562 -5.84863281 ..., -5.49926758 -5.58129883 - -5.65722656]] + [-1.072998 -1.005127 -0.9387207 ... -1.3034668 -1.2263184 + -1.1523438 ] + ... + [-5.9941406 -6.099365 -6.1816406 ... -5.6379395 -5.7575684 + -5.8745117 ] + [-5.8913574 -5.9609375 -6.027832 ... -5.675537 -5.7558594 + -5.8239746 ] + [-5.727051 -5.7910156 -5.848633 ... -5.4992676 -5.581299 + -5.6572266 ]] field_title: AJHQA Time mean !C Atmos u compnt of wind after timestep at 50.00 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 , PP Field lbyr: 2007 @@ -372,10 +361,10 @@ brsvd: (80.00135, 0.9908815, 0.0, 0.0) bdatum: 0.0 bacc: -12.0 - blev: 49.9989 - brlev: 20.0003 - bhlev: 0.994296 - bhrlev: 0.997716 + blev: 49.998882 + brlev: 20.000338 + bhlev: 0.99429625 + bhrlev: 0.9977165 bplat: 90.0 bplon: 0.0 bgor: 0.0 @@ -383,21 +372,21 @@ bdy: 1.25 bzx: -1.875 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[-1.53613281 -1.52490234 -1.51171875 ..., -1.56103516 -1.55371094 - -1.54541016] - [-1.27148438 -1.2890625 -1.30786133 ..., -1.21948242 -1.2355957 - -1.25268555] - [-1.03491211 -1.18554688 -1.34765625 ..., -0.96240234 -0.94018555 + data: [[-1.5361328 -1.5249023 -1.5117188 ... -1.5610352 -1.5537109 + -1.5454102 ] + [-1.2714844 -1.2890625 -1.3078613 ... -1.2194824 -1.2355957 + -1.2526855 ] + [-1.0349121 -1.1855469 -1.3476562 ... -0.96240234 -0.94018555 -0.9621582 ] - ..., - [-2.33325195 -2.14306641 -1.95629883 ..., -2.88891602 -2.70825195 - -2.52197266] - [-2.24414062 -2.04272461 -1.83837891 ..., -2.8112793 -2.62524414 - -2.43823242] - [-2.1965332 -2.00415039 -1.80908203 ..., -2.75512695 -2.57202148 - -2.38598633]] + ... + [-2.333252 -2.1430664 -1.9562988 ... -2.888916 -2.708252 + -2.5219727 ] + [-2.2441406 -2.0427246 -1.8383789 ... -2.8112793 -2.6252441 + -2.4382324 ] + [-2.1965332 -2.0041504 -1.809082 ... -2.755127 -2.5720215 + -2.3859863 ]] field_title: AJHQA Time mean !C Atmos v compnt of wind after timestep at 50.00 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 , PP Field lbyr: 2007 @@ -439,10 +428,10 @@ brsvd: (130.00023, 0.98520386, 0.0, 0.0) bdatum: 0.0 bacc: -10.0 - blev: 80.0014 - brlev: 49.9989 - bhlev: 0.990882 - bhrlev: 0.994296 + blev: 80.00135 + brlev: 49.998882 + bhlev: 0.9908815 + bhrlev: 0.99429625 bplat: 90.0 bplon: 0.0 bgor: 0.0 @@ -450,21 +439,15 @@ bdy: 1.25 bzx: -1.875 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 282.49609375 282.49609375 282.49609375 ..., 282.49609375 - 282.49609375 282.49609375] - [ 282.38671875 282.41210938 282.4375 ..., 282.31152344 282.3359375 - 282.36132812] - [ 282.09570312 282.16992188 282.2421875 ..., 281.91210938 - 281.96582031 282.02734375] - ..., - [ 246.62597656 246.63085938 246.625 ..., 246.59863281 246.609375 - 246.61816406] - [ 245.46386719 245.46582031 245.47070312 ..., 245.45703125 - 245.46191406 245.46386719] - [ 244.5625 244.5625 244.5625 ..., 244.5625 244.5625 - 244.5625 ]] + data: [[282.4961 282.4961 282.4961 ... 282.4961 282.4961 282.4961 ] + [282.38672 282.4121 282.4375 ... 282.31152 282.33594 282.36133] + [282.0957 282.16992 282.2422 ... 281.9121 281.96582 282.02734] + ... + [246.62598 246.63086 246.625 ... 246.59863 246.60938 246.61816] + [245.46387 245.46582 245.4707 ... 245.45703 245.46191 245.46387] + [244.5625 244.5625 244.5625 ... 244.5625 244.5625 244.5625 ]] field_title: AJHQA Time mean !C Atmos theta after timestep at 80.00 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 , PP Field lbyr: 2007 @@ -506,10 +489,10 @@ brsvd: (130.00023, 0.98520386, 0.0, 0.0) bdatum: 0.0 bacc: -99.0 - blev: 80.0014 - brlev: 49.9989 - bhlev: 0.990882 - bhrlev: 0.994296 + blev: 80.00135 + brlev: 49.998882 + bhlev: 0.9908815 + bhrlev: 0.99429625 bplat: 90.0 bplon: 0.0 bgor: 0.0 @@ -517,21 +500,15 @@ bdy: 1.25 bzx: -1.875 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 0.00077913 0.00077913 0.00077913 ..., 0.00077913 0.00077913 - 0.00077913] - [ 0.00085118 0.0008495 0.00084755 ..., 0.00085498 0.00085392 - 0.00085248] - [ 0.00091165 0.00090317 0.00089486 ..., 0.00092995 0.00092435 - 0.00091926] - ..., - [ 0.00038609 0.00038648 0.00038594 ..., 0.00038624 0.00038616 - 0.00038646] - [ 0.00034904 0.00034909 0.0003492 ..., 0.0003502 0.00035007 - 0.00034903] - [ 0.00032891 0.00032891 0.00032891 ..., 0.00032891 0.00032891 - 0.00032891]] + data: [[0.00077913 0.00077913 0.00077913 ... 0.00077913 0.00077913 0.00077913] + [0.00085118 0.0008495 0.00084755 ... 0.00085498 0.00085392 0.00085248] + [0.00091165 0.00090317 0.00089486 ... 0.00092995 0.00092435 0.00091926] + ... + [0.00038609 0.00038648 0.00038594 ... 0.00038624 0.00038616 0.00038646] + [0.00034904 0.00034909 0.0003492 ... 0.0003502 0.00035007 0.00034903] + [0.00032891 0.00032891 0.00032891 ... 0.00032891 0.00032891 0.00032891]] field_title: AJHQA Time mean !C Atmos specific humidity after timestep at 80.00 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 , PP Field lbyr: 2007 @@ -573,10 +550,10 @@ brsvd: (179.99911, 0.97954255, 0.0, 0.0) bdatum: 0.0 bacc: -12.0 - blev: 130.0 - brlev: 80.0014 - bhlev: 0.985204 - bhrlev: 0.990882 + blev: 130.00023 + brlev: 80.00135 + bhlev: 0.98520386 + bhrlev: 0.9908815 bplat: 90.0 bplon: 0.0 bgor: 0.0 @@ -584,21 +561,21 @@ bdy: 1.25 bzx: -0.9375 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 1.05249023 1.12524414 1.19677734 ..., 0.82739258 0.90356445 - 0.97851562] - [-0.66943359 -0.61328125 -0.55297852 ..., -0.81958008 -0.76855469 + data: [[ 1.0524902 1.1252441 1.1967773 ... 0.8273926 0.90356445 + 0.9785156 ] + [-0.6694336 -0.61328125 -0.5529785 ... -0.8195801 -0.7685547 -0.72021484] - [-1.32250977 -1.23583984 -1.14599609 ..., -1.57714844 -1.49536133 - -1.41308594] - ..., - [-6.96875 -7.02783203 -7.07763672 ..., -6.74145508 -6.82568359 - -6.90087891] - [-7.01049805 -7.0480957 -7.07763672 ..., -6.84472656 -6.90673828 - -6.96313477] - [-6.97167969 -7.01025391 -7.04125977 ..., -6.81201172 -6.87255859 - -6.92578125]] + [-1.3225098 -1.2358398 -1.1459961 ... -1.5771484 -1.4953613 + -1.4130859 ] + ... + [-6.96875 -7.027832 -7.0776367 ... -6.741455 -6.8256836 + -6.900879 ] + [-7.010498 -7.0480957 -7.0776367 ... -6.8447266 -6.9067383 + -6.963135 ] + [-6.9716797 -7.010254 -7.04126 ... -6.8120117 -6.8725586 + -6.9257812 ]] field_title: AJHQA Time mean !C Atmos u compnt of wind after timestep at 130.0 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 , PP Field lbyr: 2007 @@ -640,10 +617,10 @@ brsvd: (179.99911, 0.97954255, 0.0, 0.0) bdatum: 0.0 bacc: -12.0 - blev: 130.0 - brlev: 80.0014 - bhlev: 0.985204 - bhrlev: 0.990882 + blev: 130.00023 + brlev: 80.00135 + bhlev: 0.98520386 + bhrlev: 0.9908815 bplat: 90.0 bplon: 0.0 bgor: 0.0 @@ -651,20 +628,14 @@ bdy: 1.25 bzx: -1.875 bdx: 1.875 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[-1.74145508 -1.73217773 -1.72119141 ..., -1.7590332 -1.75463867 - -1.74853516] - [-1.48266602 -1.5065918 -1.53271484 ..., -1.41625977 -1.43725586 - -1.45898438] - [-1.36010742 -1.52270508 -1.69897461 ..., -1.27148438 -1.25146484 - -1.27539062] - ..., - [-1.72167969 -1.46435547 -1.2097168 ..., -2.43481445 -2.19848633 - -1.96484375] - [-1.52954102 -1.29516602 -1.06396484 ..., -2.24023438 -2.00488281 - -1.76708984] - [-1.47485352 -1.25024414 -1.02319336 ..., -2.13720703 -1.91772461 - -1.69702148]] + data: [[-1.7414551 -1.7321777 -1.7211914 ... -1.7590332 -1.7546387 -1.7485352] + [-1.482666 -1.5065918 -1.5327148 ... -1.4162598 -1.4372559 -1.4589844] + [-1.3601074 -1.5227051 -1.6989746 ... -1.2714844 -1.2514648 -1.2753906] + ... + [-1.7216797 -1.4643555 -1.2097168 ... -2.4348145 -2.1984863 -1.9648438] + [-1.529541 -1.295166 -1.0639648 ... -2.2402344 -2.0048828 -1.7670898] + [-1.4748535 -1.2502441 -1.0231934 ... -2.137207 -1.9177246 -1.6970215]] field_title: AJHQA Time mean !C Atmos v compnt of wind after timestep at 130.0 metres !C 01/12/2007 00:00 -> 01/01/2008 00:00 ] \ No newline at end of file diff --git a/lib/iris/tests/results/PP/extra_data_time_series.pp.txt b/lib/iris/tests/results/PP/extra_data_time_series.pp.txt index ba3a0d02de..52c70f42f5 100644 --- a/lib/iris/tests/results/PP/extra_data_time_series.pp.txt +++ b/lib/iris/tests/results/PP/extra_data_time_series.pp.txt @@ -51,281 +51,278 @@ bdx: 1.0 bmdi: -1e+30 bmks: 1.0 - data: [[ 4.39422607e-01 5.04180908e-01 3.77410889e-01] - [ 1.61437988e-01 4.63470459e-01 -1.27655029e-01] - [ -1.41296387e-02 1.76788330e-01 -1.96868896e-01] - [ 2.56958008e-01 3.30780029e-01 1.86279297e-01] - [ 2.12554932e-01 3.40728760e-01 8.98742676e-02] - [ 2.32818604e-01 4.48791504e-01 2.60925293e-02] - [ 1.29547119e-01 3.01300049e-01 -3.48815918e-02] - [ 1.25213623e-01 2.82897949e-01 -2.57263184e-02] - [ -9.41772461e-02 1.38977051e-01 -3.17352295e-01] - [ -9.60693359e-02 -8.30078125e-03 -1.80023193e-01] - [ 6.57958984e-02 -5.61523438e-03 1.34185791e-01] - [ -1.04064941e-01 -7.91625977e-02 -1.27899170e-01] - [ -5.49011230e-02 -2.26135254e-02 -8.58154297e-02] - [ 6.67724609e-02 1.39007568e-01 -2.38037109e-03] - [ 2.05169678e-01 2.12951660e-01 1.97753906e-01] - [ 5.14831543e-02 1.15905762e-01 -1.01318359e-02] - [ 2.46582031e-02 3.93676758e-02 1.06201172e-02] - [ 4.33654785e-02 1.40441895e-01 -4.95605469e-02] - [ 4.79736328e-02 2.16827393e-01 -1.13647461e-01] - [ 9.93347168e-02 1.56829834e-01 4.42810059e-02] - [ 9.96704102e-02 1.93481445e-01 9.91821289e-03] - [ -9.33227539e-02 -2.82897949e-02 -1.55578613e-01] - [ -9.35363770e-02 -1.93176270e-02 -1.64581299e-01] - [ 1.77642822e-01 1.06597900e-01 2.45635986e-01] - [ 1.06842041e-01 7.64160156e-02 1.35986328e-01] - [ 1.39556885e-01 1.76086426e-01 1.04583740e-01] - [ 1.80389404e-01 2.04559326e-01 1.57287598e-01] - [ 1.88323975e-01 2.18933105e-01 1.59027100e-01] - [ 1.64947510e-01 1.45812988e-01 1.83288574e-01] - [ 2.26806641e-01 2.09106445e-01 2.43774414e-01] - [ -1.53259277e-01 -7.32421875e-03 -2.92938232e-01] - [ -6.19506836e-02 -1.04339600e-01 -2.13928223e-02] - [ 2.23358154e-01 1.44958496e-01 2.98431396e-01] - [ 8.62426758e-02 2.94494629e-02 1.40655518e-01] - [ 1.97479248e-01 9.83581543e-02 2.92419434e-01] - [ 5.37139893e-01 4.97314453e-01 5.75286865e-01] - [ 3.39538574e-01 3.82598877e-01 2.98339844e-01] - [ 1.41693115e-01 1.96655273e-01 8.90808105e-02] - [ 8.66699219e-02 8.99047852e-02 8.36181641e-02] - [ 1.57348633e-01 1.78375244e-01 1.37207031e-01] - [ 1.29333496e-01 1.69128418e-01 9.12475586e-02] - [ 1.83959961e-01 2.35046387e-01 1.35101318e-01] - [ 1.60217285e-01 2.17529297e-01 1.05407715e-01] - [ 2.48352051e-01 3.26660156e-01 1.73400879e-01] - [ 1.88934326e-01 3.39538574e-01 4.47998047e-02] - [ 2.50762939e-01 2.35321045e-01 2.65563965e-01] - [ 1.97692871e-01 2.39013672e-01 1.58172607e-01] - [ 2.11181641e-01 3.82934570e-01 4.67529297e-02] - [ 3.70635986e-01 4.55749512e-01 2.89154053e-01] - [ 4.31060791e-01 4.52178955e-01 4.10858154e-01] - [ 1.18103027e-01 2.00531006e-01 3.92150879e-02] - [ 2.95288086e-01 2.99224854e-01 2.91503906e-01] - [ 3.72680664e-01 4.32220459e-01 3.15704346e-01] - [ 1.90856934e-01 3.93707275e-01 -3.32641602e-03] - [ 2.50854492e-02 2.84637451e-01 -2.23358154e-01] - [ -1.25549316e-01 6.93054199e-02 -3.12072754e-01] - [ -6.06384277e-02 7.21130371e-02 -1.87744141e-01] - [ 8.49304199e-02 2.12493896e-01 -3.71398926e-02] - [ 3.13568115e-01 3.07281494e-01 3.19610596e-01] - [ 1.98425293e-01 2.61718750e-01 1.37847900e-01] - [ 5.52307129e-01 5.37536621e-01 5.66436768e-01] - [ 1.77032471e-01 2.43347168e-01 1.13586426e-01] - [ 1.41418457e-01 2.46185303e-01 4.11376953e-02] - [ 3.28369141e-01 5.53527832e-01 1.12854004e-01] - [ 2.87322998e-01 3.74420166e-01 2.03948975e-01] - [ 4.03472900e-01 5.30029297e-01 2.82348633e-01] - [ 2.83721924e-01 4.34478760e-01 1.39404297e-01] - [ 4.91943359e-01 4.46289062e-01 5.35644531e-01] - [ 5.27069092e-01 6.34460449e-01 4.24255371e-01] - [ 1.80389404e-01 4.11346436e-01 -4.07104492e-02] - [ 2.48260498e-01 2.69256592e-01 2.28179932e-01] - [ 3.58123779e-01 4.13940430e-01 3.04687500e-01] - [ 1.52160645e-01 3.04565430e-01 6.28662109e-03] - [ 1.62414551e-01 2.32635498e-01 9.51843262e-02] - [ 2.92297363e-01 3.61572266e-01 2.26013184e-01] - [ 3.98834229e-01 4.19097900e-01 3.79455566e-01] - [ 3.25927734e-01 2.93945312e-01 3.56567383e-01] - [ 4.53002930e-01 5.42480469e-01 3.67340088e-01] - [ 4.33135986e-01 4.75921631e-01 3.92181396e-01] - [ 4.57641602e-01 4.46563721e-01 4.68292236e-01] - [ 2.60925293e-01 2.64373779e-01 2.57629395e-01] - [ 3.27392578e-01 2.14721680e-01 4.35302734e-01] - [ 4.07501221e-01 4.67163086e-01 3.50402832e-01] - [ 1.50238037e-01 3.02246094e-01 4.76074219e-03] - [ 2.34161377e-01 3.56781006e-01 1.16760254e-01] - [ 2.38861084e-01 3.21258545e-01 1.59973145e-01] - [ 4.41253662e-01 5.73211670e-01 3.14971924e-01] - [ 5.46905518e-01 6.14166260e-01 4.82513428e-01] - [ 4.51934814e-01 5.38421631e-01 3.69140625e-01] - [ 6.29669189e-01 6.36138916e-01 6.23504639e-01] - [ 5.98968506e-01 6.35559082e-01 5.63964844e-01] - [ 4.68994141e-01 5.24047852e-01 4.16320801e-01] - [ 2.43499756e-01 4.44915771e-01 5.06896973e-02] - [ 3.47290039e-01 5.42266846e-01 1.60644531e-01] - [ 5.54046631e-01 6.54754639e-01 4.57672119e-01] - [ 3.68164062e-01 5.08758545e-01 2.33612061e-01] - [ 5.15045166e-01 6.09039307e-01 4.25048828e-01] - [ 4.37408447e-01 6.33331299e-01 2.49847412e-01] - [ 6.05804443e-01 6.90673828e-01 5.24566650e-01] - [ 4.22546387e-01 5.14251709e-01 3.34777832e-01] - [ 4.70550537e-01 5.98236084e-01 3.48297119e-01] - [ 5.17395020e-01 6.31317139e-01 4.08355713e-01] - [ 5.52154541e-01 6.03424072e-01 5.03082275e-01] - [ 8.41400146e-01 9.78576660e-01 7.10113525e-01] - [ 7.35595703e-01 8.67004395e-01 6.09832764e-01] - [ 5.01708984e-01 7.05352783e-01 3.06762695e-01] - [ 6.30920410e-01 6.85180664e-01 5.79010010e-01] - [ 6.32873535e-01 8.00415039e-01 4.72503662e-01] - [ 5.23345947e-01 7.85064697e-01 2.72857666e-01] - [ 5.06164551e-01 6.80816650e-01 3.38989258e-01] - [ 5.98205566e-01 7.08618164e-01 4.92553711e-01] - [ 6.91833496e-01 8.18542480e-01 5.70556641e-01] - [ 5.53833008e-01 7.62054443e-01 3.54492188e-01] - [ 9.19586182e-01 9.40277100e-01 8.99780273e-01] - [ 8.27758789e-01 9.19403076e-01 7.40020752e-01] - [ 1.05804443e+00 1.11437988e+00 1.00411987e+00] - [ 7.01202393e-01 8.56506348e-01 5.52551270e-01] - [ 6.61163330e-01 7.11669922e-01 6.12823486e-01] - [ 7.83569336e-01 9.40887451e-01 6.32965088e-01] - [ 6.56677246e-01 7.36724854e-01 5.80047607e-01] - [ 7.54516602e-01 8.28155518e-01 6.84020996e-01] - [ 5.91125488e-01 8.23394775e-01 3.68804932e-01] - [ 7.53997803e-01 9.20166016e-01 5.94909668e-01] - [ 9.39453125e-01 9.91027832e-01 8.90075684e-01] - [ 1.08993530e+00 1.13360596e+00 1.04815674e+00] - [ 1.03469849e+00 1.26153564e+00 8.17565918e-01] - [ 1.11340332e+00 1.22210693e+00 1.00936890e+00] - [ 9.92828369e-01 1.08270264e+00 9.06768799e-01] - [ 8.60290527e-01 1.03817749e+00 6.90002441e-01] - [ 1.08633423e+00 1.21694946e+00 9.61303711e-01] - [ 1.06781006e+00 1.22933960e+00 9.13238525e-01] - [ 1.03814697e+00 1.29342651e+00 7.93792725e-01] - [ 9.47906494e-01 1.09213257e+00 8.09875488e-01] - [ 1.04327393e+00 1.25805664e+00 8.37677002e-01] - [ 1.11047363e+00 1.26431274e+00 9.63226318e-01] - [ 9.94567871e-01 1.28823853e+00 7.13439941e-01] - [ 1.02252197e+00 1.15332031e+00 8.97369385e-01] - [ 1.20819092e+00 1.40307617e+00 1.02166748e+00] - [ 1.05911255e+00 1.41232300e+00 7.21008301e-01] - [ 1.15362549e+00 1.42245483e+00 8.96270752e-01] - [ 1.19024658e+00 1.43325806e+00 9.57611084e-01] - [ 9.96490479e-01 1.27505493e+00 7.29827881e-01] - [ 1.29159546e+00 1.52636719e+00 1.06683350e+00] - [ 1.27478027e+00 1.44665527e+00 1.11026001e+00] - [ 1.22344971e+00 1.43841553e+00 1.01770020e+00] - [ 1.26553345e+00 1.56521606e+00 9.78637695e-01] - [ 1.43307495e+00 1.69100952e+00 1.18615723e+00] - [ 1.67053223e+00 1.79122925e+00 1.55502319e+00] - [ 1.58166504e+00 1.75869751e+00 1.41223145e+00] - [ 1.48156738e+00 1.82290649e+00 1.15484619e+00] - [ 1.54971313e+00 1.93185425e+00 1.18392944e+00] - [ 1.71575928e+00 2.01840210e+00 1.42605591e+00] - [ 1.74023438e+00 2.01577759e+00 1.47647095e+00] - [ 1.70233154e+00 2.03710938e+00 1.38189697e+00] - [ 1.67721558e+00 1.98394775e+00 1.38360596e+00] - [ 1.69354248e+00 1.98156738e+00 1.41781616e+00] - [ 1.70068359e+00 2.16409302e+00 1.25708008e+00] - [ 1.86215210e+00 2.10812378e+00 1.62670898e+00] - [ 1.96661377e+00 2.20684814e+00 1.73666382e+00] - [ 1.80047607e+00 2.11480713e+00 1.49960327e+00] - [ 1.68875122e+00 2.11251831e+00 1.28305054e+00] - [ 1.60568237e+00 2.08395386e+00 1.14785767e+00] - [ 1.85006714e+00 2.11837769e+00 1.59323120e+00] - [ 1.79373169e+00 2.16232300e+00 1.44091797e+00] - [ 1.83746338e+00 2.30429077e+00 1.39059448e+00] - [ 1.88656616e+00 2.25970459e+00 1.52935791e+00] - [ 1.86541748e+00 2.19226074e+00 1.55252075e+00] - [ 2.13336182e+00 2.47967529e+00 1.80184937e+00] - [ 2.24230957e+00 2.82839966e+00 1.68127441e+00] - [ 2.31884766e+00 2.74777222e+00 1.90823364e+00] - [ 2.15151978e+00 2.57403564e+00 1.74703979e+00] - [ 2.01345825e+00 2.67620850e+00 1.37902832e+00] - [ 1.98477173e+00 2.53799438e+00 1.45516968e+00] - [ 2.18768311e+00 2.50122070e+00 1.88757324e+00] - [ 2.33840942e+00 2.89501953e+00 1.80557251e+00] - [ 2.43499756e+00 2.86209106e+00 2.02618408e+00] - [ 2.69714355e+00 3.07894897e+00 2.33166504e+00] - [ 2.37374878e+00 2.90130615e+00 1.86874390e+00] - [ 2.37030029e+00 2.82366943e+00 1.93634033e+00] - [ 2.46295166e+00 2.92013550e+00 2.02532959e+00] - [ 2.74835205e+00 3.08822632e+00 2.42297363e+00] - [ 2.49890137e+00 2.98434448e+00 2.03417969e+00] - [ 2.46966553e+00 2.95443726e+00 2.00564575e+00] - [ 2.63943481e+00 3.11413574e+00 2.18502808e+00] - [ 2.48312378e+00 3.02301025e+00 1.96630859e+00] - [ 2.52224731e+00 3.02822876e+00 2.03790283e+00] - [ 2.59698486e+00 3.09338379e+00 2.12176514e+00] - [ 2.50442505e+00 3.05929565e+00 1.97329712e+00] - [ 2.78515625e+00 3.16195679e+00 2.42443848e+00] - [ 2.76461792e+00 3.31610107e+00 2.23669434e+00] - [ 2.94354248e+00 3.38668823e+00 2.51931763e+00] - [ 2.66171265e+00 3.20968628e+00 2.13717651e+00] - [ 2.43103027e+00 2.98941040e+00 1.89648438e+00] - [ 2.54162598e+00 3.22238159e+00 1.88995361e+00] - [ 2.79067993e+00 3.36560059e+00 2.24029541e+00] - [ 3.03442383e+00 3.51901245e+00 2.57055664e+00] - [ 3.04656982e+00 3.60708618e+00 2.51004028e+00] - [ 3.00198364e+00 3.57232666e+00 2.45602417e+00] - [ 2.98760986e+00 3.64099121e+00 2.36215210e+00] - [ 3.13809204e+00 3.71331787e+00 2.58743286e+00] - [ 2.95605469e+00 3.65777588e+00 2.28433228e+00] - [ 3.06344604e+00 3.65859985e+00 2.49368286e+00] - [ 3.24172974e+00 3.73605347e+00 2.76852417e+00] - [ 3.07305908e+00 3.63876343e+00 2.53152466e+00] - [ 3.19055176e+00 3.76119995e+00 2.64428711e+00] - [ 3.27514648e+00 3.88204956e+00 2.69418335e+00] - [ 3.21536255e+00 3.87390137e+00 2.58493042e+00] - [ 3.30374146e+00 3.91629028e+00 2.71734619e+00] - [ 3.31219482e+00 3.86566162e+00 2.78237915e+00] - [ 3.23471069e+00 3.76669312e+00 2.72546387e+00] - [ 3.45950317e+00 4.03723145e+00 2.90649414e+00] - [ 3.55783081e+00 4.14697266e+00 2.99386597e+00] - [ 3.34695435e+00 4.05664062e+00 2.66754150e+00] - [ 3.39938354e+00 4.09802246e+00 2.73059082e+00] - [ 3.47076416e+00 4.08825684e+00 2.87963867e+00] - [ 3.60931396e+00 4.17758179e+00 3.06533813e+00] - [ 3.45901489e+00 4.18838501e+00 2.76083374e+00] - [ 3.55413818e+00 4.23626709e+00 2.90115356e+00] - [ 3.90261841e+00 4.39932251e+00 3.42715454e+00] - [ 3.77856445e+00 4.37539673e+00 3.20724487e+00] - [ 3.83999634e+00 4.52651978e+00 3.18276978e+00] - [ 3.70617676e+00 4.51071167e+00 2.93600464e+00] - [ 3.90826416e+00 4.61489868e+00 3.23184204e+00] - [ 3.99218750e+00 4.61093140e+00 3.39987183e+00] - [ 3.98327637e+00 4.67016602e+00 3.32571411e+00] - [ 4.24465942e+00 4.82952881e+00 3.68478394e+00] - [ 4.18685913e+00 4.86254883e+00 3.54003906e+00] - [ 4.21359253e+00 4.94802856e+00 3.51052856e+00] - [ 4.23333740e+00 4.83337402e+00 3.65893555e+00] - [ 3.91738892e+00 4.80505371e+00 3.06765747e+00] - [ 4.12377930e+00 5.00881958e+00 3.27655029e+00] - [ 4.18835449e+00 5.05175781e+00 3.36184692e+00] - [ 4.24496460e+00 5.13610840e+00 3.39190674e+00] - [ 4.39852905e+00 5.05041504e+00 3.77447510e+00] - [ 4.29287720e+00 5.01931763e+00 3.59744263e+00] - [ 4.36053467e+00 5.05780029e+00 3.69308472e+00] - [ 4.41970825e+00 5.14730835e+00 3.72320557e+00] - [ 4.20068359e+00 4.96783447e+00 3.46627808e+00] - [ 4.25854492e+00 4.95800781e+00 3.58895874e+00] - [ 4.37335205e+00 5.09683228e+00 3.68075562e+00]] + data: [[ 4.39422607e-01 5.04180908e-01 3.77410889e-01] + [ 1.61437988e-01 4.63470459e-01 -1.27655029e-01] + [-1.41296387e-02 1.76788330e-01 -1.96868896e-01] + [ 2.56958008e-01 3.30780029e-01 1.86279297e-01] + [ 2.12554932e-01 3.40728760e-01 8.98742676e-02] + [ 2.32818604e-01 4.48791504e-01 2.60925293e-02] + [ 1.29547119e-01 3.01300049e-01 -3.48815918e-02] + [ 1.25213623e-01 2.82897949e-01 -2.57263184e-02] + [-9.41772461e-02 1.38977051e-01 -3.17352295e-01] + [-9.60693359e-02 -8.30078125e-03 -1.80023193e-01] + [ 6.57958984e-02 -5.61523438e-03 1.34185791e-01] + [-1.04064941e-01 -7.91625977e-02 -1.27899170e-01] + [-5.49011230e-02 -2.26135254e-02 -8.58154297e-02] + [ 6.67724609e-02 1.39007568e-01 -2.38037109e-03] + [ 2.05169678e-01 2.12951660e-01 1.97753906e-01] + [ 5.14831543e-02 1.15905762e-01 -1.01318359e-02] + [ 2.46582031e-02 3.93676758e-02 1.06201172e-02] + [ 4.33654785e-02 1.40441895e-01 -4.95605469e-02] + [ 4.79736328e-02 2.16827393e-01 -1.13647461e-01] + [ 9.93347168e-02 1.56829834e-01 4.42810059e-02] + [ 9.96704102e-02 1.93481445e-01 9.91821289e-03] + [-9.33227539e-02 -2.82897949e-02 -1.55578613e-01] + [-9.35363770e-02 -1.93176270e-02 -1.64581299e-01] + [ 1.77642822e-01 1.06597900e-01 2.45635986e-01] + [ 1.06842041e-01 7.64160156e-02 1.35986328e-01] + [ 1.39556885e-01 1.76086426e-01 1.04583740e-01] + [ 1.80389404e-01 2.04559326e-01 1.57287598e-01] + [ 1.88323975e-01 2.18933105e-01 1.59027100e-01] + [ 1.64947510e-01 1.45812988e-01 1.83288574e-01] + [ 2.26806641e-01 2.09106445e-01 2.43774414e-01] + [-1.53259277e-01 -7.32421875e-03 -2.92938232e-01] + [-6.19506836e-02 -1.04339600e-01 -2.13928223e-02] + [ 2.23358154e-01 1.44958496e-01 2.98431396e-01] + [ 8.62426758e-02 2.94494629e-02 1.40655518e-01] + [ 1.97479248e-01 9.83581543e-02 2.92419434e-01] + [ 5.37139893e-01 4.97314453e-01 5.75286865e-01] + [ 3.39538574e-01 3.82598877e-01 2.98339844e-01] + [ 1.41693115e-01 1.96655273e-01 8.90808105e-02] + [ 8.66699219e-02 8.99047852e-02 8.36181641e-02] + [ 1.57348633e-01 1.78375244e-01 1.37207031e-01] + [ 1.29333496e-01 1.69128418e-01 9.12475586e-02] + [ 1.83959961e-01 2.35046387e-01 1.35101318e-01] + [ 1.60217285e-01 2.17529297e-01 1.05407715e-01] + [ 2.48352051e-01 3.26660156e-01 1.73400879e-01] + [ 1.88934326e-01 3.39538574e-01 4.47998047e-02] + [ 2.50762939e-01 2.35321045e-01 2.65563965e-01] + [ 1.97692871e-01 2.39013672e-01 1.58172607e-01] + [ 2.11181641e-01 3.82934570e-01 4.67529297e-02] + [ 3.70635986e-01 4.55749512e-01 2.89154053e-01] + [ 4.31060791e-01 4.52178955e-01 4.10858154e-01] + [ 1.18103027e-01 2.00531006e-01 3.92150879e-02] + [ 2.95288086e-01 2.99224854e-01 2.91503906e-01] + [ 3.72680664e-01 4.32220459e-01 3.15704346e-01] + [ 1.90856934e-01 3.93707275e-01 -3.32641602e-03] + [ 2.50854492e-02 2.84637451e-01 -2.23358154e-01] + [-1.25549316e-01 6.93054199e-02 -3.12072754e-01] + [-6.06384277e-02 7.21130371e-02 -1.87744141e-01] + [ 8.49304199e-02 2.12493896e-01 -3.71398926e-02] + [ 3.13568115e-01 3.07281494e-01 3.19610596e-01] + [ 1.98425293e-01 2.61718750e-01 1.37847900e-01] + [ 5.52307129e-01 5.37536621e-01 5.66436768e-01] + [ 1.77032471e-01 2.43347168e-01 1.13586426e-01] + [ 1.41418457e-01 2.46185303e-01 4.11376953e-02] + [ 3.28369141e-01 5.53527832e-01 1.12854004e-01] + [ 2.87322998e-01 3.74420166e-01 2.03948975e-01] + [ 4.03472900e-01 5.30029297e-01 2.82348633e-01] + [ 2.83721924e-01 4.34478760e-01 1.39404297e-01] + [ 4.91943359e-01 4.46289062e-01 5.35644531e-01] + [ 5.27069092e-01 6.34460449e-01 4.24255371e-01] + [ 1.80389404e-01 4.11346436e-01 -4.07104492e-02] + [ 2.48260498e-01 2.69256592e-01 2.28179932e-01] + [ 3.58123779e-01 4.13940430e-01 3.04687500e-01] + [ 1.52160645e-01 3.04565430e-01 6.28662109e-03] + [ 1.62414551e-01 2.32635498e-01 9.51843262e-02] + [ 2.92297363e-01 3.61572266e-01 2.26013184e-01] + [ 3.98834229e-01 4.19097900e-01 3.79455566e-01] + [ 3.25927734e-01 2.93945312e-01 3.56567383e-01] + [ 4.53002930e-01 5.42480469e-01 3.67340088e-01] + [ 4.33135986e-01 4.75921631e-01 3.92181396e-01] + [ 4.57641602e-01 4.46563721e-01 4.68292236e-01] + [ 2.60925293e-01 2.64373779e-01 2.57629395e-01] + [ 3.27392578e-01 2.14721680e-01 4.35302734e-01] + [ 4.07501221e-01 4.67163086e-01 3.50402832e-01] + [ 1.50238037e-01 3.02246094e-01 4.76074219e-03] + [ 2.34161377e-01 3.56781006e-01 1.16760254e-01] + [ 2.38861084e-01 3.21258545e-01 1.59973145e-01] + [ 4.41253662e-01 5.73211670e-01 3.14971924e-01] + [ 5.46905518e-01 6.14166260e-01 4.82513428e-01] + [ 4.51934814e-01 5.38421631e-01 3.69140625e-01] + [ 6.29669189e-01 6.36138916e-01 6.23504639e-01] + [ 5.98968506e-01 6.35559082e-01 5.63964844e-01] + [ 4.68994141e-01 5.24047852e-01 4.16320801e-01] + [ 2.43499756e-01 4.44915771e-01 5.06896973e-02] + [ 3.47290039e-01 5.42266846e-01 1.60644531e-01] + [ 5.54046631e-01 6.54754639e-01 4.57672119e-01] + [ 3.68164062e-01 5.08758545e-01 2.33612061e-01] + [ 5.15045166e-01 6.09039307e-01 4.25048828e-01] + [ 4.37408447e-01 6.33331299e-01 2.49847412e-01] + [ 6.05804443e-01 6.90673828e-01 5.24566650e-01] + [ 4.22546387e-01 5.14251709e-01 3.34777832e-01] + [ 4.70550537e-01 5.98236084e-01 3.48297119e-01] + [ 5.17395020e-01 6.31317139e-01 4.08355713e-01] + [ 5.52154541e-01 6.03424072e-01 5.03082275e-01] + [ 8.41400146e-01 9.78576660e-01 7.10113525e-01] + [ 7.35595703e-01 8.67004395e-01 6.09832764e-01] + [ 5.01708984e-01 7.05352783e-01 3.06762695e-01] + [ 6.30920410e-01 6.85180664e-01 5.79010010e-01] + [ 6.32873535e-01 8.00415039e-01 4.72503662e-01] + [ 5.23345947e-01 7.85064697e-01 2.72857666e-01] + [ 5.06164551e-01 6.80816650e-01 3.38989258e-01] + [ 5.98205566e-01 7.08618164e-01 4.92553711e-01] + [ 6.91833496e-01 8.18542480e-01 5.70556641e-01] + [ 5.53833008e-01 7.62054443e-01 3.54492188e-01] + [ 9.19586182e-01 9.40277100e-01 8.99780273e-01] + [ 8.27758789e-01 9.19403076e-01 7.40020752e-01] + [ 1.05804443e+00 1.11437988e+00 1.00411987e+00] + [ 7.01202393e-01 8.56506348e-01 5.52551270e-01] + [ 6.61163330e-01 7.11669922e-01 6.12823486e-01] + [ 7.83569336e-01 9.40887451e-01 6.32965088e-01] + [ 6.56677246e-01 7.36724854e-01 5.80047607e-01] + [ 7.54516602e-01 8.28155518e-01 6.84020996e-01] + [ 5.91125488e-01 8.23394775e-01 3.68804932e-01] + [ 7.53997803e-01 9.20166016e-01 5.94909668e-01] + [ 9.39453125e-01 9.91027832e-01 8.90075684e-01] + [ 1.08993530e+00 1.13360596e+00 1.04815674e+00] + [ 1.03469849e+00 1.26153564e+00 8.17565918e-01] + [ 1.11340332e+00 1.22210693e+00 1.00936890e+00] + [ 9.92828369e-01 1.08270264e+00 9.06768799e-01] + [ 8.60290527e-01 1.03817749e+00 6.90002441e-01] + [ 1.08633423e+00 1.21694946e+00 9.61303711e-01] + [ 1.06781006e+00 1.22933960e+00 9.13238525e-01] + [ 1.03814697e+00 1.29342651e+00 7.93792725e-01] + [ 9.47906494e-01 1.09213257e+00 8.09875488e-01] + [ 1.04327393e+00 1.25805664e+00 8.37677002e-01] + [ 1.11047363e+00 1.26431274e+00 9.63226318e-01] + [ 9.94567871e-01 1.28823853e+00 7.13439941e-01] + [ 1.02252197e+00 1.15332031e+00 8.97369385e-01] + [ 1.20819092e+00 1.40307617e+00 1.02166748e+00] + [ 1.05911255e+00 1.41232300e+00 7.21008301e-01] + [ 1.15362549e+00 1.42245483e+00 8.96270752e-01] + [ 1.19024658e+00 1.43325806e+00 9.57611084e-01] + [ 9.96490479e-01 1.27505493e+00 7.29827881e-01] + [ 1.29159546e+00 1.52636719e+00 1.06683350e+00] + [ 1.27478027e+00 1.44665527e+00 1.11026001e+00] + [ 1.22344971e+00 1.43841553e+00 1.01770020e+00] + [ 1.26553345e+00 1.56521606e+00 9.78637695e-01] + [ 1.43307495e+00 1.69100952e+00 1.18615723e+00] + [ 1.67053223e+00 1.79122925e+00 1.55502319e+00] + [ 1.58166504e+00 1.75869751e+00 1.41223145e+00] + [ 1.48156738e+00 1.82290649e+00 1.15484619e+00] + [ 1.54971313e+00 1.93185425e+00 1.18392944e+00] + [ 1.71575928e+00 2.01840210e+00 1.42605591e+00] + [ 1.74023438e+00 2.01577759e+00 1.47647095e+00] + [ 1.70233154e+00 2.03710938e+00 1.38189697e+00] + [ 1.67721558e+00 1.98394775e+00 1.38360596e+00] + [ 1.69354248e+00 1.98156738e+00 1.41781616e+00] + [ 1.70068359e+00 2.16409302e+00 1.25708008e+00] + [ 1.86215210e+00 2.10812378e+00 1.62670898e+00] + [ 1.96661377e+00 2.20684814e+00 1.73666382e+00] + [ 1.80047607e+00 2.11480713e+00 1.49960327e+00] + [ 1.68875122e+00 2.11251831e+00 1.28305054e+00] + [ 1.60568237e+00 2.08395386e+00 1.14785767e+00] + [ 1.85006714e+00 2.11837769e+00 1.59323120e+00] + [ 1.79373169e+00 2.16232300e+00 1.44091797e+00] + [ 1.83746338e+00 2.30429077e+00 1.39059448e+00] + [ 1.88656616e+00 2.25970459e+00 1.52935791e+00] + [ 1.86541748e+00 2.19226074e+00 1.55252075e+00] + [ 2.13336182e+00 2.47967529e+00 1.80184937e+00] + [ 2.24230957e+00 2.82839966e+00 1.68127441e+00] + [ 2.31884766e+00 2.74777222e+00 1.90823364e+00] + [ 2.15151978e+00 2.57403564e+00 1.74703979e+00] + [ 2.01345825e+00 2.67620850e+00 1.37902832e+00] + [ 1.98477173e+00 2.53799438e+00 1.45516968e+00] + [ 2.18768311e+00 2.50122070e+00 1.88757324e+00] + [ 2.33840942e+00 2.89501953e+00 1.80557251e+00] + [ 2.43499756e+00 2.86209106e+00 2.02618408e+00] + [ 2.69714355e+00 3.07894897e+00 2.33166504e+00] + [ 2.37374878e+00 2.90130615e+00 1.86874390e+00] + [ 2.37030029e+00 2.82366943e+00 1.93634033e+00] + [ 2.46295166e+00 2.92013550e+00 2.02532959e+00] + [ 2.74835205e+00 3.08822632e+00 2.42297363e+00] + [ 2.49890137e+00 2.98434448e+00 2.03417969e+00] + [ 2.46966553e+00 2.95443726e+00 2.00564575e+00] + [ 2.63943481e+00 3.11413574e+00 2.18502808e+00] + [ 2.48312378e+00 3.02301025e+00 1.96630859e+00] + [ 2.52224731e+00 3.02822876e+00 2.03790283e+00] + [ 2.59698486e+00 3.09338379e+00 2.12176514e+00] + [ 2.50442505e+00 3.05929565e+00 1.97329712e+00] + [ 2.78515625e+00 3.16195679e+00 2.42443848e+00] + [ 2.76461792e+00 3.31610107e+00 2.23669434e+00] + [ 2.94354248e+00 3.38668823e+00 2.51931763e+00] + [ 2.66171265e+00 3.20968628e+00 2.13717651e+00] + [ 2.43103027e+00 2.98941040e+00 1.89648438e+00] + [ 2.54162598e+00 3.22238159e+00 1.88995361e+00] + [ 2.79067993e+00 3.36560059e+00 2.24029541e+00] + [ 3.03442383e+00 3.51901245e+00 2.57055664e+00] + [ 3.04656982e+00 3.60708618e+00 2.51004028e+00] + [ 3.00198364e+00 3.57232666e+00 2.45602417e+00] + [ 2.98760986e+00 3.64099121e+00 2.36215210e+00] + [ 3.13809204e+00 3.71331787e+00 2.58743286e+00] + [ 2.95605469e+00 3.65777588e+00 2.28433228e+00] + [ 3.06344604e+00 3.65859985e+00 2.49368286e+00] + [ 3.24172974e+00 3.73605347e+00 2.76852417e+00] + [ 3.07305908e+00 3.63876343e+00 2.53152466e+00] + [ 3.19055176e+00 3.76119995e+00 2.64428711e+00] + [ 3.27514648e+00 3.88204956e+00 2.69418335e+00] + [ 3.21536255e+00 3.87390137e+00 2.58493042e+00] + [ 3.30374146e+00 3.91629028e+00 2.71734619e+00] + [ 3.31219482e+00 3.86566162e+00 2.78237915e+00] + [ 3.23471069e+00 3.76669312e+00 2.72546387e+00] + [ 3.45950317e+00 4.03723145e+00 2.90649414e+00] + [ 3.55783081e+00 4.14697266e+00 2.99386597e+00] + [ 3.34695435e+00 4.05664062e+00 2.66754150e+00] + [ 3.39938354e+00 4.09802246e+00 2.73059082e+00] + [ 3.47076416e+00 4.08825684e+00 2.87963867e+00] + [ 3.60931396e+00 4.17758179e+00 3.06533813e+00] + [ 3.45901489e+00 4.18838501e+00 2.76083374e+00] + [ 3.55413818e+00 4.23626709e+00 2.90115356e+00] + [ 3.90261841e+00 4.39932251e+00 3.42715454e+00] + [ 3.77856445e+00 4.37539673e+00 3.20724487e+00] + [ 3.83999634e+00 4.52651978e+00 3.18276978e+00] + [ 3.70617676e+00 4.51071167e+00 2.93600464e+00] + [ 3.90826416e+00 4.61489868e+00 3.23184204e+00] + [ 3.99218750e+00 4.61093140e+00 3.39987183e+00] + [ 3.98327637e+00 4.67016602e+00 3.32571411e+00] + [ 4.24465942e+00 4.82952881e+00 3.68478394e+00] + [ 4.18685913e+00 4.86254883e+00 3.54003906e+00] + [ 4.21359253e+00 4.94802856e+00 3.51052856e+00] + [ 4.23333740e+00 4.83337402e+00 3.65893555e+00] + [ 3.91738892e+00 4.80505371e+00 3.06765747e+00] + [ 4.12377930e+00 5.00881958e+00 3.27655029e+00] + [ 4.18835449e+00 5.05175781e+00 3.36184692e+00] + [ 4.24496460e+00 5.13610840e+00 3.39190674e+00] + [ 4.39852905e+00 5.05041504e+00 3.77447510e+00] + [ 4.29287720e+00 5.01931763e+00 3.59744263e+00] + [ 4.36053467e+00 5.05780029e+00 3.69308472e+00] + [ 4.41970825e+00 5.14730835e+00 3.72320557e+00] + [ 4.20068359e+00 4.96783447e+00 3.46627808e+00] + [ 4.25854492e+00 4.95800781e+00 3.58895874e+00] + [ 4.37335205e+00 5.09683228e+00 3.68075562e+00]] domain_title: Southern Hemisphere lower_x_domain: [-1.875 -1.875 -1.875] - lower_y_domain: [-89.90000153 1.25 -89.90000153] - lower_z_domain: [ -1.00000002e+30 -1.00000002e+30 -1.00000002e+30] - upper_x_domain: [ 358.125 358.125 358.125] - upper_y_domain: [ 89.90000153 89.90000153 1.24998474] - upper_z_domain: [ -1.00000002e+30 -1.00000002e+30 -1.00000002e+30] - y: [ 670020. 670380. 670740. 671100. 671460. 671820. 672180. 672540. - 672900. 673260. 673620. 673980. 674340. 674700. 675060. 675420. - 675780. 676140. 676500. 676860. 677220. 677580. 677940. 678300. - 678660. 679020. 679380. 679740. 680100. 680460. 680820. 681180. - 681540. 681900. 682260. 682620. 682980. 683340. 683700. 684060. - 684420. 684780. 685140. 685500. 685860. 686220. 686580. 686940. - 687300. 687660. 688020. 688380. 688740. 689100. 689460. 689820. - 690180. 690540. 690900. 691260. 691620. 691980. 692340. 692700. - 693060. 693420. 693780. 694140. 694500. 694860. 695220. 695580. - 695940. 696300. 696660. 697020. 697380. 697740. 698100. 698460. - 698820. 699180. 699540. 699900. 700260. 700620. 700980. 701340. - 701700. 702060. 702420. 702780. 703140. 703500. 703860. 704220. - 704580. 704940. 705300. 705660. 706020. 706380. 706740. 707100. - 707460. 707820. 708180. 708540. 708900. 709260. 709620. 709980. - 710340. 710700. 711060. 711420. 711780. 712140. 712500. 712860. - 713220. 713580. 713940. 714300. 714660. 715020. 715380. 715740. - 716100. 716460. 716820. 717180. 717540. 717900. 718260. 718620. - 718980. 719340. 719700. 720060. 720420. 720780. 721140. 721500. - 721860. 722220. 722580. 722940. 723300. 723660. 724020. 724380. - 724740. 725100. 725460. 725820. 726180. 726540. 726900. 727260. - 727620. 727980. 728340. 728700. 729060. 729420. 729780. 730140. - 730500. 730860. 731220. 731580. 731940. 732300. 732660. 733020. - 733380. 733740. 734100. 734460. 734820. 735180. 735540. 735900. - 736260. 736620. 736980. 737340. 737700. 738060. 738420. 738780. - 739140. 739500. 739860. 740220. 740580. 740940. 741300. 741660. - 742020. 742380. 742740. 743100. 743460. 743820. 744180. 744540. - 744900. 745260. 745620. 745980. 746340. 746700. 747060. 747420. - 747780. 748140. 748500. 748860. 749220. 749580. 749940. 750300. - 750660. 751020. 751380. 751740. 752100. 752460. 752820. 753180. - 753540. 753900. 754260. 754620. 754980. 755340. 755700. 756060.] + lower_y_domain: [-89.9 1.25 -89.9 ] + lower_z_domain: [-1.e+30 -1.e+30 -1.e+30] + upper_x_domain: [358.125 358.125 358.125] + upper_y_domain: [89.9 89.9 1.2499847] + upper_z_domain: [-1.e+30 -1.e+30 -1.e+30] + y: [670020. 670380. 670740. 671100. 671460. 671820. 672180. 672540. 672900. + 673260. 673620. 673980. 674340. 674700. 675060. 675420. 675780. 676140. + 676500. 676860. 677220. 677580. 677940. 678300. 678660. 679020. 679380. + 679740. 680100. 680460. 680820. 681180. 681540. 681900. 682260. 682620. + 682980. 683340. 683700. 684060. 684420. 684780. 685140. 685500. 685860. + 686220. 686580. 686940. 687300. 687660. 688020. 688380. 688740. 689100. + 689460. 689820. 690180. 690540. 690900. 691260. 691620. 691980. 692340. + 692700. 693060. 693420. 693780. 694140. 694500. 694860. 695220. 695580. + 695940. 696300. 696660. 697020. 697380. 697740. 698100. 698460. 698820. + 699180. 699540. 699900. 700260. 700620. 700980. 701340. 701700. 702060. + 702420. 702780. 703140. 703500. 703860. 704220. 704580. 704940. 705300. + 705660. 706020. 706380. 706740. 707100. 707460. 707820. 708180. 708540. + 708900. 709260. 709620. 709980. 710340. 710700. 711060. 711420. 711780. + 712140. 712500. 712860. 713220. 713580. 713940. 714300. 714660. 715020. + 715380. 715740. 716100. 716460. 716820. 717180. 717540. 717900. 718260. + 718620. 718980. 719340. 719700. 720060. 720420. 720780. 721140. 721500. + 721860. 722220. 722580. 722940. 723300. 723660. 724020. 724380. 724740. + 725100. 725460. 725820. 726180. 726540. 726900. 727260. 727620. 727980. + 728340. 728700. 729060. 729420. 729780. 730140. 730500. 730860. 731220. + 731580. 731940. 732300. 732660. 733020. 733380. 733740. 734100. 734460. + 734820. 735180. 735540. 735900. 736260. 736620. 736980. 737340. 737700. + 738060. 738420. 738780. 739140. 739500. 739860. 740220. 740580. 740940. + 741300. 741660. 742020. 742380. 742740. 743100. 743460. 743820. 744180. + 744540. 744900. 745260. 745620. 745980. 746340. 746700. 747060. 747420. + 747780. 748140. 748500. 748860. 749220. 749580. 749940. 750300. 750660. + 751020. 751380. 751740. 752100. 752460. 752820. 753180. 753540. 753900. + 754260. 754620. 754980. 755340. 755700. 756060.] ] \ No newline at end of file diff --git a/lib/iris/tests/results/PP/extra_x_data.pp.txt b/lib/iris/tests/results/PP/extra_x_data.pp.txt index 607c1ec41f..d65e6fb6fc 100644 --- a/lib/iris/tests/results/PP/extra_x_data.pp.txt +++ b/lib/iris/tests/results/PP/extra_x_data.pp.txt @@ -49,1158 +49,1032 @@ bdy: 0.0 bzx: 0.0 bdx: 0.0 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 100075. 100073. 100071. ..., 101147. 101153. 101155.] - [ 100072. 100070. 100068. ..., 101149. 101155. 101157.] - [ 100070. 100069. 100067. ..., 101149. 101156. 101158.] - ..., - [ 102231. 102239. 102247. ..., 101882. 101855. 101852.] - [ 102237. 102245. 102253. ..., 101879. 101859. 101854.] - [ 102244. 102252. 102260. ..., 101886. 101863. 101855.]] - x: [ 353.05249023 353.08850098 353.12451172 353.16049194 353.19650269 - 353.23251343 353.26849365 353.30450439 353.34051514 353.37649536 - 353.4125061 353.44848633 353.48449707 353.52050781 353.55648804 - 353.59249878 353.62850952 353.66448975 353.70050049 353.73651123 - 353.77249146 353.8085022 353.84451294 353.88049316 353.91650391 - 353.95251465 353.98849487 354.02450562 354.06048584 354.09649658 - 354.13250732 354.16848755 354.20449829 354.24050903 354.27648926 - 354.3125 354.34851074 354.38449097 354.42050171 354.45651245 - 354.49249268 354.52185059 354.55010986 354.57736206 354.6036377 - 354.62893677 354.65332031 354.67684937 354.69949341 354.72131348 - 354.74234009 354.76263428 354.78216553 354.80099487 354.81915283 - 354.8366394 354.85348511 354.86972046 354.88537598 354.90045166 - 354.91497803 354.9289856 354.94250488 354.95599365 354.96951294 - 354.98300171 354.99649048 355.01000977 355.02349854 355.0369873 - 355.05050659 355.06399536 355.07751465 355.09100342 355.10449219 - 355.11801147 355.13150024 355.14498901 355.1585083 355.17199707 - 355.18548584 355.19900513 355.2124939 355.22601318 355.23950195 - 355.25299072 355.26651001 355.27999878 355.29348755 355.30700684 - 355.32049561 355.33401489 355.34750366 355.36099243 355.37451172 - 355.38800049 355.40148926 355.41500854 355.42849731 355.44198608 - 355.45550537 355.46899414 355.48251343 355.4960022 355.50949097 - 355.52301025 355.53649902 355.54998779 355.56350708 355.57699585 - 355.59051514 355.60400391 355.61749268 355.63101196 355.64450073 - 355.6579895 355.67150879 355.68499756 355.69848633 355.71200562 - 355.72549438 355.73901367 355.75250244 355.76599121 355.7795105 - 355.79299927 355.80648804 355.82000732 355.83349609 355.84698486 - 355.86050415 355.87399292 355.88751221 355.90100098 355.91448975 - 355.92800903 355.9414978 355.95498657 355.96850586 355.98199463 - 355.99551392 356.00900269 356.02249146 356.03601074 356.04949951 - 356.06298828 356.07650757 356.08999634 356.10348511 356.11700439 - 356.13049316 356.14401245 356.15750122 356.17098999 356.18450928 - 356.19799805 356.21148682 356.2250061 356.23849487 356.25201416 - 356.26550293 356.2789917 356.29251099 356.30599976 356.31948853 - 356.33300781 356.34649658 356.35998535 356.37350464 356.38699341 - 356.4005127 356.41400146 356.42749023 356.44100952 356.45449829 - 356.46798706 356.48150635 356.49499512 356.5085144 356.52200317 - 356.53549194 356.54901123 356.5625 356.57598877 356.58950806 - 356.60299683 356.6164856 356.63000488 356.64349365 356.65701294 - 356.67050171 356.68399048 356.69750977 356.71099854 356.7244873 - 356.73800659 356.75149536 356.76501465 356.77850342 356.79199219 - 356.80551147 356.81900024 356.83248901 356.8460083 356.85949707 - 356.87298584 356.88650513 356.8999939 356.91351318 356.92700195 - 356.94049072 356.95401001 356.96749878 356.98098755 356.99450684 - 357.00799561 357.02151489 357.03500366 357.04849243 357.06201172 - 357.07550049 357.08898926 357.10250854 357.11599731 357.12948608 - 357.14300537 357.15649414 357.17001343 357.1835022 357.19699097 - 357.21051025 357.22399902 357.23748779 357.25100708 357.26449585 - 357.27801514 357.29150391 357.30499268 357.31851196 357.33200073 - 357.3454895 357.35900879 357.37249756 357.38598633 357.39950562 - 357.41299438 357.42651367 357.44000244 357.45349121 357.4670105 - 357.48049927 357.49398804 357.50750732 357.52099609 357.53448486 - 357.54800415 357.56149292 357.57501221 357.58850098 357.60198975 - 357.61550903 357.6289978 357.64248657 357.65600586 357.66949463 - 357.68301392 357.69650269 357.70999146 357.72351074 357.73699951 - 357.75048828 357.76400757 357.77749634 357.79098511 357.80450439 - 357.81799316 357.83151245 357.84500122 357.85848999 357.87200928 - 357.88549805 357.89898682 357.9125061 357.92599487 357.93951416 - 357.95300293 357.9664917 357.98001099 357.99349976 358.00698853 - 358.02050781 358.03399658 358.04748535 358.06100464 358.07449341 - 358.0880127 358.10150146 358.11499023 358.12850952 358.14199829 - 358.15548706 358.16900635 358.18249512 358.1960144 358.20950317 - 358.22299194 358.23651123 358.25 358.26348877 358.27700806 - 358.29049683 358.3039856 358.31750488 358.33099365 358.34451294 - 358.35800171 358.37149048 358.38500977 358.39849854 358.4119873 - 358.42550659 358.43899536 358.45251465 358.46600342 358.47949219 - 358.49301147 358.50650024 358.51998901 358.5335083 358.54699707 - 358.56048584 358.57400513 358.5874939 358.60101318 358.61450195 - 358.62799072 358.64151001 358.65499878 358.66848755 358.68200684 - 358.69549561 358.70901489 358.72250366 358.73599243 358.74951172 - 358.76300049 358.77648926 358.79000854 358.80349731 358.81698608 - 358.83050537 358.84399414 358.85751343 358.8710022 358.88449097 - 358.89801025 358.91149902 358.92498779 358.93850708 358.95199585 - 358.96551514 358.97900391 358.99249268 359.00601196 359.01950073 - 359.0329895 359.04650879 359.05999756 359.07348633 359.08700562 - 359.10049438 359.11401367 359.12750244 359.14099121 359.1545105 - 359.16799927 359.18148804 359.19500732 359.20849609 359.22198486 - 359.23550415 359.24899292 359.26251221 359.27600098 359.28948975 - 359.30300903 359.3164978 359.32998657 359.34350586 359.35699463 - 359.37051392 359.38400269 359.39749146 359.41101074 359.42449951 - 359.43798828 359.45150757 359.46499634 359.47848511 359.49200439 - 359.50549316 359.51901245 359.53250122 359.54598999 359.55950928 - 359.57299805 359.58648682 359.6000061 359.61349487 359.62701416 - 359.64050293 359.6539917 359.66751099 359.68099976 359.69448853 - 359.70800781 359.72149658 359.73498535 359.74850464 359.76199341 - 359.7755127 359.78900146 359.80249023 359.81600952 359.82949829 - 359.84298706 359.85650635 359.86999512 359.8835144 359.89700317 - 359.91049194 359.92401123 359.9375 359.95098877 359.96450806 - 359.97799683 359.9914856 360.00500488 360.01849365 360.03201294 - 360.04550171 360.05899048 360.07250977 360.08599854 360.0994873 - 360.11300659 360.12649536 360.14001465 360.15350342 360.16699219 - 360.18051147 360.19400024 360.20748901 360.2210083 360.23449707 - 360.24798584 360.26150513 360.2749939 360.28851318 360.30200195 - 360.31549072 360.32901001 360.34249878 360.35598755 360.36950684 - 360.38299561 360.39651489 360.41000366 360.42349243 360.43701172 - 360.45050049 360.46398926 360.47750854 360.49099731 360.50448608 - 360.51800537 360.53149414 360.54501343 360.5585022 360.57199097 - 360.58551025 360.59899902 360.61248779 360.62600708 360.63949585 - 360.65301514 360.66650391 360.67999268 360.69351196 360.70700073 - 360.7204895 360.73400879 360.74749756 360.76098633 360.77450562 - 360.78799438 360.80151367 360.81500244 360.82849121 360.8420105 - 360.85549927 360.86898804 360.88250732 360.89599609 360.90948486 - 360.92300415 360.93649292 360.95001221 360.96350098 360.97698975 - 360.99050903 361.0039978 361.01748657 361.03100586 361.04449463 - 361.05801392 361.07150269 361.08499146 361.09851074 361.11199951 - 361.12548828 361.13900757 361.15249634 361.16598511 361.17950439 - 361.19299316 361.20651245 361.22000122 361.23348999 361.24700928 - 361.26049805 361.27398682 361.2875061 361.30099487 361.31451416 - 361.32800293 361.3414917 361.35501099 361.36849976 361.38198853 - 361.39550781 361.40899658 361.42248535 361.43600464 361.44949341 - 361.4630127 361.47650146 361.48999023 361.50350952 361.51699829 - 361.53048706 361.54400635 361.55749512 361.5710144 361.58450317 - 361.59799194 361.61151123 361.625 361.63848877 361.65200806 - 361.66549683 361.6789856 361.69250488 361.70599365 361.71951294 - 361.73300171 361.74649048 361.76000977 361.77349854 361.7869873 - 361.80050659 361.81399536 361.82751465 361.84100342 361.85449219 - 361.86801147 361.88150024 361.89498901 361.9085083 361.92199707 - 361.93548584 361.94900513 361.9624939 361.97601318 361.98950195 - 362.00299072 362.01651001 362.02999878 362.04348755 362.05700684 - 362.07049561 362.08401489 362.09750366 362.11099243 362.12451172 - 362.13800049 362.15148926 362.16500854 362.17849731 362.19198608 - 362.20550537 362.21899414 362.23251343 362.2460022 362.25949097 - 362.27301025 362.28649902 362.29998779 362.31350708 362.32699585 - 362.34051514 362.35400391 362.36749268 362.38101196 362.39450073 - 362.4079895 362.42150879 362.43499756 362.44848633 362.46200562 - 362.47549438 362.48901367 362.50250244 362.51599121 362.5295105 - 362.54299927 362.55648804 362.57000732 362.58349609 362.59698486 - 362.61050415 362.62399292 362.63751221 362.65100098 362.66448975 - 362.67800903 362.6914978 362.70498657 362.71850586 362.73199463 - 362.74551392 362.75900269 362.77249146 362.78601074 362.79949951 - 362.81298828 362.82650757 362.83999634 362.85348511 362.86700439 - 362.88049316 362.89401245 362.90750122 362.92098999 362.93450928 - 362.94799805 362.96148682 362.9750061 362.98849487 363.00201416 - 363.01550293 363.0289917 363.04251099 363.05599976 363.06948853 - 363.08300781 363.09649658 363.10998535 363.12350464 363.13699341 - 363.1505127 363.16400146 363.17749023 363.19100952 363.20449829 - 363.21798706 363.23150635 363.24499512 363.2585144 363.27200317 - 363.28549194 363.29901123 363.3125 363.32650757 363.34103394 - 363.35614014 363.37176514 363.38803101 363.40487671 363.42236328 - 363.44049072 363.45932007 363.47888184 363.49914551 363.52017212 - 363.54202271 363.56466675 363.58816528 363.61254883 363.63787842 - 363.66412354 363.69137573 363.71966553 363.74899292 363.78500366 - 363.8210144 363.85699463 363.89300537 363.9289856 363.96499634 - 364.00100708 364.0369873 364.07299805 364.10900879 364.14498901 - 364.18099976 364.2170105 364.25299072 364.28900146 364.32501221 - 364.36099243 364.39700317 364.43301392 364.46899414 364.50500488 - 364.54098511 364.57699585 364.61300659 364.64898682 364.68499756 - 364.7210083 364.75698853 364.79299927 364.82901001 364.86499023 - 364.90100098 364.93701172 364.97299194 365.00900269 365.04501343 - 365.08099365 365.11700439 365.15301514 365.18899536] - x_lower_bound: [ 353.03448486 353.07049561 353.10650635 353.14248657 353.17849731 - 353.21450806 353.25048828 353.28649902 353.32250977 353.35848999 - 353.39450073 353.43051147 353.4664917 353.50250244 353.53851318 - 353.57449341 353.61050415 353.64651489 353.68249512 353.71850586 - 353.75448608 353.79049683 353.82650757 353.86248779 353.89849854 - 353.93450928 353.9704895 354.00650024 354.04251099 354.07849121 - 354.11450195 354.1505127 354.18649292 354.22250366 354.2585144 - 354.29449463 354.33050537 354.3664856 354.40249634 354.43850708 - 354.4744873 354.50717163 354.53598022 354.56375122 354.59051514 - 354.61627197 354.6411438 354.66506958 354.68817139 354.71038818 - 354.73184204 354.75250244 354.7723999 354.79159546 354.81005859 - 354.82788086 354.84506226 354.86160278 354.87753296 354.89291382 - 354.90771484 354.92199707 354.9357605 354.94924927 354.96273804 - 354.97625732 354.98974609 355.00323486 355.01675415 355.03024292 - 355.04376221 355.05725098 355.07073975 355.08425903 355.0977478 - 355.11123657 355.12475586 355.13824463 355.15176392 355.16525269 - 355.17874146 355.19226074 355.20574951 355.21923828 355.23275757 - 355.24624634 355.25973511 355.27325439 355.28674316 355.30026245 - 355.31375122 355.32723999 355.34075928 355.35424805 355.36773682 - 355.3812561 355.39474487 355.40826416 355.42175293 355.4352417 - 355.44876099 355.46224976 355.47573853 355.48925781 355.50274658 - 355.51623535 355.52975464 355.54324341 355.5567627 355.57025146 - 355.58374023 355.59725952 355.61074829 355.62423706 355.63775635 - 355.65124512 355.6647644 355.67825317 355.69174194 355.70526123 - 355.71875 355.73223877 355.74575806 355.75924683 355.7727356 - 355.78625488 355.79974365 355.81326294 355.82675171 355.84024048 - 355.85375977 355.86724854 355.8807373 355.89425659 355.90774536 - 355.92126465 355.93475342 355.94824219 355.96176147 355.97525024 - 355.98873901 356.0022583 356.01574707 356.02923584 356.04275513 - 356.0562439 356.06976318 356.08325195 356.09674072 356.11026001 - 356.12374878 356.13723755 356.15075684 356.16424561 356.17776489 - 356.19125366 356.20474243 356.21826172 356.23175049 356.24523926 - 356.25875854 356.27224731 356.28573608 356.29925537 356.31274414 - 356.32626343 356.3397522 356.35324097 356.36676025 356.38024902 - 356.39373779 356.40725708 356.42074585 356.43426514 356.44775391 - 356.46124268 356.47476196 356.48825073 356.5017395 356.51525879 - 356.52874756 356.54223633 356.55575562 356.56924438 356.58276367 - 356.59625244 356.60974121 356.6232605 356.63674927 356.65023804 - 356.66375732 356.67724609 356.69073486 356.70425415 356.71774292 - 356.73126221 356.74475098 356.75823975 356.77175903 356.7852478 - 356.79873657 356.81225586 356.82574463 356.83926392 356.85275269 - 356.86624146 356.87976074 356.89324951 356.90673828 356.92025757 - 356.93374634 356.94723511 356.96075439 356.97424316 356.98776245 - 357.00125122 357.01473999 357.02825928 357.04174805 357.05523682 - 357.0687561 357.08224487 357.09576416 357.10925293 357.1227417 - 357.13626099 357.14974976 357.16323853 357.17675781 357.19024658 - 357.20373535 357.21725464 357.23074341 357.2442627 357.25775146 - 357.27124023 357.28475952 357.29824829 357.31173706 357.32525635 - 357.33874512 357.3522644 357.36575317 357.37924194 357.39276123 - 357.40625 357.41973877 357.43325806 357.44674683 357.4602356 - 357.47375488 357.48724365 357.50076294 357.51425171 357.52774048 - 357.54125977 357.55474854 357.5682373 357.58175659 357.59524536 - 357.60876465 357.62225342 357.63574219 357.64926147 357.66275024 - 357.67623901 357.6897583 357.70324707 357.71673584 357.73025513 - 357.7437439 357.75726318 357.77075195 357.78424072 357.79776001 - 357.81124878 357.82473755 357.83825684 357.85174561 357.86526489 - 357.87875366 357.89224243 357.90576172 357.91925049 357.93273926 - 357.94625854 357.95974731 357.97323608 357.98675537 358.00024414 - 358.01376343 358.0272522 358.04074097 358.05426025 358.06774902 - 358.08123779 358.09475708 358.10824585 358.12176514 358.13525391 - 358.14874268 358.16226196 358.17575073 358.1892395 358.20275879 - 358.21624756 358.22973633 358.24325562 358.25674438 358.27026367 - 358.28375244 358.29724121 358.3107605 358.32424927 358.33773804 - 358.35125732 358.36474609 358.37823486 358.39175415 358.40524292 - 358.41876221 358.43225098 358.44573975 358.45925903 358.4727478 - 358.48623657 358.49975586 358.51324463 358.52676392 358.54025269 - 358.55374146 358.56726074 358.58074951 358.59423828 358.60775757 - 358.62124634 358.63473511 358.64825439 358.66174316 358.67526245 - 358.68875122 358.70223999 358.71575928 358.72924805 358.74273682 - 358.7562561 358.76974487 358.78326416 358.79675293 358.8102417 - 358.82376099 358.83724976 358.85073853 358.86425781 358.87774658 - 358.89123535 358.90475464 358.91824341 358.9317627 358.94525146 - 358.95874023 358.97225952 358.98574829 358.99923706 359.01275635 - 359.02624512 359.0397644 359.05325317 359.06674194 359.08026123 - 359.09375 359.10723877 359.12075806 359.13424683 359.1477356 - 359.16125488 359.17474365 359.18826294 359.20175171 359.21524048 - 359.22875977 359.24224854 359.2557373 359.26925659 359.28274536 - 359.29626465 359.30975342 359.32324219 359.33676147 359.35025024 - 359.36373901 359.3772583 359.39074707 359.40423584 359.41775513 - 359.4312439 359.44476318 359.45825195 359.47174072 359.48526001 - 359.49874878 359.51223755 359.52575684 359.53924561 359.55276489 - 359.56625366 359.57974243 359.59326172 359.60675049 359.62023926 - 359.63375854 359.64724731 359.66073608 359.67425537 359.68774414 - 359.70126343 359.7147522 359.72824097 359.74176025 359.75524902 - 359.76873779 359.78225708 359.79574585 359.80926514 359.82275391 - 359.83624268 359.84976196 359.86325073 359.8767395 359.89025879 - 359.90374756 359.91723633 359.93075562 359.94424438 359.95776367 - 359.97125244 359.98474121 359.9982605 360.01174927 360.02523804 - 360.03875732 360.05224609 360.06573486 360.07925415 360.09274292 - 360.10626221 360.11975098 360.13323975 360.14675903 360.1602478 - 360.17373657 360.18725586 360.20074463 360.21426392 360.22775269 - 360.24124146 360.25476074 360.26824951 360.28173828 360.29525757 - 360.30874634 360.32223511 360.33575439 360.34924316 360.36276245 - 360.37625122 360.38973999 360.40325928 360.41674805 360.43023682 - 360.4437561 360.45724487 360.47076416 360.48425293 360.4977417 - 360.51126099 360.52474976 360.53823853 360.55175781 360.56524658 - 360.57873535 360.59225464 360.60574341 360.6192627 360.63275146 - 360.64624023 360.65975952 360.67324829 360.68673706 360.70025635 - 360.71374512 360.7272644 360.74075317 360.75424194 360.76776123 - 360.78125 360.79473877 360.80825806 360.82174683 360.8352356 - 360.84875488 360.86224365 360.87576294 360.88925171 360.90274048 - 360.91625977 360.92974854 360.9432373 360.95675659 360.97024536 - 360.98376465 360.99725342 361.01074219 361.02426147 361.03775024 - 361.05123901 361.0647583 361.07824707 361.09173584 361.10525513 - 361.1187439 361.13226318 361.14575195 361.15924072 361.17276001 - 361.18624878 361.19973755 361.21325684 361.22674561 361.24026489 - 361.25375366 361.26724243 361.28076172 361.29425049 361.30773926 - 361.32125854 361.33474731 361.34823608 361.36175537 361.37524414 - 361.38876343 361.4022522 361.41574097 361.42926025 361.44274902 - 361.45623779 361.46975708 361.48324585 361.49676514 361.51025391 - 361.52374268 361.53726196 361.55075073 361.5642395 361.57775879 - 361.59124756 361.60473633 361.61825562 361.63174438 361.64526367 - 361.65875244 361.67224121 361.6857605 361.69924927 361.71273804 - 361.72625732 361.73974609 361.75323486 361.76675415 361.78024292 - 361.79376221 361.80725098 361.82073975 361.83425903 361.8477478 - 361.86123657 361.87475586 361.88824463 361.90176392 361.91525269 - 361.92874146 361.94226074 361.95574951 361.96923828 361.98275757 - 361.99624634 362.00973511 362.02325439 362.03674316 362.05026245 - 362.06375122 362.07723999 362.09075928 362.10424805 362.11773682 - 362.1312561 362.14474487 362.15826416 362.17175293 362.1852417 - 362.19876099 362.21224976 362.22573853 362.23925781 362.25274658 - 362.26623535 362.27975464 362.29324341 362.3067627 362.32025146 - 362.33374023 362.34725952 362.36074829 362.37423706 362.38775635 - 362.40124512 362.4147644 362.42825317 362.44174194 362.45526123 - 362.46875 362.48223877 362.49575806 362.50924683 362.5227356 - 362.53625488 362.54974365 362.56326294 362.57675171 362.59024048 - 362.60375977 362.61724854 362.6307373 362.64425659 362.65774536 - 362.67126465 362.68475342 362.69824219 362.71176147 362.72525024 - 362.73873901 362.7522583 362.76574707 362.77923584 362.79275513 - 362.8062439 362.81976318 362.83325195 362.84674072 362.86026001 - 362.87374878 362.88723755 362.90075684 362.91424561 362.92776489 - 362.94125366 362.95474243 362.96826172 362.98175049 362.99523926 - 363.00875854 363.02224731 363.03573608 363.04925537 363.06274414 - 363.07626343 363.0897522 363.10324097 363.11676025 363.13024902 - 363.14373779 363.15725708 363.17074585 363.18426514 363.19775391 - 363.21124268 363.22476196 363.23825073 363.2517395 363.26525879 - 363.27874756 363.29223633 363.30575562 363.31951904 363.33377075 - 363.34857178 363.36395264 363.37991333 363.39645386 363.41360474 - 363.431427 363.44992065 363.46911621 363.48901367 363.50967407 - 363.53109741 363.55334473 363.57641602 363.60037231 363.62521362 - 363.65100098 363.67776489 363.70550537 363.73431396 363.76699829 - 363.80300903 363.83898926 363.875 363.91101074 363.94699097 - 363.98300171 364.01901245 364.05499268 364.09100342 364.12701416 - 364.16299438 364.19900513 364.23498535 364.27099609 364.30700684 - 364.34298706 364.3789978 364.41500854 364.45098877 364.48699951 - 364.52301025 364.55899048 364.59500122 364.63101196 364.66699219 - 364.70300293 364.73901367 364.7749939 364.81100464 364.84698486 - 364.88299561 364.91900635 364.95498657 364.99099731 365.02700806 - 365.06298828 365.09899902 365.13500977 365.17098999] - x_upper_bound: [ 353.07049561 353.10650635 353.14248657 353.17849731 353.21450806 - 353.25048828 353.28649902 353.32250977 353.35848999 353.39450073 - 353.43051147 353.4664917 353.50250244 353.53851318 353.57449341 - 353.61050415 353.64651489 353.68249512 353.71850586 353.75448608 - 353.79049683 353.82650757 353.86248779 353.89849854 353.93450928 - 353.9704895 354.00650024 354.04251099 354.07849121 354.11450195 - 354.1505127 354.18649292 354.22250366 354.2585144 354.29449463 - 354.33050537 354.3664856 354.40249634 354.43850708 354.4744873 - 354.50717163 354.53598022 354.56375122 354.59051514 354.61627197 - 354.6411438 354.66506958 354.68817139 354.71038818 354.73184204 - 354.75250244 354.7723999 354.79159546 354.81005859 354.82788086 - 354.84506226 354.86160278 354.87753296 354.89291382 354.90771484 - 354.92199707 354.9357605 354.94924927 354.96273804 354.97625732 - 354.98974609 355.00323486 355.01675415 355.03024292 355.04376221 - 355.05725098 355.07073975 355.08425903 355.0977478 355.11123657 - 355.12475586 355.13824463 355.15176392 355.16525269 355.17874146 - 355.19226074 355.20574951 355.21923828 355.23275757 355.24624634 - 355.25973511 355.27325439 355.28674316 355.30026245 355.31375122 - 355.32723999 355.34075928 355.35424805 355.36773682 355.3812561 - 355.39474487 355.40826416 355.42175293 355.4352417 355.44876099 - 355.46224976 355.47573853 355.48925781 355.50274658 355.51623535 - 355.52975464 355.54324341 355.5567627 355.57025146 355.58374023 - 355.59725952 355.61074829 355.62423706 355.63775635 355.65124512 - 355.6647644 355.67825317 355.69174194 355.70526123 355.71875 - 355.73223877 355.74575806 355.75924683 355.7727356 355.78625488 - 355.79974365 355.81326294 355.82675171 355.84024048 355.85375977 - 355.86724854 355.8807373 355.89425659 355.90774536 355.92126465 - 355.93475342 355.94824219 355.96176147 355.97525024 355.98873901 - 356.0022583 356.01574707 356.02923584 356.04275513 356.0562439 - 356.06976318 356.08325195 356.09674072 356.11026001 356.12374878 - 356.13723755 356.15075684 356.16424561 356.17776489 356.19125366 - 356.20474243 356.21826172 356.23175049 356.24523926 356.25875854 - 356.27224731 356.28573608 356.29925537 356.31274414 356.32626343 - 356.3397522 356.35324097 356.36676025 356.38024902 356.39373779 - 356.40725708 356.42074585 356.43426514 356.44775391 356.46124268 - 356.47476196 356.48825073 356.5017395 356.51525879 356.52874756 - 356.54223633 356.55575562 356.56924438 356.58276367 356.59625244 - 356.60974121 356.6232605 356.63674927 356.65023804 356.66375732 - 356.67724609 356.69073486 356.70425415 356.71774292 356.73126221 - 356.74475098 356.75823975 356.77175903 356.7852478 356.79873657 - 356.81225586 356.82574463 356.83926392 356.85275269 356.86624146 - 356.87976074 356.89324951 356.90673828 356.92025757 356.93374634 - 356.94723511 356.96075439 356.97424316 356.98776245 357.00125122 - 357.01473999 357.02825928 357.04174805 357.05523682 357.0687561 - 357.08224487 357.09576416 357.10925293 357.1227417 357.13626099 - 357.14974976 357.16323853 357.17675781 357.19024658 357.20373535 - 357.21725464 357.23074341 357.2442627 357.25775146 357.27124023 - 357.28475952 357.29824829 357.31173706 357.32525635 357.33874512 - 357.3522644 357.36575317 357.37924194 357.39276123 357.40625 - 357.41973877 357.43325806 357.44674683 357.4602356 357.47375488 - 357.48724365 357.50076294 357.51425171 357.52774048 357.54125977 - 357.55474854 357.5682373 357.58175659 357.59524536 357.60876465 - 357.62225342 357.63574219 357.64926147 357.66275024 357.67623901 - 357.6897583 357.70324707 357.71673584 357.73025513 357.7437439 - 357.75726318 357.77075195 357.78424072 357.79776001 357.81124878 - 357.82473755 357.83825684 357.85174561 357.86526489 357.87875366 - 357.89224243 357.90576172 357.91925049 357.93273926 357.94625854 - 357.95974731 357.97323608 357.98675537 358.00024414 358.01376343 - 358.0272522 358.04074097 358.05426025 358.06774902 358.08123779 - 358.09475708 358.10824585 358.12176514 358.13525391 358.14874268 - 358.16226196 358.17575073 358.1892395 358.20275879 358.21624756 - 358.22973633 358.24325562 358.25674438 358.27026367 358.28375244 - 358.29724121 358.3107605 358.32424927 358.33773804 358.35125732 - 358.36474609 358.37823486 358.39175415 358.40524292 358.41876221 - 358.43225098 358.44573975 358.45925903 358.4727478 358.48623657 - 358.49975586 358.51324463 358.52676392 358.54025269 358.55374146 - 358.56726074 358.58074951 358.59423828 358.60775757 358.62124634 - 358.63473511 358.64825439 358.66174316 358.67526245 358.68875122 - 358.70223999 358.71575928 358.72924805 358.74273682 358.7562561 - 358.76974487 358.78326416 358.79675293 358.8102417 358.82376099 - 358.83724976 358.85073853 358.86425781 358.87774658 358.89123535 - 358.90475464 358.91824341 358.9317627 358.94525146 358.95874023 - 358.97225952 358.98574829 358.99923706 359.01275635 359.02624512 - 359.0397644 359.05325317 359.06674194 359.08026123 359.09375 - 359.10723877 359.12075806 359.13424683 359.1477356 359.16125488 - 359.17474365 359.18826294 359.20175171 359.21524048 359.22875977 - 359.24224854 359.2557373 359.26925659 359.28274536 359.29626465 - 359.30975342 359.32324219 359.33676147 359.35025024 359.36373901 - 359.3772583 359.39074707 359.40423584 359.41775513 359.4312439 - 359.44476318 359.45825195 359.47174072 359.48526001 359.49874878 - 359.51223755 359.52575684 359.53924561 359.55276489 359.56625366 - 359.57974243 359.59326172 359.60675049 359.62023926 359.63375854 - 359.64724731 359.66073608 359.67425537 359.68774414 359.70126343 - 359.7147522 359.72824097 359.74176025 359.75524902 359.76873779 - 359.78225708 359.79574585 359.80926514 359.82275391 359.83624268 - 359.84976196 359.86325073 359.8767395 359.89025879 359.90374756 - 359.91723633 359.93075562 359.94424438 359.95776367 359.97125244 - 359.98474121 359.9982605 360.01174927 360.02523804 360.03875732 - 360.05224609 360.06573486 360.07925415 360.09274292 360.10626221 - 360.11975098 360.13323975 360.14675903 360.1602478 360.17373657 - 360.18725586 360.20074463 360.21426392 360.22775269 360.24124146 - 360.25476074 360.26824951 360.28173828 360.29525757 360.30874634 - 360.32223511 360.33575439 360.34924316 360.36276245 360.37625122 - 360.38973999 360.40325928 360.41674805 360.43023682 360.4437561 - 360.45724487 360.47076416 360.48425293 360.4977417 360.51126099 - 360.52474976 360.53823853 360.55175781 360.56524658 360.57873535 - 360.59225464 360.60574341 360.6192627 360.63275146 360.64624023 - 360.65975952 360.67324829 360.68673706 360.70025635 360.71374512 - 360.7272644 360.74075317 360.75424194 360.76776123 360.78125 - 360.79473877 360.80825806 360.82174683 360.8352356 360.84875488 - 360.86224365 360.87576294 360.88925171 360.90274048 360.91625977 - 360.92974854 360.9432373 360.95675659 360.97024536 360.98376465 - 360.99725342 361.01074219 361.02426147 361.03775024 361.05123901 - 361.0647583 361.07824707 361.09173584 361.10525513 361.1187439 - 361.13226318 361.14575195 361.15924072 361.17276001 361.18624878 - 361.19973755 361.21325684 361.22674561 361.24026489 361.25375366 - 361.26724243 361.28076172 361.29425049 361.30773926 361.32125854 - 361.33474731 361.34823608 361.36175537 361.37524414 361.38876343 - 361.4022522 361.41574097 361.42926025 361.44274902 361.45623779 - 361.46975708 361.48324585 361.49676514 361.51025391 361.52374268 - 361.53726196 361.55075073 361.5642395 361.57775879 361.59124756 - 361.60473633 361.61825562 361.63174438 361.64526367 361.65875244 - 361.67224121 361.6857605 361.69924927 361.71273804 361.72625732 - 361.73974609 361.75323486 361.76675415 361.78024292 361.79376221 - 361.80725098 361.82073975 361.83425903 361.8477478 361.86123657 - 361.87475586 361.88824463 361.90176392 361.91525269 361.92874146 - 361.94226074 361.95574951 361.96923828 361.98275757 361.99624634 - 362.00973511 362.02325439 362.03674316 362.05026245 362.06375122 - 362.07723999 362.09075928 362.10424805 362.11773682 362.1312561 - 362.14474487 362.15826416 362.17175293 362.1852417 362.19876099 - 362.21224976 362.22573853 362.23925781 362.25274658 362.26623535 - 362.27975464 362.29324341 362.3067627 362.32025146 362.33374023 - 362.34725952 362.36074829 362.37423706 362.38775635 362.40124512 - 362.4147644 362.42825317 362.44174194 362.45526123 362.46875 - 362.48223877 362.49575806 362.50924683 362.5227356 362.53625488 - 362.54974365 362.56326294 362.57675171 362.59024048 362.60375977 - 362.61724854 362.6307373 362.64425659 362.65774536 362.67126465 - 362.68475342 362.69824219 362.71176147 362.72525024 362.73873901 - 362.7522583 362.76574707 362.77923584 362.79275513 362.8062439 - 362.81976318 362.83325195 362.84674072 362.86026001 362.87374878 - 362.88723755 362.90075684 362.91424561 362.92776489 362.94125366 - 362.95474243 362.96826172 362.98175049 362.99523926 363.00875854 - 363.02224731 363.03573608 363.04925537 363.06274414 363.07626343 - 363.0897522 363.10324097 363.11676025 363.13024902 363.14373779 - 363.15725708 363.17074585 363.18426514 363.19775391 363.21124268 - 363.22476196 363.23825073 363.2517395 363.26525879 363.27874756 - 363.29223633 363.30575562 363.31951904 363.33377075 363.34857178 - 363.36395264 363.37991333 363.39645386 363.41360474 363.431427 - 363.44992065 363.46911621 363.48901367 363.50967407 363.53109741 - 363.55334473 363.57641602 363.60037231 363.62521362 363.65100098 - 363.67776489 363.70550537 363.73431396 363.76699829 363.80300903 - 363.83898926 363.875 363.91101074 363.94699097 363.98300171 - 364.01901245 364.05499268 364.09100342 364.12701416 364.16299438 - 364.19900513 364.23498535 364.27099609 364.30700684 364.34298706 - 364.3789978 364.41500854 364.45098877 364.48699951 364.52301025 - 364.55899048 364.59500122 364.63101196 364.66699219 364.70300293 - 364.73901367 364.7749939 364.81100464 364.84698486 364.88299561 - 364.91900635 364.95498657 364.99099731 365.02700806 365.06298828 - 365.09899902 365.13500977 365.17098999 365.20700073] - y: [ -5.59320021e+00 -5.55719995e+00 -5.52120018e+00 -5.48519993e+00 - -5.44920015e+00 -5.41319990e+00 -5.37720013e+00 -5.34119987e+00 - -5.30520010e+00 -5.26919985e+00 -5.23320007e+00 -5.19719982e+00 - -5.16120005e+00 -5.12519979e+00 -5.08920002e+00 -5.05319977e+00 - -5.01719999e+00 -4.98120022e+00 -4.94519997e+00 -4.90920019e+00 - -4.87319994e+00 -4.83720016e+00 -4.80119991e+00 -4.76520014e+00 - -4.72919989e+00 -4.69320011e+00 -4.65719986e+00 -4.62120008e+00 - -4.58519983e+00 -4.54920006e+00 -4.51319981e+00 -4.47720003e+00 - -4.44119978e+00 -4.40520000e+00 -4.36920023e+00 -4.33319998e+00 - -4.29720020e+00 -4.26119995e+00 -4.22520018e+00 -4.19377995e+00 - -4.16359854e+00 -4.13460732e+00 -4.10675907e+00 -4.08000851e+00 - -4.05431318e+00 -4.02963066e+00 -4.00592136e+00 -3.98314714e+00 - -3.96127057e+00 -3.94025683e+00 -3.92007136e+00 -3.90068197e+00 - -3.88205695e+00 -3.86416626e+00 -3.84698105e+00 -3.83047342e+00 - -3.81461668e+00 -3.79938507e+00 -3.78475404e+00 -3.77069998e+00 - -3.75720000e+00 -3.74370003e+00 -3.73020005e+00 -3.71670008e+00 - -3.70320010e+00 -3.68969989e+00 -3.67619991e+00 -3.66269994e+00 - -3.64919996e+00 -3.63569999e+00 -3.62220001e+00 -3.60870004e+00 - -3.59520006e+00 -3.58170009e+00 -3.56820011e+00 -3.55469990e+00 - -3.54119992e+00 -3.52769995e+00 -3.51419997e+00 -3.50070000e+00 - -3.48720002e+00 -3.47370005e+00 -3.46020007e+00 -3.44670010e+00 - -3.43319988e+00 -3.41969991e+00 -3.40619993e+00 -3.39269996e+00 - -3.37919998e+00 -3.36570001e+00 -3.35220003e+00 -3.33870006e+00 - -3.32520008e+00 -3.31170011e+00 -3.29819989e+00 -3.28469992e+00 - -3.27119994e+00 -3.25769997e+00 -3.24419999e+00 -3.23070002e+00 - -3.21720004e+00 -3.20370007e+00 -3.19020009e+00 -3.17670012e+00 - -3.16319990e+00 -3.14969993e+00 -3.13619995e+00 -3.12269998e+00 - -3.10920000e+00 -3.09570003e+00 -3.08220005e+00 -3.06870008e+00 - -3.05520010e+00 -3.04169989e+00 -3.02819991e+00 -3.01469994e+00 - -3.00119996e+00 -2.98769999e+00 -2.97420001e+00 -2.96070004e+00 - -2.94720006e+00 -2.93370008e+00 -2.92020011e+00 -2.90669990e+00 - -2.89319992e+00 -2.87969995e+00 -2.86619997e+00 -2.85270000e+00 - -2.83920002e+00 -2.82570004e+00 -2.81220007e+00 -2.79870009e+00 - -2.78520012e+00 -2.77169991e+00 -2.75819993e+00 -2.74469995e+00 - -2.73119998e+00 -2.71770000e+00 -2.70420003e+00 -2.69070005e+00 - -2.67720008e+00 -2.66370010e+00 -2.65019989e+00 -2.63669991e+00 - -2.62319994e+00 -2.60969996e+00 -2.59619999e+00 -2.58270001e+00 - -2.56920004e+00 -2.55570006e+00 -2.54220009e+00 -2.52870011e+00 - -2.51519990e+00 -2.50169992e+00 -2.48819995e+00 -2.47469997e+00 - -2.46120000e+00 -2.44770002e+00 -2.43420005e+00 -2.42070007e+00 - -2.40720010e+00 -2.39369988e+00 -2.38019991e+00 -2.36669993e+00 - -2.35319996e+00 -2.33969998e+00 -2.32620001e+00 -2.31270003e+00 - -2.29920006e+00 -2.28570008e+00 -2.27220011e+00 -2.25869989e+00 - -2.24519992e+00 -2.23169994e+00 -2.21819997e+00 -2.20469999e+00 - -2.19120002e+00 -2.17770004e+00 -2.16420007e+00 -2.15070009e+00 - -2.13720012e+00 -2.12369990e+00 -2.11019993e+00 -2.09669995e+00 - -2.08319998e+00 -2.06970000e+00 -2.05620003e+00 -2.04270005e+00 - -2.02920008e+00 -2.01570010e+00 -2.00219989e+00 -1.98870003e+00 - -1.97520006e+00 -1.96169996e+00 -1.94819999e+00 -1.93470001e+00 - -1.92120004e+00 -1.90769994e+00 -1.89419997e+00 -1.88069999e+00 - -1.86720002e+00 -1.85370004e+00 -1.84019995e+00 -1.82669997e+00 - -1.81320000e+00 -1.79970002e+00 -1.78620005e+00 -1.77269995e+00 - -1.75919998e+00 -1.74570000e+00 -1.73220003e+00 -1.71870005e+00 - -1.70519996e+00 -1.69169998e+00 -1.67820001e+00 -1.66470003e+00 - -1.65120006e+00 -1.63769996e+00 -1.62419999e+00 -1.61070001e+00 - -1.59720004e+00 -1.58369994e+00 -1.57019997e+00 -1.55669999e+00 - -1.54320002e+00 -1.52970004e+00 -1.51619995e+00 -1.50269997e+00 - -1.48920000e+00 -1.47570002e+00 -1.46220005e+00 -1.44869995e+00 - -1.43519998e+00 -1.42170000e+00 -1.40820003e+00 -1.39470005e+00 - -1.38119996e+00 -1.36769998e+00 -1.35420001e+00 -1.34070003e+00 - -1.32720006e+00 -1.31369996e+00 -1.30019999e+00 -1.28670001e+00 - -1.27320004e+00 -1.25969994e+00 -1.24619997e+00 -1.23269999e+00 - -1.21920002e+00 -1.20570004e+00 -1.19219995e+00 -1.17869997e+00 - -1.16520000e+00 -1.15170002e+00 -1.13820004e+00 -1.12469995e+00 - -1.11119998e+00 -1.09770000e+00 -1.08420002e+00 -1.07070005e+00 - -1.05719995e+00 -1.04369998e+00 -1.03020000e+00 -1.01670003e+00 - -1.00320005e+00 -9.89700019e-01 -9.76199985e-01 -9.62700009e-01 - -9.49199975e-01 -9.35699999e-01 -9.22200024e-01 -9.08699989e-01 - -8.95200014e-01 -8.81699979e-01 -8.68200004e-01 -8.54700029e-01 - -8.41199994e-01 -8.27700019e-01 -8.14199984e-01 -8.00700009e-01 - -7.87199974e-01 -7.73699999e-01 -7.60200024e-01 -7.46699989e-01 - -7.33200014e-01 -7.19699979e-01 -7.06200004e-01 -6.92700028e-01 - -6.79199994e-01 -6.65700018e-01 -6.52199984e-01 -6.38700008e-01 - -6.25199974e-01 -6.11699998e-01 -5.98200023e-01 -5.84699988e-01 - -5.71200013e-01 -5.57699978e-01 -5.44200003e-01 -5.30700028e-01 - -5.17199993e-01 -5.03700018e-01 -4.90200013e-01 -4.76700008e-01 - -4.63200003e-01 -4.49699998e-01 -4.36199993e-01 -4.22699988e-01 - -4.09200013e-01 -3.95700008e-01 -3.82200003e-01 -3.68699998e-01 - -3.55199993e-01 -3.41699988e-01 -3.28200012e-01 -3.14700007e-01 - -3.01200002e-01 -2.87699997e-01 -2.74199992e-01 -2.60699987e-01 - -2.47199997e-01 -2.33700007e-01 -2.20200002e-01 -2.06699997e-01 - -1.93200007e-01 -1.79700002e-01 -1.66199997e-01 -1.52700007e-01 - -1.39200002e-01 -1.25699997e-01 -1.12199999e-01 -9.87000018e-02 - -8.51999968e-02 -7.16999993e-02 -5.82000017e-02 -4.47000004e-02 - -3.11999992e-02 -1.76999997e-02 -4.19999985e-03 9.30000003e-03 - 2.28000004e-02 3.62999998e-02 4.98000011e-02 6.32999986e-02 - 7.68000036e-02 9.03000012e-02 1.03799999e-01 1.17299996e-01 - 1.30799994e-01 1.44299999e-01 1.57800004e-01 1.71299994e-01 - 1.84799999e-01 1.98300004e-01 2.11799994e-01 2.25299999e-01 - 2.38800004e-01 2.52299994e-01 2.65799999e-01 2.79300004e-01 - 2.92800009e-01 3.06300014e-01 3.19799989e-01 3.33299994e-01 - 3.46799999e-01 3.60300004e-01 3.73800009e-01 3.87300014e-01 - 4.00799990e-01 4.14299995e-01 4.27800000e-01 4.41300005e-01 - 4.54800010e-01 4.68300015e-01 4.81799990e-01 4.95299995e-01 - 5.08800030e-01 5.22300005e-01 5.35799980e-01 5.49300015e-01 - 5.62799990e-01 5.76300025e-01 5.89800000e-01 6.03299975e-01 - 6.16800010e-01 6.30299985e-01 6.43800020e-01 6.57299995e-01 - 6.70799971e-01 6.84300005e-01 6.97799981e-01 7.11300015e-01 - 7.24799991e-01 7.38300025e-01 7.51800001e-01 7.65299976e-01 - 7.78800011e-01 7.92299986e-01 8.05800021e-01 8.19299996e-01 - 8.32799971e-01 8.46300006e-01 8.59799981e-01 8.73300016e-01 - 8.86799991e-01 9.00300026e-01 9.13800001e-01 9.27299976e-01 - 9.40800011e-01 9.54299986e-01 9.67800021e-01 9.81299996e-01 - 9.94799972e-01 1.00829995e+00 1.02180004e+00 1.03530002e+00 - 1.04879999e+00 1.06229997e+00 1.07579994e+00 1.08930004e+00 - 1.10280001e+00 1.11629999e+00 1.12979996e+00 1.14330006e+00 - 1.15680003e+00 1.17030001e+00 1.18379998e+00 1.19729996e+00 - 1.21080005e+00 1.22430003e+00 1.23780000e+00 1.25129998e+00 - 1.26479995e+00 1.27830005e+00 1.29180002e+00 1.30530000e+00 - 1.31879997e+00 1.33229995e+00 1.34580004e+00 1.35930002e+00 - 1.37279999e+00 1.38629997e+00 1.39979994e+00 1.41330004e+00 - 1.42680001e+00 1.44029999e+00 1.45379996e+00 1.46730006e+00 - 1.48080003e+00 1.49430001e+00 1.50779998e+00 1.52129996e+00 - 1.53480005e+00 1.54830003e+00 1.56180000e+00 1.57529998e+00 - 1.58879995e+00 1.60230005e+00 1.61580002e+00 1.62930000e+00 - 1.64279997e+00 1.65629995e+00 1.66980004e+00 1.68330002e+00 - 1.69679999e+00 1.71029997e+00 1.72379994e+00 1.73730004e+00 - 1.75080001e+00 1.76429999e+00 1.77779996e+00 1.79130006e+00 - 1.80480003e+00 1.81830001e+00 1.83179998e+00 1.84529996e+00 - 1.85880005e+00 1.87230003e+00 1.88580000e+00 1.89929998e+00 - 1.91279995e+00 1.92630005e+00 1.93980002e+00 1.95330000e+00 - 1.96679997e+00 1.98029995e+00 1.99380004e+00 2.00729990e+00 - 2.02080011e+00 2.03430009e+00 2.04780006e+00 2.06130004e+00 - 2.07480001e+00 2.08829999e+00 2.10179996e+00 2.11529994e+00 - 2.12879992e+00 2.14229989e+00 2.15580010e+00 2.16930008e+00 - 2.18280005e+00 2.19630003e+00 2.20980000e+00 2.22329998e+00 - 2.23679996e+00 2.25029993e+00 2.26379991e+00 2.27729988e+00 - 2.29080009e+00 2.30430007e+00 2.31780005e+00 2.33130002e+00 - 2.34480000e+00 2.35829997e+00 2.37179995e+00 2.38529992e+00 - 2.39879990e+00 2.41230011e+00 2.42580009e+00 2.43930006e+00 - 2.45280004e+00 2.46630001e+00 2.47979999e+00 2.49329996e+00 - 2.50679994e+00 2.52029991e+00 2.53379989e+00 2.54730010e+00 - 2.56080008e+00 2.57430005e+00 2.58780003e+00 2.60130000e+00 - 2.61479998e+00 2.62829995e+00 2.64179993e+00 2.65529990e+00 - 2.66880012e+00 2.68230009e+00 2.69580007e+00 2.70930004e+00 - 2.72280002e+00 2.73629999e+00 2.74979997e+00 2.76329994e+00 - 2.77679992e+00 2.79029989e+00 2.80380011e+00 2.81730008e+00 - 2.83080006e+00 2.84430003e+00 2.85780001e+00 2.87129998e+00 - 2.88479996e+00 2.89829993e+00 2.91179991e+00 2.92529988e+00 - 2.93880010e+00 2.95230007e+00 2.96580005e+00 2.97930002e+00 - 2.99280000e+00 3.00629997e+00 3.01979995e+00 3.03329992e+00 - 3.04679990e+00 3.06030011e+00 3.07380009e+00 3.08730006e+00 - 3.10080004e+00 3.11430001e+00 3.12779999e+00 3.14129996e+00 - 3.15479994e+00 3.16829991e+00 3.18179989e+00 3.19530010e+00 - 3.20880008e+00 3.22230005e+00 3.23580003e+00 3.24930000e+00 - 3.26279998e+00 3.27629995e+00 3.28979993e+00 3.30329990e+00 - 3.31680012e+00 3.33030009e+00 3.34380007e+00 3.35730004e+00 - 3.37080002e+00 3.38429999e+00 3.39779997e+00 3.41129994e+00 - 3.42479992e+00 3.43829989e+00 3.45180011e+00 3.46530008e+00 - 3.47880006e+00 3.49230003e+00 3.50580001e+00 3.51929998e+00 - 3.53279996e+00 3.54629993e+00 3.55979991e+00 3.57329988e+00 - 3.58680010e+00 3.60030007e+00 3.61380005e+00 3.62730002e+00 - 3.64080000e+00 3.65429997e+00 3.66779995e+00 3.68129992e+00 - 3.69479990e+00 3.70830011e+00 3.72180009e+00 3.73530006e+00 - 3.74880004e+00 3.76230001e+00 3.77579999e+00 3.78929996e+00 - 3.80279994e+00 3.81629992e+00 3.82979989e+00 3.84330010e+00 - 3.85680008e+00 3.87030005e+00 3.88380003e+00 3.89730000e+00 - 3.91079998e+00 3.92429996e+00 3.93779993e+00 3.95129991e+00 - 3.96479988e+00 3.97830009e+00 3.99180007e+00 4.00530005e+00 - 4.01879978e+00 4.03230000e+00 4.04580021e+00 4.05929995e+00 - 4.07280016e+00 4.08629990e+00 4.09980011e+00 4.11329985e+00 - 4.12680006e+00 4.14029980e+00 4.15380001e+00 4.16730022e+00 - 4.18079996e+00 4.19430017e+00 4.20779991e+00 4.22130013e+00 - 4.23479986e+00 4.24830008e+00 4.26179981e+00 4.27530003e+00 - 4.28879976e+00 4.30229998e+00 4.31580019e+00 4.32929993e+00 - 4.34280014e+00 4.35629988e+00 4.36980009e+00 4.38329983e+00 - 4.39680004e+00 4.41029978e+00 4.42379999e+00 4.43730021e+00 - 4.45079994e+00 4.46430016e+00 4.47779989e+00 4.49130011e+00 - 4.50479984e+00 4.51830006e+00 4.53179979e+00 4.54530001e+00 - 4.55880022e+00 4.57229996e+00 4.58580017e+00 4.59929991e+00 - 4.61280012e+00 4.62629986e+00 4.63980007e+00 4.65329981e+00 - 4.66680002e+00 4.68030024e+00 4.69379997e+00 4.70730019e+00 - 4.72079992e+00 4.73430014e+00 4.74779987e+00 4.76130009e+00 - 4.77479982e+00 4.78830004e+00 4.80179977e+00 4.81529999e+00 - 4.82880020e+00 4.84229994e+00 4.85580015e+00 4.86929989e+00 - 4.88280010e+00 4.89629984e+00 4.90980005e+00 4.92329979e+00 - 4.93680000e+00 4.95030022e+00 4.96379995e+00 4.97730017e+00 - 4.99079990e+00 5.00430012e+00 5.01779985e+00 5.03130007e+00 - 5.04479980e+00 5.05830002e+00 5.07180023e+00 5.08529997e+00 - 5.09880018e+00 5.11229992e+00 5.12580013e+00 5.13929987e+00 - 5.15280008e+00 5.16629982e+00 5.17980003e+00 5.19329977e+00 - 5.20679998e+00 5.22030020e+00 5.23379993e+00 5.24730015e+00 - 5.26079988e+00 5.27430010e+00 5.28779984e+00 5.30130005e+00 - 5.31479979e+00 5.32830000e+00 5.34180021e+00 5.35529995e+00 - 5.36880016e+00 5.38229990e+00 5.39580011e+00 5.40929985e+00 - 5.42280006e+00 5.43629980e+00 5.44980001e+00 5.46330023e+00 - 5.47679996e+00 5.49030018e+00 5.50379992e+00 5.51730013e+00 - 5.53079987e+00 5.54430008e+00 5.55779982e+00 5.57130003e+00 - 5.58479977e+00 5.59829998e+00 5.61180019e+00 5.62529993e+00 - 5.63880014e+00 5.65229988e+00 5.66580009e+00 5.67929983e+00 - 5.69280005e+00 5.70629978e+00 5.71980000e+00 5.73330021e+00 - 5.74679995e+00 5.76030016e+00 5.77379990e+00 5.78730011e+00 - 5.80079985e+00 5.81430006e+00 5.82779980e+00 5.84130001e+00 - 5.85480022e+00 5.86829996e+00 5.88180017e+00 5.89529991e+00 - 5.90880013e+00 5.92229986e+00 5.93580008e+00 5.94929981e+00 - 5.96280003e+00 5.97629976e+00 5.98979998e+00 6.00330019e+00 - 6.01679993e+00 6.03030014e+00 6.04379988e+00 6.05730009e+00 - 6.07079983e+00 6.08430004e+00 6.09779978e+00 6.11129999e+00 - 6.12480021e+00 6.13829994e+00 6.15180016e+00 6.16529989e+00 - 6.17880011e+00 6.19229984e+00 6.20580006e+00 6.21929979e+00 - 6.23280001e+00 6.24630022e+00 6.25979996e+00 6.27330017e+00 - 6.28679991e+00 6.30030012e+00 6.31379986e+00 6.32730007e+00 - 6.34079981e+00 6.35430002e+00 6.36780024e+00 6.38129997e+00 - 6.39480019e+00 6.40829992e+00 6.42180014e+00 6.43529987e+00 - 6.44880009e+00 6.46229982e+00 6.47580004e+00 6.48929977e+00 - 6.50279999e+00 6.51630020e+00 6.52979994e+00 6.54330015e+00 - 6.55679989e+00 6.57030010e+00 6.58379984e+00 6.59730005e+00 - 6.61079979e+00 6.62430000e+00 6.63780022e+00 6.65129995e+00 - 6.66480017e+00 6.67829990e+00 6.69180012e+00 6.70529985e+00 - 6.71880007e+00 6.73229980e+00 6.74580002e+00 6.75930023e+00 - 6.77279997e+00 6.78630018e+00 6.79979992e+00 6.81330013e+00 - 6.82679987e+00 6.84030008e+00 6.85379982e+00 6.86730003e+00 - 6.88079977e+00 6.89429998e+00 6.90780020e+00 6.92129993e+00 - 6.93480015e+00 6.94829988e+00 6.96180010e+00 6.97529984e+00 - 6.98880005e+00 7.00229979e+00 7.01580000e+00 7.02930021e+00 - 7.04279995e+00 7.05630016e+00 7.06979990e+00 7.08330011e+00 - 7.09679985e+00 7.11030006e+00 7.12379980e+00 7.13730001e+00 - 7.15080023e+00 7.16485405e+00 7.17948532e+00 7.19471693e+00 - 7.21057367e+00 7.22708130e+00 7.24426651e+00 7.26215696e+00 - 7.28078175e+00 7.30017138e+00 7.32035685e+00 7.34137058e+00 - 7.36324692e+00 7.38602161e+00 7.40973091e+00 7.43441296e+00 - 7.46010876e+00 7.48685884e+00 7.51470709e+00 7.54369831e+00 - 7.57387972e+00 7.60529995e+00 7.64130020e+00 7.67729998e+00 - 7.71330023e+00 7.74930000e+00 7.78529978e+00 7.82130003e+00 - 7.85729980e+00 7.89330006e+00 7.92929983e+00 7.96530008e+00 - 8.00129986e+00 8.03730011e+00 8.07330036e+00 8.10929966e+00 - 8.14529991e+00 8.18130016e+00 8.21730042e+00 8.25329971e+00 - 8.28929996e+00 8.32530022e+00 8.36130047e+00 8.39729977e+00 - 8.43330002e+00 8.46930027e+00 8.50529957e+00 8.54129982e+00 - 8.57730007e+00 8.61330032e+00 8.64929962e+00 8.68529987e+00 - 8.72130013e+00 8.75730038e+00 8.79329967e+00 8.82929993e+00 - 8.86530018e+00 8.90130043e+00 8.93729973e+00 8.97329998e+00] - y_lower_bound: [ -5.61120033e+00 -5.57520008e+00 -5.53919983e+00 -5.50320005e+00 - -5.46719980e+00 -5.43120003e+00 -5.39519978e+00 -5.35920000e+00 - -5.32320023e+00 -5.28719997e+00 -5.25120020e+00 -5.21519995e+00 - -5.17920017e+00 -5.14319992e+00 -5.10720015e+00 -5.07119989e+00 - -5.03520012e+00 -4.99919987e+00 -4.96320009e+00 -4.92719984e+00 - -4.89120007e+00 -4.85519981e+00 -4.81920004e+00 -4.78319979e+00 - -4.74720001e+00 -4.71120024e+00 -4.67519999e+00 -4.63920021e+00 - -4.60319996e+00 -4.56720018e+00 -4.53119993e+00 -4.49520016e+00 - -4.45919991e+00 -4.42320013e+00 -4.38719988e+00 -4.35120010e+00 - -4.31519985e+00 -4.27920008e+00 -4.24319983e+00 -4.20948982e+00 - -4.17868900e+00 -4.14910269e+00 -4.12068319e+00 -4.09338379e+00 - -4.06716108e+00 -4.04197168e+00 -4.01777601e+00 -3.99453425e+00 - -3.97220898e+00 -3.95076370e+00 -3.93016410e+00 -3.91037679e+00 - -3.89136934e+00 -3.87311172e+00 -3.85557365e+00 -3.83872724e+00 - -3.82254505e+00 -3.80700088e+00 -3.79206967e+00 -3.77772713e+00 - -3.76395011e+00 -3.75044990e+00 -3.73694992e+00 -3.72344995e+00 - -3.70994997e+00 -3.69645000e+00 -3.68295002e+00 -3.66945004e+00 - -3.65595007e+00 -3.64245009e+00 -3.62895012e+00 -3.61544991e+00 - -3.60194993e+00 -3.58844995e+00 -3.57494998e+00 -3.56145000e+00 - -3.54795003e+00 -3.53445005e+00 -3.52095008e+00 -3.50745010e+00 - -3.49394989e+00 -3.48044991e+00 -3.46694994e+00 -3.45344996e+00 - -3.43994999e+00 -3.42645001e+00 -3.41295004e+00 -3.39945006e+00 - -3.38595009e+00 -3.37245011e+00 -3.35894990e+00 -3.34544992e+00 - -3.33194995e+00 -3.31844997e+00 -3.30495000e+00 -3.29145002e+00 - -3.27795005e+00 -3.26445007e+00 -3.25095010e+00 -3.23744988e+00 - -3.22394991e+00 -3.21044993e+00 -3.19694996e+00 -3.18344998e+00 - -3.16995001e+00 -3.15645003e+00 -3.14295006e+00 -3.12945008e+00 - -3.11595011e+00 -3.10244989e+00 -3.08894992e+00 -3.07544994e+00 - -3.06194997e+00 -3.04844999e+00 -3.03495002e+00 -3.02145004e+00 - -3.00795007e+00 -2.99445009e+00 -2.98095012e+00 -2.96744990e+00 - -2.95394993e+00 -2.94044995e+00 -2.92694998e+00 -2.91345000e+00 - -2.89995003e+00 -2.88645005e+00 -2.87295008e+00 -2.85945010e+00 - -2.84594989e+00 -2.83244991e+00 -2.81894994e+00 -2.80544996e+00 - -2.79194999e+00 -2.77845001e+00 -2.76495004e+00 -2.75145006e+00 - -2.73795009e+00 -2.72445011e+00 -2.71094990e+00 -2.69744992e+00 - -2.68394995e+00 -2.67044997e+00 -2.65695000e+00 -2.64345002e+00 - -2.62995005e+00 -2.61645007e+00 -2.60295010e+00 -2.58944988e+00 - -2.57594991e+00 -2.56244993e+00 -2.54894996e+00 -2.53544998e+00 - -2.52195001e+00 -2.50845003e+00 -2.49495006e+00 -2.48145008e+00 - -2.46795011e+00 -2.45444989e+00 -2.44094992e+00 -2.42744994e+00 - -2.41394997e+00 -2.40044999e+00 -2.38695002e+00 -2.37345004e+00 - -2.35995007e+00 -2.34645009e+00 -2.33295012e+00 -2.31944990e+00 - -2.30594993e+00 -2.29244995e+00 -2.27894998e+00 -2.26545000e+00 - -2.25195003e+00 -2.23845005e+00 -2.22495008e+00 -2.21145010e+00 - -2.19794989e+00 -2.18444991e+00 -2.17094994e+00 -2.15744996e+00 - -2.14394999e+00 -2.13045001e+00 -2.11695004e+00 -2.10345006e+00 - -2.08995008e+00 -2.07645011e+00 -2.06294990e+00 -2.04944992e+00 - -2.03594995e+00 -2.02244997e+00 -2.00895000e+00 -1.99545002e+00 - -1.98195004e+00 -1.96844995e+00 -1.95494998e+00 -1.94145000e+00 - -1.92795002e+00 -1.91445005e+00 -1.90094995e+00 -1.88744998e+00 - -1.87395000e+00 -1.86045003e+00 -1.84695005e+00 -1.83344996e+00 - -1.81994998e+00 -1.80645001e+00 -1.79295003e+00 -1.77945006e+00 - -1.76594996e+00 -1.75244999e+00 -1.73895001e+00 -1.72545004e+00 - -1.71194994e+00 -1.69844997e+00 -1.68494999e+00 -1.67145002e+00 - -1.65795004e+00 -1.64444995e+00 -1.63094997e+00 -1.61745000e+00 - -1.60395002e+00 -1.59045005e+00 -1.57694995e+00 -1.56344998e+00 - -1.54995000e+00 -1.53645003e+00 -1.52295005e+00 -1.50944996e+00 - -1.49594998e+00 -1.48245001e+00 -1.46895003e+00 -1.45545006e+00 - -1.44194996e+00 -1.42844999e+00 -1.41495001e+00 -1.40145004e+00 - -1.38794994e+00 -1.37444997e+00 -1.36094999e+00 -1.34745002e+00 - -1.33395004e+00 -1.32044995e+00 -1.30694997e+00 -1.29345000e+00 - -1.27995002e+00 -1.26645005e+00 -1.25294995e+00 -1.23944998e+00 - -1.22595000e+00 -1.21245003e+00 -1.19895005e+00 -1.18544996e+00 - -1.17194998e+00 -1.15845001e+00 -1.14495003e+00 -1.13145006e+00 - -1.11794996e+00 -1.10444999e+00 -1.09095001e+00 -1.07745004e+00 - -1.06394994e+00 -1.05044997e+00 -1.03694999e+00 -1.02345002e+00 - -1.00995004e+00 -9.96450007e-01 -9.82949972e-01 -9.69449997e-01 - -9.55950022e-01 -9.42449987e-01 -9.28950012e-01 -9.15449977e-01 - -9.01950002e-01 -8.88450027e-01 -8.74949992e-01 -8.61450016e-01 - -8.47949982e-01 -8.34450006e-01 -8.20949972e-01 -8.07449996e-01 - -7.93950021e-01 -7.80449986e-01 -7.66950011e-01 -7.53449976e-01 - -7.39950001e-01 -7.26450026e-01 -7.12949991e-01 -6.99450016e-01 - -6.85949981e-01 -6.72450006e-01 -6.58949971e-01 -6.45449996e-01 - -6.31950021e-01 -6.18449986e-01 -6.04950011e-01 -5.91449976e-01 - -5.77950001e-01 -5.64450026e-01 -5.50949991e-01 -5.37450016e-01 - -5.23949981e-01 -5.10450006e-01 -4.96950001e-01 -4.83449996e-01 - -4.69949991e-01 -4.56449986e-01 -4.42950010e-01 -4.29450005e-01 - -4.15950000e-01 -4.02449995e-01 -3.88949990e-01 -3.75449985e-01 - -3.61950010e-01 -3.48450005e-01 -3.34950000e-01 -3.21449995e-01 - -3.07949990e-01 -2.94450015e-01 -2.80950010e-01 -2.67450005e-01 - -2.53950000e-01 -2.40449995e-01 -2.26950005e-01 -2.13450000e-01 - -1.99949995e-01 -1.86450005e-01 -1.72950000e-01 -1.59449995e-01 - -1.45950004e-01 -1.32449999e-01 -1.18950002e-01 -1.05449997e-01 - -9.19499993e-02 -7.84500018e-02 -6.49499968e-02 -5.14499992e-02 - -3.79500017e-02 -2.44500004e-02 -1.09500000e-02 2.55000009e-03 - 1.60499997e-02 2.95499992e-02 4.30499986e-02 5.65499999e-02 - 7.00500011e-02 8.35499987e-02 9.70500037e-02 1.10550001e-01 - 1.24049999e-01 1.37549996e-01 1.51050001e-01 1.64550006e-01 - 1.78049996e-01 1.91550002e-01 2.05050007e-01 2.18549997e-01 - 2.32050002e-01 2.45550007e-01 2.59050012e-01 2.72549987e-01 - 2.86049992e-01 2.99549997e-01 3.13050002e-01 3.26550007e-01 - 3.40050012e-01 3.53549987e-01 3.67049992e-01 3.80549997e-01 - 3.94050002e-01 4.07550007e-01 4.21050012e-01 4.34549987e-01 - 4.48049992e-01 4.61549997e-01 4.75050002e-01 4.88550007e-01 - 5.02049983e-01 5.15550017e-01 5.29049993e-01 5.42550027e-01 - 5.56050003e-01 5.69549978e-01 5.83050013e-01 5.96549988e-01 - 6.10050023e-01 6.23549998e-01 6.37049973e-01 6.50550008e-01 - 6.64049983e-01 6.77550018e-01 6.91049993e-01 7.04550028e-01 - 7.18050003e-01 7.31549978e-01 7.45050013e-01 7.58549988e-01 - 7.72050023e-01 7.85549998e-01 7.99049973e-01 8.12550008e-01 - 8.26049984e-01 8.39550018e-01 8.53049994e-01 8.66550028e-01 - 8.80050004e-01 8.93549979e-01 9.07050014e-01 9.20549989e-01 - 9.34050024e-01 9.47549999e-01 9.61049974e-01 9.74550009e-01 - 9.88049984e-01 1.00154996e+00 1.01505005e+00 1.02855003e+00 - 1.04205000e+00 1.05554998e+00 1.06904995e+00 1.08255005e+00 - 1.09605002e+00 1.10955000e+00 1.12304997e+00 1.13654995e+00 - 1.15005004e+00 1.16355002e+00 1.17704999e+00 1.19054997e+00 - 1.20404994e+00 1.21755004e+00 1.23105001e+00 1.24454999e+00 - 1.25804996e+00 1.27155006e+00 1.28505003e+00 1.29855001e+00 - 1.31204998e+00 1.32554996e+00 1.33905005e+00 1.35255003e+00 - 1.36605000e+00 1.37954998e+00 1.39304996e+00 1.40655005e+00 - 1.42005002e+00 1.43355000e+00 1.44704998e+00 1.46054995e+00 - 1.47405005e+00 1.48755002e+00 1.50105000e+00 1.51454997e+00 - 1.52804995e+00 1.54155004e+00 1.55505002e+00 1.56854999e+00 - 1.58204997e+00 1.59554994e+00 1.60905004e+00 1.62255001e+00 - 1.63604999e+00 1.64954996e+00 1.66305006e+00 1.67655003e+00 - 1.69005001e+00 1.70354998e+00 1.71704996e+00 1.73055005e+00 - 1.74405003e+00 1.75755000e+00 1.77104998e+00 1.78454995e+00 - 1.79805005e+00 1.81155002e+00 1.82505000e+00 1.83854997e+00 - 1.85204995e+00 1.86555004e+00 1.87905002e+00 1.89254999e+00 - 1.90604997e+00 1.91954994e+00 1.93305004e+00 1.94655001e+00 - 1.96004999e+00 1.97354996e+00 1.98705006e+00 2.00055003e+00 - 2.01405001e+00 2.02754998e+00 2.04104996e+00 2.05454993e+00 - 2.06804991e+00 2.08154988e+00 2.09505010e+00 2.10855007e+00 - 2.12205005e+00 2.13555002e+00 2.14905000e+00 2.16254997e+00 - 2.17604995e+00 2.18954992e+00 2.20304990e+00 2.21655011e+00 - 2.23005009e+00 2.24355006e+00 2.25705004e+00 2.27055001e+00 - 2.28404999e+00 2.29754996e+00 2.31104994e+00 2.32454991e+00 - 2.33804989e+00 2.35155010e+00 2.36505008e+00 2.37855005e+00 - 2.39205003e+00 2.40555000e+00 2.41904998e+00 2.43254995e+00 - 2.44604993e+00 2.45954990e+00 2.47305012e+00 2.48655009e+00 - 2.50005007e+00 2.51355004e+00 2.52705002e+00 2.54054999e+00 - 2.55404997e+00 2.56754994e+00 2.58104992e+00 2.59454989e+00 - 2.60805011e+00 2.62155008e+00 2.63505006e+00 2.64855003e+00 - 2.66205001e+00 2.67554998e+00 2.68904996e+00 2.70254993e+00 - 2.71604991e+00 2.72954988e+00 2.74305010e+00 2.75655007e+00 - 2.77005005e+00 2.78355002e+00 2.79705000e+00 2.81054997e+00 - 2.82404995e+00 2.83754992e+00 2.85104990e+00 2.86455011e+00 - 2.87805009e+00 2.89155006e+00 2.90505004e+00 2.91855001e+00 - 2.93204999e+00 2.94554996e+00 2.95904994e+00 2.97254992e+00 - 2.98604989e+00 2.99955010e+00 3.01305008e+00 3.02655005e+00 - 3.04005003e+00 3.05355000e+00 3.06704998e+00 3.08054996e+00 - 3.09404993e+00 3.10754991e+00 3.12104988e+00 3.13455009e+00 - 3.14805007e+00 3.16155005e+00 3.17505002e+00 3.18855000e+00 - 3.20204997e+00 3.21554995e+00 3.22904992e+00 3.24254990e+00 - 3.25605011e+00 3.26955009e+00 3.28305006e+00 3.29655004e+00 - 3.31005001e+00 3.32354999e+00 3.33704996e+00 3.35054994e+00 - 3.36404991e+00 3.37754989e+00 3.39105010e+00 3.40455008e+00 - 3.41805005e+00 3.43155003e+00 3.44505000e+00 3.45854998e+00 - 3.47204995e+00 3.48554993e+00 3.49904990e+00 3.51255012e+00 - 3.52605009e+00 3.53955007e+00 3.55305004e+00 3.56655002e+00 - 3.58004999e+00 3.59354997e+00 3.60704994e+00 3.62054992e+00 - 3.63404989e+00 3.64755011e+00 3.66105008e+00 3.67455006e+00 - 3.68805003e+00 3.70155001e+00 3.71504998e+00 3.72854996e+00 - 3.74204993e+00 3.75554991e+00 3.76904988e+00 3.78255010e+00 - 3.79605007e+00 3.80955005e+00 3.82305002e+00 3.83655000e+00 - 3.85004997e+00 3.86354995e+00 3.87704992e+00 3.89054990e+00 - 3.90405011e+00 3.91755009e+00 3.93105006e+00 3.94455004e+00 - 3.95805001e+00 3.97154999e+00 3.98504996e+00 3.99854994e+00 - 4.01205015e+00 4.02554989e+00 4.03905010e+00 4.05254984e+00 - 4.06605005e+00 4.07954979e+00 4.09305000e+00 4.10655022e+00 - 4.12004995e+00 4.13355017e+00 4.14704990e+00 4.16055012e+00 - 4.17404985e+00 4.18755007e+00 4.20104980e+00 4.21455002e+00 - 4.22805023e+00 4.24154997e+00 4.25505018e+00 4.26854992e+00 - 4.28205013e+00 4.29554987e+00 4.30905008e+00 4.32254982e+00 - 4.33605003e+00 4.34954977e+00 4.36304998e+00 4.37655020e+00 - 4.39004993e+00 4.40355015e+00 4.41704988e+00 4.43055010e+00 - 4.44404984e+00 4.45755005e+00 4.47104979e+00 4.48455000e+00 - 4.49805021e+00 4.51154995e+00 4.52505016e+00 4.53854990e+00 - 4.55205011e+00 4.56554985e+00 4.57905006e+00 4.59254980e+00 - 4.60605001e+00 4.61955023e+00 4.63304996e+00 4.64655018e+00 - 4.66004992e+00 4.67355013e+00 4.68704987e+00 4.70055008e+00 - 4.71404982e+00 4.72755003e+00 4.74104977e+00 4.75454998e+00 - 4.76805019e+00 4.78154993e+00 4.79505014e+00 4.80854988e+00 - 4.82205009e+00 4.83554983e+00 4.84905005e+00 4.86254978e+00 - 4.87605000e+00 4.88955021e+00 4.90304995e+00 4.91655016e+00 - 4.93004990e+00 4.94355011e+00 4.95704985e+00 4.97055006e+00 - 4.98404980e+00 4.99755001e+00 5.01105022e+00 5.02454996e+00 - 5.03805017e+00 5.05154991e+00 5.06505013e+00 5.07854986e+00 - 5.09205008e+00 5.10554981e+00 5.11905003e+00 5.13254976e+00 - 5.14604998e+00 5.15955019e+00 5.17304993e+00 5.18655014e+00 - 5.20004988e+00 5.21355009e+00 5.22704983e+00 5.24055004e+00 - 5.25404978e+00 5.26754999e+00 5.28105021e+00 5.29454994e+00 - 5.30805016e+00 5.32154989e+00 5.33505011e+00 5.34854984e+00 - 5.36205006e+00 5.37554979e+00 5.38905001e+00 5.40255022e+00 - 5.41604996e+00 5.42955017e+00 5.44304991e+00 5.45655012e+00 - 5.47004986e+00 5.48355007e+00 5.49704981e+00 5.51055002e+00 - 5.52405024e+00 5.53754997e+00 5.55105019e+00 5.56454992e+00 - 5.57805014e+00 5.59154987e+00 5.60505009e+00 5.61854982e+00 - 5.63205004e+00 5.64554977e+00 5.65904999e+00 5.67255020e+00 - 5.68604994e+00 5.69955015e+00 5.71304989e+00 5.72655010e+00 - 5.74004984e+00 5.75355005e+00 5.76704979e+00 5.78055000e+00 - 5.79405022e+00 5.80754995e+00 5.82105017e+00 5.83454990e+00 - 5.84805012e+00 5.86154985e+00 5.87505007e+00 5.88854980e+00 - 5.90205002e+00 5.91555023e+00 5.92904997e+00 5.94255018e+00 - 5.95604992e+00 5.96955013e+00 5.98304987e+00 5.99655008e+00 - 6.01004982e+00 6.02355003e+00 6.03704977e+00 6.05054998e+00 - 6.06405020e+00 6.07754993e+00 6.09105015e+00 6.10454988e+00 - 6.11805010e+00 6.13154984e+00 6.14505005e+00 6.15854979e+00 - 6.17205000e+00 6.18555021e+00 6.19904995e+00 6.21255016e+00 - 6.22604990e+00 6.23955011e+00 6.25304985e+00 6.26655006e+00 - 6.28004980e+00 6.29355001e+00 6.30705023e+00 6.32054996e+00 - 6.33405018e+00 6.34754992e+00 6.36105013e+00 6.37454987e+00 - 6.38805008e+00 6.40154982e+00 6.41505003e+00 6.42854977e+00 - 6.44204998e+00 6.45555019e+00 6.46904993e+00 6.48255014e+00 - 6.49604988e+00 6.50955009e+00 6.52304983e+00 6.53655005e+00 - 6.55004978e+00 6.56355000e+00 6.57705021e+00 6.59054995e+00 - 6.60405016e+00 6.61754990e+00 6.63105011e+00 6.64454985e+00 - 6.65805006e+00 6.67154980e+00 6.68505001e+00 6.69855022e+00 - 6.71204996e+00 6.72555017e+00 6.73904991e+00 6.75255013e+00 - 6.76604986e+00 6.77955008e+00 6.79304981e+00 6.80655003e+00 - 6.82004976e+00 6.83354998e+00 6.84705019e+00 6.86054993e+00 - 6.87405014e+00 6.88754988e+00 6.90105009e+00 6.91454983e+00 - 6.92805004e+00 6.94154978e+00 6.95504999e+00 6.96855021e+00 - 6.98204994e+00 6.99555016e+00 7.00904989e+00 7.02255011e+00 - 7.03604984e+00 7.04955006e+00 7.06304979e+00 7.07655001e+00 - 7.09005022e+00 7.10354996e+00 7.11705017e+00 7.13054991e+00 - 7.14405012e+00 7.15782690e+00 7.17216969e+00 7.18710089e+00 - 7.20264530e+00 7.21882725e+00 7.23567390e+00 7.25321150e+00 - 7.27146959e+00 7.29047680e+00 7.31026411e+00 7.33086348e+00 - 7.35230875e+00 7.37463427e+00 7.39787626e+00 7.42207193e+00 - 7.44726086e+00 7.47348356e+00 7.50078297e+00 7.52920294e+00 - 7.55878925e+00 7.58959007e+00 7.62330008e+00 7.65929985e+00 - 7.69530010e+00 7.73129988e+00 7.76730013e+00 7.80329990e+00 - 7.83930016e+00 7.87529993e+00 7.91130018e+00 7.94729996e+00 - 7.98330021e+00 8.01930046e+00 8.05529976e+00 8.09130001e+00 - 8.12730026e+00 8.16329956e+00 8.19929981e+00 8.23530006e+00 - 8.27130032e+00 8.30729961e+00 8.34329987e+00 8.37930012e+00 - 8.41530037e+00 8.45129967e+00 8.48729992e+00 8.52330017e+00 - 8.55930042e+00 8.59529972e+00 8.63129997e+00 8.66730022e+00 - 8.70330048e+00 8.73929977e+00 8.77530003e+00 8.81130028e+00 - 8.84729958e+00 8.88329983e+00 8.91930008e+00 8.95530033e+00] - y_upper_bound: [ -5.57520008e+00 -5.53919983e+00 -5.50320005e+00 -5.46719980e+00 - -5.43120003e+00 -5.39519978e+00 -5.35920000e+00 -5.32320023e+00 - -5.28719997e+00 -5.25120020e+00 -5.21519995e+00 -5.17920017e+00 - -5.14319992e+00 -5.10720015e+00 -5.07119989e+00 -5.03520012e+00 - -4.99919987e+00 -4.96320009e+00 -4.92719984e+00 -4.89120007e+00 - -4.85519981e+00 -4.81920004e+00 -4.78319979e+00 -4.74720001e+00 - -4.71120024e+00 -4.67519999e+00 -4.63920021e+00 -4.60319996e+00 - -4.56720018e+00 -4.53119993e+00 -4.49520016e+00 -4.45919991e+00 - -4.42320013e+00 -4.38719988e+00 -4.35120010e+00 -4.31519985e+00 - -4.27920008e+00 -4.24319983e+00 -4.20948982e+00 -4.17868900e+00 - -4.14910269e+00 -4.12068319e+00 -4.09338379e+00 -4.06716108e+00 - -4.04197168e+00 -4.01777601e+00 -3.99453425e+00 -3.97220898e+00 - -3.95076370e+00 -3.93016410e+00 -3.91037679e+00 -3.89136934e+00 - -3.87311172e+00 -3.85557365e+00 -3.83872724e+00 -3.82254505e+00 - -3.80700088e+00 -3.79206967e+00 -3.77772713e+00 -3.76395011e+00 - -3.75044990e+00 -3.73694992e+00 -3.72344995e+00 -3.70994997e+00 - -3.69645000e+00 -3.68295002e+00 -3.66945004e+00 -3.65595007e+00 - -3.64245009e+00 -3.62895012e+00 -3.61544991e+00 -3.60194993e+00 - -3.58844995e+00 -3.57494998e+00 -3.56145000e+00 -3.54795003e+00 - -3.53445005e+00 -3.52095008e+00 -3.50745010e+00 -3.49394989e+00 - -3.48044991e+00 -3.46694994e+00 -3.45344996e+00 -3.43994999e+00 - -3.42645001e+00 -3.41295004e+00 -3.39945006e+00 -3.38595009e+00 - -3.37245011e+00 -3.35894990e+00 -3.34544992e+00 -3.33194995e+00 - -3.31844997e+00 -3.30495000e+00 -3.29145002e+00 -3.27795005e+00 - -3.26445007e+00 -3.25095010e+00 -3.23744988e+00 -3.22394991e+00 - -3.21044993e+00 -3.19694996e+00 -3.18344998e+00 -3.16995001e+00 - -3.15645003e+00 -3.14295006e+00 -3.12945008e+00 -3.11595011e+00 - -3.10244989e+00 -3.08894992e+00 -3.07544994e+00 -3.06194997e+00 - -3.04844999e+00 -3.03495002e+00 -3.02145004e+00 -3.00795007e+00 - -2.99445009e+00 -2.98095012e+00 -2.96744990e+00 -2.95394993e+00 - -2.94044995e+00 -2.92694998e+00 -2.91345000e+00 -2.89995003e+00 - -2.88645005e+00 -2.87295008e+00 -2.85945010e+00 -2.84594989e+00 - -2.83244991e+00 -2.81894994e+00 -2.80544996e+00 -2.79194999e+00 - -2.77845001e+00 -2.76495004e+00 -2.75145006e+00 -2.73795009e+00 - -2.72445011e+00 -2.71094990e+00 -2.69744992e+00 -2.68394995e+00 - -2.67044997e+00 -2.65695000e+00 -2.64345002e+00 -2.62995005e+00 - -2.61645007e+00 -2.60295010e+00 -2.58944988e+00 -2.57594991e+00 - -2.56244993e+00 -2.54894996e+00 -2.53544998e+00 -2.52195001e+00 - -2.50845003e+00 -2.49495006e+00 -2.48145008e+00 -2.46795011e+00 - -2.45444989e+00 -2.44094992e+00 -2.42744994e+00 -2.41394997e+00 - -2.40044999e+00 -2.38695002e+00 -2.37345004e+00 -2.35995007e+00 - -2.34645009e+00 -2.33295012e+00 -2.31944990e+00 -2.30594993e+00 - -2.29244995e+00 -2.27894998e+00 -2.26545000e+00 -2.25195003e+00 - -2.23845005e+00 -2.22495008e+00 -2.21145010e+00 -2.19794989e+00 - -2.18444991e+00 -2.17094994e+00 -2.15744996e+00 -2.14394999e+00 - -2.13045001e+00 -2.11695004e+00 -2.10345006e+00 -2.08995008e+00 - -2.07645011e+00 -2.06294990e+00 -2.04944992e+00 -2.03594995e+00 - -2.02244997e+00 -2.00895000e+00 -1.99545002e+00 -1.98195004e+00 - -1.96844995e+00 -1.95494998e+00 -1.94145000e+00 -1.92795002e+00 - -1.91445005e+00 -1.90094995e+00 -1.88744998e+00 -1.87395000e+00 - -1.86045003e+00 -1.84695005e+00 -1.83344996e+00 -1.81994998e+00 - -1.80645001e+00 -1.79295003e+00 -1.77945006e+00 -1.76594996e+00 - -1.75244999e+00 -1.73895001e+00 -1.72545004e+00 -1.71194994e+00 - -1.69844997e+00 -1.68494999e+00 -1.67145002e+00 -1.65795004e+00 - -1.64444995e+00 -1.63094997e+00 -1.61745000e+00 -1.60395002e+00 - -1.59045005e+00 -1.57694995e+00 -1.56344998e+00 -1.54995000e+00 - -1.53645003e+00 -1.52295005e+00 -1.50944996e+00 -1.49594998e+00 - -1.48245001e+00 -1.46895003e+00 -1.45545006e+00 -1.44194996e+00 - -1.42844999e+00 -1.41495001e+00 -1.40145004e+00 -1.38794994e+00 - -1.37444997e+00 -1.36094999e+00 -1.34745002e+00 -1.33395004e+00 - -1.32044995e+00 -1.30694997e+00 -1.29345000e+00 -1.27995002e+00 - -1.26645005e+00 -1.25294995e+00 -1.23944998e+00 -1.22595000e+00 - -1.21245003e+00 -1.19895005e+00 -1.18544996e+00 -1.17194998e+00 - -1.15845001e+00 -1.14495003e+00 -1.13145006e+00 -1.11794996e+00 - -1.10444999e+00 -1.09095001e+00 -1.07745004e+00 -1.06394994e+00 - -1.05044997e+00 -1.03694999e+00 -1.02345002e+00 -1.00995004e+00 - -9.96450007e-01 -9.82949972e-01 -9.69449997e-01 -9.55950022e-01 - -9.42449987e-01 -9.28950012e-01 -9.15449977e-01 -9.01950002e-01 - -8.88450027e-01 -8.74949992e-01 -8.61450016e-01 -8.47949982e-01 - -8.34450006e-01 -8.20949972e-01 -8.07449996e-01 -7.93950021e-01 - -7.80449986e-01 -7.66950011e-01 -7.53449976e-01 -7.39950001e-01 - -7.26450026e-01 -7.12949991e-01 -6.99450016e-01 -6.85949981e-01 - -6.72450006e-01 -6.58949971e-01 -6.45449996e-01 -6.31950021e-01 - -6.18449986e-01 -6.04950011e-01 -5.91449976e-01 -5.77950001e-01 - -5.64450026e-01 -5.50949991e-01 -5.37450016e-01 -5.23949981e-01 - -5.10450006e-01 -4.96950001e-01 -4.83449996e-01 -4.69949991e-01 - -4.56449986e-01 -4.42950010e-01 -4.29450005e-01 -4.15950000e-01 - -4.02449995e-01 -3.88949990e-01 -3.75449985e-01 -3.61950010e-01 - -3.48450005e-01 -3.34950000e-01 -3.21449995e-01 -3.07949990e-01 - -2.94450015e-01 -2.80950010e-01 -2.67450005e-01 -2.53950000e-01 - -2.40449995e-01 -2.26950005e-01 -2.13450000e-01 -1.99949995e-01 - -1.86450005e-01 -1.72950000e-01 -1.59449995e-01 -1.45950004e-01 - -1.32449999e-01 -1.18950002e-01 -1.05449997e-01 -9.19499993e-02 - -7.84500018e-02 -6.49499968e-02 -5.14499992e-02 -3.79500017e-02 - -2.44500004e-02 -1.09500000e-02 2.55000009e-03 1.60499997e-02 - 2.95499992e-02 4.30499986e-02 5.65499999e-02 7.00500011e-02 - 8.35499987e-02 9.70500037e-02 1.10550001e-01 1.24049999e-01 - 1.37549996e-01 1.51050001e-01 1.64550006e-01 1.78049996e-01 - 1.91550002e-01 2.05050007e-01 2.18549997e-01 2.32050002e-01 - 2.45550007e-01 2.59050012e-01 2.72549987e-01 2.86049992e-01 - 2.99549997e-01 3.13050002e-01 3.26550007e-01 3.40050012e-01 - 3.53549987e-01 3.67049992e-01 3.80549997e-01 3.94050002e-01 - 4.07550007e-01 4.21050012e-01 4.34549987e-01 4.48049992e-01 - 4.61549997e-01 4.75050002e-01 4.88550007e-01 5.02049983e-01 - 5.15550017e-01 5.29049993e-01 5.42550027e-01 5.56050003e-01 - 5.69549978e-01 5.83050013e-01 5.96549988e-01 6.10050023e-01 - 6.23549998e-01 6.37049973e-01 6.50550008e-01 6.64049983e-01 - 6.77550018e-01 6.91049993e-01 7.04550028e-01 7.18050003e-01 - 7.31549978e-01 7.45050013e-01 7.58549988e-01 7.72050023e-01 - 7.85549998e-01 7.99049973e-01 8.12550008e-01 8.26049984e-01 - 8.39550018e-01 8.53049994e-01 8.66550028e-01 8.80050004e-01 - 8.93549979e-01 9.07050014e-01 9.20549989e-01 9.34050024e-01 - 9.47549999e-01 9.61049974e-01 9.74550009e-01 9.88049984e-01 - 1.00154996e+00 1.01505005e+00 1.02855003e+00 1.04205000e+00 - 1.05554998e+00 1.06904995e+00 1.08255005e+00 1.09605002e+00 - 1.10955000e+00 1.12304997e+00 1.13654995e+00 1.15005004e+00 - 1.16355002e+00 1.17704999e+00 1.19054997e+00 1.20404994e+00 - 1.21755004e+00 1.23105001e+00 1.24454999e+00 1.25804996e+00 - 1.27155006e+00 1.28505003e+00 1.29855001e+00 1.31204998e+00 - 1.32554996e+00 1.33905005e+00 1.35255003e+00 1.36605000e+00 - 1.37954998e+00 1.39304996e+00 1.40655005e+00 1.42005002e+00 - 1.43355000e+00 1.44704998e+00 1.46054995e+00 1.47405005e+00 - 1.48755002e+00 1.50105000e+00 1.51454997e+00 1.52804995e+00 - 1.54155004e+00 1.55505002e+00 1.56854999e+00 1.58204997e+00 - 1.59554994e+00 1.60905004e+00 1.62255001e+00 1.63604999e+00 - 1.64954996e+00 1.66305006e+00 1.67655003e+00 1.69005001e+00 - 1.70354998e+00 1.71704996e+00 1.73055005e+00 1.74405003e+00 - 1.75755000e+00 1.77104998e+00 1.78454995e+00 1.79805005e+00 - 1.81155002e+00 1.82505000e+00 1.83854997e+00 1.85204995e+00 - 1.86555004e+00 1.87905002e+00 1.89254999e+00 1.90604997e+00 - 1.91954994e+00 1.93305004e+00 1.94655001e+00 1.96004999e+00 - 1.97354996e+00 1.98705006e+00 2.00055003e+00 2.01405001e+00 - 2.02754998e+00 2.04104996e+00 2.05454993e+00 2.06804991e+00 - 2.08154988e+00 2.09505010e+00 2.10855007e+00 2.12205005e+00 - 2.13555002e+00 2.14905000e+00 2.16254997e+00 2.17604995e+00 - 2.18954992e+00 2.20304990e+00 2.21655011e+00 2.23005009e+00 - 2.24355006e+00 2.25705004e+00 2.27055001e+00 2.28404999e+00 - 2.29754996e+00 2.31104994e+00 2.32454991e+00 2.33804989e+00 - 2.35155010e+00 2.36505008e+00 2.37855005e+00 2.39205003e+00 - 2.40555000e+00 2.41904998e+00 2.43254995e+00 2.44604993e+00 - 2.45954990e+00 2.47305012e+00 2.48655009e+00 2.50005007e+00 - 2.51355004e+00 2.52705002e+00 2.54054999e+00 2.55404997e+00 - 2.56754994e+00 2.58104992e+00 2.59454989e+00 2.60805011e+00 - 2.62155008e+00 2.63505006e+00 2.64855003e+00 2.66205001e+00 - 2.67554998e+00 2.68904996e+00 2.70254993e+00 2.71604991e+00 - 2.72954988e+00 2.74305010e+00 2.75655007e+00 2.77005005e+00 - 2.78355002e+00 2.79705000e+00 2.81054997e+00 2.82404995e+00 - 2.83754992e+00 2.85104990e+00 2.86455011e+00 2.87805009e+00 - 2.89155006e+00 2.90505004e+00 2.91855001e+00 2.93204999e+00 - 2.94554996e+00 2.95904994e+00 2.97254992e+00 2.98604989e+00 - 2.99955010e+00 3.01305008e+00 3.02655005e+00 3.04005003e+00 - 3.05355000e+00 3.06704998e+00 3.08054996e+00 3.09404993e+00 - 3.10754991e+00 3.12104988e+00 3.13455009e+00 3.14805007e+00 - 3.16155005e+00 3.17505002e+00 3.18855000e+00 3.20204997e+00 - 3.21554995e+00 3.22904992e+00 3.24254990e+00 3.25605011e+00 - 3.26955009e+00 3.28305006e+00 3.29655004e+00 3.31005001e+00 - 3.32354999e+00 3.33704996e+00 3.35054994e+00 3.36404991e+00 - 3.37754989e+00 3.39105010e+00 3.40455008e+00 3.41805005e+00 - 3.43155003e+00 3.44505000e+00 3.45854998e+00 3.47204995e+00 - 3.48554993e+00 3.49904990e+00 3.51255012e+00 3.52605009e+00 - 3.53955007e+00 3.55305004e+00 3.56655002e+00 3.58004999e+00 - 3.59354997e+00 3.60704994e+00 3.62054992e+00 3.63404989e+00 - 3.64755011e+00 3.66105008e+00 3.67455006e+00 3.68805003e+00 - 3.70155001e+00 3.71504998e+00 3.72854996e+00 3.74204993e+00 - 3.75554991e+00 3.76904988e+00 3.78255010e+00 3.79605007e+00 - 3.80955005e+00 3.82305002e+00 3.83655000e+00 3.85004997e+00 - 3.86354995e+00 3.87704992e+00 3.89054990e+00 3.90405011e+00 - 3.91755009e+00 3.93105006e+00 3.94455004e+00 3.95805001e+00 - 3.97154999e+00 3.98504996e+00 3.99854994e+00 4.01205015e+00 - 4.02554989e+00 4.03905010e+00 4.05254984e+00 4.06605005e+00 - 4.07954979e+00 4.09305000e+00 4.10655022e+00 4.12004995e+00 - 4.13355017e+00 4.14704990e+00 4.16055012e+00 4.17404985e+00 - 4.18755007e+00 4.20104980e+00 4.21455002e+00 4.22805023e+00 - 4.24154997e+00 4.25505018e+00 4.26854992e+00 4.28205013e+00 - 4.29554987e+00 4.30905008e+00 4.32254982e+00 4.33605003e+00 - 4.34954977e+00 4.36304998e+00 4.37655020e+00 4.39004993e+00 - 4.40355015e+00 4.41704988e+00 4.43055010e+00 4.44404984e+00 - 4.45755005e+00 4.47104979e+00 4.48455000e+00 4.49805021e+00 - 4.51154995e+00 4.52505016e+00 4.53854990e+00 4.55205011e+00 - 4.56554985e+00 4.57905006e+00 4.59254980e+00 4.60605001e+00 - 4.61955023e+00 4.63304996e+00 4.64655018e+00 4.66004992e+00 - 4.67355013e+00 4.68704987e+00 4.70055008e+00 4.71404982e+00 - 4.72755003e+00 4.74104977e+00 4.75454998e+00 4.76805019e+00 - 4.78154993e+00 4.79505014e+00 4.80854988e+00 4.82205009e+00 - 4.83554983e+00 4.84905005e+00 4.86254978e+00 4.87605000e+00 - 4.88955021e+00 4.90304995e+00 4.91655016e+00 4.93004990e+00 - 4.94355011e+00 4.95704985e+00 4.97055006e+00 4.98404980e+00 - 4.99755001e+00 5.01105022e+00 5.02454996e+00 5.03805017e+00 - 5.05154991e+00 5.06505013e+00 5.07854986e+00 5.09205008e+00 - 5.10554981e+00 5.11905003e+00 5.13254976e+00 5.14604998e+00 - 5.15955019e+00 5.17304993e+00 5.18655014e+00 5.20004988e+00 - 5.21355009e+00 5.22704983e+00 5.24055004e+00 5.25404978e+00 - 5.26754999e+00 5.28105021e+00 5.29454994e+00 5.30805016e+00 - 5.32154989e+00 5.33505011e+00 5.34854984e+00 5.36205006e+00 - 5.37554979e+00 5.38905001e+00 5.40255022e+00 5.41604996e+00 - 5.42955017e+00 5.44304991e+00 5.45655012e+00 5.47004986e+00 - 5.48355007e+00 5.49704981e+00 5.51055002e+00 5.52405024e+00 - 5.53754997e+00 5.55105019e+00 5.56454992e+00 5.57805014e+00 - 5.59154987e+00 5.60505009e+00 5.61854982e+00 5.63205004e+00 - 5.64554977e+00 5.65904999e+00 5.67255020e+00 5.68604994e+00 - 5.69955015e+00 5.71304989e+00 5.72655010e+00 5.74004984e+00 - 5.75355005e+00 5.76704979e+00 5.78055000e+00 5.79405022e+00 - 5.80754995e+00 5.82105017e+00 5.83454990e+00 5.84805012e+00 - 5.86154985e+00 5.87505007e+00 5.88854980e+00 5.90205002e+00 - 5.91555023e+00 5.92904997e+00 5.94255018e+00 5.95604992e+00 - 5.96955013e+00 5.98304987e+00 5.99655008e+00 6.01004982e+00 - 6.02355003e+00 6.03704977e+00 6.05054998e+00 6.06405020e+00 - 6.07754993e+00 6.09105015e+00 6.10454988e+00 6.11805010e+00 - 6.13154984e+00 6.14505005e+00 6.15854979e+00 6.17205000e+00 - 6.18555021e+00 6.19904995e+00 6.21255016e+00 6.22604990e+00 - 6.23955011e+00 6.25304985e+00 6.26655006e+00 6.28004980e+00 - 6.29355001e+00 6.30705023e+00 6.32054996e+00 6.33405018e+00 - 6.34754992e+00 6.36105013e+00 6.37454987e+00 6.38805008e+00 - 6.40154982e+00 6.41505003e+00 6.42854977e+00 6.44204998e+00 - 6.45555019e+00 6.46904993e+00 6.48255014e+00 6.49604988e+00 - 6.50955009e+00 6.52304983e+00 6.53655005e+00 6.55004978e+00 - 6.56355000e+00 6.57705021e+00 6.59054995e+00 6.60405016e+00 - 6.61754990e+00 6.63105011e+00 6.64454985e+00 6.65805006e+00 - 6.67154980e+00 6.68505001e+00 6.69855022e+00 6.71204996e+00 - 6.72555017e+00 6.73904991e+00 6.75255013e+00 6.76604986e+00 - 6.77955008e+00 6.79304981e+00 6.80655003e+00 6.82004976e+00 - 6.83354998e+00 6.84705019e+00 6.86054993e+00 6.87405014e+00 - 6.88754988e+00 6.90105009e+00 6.91454983e+00 6.92805004e+00 - 6.94154978e+00 6.95504999e+00 6.96855021e+00 6.98204994e+00 - 6.99555016e+00 7.00904989e+00 7.02255011e+00 7.03604984e+00 - 7.04955006e+00 7.06304979e+00 7.07655001e+00 7.09005022e+00 - 7.10354996e+00 7.11705017e+00 7.13054991e+00 7.14405012e+00 - 7.15782690e+00 7.17216969e+00 7.18710089e+00 7.20264530e+00 - 7.21882725e+00 7.23567390e+00 7.25321150e+00 7.27146959e+00 - 7.29047680e+00 7.31026411e+00 7.33086348e+00 7.35230875e+00 - 7.37463427e+00 7.39787626e+00 7.42207193e+00 7.44726086e+00 - 7.47348356e+00 7.50078297e+00 7.52920294e+00 7.55878925e+00 - 7.58959007e+00 7.62330008e+00 7.65929985e+00 7.69530010e+00 - 7.73129988e+00 7.76730013e+00 7.80329990e+00 7.83930016e+00 - 7.87529993e+00 7.91130018e+00 7.94729996e+00 7.98330021e+00 - 8.01930046e+00 8.05529976e+00 8.09130001e+00 8.12730026e+00 - 8.16329956e+00 8.19929981e+00 8.23530006e+00 8.27130032e+00 - 8.30729961e+00 8.34329987e+00 8.37930012e+00 8.41530037e+00 - 8.45129967e+00 8.48729992e+00 8.52330017e+00 8.55930042e+00 - 8.59529972e+00 8.63129997e+00 8.66730022e+00 8.70330048e+00 - 8.73929977e+00 8.77530003e+00 8.81130028e+00 8.84729958e+00 - 8.88329983e+00 8.91930008e+00 8.95530033e+00 8.99129963e+00] + data: [[100075. 100073. 100071. ... 101147. 101153. 101155.] + [100072. 100070. 100068. ... 101149. 101155. 101157.] + [100070. 100069. 100067. ... 101149. 101156. 101158.] + ... + [102231. 102239. 102247. ... 101882. 101855. 101852.] + [102237. 102245. 102253. ... 101879. 101859. 101854.] + [102244. 102252. 102260. ... 101886. 101863. 101855.]] + x: [353.0525 353.0885 353.1245 353.1605 353.1965 353.2325 353.2685 + 353.3045 353.3405 353.3765 353.4125 353.4485 353.4845 353.5205 + 353.5565 353.5925 353.6285 353.6645 353.7005 353.7365 353.7725 + 353.8085 353.8445 353.8805 353.9165 353.9525 353.9885 354.0245 + 354.0605 354.0965 354.1325 354.1685 354.2045 354.2405 354.2765 + 354.3125 354.3485 354.3845 354.4205 354.4565 354.4925 354.52185 + 354.5501 354.57736 354.60364 354.62894 354.65332 354.67685 354.6995 + 354.7213 354.74234 354.76263 354.78217 354.801 354.81915 354.83664 + 354.8535 354.86972 354.88538 354.90045 354.91498 354.929 354.9425 + 354.956 354.9695 354.983 354.9965 355.01 355.0235 355.037 + 355.0505 355.064 355.0775 355.091 355.1045 355.118 355.1315 + 355.145 355.1585 355.172 355.1855 355.199 355.2125 355.226 + 355.2395 355.253 355.2665 355.28 355.2935 355.307 355.3205 + 355.334 355.3475 355.361 355.3745 355.388 355.4015 355.415 + 355.4285 355.442 355.4555 355.469 355.4825 355.496 355.5095 + 355.523 355.5365 355.55 355.5635 355.577 355.5905 355.604 + 355.6175 355.631 355.6445 355.658 355.6715 355.685 355.6985 + 355.712 355.7255 355.739 355.7525 355.766 355.7795 355.793 + 355.8065 355.82 355.8335 355.847 355.8605 355.874 355.8875 + 355.901 355.9145 355.928 355.9415 355.955 355.9685 355.982 + 355.9955 356.009 356.0225 356.036 356.0495 356.063 356.0765 + 356.09 356.1035 356.117 356.1305 356.144 356.1575 356.171 + 356.1845 356.198 356.2115 356.225 356.2385 356.252 356.2655 + 356.279 356.2925 356.306 356.3195 356.333 356.3465 356.36 + 356.3735 356.387 356.4005 356.414 356.4275 356.441 356.4545 + 356.468 356.4815 356.495 356.5085 356.522 356.5355 356.549 + 356.5625 356.576 356.5895 356.603 356.6165 356.63 356.6435 + 356.657 356.6705 356.684 356.6975 356.711 356.7245 356.738 + 356.7515 356.765 356.7785 356.792 356.8055 356.819 356.8325 + 356.846 356.8595 356.873 356.8865 356.9 356.9135 356.927 + 356.9405 356.954 356.9675 356.981 356.9945 357.008 357.0215 + 357.035 357.0485 357.062 357.0755 357.089 357.1025 357.116 + 357.1295 357.143 357.1565 357.17 357.1835 357.197 357.2105 + 357.224 357.2375 357.251 357.2645 357.278 357.2915 357.305 + 357.3185 357.332 357.3455 357.359 357.3725 357.386 357.3995 + 357.413 357.4265 357.44 357.4535 357.467 357.4805 357.494 + 357.5075 357.521 357.5345 357.548 357.5615 357.575 357.5885 + 357.602 357.6155 357.629 357.6425 357.656 357.6695 357.683 + 357.6965 357.71 357.7235 357.737 357.7505 357.764 357.7775 + 357.791 357.8045 357.818 357.8315 357.845 357.8585 357.872 + 357.8855 357.899 357.9125 357.926 357.9395 357.953 357.9665 + 357.98 357.9935 358.007 358.0205 358.034 358.0475 358.061 + 358.0745 358.088 358.1015 358.115 358.1285 358.142 358.1555 + 358.169 358.1825 358.196 358.2095 358.223 358.2365 358.25 + 358.2635 358.277 358.2905 358.304 358.3175 358.331 358.3445 + 358.358 358.3715 358.385 358.3985 358.412 358.4255 358.439 + 358.4525 358.466 358.4795 358.493 358.5065 358.52 358.5335 + 358.547 358.5605 358.574 358.5875 358.601 358.6145 358.628 + 358.6415 358.655 358.6685 358.682 358.6955 358.709 358.7225 + 358.736 358.7495 358.763 358.7765 358.79 358.8035 358.817 + 358.8305 358.844 358.8575 358.871 358.8845 358.898 358.9115 + 358.925 358.9385 358.952 358.9655 358.979 358.9925 359.006 + 359.0195 359.033 359.0465 359.06 359.0735 359.087 359.1005 + 359.114 359.1275 359.141 359.1545 359.168 359.1815 359.195 + 359.2085 359.222 359.2355 359.249 359.2625 359.276 359.2895 + 359.303 359.3165 359.33 359.3435 359.357 359.3705 359.384 + 359.3975 359.411 359.4245 359.438 359.4515 359.465 359.4785 + 359.492 359.5055 359.519 359.5325 359.546 359.5595 359.573 + 359.5865 359.6 359.6135 359.627 359.6405 359.654 359.6675 + 359.681 359.6945 359.708 359.7215 359.735 359.7485 359.762 + 359.7755 359.789 359.8025 359.816 359.8295 359.843 359.8565 + 359.87 359.8835 359.897 359.9105 359.924 359.9375 359.951 + 359.9645 359.978 359.9915 360.005 360.0185 360.032 360.0455 + 360.059 360.0725 360.086 360.0995 360.113 360.1265 360.14 + 360.1535 360.167 360.1805 360.194 360.2075 360.221 360.2345 + 360.248 360.2615 360.275 360.2885 360.302 360.3155 360.329 + 360.3425 360.356 360.3695 360.383 360.3965 360.41 360.4235 + 360.437 360.4505 360.464 360.4775 360.491 360.5045 360.518 + 360.5315 360.545 360.5585 360.572 360.5855 360.599 360.6125 + 360.626 360.6395 360.653 360.6665 360.68 360.6935 360.707 + 360.7205 360.734 360.7475 360.761 360.7745 360.788 360.8015 + 360.815 360.8285 360.842 360.8555 360.869 360.8825 360.896 + 360.9095 360.923 360.9365 360.95 360.9635 360.977 360.9905 + 361.004 361.0175 361.031 361.0445 361.058 361.0715 361.085 + 361.0985 361.112 361.1255 361.139 361.1525 361.166 361.1795 + 361.193 361.2065 361.22 361.2335 361.247 361.2605 361.274 + 361.2875 361.301 361.3145 361.328 361.3415 361.355 361.3685 + 361.382 361.3955 361.409 361.4225 361.436 361.4495 361.463 + 361.4765 361.49 361.5035 361.517 361.5305 361.544 361.5575 + 361.571 361.5845 361.598 361.6115 361.625 361.6385 361.652 + 361.6655 361.679 361.6925 361.706 361.7195 361.733 361.7465 + 361.76 361.7735 361.787 361.8005 361.814 361.8275 361.841 + 361.8545 361.868 361.8815 361.895 361.9085 361.922 361.9355 + 361.949 361.9625 361.976 361.9895 362.003 362.0165 362.03 + 362.0435 362.057 362.0705 362.084 362.0975 362.111 362.1245 + 362.138 362.1515 362.165 362.1785 362.192 362.2055 362.219 + 362.2325 362.246 362.2595 362.273 362.2865 362.3 362.3135 + 362.327 362.3405 362.354 362.3675 362.381 362.3945 362.408 + 362.4215 362.435 362.4485 362.462 362.4755 362.489 362.5025 + 362.516 362.5295 362.543 362.5565 362.57 362.5835 362.597 + 362.6105 362.624 362.6375 362.651 362.6645 362.678 362.6915 + 362.705 362.7185 362.732 362.7455 362.759 362.7725 362.786 + 362.7995 362.813 362.8265 362.84 362.8535 362.867 362.8805 + 362.894 362.9075 362.921 362.9345 362.948 362.9615 362.975 + 362.9885 363.002 363.0155 363.029 363.0425 363.056 363.0695 + 363.083 363.0965 363.11 363.1235 363.137 363.1505 363.164 + 363.1775 363.191 363.2045 363.218 363.2315 363.245 363.2585 + 363.272 363.2855 363.299 363.3125 363.3265 363.34103 363.35614 + 363.37177 363.38803 363.40488 363.42236 363.4405 363.45932 363.47888 + 363.49915 363.52017 363.54202 363.56467 363.58817 363.61255 363.63788 + 363.66412 363.69138 363.71967 363.749 363.785 363.821 363.857 + 363.893 363.929 363.965 364.001 364.037 364.073 364.109 + 364.145 364.181 364.217 364.253 364.289 364.325 364.361 + 364.397 364.433 364.469 364.505 364.541 364.577 364.613 + 364.649 364.685 364.721 364.757 364.793 364.829 364.865 + 364.901 364.937 364.973 365.009 365.045 365.081 365.117 + 365.153 365.189 ] + x_lower_bound: [353.0345 353.0705 353.1065 353.1425 353.1785 353.2145 353.2505 + 353.2865 353.3225 353.3585 353.3945 353.4305 353.4665 353.5025 + 353.5385 353.5745 353.6105 353.6465 353.6825 353.7185 353.7545 + 353.7905 353.8265 353.8625 353.8985 353.9345 353.9705 354.0065 + 354.0425 354.0785 354.1145 354.1505 354.1865 354.2225 354.2585 + 354.2945 354.3305 354.3665 354.4025 354.4385 354.4745 354.50717 + 354.53598 354.56375 354.5905 354.61627 354.64114 354.66507 354.68817 + 354.7104 354.73184 354.7525 354.7724 354.7916 354.81006 354.82788 + 354.84506 354.8616 354.87753 354.8929 354.9077 354.922 354.93576 + 354.94925 354.96274 354.97626 354.98975 355.00323 355.01675 355.03024 + 355.04376 355.05725 355.07074 355.08426 355.09775 355.11124 355.12476 + 355.13824 355.15176 355.16525 355.17874 355.19226 355.20575 355.21924 + 355.23276 355.24625 355.25974 355.27325 355.28674 355.30026 355.31375 + 355.32724 355.34076 355.35425 355.36774 355.38126 355.39474 355.40826 + 355.42175 355.43524 355.44876 355.46225 355.47574 355.48926 355.50275 + 355.51624 355.52975 355.54324 355.55676 355.57025 355.58374 355.59726 + 355.61075 355.62424 355.63776 355.65125 355.66476 355.67825 355.69174 + 355.70526 355.71875 355.73224 355.74576 355.75925 355.77274 355.78625 + 355.79974 355.81326 355.82675 355.84024 355.85376 355.86725 355.88074 + 355.89426 355.90775 355.92126 355.93475 355.94824 355.96176 355.97525 + 355.98874 356.00226 356.01575 356.02924 356.04276 356.05624 356.06976 + 356.08325 356.09674 356.11026 356.12375 356.13724 356.15076 356.16425 + 356.17776 356.19125 356.20474 356.21826 356.23175 356.24524 356.25876 + 356.27225 356.28574 356.29926 356.31274 356.32626 356.33975 356.35324 + 356.36676 356.38025 356.39374 356.40726 356.42075 356.43427 356.44775 + 356.46124 356.47476 356.48825 356.50174 356.51526 356.52875 356.54224 + 356.55576 356.56924 356.58276 356.59625 356.60974 356.62326 356.63675 + 356.65024 356.66376 356.67725 356.69073 356.70425 356.71774 356.73126 + 356.74475 356.75824 356.77176 356.78525 356.79874 356.81226 356.82574 + 356.83926 356.85275 356.86624 356.87976 356.89325 356.90674 356.92026 + 356.93375 356.94724 356.96075 356.97424 356.98776 357.00125 357.01474 + 357.02826 357.04175 357.05524 357.06876 357.08224 357.09576 357.10925 + 357.12274 357.13626 357.14975 357.16324 357.17676 357.19025 357.20374 + 357.21725 357.23074 357.24426 357.25775 357.27124 357.28476 357.29825 + 357.31174 357.32526 357.33875 357.35226 357.36575 357.37924 357.39276 + 357.40625 357.41974 357.43326 357.44675 357.46024 357.47375 357.48724 + 357.50076 357.51425 357.52774 357.54126 357.55475 357.56824 357.58176 + 357.59525 357.60876 357.62225 357.63574 357.64926 357.66275 357.67624 + 357.68976 357.70325 357.71674 357.73026 357.74374 357.75726 357.77075 + 357.78424 357.79776 357.81125 357.82474 357.83826 357.85175 357.86526 + 357.87875 357.89224 357.90576 357.91925 357.93274 357.94626 357.95975 + 357.97324 357.98676 358.00024 358.01376 358.02725 358.04074 358.05426 + 358.06775 358.08124 358.09476 358.10825 358.12177 358.13525 358.14874 + 358.16226 358.17575 358.18924 358.20276 358.21625 358.22974 358.24326 + 358.25674 358.27026 358.28375 358.29724 358.31076 358.32425 358.33774 + 358.35126 358.36475 358.37823 358.39175 358.40524 358.41876 358.43225 + 358.44574 358.45926 358.47275 358.48624 358.49976 358.51324 358.52676 + 358.54025 358.55374 358.56726 358.58075 358.59424 358.60776 358.62125 + 358.63474 358.64825 358.66174 358.67526 358.68875 358.70224 358.71576 + 358.72925 358.74274 358.75626 358.76974 358.78326 358.79675 358.81024 + 358.82376 358.83725 358.85074 358.86426 358.87775 358.89124 358.90475 + 358.91824 358.93176 358.94525 358.95874 358.97226 358.98575 358.99924 + 359.01276 359.02625 359.03976 359.05325 359.06674 359.08026 359.09375 + 359.10724 359.12076 359.13425 359.14774 359.16125 359.17474 359.18826 + 359.20175 359.21524 359.22876 359.24225 359.25574 359.26926 359.28275 + 359.29626 359.30975 359.32324 359.33676 359.35025 359.36374 359.37726 + 359.39075 359.40424 359.41776 359.43124 359.44476 359.45825 359.47174 + 359.48526 359.49875 359.51224 359.52576 359.53925 359.55276 359.56625 + 359.57974 359.59326 359.60675 359.62024 359.63376 359.64725 359.66074 + 359.67426 359.68774 359.70126 359.71475 359.72824 359.74176 359.75525 + 359.76874 359.78226 359.79575 359.80927 359.82275 359.83624 359.84976 + 359.86325 359.87674 359.89026 359.90375 359.91724 359.93076 359.94424 + 359.95776 359.97125 359.98474 359.99826 360.01175 360.02524 360.03876 + 360.05225 360.06573 360.07925 360.09274 360.10626 360.11975 360.13324 + 360.14676 360.16025 360.17374 360.18726 360.20074 360.21426 360.22775 + 360.24124 360.25476 360.26825 360.28174 360.29526 360.30875 360.32224 + 360.33575 360.34924 360.36276 360.37625 360.38974 360.40326 360.41675 + 360.43024 360.44376 360.45724 360.47076 360.48425 360.49774 360.51126 + 360.52475 360.53824 360.55176 360.56525 360.57874 360.59225 360.60574 + 360.61926 360.63275 360.64624 360.65976 360.67325 360.68674 360.70026 + 360.71375 360.72726 360.74075 360.75424 360.76776 360.78125 360.79474 + 360.80826 360.82175 360.83524 360.84875 360.86224 360.87576 360.88925 + 360.90274 360.91626 360.92975 360.94324 360.95676 360.97025 360.98376 + 360.99725 361.01074 361.02426 361.03775 361.05124 361.06476 361.07825 + 361.09174 361.10526 361.11874 361.13226 361.14575 361.15924 361.17276 + 361.18625 361.19974 361.21326 361.22675 361.24026 361.25375 361.26724 + 361.28076 361.29425 361.30774 361.32126 361.33475 361.34824 361.36176 + 361.37524 361.38876 361.40225 361.41574 361.42926 361.44275 361.45624 + 361.46976 361.48325 361.49677 361.51025 361.52374 361.53726 361.55075 + 361.56424 361.57776 361.59125 361.60474 361.61826 361.63174 361.64526 + 361.65875 361.67224 361.68576 361.69925 361.71274 361.72626 361.73975 + 361.75323 361.76675 361.78024 361.79376 361.80725 361.82074 361.83426 + 361.84775 361.86124 361.87476 361.88824 361.90176 361.91525 361.92874 + 361.94226 361.95575 361.96924 361.98276 361.99625 362.00974 362.02325 + 362.03674 362.05026 362.06375 362.07724 362.09076 362.10425 362.11774 + 362.13126 362.14474 362.15826 362.17175 362.18524 362.19876 362.21225 + 362.22574 362.23926 362.25275 362.26624 362.27975 362.29324 362.30676 + 362.32025 362.33374 362.34726 362.36075 362.37424 362.38776 362.40125 + 362.41476 362.42825 362.44174 362.45526 362.46875 362.48224 362.49576 + 362.50925 362.52274 362.53625 362.54974 362.56326 362.57675 362.59024 + 362.60376 362.61725 362.63074 362.64426 362.65775 362.67126 362.68475 + 362.69824 362.71176 362.72525 362.73874 362.75226 362.76575 362.77924 + 362.79276 362.80624 362.81976 362.83325 362.84674 362.86026 362.87375 + 362.88724 362.90076 362.91425 362.92776 362.94125 362.95474 362.96826 + 362.98175 362.99524 363.00876 363.02225 363.03574 363.04926 363.06274 + 363.07626 363.08975 363.10324 363.11676 363.13025 363.14374 363.15726 + 363.17075 363.18427 363.19775 363.21124 363.22476 363.23825 363.25174 + 363.26526 363.27875 363.29224 363.30576 363.31952 363.33377 363.34857 + 363.36395 363.3799 363.39645 363.4136 363.43143 363.44992 363.46912 + 363.489 363.50967 363.5311 363.55334 363.57642 363.60037 363.6252 + 363.651 363.67776 363.7055 363.7343 363.767 363.803 363.839 + 363.875 363.911 363.947 363.983 364.019 364.055 364.091 + 364.127 364.163 364.199 364.235 364.271 364.307 364.343 + 364.379 364.415 364.451 364.487 364.523 364.559 364.595 + 364.631 364.667 364.703 364.739 364.775 364.811 364.847 + 364.883 364.919 364.955 364.991 365.027 365.063 365.099 + 365.135 365.171 ] + x_upper_bound: [353.0705 353.1065 353.1425 353.1785 353.2145 353.2505 353.2865 + 353.3225 353.3585 353.3945 353.4305 353.4665 353.5025 353.5385 + 353.5745 353.6105 353.6465 353.6825 353.7185 353.7545 353.7905 + 353.8265 353.8625 353.8985 353.9345 353.9705 354.0065 354.0425 + 354.0785 354.1145 354.1505 354.1865 354.2225 354.2585 354.2945 + 354.3305 354.3665 354.4025 354.4385 354.4745 354.50717 354.53598 + 354.56375 354.5905 354.61627 354.64114 354.66507 354.68817 354.7104 + 354.73184 354.7525 354.7724 354.7916 354.81006 354.82788 354.84506 + 354.8616 354.87753 354.8929 354.9077 354.922 354.93576 354.94925 + 354.96274 354.97626 354.98975 355.00323 355.01675 355.03024 355.04376 + 355.05725 355.07074 355.08426 355.09775 355.11124 355.12476 355.13824 + 355.15176 355.16525 355.17874 355.19226 355.20575 355.21924 355.23276 + 355.24625 355.25974 355.27325 355.28674 355.30026 355.31375 355.32724 + 355.34076 355.35425 355.36774 355.38126 355.39474 355.40826 355.42175 + 355.43524 355.44876 355.46225 355.47574 355.48926 355.50275 355.51624 + 355.52975 355.54324 355.55676 355.57025 355.58374 355.59726 355.61075 + 355.62424 355.63776 355.65125 355.66476 355.67825 355.69174 355.70526 + 355.71875 355.73224 355.74576 355.75925 355.77274 355.78625 355.79974 + 355.81326 355.82675 355.84024 355.85376 355.86725 355.88074 355.89426 + 355.90775 355.92126 355.93475 355.94824 355.96176 355.97525 355.98874 + 356.00226 356.01575 356.02924 356.04276 356.05624 356.06976 356.08325 + 356.09674 356.11026 356.12375 356.13724 356.15076 356.16425 356.17776 + 356.19125 356.20474 356.21826 356.23175 356.24524 356.25876 356.27225 + 356.28574 356.29926 356.31274 356.32626 356.33975 356.35324 356.36676 + 356.38025 356.39374 356.40726 356.42075 356.43427 356.44775 356.46124 + 356.47476 356.48825 356.50174 356.51526 356.52875 356.54224 356.55576 + 356.56924 356.58276 356.59625 356.60974 356.62326 356.63675 356.65024 + 356.66376 356.67725 356.69073 356.70425 356.71774 356.73126 356.74475 + 356.75824 356.77176 356.78525 356.79874 356.81226 356.82574 356.83926 + 356.85275 356.86624 356.87976 356.89325 356.90674 356.92026 356.93375 + 356.94724 356.96075 356.97424 356.98776 357.00125 357.01474 357.02826 + 357.04175 357.05524 357.06876 357.08224 357.09576 357.10925 357.12274 + 357.13626 357.14975 357.16324 357.17676 357.19025 357.20374 357.21725 + 357.23074 357.24426 357.25775 357.27124 357.28476 357.29825 357.31174 + 357.32526 357.33875 357.35226 357.36575 357.37924 357.39276 357.40625 + 357.41974 357.43326 357.44675 357.46024 357.47375 357.48724 357.50076 + 357.51425 357.52774 357.54126 357.55475 357.56824 357.58176 357.59525 + 357.60876 357.62225 357.63574 357.64926 357.66275 357.67624 357.68976 + 357.70325 357.71674 357.73026 357.74374 357.75726 357.77075 357.78424 + 357.79776 357.81125 357.82474 357.83826 357.85175 357.86526 357.87875 + 357.89224 357.90576 357.91925 357.93274 357.94626 357.95975 357.97324 + 357.98676 358.00024 358.01376 358.02725 358.04074 358.05426 358.06775 + 358.08124 358.09476 358.10825 358.12177 358.13525 358.14874 358.16226 + 358.17575 358.18924 358.20276 358.21625 358.22974 358.24326 358.25674 + 358.27026 358.28375 358.29724 358.31076 358.32425 358.33774 358.35126 + 358.36475 358.37823 358.39175 358.40524 358.41876 358.43225 358.44574 + 358.45926 358.47275 358.48624 358.49976 358.51324 358.52676 358.54025 + 358.55374 358.56726 358.58075 358.59424 358.60776 358.62125 358.63474 + 358.64825 358.66174 358.67526 358.68875 358.70224 358.71576 358.72925 + 358.74274 358.75626 358.76974 358.78326 358.79675 358.81024 358.82376 + 358.83725 358.85074 358.86426 358.87775 358.89124 358.90475 358.91824 + 358.93176 358.94525 358.95874 358.97226 358.98575 358.99924 359.01276 + 359.02625 359.03976 359.05325 359.06674 359.08026 359.09375 359.10724 + 359.12076 359.13425 359.14774 359.16125 359.17474 359.18826 359.20175 + 359.21524 359.22876 359.24225 359.25574 359.26926 359.28275 359.29626 + 359.30975 359.32324 359.33676 359.35025 359.36374 359.37726 359.39075 + 359.40424 359.41776 359.43124 359.44476 359.45825 359.47174 359.48526 + 359.49875 359.51224 359.52576 359.53925 359.55276 359.56625 359.57974 + 359.59326 359.60675 359.62024 359.63376 359.64725 359.66074 359.67426 + 359.68774 359.70126 359.71475 359.72824 359.74176 359.75525 359.76874 + 359.78226 359.79575 359.80927 359.82275 359.83624 359.84976 359.86325 + 359.87674 359.89026 359.90375 359.91724 359.93076 359.94424 359.95776 + 359.97125 359.98474 359.99826 360.01175 360.02524 360.03876 360.05225 + 360.06573 360.07925 360.09274 360.10626 360.11975 360.13324 360.14676 + 360.16025 360.17374 360.18726 360.20074 360.21426 360.22775 360.24124 + 360.25476 360.26825 360.28174 360.29526 360.30875 360.32224 360.33575 + 360.34924 360.36276 360.37625 360.38974 360.40326 360.41675 360.43024 + 360.44376 360.45724 360.47076 360.48425 360.49774 360.51126 360.52475 + 360.53824 360.55176 360.56525 360.57874 360.59225 360.60574 360.61926 + 360.63275 360.64624 360.65976 360.67325 360.68674 360.70026 360.71375 + 360.72726 360.74075 360.75424 360.76776 360.78125 360.79474 360.80826 + 360.82175 360.83524 360.84875 360.86224 360.87576 360.88925 360.90274 + 360.91626 360.92975 360.94324 360.95676 360.97025 360.98376 360.99725 + 361.01074 361.02426 361.03775 361.05124 361.06476 361.07825 361.09174 + 361.10526 361.11874 361.13226 361.14575 361.15924 361.17276 361.18625 + 361.19974 361.21326 361.22675 361.24026 361.25375 361.26724 361.28076 + 361.29425 361.30774 361.32126 361.33475 361.34824 361.36176 361.37524 + 361.38876 361.40225 361.41574 361.42926 361.44275 361.45624 361.46976 + 361.48325 361.49677 361.51025 361.52374 361.53726 361.55075 361.56424 + 361.57776 361.59125 361.60474 361.61826 361.63174 361.64526 361.65875 + 361.67224 361.68576 361.69925 361.71274 361.72626 361.73975 361.75323 + 361.76675 361.78024 361.79376 361.80725 361.82074 361.83426 361.84775 + 361.86124 361.87476 361.88824 361.90176 361.91525 361.92874 361.94226 + 361.95575 361.96924 361.98276 361.99625 362.00974 362.02325 362.03674 + 362.05026 362.06375 362.07724 362.09076 362.10425 362.11774 362.13126 + 362.14474 362.15826 362.17175 362.18524 362.19876 362.21225 362.22574 + 362.23926 362.25275 362.26624 362.27975 362.29324 362.30676 362.32025 + 362.33374 362.34726 362.36075 362.37424 362.38776 362.40125 362.41476 + 362.42825 362.44174 362.45526 362.46875 362.48224 362.49576 362.50925 + 362.52274 362.53625 362.54974 362.56326 362.57675 362.59024 362.60376 + 362.61725 362.63074 362.64426 362.65775 362.67126 362.68475 362.69824 + 362.71176 362.72525 362.73874 362.75226 362.76575 362.77924 362.79276 + 362.80624 362.81976 362.83325 362.84674 362.86026 362.87375 362.88724 + 362.90076 362.91425 362.92776 362.94125 362.95474 362.96826 362.98175 + 362.99524 363.00876 363.02225 363.03574 363.04926 363.06274 363.07626 + 363.08975 363.10324 363.11676 363.13025 363.14374 363.15726 363.17075 + 363.18427 363.19775 363.21124 363.22476 363.23825 363.25174 363.26526 + 363.27875 363.29224 363.30576 363.31952 363.33377 363.34857 363.36395 + 363.3799 363.39645 363.4136 363.43143 363.44992 363.46912 363.489 + 363.50967 363.5311 363.55334 363.57642 363.60037 363.6252 363.651 + 363.67776 363.7055 363.7343 363.767 363.803 363.839 363.875 + 363.911 363.947 363.983 364.019 364.055 364.091 364.127 + 364.163 364.199 364.235 364.271 364.307 364.343 364.379 + 364.415 364.451 364.487 364.523 364.559 364.595 364.631 + 364.667 364.703 364.739 364.775 364.811 364.847 364.883 + 364.919 364.955 364.991 365.027 365.063 365.099 365.135 + 365.171 365.207 ] + y: [-5.5932002e+00 -5.5572000e+00 -5.5212002e+00 -5.4851999e+00 + -5.4492002e+00 -5.4131999e+00 -5.3772001e+00 -5.3411999e+00 + -5.3052001e+00 -5.2691998e+00 -5.2332001e+00 -5.1971998e+00 + -5.1612000e+00 -5.1251998e+00 -5.0892000e+00 -5.0531998e+00 + -5.0172000e+00 -4.9812002e+00 -4.9452000e+00 -4.9092002e+00 + -4.8731999e+00 -4.8372002e+00 -4.8011999e+00 -4.7652001e+00 + -4.7291999e+00 -4.6932001e+00 -4.6571999e+00 -4.6212001e+00 + -4.5851998e+00 -4.5492001e+00 -4.5131998e+00 -4.4772000e+00 + -4.4411998e+00 -4.4052000e+00 -4.3692002e+00 -4.3332000e+00 + -4.2972002e+00 -4.2612000e+00 -4.2252002e+00 -4.1937799e+00 + -4.1635985e+00 -4.1346073e+00 -4.1067591e+00 -4.0800085e+00 + -4.0543132e+00 -4.0296307e+00 -4.0059214e+00 -3.9831471e+00 + -3.9612706e+00 -3.9402568e+00 -3.9200714e+00 -3.9006820e+00 + -3.8820570e+00 -3.8641663e+00 -3.8469810e+00 -3.8304734e+00 + -3.8146167e+00 -3.7993851e+00 -3.7847540e+00 -3.7707000e+00 + -3.7572000e+00 -3.7437000e+00 -3.7302001e+00 -3.7167001e+00 + -3.7032001e+00 -3.6896999e+00 -3.6761999e+00 -3.6626999e+00 + -3.6492000e+00 -3.6357000e+00 -3.6222000e+00 -3.6087000e+00 + -3.5952001e+00 -3.5817001e+00 -3.5682001e+00 -3.5546999e+00 + -3.5411999e+00 -3.5276999e+00 -3.5142000e+00 -3.5007000e+00 + -3.4872000e+00 -3.4737000e+00 -3.4602001e+00 -3.4467001e+00 + -3.4331999e+00 -3.4196999e+00 -3.4061999e+00 -3.3927000e+00 + -3.3792000e+00 -3.3657000e+00 -3.3522000e+00 -3.3387001e+00 + -3.3252001e+00 -3.3117001e+00 -3.2981999e+00 -3.2846999e+00 + -3.2711999e+00 -3.2577000e+00 -3.2442000e+00 -3.2307000e+00 + -3.2172000e+00 -3.2037001e+00 -3.1902001e+00 -3.1767001e+00 + -3.1631999e+00 -3.1496999e+00 -3.1362000e+00 -3.1227000e+00 + -3.1092000e+00 -3.0957000e+00 -3.0822001e+00 -3.0687001e+00 + -3.0552001e+00 -3.0416999e+00 -3.0281999e+00 -3.0146999e+00 + -3.0012000e+00 -2.9877000e+00 -2.9742000e+00 -2.9607000e+00 + -2.9472001e+00 -2.9337001e+00 -2.9202001e+00 -2.9066999e+00 + -2.8931999e+00 -2.8796999e+00 -2.8662000e+00 -2.8527000e+00 + -2.8392000e+00 -2.8257000e+00 -2.8122001e+00 -2.7987001e+00 + -2.7852001e+00 -2.7716999e+00 -2.7581999e+00 -2.7447000e+00 + -2.7312000e+00 -2.7177000e+00 -2.7042000e+00 -2.6907001e+00 + -2.6772001e+00 -2.6637001e+00 -2.6501999e+00 -2.6366999e+00 + -2.6231999e+00 -2.6097000e+00 -2.5962000e+00 -2.5827000e+00 + -2.5692000e+00 -2.5557001e+00 -2.5422001e+00 -2.5287001e+00 + -2.5151999e+00 -2.5016999e+00 -2.4881999e+00 -2.4747000e+00 + -2.4612000e+00 -2.4477000e+00 -2.4342000e+00 -2.4207001e+00 + -2.4072001e+00 -2.3936999e+00 -2.3801999e+00 -2.3666999e+00 + -2.3532000e+00 -2.3397000e+00 -2.3262000e+00 -2.3127000e+00 + -2.2992001e+00 -2.2857001e+00 -2.2722001e+00 -2.2586999e+00 + -2.2451999e+00 -2.2316999e+00 -2.2182000e+00 -2.2047000e+00 + -2.1912000e+00 -2.1777000e+00 -2.1642001e+00 -2.1507001e+00 + -2.1372001e+00 -2.1236999e+00 -2.1101999e+00 -2.0967000e+00 + -2.0832000e+00 -2.0697000e+00 -2.0562000e+00 -2.0427001e+00 + -2.0292001e+00 -2.0157001e+00 -2.0021999e+00 -1.9887000e+00 + -1.9752001e+00 -1.9617000e+00 -1.9482000e+00 -1.9347000e+00 + -1.9212000e+00 -1.9076999e+00 -1.8942000e+00 -1.8807000e+00 + -1.8672000e+00 -1.8537000e+00 -1.8401999e+00 -1.8267000e+00 + -1.8132000e+00 -1.7997000e+00 -1.7862000e+00 -1.7727000e+00 + -1.7592000e+00 -1.7457000e+00 -1.7322000e+00 -1.7187001e+00 + -1.7052000e+00 -1.6917000e+00 -1.6782000e+00 -1.6647000e+00 + -1.6512001e+00 -1.6377000e+00 -1.6242000e+00 -1.6107000e+00 + -1.5972000e+00 -1.5836999e+00 -1.5702000e+00 -1.5567000e+00 + -1.5432000e+00 -1.5297000e+00 -1.5161999e+00 -1.5027000e+00 + -1.4892000e+00 -1.4757000e+00 -1.4622000e+00 -1.4487000e+00 + -1.4352000e+00 -1.4217000e+00 -1.4082000e+00 -1.3947001e+00 + -1.3812000e+00 -1.3677000e+00 -1.3542000e+00 -1.3407000e+00 + -1.3272001e+00 -1.3137000e+00 -1.3002000e+00 -1.2867000e+00 + -1.2732000e+00 -1.2596999e+00 -1.2462000e+00 -1.2327000e+00 + -1.2192000e+00 -1.2057000e+00 -1.1921999e+00 -1.1787000e+00 + -1.1652000e+00 -1.1517000e+00 -1.1382000e+00 -1.1247000e+00 + -1.1112000e+00 -1.0977000e+00 -1.0842000e+00 -1.0707000e+00 + -1.0572000e+00 -1.0437000e+00 -1.0302000e+00 -1.0167000e+00 + -1.0032001e+00 -9.8970002e-01 -9.7619998e-01 -9.6270001e-01 + -9.4919997e-01 -9.3570000e-01 -9.2220002e-01 -9.0869999e-01 + -8.9520001e-01 -8.8169998e-01 -8.6820000e-01 -8.5470003e-01 + -8.4119999e-01 -8.2770002e-01 -8.1419998e-01 -8.0070001e-01 + -7.8719997e-01 -7.7370000e-01 -7.6020002e-01 -7.4669999e-01 + -7.3320001e-01 -7.1969998e-01 -7.0620000e-01 -6.9270003e-01 + -6.7919999e-01 -6.6570002e-01 -6.5219998e-01 -6.3870001e-01 + -6.2519997e-01 -6.1170000e-01 -5.9820002e-01 -5.8469999e-01 + -5.7120001e-01 -5.5769998e-01 -5.4420000e-01 -5.3070003e-01 + -5.1719999e-01 -5.0370002e-01 -4.9020001e-01 -4.7670001e-01 + -4.6320000e-01 -4.4970000e-01 -4.3619999e-01 -4.2269999e-01 + -4.0920001e-01 -3.9570001e-01 -3.8220000e-01 -3.6870000e-01 + -3.5519999e-01 -3.4169999e-01 -3.2820001e-01 -3.1470001e-01 + -3.0120000e-01 -2.8770000e-01 -2.7419999e-01 -2.6069999e-01 + -2.4720000e-01 -2.3370001e-01 -2.2020000e-01 -2.0670000e-01 + -1.9320001e-01 -1.7970000e-01 -1.6620000e-01 -1.5270001e-01 + -1.3920000e-01 -1.2570000e-01 -1.1220000e-01 -9.8700002e-02 + -8.5199997e-02 -7.1699999e-02 -5.8200002e-02 -4.4700000e-02 + -3.1199999e-02 -1.7700000e-02 -4.1999999e-03 9.3000000e-03 + 2.2800000e-02 3.6300000e-02 4.9800001e-02 6.3299999e-02 + 7.6800004e-02 9.0300001e-02 1.0380000e-01 1.1730000e-01 + 1.3079999e-01 1.4430000e-01 1.5780000e-01 1.7129999e-01 + 1.8480000e-01 1.9830000e-01 2.1179999e-01 2.2530000e-01 + 2.3880000e-01 2.5229999e-01 2.6580000e-01 2.7930000e-01 + 2.9280001e-01 3.0630001e-01 3.1979999e-01 3.3329999e-01 + 3.4680000e-01 3.6030000e-01 3.7380001e-01 3.8730001e-01 + 4.0079999e-01 4.1429999e-01 4.2780000e-01 4.4130000e-01 + 4.5480001e-01 4.6830001e-01 4.8179999e-01 4.9529999e-01 + 5.0880003e-01 5.2230000e-01 5.3579998e-01 5.4930001e-01 + 5.6279999e-01 5.7630002e-01 5.8980000e-01 6.0329998e-01 + 6.1680001e-01 6.3029999e-01 6.4380002e-01 6.5730000e-01 + 6.7079997e-01 6.8430001e-01 6.9779998e-01 7.1130002e-01 + 7.2479999e-01 7.3830003e-01 7.5180000e-01 7.6529998e-01 + 7.7880001e-01 7.9229999e-01 8.0580002e-01 8.1930000e-01 + 8.3279997e-01 8.4630001e-01 8.5979998e-01 8.7330002e-01 + 8.8679999e-01 9.0030003e-01 9.1380000e-01 9.2729998e-01 + 9.4080001e-01 9.5429999e-01 9.6780002e-01 9.8130000e-01 + 9.9479997e-01 1.0082999e+00 1.0218000e+00 1.0353000e+00 + 1.0488000e+00 1.0623000e+00 1.0757999e+00 1.0893000e+00 + 1.1028000e+00 1.1163000e+00 1.1298000e+00 1.1433001e+00 + 1.1568000e+00 1.1703000e+00 1.1838000e+00 1.1973000e+00 + 1.2108001e+00 1.2243000e+00 1.2378000e+00 1.2513000e+00 + 1.2648000e+00 1.2783000e+00 1.2918000e+00 1.3053000e+00 + 1.3188000e+00 1.3322999e+00 1.3458000e+00 1.3593000e+00 + 1.3728000e+00 1.3863000e+00 1.3997999e+00 1.4133000e+00 + 1.4268000e+00 1.4403000e+00 1.4538000e+00 1.4673001e+00 + 1.4808000e+00 1.4943000e+00 1.5078000e+00 1.5213000e+00 + 1.5348001e+00 1.5483000e+00 1.5618000e+00 1.5753000e+00 + 1.5888000e+00 1.6023000e+00 1.6158000e+00 1.6293000e+00 + 1.6428000e+00 1.6562999e+00 1.6698000e+00 1.6833000e+00 + 1.6968000e+00 1.7103000e+00 1.7237999e+00 1.7373000e+00 + 1.7508000e+00 1.7643000e+00 1.7778000e+00 1.7913001e+00 + 1.8048000e+00 1.8183000e+00 1.8318000e+00 1.8453000e+00 + 1.8588001e+00 1.8723000e+00 1.8858000e+00 1.8993000e+00 + 1.9128000e+00 1.9263000e+00 1.9398000e+00 1.9533000e+00 + 1.9668000e+00 1.9802999e+00 1.9938000e+00 2.0072999e+00 + 2.0208001e+00 2.0343001e+00 2.0478001e+00 2.0613000e+00 + 2.0748000e+00 2.0883000e+00 2.1018000e+00 2.1152999e+00 + 2.1287999e+00 2.1422999e+00 2.1558001e+00 2.1693001e+00 + 2.1828001e+00 2.1963000e+00 2.2098000e+00 2.2233000e+00 + 2.2368000e+00 2.2502999e+00 2.2637999e+00 2.2772999e+00 + 2.2908001e+00 2.3043001e+00 2.3178000e+00 2.3313000e+00 + 2.3448000e+00 2.3583000e+00 2.3717999e+00 2.3852999e+00 + 2.3987999e+00 2.4123001e+00 2.4258001e+00 2.4393001e+00 + 2.4528000e+00 2.4663000e+00 2.4798000e+00 2.4933000e+00 + 2.5067999e+00 2.5202999e+00 2.5337999e+00 2.5473001e+00 + 2.5608001e+00 2.5743001e+00 2.5878000e+00 2.6013000e+00 + 2.6148000e+00 2.6283000e+00 2.6417999e+00 2.6552999e+00 + 2.6688001e+00 2.6823001e+00 2.6958001e+00 2.7093000e+00 + 2.7228000e+00 2.7363000e+00 2.7498000e+00 2.7632999e+00 + 2.7767999e+00 2.7902999e+00 2.8038001e+00 2.8173001e+00 + 2.8308001e+00 2.8443000e+00 2.8578000e+00 2.8713000e+00 + 2.8848000e+00 2.8982999e+00 2.9117999e+00 2.9252999e+00 + 2.9388001e+00 2.9523001e+00 2.9658000e+00 2.9793000e+00 + 2.9928000e+00 3.0063000e+00 3.0197999e+00 3.0332999e+00 + 3.0467999e+00 3.0603001e+00 3.0738001e+00 3.0873001e+00 + 3.1008000e+00 3.1143000e+00 3.1278000e+00 3.1413000e+00 + 3.1547999e+00 3.1682999e+00 3.1817999e+00 3.1953001e+00 + 3.2088001e+00 3.2223001e+00 3.2358000e+00 3.2493000e+00 + 3.2628000e+00 3.2763000e+00 3.2897999e+00 3.3032999e+00 + 3.3168001e+00 3.3303001e+00 3.3438001e+00 3.3573000e+00 + 3.3708000e+00 3.3843000e+00 3.3978000e+00 3.4112999e+00 + 3.4247999e+00 3.4382999e+00 3.4518001e+00 3.4653001e+00 + 3.4788001e+00 3.4923000e+00 3.5058000e+00 3.5193000e+00 + 3.5328000e+00 3.5462999e+00 3.5597999e+00 3.5732999e+00 + 3.5868001e+00 3.6003001e+00 3.6138000e+00 3.6273000e+00 + 3.6408000e+00 3.6543000e+00 3.6677999e+00 3.6812999e+00 + 3.6947999e+00 3.7083001e+00 3.7218001e+00 3.7353001e+00 + 3.7488000e+00 3.7623000e+00 3.7758000e+00 3.7893000e+00 + 3.8027999e+00 3.8162999e+00 3.8297999e+00 3.8433001e+00 + 3.8568001e+00 3.8703001e+00 3.8838000e+00 3.8973000e+00 + 3.9108000e+00 3.9243000e+00 3.9377999e+00 3.9512999e+00 + 3.9647999e+00 3.9783001e+00 3.9918001e+00 4.0053000e+00 + 4.0187998e+00 4.0323000e+00 4.0458002e+00 4.0592999e+00 + 4.0728002e+00 4.0862999e+00 4.0998001e+00 4.1132998e+00 + 4.1268001e+00 4.1402998e+00 4.1538000e+00 4.1673002e+00 + 4.1808000e+00 4.1943002e+00 4.2077999e+00 4.2213001e+00 + 4.2347999e+00 4.2483001e+00 4.2617998e+00 4.2753000e+00 + 4.2887998e+00 4.3023000e+00 4.3158002e+00 4.3292999e+00 + 4.3428001e+00 4.3562999e+00 4.3698001e+00 4.3832998e+00 + 4.3968000e+00 4.4102998e+00 4.4238000e+00 4.4373002e+00 + 4.4507999e+00 4.4643002e+00 4.4777999e+00 4.4913001e+00 + 4.5047998e+00 4.5183001e+00 4.5317998e+00 4.5453000e+00 + 4.5588002e+00 4.5723000e+00 4.5858002e+00 4.5992999e+00 + 4.6128001e+00 4.6262999e+00 4.6398001e+00 4.6532998e+00 + 4.6668000e+00 4.6803002e+00 4.6938000e+00 4.7073002e+00 + 4.7207999e+00 4.7343001e+00 4.7477999e+00 4.7613001e+00 + 4.7747998e+00 4.7883000e+00 4.8017998e+00 4.8153000e+00 + 4.8288002e+00 4.8422999e+00 4.8558002e+00 4.8692999e+00 + 4.8828001e+00 4.8962998e+00 4.9098001e+00 4.9232998e+00 + 4.9368000e+00 4.9503002e+00 4.9638000e+00 4.9773002e+00 + 4.9907999e+00 5.0043001e+00 5.0177999e+00 5.0313001e+00 + 5.0447998e+00 5.0583000e+00 5.0718002e+00 5.0853000e+00 + 5.0988002e+00 5.1122999e+00 5.1258001e+00 5.1392999e+00 + 5.1528001e+00 5.1662998e+00 5.1798000e+00 5.1932998e+00 + 5.2068000e+00 5.2203002e+00 5.2337999e+00 5.2473001e+00 + 5.2607999e+00 5.2743001e+00 5.2877998e+00 5.3013000e+00 + 5.3147998e+00 5.3283000e+00 5.3418002e+00 5.3552999e+00 + 5.3688002e+00 5.3822999e+00 5.3958001e+00 5.4092999e+00 + 5.4228001e+00 5.4362998e+00 5.4498000e+00 5.4633002e+00 + 5.4768000e+00 5.4903002e+00 5.5037999e+00 5.5173001e+00 + 5.5307999e+00 5.5443001e+00 5.5577998e+00 5.5713000e+00 + 5.5847998e+00 5.5983000e+00 5.6118002e+00 5.6252999e+00 + 5.6388001e+00 5.6522999e+00 5.6658001e+00 5.6792998e+00 + 5.6928000e+00 5.7062998e+00 5.7198000e+00 5.7333002e+00 + 5.7467999e+00 5.7603002e+00 5.7737999e+00 5.7873001e+00 + 5.8007998e+00 5.8143001e+00 5.8277998e+00 5.8413000e+00 + 5.8548002e+00 5.8683000e+00 5.8818002e+00 5.8952999e+00 + 5.9088001e+00 5.9222999e+00 5.9358001e+00 5.9492998e+00 + 5.9628000e+00 5.9762998e+00 5.9898000e+00 6.0033002e+00 + 6.0167999e+00 6.0303001e+00 6.0437999e+00 6.0573001e+00 + 6.0707998e+00 6.0843000e+00 6.0977998e+00 6.1113000e+00 + 6.1248002e+00 6.1382999e+00 6.1518002e+00 6.1652999e+00 + 6.1788001e+00 6.1922998e+00 6.2058001e+00 6.2192998e+00 + 6.2328000e+00 6.2463002e+00 6.2598000e+00 6.2733002e+00 + 6.2867999e+00 6.3003001e+00 6.3137999e+00 6.3273001e+00 + 6.3407998e+00 6.3543000e+00 6.3678002e+00 6.3813000e+00 + 6.3948002e+00 6.4082999e+00 6.4218001e+00 6.4352999e+00 + 6.4488001e+00 6.4622998e+00 6.4758000e+00 6.4892998e+00 + 6.5028000e+00 6.5163002e+00 6.5297999e+00 6.5433002e+00 + 6.5567999e+00 6.5703001e+00 6.5837998e+00 6.5973001e+00 + 6.6107998e+00 6.6243000e+00 6.6378002e+00 6.6513000e+00 + 6.6648002e+00 6.6782999e+00 6.6918001e+00 6.7052999e+00 + 6.7188001e+00 6.7322998e+00 6.7458000e+00 6.7593002e+00 + 6.7728000e+00 6.7863002e+00 6.7997999e+00 6.8133001e+00 + 6.8267999e+00 6.8403001e+00 6.8537998e+00 6.8673000e+00 + 6.8807998e+00 6.8943000e+00 6.9078002e+00 6.9212999e+00 + 6.9348001e+00 6.9482999e+00 6.9618001e+00 6.9752998e+00 + 6.9888000e+00 7.0022998e+00 7.0158000e+00 7.0293002e+00 + 7.0427999e+00 7.0563002e+00 7.0697999e+00 7.0833001e+00 + 7.0967999e+00 7.1103001e+00 7.1237998e+00 7.1373000e+00 + 7.1508002e+00 7.1648540e+00 7.1794853e+00 7.1947169e+00 + 7.2105737e+00 7.2270813e+00 7.2442665e+00 7.2621570e+00 + 7.2807817e+00 7.3001714e+00 7.3203568e+00 7.3413706e+00 + 7.3632469e+00 7.3860216e+00 7.4097309e+00 7.4344130e+00 + 7.4601088e+00 7.4868588e+00 7.5147071e+00 7.5436983e+00 + 7.5738797e+00 7.6052999e+00 7.6413002e+00 7.6773000e+00 + 7.7133002e+00 7.7493000e+00 7.7852998e+00 7.8213000e+00 + 7.8572998e+00 7.8933001e+00 7.9292998e+00 7.9653001e+00 + 8.0012999e+00 8.0373001e+00 8.0733004e+00 8.1092997e+00 + 8.1452999e+00 8.1813002e+00 8.2173004e+00 8.2532997e+00 + 8.2893000e+00 8.3253002e+00 8.3613005e+00 8.3972998e+00 + 8.4333000e+00 8.4693003e+00 8.5052996e+00 8.5412998e+00 + 8.5773001e+00 8.6133003e+00 8.6492996e+00 8.6852999e+00 + 8.7213001e+00 8.7573004e+00 8.7932997e+00 8.8292999e+00 + 8.8653002e+00 8.9013004e+00 8.9372997e+00 8.9733000e+00] + y_lower_bound: [-5.6112003e+00 -5.5752001e+00 -5.5391998e+00 -5.5032001e+00 + -5.4671998e+00 -5.4312000e+00 -5.3951998e+00 -5.3592000e+00 + -5.3232002e+00 -5.2872000e+00 -5.2512002e+00 -5.2151999e+00 + -5.1792002e+00 -5.1431999e+00 -5.1072001e+00 -5.0711999e+00 + -5.0352001e+00 -4.9991999e+00 -4.9632001e+00 -4.9271998e+00 + -4.8912001e+00 -4.8551998e+00 -4.8192000e+00 -4.7831998e+00 + -4.7472000e+00 -4.7112002e+00 -4.6752000e+00 -4.6392002e+00 + -4.6032000e+00 -4.5672002e+00 -4.5311999e+00 -4.4952002e+00 + -4.4591999e+00 -4.4232001e+00 -4.3871999e+00 -4.3512001e+00 + -4.3151999e+00 -4.2792001e+00 -4.2431998e+00 -4.2094898e+00 + -4.1786890e+00 -4.1491027e+00 -4.1206832e+00 -4.0933838e+00 + -4.0671611e+00 -4.0419717e+00 -4.0177760e+00 -3.9945343e+00 + -3.9722090e+00 -3.9507637e+00 -3.9301641e+00 -3.9103768e+00 + -3.8913693e+00 -3.8731117e+00 -3.8555737e+00 -3.8387272e+00 + -3.8225451e+00 -3.8070009e+00 -3.7920697e+00 -3.7777271e+00 + -3.7639501e+00 -3.7504499e+00 -3.7369499e+00 -3.7234499e+00 + -3.7099500e+00 -3.6964500e+00 -3.6829500e+00 -3.6694500e+00 + -3.6559501e+00 -3.6424501e+00 -3.6289501e+00 -3.6154499e+00 + -3.6019499e+00 -3.5884500e+00 -3.5749500e+00 -3.5614500e+00 + -3.5479500e+00 -3.5344501e+00 -3.5209501e+00 -3.5074501e+00 + -3.4939499e+00 -3.4804499e+00 -3.4669499e+00 -3.4534500e+00 + -3.4399500e+00 -3.4264500e+00 -3.4129500e+00 -3.3994501e+00 + -3.3859501e+00 -3.3724501e+00 -3.3589499e+00 -3.3454499e+00 + -3.3319499e+00 -3.3184500e+00 -3.3049500e+00 -3.2914500e+00 + -3.2779500e+00 -3.2644501e+00 -3.2509501e+00 -3.2374499e+00 + -3.2239499e+00 -3.2104499e+00 -3.1969500e+00 -3.1834500e+00 + -3.1699500e+00 -3.1564500e+00 -3.1429501e+00 -3.1294501e+00 + -3.1159501e+00 -3.1024499e+00 -3.0889499e+00 -3.0754499e+00 + -3.0619500e+00 -3.0484500e+00 -3.0349500e+00 -3.0214500e+00 + -3.0079501e+00 -2.9944501e+00 -2.9809501e+00 -2.9674499e+00 + -2.9539499e+00 -2.9404500e+00 -2.9269500e+00 -2.9134500e+00 + -2.8999500e+00 -2.8864501e+00 -2.8729501e+00 -2.8594501e+00 + -2.8459499e+00 -2.8324499e+00 -2.8189499e+00 -2.8054500e+00 + -2.7919500e+00 -2.7784500e+00 -2.7649500e+00 -2.7514501e+00 + -2.7379501e+00 -2.7244501e+00 -2.7109499e+00 -2.6974499e+00 + -2.6839499e+00 -2.6704500e+00 -2.6569500e+00 -2.6434500e+00 + -2.6299500e+00 -2.6164501e+00 -2.6029501e+00 -2.5894499e+00 + -2.5759499e+00 -2.5624499e+00 -2.5489500e+00 -2.5354500e+00 + -2.5219500e+00 -2.5084500e+00 -2.4949501e+00 -2.4814501e+00 + -2.4679501e+00 -2.4544499e+00 -2.4409499e+00 -2.4274499e+00 + -2.4139500e+00 -2.4004500e+00 -2.3869500e+00 -2.3734500e+00 + -2.3599501e+00 -2.3464501e+00 -2.3329501e+00 -2.3194499e+00 + -2.3059499e+00 -2.2924500e+00 -2.2789500e+00 -2.2654500e+00 + -2.2519500e+00 -2.2384501e+00 -2.2249501e+00 -2.2114501e+00 + -2.1979499e+00 -2.1844499e+00 -2.1709499e+00 -2.1574500e+00 + -2.1439500e+00 -2.1304500e+00 -2.1169500e+00 -2.1034501e+00 + -2.0899501e+00 -2.0764501e+00 -2.0629499e+00 -2.0494499e+00 + -2.0359499e+00 -2.0224500e+00 -2.0089500e+00 -1.9954500e+00 + -1.9819500e+00 -1.9684500e+00 -1.9549500e+00 -1.9414500e+00 + -1.9279500e+00 -1.9144500e+00 -1.9009500e+00 -1.8874500e+00 + -1.8739500e+00 -1.8604500e+00 -1.8469501e+00 -1.8334500e+00 + -1.8199500e+00 -1.8064500e+00 -1.7929500e+00 -1.7794501e+00 + -1.7659500e+00 -1.7524500e+00 -1.7389500e+00 -1.7254500e+00 + -1.7119499e+00 -1.6984500e+00 -1.6849500e+00 -1.6714500e+00 + -1.6579500e+00 -1.6444499e+00 -1.6309500e+00 -1.6174500e+00 + -1.6039500e+00 -1.5904500e+00 -1.5769500e+00 -1.5634500e+00 + -1.5499500e+00 -1.5364500e+00 -1.5229501e+00 -1.5094500e+00 + -1.4959500e+00 -1.4824500e+00 -1.4689500e+00 -1.4554501e+00 + -1.4419500e+00 -1.4284500e+00 -1.4149500e+00 -1.4014500e+00 + -1.3879499e+00 -1.3744500e+00 -1.3609500e+00 -1.3474500e+00 + -1.3339500e+00 -1.3204499e+00 -1.3069500e+00 -1.2934500e+00 + -1.2799500e+00 -1.2664500e+00 -1.2529500e+00 -1.2394500e+00 + -1.2259500e+00 -1.2124500e+00 -1.1989501e+00 -1.1854500e+00 + -1.1719500e+00 -1.1584500e+00 -1.1449500e+00 -1.1314501e+00 + -1.1179500e+00 -1.1044500e+00 -1.0909500e+00 -1.0774500e+00 + -1.0639499e+00 -1.0504500e+00 -1.0369500e+00 -1.0234500e+00 + -1.0099500e+00 -9.9645001e-01 -9.8294997e-01 -9.6945000e-01 + -9.5595002e-01 -9.4244999e-01 -9.2895001e-01 -9.1544998e-01 + -9.0195000e-01 -8.8845003e-01 -8.7494999e-01 -8.6145002e-01 + -8.4794998e-01 -8.3445001e-01 -8.2094997e-01 -8.0745000e-01 + -7.9395002e-01 -7.8044999e-01 -7.6695001e-01 -7.5344998e-01 + -7.3995000e-01 -7.2645003e-01 -7.1294999e-01 -6.9945002e-01 + -6.8594998e-01 -6.7245001e-01 -6.5894997e-01 -6.4545000e-01 + -6.3195002e-01 -6.1844999e-01 -6.0495001e-01 -5.9144998e-01 + -5.7795000e-01 -5.6445003e-01 -5.5094999e-01 -5.3745002e-01 + -5.2394998e-01 -5.1045001e-01 -4.9695000e-01 -4.8345000e-01 + -4.6994999e-01 -4.5644999e-01 -4.4295001e-01 -4.2945001e-01 + -4.1595000e-01 -4.0245000e-01 -3.8894999e-01 -3.7544999e-01 + -3.6195001e-01 -3.4845001e-01 -3.3495000e-01 -3.2145000e-01 + -3.0794999e-01 -2.9445001e-01 -2.8095001e-01 -2.6745000e-01 + -2.5395000e-01 -2.4044999e-01 -2.2695000e-01 -2.1345000e-01 + -1.9994999e-01 -1.8645000e-01 -1.7295000e-01 -1.5944999e-01 + -1.4595000e-01 -1.3245000e-01 -1.1895000e-01 -1.0545000e-01 + -9.1949999e-02 -7.8450002e-02 -6.4949997e-02 -5.1449999e-02 + -3.7950002e-02 -2.4450000e-02 -1.0950000e-02 2.5500001e-03 + 1.6050000e-02 2.9549999e-02 4.3049999e-02 5.6550000e-02 + 7.0050001e-02 8.3549999e-02 9.7050004e-02 1.1055000e-01 + 1.2405000e-01 1.3755000e-01 1.5105000e-01 1.6455001e-01 + 1.7805000e-01 1.9155000e-01 2.0505001e-01 2.1855000e-01 + 2.3205000e-01 2.4555001e-01 2.5905001e-01 2.7254999e-01 + 2.8604999e-01 2.9955000e-01 3.1305000e-01 3.2655001e-01 + 3.4005001e-01 3.5354999e-01 3.6704999e-01 3.8055000e-01 + 3.9405000e-01 4.0755001e-01 4.2105001e-01 4.3454999e-01 + 4.4804999e-01 4.6155000e-01 4.7505000e-01 4.8855001e-01 + 5.0204998e-01 5.1555002e-01 5.2904999e-01 5.4255003e-01 + 5.5605000e-01 5.6954998e-01 5.8305001e-01 5.9654999e-01 + 6.1005002e-01 6.2355000e-01 6.3704997e-01 6.5055001e-01 + 6.6404998e-01 6.7755002e-01 6.9104999e-01 7.0455003e-01 + 7.1805000e-01 7.3154998e-01 7.4505001e-01 7.5854999e-01 + 7.7205002e-01 7.8555000e-01 7.9904997e-01 8.1255001e-01 + 8.2604998e-01 8.3955002e-01 8.5304999e-01 8.6655003e-01 + 8.8005000e-01 8.9354998e-01 9.0705001e-01 9.2054999e-01 + 9.3405002e-01 9.4755000e-01 9.6104997e-01 9.7455001e-01 + 9.8804998e-01 1.0015500e+00 1.0150501e+00 1.0285500e+00 + 1.0420500e+00 1.0555500e+00 1.0690500e+00 1.0825500e+00 + 1.0960500e+00 1.1095500e+00 1.1230500e+00 1.1365499e+00 + 1.1500500e+00 1.1635500e+00 1.1770500e+00 1.1905500e+00 + 1.2040499e+00 1.2175500e+00 1.2310500e+00 1.2445500e+00 + 1.2580500e+00 1.2715501e+00 1.2850500e+00 1.2985500e+00 + 1.3120500e+00 1.3255500e+00 1.3390501e+00 1.3525500e+00 + 1.3660500e+00 1.3795500e+00 1.3930500e+00 1.4065500e+00 + 1.4200500e+00 1.4335500e+00 1.4470500e+00 1.4605500e+00 + 1.4740500e+00 1.4875500e+00 1.5010500e+00 1.5145500e+00 + 1.5280499e+00 1.5415500e+00 1.5550500e+00 1.5685500e+00 + 1.5820500e+00 1.5955499e+00 1.6090500e+00 1.6225500e+00 + 1.6360500e+00 1.6495500e+00 1.6630501e+00 1.6765500e+00 + 1.6900500e+00 1.7035500e+00 1.7170500e+00 1.7305501e+00 + 1.7440500e+00 1.7575500e+00 1.7710500e+00 1.7845500e+00 + 1.7980500e+00 1.8115500e+00 1.8250500e+00 1.8385500e+00 + 1.8520499e+00 1.8655500e+00 1.8790500e+00 1.8925500e+00 + 1.9060500e+00 1.9195499e+00 1.9330500e+00 1.9465500e+00 + 1.9600500e+00 1.9735500e+00 1.9870501e+00 2.0005500e+00 + 2.0140500e+00 2.0275500e+00 2.0410500e+00 2.0545499e+00 + 2.0680499e+00 2.0815499e+00 2.0950501e+00 2.1085501e+00 + 2.1220500e+00 2.1355500e+00 2.1490500e+00 2.1625500e+00 + 2.1760499e+00 2.1895499e+00 2.2030499e+00 2.2165501e+00 + 2.2300501e+00 2.2435501e+00 2.2570500e+00 2.2705500e+00 + 2.2840500e+00 2.2975500e+00 2.3110499e+00 2.3245499e+00 + 2.3380499e+00 2.3515501e+00 2.3650501e+00 2.3785501e+00 + 2.3920500e+00 2.4055500e+00 2.4190500e+00 2.4325500e+00 + 2.4460499e+00 2.4595499e+00 2.4730501e+00 2.4865501e+00 + 2.5000501e+00 2.5135500e+00 2.5270500e+00 2.5405500e+00 + 2.5540500e+00 2.5675499e+00 2.5810499e+00 2.5945499e+00 + 2.6080501e+00 2.6215501e+00 2.6350501e+00 2.6485500e+00 + 2.6620500e+00 2.6755500e+00 2.6890500e+00 2.7025499e+00 + 2.7160499e+00 2.7295499e+00 2.7430501e+00 2.7565501e+00 + 2.7700500e+00 2.7835500e+00 2.7970500e+00 2.8105500e+00 + 2.8240499e+00 2.8375499e+00 2.8510499e+00 2.8645501e+00 + 2.8780501e+00 2.8915501e+00 2.9050500e+00 2.9185500e+00 + 2.9320500e+00 2.9455500e+00 2.9590499e+00 2.9725499e+00 + 2.9860499e+00 2.9995501e+00 3.0130501e+00 3.0265501e+00 + 3.0400500e+00 3.0535500e+00 3.0670500e+00 3.0805500e+00 + 3.0940499e+00 3.1075499e+00 3.1210499e+00 3.1345501e+00 + 3.1480501e+00 3.1615500e+00 3.1750500e+00 3.1885500e+00 + 3.2020500e+00 3.2155499e+00 3.2290499e+00 3.2425499e+00 + 3.2560501e+00 3.2695501e+00 3.2830501e+00 3.2965500e+00 + 3.3100500e+00 3.3235500e+00 3.3370500e+00 3.3505499e+00 + 3.3640499e+00 3.3775499e+00 3.3910501e+00 3.4045501e+00 + 3.4180501e+00 3.4315500e+00 3.4450500e+00 3.4585500e+00 + 3.4720500e+00 3.4855499e+00 3.4990499e+00 3.5125501e+00 + 3.5260501e+00 3.5395501e+00 3.5530500e+00 3.5665500e+00 + 3.5800500e+00 3.5935500e+00 3.6070499e+00 3.6205499e+00 + 3.6340499e+00 3.6475501e+00 3.6610501e+00 3.6745501e+00 + 3.6880500e+00 3.7015500e+00 3.7150500e+00 3.7285500e+00 + 3.7420499e+00 3.7555499e+00 3.7690499e+00 3.7825501e+00 + 3.7960501e+00 3.8095500e+00 3.8230500e+00 3.8365500e+00 + 3.8500500e+00 3.8635499e+00 3.8770499e+00 3.8905499e+00 + 3.9040501e+00 3.9175501e+00 3.9310501e+00 3.9445500e+00 + 3.9580500e+00 3.9715500e+00 3.9850500e+00 3.9985499e+00 + 4.0120502e+00 4.0255499e+00 4.0390501e+00 4.0525498e+00 + 4.0660501e+00 4.0795498e+00 4.0930500e+00 4.1065502e+00 + 4.1200500e+00 4.1335502e+00 4.1470499e+00 4.1605501e+00 + 4.1740499e+00 4.1875501e+00 4.2010498e+00 4.2145500e+00 + 4.2280502e+00 4.2415500e+00 4.2550502e+00 4.2685499e+00 + 4.2820501e+00 4.2955499e+00 4.3090501e+00 4.3225498e+00 + 4.3360500e+00 4.3495498e+00 4.3630500e+00 4.3765502e+00 + 4.3900499e+00 4.4035501e+00 4.4170499e+00 4.4305501e+00 + 4.4440498e+00 4.4575500e+00 4.4710498e+00 4.4845500e+00 + 4.4980502e+00 4.5115499e+00 4.5250502e+00 4.5385499e+00 + 4.5520501e+00 4.5655499e+00 4.5790501e+00 4.5925498e+00 + 4.6060500e+00 4.6195502e+00 4.6330500e+00 4.6465502e+00 + 4.6600499e+00 4.6735501e+00 4.6870499e+00 4.7005501e+00 + 4.7140498e+00 4.7275500e+00 4.7410498e+00 4.7545500e+00 + 4.7680502e+00 4.7815499e+00 4.7950501e+00 4.8085499e+00 + 4.8220501e+00 4.8355498e+00 4.8490500e+00 4.8625498e+00 + 4.8760500e+00 4.8895502e+00 4.9030499e+00 4.9165502e+00 + 4.9300499e+00 4.9435501e+00 4.9570498e+00 4.9705501e+00 + 4.9840498e+00 4.9975500e+00 5.0110502e+00 5.0245500e+00 + 5.0380502e+00 5.0515499e+00 5.0650501e+00 5.0785499e+00 + 5.0920501e+00 5.1055498e+00 5.1190500e+00 5.1325498e+00 + 5.1460500e+00 5.1595502e+00 5.1730499e+00 5.1865501e+00 + 5.2000499e+00 5.2135501e+00 5.2270498e+00 5.2405500e+00 + 5.2540498e+00 5.2675500e+00 5.2810502e+00 5.2945499e+00 + 5.3080502e+00 5.3215499e+00 5.3350501e+00 5.3485498e+00 + 5.3620501e+00 5.3755498e+00 5.3890500e+00 5.4025502e+00 + 5.4160500e+00 5.4295502e+00 5.4430499e+00 5.4565501e+00 + 5.4700499e+00 5.4835501e+00 5.4970498e+00 5.5105500e+00 + 5.5240502e+00 5.5375500e+00 5.5510502e+00 5.5645499e+00 + 5.5780501e+00 5.5915499e+00 5.6050501e+00 5.6185498e+00 + 5.6320500e+00 5.6455498e+00 5.6590500e+00 5.6725502e+00 + 5.6860499e+00 5.6995502e+00 5.7130499e+00 5.7265501e+00 + 5.7400498e+00 5.7535501e+00 5.7670498e+00 5.7805500e+00 + 5.7940502e+00 5.8075500e+00 5.8210502e+00 5.8345499e+00 + 5.8480501e+00 5.8615499e+00 5.8750501e+00 5.8885498e+00 + 5.9020500e+00 5.9155502e+00 5.9290500e+00 5.9425502e+00 + 5.9560499e+00 5.9695501e+00 5.9830499e+00 5.9965501e+00 + 6.0100498e+00 6.0235500e+00 6.0370498e+00 6.0505500e+00 + 6.0640502e+00 6.0775499e+00 6.0910501e+00 6.1045499e+00 + 6.1180501e+00 6.1315498e+00 6.1450500e+00 6.1585498e+00 + 6.1720500e+00 6.1855502e+00 6.1990499e+00 6.2125502e+00 + 6.2260499e+00 6.2395501e+00 6.2530499e+00 6.2665501e+00 + 6.2800498e+00 6.2935500e+00 6.3070502e+00 6.3205500e+00 + 6.3340502e+00 6.3475499e+00 6.3610501e+00 6.3745499e+00 + 6.3880501e+00 6.4015498e+00 6.4150500e+00 6.4285498e+00 + 6.4420500e+00 6.4555502e+00 6.4690499e+00 6.4825501e+00 + 6.4960499e+00 6.5095501e+00 6.5230498e+00 6.5365500e+00 + 6.5500498e+00 6.5635500e+00 6.5770502e+00 6.5905499e+00 + 6.6040502e+00 6.6175499e+00 6.6310501e+00 6.6445498e+00 + 6.6580501e+00 6.6715498e+00 6.6850500e+00 6.6985502e+00 + 6.7120500e+00 6.7255502e+00 6.7390499e+00 6.7525501e+00 + 6.7660499e+00 6.7795501e+00 6.7930498e+00 6.8065500e+00 + 6.8200498e+00 6.8335500e+00 6.8470502e+00 6.8605499e+00 + 6.8740501e+00 6.8875499e+00 6.9010501e+00 6.9145498e+00 + 6.9280500e+00 6.9415498e+00 6.9550500e+00 6.9685502e+00 + 6.9820499e+00 6.9955502e+00 7.0090499e+00 7.0225501e+00 + 7.0360498e+00 7.0495501e+00 7.0630498e+00 7.0765500e+00 + 7.0900502e+00 7.1035500e+00 7.1170502e+00 7.1305499e+00 + 7.1440501e+00 7.1578269e+00 7.1721697e+00 7.1871009e+00 + 7.2026453e+00 7.2188272e+00 7.2356739e+00 7.2532115e+00 + 7.2714696e+00 7.2904768e+00 7.3102641e+00 7.3308635e+00 + 7.3523088e+00 7.3746343e+00 7.3978763e+00 7.4220719e+00 + 7.4472609e+00 7.4734836e+00 7.5007830e+00 7.5292029e+00 + 7.5587893e+00 7.5895901e+00 7.6233001e+00 7.6592999e+00 + 7.6953001e+00 7.7312999e+00 7.7673001e+00 7.8032999e+00 + 7.8393002e+00 7.8752999e+00 7.9113002e+00 7.9473000e+00 + 7.9833002e+00 8.0193005e+00 8.0552998e+00 8.0913000e+00 + 8.1273003e+00 8.1632996e+00 8.1992998e+00 8.2353001e+00 + 8.2713003e+00 8.3072996e+00 8.3432999e+00 8.3793001e+00 + 8.4153004e+00 8.4512997e+00 8.4872999e+00 8.5233002e+00 + 8.5593004e+00 8.5952997e+00 8.6313000e+00 8.6673002e+00 + 8.7033005e+00 8.7392998e+00 8.7753000e+00 8.8113003e+00 + 8.8472996e+00 8.8832998e+00 8.9193001e+00 8.9553003e+00] + y_upper_bound: [-5.5752001e+00 -5.5391998e+00 -5.5032001e+00 -5.4671998e+00 + -5.4312000e+00 -5.3951998e+00 -5.3592000e+00 -5.3232002e+00 + -5.2872000e+00 -5.2512002e+00 -5.2151999e+00 -5.1792002e+00 + -5.1431999e+00 -5.1072001e+00 -5.0711999e+00 -5.0352001e+00 + -4.9991999e+00 -4.9632001e+00 -4.9271998e+00 -4.8912001e+00 + -4.8551998e+00 -4.8192000e+00 -4.7831998e+00 -4.7472000e+00 + -4.7112002e+00 -4.6752000e+00 -4.6392002e+00 -4.6032000e+00 + -4.5672002e+00 -4.5311999e+00 -4.4952002e+00 -4.4591999e+00 + -4.4232001e+00 -4.3871999e+00 -4.3512001e+00 -4.3151999e+00 + -4.2792001e+00 -4.2431998e+00 -4.2094898e+00 -4.1786890e+00 + -4.1491027e+00 -4.1206832e+00 -4.0933838e+00 -4.0671611e+00 + -4.0419717e+00 -4.0177760e+00 -3.9945343e+00 -3.9722090e+00 + -3.9507637e+00 -3.9301641e+00 -3.9103768e+00 -3.8913693e+00 + -3.8731117e+00 -3.8555737e+00 -3.8387272e+00 -3.8225451e+00 + -3.8070009e+00 -3.7920697e+00 -3.7777271e+00 -3.7639501e+00 + -3.7504499e+00 -3.7369499e+00 -3.7234499e+00 -3.7099500e+00 + -3.6964500e+00 -3.6829500e+00 -3.6694500e+00 -3.6559501e+00 + -3.6424501e+00 -3.6289501e+00 -3.6154499e+00 -3.6019499e+00 + -3.5884500e+00 -3.5749500e+00 -3.5614500e+00 -3.5479500e+00 + -3.5344501e+00 -3.5209501e+00 -3.5074501e+00 -3.4939499e+00 + -3.4804499e+00 -3.4669499e+00 -3.4534500e+00 -3.4399500e+00 + -3.4264500e+00 -3.4129500e+00 -3.3994501e+00 -3.3859501e+00 + -3.3724501e+00 -3.3589499e+00 -3.3454499e+00 -3.3319499e+00 + -3.3184500e+00 -3.3049500e+00 -3.2914500e+00 -3.2779500e+00 + -3.2644501e+00 -3.2509501e+00 -3.2374499e+00 -3.2239499e+00 + -3.2104499e+00 -3.1969500e+00 -3.1834500e+00 -3.1699500e+00 + -3.1564500e+00 -3.1429501e+00 -3.1294501e+00 -3.1159501e+00 + -3.1024499e+00 -3.0889499e+00 -3.0754499e+00 -3.0619500e+00 + -3.0484500e+00 -3.0349500e+00 -3.0214500e+00 -3.0079501e+00 + -2.9944501e+00 -2.9809501e+00 -2.9674499e+00 -2.9539499e+00 + -2.9404500e+00 -2.9269500e+00 -2.9134500e+00 -2.8999500e+00 + -2.8864501e+00 -2.8729501e+00 -2.8594501e+00 -2.8459499e+00 + -2.8324499e+00 -2.8189499e+00 -2.8054500e+00 -2.7919500e+00 + -2.7784500e+00 -2.7649500e+00 -2.7514501e+00 -2.7379501e+00 + -2.7244501e+00 -2.7109499e+00 -2.6974499e+00 -2.6839499e+00 + -2.6704500e+00 -2.6569500e+00 -2.6434500e+00 -2.6299500e+00 + -2.6164501e+00 -2.6029501e+00 -2.5894499e+00 -2.5759499e+00 + -2.5624499e+00 -2.5489500e+00 -2.5354500e+00 -2.5219500e+00 + -2.5084500e+00 -2.4949501e+00 -2.4814501e+00 -2.4679501e+00 + -2.4544499e+00 -2.4409499e+00 -2.4274499e+00 -2.4139500e+00 + -2.4004500e+00 -2.3869500e+00 -2.3734500e+00 -2.3599501e+00 + -2.3464501e+00 -2.3329501e+00 -2.3194499e+00 -2.3059499e+00 + -2.2924500e+00 -2.2789500e+00 -2.2654500e+00 -2.2519500e+00 + -2.2384501e+00 -2.2249501e+00 -2.2114501e+00 -2.1979499e+00 + -2.1844499e+00 -2.1709499e+00 -2.1574500e+00 -2.1439500e+00 + -2.1304500e+00 -2.1169500e+00 -2.1034501e+00 -2.0899501e+00 + -2.0764501e+00 -2.0629499e+00 -2.0494499e+00 -2.0359499e+00 + -2.0224500e+00 -2.0089500e+00 -1.9954500e+00 -1.9819500e+00 + -1.9684500e+00 -1.9549500e+00 -1.9414500e+00 -1.9279500e+00 + -1.9144500e+00 -1.9009500e+00 -1.8874500e+00 -1.8739500e+00 + -1.8604500e+00 -1.8469501e+00 -1.8334500e+00 -1.8199500e+00 + -1.8064500e+00 -1.7929500e+00 -1.7794501e+00 -1.7659500e+00 + -1.7524500e+00 -1.7389500e+00 -1.7254500e+00 -1.7119499e+00 + -1.6984500e+00 -1.6849500e+00 -1.6714500e+00 -1.6579500e+00 + -1.6444499e+00 -1.6309500e+00 -1.6174500e+00 -1.6039500e+00 + -1.5904500e+00 -1.5769500e+00 -1.5634500e+00 -1.5499500e+00 + -1.5364500e+00 -1.5229501e+00 -1.5094500e+00 -1.4959500e+00 + -1.4824500e+00 -1.4689500e+00 -1.4554501e+00 -1.4419500e+00 + -1.4284500e+00 -1.4149500e+00 -1.4014500e+00 -1.3879499e+00 + -1.3744500e+00 -1.3609500e+00 -1.3474500e+00 -1.3339500e+00 + -1.3204499e+00 -1.3069500e+00 -1.2934500e+00 -1.2799500e+00 + -1.2664500e+00 -1.2529500e+00 -1.2394500e+00 -1.2259500e+00 + -1.2124500e+00 -1.1989501e+00 -1.1854500e+00 -1.1719500e+00 + -1.1584500e+00 -1.1449500e+00 -1.1314501e+00 -1.1179500e+00 + -1.1044500e+00 -1.0909500e+00 -1.0774500e+00 -1.0639499e+00 + -1.0504500e+00 -1.0369500e+00 -1.0234500e+00 -1.0099500e+00 + -9.9645001e-01 -9.8294997e-01 -9.6945000e-01 -9.5595002e-01 + -9.4244999e-01 -9.2895001e-01 -9.1544998e-01 -9.0195000e-01 + -8.8845003e-01 -8.7494999e-01 -8.6145002e-01 -8.4794998e-01 + -8.3445001e-01 -8.2094997e-01 -8.0745000e-01 -7.9395002e-01 + -7.8044999e-01 -7.6695001e-01 -7.5344998e-01 -7.3995000e-01 + -7.2645003e-01 -7.1294999e-01 -6.9945002e-01 -6.8594998e-01 + -6.7245001e-01 -6.5894997e-01 -6.4545000e-01 -6.3195002e-01 + -6.1844999e-01 -6.0495001e-01 -5.9144998e-01 -5.7795000e-01 + -5.6445003e-01 -5.5094999e-01 -5.3745002e-01 -5.2394998e-01 + -5.1045001e-01 -4.9695000e-01 -4.8345000e-01 -4.6994999e-01 + -4.5644999e-01 -4.4295001e-01 -4.2945001e-01 -4.1595000e-01 + -4.0245000e-01 -3.8894999e-01 -3.7544999e-01 -3.6195001e-01 + -3.4845001e-01 -3.3495000e-01 -3.2145000e-01 -3.0794999e-01 + -2.9445001e-01 -2.8095001e-01 -2.6745000e-01 -2.5395000e-01 + -2.4044999e-01 -2.2695000e-01 -2.1345000e-01 -1.9994999e-01 + -1.8645000e-01 -1.7295000e-01 -1.5944999e-01 -1.4595000e-01 + -1.3245000e-01 -1.1895000e-01 -1.0545000e-01 -9.1949999e-02 + -7.8450002e-02 -6.4949997e-02 -5.1449999e-02 -3.7950002e-02 + -2.4450000e-02 -1.0950000e-02 2.5500001e-03 1.6050000e-02 + 2.9549999e-02 4.3049999e-02 5.6550000e-02 7.0050001e-02 + 8.3549999e-02 9.7050004e-02 1.1055000e-01 1.2405000e-01 + 1.3755000e-01 1.5105000e-01 1.6455001e-01 1.7805000e-01 + 1.9155000e-01 2.0505001e-01 2.1855000e-01 2.3205000e-01 + 2.4555001e-01 2.5905001e-01 2.7254999e-01 2.8604999e-01 + 2.9955000e-01 3.1305000e-01 3.2655001e-01 3.4005001e-01 + 3.5354999e-01 3.6704999e-01 3.8055000e-01 3.9405000e-01 + 4.0755001e-01 4.2105001e-01 4.3454999e-01 4.4804999e-01 + 4.6155000e-01 4.7505000e-01 4.8855001e-01 5.0204998e-01 + 5.1555002e-01 5.2904999e-01 5.4255003e-01 5.5605000e-01 + 5.6954998e-01 5.8305001e-01 5.9654999e-01 6.1005002e-01 + 6.2355000e-01 6.3704997e-01 6.5055001e-01 6.6404998e-01 + 6.7755002e-01 6.9104999e-01 7.0455003e-01 7.1805000e-01 + 7.3154998e-01 7.4505001e-01 7.5854999e-01 7.7205002e-01 + 7.8555000e-01 7.9904997e-01 8.1255001e-01 8.2604998e-01 + 8.3955002e-01 8.5304999e-01 8.6655003e-01 8.8005000e-01 + 8.9354998e-01 9.0705001e-01 9.2054999e-01 9.3405002e-01 + 9.4755000e-01 9.6104997e-01 9.7455001e-01 9.8804998e-01 + 1.0015500e+00 1.0150501e+00 1.0285500e+00 1.0420500e+00 + 1.0555500e+00 1.0690500e+00 1.0825500e+00 1.0960500e+00 + 1.1095500e+00 1.1230500e+00 1.1365499e+00 1.1500500e+00 + 1.1635500e+00 1.1770500e+00 1.1905500e+00 1.2040499e+00 + 1.2175500e+00 1.2310500e+00 1.2445500e+00 1.2580500e+00 + 1.2715501e+00 1.2850500e+00 1.2985500e+00 1.3120500e+00 + 1.3255500e+00 1.3390501e+00 1.3525500e+00 1.3660500e+00 + 1.3795500e+00 1.3930500e+00 1.4065500e+00 1.4200500e+00 + 1.4335500e+00 1.4470500e+00 1.4605500e+00 1.4740500e+00 + 1.4875500e+00 1.5010500e+00 1.5145500e+00 1.5280499e+00 + 1.5415500e+00 1.5550500e+00 1.5685500e+00 1.5820500e+00 + 1.5955499e+00 1.6090500e+00 1.6225500e+00 1.6360500e+00 + 1.6495500e+00 1.6630501e+00 1.6765500e+00 1.6900500e+00 + 1.7035500e+00 1.7170500e+00 1.7305501e+00 1.7440500e+00 + 1.7575500e+00 1.7710500e+00 1.7845500e+00 1.7980500e+00 + 1.8115500e+00 1.8250500e+00 1.8385500e+00 1.8520499e+00 + 1.8655500e+00 1.8790500e+00 1.8925500e+00 1.9060500e+00 + 1.9195499e+00 1.9330500e+00 1.9465500e+00 1.9600500e+00 + 1.9735500e+00 1.9870501e+00 2.0005500e+00 2.0140500e+00 + 2.0275500e+00 2.0410500e+00 2.0545499e+00 2.0680499e+00 + 2.0815499e+00 2.0950501e+00 2.1085501e+00 2.1220500e+00 + 2.1355500e+00 2.1490500e+00 2.1625500e+00 2.1760499e+00 + 2.1895499e+00 2.2030499e+00 2.2165501e+00 2.2300501e+00 + 2.2435501e+00 2.2570500e+00 2.2705500e+00 2.2840500e+00 + 2.2975500e+00 2.3110499e+00 2.3245499e+00 2.3380499e+00 + 2.3515501e+00 2.3650501e+00 2.3785501e+00 2.3920500e+00 + 2.4055500e+00 2.4190500e+00 2.4325500e+00 2.4460499e+00 + 2.4595499e+00 2.4730501e+00 2.4865501e+00 2.5000501e+00 + 2.5135500e+00 2.5270500e+00 2.5405500e+00 2.5540500e+00 + 2.5675499e+00 2.5810499e+00 2.5945499e+00 2.6080501e+00 + 2.6215501e+00 2.6350501e+00 2.6485500e+00 2.6620500e+00 + 2.6755500e+00 2.6890500e+00 2.7025499e+00 2.7160499e+00 + 2.7295499e+00 2.7430501e+00 2.7565501e+00 2.7700500e+00 + 2.7835500e+00 2.7970500e+00 2.8105500e+00 2.8240499e+00 + 2.8375499e+00 2.8510499e+00 2.8645501e+00 2.8780501e+00 + 2.8915501e+00 2.9050500e+00 2.9185500e+00 2.9320500e+00 + 2.9455500e+00 2.9590499e+00 2.9725499e+00 2.9860499e+00 + 2.9995501e+00 3.0130501e+00 3.0265501e+00 3.0400500e+00 + 3.0535500e+00 3.0670500e+00 3.0805500e+00 3.0940499e+00 + 3.1075499e+00 3.1210499e+00 3.1345501e+00 3.1480501e+00 + 3.1615500e+00 3.1750500e+00 3.1885500e+00 3.2020500e+00 + 3.2155499e+00 3.2290499e+00 3.2425499e+00 3.2560501e+00 + 3.2695501e+00 3.2830501e+00 3.2965500e+00 3.3100500e+00 + 3.3235500e+00 3.3370500e+00 3.3505499e+00 3.3640499e+00 + 3.3775499e+00 3.3910501e+00 3.4045501e+00 3.4180501e+00 + 3.4315500e+00 3.4450500e+00 3.4585500e+00 3.4720500e+00 + 3.4855499e+00 3.4990499e+00 3.5125501e+00 3.5260501e+00 + 3.5395501e+00 3.5530500e+00 3.5665500e+00 3.5800500e+00 + 3.5935500e+00 3.6070499e+00 3.6205499e+00 3.6340499e+00 + 3.6475501e+00 3.6610501e+00 3.6745501e+00 3.6880500e+00 + 3.7015500e+00 3.7150500e+00 3.7285500e+00 3.7420499e+00 + 3.7555499e+00 3.7690499e+00 3.7825501e+00 3.7960501e+00 + 3.8095500e+00 3.8230500e+00 3.8365500e+00 3.8500500e+00 + 3.8635499e+00 3.8770499e+00 3.8905499e+00 3.9040501e+00 + 3.9175501e+00 3.9310501e+00 3.9445500e+00 3.9580500e+00 + 3.9715500e+00 3.9850500e+00 3.9985499e+00 4.0120502e+00 + 4.0255499e+00 4.0390501e+00 4.0525498e+00 4.0660501e+00 + 4.0795498e+00 4.0930500e+00 4.1065502e+00 4.1200500e+00 + 4.1335502e+00 4.1470499e+00 4.1605501e+00 4.1740499e+00 + 4.1875501e+00 4.2010498e+00 4.2145500e+00 4.2280502e+00 + 4.2415500e+00 4.2550502e+00 4.2685499e+00 4.2820501e+00 + 4.2955499e+00 4.3090501e+00 4.3225498e+00 4.3360500e+00 + 4.3495498e+00 4.3630500e+00 4.3765502e+00 4.3900499e+00 + 4.4035501e+00 4.4170499e+00 4.4305501e+00 4.4440498e+00 + 4.4575500e+00 4.4710498e+00 4.4845500e+00 4.4980502e+00 + 4.5115499e+00 4.5250502e+00 4.5385499e+00 4.5520501e+00 + 4.5655499e+00 4.5790501e+00 4.5925498e+00 4.6060500e+00 + 4.6195502e+00 4.6330500e+00 4.6465502e+00 4.6600499e+00 + 4.6735501e+00 4.6870499e+00 4.7005501e+00 4.7140498e+00 + 4.7275500e+00 4.7410498e+00 4.7545500e+00 4.7680502e+00 + 4.7815499e+00 4.7950501e+00 4.8085499e+00 4.8220501e+00 + 4.8355498e+00 4.8490500e+00 4.8625498e+00 4.8760500e+00 + 4.8895502e+00 4.9030499e+00 4.9165502e+00 4.9300499e+00 + 4.9435501e+00 4.9570498e+00 4.9705501e+00 4.9840498e+00 + 4.9975500e+00 5.0110502e+00 5.0245500e+00 5.0380502e+00 + 5.0515499e+00 5.0650501e+00 5.0785499e+00 5.0920501e+00 + 5.1055498e+00 5.1190500e+00 5.1325498e+00 5.1460500e+00 + 5.1595502e+00 5.1730499e+00 5.1865501e+00 5.2000499e+00 + 5.2135501e+00 5.2270498e+00 5.2405500e+00 5.2540498e+00 + 5.2675500e+00 5.2810502e+00 5.2945499e+00 5.3080502e+00 + 5.3215499e+00 5.3350501e+00 5.3485498e+00 5.3620501e+00 + 5.3755498e+00 5.3890500e+00 5.4025502e+00 5.4160500e+00 + 5.4295502e+00 5.4430499e+00 5.4565501e+00 5.4700499e+00 + 5.4835501e+00 5.4970498e+00 5.5105500e+00 5.5240502e+00 + 5.5375500e+00 5.5510502e+00 5.5645499e+00 5.5780501e+00 + 5.5915499e+00 5.6050501e+00 5.6185498e+00 5.6320500e+00 + 5.6455498e+00 5.6590500e+00 5.6725502e+00 5.6860499e+00 + 5.6995502e+00 5.7130499e+00 5.7265501e+00 5.7400498e+00 + 5.7535501e+00 5.7670498e+00 5.7805500e+00 5.7940502e+00 + 5.8075500e+00 5.8210502e+00 5.8345499e+00 5.8480501e+00 + 5.8615499e+00 5.8750501e+00 5.8885498e+00 5.9020500e+00 + 5.9155502e+00 5.9290500e+00 5.9425502e+00 5.9560499e+00 + 5.9695501e+00 5.9830499e+00 5.9965501e+00 6.0100498e+00 + 6.0235500e+00 6.0370498e+00 6.0505500e+00 6.0640502e+00 + 6.0775499e+00 6.0910501e+00 6.1045499e+00 6.1180501e+00 + 6.1315498e+00 6.1450500e+00 6.1585498e+00 6.1720500e+00 + 6.1855502e+00 6.1990499e+00 6.2125502e+00 6.2260499e+00 + 6.2395501e+00 6.2530499e+00 6.2665501e+00 6.2800498e+00 + 6.2935500e+00 6.3070502e+00 6.3205500e+00 6.3340502e+00 + 6.3475499e+00 6.3610501e+00 6.3745499e+00 6.3880501e+00 + 6.4015498e+00 6.4150500e+00 6.4285498e+00 6.4420500e+00 + 6.4555502e+00 6.4690499e+00 6.4825501e+00 6.4960499e+00 + 6.5095501e+00 6.5230498e+00 6.5365500e+00 6.5500498e+00 + 6.5635500e+00 6.5770502e+00 6.5905499e+00 6.6040502e+00 + 6.6175499e+00 6.6310501e+00 6.6445498e+00 6.6580501e+00 + 6.6715498e+00 6.6850500e+00 6.6985502e+00 6.7120500e+00 + 6.7255502e+00 6.7390499e+00 6.7525501e+00 6.7660499e+00 + 6.7795501e+00 6.7930498e+00 6.8065500e+00 6.8200498e+00 + 6.8335500e+00 6.8470502e+00 6.8605499e+00 6.8740501e+00 + 6.8875499e+00 6.9010501e+00 6.9145498e+00 6.9280500e+00 + 6.9415498e+00 6.9550500e+00 6.9685502e+00 6.9820499e+00 + 6.9955502e+00 7.0090499e+00 7.0225501e+00 7.0360498e+00 + 7.0495501e+00 7.0630498e+00 7.0765500e+00 7.0900502e+00 + 7.1035500e+00 7.1170502e+00 7.1305499e+00 7.1440501e+00 + 7.1578269e+00 7.1721697e+00 7.1871009e+00 7.2026453e+00 + 7.2188272e+00 7.2356739e+00 7.2532115e+00 7.2714696e+00 + 7.2904768e+00 7.3102641e+00 7.3308635e+00 7.3523088e+00 + 7.3746343e+00 7.3978763e+00 7.4220719e+00 7.4472609e+00 + 7.4734836e+00 7.5007830e+00 7.5292029e+00 7.5587893e+00 + 7.5895901e+00 7.6233001e+00 7.6592999e+00 7.6953001e+00 + 7.7312999e+00 7.7673001e+00 7.8032999e+00 7.8393002e+00 + 7.8752999e+00 7.9113002e+00 7.9473000e+00 7.9833002e+00 + 8.0193005e+00 8.0552998e+00 8.0913000e+00 8.1273003e+00 + 8.1632996e+00 8.1992998e+00 8.2353001e+00 8.2713003e+00 + 8.3072996e+00 8.3432999e+00 8.3793001e+00 8.4153004e+00 + 8.4512997e+00 8.4872999e+00 8.5233002e+00 8.5593004e+00 + 8.5952997e+00 8.6313000e+00 8.6673002e+00 8.7033005e+00 + 8.7392998e+00 8.7753000e+00 8.8113003e+00 8.8472996e+00 + 8.8832998e+00 8.9193001e+00 8.9553003e+00 8.9912996e+00] , PP Field lbyr: 2010 lbmon: 2 @@ -1252,1158 +1126,1032 @@ bdy: 0.0 bzx: 0.0 bdx: 0.0 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 100070. 100070. 100070. ..., 101057. 101063. 101063.] - [ 100069. 100068. 100068. ..., 101061. 101065. 101066.] - [ 100068. 100068. 100067. ..., 101062. 101068. 101068.] - ..., - [ 102203. 102211. 102219. ..., 101783. 101757. 101752.] - [ 102210. 102218. 102225. ..., 101783. 101763. 101756.] - [ 102216. 102224. 102232. ..., 101793. 101770. 101761.]] - x: [ 353.05249023 353.08850098 353.12451172 353.16049194 353.19650269 - 353.23251343 353.26849365 353.30450439 353.34051514 353.37649536 - 353.4125061 353.44848633 353.48449707 353.52050781 353.55648804 - 353.59249878 353.62850952 353.66448975 353.70050049 353.73651123 - 353.77249146 353.8085022 353.84451294 353.88049316 353.91650391 - 353.95251465 353.98849487 354.02450562 354.06048584 354.09649658 - 354.13250732 354.16848755 354.20449829 354.24050903 354.27648926 - 354.3125 354.34851074 354.38449097 354.42050171 354.45651245 - 354.49249268 354.52185059 354.55010986 354.57736206 354.6036377 - 354.62893677 354.65332031 354.67684937 354.69949341 354.72131348 - 354.74234009 354.76263428 354.78216553 354.80099487 354.81915283 - 354.8366394 354.85348511 354.86972046 354.88537598 354.90045166 - 354.91497803 354.9289856 354.94250488 354.95599365 354.96951294 - 354.98300171 354.99649048 355.01000977 355.02349854 355.0369873 - 355.05050659 355.06399536 355.07751465 355.09100342 355.10449219 - 355.11801147 355.13150024 355.14498901 355.1585083 355.17199707 - 355.18548584 355.19900513 355.2124939 355.22601318 355.23950195 - 355.25299072 355.26651001 355.27999878 355.29348755 355.30700684 - 355.32049561 355.33401489 355.34750366 355.36099243 355.37451172 - 355.38800049 355.40148926 355.41500854 355.42849731 355.44198608 - 355.45550537 355.46899414 355.48251343 355.4960022 355.50949097 - 355.52301025 355.53649902 355.54998779 355.56350708 355.57699585 - 355.59051514 355.60400391 355.61749268 355.63101196 355.64450073 - 355.6579895 355.67150879 355.68499756 355.69848633 355.71200562 - 355.72549438 355.73901367 355.75250244 355.76599121 355.7795105 - 355.79299927 355.80648804 355.82000732 355.83349609 355.84698486 - 355.86050415 355.87399292 355.88751221 355.90100098 355.91448975 - 355.92800903 355.9414978 355.95498657 355.96850586 355.98199463 - 355.99551392 356.00900269 356.02249146 356.03601074 356.04949951 - 356.06298828 356.07650757 356.08999634 356.10348511 356.11700439 - 356.13049316 356.14401245 356.15750122 356.17098999 356.18450928 - 356.19799805 356.21148682 356.2250061 356.23849487 356.25201416 - 356.26550293 356.2789917 356.29251099 356.30599976 356.31948853 - 356.33300781 356.34649658 356.35998535 356.37350464 356.38699341 - 356.4005127 356.41400146 356.42749023 356.44100952 356.45449829 - 356.46798706 356.48150635 356.49499512 356.5085144 356.52200317 - 356.53549194 356.54901123 356.5625 356.57598877 356.58950806 - 356.60299683 356.6164856 356.63000488 356.64349365 356.65701294 - 356.67050171 356.68399048 356.69750977 356.71099854 356.7244873 - 356.73800659 356.75149536 356.76501465 356.77850342 356.79199219 - 356.80551147 356.81900024 356.83248901 356.8460083 356.85949707 - 356.87298584 356.88650513 356.8999939 356.91351318 356.92700195 - 356.94049072 356.95401001 356.96749878 356.98098755 356.99450684 - 357.00799561 357.02151489 357.03500366 357.04849243 357.06201172 - 357.07550049 357.08898926 357.10250854 357.11599731 357.12948608 - 357.14300537 357.15649414 357.17001343 357.1835022 357.19699097 - 357.21051025 357.22399902 357.23748779 357.25100708 357.26449585 - 357.27801514 357.29150391 357.30499268 357.31851196 357.33200073 - 357.3454895 357.35900879 357.37249756 357.38598633 357.39950562 - 357.41299438 357.42651367 357.44000244 357.45349121 357.4670105 - 357.48049927 357.49398804 357.50750732 357.52099609 357.53448486 - 357.54800415 357.56149292 357.57501221 357.58850098 357.60198975 - 357.61550903 357.6289978 357.64248657 357.65600586 357.66949463 - 357.68301392 357.69650269 357.70999146 357.72351074 357.73699951 - 357.75048828 357.76400757 357.77749634 357.79098511 357.80450439 - 357.81799316 357.83151245 357.84500122 357.85848999 357.87200928 - 357.88549805 357.89898682 357.9125061 357.92599487 357.93951416 - 357.95300293 357.9664917 357.98001099 357.99349976 358.00698853 - 358.02050781 358.03399658 358.04748535 358.06100464 358.07449341 - 358.0880127 358.10150146 358.11499023 358.12850952 358.14199829 - 358.15548706 358.16900635 358.18249512 358.1960144 358.20950317 - 358.22299194 358.23651123 358.25 358.26348877 358.27700806 - 358.29049683 358.3039856 358.31750488 358.33099365 358.34451294 - 358.35800171 358.37149048 358.38500977 358.39849854 358.4119873 - 358.42550659 358.43899536 358.45251465 358.46600342 358.47949219 - 358.49301147 358.50650024 358.51998901 358.5335083 358.54699707 - 358.56048584 358.57400513 358.5874939 358.60101318 358.61450195 - 358.62799072 358.64151001 358.65499878 358.66848755 358.68200684 - 358.69549561 358.70901489 358.72250366 358.73599243 358.74951172 - 358.76300049 358.77648926 358.79000854 358.80349731 358.81698608 - 358.83050537 358.84399414 358.85751343 358.8710022 358.88449097 - 358.89801025 358.91149902 358.92498779 358.93850708 358.95199585 - 358.96551514 358.97900391 358.99249268 359.00601196 359.01950073 - 359.0329895 359.04650879 359.05999756 359.07348633 359.08700562 - 359.10049438 359.11401367 359.12750244 359.14099121 359.1545105 - 359.16799927 359.18148804 359.19500732 359.20849609 359.22198486 - 359.23550415 359.24899292 359.26251221 359.27600098 359.28948975 - 359.30300903 359.3164978 359.32998657 359.34350586 359.35699463 - 359.37051392 359.38400269 359.39749146 359.41101074 359.42449951 - 359.43798828 359.45150757 359.46499634 359.47848511 359.49200439 - 359.50549316 359.51901245 359.53250122 359.54598999 359.55950928 - 359.57299805 359.58648682 359.6000061 359.61349487 359.62701416 - 359.64050293 359.6539917 359.66751099 359.68099976 359.69448853 - 359.70800781 359.72149658 359.73498535 359.74850464 359.76199341 - 359.7755127 359.78900146 359.80249023 359.81600952 359.82949829 - 359.84298706 359.85650635 359.86999512 359.8835144 359.89700317 - 359.91049194 359.92401123 359.9375 359.95098877 359.96450806 - 359.97799683 359.9914856 360.00500488 360.01849365 360.03201294 - 360.04550171 360.05899048 360.07250977 360.08599854 360.0994873 - 360.11300659 360.12649536 360.14001465 360.15350342 360.16699219 - 360.18051147 360.19400024 360.20748901 360.2210083 360.23449707 - 360.24798584 360.26150513 360.2749939 360.28851318 360.30200195 - 360.31549072 360.32901001 360.34249878 360.35598755 360.36950684 - 360.38299561 360.39651489 360.41000366 360.42349243 360.43701172 - 360.45050049 360.46398926 360.47750854 360.49099731 360.50448608 - 360.51800537 360.53149414 360.54501343 360.5585022 360.57199097 - 360.58551025 360.59899902 360.61248779 360.62600708 360.63949585 - 360.65301514 360.66650391 360.67999268 360.69351196 360.70700073 - 360.7204895 360.73400879 360.74749756 360.76098633 360.77450562 - 360.78799438 360.80151367 360.81500244 360.82849121 360.8420105 - 360.85549927 360.86898804 360.88250732 360.89599609 360.90948486 - 360.92300415 360.93649292 360.95001221 360.96350098 360.97698975 - 360.99050903 361.0039978 361.01748657 361.03100586 361.04449463 - 361.05801392 361.07150269 361.08499146 361.09851074 361.11199951 - 361.12548828 361.13900757 361.15249634 361.16598511 361.17950439 - 361.19299316 361.20651245 361.22000122 361.23348999 361.24700928 - 361.26049805 361.27398682 361.2875061 361.30099487 361.31451416 - 361.32800293 361.3414917 361.35501099 361.36849976 361.38198853 - 361.39550781 361.40899658 361.42248535 361.43600464 361.44949341 - 361.4630127 361.47650146 361.48999023 361.50350952 361.51699829 - 361.53048706 361.54400635 361.55749512 361.5710144 361.58450317 - 361.59799194 361.61151123 361.625 361.63848877 361.65200806 - 361.66549683 361.6789856 361.69250488 361.70599365 361.71951294 - 361.73300171 361.74649048 361.76000977 361.77349854 361.7869873 - 361.80050659 361.81399536 361.82751465 361.84100342 361.85449219 - 361.86801147 361.88150024 361.89498901 361.9085083 361.92199707 - 361.93548584 361.94900513 361.9624939 361.97601318 361.98950195 - 362.00299072 362.01651001 362.02999878 362.04348755 362.05700684 - 362.07049561 362.08401489 362.09750366 362.11099243 362.12451172 - 362.13800049 362.15148926 362.16500854 362.17849731 362.19198608 - 362.20550537 362.21899414 362.23251343 362.2460022 362.25949097 - 362.27301025 362.28649902 362.29998779 362.31350708 362.32699585 - 362.34051514 362.35400391 362.36749268 362.38101196 362.39450073 - 362.4079895 362.42150879 362.43499756 362.44848633 362.46200562 - 362.47549438 362.48901367 362.50250244 362.51599121 362.5295105 - 362.54299927 362.55648804 362.57000732 362.58349609 362.59698486 - 362.61050415 362.62399292 362.63751221 362.65100098 362.66448975 - 362.67800903 362.6914978 362.70498657 362.71850586 362.73199463 - 362.74551392 362.75900269 362.77249146 362.78601074 362.79949951 - 362.81298828 362.82650757 362.83999634 362.85348511 362.86700439 - 362.88049316 362.89401245 362.90750122 362.92098999 362.93450928 - 362.94799805 362.96148682 362.9750061 362.98849487 363.00201416 - 363.01550293 363.0289917 363.04251099 363.05599976 363.06948853 - 363.08300781 363.09649658 363.10998535 363.12350464 363.13699341 - 363.1505127 363.16400146 363.17749023 363.19100952 363.20449829 - 363.21798706 363.23150635 363.24499512 363.2585144 363.27200317 - 363.28549194 363.29901123 363.3125 363.32650757 363.34103394 - 363.35614014 363.37176514 363.38803101 363.40487671 363.42236328 - 363.44049072 363.45932007 363.47888184 363.49914551 363.52017212 - 363.54202271 363.56466675 363.58816528 363.61254883 363.63787842 - 363.66412354 363.69137573 363.71966553 363.74899292 363.78500366 - 363.8210144 363.85699463 363.89300537 363.9289856 363.96499634 - 364.00100708 364.0369873 364.07299805 364.10900879 364.14498901 - 364.18099976 364.2170105 364.25299072 364.28900146 364.32501221 - 364.36099243 364.39700317 364.43301392 364.46899414 364.50500488 - 364.54098511 364.57699585 364.61300659 364.64898682 364.68499756 - 364.7210083 364.75698853 364.79299927 364.82901001 364.86499023 - 364.90100098 364.93701172 364.97299194 365.00900269 365.04501343 - 365.08099365 365.11700439 365.15301514 365.18899536] - x_lower_bound: [ 353.03448486 353.07049561 353.10650635 353.14248657 353.17849731 - 353.21450806 353.25048828 353.28649902 353.32250977 353.35848999 - 353.39450073 353.43051147 353.4664917 353.50250244 353.53851318 - 353.57449341 353.61050415 353.64651489 353.68249512 353.71850586 - 353.75448608 353.79049683 353.82650757 353.86248779 353.89849854 - 353.93450928 353.9704895 354.00650024 354.04251099 354.07849121 - 354.11450195 354.1505127 354.18649292 354.22250366 354.2585144 - 354.29449463 354.33050537 354.3664856 354.40249634 354.43850708 - 354.4744873 354.50717163 354.53598022 354.56375122 354.59051514 - 354.61627197 354.6411438 354.66506958 354.68817139 354.71038818 - 354.73184204 354.75250244 354.7723999 354.79159546 354.81005859 - 354.82788086 354.84506226 354.86160278 354.87753296 354.89291382 - 354.90771484 354.92199707 354.9357605 354.94924927 354.96273804 - 354.97625732 354.98974609 355.00323486 355.01675415 355.03024292 - 355.04376221 355.05725098 355.07073975 355.08425903 355.0977478 - 355.11123657 355.12475586 355.13824463 355.15176392 355.16525269 - 355.17874146 355.19226074 355.20574951 355.21923828 355.23275757 - 355.24624634 355.25973511 355.27325439 355.28674316 355.30026245 - 355.31375122 355.32723999 355.34075928 355.35424805 355.36773682 - 355.3812561 355.39474487 355.40826416 355.42175293 355.4352417 - 355.44876099 355.46224976 355.47573853 355.48925781 355.50274658 - 355.51623535 355.52975464 355.54324341 355.5567627 355.57025146 - 355.58374023 355.59725952 355.61074829 355.62423706 355.63775635 - 355.65124512 355.6647644 355.67825317 355.69174194 355.70526123 - 355.71875 355.73223877 355.74575806 355.75924683 355.7727356 - 355.78625488 355.79974365 355.81326294 355.82675171 355.84024048 - 355.85375977 355.86724854 355.8807373 355.89425659 355.90774536 - 355.92126465 355.93475342 355.94824219 355.96176147 355.97525024 - 355.98873901 356.0022583 356.01574707 356.02923584 356.04275513 - 356.0562439 356.06976318 356.08325195 356.09674072 356.11026001 - 356.12374878 356.13723755 356.15075684 356.16424561 356.17776489 - 356.19125366 356.20474243 356.21826172 356.23175049 356.24523926 - 356.25875854 356.27224731 356.28573608 356.29925537 356.31274414 - 356.32626343 356.3397522 356.35324097 356.36676025 356.38024902 - 356.39373779 356.40725708 356.42074585 356.43426514 356.44775391 - 356.46124268 356.47476196 356.48825073 356.5017395 356.51525879 - 356.52874756 356.54223633 356.55575562 356.56924438 356.58276367 - 356.59625244 356.60974121 356.6232605 356.63674927 356.65023804 - 356.66375732 356.67724609 356.69073486 356.70425415 356.71774292 - 356.73126221 356.74475098 356.75823975 356.77175903 356.7852478 - 356.79873657 356.81225586 356.82574463 356.83926392 356.85275269 - 356.86624146 356.87976074 356.89324951 356.90673828 356.92025757 - 356.93374634 356.94723511 356.96075439 356.97424316 356.98776245 - 357.00125122 357.01473999 357.02825928 357.04174805 357.05523682 - 357.0687561 357.08224487 357.09576416 357.10925293 357.1227417 - 357.13626099 357.14974976 357.16323853 357.17675781 357.19024658 - 357.20373535 357.21725464 357.23074341 357.2442627 357.25775146 - 357.27124023 357.28475952 357.29824829 357.31173706 357.32525635 - 357.33874512 357.3522644 357.36575317 357.37924194 357.39276123 - 357.40625 357.41973877 357.43325806 357.44674683 357.4602356 - 357.47375488 357.48724365 357.50076294 357.51425171 357.52774048 - 357.54125977 357.55474854 357.5682373 357.58175659 357.59524536 - 357.60876465 357.62225342 357.63574219 357.64926147 357.66275024 - 357.67623901 357.6897583 357.70324707 357.71673584 357.73025513 - 357.7437439 357.75726318 357.77075195 357.78424072 357.79776001 - 357.81124878 357.82473755 357.83825684 357.85174561 357.86526489 - 357.87875366 357.89224243 357.90576172 357.91925049 357.93273926 - 357.94625854 357.95974731 357.97323608 357.98675537 358.00024414 - 358.01376343 358.0272522 358.04074097 358.05426025 358.06774902 - 358.08123779 358.09475708 358.10824585 358.12176514 358.13525391 - 358.14874268 358.16226196 358.17575073 358.1892395 358.20275879 - 358.21624756 358.22973633 358.24325562 358.25674438 358.27026367 - 358.28375244 358.29724121 358.3107605 358.32424927 358.33773804 - 358.35125732 358.36474609 358.37823486 358.39175415 358.40524292 - 358.41876221 358.43225098 358.44573975 358.45925903 358.4727478 - 358.48623657 358.49975586 358.51324463 358.52676392 358.54025269 - 358.55374146 358.56726074 358.58074951 358.59423828 358.60775757 - 358.62124634 358.63473511 358.64825439 358.66174316 358.67526245 - 358.68875122 358.70223999 358.71575928 358.72924805 358.74273682 - 358.7562561 358.76974487 358.78326416 358.79675293 358.8102417 - 358.82376099 358.83724976 358.85073853 358.86425781 358.87774658 - 358.89123535 358.90475464 358.91824341 358.9317627 358.94525146 - 358.95874023 358.97225952 358.98574829 358.99923706 359.01275635 - 359.02624512 359.0397644 359.05325317 359.06674194 359.08026123 - 359.09375 359.10723877 359.12075806 359.13424683 359.1477356 - 359.16125488 359.17474365 359.18826294 359.20175171 359.21524048 - 359.22875977 359.24224854 359.2557373 359.26925659 359.28274536 - 359.29626465 359.30975342 359.32324219 359.33676147 359.35025024 - 359.36373901 359.3772583 359.39074707 359.40423584 359.41775513 - 359.4312439 359.44476318 359.45825195 359.47174072 359.48526001 - 359.49874878 359.51223755 359.52575684 359.53924561 359.55276489 - 359.56625366 359.57974243 359.59326172 359.60675049 359.62023926 - 359.63375854 359.64724731 359.66073608 359.67425537 359.68774414 - 359.70126343 359.7147522 359.72824097 359.74176025 359.75524902 - 359.76873779 359.78225708 359.79574585 359.80926514 359.82275391 - 359.83624268 359.84976196 359.86325073 359.8767395 359.89025879 - 359.90374756 359.91723633 359.93075562 359.94424438 359.95776367 - 359.97125244 359.98474121 359.9982605 360.01174927 360.02523804 - 360.03875732 360.05224609 360.06573486 360.07925415 360.09274292 - 360.10626221 360.11975098 360.13323975 360.14675903 360.1602478 - 360.17373657 360.18725586 360.20074463 360.21426392 360.22775269 - 360.24124146 360.25476074 360.26824951 360.28173828 360.29525757 - 360.30874634 360.32223511 360.33575439 360.34924316 360.36276245 - 360.37625122 360.38973999 360.40325928 360.41674805 360.43023682 - 360.4437561 360.45724487 360.47076416 360.48425293 360.4977417 - 360.51126099 360.52474976 360.53823853 360.55175781 360.56524658 - 360.57873535 360.59225464 360.60574341 360.6192627 360.63275146 - 360.64624023 360.65975952 360.67324829 360.68673706 360.70025635 - 360.71374512 360.7272644 360.74075317 360.75424194 360.76776123 - 360.78125 360.79473877 360.80825806 360.82174683 360.8352356 - 360.84875488 360.86224365 360.87576294 360.88925171 360.90274048 - 360.91625977 360.92974854 360.9432373 360.95675659 360.97024536 - 360.98376465 360.99725342 361.01074219 361.02426147 361.03775024 - 361.05123901 361.0647583 361.07824707 361.09173584 361.10525513 - 361.1187439 361.13226318 361.14575195 361.15924072 361.17276001 - 361.18624878 361.19973755 361.21325684 361.22674561 361.24026489 - 361.25375366 361.26724243 361.28076172 361.29425049 361.30773926 - 361.32125854 361.33474731 361.34823608 361.36175537 361.37524414 - 361.38876343 361.4022522 361.41574097 361.42926025 361.44274902 - 361.45623779 361.46975708 361.48324585 361.49676514 361.51025391 - 361.52374268 361.53726196 361.55075073 361.5642395 361.57775879 - 361.59124756 361.60473633 361.61825562 361.63174438 361.64526367 - 361.65875244 361.67224121 361.6857605 361.69924927 361.71273804 - 361.72625732 361.73974609 361.75323486 361.76675415 361.78024292 - 361.79376221 361.80725098 361.82073975 361.83425903 361.8477478 - 361.86123657 361.87475586 361.88824463 361.90176392 361.91525269 - 361.92874146 361.94226074 361.95574951 361.96923828 361.98275757 - 361.99624634 362.00973511 362.02325439 362.03674316 362.05026245 - 362.06375122 362.07723999 362.09075928 362.10424805 362.11773682 - 362.1312561 362.14474487 362.15826416 362.17175293 362.1852417 - 362.19876099 362.21224976 362.22573853 362.23925781 362.25274658 - 362.26623535 362.27975464 362.29324341 362.3067627 362.32025146 - 362.33374023 362.34725952 362.36074829 362.37423706 362.38775635 - 362.40124512 362.4147644 362.42825317 362.44174194 362.45526123 - 362.46875 362.48223877 362.49575806 362.50924683 362.5227356 - 362.53625488 362.54974365 362.56326294 362.57675171 362.59024048 - 362.60375977 362.61724854 362.6307373 362.64425659 362.65774536 - 362.67126465 362.68475342 362.69824219 362.71176147 362.72525024 - 362.73873901 362.7522583 362.76574707 362.77923584 362.79275513 - 362.8062439 362.81976318 362.83325195 362.84674072 362.86026001 - 362.87374878 362.88723755 362.90075684 362.91424561 362.92776489 - 362.94125366 362.95474243 362.96826172 362.98175049 362.99523926 - 363.00875854 363.02224731 363.03573608 363.04925537 363.06274414 - 363.07626343 363.0897522 363.10324097 363.11676025 363.13024902 - 363.14373779 363.15725708 363.17074585 363.18426514 363.19775391 - 363.21124268 363.22476196 363.23825073 363.2517395 363.26525879 - 363.27874756 363.29223633 363.30575562 363.31951904 363.33377075 - 363.34857178 363.36395264 363.37991333 363.39645386 363.41360474 - 363.431427 363.44992065 363.46911621 363.48901367 363.50967407 - 363.53109741 363.55334473 363.57641602 363.60037231 363.62521362 - 363.65100098 363.67776489 363.70550537 363.73431396 363.76699829 - 363.80300903 363.83898926 363.875 363.91101074 363.94699097 - 363.98300171 364.01901245 364.05499268 364.09100342 364.12701416 - 364.16299438 364.19900513 364.23498535 364.27099609 364.30700684 - 364.34298706 364.3789978 364.41500854 364.45098877 364.48699951 - 364.52301025 364.55899048 364.59500122 364.63101196 364.66699219 - 364.70300293 364.73901367 364.7749939 364.81100464 364.84698486 - 364.88299561 364.91900635 364.95498657 364.99099731 365.02700806 - 365.06298828 365.09899902 365.13500977 365.17098999] - x_upper_bound: [ 353.07049561 353.10650635 353.14248657 353.17849731 353.21450806 - 353.25048828 353.28649902 353.32250977 353.35848999 353.39450073 - 353.43051147 353.4664917 353.50250244 353.53851318 353.57449341 - 353.61050415 353.64651489 353.68249512 353.71850586 353.75448608 - 353.79049683 353.82650757 353.86248779 353.89849854 353.93450928 - 353.9704895 354.00650024 354.04251099 354.07849121 354.11450195 - 354.1505127 354.18649292 354.22250366 354.2585144 354.29449463 - 354.33050537 354.3664856 354.40249634 354.43850708 354.4744873 - 354.50717163 354.53598022 354.56375122 354.59051514 354.61627197 - 354.6411438 354.66506958 354.68817139 354.71038818 354.73184204 - 354.75250244 354.7723999 354.79159546 354.81005859 354.82788086 - 354.84506226 354.86160278 354.87753296 354.89291382 354.90771484 - 354.92199707 354.9357605 354.94924927 354.96273804 354.97625732 - 354.98974609 355.00323486 355.01675415 355.03024292 355.04376221 - 355.05725098 355.07073975 355.08425903 355.0977478 355.11123657 - 355.12475586 355.13824463 355.15176392 355.16525269 355.17874146 - 355.19226074 355.20574951 355.21923828 355.23275757 355.24624634 - 355.25973511 355.27325439 355.28674316 355.30026245 355.31375122 - 355.32723999 355.34075928 355.35424805 355.36773682 355.3812561 - 355.39474487 355.40826416 355.42175293 355.4352417 355.44876099 - 355.46224976 355.47573853 355.48925781 355.50274658 355.51623535 - 355.52975464 355.54324341 355.5567627 355.57025146 355.58374023 - 355.59725952 355.61074829 355.62423706 355.63775635 355.65124512 - 355.6647644 355.67825317 355.69174194 355.70526123 355.71875 - 355.73223877 355.74575806 355.75924683 355.7727356 355.78625488 - 355.79974365 355.81326294 355.82675171 355.84024048 355.85375977 - 355.86724854 355.8807373 355.89425659 355.90774536 355.92126465 - 355.93475342 355.94824219 355.96176147 355.97525024 355.98873901 - 356.0022583 356.01574707 356.02923584 356.04275513 356.0562439 - 356.06976318 356.08325195 356.09674072 356.11026001 356.12374878 - 356.13723755 356.15075684 356.16424561 356.17776489 356.19125366 - 356.20474243 356.21826172 356.23175049 356.24523926 356.25875854 - 356.27224731 356.28573608 356.29925537 356.31274414 356.32626343 - 356.3397522 356.35324097 356.36676025 356.38024902 356.39373779 - 356.40725708 356.42074585 356.43426514 356.44775391 356.46124268 - 356.47476196 356.48825073 356.5017395 356.51525879 356.52874756 - 356.54223633 356.55575562 356.56924438 356.58276367 356.59625244 - 356.60974121 356.6232605 356.63674927 356.65023804 356.66375732 - 356.67724609 356.69073486 356.70425415 356.71774292 356.73126221 - 356.74475098 356.75823975 356.77175903 356.7852478 356.79873657 - 356.81225586 356.82574463 356.83926392 356.85275269 356.86624146 - 356.87976074 356.89324951 356.90673828 356.92025757 356.93374634 - 356.94723511 356.96075439 356.97424316 356.98776245 357.00125122 - 357.01473999 357.02825928 357.04174805 357.05523682 357.0687561 - 357.08224487 357.09576416 357.10925293 357.1227417 357.13626099 - 357.14974976 357.16323853 357.17675781 357.19024658 357.20373535 - 357.21725464 357.23074341 357.2442627 357.25775146 357.27124023 - 357.28475952 357.29824829 357.31173706 357.32525635 357.33874512 - 357.3522644 357.36575317 357.37924194 357.39276123 357.40625 - 357.41973877 357.43325806 357.44674683 357.4602356 357.47375488 - 357.48724365 357.50076294 357.51425171 357.52774048 357.54125977 - 357.55474854 357.5682373 357.58175659 357.59524536 357.60876465 - 357.62225342 357.63574219 357.64926147 357.66275024 357.67623901 - 357.6897583 357.70324707 357.71673584 357.73025513 357.7437439 - 357.75726318 357.77075195 357.78424072 357.79776001 357.81124878 - 357.82473755 357.83825684 357.85174561 357.86526489 357.87875366 - 357.89224243 357.90576172 357.91925049 357.93273926 357.94625854 - 357.95974731 357.97323608 357.98675537 358.00024414 358.01376343 - 358.0272522 358.04074097 358.05426025 358.06774902 358.08123779 - 358.09475708 358.10824585 358.12176514 358.13525391 358.14874268 - 358.16226196 358.17575073 358.1892395 358.20275879 358.21624756 - 358.22973633 358.24325562 358.25674438 358.27026367 358.28375244 - 358.29724121 358.3107605 358.32424927 358.33773804 358.35125732 - 358.36474609 358.37823486 358.39175415 358.40524292 358.41876221 - 358.43225098 358.44573975 358.45925903 358.4727478 358.48623657 - 358.49975586 358.51324463 358.52676392 358.54025269 358.55374146 - 358.56726074 358.58074951 358.59423828 358.60775757 358.62124634 - 358.63473511 358.64825439 358.66174316 358.67526245 358.68875122 - 358.70223999 358.71575928 358.72924805 358.74273682 358.7562561 - 358.76974487 358.78326416 358.79675293 358.8102417 358.82376099 - 358.83724976 358.85073853 358.86425781 358.87774658 358.89123535 - 358.90475464 358.91824341 358.9317627 358.94525146 358.95874023 - 358.97225952 358.98574829 358.99923706 359.01275635 359.02624512 - 359.0397644 359.05325317 359.06674194 359.08026123 359.09375 - 359.10723877 359.12075806 359.13424683 359.1477356 359.16125488 - 359.17474365 359.18826294 359.20175171 359.21524048 359.22875977 - 359.24224854 359.2557373 359.26925659 359.28274536 359.29626465 - 359.30975342 359.32324219 359.33676147 359.35025024 359.36373901 - 359.3772583 359.39074707 359.40423584 359.41775513 359.4312439 - 359.44476318 359.45825195 359.47174072 359.48526001 359.49874878 - 359.51223755 359.52575684 359.53924561 359.55276489 359.56625366 - 359.57974243 359.59326172 359.60675049 359.62023926 359.63375854 - 359.64724731 359.66073608 359.67425537 359.68774414 359.70126343 - 359.7147522 359.72824097 359.74176025 359.75524902 359.76873779 - 359.78225708 359.79574585 359.80926514 359.82275391 359.83624268 - 359.84976196 359.86325073 359.8767395 359.89025879 359.90374756 - 359.91723633 359.93075562 359.94424438 359.95776367 359.97125244 - 359.98474121 359.9982605 360.01174927 360.02523804 360.03875732 - 360.05224609 360.06573486 360.07925415 360.09274292 360.10626221 - 360.11975098 360.13323975 360.14675903 360.1602478 360.17373657 - 360.18725586 360.20074463 360.21426392 360.22775269 360.24124146 - 360.25476074 360.26824951 360.28173828 360.29525757 360.30874634 - 360.32223511 360.33575439 360.34924316 360.36276245 360.37625122 - 360.38973999 360.40325928 360.41674805 360.43023682 360.4437561 - 360.45724487 360.47076416 360.48425293 360.4977417 360.51126099 - 360.52474976 360.53823853 360.55175781 360.56524658 360.57873535 - 360.59225464 360.60574341 360.6192627 360.63275146 360.64624023 - 360.65975952 360.67324829 360.68673706 360.70025635 360.71374512 - 360.7272644 360.74075317 360.75424194 360.76776123 360.78125 - 360.79473877 360.80825806 360.82174683 360.8352356 360.84875488 - 360.86224365 360.87576294 360.88925171 360.90274048 360.91625977 - 360.92974854 360.9432373 360.95675659 360.97024536 360.98376465 - 360.99725342 361.01074219 361.02426147 361.03775024 361.05123901 - 361.0647583 361.07824707 361.09173584 361.10525513 361.1187439 - 361.13226318 361.14575195 361.15924072 361.17276001 361.18624878 - 361.19973755 361.21325684 361.22674561 361.24026489 361.25375366 - 361.26724243 361.28076172 361.29425049 361.30773926 361.32125854 - 361.33474731 361.34823608 361.36175537 361.37524414 361.38876343 - 361.4022522 361.41574097 361.42926025 361.44274902 361.45623779 - 361.46975708 361.48324585 361.49676514 361.51025391 361.52374268 - 361.53726196 361.55075073 361.5642395 361.57775879 361.59124756 - 361.60473633 361.61825562 361.63174438 361.64526367 361.65875244 - 361.67224121 361.6857605 361.69924927 361.71273804 361.72625732 - 361.73974609 361.75323486 361.76675415 361.78024292 361.79376221 - 361.80725098 361.82073975 361.83425903 361.8477478 361.86123657 - 361.87475586 361.88824463 361.90176392 361.91525269 361.92874146 - 361.94226074 361.95574951 361.96923828 361.98275757 361.99624634 - 362.00973511 362.02325439 362.03674316 362.05026245 362.06375122 - 362.07723999 362.09075928 362.10424805 362.11773682 362.1312561 - 362.14474487 362.15826416 362.17175293 362.1852417 362.19876099 - 362.21224976 362.22573853 362.23925781 362.25274658 362.26623535 - 362.27975464 362.29324341 362.3067627 362.32025146 362.33374023 - 362.34725952 362.36074829 362.37423706 362.38775635 362.40124512 - 362.4147644 362.42825317 362.44174194 362.45526123 362.46875 - 362.48223877 362.49575806 362.50924683 362.5227356 362.53625488 - 362.54974365 362.56326294 362.57675171 362.59024048 362.60375977 - 362.61724854 362.6307373 362.64425659 362.65774536 362.67126465 - 362.68475342 362.69824219 362.71176147 362.72525024 362.73873901 - 362.7522583 362.76574707 362.77923584 362.79275513 362.8062439 - 362.81976318 362.83325195 362.84674072 362.86026001 362.87374878 - 362.88723755 362.90075684 362.91424561 362.92776489 362.94125366 - 362.95474243 362.96826172 362.98175049 362.99523926 363.00875854 - 363.02224731 363.03573608 363.04925537 363.06274414 363.07626343 - 363.0897522 363.10324097 363.11676025 363.13024902 363.14373779 - 363.15725708 363.17074585 363.18426514 363.19775391 363.21124268 - 363.22476196 363.23825073 363.2517395 363.26525879 363.27874756 - 363.29223633 363.30575562 363.31951904 363.33377075 363.34857178 - 363.36395264 363.37991333 363.39645386 363.41360474 363.431427 - 363.44992065 363.46911621 363.48901367 363.50967407 363.53109741 - 363.55334473 363.57641602 363.60037231 363.62521362 363.65100098 - 363.67776489 363.70550537 363.73431396 363.76699829 363.80300903 - 363.83898926 363.875 363.91101074 363.94699097 363.98300171 - 364.01901245 364.05499268 364.09100342 364.12701416 364.16299438 - 364.19900513 364.23498535 364.27099609 364.30700684 364.34298706 - 364.3789978 364.41500854 364.45098877 364.48699951 364.52301025 - 364.55899048 364.59500122 364.63101196 364.66699219 364.70300293 - 364.73901367 364.7749939 364.81100464 364.84698486 364.88299561 - 364.91900635 364.95498657 364.99099731 365.02700806 365.06298828 - 365.09899902 365.13500977 365.17098999 365.20700073] - y: [ -5.59320021e+00 -5.55719995e+00 -5.52120018e+00 -5.48519993e+00 - -5.44920015e+00 -5.41319990e+00 -5.37720013e+00 -5.34119987e+00 - -5.30520010e+00 -5.26919985e+00 -5.23320007e+00 -5.19719982e+00 - -5.16120005e+00 -5.12519979e+00 -5.08920002e+00 -5.05319977e+00 - -5.01719999e+00 -4.98120022e+00 -4.94519997e+00 -4.90920019e+00 - -4.87319994e+00 -4.83720016e+00 -4.80119991e+00 -4.76520014e+00 - -4.72919989e+00 -4.69320011e+00 -4.65719986e+00 -4.62120008e+00 - -4.58519983e+00 -4.54920006e+00 -4.51319981e+00 -4.47720003e+00 - -4.44119978e+00 -4.40520000e+00 -4.36920023e+00 -4.33319998e+00 - -4.29720020e+00 -4.26119995e+00 -4.22520018e+00 -4.19377995e+00 - -4.16359854e+00 -4.13460732e+00 -4.10675907e+00 -4.08000851e+00 - -4.05431318e+00 -4.02963066e+00 -4.00592136e+00 -3.98314714e+00 - -3.96127057e+00 -3.94025683e+00 -3.92007136e+00 -3.90068197e+00 - -3.88205695e+00 -3.86416626e+00 -3.84698105e+00 -3.83047342e+00 - -3.81461668e+00 -3.79938507e+00 -3.78475404e+00 -3.77069998e+00 - -3.75720000e+00 -3.74370003e+00 -3.73020005e+00 -3.71670008e+00 - -3.70320010e+00 -3.68969989e+00 -3.67619991e+00 -3.66269994e+00 - -3.64919996e+00 -3.63569999e+00 -3.62220001e+00 -3.60870004e+00 - -3.59520006e+00 -3.58170009e+00 -3.56820011e+00 -3.55469990e+00 - -3.54119992e+00 -3.52769995e+00 -3.51419997e+00 -3.50070000e+00 - -3.48720002e+00 -3.47370005e+00 -3.46020007e+00 -3.44670010e+00 - -3.43319988e+00 -3.41969991e+00 -3.40619993e+00 -3.39269996e+00 - -3.37919998e+00 -3.36570001e+00 -3.35220003e+00 -3.33870006e+00 - -3.32520008e+00 -3.31170011e+00 -3.29819989e+00 -3.28469992e+00 - -3.27119994e+00 -3.25769997e+00 -3.24419999e+00 -3.23070002e+00 - -3.21720004e+00 -3.20370007e+00 -3.19020009e+00 -3.17670012e+00 - -3.16319990e+00 -3.14969993e+00 -3.13619995e+00 -3.12269998e+00 - -3.10920000e+00 -3.09570003e+00 -3.08220005e+00 -3.06870008e+00 - -3.05520010e+00 -3.04169989e+00 -3.02819991e+00 -3.01469994e+00 - -3.00119996e+00 -2.98769999e+00 -2.97420001e+00 -2.96070004e+00 - -2.94720006e+00 -2.93370008e+00 -2.92020011e+00 -2.90669990e+00 - -2.89319992e+00 -2.87969995e+00 -2.86619997e+00 -2.85270000e+00 - -2.83920002e+00 -2.82570004e+00 -2.81220007e+00 -2.79870009e+00 - -2.78520012e+00 -2.77169991e+00 -2.75819993e+00 -2.74469995e+00 - -2.73119998e+00 -2.71770000e+00 -2.70420003e+00 -2.69070005e+00 - -2.67720008e+00 -2.66370010e+00 -2.65019989e+00 -2.63669991e+00 - -2.62319994e+00 -2.60969996e+00 -2.59619999e+00 -2.58270001e+00 - -2.56920004e+00 -2.55570006e+00 -2.54220009e+00 -2.52870011e+00 - -2.51519990e+00 -2.50169992e+00 -2.48819995e+00 -2.47469997e+00 - -2.46120000e+00 -2.44770002e+00 -2.43420005e+00 -2.42070007e+00 - -2.40720010e+00 -2.39369988e+00 -2.38019991e+00 -2.36669993e+00 - -2.35319996e+00 -2.33969998e+00 -2.32620001e+00 -2.31270003e+00 - -2.29920006e+00 -2.28570008e+00 -2.27220011e+00 -2.25869989e+00 - -2.24519992e+00 -2.23169994e+00 -2.21819997e+00 -2.20469999e+00 - -2.19120002e+00 -2.17770004e+00 -2.16420007e+00 -2.15070009e+00 - -2.13720012e+00 -2.12369990e+00 -2.11019993e+00 -2.09669995e+00 - -2.08319998e+00 -2.06970000e+00 -2.05620003e+00 -2.04270005e+00 - -2.02920008e+00 -2.01570010e+00 -2.00219989e+00 -1.98870003e+00 - -1.97520006e+00 -1.96169996e+00 -1.94819999e+00 -1.93470001e+00 - -1.92120004e+00 -1.90769994e+00 -1.89419997e+00 -1.88069999e+00 - -1.86720002e+00 -1.85370004e+00 -1.84019995e+00 -1.82669997e+00 - -1.81320000e+00 -1.79970002e+00 -1.78620005e+00 -1.77269995e+00 - -1.75919998e+00 -1.74570000e+00 -1.73220003e+00 -1.71870005e+00 - -1.70519996e+00 -1.69169998e+00 -1.67820001e+00 -1.66470003e+00 - -1.65120006e+00 -1.63769996e+00 -1.62419999e+00 -1.61070001e+00 - -1.59720004e+00 -1.58369994e+00 -1.57019997e+00 -1.55669999e+00 - -1.54320002e+00 -1.52970004e+00 -1.51619995e+00 -1.50269997e+00 - -1.48920000e+00 -1.47570002e+00 -1.46220005e+00 -1.44869995e+00 - -1.43519998e+00 -1.42170000e+00 -1.40820003e+00 -1.39470005e+00 - -1.38119996e+00 -1.36769998e+00 -1.35420001e+00 -1.34070003e+00 - -1.32720006e+00 -1.31369996e+00 -1.30019999e+00 -1.28670001e+00 - -1.27320004e+00 -1.25969994e+00 -1.24619997e+00 -1.23269999e+00 - -1.21920002e+00 -1.20570004e+00 -1.19219995e+00 -1.17869997e+00 - -1.16520000e+00 -1.15170002e+00 -1.13820004e+00 -1.12469995e+00 - -1.11119998e+00 -1.09770000e+00 -1.08420002e+00 -1.07070005e+00 - -1.05719995e+00 -1.04369998e+00 -1.03020000e+00 -1.01670003e+00 - -1.00320005e+00 -9.89700019e-01 -9.76199985e-01 -9.62700009e-01 - -9.49199975e-01 -9.35699999e-01 -9.22200024e-01 -9.08699989e-01 - -8.95200014e-01 -8.81699979e-01 -8.68200004e-01 -8.54700029e-01 - -8.41199994e-01 -8.27700019e-01 -8.14199984e-01 -8.00700009e-01 - -7.87199974e-01 -7.73699999e-01 -7.60200024e-01 -7.46699989e-01 - -7.33200014e-01 -7.19699979e-01 -7.06200004e-01 -6.92700028e-01 - -6.79199994e-01 -6.65700018e-01 -6.52199984e-01 -6.38700008e-01 - -6.25199974e-01 -6.11699998e-01 -5.98200023e-01 -5.84699988e-01 - -5.71200013e-01 -5.57699978e-01 -5.44200003e-01 -5.30700028e-01 - -5.17199993e-01 -5.03700018e-01 -4.90200013e-01 -4.76700008e-01 - -4.63200003e-01 -4.49699998e-01 -4.36199993e-01 -4.22699988e-01 - -4.09200013e-01 -3.95700008e-01 -3.82200003e-01 -3.68699998e-01 - -3.55199993e-01 -3.41699988e-01 -3.28200012e-01 -3.14700007e-01 - -3.01200002e-01 -2.87699997e-01 -2.74199992e-01 -2.60699987e-01 - -2.47199997e-01 -2.33700007e-01 -2.20200002e-01 -2.06699997e-01 - -1.93200007e-01 -1.79700002e-01 -1.66199997e-01 -1.52700007e-01 - -1.39200002e-01 -1.25699997e-01 -1.12199999e-01 -9.87000018e-02 - -8.51999968e-02 -7.16999993e-02 -5.82000017e-02 -4.47000004e-02 - -3.11999992e-02 -1.76999997e-02 -4.19999985e-03 9.30000003e-03 - 2.28000004e-02 3.62999998e-02 4.98000011e-02 6.32999986e-02 - 7.68000036e-02 9.03000012e-02 1.03799999e-01 1.17299996e-01 - 1.30799994e-01 1.44299999e-01 1.57800004e-01 1.71299994e-01 - 1.84799999e-01 1.98300004e-01 2.11799994e-01 2.25299999e-01 - 2.38800004e-01 2.52299994e-01 2.65799999e-01 2.79300004e-01 - 2.92800009e-01 3.06300014e-01 3.19799989e-01 3.33299994e-01 - 3.46799999e-01 3.60300004e-01 3.73800009e-01 3.87300014e-01 - 4.00799990e-01 4.14299995e-01 4.27800000e-01 4.41300005e-01 - 4.54800010e-01 4.68300015e-01 4.81799990e-01 4.95299995e-01 - 5.08800030e-01 5.22300005e-01 5.35799980e-01 5.49300015e-01 - 5.62799990e-01 5.76300025e-01 5.89800000e-01 6.03299975e-01 - 6.16800010e-01 6.30299985e-01 6.43800020e-01 6.57299995e-01 - 6.70799971e-01 6.84300005e-01 6.97799981e-01 7.11300015e-01 - 7.24799991e-01 7.38300025e-01 7.51800001e-01 7.65299976e-01 - 7.78800011e-01 7.92299986e-01 8.05800021e-01 8.19299996e-01 - 8.32799971e-01 8.46300006e-01 8.59799981e-01 8.73300016e-01 - 8.86799991e-01 9.00300026e-01 9.13800001e-01 9.27299976e-01 - 9.40800011e-01 9.54299986e-01 9.67800021e-01 9.81299996e-01 - 9.94799972e-01 1.00829995e+00 1.02180004e+00 1.03530002e+00 - 1.04879999e+00 1.06229997e+00 1.07579994e+00 1.08930004e+00 - 1.10280001e+00 1.11629999e+00 1.12979996e+00 1.14330006e+00 - 1.15680003e+00 1.17030001e+00 1.18379998e+00 1.19729996e+00 - 1.21080005e+00 1.22430003e+00 1.23780000e+00 1.25129998e+00 - 1.26479995e+00 1.27830005e+00 1.29180002e+00 1.30530000e+00 - 1.31879997e+00 1.33229995e+00 1.34580004e+00 1.35930002e+00 - 1.37279999e+00 1.38629997e+00 1.39979994e+00 1.41330004e+00 - 1.42680001e+00 1.44029999e+00 1.45379996e+00 1.46730006e+00 - 1.48080003e+00 1.49430001e+00 1.50779998e+00 1.52129996e+00 - 1.53480005e+00 1.54830003e+00 1.56180000e+00 1.57529998e+00 - 1.58879995e+00 1.60230005e+00 1.61580002e+00 1.62930000e+00 - 1.64279997e+00 1.65629995e+00 1.66980004e+00 1.68330002e+00 - 1.69679999e+00 1.71029997e+00 1.72379994e+00 1.73730004e+00 - 1.75080001e+00 1.76429999e+00 1.77779996e+00 1.79130006e+00 - 1.80480003e+00 1.81830001e+00 1.83179998e+00 1.84529996e+00 - 1.85880005e+00 1.87230003e+00 1.88580000e+00 1.89929998e+00 - 1.91279995e+00 1.92630005e+00 1.93980002e+00 1.95330000e+00 - 1.96679997e+00 1.98029995e+00 1.99380004e+00 2.00729990e+00 - 2.02080011e+00 2.03430009e+00 2.04780006e+00 2.06130004e+00 - 2.07480001e+00 2.08829999e+00 2.10179996e+00 2.11529994e+00 - 2.12879992e+00 2.14229989e+00 2.15580010e+00 2.16930008e+00 - 2.18280005e+00 2.19630003e+00 2.20980000e+00 2.22329998e+00 - 2.23679996e+00 2.25029993e+00 2.26379991e+00 2.27729988e+00 - 2.29080009e+00 2.30430007e+00 2.31780005e+00 2.33130002e+00 - 2.34480000e+00 2.35829997e+00 2.37179995e+00 2.38529992e+00 - 2.39879990e+00 2.41230011e+00 2.42580009e+00 2.43930006e+00 - 2.45280004e+00 2.46630001e+00 2.47979999e+00 2.49329996e+00 - 2.50679994e+00 2.52029991e+00 2.53379989e+00 2.54730010e+00 - 2.56080008e+00 2.57430005e+00 2.58780003e+00 2.60130000e+00 - 2.61479998e+00 2.62829995e+00 2.64179993e+00 2.65529990e+00 - 2.66880012e+00 2.68230009e+00 2.69580007e+00 2.70930004e+00 - 2.72280002e+00 2.73629999e+00 2.74979997e+00 2.76329994e+00 - 2.77679992e+00 2.79029989e+00 2.80380011e+00 2.81730008e+00 - 2.83080006e+00 2.84430003e+00 2.85780001e+00 2.87129998e+00 - 2.88479996e+00 2.89829993e+00 2.91179991e+00 2.92529988e+00 - 2.93880010e+00 2.95230007e+00 2.96580005e+00 2.97930002e+00 - 2.99280000e+00 3.00629997e+00 3.01979995e+00 3.03329992e+00 - 3.04679990e+00 3.06030011e+00 3.07380009e+00 3.08730006e+00 - 3.10080004e+00 3.11430001e+00 3.12779999e+00 3.14129996e+00 - 3.15479994e+00 3.16829991e+00 3.18179989e+00 3.19530010e+00 - 3.20880008e+00 3.22230005e+00 3.23580003e+00 3.24930000e+00 - 3.26279998e+00 3.27629995e+00 3.28979993e+00 3.30329990e+00 - 3.31680012e+00 3.33030009e+00 3.34380007e+00 3.35730004e+00 - 3.37080002e+00 3.38429999e+00 3.39779997e+00 3.41129994e+00 - 3.42479992e+00 3.43829989e+00 3.45180011e+00 3.46530008e+00 - 3.47880006e+00 3.49230003e+00 3.50580001e+00 3.51929998e+00 - 3.53279996e+00 3.54629993e+00 3.55979991e+00 3.57329988e+00 - 3.58680010e+00 3.60030007e+00 3.61380005e+00 3.62730002e+00 - 3.64080000e+00 3.65429997e+00 3.66779995e+00 3.68129992e+00 - 3.69479990e+00 3.70830011e+00 3.72180009e+00 3.73530006e+00 - 3.74880004e+00 3.76230001e+00 3.77579999e+00 3.78929996e+00 - 3.80279994e+00 3.81629992e+00 3.82979989e+00 3.84330010e+00 - 3.85680008e+00 3.87030005e+00 3.88380003e+00 3.89730000e+00 - 3.91079998e+00 3.92429996e+00 3.93779993e+00 3.95129991e+00 - 3.96479988e+00 3.97830009e+00 3.99180007e+00 4.00530005e+00 - 4.01879978e+00 4.03230000e+00 4.04580021e+00 4.05929995e+00 - 4.07280016e+00 4.08629990e+00 4.09980011e+00 4.11329985e+00 - 4.12680006e+00 4.14029980e+00 4.15380001e+00 4.16730022e+00 - 4.18079996e+00 4.19430017e+00 4.20779991e+00 4.22130013e+00 - 4.23479986e+00 4.24830008e+00 4.26179981e+00 4.27530003e+00 - 4.28879976e+00 4.30229998e+00 4.31580019e+00 4.32929993e+00 - 4.34280014e+00 4.35629988e+00 4.36980009e+00 4.38329983e+00 - 4.39680004e+00 4.41029978e+00 4.42379999e+00 4.43730021e+00 - 4.45079994e+00 4.46430016e+00 4.47779989e+00 4.49130011e+00 - 4.50479984e+00 4.51830006e+00 4.53179979e+00 4.54530001e+00 - 4.55880022e+00 4.57229996e+00 4.58580017e+00 4.59929991e+00 - 4.61280012e+00 4.62629986e+00 4.63980007e+00 4.65329981e+00 - 4.66680002e+00 4.68030024e+00 4.69379997e+00 4.70730019e+00 - 4.72079992e+00 4.73430014e+00 4.74779987e+00 4.76130009e+00 - 4.77479982e+00 4.78830004e+00 4.80179977e+00 4.81529999e+00 - 4.82880020e+00 4.84229994e+00 4.85580015e+00 4.86929989e+00 - 4.88280010e+00 4.89629984e+00 4.90980005e+00 4.92329979e+00 - 4.93680000e+00 4.95030022e+00 4.96379995e+00 4.97730017e+00 - 4.99079990e+00 5.00430012e+00 5.01779985e+00 5.03130007e+00 - 5.04479980e+00 5.05830002e+00 5.07180023e+00 5.08529997e+00 - 5.09880018e+00 5.11229992e+00 5.12580013e+00 5.13929987e+00 - 5.15280008e+00 5.16629982e+00 5.17980003e+00 5.19329977e+00 - 5.20679998e+00 5.22030020e+00 5.23379993e+00 5.24730015e+00 - 5.26079988e+00 5.27430010e+00 5.28779984e+00 5.30130005e+00 - 5.31479979e+00 5.32830000e+00 5.34180021e+00 5.35529995e+00 - 5.36880016e+00 5.38229990e+00 5.39580011e+00 5.40929985e+00 - 5.42280006e+00 5.43629980e+00 5.44980001e+00 5.46330023e+00 - 5.47679996e+00 5.49030018e+00 5.50379992e+00 5.51730013e+00 - 5.53079987e+00 5.54430008e+00 5.55779982e+00 5.57130003e+00 - 5.58479977e+00 5.59829998e+00 5.61180019e+00 5.62529993e+00 - 5.63880014e+00 5.65229988e+00 5.66580009e+00 5.67929983e+00 - 5.69280005e+00 5.70629978e+00 5.71980000e+00 5.73330021e+00 - 5.74679995e+00 5.76030016e+00 5.77379990e+00 5.78730011e+00 - 5.80079985e+00 5.81430006e+00 5.82779980e+00 5.84130001e+00 - 5.85480022e+00 5.86829996e+00 5.88180017e+00 5.89529991e+00 - 5.90880013e+00 5.92229986e+00 5.93580008e+00 5.94929981e+00 - 5.96280003e+00 5.97629976e+00 5.98979998e+00 6.00330019e+00 - 6.01679993e+00 6.03030014e+00 6.04379988e+00 6.05730009e+00 - 6.07079983e+00 6.08430004e+00 6.09779978e+00 6.11129999e+00 - 6.12480021e+00 6.13829994e+00 6.15180016e+00 6.16529989e+00 - 6.17880011e+00 6.19229984e+00 6.20580006e+00 6.21929979e+00 - 6.23280001e+00 6.24630022e+00 6.25979996e+00 6.27330017e+00 - 6.28679991e+00 6.30030012e+00 6.31379986e+00 6.32730007e+00 - 6.34079981e+00 6.35430002e+00 6.36780024e+00 6.38129997e+00 - 6.39480019e+00 6.40829992e+00 6.42180014e+00 6.43529987e+00 - 6.44880009e+00 6.46229982e+00 6.47580004e+00 6.48929977e+00 - 6.50279999e+00 6.51630020e+00 6.52979994e+00 6.54330015e+00 - 6.55679989e+00 6.57030010e+00 6.58379984e+00 6.59730005e+00 - 6.61079979e+00 6.62430000e+00 6.63780022e+00 6.65129995e+00 - 6.66480017e+00 6.67829990e+00 6.69180012e+00 6.70529985e+00 - 6.71880007e+00 6.73229980e+00 6.74580002e+00 6.75930023e+00 - 6.77279997e+00 6.78630018e+00 6.79979992e+00 6.81330013e+00 - 6.82679987e+00 6.84030008e+00 6.85379982e+00 6.86730003e+00 - 6.88079977e+00 6.89429998e+00 6.90780020e+00 6.92129993e+00 - 6.93480015e+00 6.94829988e+00 6.96180010e+00 6.97529984e+00 - 6.98880005e+00 7.00229979e+00 7.01580000e+00 7.02930021e+00 - 7.04279995e+00 7.05630016e+00 7.06979990e+00 7.08330011e+00 - 7.09679985e+00 7.11030006e+00 7.12379980e+00 7.13730001e+00 - 7.15080023e+00 7.16485405e+00 7.17948532e+00 7.19471693e+00 - 7.21057367e+00 7.22708130e+00 7.24426651e+00 7.26215696e+00 - 7.28078175e+00 7.30017138e+00 7.32035685e+00 7.34137058e+00 - 7.36324692e+00 7.38602161e+00 7.40973091e+00 7.43441296e+00 - 7.46010876e+00 7.48685884e+00 7.51470709e+00 7.54369831e+00 - 7.57387972e+00 7.60529995e+00 7.64130020e+00 7.67729998e+00 - 7.71330023e+00 7.74930000e+00 7.78529978e+00 7.82130003e+00 - 7.85729980e+00 7.89330006e+00 7.92929983e+00 7.96530008e+00 - 8.00129986e+00 8.03730011e+00 8.07330036e+00 8.10929966e+00 - 8.14529991e+00 8.18130016e+00 8.21730042e+00 8.25329971e+00 - 8.28929996e+00 8.32530022e+00 8.36130047e+00 8.39729977e+00 - 8.43330002e+00 8.46930027e+00 8.50529957e+00 8.54129982e+00 - 8.57730007e+00 8.61330032e+00 8.64929962e+00 8.68529987e+00 - 8.72130013e+00 8.75730038e+00 8.79329967e+00 8.82929993e+00 - 8.86530018e+00 8.90130043e+00 8.93729973e+00 8.97329998e+00] - y_lower_bound: [ -5.61120033e+00 -5.57520008e+00 -5.53919983e+00 -5.50320005e+00 - -5.46719980e+00 -5.43120003e+00 -5.39519978e+00 -5.35920000e+00 - -5.32320023e+00 -5.28719997e+00 -5.25120020e+00 -5.21519995e+00 - -5.17920017e+00 -5.14319992e+00 -5.10720015e+00 -5.07119989e+00 - -5.03520012e+00 -4.99919987e+00 -4.96320009e+00 -4.92719984e+00 - -4.89120007e+00 -4.85519981e+00 -4.81920004e+00 -4.78319979e+00 - -4.74720001e+00 -4.71120024e+00 -4.67519999e+00 -4.63920021e+00 - -4.60319996e+00 -4.56720018e+00 -4.53119993e+00 -4.49520016e+00 - -4.45919991e+00 -4.42320013e+00 -4.38719988e+00 -4.35120010e+00 - -4.31519985e+00 -4.27920008e+00 -4.24319983e+00 -4.20948982e+00 - -4.17868900e+00 -4.14910269e+00 -4.12068319e+00 -4.09338379e+00 - -4.06716108e+00 -4.04197168e+00 -4.01777601e+00 -3.99453425e+00 - -3.97220898e+00 -3.95076370e+00 -3.93016410e+00 -3.91037679e+00 - -3.89136934e+00 -3.87311172e+00 -3.85557365e+00 -3.83872724e+00 - -3.82254505e+00 -3.80700088e+00 -3.79206967e+00 -3.77772713e+00 - -3.76395011e+00 -3.75044990e+00 -3.73694992e+00 -3.72344995e+00 - -3.70994997e+00 -3.69645000e+00 -3.68295002e+00 -3.66945004e+00 - -3.65595007e+00 -3.64245009e+00 -3.62895012e+00 -3.61544991e+00 - -3.60194993e+00 -3.58844995e+00 -3.57494998e+00 -3.56145000e+00 - -3.54795003e+00 -3.53445005e+00 -3.52095008e+00 -3.50745010e+00 - -3.49394989e+00 -3.48044991e+00 -3.46694994e+00 -3.45344996e+00 - -3.43994999e+00 -3.42645001e+00 -3.41295004e+00 -3.39945006e+00 - -3.38595009e+00 -3.37245011e+00 -3.35894990e+00 -3.34544992e+00 - -3.33194995e+00 -3.31844997e+00 -3.30495000e+00 -3.29145002e+00 - -3.27795005e+00 -3.26445007e+00 -3.25095010e+00 -3.23744988e+00 - -3.22394991e+00 -3.21044993e+00 -3.19694996e+00 -3.18344998e+00 - -3.16995001e+00 -3.15645003e+00 -3.14295006e+00 -3.12945008e+00 - -3.11595011e+00 -3.10244989e+00 -3.08894992e+00 -3.07544994e+00 - -3.06194997e+00 -3.04844999e+00 -3.03495002e+00 -3.02145004e+00 - -3.00795007e+00 -2.99445009e+00 -2.98095012e+00 -2.96744990e+00 - -2.95394993e+00 -2.94044995e+00 -2.92694998e+00 -2.91345000e+00 - -2.89995003e+00 -2.88645005e+00 -2.87295008e+00 -2.85945010e+00 - -2.84594989e+00 -2.83244991e+00 -2.81894994e+00 -2.80544996e+00 - -2.79194999e+00 -2.77845001e+00 -2.76495004e+00 -2.75145006e+00 - -2.73795009e+00 -2.72445011e+00 -2.71094990e+00 -2.69744992e+00 - -2.68394995e+00 -2.67044997e+00 -2.65695000e+00 -2.64345002e+00 - -2.62995005e+00 -2.61645007e+00 -2.60295010e+00 -2.58944988e+00 - -2.57594991e+00 -2.56244993e+00 -2.54894996e+00 -2.53544998e+00 - -2.52195001e+00 -2.50845003e+00 -2.49495006e+00 -2.48145008e+00 - -2.46795011e+00 -2.45444989e+00 -2.44094992e+00 -2.42744994e+00 - -2.41394997e+00 -2.40044999e+00 -2.38695002e+00 -2.37345004e+00 - -2.35995007e+00 -2.34645009e+00 -2.33295012e+00 -2.31944990e+00 - -2.30594993e+00 -2.29244995e+00 -2.27894998e+00 -2.26545000e+00 - -2.25195003e+00 -2.23845005e+00 -2.22495008e+00 -2.21145010e+00 - -2.19794989e+00 -2.18444991e+00 -2.17094994e+00 -2.15744996e+00 - -2.14394999e+00 -2.13045001e+00 -2.11695004e+00 -2.10345006e+00 - -2.08995008e+00 -2.07645011e+00 -2.06294990e+00 -2.04944992e+00 - -2.03594995e+00 -2.02244997e+00 -2.00895000e+00 -1.99545002e+00 - -1.98195004e+00 -1.96844995e+00 -1.95494998e+00 -1.94145000e+00 - -1.92795002e+00 -1.91445005e+00 -1.90094995e+00 -1.88744998e+00 - -1.87395000e+00 -1.86045003e+00 -1.84695005e+00 -1.83344996e+00 - -1.81994998e+00 -1.80645001e+00 -1.79295003e+00 -1.77945006e+00 - -1.76594996e+00 -1.75244999e+00 -1.73895001e+00 -1.72545004e+00 - -1.71194994e+00 -1.69844997e+00 -1.68494999e+00 -1.67145002e+00 - -1.65795004e+00 -1.64444995e+00 -1.63094997e+00 -1.61745000e+00 - -1.60395002e+00 -1.59045005e+00 -1.57694995e+00 -1.56344998e+00 - -1.54995000e+00 -1.53645003e+00 -1.52295005e+00 -1.50944996e+00 - -1.49594998e+00 -1.48245001e+00 -1.46895003e+00 -1.45545006e+00 - -1.44194996e+00 -1.42844999e+00 -1.41495001e+00 -1.40145004e+00 - -1.38794994e+00 -1.37444997e+00 -1.36094999e+00 -1.34745002e+00 - -1.33395004e+00 -1.32044995e+00 -1.30694997e+00 -1.29345000e+00 - -1.27995002e+00 -1.26645005e+00 -1.25294995e+00 -1.23944998e+00 - -1.22595000e+00 -1.21245003e+00 -1.19895005e+00 -1.18544996e+00 - -1.17194998e+00 -1.15845001e+00 -1.14495003e+00 -1.13145006e+00 - -1.11794996e+00 -1.10444999e+00 -1.09095001e+00 -1.07745004e+00 - -1.06394994e+00 -1.05044997e+00 -1.03694999e+00 -1.02345002e+00 - -1.00995004e+00 -9.96450007e-01 -9.82949972e-01 -9.69449997e-01 - -9.55950022e-01 -9.42449987e-01 -9.28950012e-01 -9.15449977e-01 - -9.01950002e-01 -8.88450027e-01 -8.74949992e-01 -8.61450016e-01 - -8.47949982e-01 -8.34450006e-01 -8.20949972e-01 -8.07449996e-01 - -7.93950021e-01 -7.80449986e-01 -7.66950011e-01 -7.53449976e-01 - -7.39950001e-01 -7.26450026e-01 -7.12949991e-01 -6.99450016e-01 - -6.85949981e-01 -6.72450006e-01 -6.58949971e-01 -6.45449996e-01 - -6.31950021e-01 -6.18449986e-01 -6.04950011e-01 -5.91449976e-01 - -5.77950001e-01 -5.64450026e-01 -5.50949991e-01 -5.37450016e-01 - -5.23949981e-01 -5.10450006e-01 -4.96950001e-01 -4.83449996e-01 - -4.69949991e-01 -4.56449986e-01 -4.42950010e-01 -4.29450005e-01 - -4.15950000e-01 -4.02449995e-01 -3.88949990e-01 -3.75449985e-01 - -3.61950010e-01 -3.48450005e-01 -3.34950000e-01 -3.21449995e-01 - -3.07949990e-01 -2.94450015e-01 -2.80950010e-01 -2.67450005e-01 - -2.53950000e-01 -2.40449995e-01 -2.26950005e-01 -2.13450000e-01 - -1.99949995e-01 -1.86450005e-01 -1.72950000e-01 -1.59449995e-01 - -1.45950004e-01 -1.32449999e-01 -1.18950002e-01 -1.05449997e-01 - -9.19499993e-02 -7.84500018e-02 -6.49499968e-02 -5.14499992e-02 - -3.79500017e-02 -2.44500004e-02 -1.09500000e-02 2.55000009e-03 - 1.60499997e-02 2.95499992e-02 4.30499986e-02 5.65499999e-02 - 7.00500011e-02 8.35499987e-02 9.70500037e-02 1.10550001e-01 - 1.24049999e-01 1.37549996e-01 1.51050001e-01 1.64550006e-01 - 1.78049996e-01 1.91550002e-01 2.05050007e-01 2.18549997e-01 - 2.32050002e-01 2.45550007e-01 2.59050012e-01 2.72549987e-01 - 2.86049992e-01 2.99549997e-01 3.13050002e-01 3.26550007e-01 - 3.40050012e-01 3.53549987e-01 3.67049992e-01 3.80549997e-01 - 3.94050002e-01 4.07550007e-01 4.21050012e-01 4.34549987e-01 - 4.48049992e-01 4.61549997e-01 4.75050002e-01 4.88550007e-01 - 5.02049983e-01 5.15550017e-01 5.29049993e-01 5.42550027e-01 - 5.56050003e-01 5.69549978e-01 5.83050013e-01 5.96549988e-01 - 6.10050023e-01 6.23549998e-01 6.37049973e-01 6.50550008e-01 - 6.64049983e-01 6.77550018e-01 6.91049993e-01 7.04550028e-01 - 7.18050003e-01 7.31549978e-01 7.45050013e-01 7.58549988e-01 - 7.72050023e-01 7.85549998e-01 7.99049973e-01 8.12550008e-01 - 8.26049984e-01 8.39550018e-01 8.53049994e-01 8.66550028e-01 - 8.80050004e-01 8.93549979e-01 9.07050014e-01 9.20549989e-01 - 9.34050024e-01 9.47549999e-01 9.61049974e-01 9.74550009e-01 - 9.88049984e-01 1.00154996e+00 1.01505005e+00 1.02855003e+00 - 1.04205000e+00 1.05554998e+00 1.06904995e+00 1.08255005e+00 - 1.09605002e+00 1.10955000e+00 1.12304997e+00 1.13654995e+00 - 1.15005004e+00 1.16355002e+00 1.17704999e+00 1.19054997e+00 - 1.20404994e+00 1.21755004e+00 1.23105001e+00 1.24454999e+00 - 1.25804996e+00 1.27155006e+00 1.28505003e+00 1.29855001e+00 - 1.31204998e+00 1.32554996e+00 1.33905005e+00 1.35255003e+00 - 1.36605000e+00 1.37954998e+00 1.39304996e+00 1.40655005e+00 - 1.42005002e+00 1.43355000e+00 1.44704998e+00 1.46054995e+00 - 1.47405005e+00 1.48755002e+00 1.50105000e+00 1.51454997e+00 - 1.52804995e+00 1.54155004e+00 1.55505002e+00 1.56854999e+00 - 1.58204997e+00 1.59554994e+00 1.60905004e+00 1.62255001e+00 - 1.63604999e+00 1.64954996e+00 1.66305006e+00 1.67655003e+00 - 1.69005001e+00 1.70354998e+00 1.71704996e+00 1.73055005e+00 - 1.74405003e+00 1.75755000e+00 1.77104998e+00 1.78454995e+00 - 1.79805005e+00 1.81155002e+00 1.82505000e+00 1.83854997e+00 - 1.85204995e+00 1.86555004e+00 1.87905002e+00 1.89254999e+00 - 1.90604997e+00 1.91954994e+00 1.93305004e+00 1.94655001e+00 - 1.96004999e+00 1.97354996e+00 1.98705006e+00 2.00055003e+00 - 2.01405001e+00 2.02754998e+00 2.04104996e+00 2.05454993e+00 - 2.06804991e+00 2.08154988e+00 2.09505010e+00 2.10855007e+00 - 2.12205005e+00 2.13555002e+00 2.14905000e+00 2.16254997e+00 - 2.17604995e+00 2.18954992e+00 2.20304990e+00 2.21655011e+00 - 2.23005009e+00 2.24355006e+00 2.25705004e+00 2.27055001e+00 - 2.28404999e+00 2.29754996e+00 2.31104994e+00 2.32454991e+00 - 2.33804989e+00 2.35155010e+00 2.36505008e+00 2.37855005e+00 - 2.39205003e+00 2.40555000e+00 2.41904998e+00 2.43254995e+00 - 2.44604993e+00 2.45954990e+00 2.47305012e+00 2.48655009e+00 - 2.50005007e+00 2.51355004e+00 2.52705002e+00 2.54054999e+00 - 2.55404997e+00 2.56754994e+00 2.58104992e+00 2.59454989e+00 - 2.60805011e+00 2.62155008e+00 2.63505006e+00 2.64855003e+00 - 2.66205001e+00 2.67554998e+00 2.68904996e+00 2.70254993e+00 - 2.71604991e+00 2.72954988e+00 2.74305010e+00 2.75655007e+00 - 2.77005005e+00 2.78355002e+00 2.79705000e+00 2.81054997e+00 - 2.82404995e+00 2.83754992e+00 2.85104990e+00 2.86455011e+00 - 2.87805009e+00 2.89155006e+00 2.90505004e+00 2.91855001e+00 - 2.93204999e+00 2.94554996e+00 2.95904994e+00 2.97254992e+00 - 2.98604989e+00 2.99955010e+00 3.01305008e+00 3.02655005e+00 - 3.04005003e+00 3.05355000e+00 3.06704998e+00 3.08054996e+00 - 3.09404993e+00 3.10754991e+00 3.12104988e+00 3.13455009e+00 - 3.14805007e+00 3.16155005e+00 3.17505002e+00 3.18855000e+00 - 3.20204997e+00 3.21554995e+00 3.22904992e+00 3.24254990e+00 - 3.25605011e+00 3.26955009e+00 3.28305006e+00 3.29655004e+00 - 3.31005001e+00 3.32354999e+00 3.33704996e+00 3.35054994e+00 - 3.36404991e+00 3.37754989e+00 3.39105010e+00 3.40455008e+00 - 3.41805005e+00 3.43155003e+00 3.44505000e+00 3.45854998e+00 - 3.47204995e+00 3.48554993e+00 3.49904990e+00 3.51255012e+00 - 3.52605009e+00 3.53955007e+00 3.55305004e+00 3.56655002e+00 - 3.58004999e+00 3.59354997e+00 3.60704994e+00 3.62054992e+00 - 3.63404989e+00 3.64755011e+00 3.66105008e+00 3.67455006e+00 - 3.68805003e+00 3.70155001e+00 3.71504998e+00 3.72854996e+00 - 3.74204993e+00 3.75554991e+00 3.76904988e+00 3.78255010e+00 - 3.79605007e+00 3.80955005e+00 3.82305002e+00 3.83655000e+00 - 3.85004997e+00 3.86354995e+00 3.87704992e+00 3.89054990e+00 - 3.90405011e+00 3.91755009e+00 3.93105006e+00 3.94455004e+00 - 3.95805001e+00 3.97154999e+00 3.98504996e+00 3.99854994e+00 - 4.01205015e+00 4.02554989e+00 4.03905010e+00 4.05254984e+00 - 4.06605005e+00 4.07954979e+00 4.09305000e+00 4.10655022e+00 - 4.12004995e+00 4.13355017e+00 4.14704990e+00 4.16055012e+00 - 4.17404985e+00 4.18755007e+00 4.20104980e+00 4.21455002e+00 - 4.22805023e+00 4.24154997e+00 4.25505018e+00 4.26854992e+00 - 4.28205013e+00 4.29554987e+00 4.30905008e+00 4.32254982e+00 - 4.33605003e+00 4.34954977e+00 4.36304998e+00 4.37655020e+00 - 4.39004993e+00 4.40355015e+00 4.41704988e+00 4.43055010e+00 - 4.44404984e+00 4.45755005e+00 4.47104979e+00 4.48455000e+00 - 4.49805021e+00 4.51154995e+00 4.52505016e+00 4.53854990e+00 - 4.55205011e+00 4.56554985e+00 4.57905006e+00 4.59254980e+00 - 4.60605001e+00 4.61955023e+00 4.63304996e+00 4.64655018e+00 - 4.66004992e+00 4.67355013e+00 4.68704987e+00 4.70055008e+00 - 4.71404982e+00 4.72755003e+00 4.74104977e+00 4.75454998e+00 - 4.76805019e+00 4.78154993e+00 4.79505014e+00 4.80854988e+00 - 4.82205009e+00 4.83554983e+00 4.84905005e+00 4.86254978e+00 - 4.87605000e+00 4.88955021e+00 4.90304995e+00 4.91655016e+00 - 4.93004990e+00 4.94355011e+00 4.95704985e+00 4.97055006e+00 - 4.98404980e+00 4.99755001e+00 5.01105022e+00 5.02454996e+00 - 5.03805017e+00 5.05154991e+00 5.06505013e+00 5.07854986e+00 - 5.09205008e+00 5.10554981e+00 5.11905003e+00 5.13254976e+00 - 5.14604998e+00 5.15955019e+00 5.17304993e+00 5.18655014e+00 - 5.20004988e+00 5.21355009e+00 5.22704983e+00 5.24055004e+00 - 5.25404978e+00 5.26754999e+00 5.28105021e+00 5.29454994e+00 - 5.30805016e+00 5.32154989e+00 5.33505011e+00 5.34854984e+00 - 5.36205006e+00 5.37554979e+00 5.38905001e+00 5.40255022e+00 - 5.41604996e+00 5.42955017e+00 5.44304991e+00 5.45655012e+00 - 5.47004986e+00 5.48355007e+00 5.49704981e+00 5.51055002e+00 - 5.52405024e+00 5.53754997e+00 5.55105019e+00 5.56454992e+00 - 5.57805014e+00 5.59154987e+00 5.60505009e+00 5.61854982e+00 - 5.63205004e+00 5.64554977e+00 5.65904999e+00 5.67255020e+00 - 5.68604994e+00 5.69955015e+00 5.71304989e+00 5.72655010e+00 - 5.74004984e+00 5.75355005e+00 5.76704979e+00 5.78055000e+00 - 5.79405022e+00 5.80754995e+00 5.82105017e+00 5.83454990e+00 - 5.84805012e+00 5.86154985e+00 5.87505007e+00 5.88854980e+00 - 5.90205002e+00 5.91555023e+00 5.92904997e+00 5.94255018e+00 - 5.95604992e+00 5.96955013e+00 5.98304987e+00 5.99655008e+00 - 6.01004982e+00 6.02355003e+00 6.03704977e+00 6.05054998e+00 - 6.06405020e+00 6.07754993e+00 6.09105015e+00 6.10454988e+00 - 6.11805010e+00 6.13154984e+00 6.14505005e+00 6.15854979e+00 - 6.17205000e+00 6.18555021e+00 6.19904995e+00 6.21255016e+00 - 6.22604990e+00 6.23955011e+00 6.25304985e+00 6.26655006e+00 - 6.28004980e+00 6.29355001e+00 6.30705023e+00 6.32054996e+00 - 6.33405018e+00 6.34754992e+00 6.36105013e+00 6.37454987e+00 - 6.38805008e+00 6.40154982e+00 6.41505003e+00 6.42854977e+00 - 6.44204998e+00 6.45555019e+00 6.46904993e+00 6.48255014e+00 - 6.49604988e+00 6.50955009e+00 6.52304983e+00 6.53655005e+00 - 6.55004978e+00 6.56355000e+00 6.57705021e+00 6.59054995e+00 - 6.60405016e+00 6.61754990e+00 6.63105011e+00 6.64454985e+00 - 6.65805006e+00 6.67154980e+00 6.68505001e+00 6.69855022e+00 - 6.71204996e+00 6.72555017e+00 6.73904991e+00 6.75255013e+00 - 6.76604986e+00 6.77955008e+00 6.79304981e+00 6.80655003e+00 - 6.82004976e+00 6.83354998e+00 6.84705019e+00 6.86054993e+00 - 6.87405014e+00 6.88754988e+00 6.90105009e+00 6.91454983e+00 - 6.92805004e+00 6.94154978e+00 6.95504999e+00 6.96855021e+00 - 6.98204994e+00 6.99555016e+00 7.00904989e+00 7.02255011e+00 - 7.03604984e+00 7.04955006e+00 7.06304979e+00 7.07655001e+00 - 7.09005022e+00 7.10354996e+00 7.11705017e+00 7.13054991e+00 - 7.14405012e+00 7.15782690e+00 7.17216969e+00 7.18710089e+00 - 7.20264530e+00 7.21882725e+00 7.23567390e+00 7.25321150e+00 - 7.27146959e+00 7.29047680e+00 7.31026411e+00 7.33086348e+00 - 7.35230875e+00 7.37463427e+00 7.39787626e+00 7.42207193e+00 - 7.44726086e+00 7.47348356e+00 7.50078297e+00 7.52920294e+00 - 7.55878925e+00 7.58959007e+00 7.62330008e+00 7.65929985e+00 - 7.69530010e+00 7.73129988e+00 7.76730013e+00 7.80329990e+00 - 7.83930016e+00 7.87529993e+00 7.91130018e+00 7.94729996e+00 - 7.98330021e+00 8.01930046e+00 8.05529976e+00 8.09130001e+00 - 8.12730026e+00 8.16329956e+00 8.19929981e+00 8.23530006e+00 - 8.27130032e+00 8.30729961e+00 8.34329987e+00 8.37930012e+00 - 8.41530037e+00 8.45129967e+00 8.48729992e+00 8.52330017e+00 - 8.55930042e+00 8.59529972e+00 8.63129997e+00 8.66730022e+00 - 8.70330048e+00 8.73929977e+00 8.77530003e+00 8.81130028e+00 - 8.84729958e+00 8.88329983e+00 8.91930008e+00 8.95530033e+00] - y_upper_bound: [ -5.57520008e+00 -5.53919983e+00 -5.50320005e+00 -5.46719980e+00 - -5.43120003e+00 -5.39519978e+00 -5.35920000e+00 -5.32320023e+00 - -5.28719997e+00 -5.25120020e+00 -5.21519995e+00 -5.17920017e+00 - -5.14319992e+00 -5.10720015e+00 -5.07119989e+00 -5.03520012e+00 - -4.99919987e+00 -4.96320009e+00 -4.92719984e+00 -4.89120007e+00 - -4.85519981e+00 -4.81920004e+00 -4.78319979e+00 -4.74720001e+00 - -4.71120024e+00 -4.67519999e+00 -4.63920021e+00 -4.60319996e+00 - -4.56720018e+00 -4.53119993e+00 -4.49520016e+00 -4.45919991e+00 - -4.42320013e+00 -4.38719988e+00 -4.35120010e+00 -4.31519985e+00 - -4.27920008e+00 -4.24319983e+00 -4.20948982e+00 -4.17868900e+00 - -4.14910269e+00 -4.12068319e+00 -4.09338379e+00 -4.06716108e+00 - -4.04197168e+00 -4.01777601e+00 -3.99453425e+00 -3.97220898e+00 - -3.95076370e+00 -3.93016410e+00 -3.91037679e+00 -3.89136934e+00 - -3.87311172e+00 -3.85557365e+00 -3.83872724e+00 -3.82254505e+00 - -3.80700088e+00 -3.79206967e+00 -3.77772713e+00 -3.76395011e+00 - -3.75044990e+00 -3.73694992e+00 -3.72344995e+00 -3.70994997e+00 - -3.69645000e+00 -3.68295002e+00 -3.66945004e+00 -3.65595007e+00 - -3.64245009e+00 -3.62895012e+00 -3.61544991e+00 -3.60194993e+00 - -3.58844995e+00 -3.57494998e+00 -3.56145000e+00 -3.54795003e+00 - -3.53445005e+00 -3.52095008e+00 -3.50745010e+00 -3.49394989e+00 - -3.48044991e+00 -3.46694994e+00 -3.45344996e+00 -3.43994999e+00 - -3.42645001e+00 -3.41295004e+00 -3.39945006e+00 -3.38595009e+00 - -3.37245011e+00 -3.35894990e+00 -3.34544992e+00 -3.33194995e+00 - -3.31844997e+00 -3.30495000e+00 -3.29145002e+00 -3.27795005e+00 - -3.26445007e+00 -3.25095010e+00 -3.23744988e+00 -3.22394991e+00 - -3.21044993e+00 -3.19694996e+00 -3.18344998e+00 -3.16995001e+00 - -3.15645003e+00 -3.14295006e+00 -3.12945008e+00 -3.11595011e+00 - -3.10244989e+00 -3.08894992e+00 -3.07544994e+00 -3.06194997e+00 - -3.04844999e+00 -3.03495002e+00 -3.02145004e+00 -3.00795007e+00 - -2.99445009e+00 -2.98095012e+00 -2.96744990e+00 -2.95394993e+00 - -2.94044995e+00 -2.92694998e+00 -2.91345000e+00 -2.89995003e+00 - -2.88645005e+00 -2.87295008e+00 -2.85945010e+00 -2.84594989e+00 - -2.83244991e+00 -2.81894994e+00 -2.80544996e+00 -2.79194999e+00 - -2.77845001e+00 -2.76495004e+00 -2.75145006e+00 -2.73795009e+00 - -2.72445011e+00 -2.71094990e+00 -2.69744992e+00 -2.68394995e+00 - -2.67044997e+00 -2.65695000e+00 -2.64345002e+00 -2.62995005e+00 - -2.61645007e+00 -2.60295010e+00 -2.58944988e+00 -2.57594991e+00 - -2.56244993e+00 -2.54894996e+00 -2.53544998e+00 -2.52195001e+00 - -2.50845003e+00 -2.49495006e+00 -2.48145008e+00 -2.46795011e+00 - -2.45444989e+00 -2.44094992e+00 -2.42744994e+00 -2.41394997e+00 - -2.40044999e+00 -2.38695002e+00 -2.37345004e+00 -2.35995007e+00 - -2.34645009e+00 -2.33295012e+00 -2.31944990e+00 -2.30594993e+00 - -2.29244995e+00 -2.27894998e+00 -2.26545000e+00 -2.25195003e+00 - -2.23845005e+00 -2.22495008e+00 -2.21145010e+00 -2.19794989e+00 - -2.18444991e+00 -2.17094994e+00 -2.15744996e+00 -2.14394999e+00 - -2.13045001e+00 -2.11695004e+00 -2.10345006e+00 -2.08995008e+00 - -2.07645011e+00 -2.06294990e+00 -2.04944992e+00 -2.03594995e+00 - -2.02244997e+00 -2.00895000e+00 -1.99545002e+00 -1.98195004e+00 - -1.96844995e+00 -1.95494998e+00 -1.94145000e+00 -1.92795002e+00 - -1.91445005e+00 -1.90094995e+00 -1.88744998e+00 -1.87395000e+00 - -1.86045003e+00 -1.84695005e+00 -1.83344996e+00 -1.81994998e+00 - -1.80645001e+00 -1.79295003e+00 -1.77945006e+00 -1.76594996e+00 - -1.75244999e+00 -1.73895001e+00 -1.72545004e+00 -1.71194994e+00 - -1.69844997e+00 -1.68494999e+00 -1.67145002e+00 -1.65795004e+00 - -1.64444995e+00 -1.63094997e+00 -1.61745000e+00 -1.60395002e+00 - -1.59045005e+00 -1.57694995e+00 -1.56344998e+00 -1.54995000e+00 - -1.53645003e+00 -1.52295005e+00 -1.50944996e+00 -1.49594998e+00 - -1.48245001e+00 -1.46895003e+00 -1.45545006e+00 -1.44194996e+00 - -1.42844999e+00 -1.41495001e+00 -1.40145004e+00 -1.38794994e+00 - -1.37444997e+00 -1.36094999e+00 -1.34745002e+00 -1.33395004e+00 - -1.32044995e+00 -1.30694997e+00 -1.29345000e+00 -1.27995002e+00 - -1.26645005e+00 -1.25294995e+00 -1.23944998e+00 -1.22595000e+00 - -1.21245003e+00 -1.19895005e+00 -1.18544996e+00 -1.17194998e+00 - -1.15845001e+00 -1.14495003e+00 -1.13145006e+00 -1.11794996e+00 - -1.10444999e+00 -1.09095001e+00 -1.07745004e+00 -1.06394994e+00 - -1.05044997e+00 -1.03694999e+00 -1.02345002e+00 -1.00995004e+00 - -9.96450007e-01 -9.82949972e-01 -9.69449997e-01 -9.55950022e-01 - -9.42449987e-01 -9.28950012e-01 -9.15449977e-01 -9.01950002e-01 - -8.88450027e-01 -8.74949992e-01 -8.61450016e-01 -8.47949982e-01 - -8.34450006e-01 -8.20949972e-01 -8.07449996e-01 -7.93950021e-01 - -7.80449986e-01 -7.66950011e-01 -7.53449976e-01 -7.39950001e-01 - -7.26450026e-01 -7.12949991e-01 -6.99450016e-01 -6.85949981e-01 - -6.72450006e-01 -6.58949971e-01 -6.45449996e-01 -6.31950021e-01 - -6.18449986e-01 -6.04950011e-01 -5.91449976e-01 -5.77950001e-01 - -5.64450026e-01 -5.50949991e-01 -5.37450016e-01 -5.23949981e-01 - -5.10450006e-01 -4.96950001e-01 -4.83449996e-01 -4.69949991e-01 - -4.56449986e-01 -4.42950010e-01 -4.29450005e-01 -4.15950000e-01 - -4.02449995e-01 -3.88949990e-01 -3.75449985e-01 -3.61950010e-01 - -3.48450005e-01 -3.34950000e-01 -3.21449995e-01 -3.07949990e-01 - -2.94450015e-01 -2.80950010e-01 -2.67450005e-01 -2.53950000e-01 - -2.40449995e-01 -2.26950005e-01 -2.13450000e-01 -1.99949995e-01 - -1.86450005e-01 -1.72950000e-01 -1.59449995e-01 -1.45950004e-01 - -1.32449999e-01 -1.18950002e-01 -1.05449997e-01 -9.19499993e-02 - -7.84500018e-02 -6.49499968e-02 -5.14499992e-02 -3.79500017e-02 - -2.44500004e-02 -1.09500000e-02 2.55000009e-03 1.60499997e-02 - 2.95499992e-02 4.30499986e-02 5.65499999e-02 7.00500011e-02 - 8.35499987e-02 9.70500037e-02 1.10550001e-01 1.24049999e-01 - 1.37549996e-01 1.51050001e-01 1.64550006e-01 1.78049996e-01 - 1.91550002e-01 2.05050007e-01 2.18549997e-01 2.32050002e-01 - 2.45550007e-01 2.59050012e-01 2.72549987e-01 2.86049992e-01 - 2.99549997e-01 3.13050002e-01 3.26550007e-01 3.40050012e-01 - 3.53549987e-01 3.67049992e-01 3.80549997e-01 3.94050002e-01 - 4.07550007e-01 4.21050012e-01 4.34549987e-01 4.48049992e-01 - 4.61549997e-01 4.75050002e-01 4.88550007e-01 5.02049983e-01 - 5.15550017e-01 5.29049993e-01 5.42550027e-01 5.56050003e-01 - 5.69549978e-01 5.83050013e-01 5.96549988e-01 6.10050023e-01 - 6.23549998e-01 6.37049973e-01 6.50550008e-01 6.64049983e-01 - 6.77550018e-01 6.91049993e-01 7.04550028e-01 7.18050003e-01 - 7.31549978e-01 7.45050013e-01 7.58549988e-01 7.72050023e-01 - 7.85549998e-01 7.99049973e-01 8.12550008e-01 8.26049984e-01 - 8.39550018e-01 8.53049994e-01 8.66550028e-01 8.80050004e-01 - 8.93549979e-01 9.07050014e-01 9.20549989e-01 9.34050024e-01 - 9.47549999e-01 9.61049974e-01 9.74550009e-01 9.88049984e-01 - 1.00154996e+00 1.01505005e+00 1.02855003e+00 1.04205000e+00 - 1.05554998e+00 1.06904995e+00 1.08255005e+00 1.09605002e+00 - 1.10955000e+00 1.12304997e+00 1.13654995e+00 1.15005004e+00 - 1.16355002e+00 1.17704999e+00 1.19054997e+00 1.20404994e+00 - 1.21755004e+00 1.23105001e+00 1.24454999e+00 1.25804996e+00 - 1.27155006e+00 1.28505003e+00 1.29855001e+00 1.31204998e+00 - 1.32554996e+00 1.33905005e+00 1.35255003e+00 1.36605000e+00 - 1.37954998e+00 1.39304996e+00 1.40655005e+00 1.42005002e+00 - 1.43355000e+00 1.44704998e+00 1.46054995e+00 1.47405005e+00 - 1.48755002e+00 1.50105000e+00 1.51454997e+00 1.52804995e+00 - 1.54155004e+00 1.55505002e+00 1.56854999e+00 1.58204997e+00 - 1.59554994e+00 1.60905004e+00 1.62255001e+00 1.63604999e+00 - 1.64954996e+00 1.66305006e+00 1.67655003e+00 1.69005001e+00 - 1.70354998e+00 1.71704996e+00 1.73055005e+00 1.74405003e+00 - 1.75755000e+00 1.77104998e+00 1.78454995e+00 1.79805005e+00 - 1.81155002e+00 1.82505000e+00 1.83854997e+00 1.85204995e+00 - 1.86555004e+00 1.87905002e+00 1.89254999e+00 1.90604997e+00 - 1.91954994e+00 1.93305004e+00 1.94655001e+00 1.96004999e+00 - 1.97354996e+00 1.98705006e+00 2.00055003e+00 2.01405001e+00 - 2.02754998e+00 2.04104996e+00 2.05454993e+00 2.06804991e+00 - 2.08154988e+00 2.09505010e+00 2.10855007e+00 2.12205005e+00 - 2.13555002e+00 2.14905000e+00 2.16254997e+00 2.17604995e+00 - 2.18954992e+00 2.20304990e+00 2.21655011e+00 2.23005009e+00 - 2.24355006e+00 2.25705004e+00 2.27055001e+00 2.28404999e+00 - 2.29754996e+00 2.31104994e+00 2.32454991e+00 2.33804989e+00 - 2.35155010e+00 2.36505008e+00 2.37855005e+00 2.39205003e+00 - 2.40555000e+00 2.41904998e+00 2.43254995e+00 2.44604993e+00 - 2.45954990e+00 2.47305012e+00 2.48655009e+00 2.50005007e+00 - 2.51355004e+00 2.52705002e+00 2.54054999e+00 2.55404997e+00 - 2.56754994e+00 2.58104992e+00 2.59454989e+00 2.60805011e+00 - 2.62155008e+00 2.63505006e+00 2.64855003e+00 2.66205001e+00 - 2.67554998e+00 2.68904996e+00 2.70254993e+00 2.71604991e+00 - 2.72954988e+00 2.74305010e+00 2.75655007e+00 2.77005005e+00 - 2.78355002e+00 2.79705000e+00 2.81054997e+00 2.82404995e+00 - 2.83754992e+00 2.85104990e+00 2.86455011e+00 2.87805009e+00 - 2.89155006e+00 2.90505004e+00 2.91855001e+00 2.93204999e+00 - 2.94554996e+00 2.95904994e+00 2.97254992e+00 2.98604989e+00 - 2.99955010e+00 3.01305008e+00 3.02655005e+00 3.04005003e+00 - 3.05355000e+00 3.06704998e+00 3.08054996e+00 3.09404993e+00 - 3.10754991e+00 3.12104988e+00 3.13455009e+00 3.14805007e+00 - 3.16155005e+00 3.17505002e+00 3.18855000e+00 3.20204997e+00 - 3.21554995e+00 3.22904992e+00 3.24254990e+00 3.25605011e+00 - 3.26955009e+00 3.28305006e+00 3.29655004e+00 3.31005001e+00 - 3.32354999e+00 3.33704996e+00 3.35054994e+00 3.36404991e+00 - 3.37754989e+00 3.39105010e+00 3.40455008e+00 3.41805005e+00 - 3.43155003e+00 3.44505000e+00 3.45854998e+00 3.47204995e+00 - 3.48554993e+00 3.49904990e+00 3.51255012e+00 3.52605009e+00 - 3.53955007e+00 3.55305004e+00 3.56655002e+00 3.58004999e+00 - 3.59354997e+00 3.60704994e+00 3.62054992e+00 3.63404989e+00 - 3.64755011e+00 3.66105008e+00 3.67455006e+00 3.68805003e+00 - 3.70155001e+00 3.71504998e+00 3.72854996e+00 3.74204993e+00 - 3.75554991e+00 3.76904988e+00 3.78255010e+00 3.79605007e+00 - 3.80955005e+00 3.82305002e+00 3.83655000e+00 3.85004997e+00 - 3.86354995e+00 3.87704992e+00 3.89054990e+00 3.90405011e+00 - 3.91755009e+00 3.93105006e+00 3.94455004e+00 3.95805001e+00 - 3.97154999e+00 3.98504996e+00 3.99854994e+00 4.01205015e+00 - 4.02554989e+00 4.03905010e+00 4.05254984e+00 4.06605005e+00 - 4.07954979e+00 4.09305000e+00 4.10655022e+00 4.12004995e+00 - 4.13355017e+00 4.14704990e+00 4.16055012e+00 4.17404985e+00 - 4.18755007e+00 4.20104980e+00 4.21455002e+00 4.22805023e+00 - 4.24154997e+00 4.25505018e+00 4.26854992e+00 4.28205013e+00 - 4.29554987e+00 4.30905008e+00 4.32254982e+00 4.33605003e+00 - 4.34954977e+00 4.36304998e+00 4.37655020e+00 4.39004993e+00 - 4.40355015e+00 4.41704988e+00 4.43055010e+00 4.44404984e+00 - 4.45755005e+00 4.47104979e+00 4.48455000e+00 4.49805021e+00 - 4.51154995e+00 4.52505016e+00 4.53854990e+00 4.55205011e+00 - 4.56554985e+00 4.57905006e+00 4.59254980e+00 4.60605001e+00 - 4.61955023e+00 4.63304996e+00 4.64655018e+00 4.66004992e+00 - 4.67355013e+00 4.68704987e+00 4.70055008e+00 4.71404982e+00 - 4.72755003e+00 4.74104977e+00 4.75454998e+00 4.76805019e+00 - 4.78154993e+00 4.79505014e+00 4.80854988e+00 4.82205009e+00 - 4.83554983e+00 4.84905005e+00 4.86254978e+00 4.87605000e+00 - 4.88955021e+00 4.90304995e+00 4.91655016e+00 4.93004990e+00 - 4.94355011e+00 4.95704985e+00 4.97055006e+00 4.98404980e+00 - 4.99755001e+00 5.01105022e+00 5.02454996e+00 5.03805017e+00 - 5.05154991e+00 5.06505013e+00 5.07854986e+00 5.09205008e+00 - 5.10554981e+00 5.11905003e+00 5.13254976e+00 5.14604998e+00 - 5.15955019e+00 5.17304993e+00 5.18655014e+00 5.20004988e+00 - 5.21355009e+00 5.22704983e+00 5.24055004e+00 5.25404978e+00 - 5.26754999e+00 5.28105021e+00 5.29454994e+00 5.30805016e+00 - 5.32154989e+00 5.33505011e+00 5.34854984e+00 5.36205006e+00 - 5.37554979e+00 5.38905001e+00 5.40255022e+00 5.41604996e+00 - 5.42955017e+00 5.44304991e+00 5.45655012e+00 5.47004986e+00 - 5.48355007e+00 5.49704981e+00 5.51055002e+00 5.52405024e+00 - 5.53754997e+00 5.55105019e+00 5.56454992e+00 5.57805014e+00 - 5.59154987e+00 5.60505009e+00 5.61854982e+00 5.63205004e+00 - 5.64554977e+00 5.65904999e+00 5.67255020e+00 5.68604994e+00 - 5.69955015e+00 5.71304989e+00 5.72655010e+00 5.74004984e+00 - 5.75355005e+00 5.76704979e+00 5.78055000e+00 5.79405022e+00 - 5.80754995e+00 5.82105017e+00 5.83454990e+00 5.84805012e+00 - 5.86154985e+00 5.87505007e+00 5.88854980e+00 5.90205002e+00 - 5.91555023e+00 5.92904997e+00 5.94255018e+00 5.95604992e+00 - 5.96955013e+00 5.98304987e+00 5.99655008e+00 6.01004982e+00 - 6.02355003e+00 6.03704977e+00 6.05054998e+00 6.06405020e+00 - 6.07754993e+00 6.09105015e+00 6.10454988e+00 6.11805010e+00 - 6.13154984e+00 6.14505005e+00 6.15854979e+00 6.17205000e+00 - 6.18555021e+00 6.19904995e+00 6.21255016e+00 6.22604990e+00 - 6.23955011e+00 6.25304985e+00 6.26655006e+00 6.28004980e+00 - 6.29355001e+00 6.30705023e+00 6.32054996e+00 6.33405018e+00 - 6.34754992e+00 6.36105013e+00 6.37454987e+00 6.38805008e+00 - 6.40154982e+00 6.41505003e+00 6.42854977e+00 6.44204998e+00 - 6.45555019e+00 6.46904993e+00 6.48255014e+00 6.49604988e+00 - 6.50955009e+00 6.52304983e+00 6.53655005e+00 6.55004978e+00 - 6.56355000e+00 6.57705021e+00 6.59054995e+00 6.60405016e+00 - 6.61754990e+00 6.63105011e+00 6.64454985e+00 6.65805006e+00 - 6.67154980e+00 6.68505001e+00 6.69855022e+00 6.71204996e+00 - 6.72555017e+00 6.73904991e+00 6.75255013e+00 6.76604986e+00 - 6.77955008e+00 6.79304981e+00 6.80655003e+00 6.82004976e+00 - 6.83354998e+00 6.84705019e+00 6.86054993e+00 6.87405014e+00 - 6.88754988e+00 6.90105009e+00 6.91454983e+00 6.92805004e+00 - 6.94154978e+00 6.95504999e+00 6.96855021e+00 6.98204994e+00 - 6.99555016e+00 7.00904989e+00 7.02255011e+00 7.03604984e+00 - 7.04955006e+00 7.06304979e+00 7.07655001e+00 7.09005022e+00 - 7.10354996e+00 7.11705017e+00 7.13054991e+00 7.14405012e+00 - 7.15782690e+00 7.17216969e+00 7.18710089e+00 7.20264530e+00 - 7.21882725e+00 7.23567390e+00 7.25321150e+00 7.27146959e+00 - 7.29047680e+00 7.31026411e+00 7.33086348e+00 7.35230875e+00 - 7.37463427e+00 7.39787626e+00 7.42207193e+00 7.44726086e+00 - 7.47348356e+00 7.50078297e+00 7.52920294e+00 7.55878925e+00 - 7.58959007e+00 7.62330008e+00 7.65929985e+00 7.69530010e+00 - 7.73129988e+00 7.76730013e+00 7.80329990e+00 7.83930016e+00 - 7.87529993e+00 7.91130018e+00 7.94729996e+00 7.98330021e+00 - 8.01930046e+00 8.05529976e+00 8.09130001e+00 8.12730026e+00 - 8.16329956e+00 8.19929981e+00 8.23530006e+00 8.27130032e+00 - 8.30729961e+00 8.34329987e+00 8.37930012e+00 8.41530037e+00 - 8.45129967e+00 8.48729992e+00 8.52330017e+00 8.55930042e+00 - 8.59529972e+00 8.63129997e+00 8.66730022e+00 8.70330048e+00 - 8.73929977e+00 8.77530003e+00 8.81130028e+00 8.84729958e+00 - 8.88329983e+00 8.91930008e+00 8.95530033e+00 8.99129963e+00] + data: [[100070. 100070. 100070. ... 101057. 101063. 101063.] + [100069. 100068. 100068. ... 101061. 101065. 101066.] + [100068. 100068. 100067. ... 101062. 101068. 101068.] + ... + [102203. 102211. 102219. ... 101783. 101757. 101752.] + [102210. 102218. 102225. ... 101783. 101763. 101756.] + [102216. 102224. 102232. ... 101793. 101770. 101761.]] + x: [353.0525 353.0885 353.1245 353.1605 353.1965 353.2325 353.2685 + 353.3045 353.3405 353.3765 353.4125 353.4485 353.4845 353.5205 + 353.5565 353.5925 353.6285 353.6645 353.7005 353.7365 353.7725 + 353.8085 353.8445 353.8805 353.9165 353.9525 353.9885 354.0245 + 354.0605 354.0965 354.1325 354.1685 354.2045 354.2405 354.2765 + 354.3125 354.3485 354.3845 354.4205 354.4565 354.4925 354.52185 + 354.5501 354.57736 354.60364 354.62894 354.65332 354.67685 354.6995 + 354.7213 354.74234 354.76263 354.78217 354.801 354.81915 354.83664 + 354.8535 354.86972 354.88538 354.90045 354.91498 354.929 354.9425 + 354.956 354.9695 354.983 354.9965 355.01 355.0235 355.037 + 355.0505 355.064 355.0775 355.091 355.1045 355.118 355.1315 + 355.145 355.1585 355.172 355.1855 355.199 355.2125 355.226 + 355.2395 355.253 355.2665 355.28 355.2935 355.307 355.3205 + 355.334 355.3475 355.361 355.3745 355.388 355.4015 355.415 + 355.4285 355.442 355.4555 355.469 355.4825 355.496 355.5095 + 355.523 355.5365 355.55 355.5635 355.577 355.5905 355.604 + 355.6175 355.631 355.6445 355.658 355.6715 355.685 355.6985 + 355.712 355.7255 355.739 355.7525 355.766 355.7795 355.793 + 355.8065 355.82 355.8335 355.847 355.8605 355.874 355.8875 + 355.901 355.9145 355.928 355.9415 355.955 355.9685 355.982 + 355.9955 356.009 356.0225 356.036 356.0495 356.063 356.0765 + 356.09 356.1035 356.117 356.1305 356.144 356.1575 356.171 + 356.1845 356.198 356.2115 356.225 356.2385 356.252 356.2655 + 356.279 356.2925 356.306 356.3195 356.333 356.3465 356.36 + 356.3735 356.387 356.4005 356.414 356.4275 356.441 356.4545 + 356.468 356.4815 356.495 356.5085 356.522 356.5355 356.549 + 356.5625 356.576 356.5895 356.603 356.6165 356.63 356.6435 + 356.657 356.6705 356.684 356.6975 356.711 356.7245 356.738 + 356.7515 356.765 356.7785 356.792 356.8055 356.819 356.8325 + 356.846 356.8595 356.873 356.8865 356.9 356.9135 356.927 + 356.9405 356.954 356.9675 356.981 356.9945 357.008 357.0215 + 357.035 357.0485 357.062 357.0755 357.089 357.1025 357.116 + 357.1295 357.143 357.1565 357.17 357.1835 357.197 357.2105 + 357.224 357.2375 357.251 357.2645 357.278 357.2915 357.305 + 357.3185 357.332 357.3455 357.359 357.3725 357.386 357.3995 + 357.413 357.4265 357.44 357.4535 357.467 357.4805 357.494 + 357.5075 357.521 357.5345 357.548 357.5615 357.575 357.5885 + 357.602 357.6155 357.629 357.6425 357.656 357.6695 357.683 + 357.6965 357.71 357.7235 357.737 357.7505 357.764 357.7775 + 357.791 357.8045 357.818 357.8315 357.845 357.8585 357.872 + 357.8855 357.899 357.9125 357.926 357.9395 357.953 357.9665 + 357.98 357.9935 358.007 358.0205 358.034 358.0475 358.061 + 358.0745 358.088 358.1015 358.115 358.1285 358.142 358.1555 + 358.169 358.1825 358.196 358.2095 358.223 358.2365 358.25 + 358.2635 358.277 358.2905 358.304 358.3175 358.331 358.3445 + 358.358 358.3715 358.385 358.3985 358.412 358.4255 358.439 + 358.4525 358.466 358.4795 358.493 358.5065 358.52 358.5335 + 358.547 358.5605 358.574 358.5875 358.601 358.6145 358.628 + 358.6415 358.655 358.6685 358.682 358.6955 358.709 358.7225 + 358.736 358.7495 358.763 358.7765 358.79 358.8035 358.817 + 358.8305 358.844 358.8575 358.871 358.8845 358.898 358.9115 + 358.925 358.9385 358.952 358.9655 358.979 358.9925 359.006 + 359.0195 359.033 359.0465 359.06 359.0735 359.087 359.1005 + 359.114 359.1275 359.141 359.1545 359.168 359.1815 359.195 + 359.2085 359.222 359.2355 359.249 359.2625 359.276 359.2895 + 359.303 359.3165 359.33 359.3435 359.357 359.3705 359.384 + 359.3975 359.411 359.4245 359.438 359.4515 359.465 359.4785 + 359.492 359.5055 359.519 359.5325 359.546 359.5595 359.573 + 359.5865 359.6 359.6135 359.627 359.6405 359.654 359.6675 + 359.681 359.6945 359.708 359.7215 359.735 359.7485 359.762 + 359.7755 359.789 359.8025 359.816 359.8295 359.843 359.8565 + 359.87 359.8835 359.897 359.9105 359.924 359.9375 359.951 + 359.9645 359.978 359.9915 360.005 360.0185 360.032 360.0455 + 360.059 360.0725 360.086 360.0995 360.113 360.1265 360.14 + 360.1535 360.167 360.1805 360.194 360.2075 360.221 360.2345 + 360.248 360.2615 360.275 360.2885 360.302 360.3155 360.329 + 360.3425 360.356 360.3695 360.383 360.3965 360.41 360.4235 + 360.437 360.4505 360.464 360.4775 360.491 360.5045 360.518 + 360.5315 360.545 360.5585 360.572 360.5855 360.599 360.6125 + 360.626 360.6395 360.653 360.6665 360.68 360.6935 360.707 + 360.7205 360.734 360.7475 360.761 360.7745 360.788 360.8015 + 360.815 360.8285 360.842 360.8555 360.869 360.8825 360.896 + 360.9095 360.923 360.9365 360.95 360.9635 360.977 360.9905 + 361.004 361.0175 361.031 361.0445 361.058 361.0715 361.085 + 361.0985 361.112 361.1255 361.139 361.1525 361.166 361.1795 + 361.193 361.2065 361.22 361.2335 361.247 361.2605 361.274 + 361.2875 361.301 361.3145 361.328 361.3415 361.355 361.3685 + 361.382 361.3955 361.409 361.4225 361.436 361.4495 361.463 + 361.4765 361.49 361.5035 361.517 361.5305 361.544 361.5575 + 361.571 361.5845 361.598 361.6115 361.625 361.6385 361.652 + 361.6655 361.679 361.6925 361.706 361.7195 361.733 361.7465 + 361.76 361.7735 361.787 361.8005 361.814 361.8275 361.841 + 361.8545 361.868 361.8815 361.895 361.9085 361.922 361.9355 + 361.949 361.9625 361.976 361.9895 362.003 362.0165 362.03 + 362.0435 362.057 362.0705 362.084 362.0975 362.111 362.1245 + 362.138 362.1515 362.165 362.1785 362.192 362.2055 362.219 + 362.2325 362.246 362.2595 362.273 362.2865 362.3 362.3135 + 362.327 362.3405 362.354 362.3675 362.381 362.3945 362.408 + 362.4215 362.435 362.4485 362.462 362.4755 362.489 362.5025 + 362.516 362.5295 362.543 362.5565 362.57 362.5835 362.597 + 362.6105 362.624 362.6375 362.651 362.6645 362.678 362.6915 + 362.705 362.7185 362.732 362.7455 362.759 362.7725 362.786 + 362.7995 362.813 362.8265 362.84 362.8535 362.867 362.8805 + 362.894 362.9075 362.921 362.9345 362.948 362.9615 362.975 + 362.9885 363.002 363.0155 363.029 363.0425 363.056 363.0695 + 363.083 363.0965 363.11 363.1235 363.137 363.1505 363.164 + 363.1775 363.191 363.2045 363.218 363.2315 363.245 363.2585 + 363.272 363.2855 363.299 363.3125 363.3265 363.34103 363.35614 + 363.37177 363.38803 363.40488 363.42236 363.4405 363.45932 363.47888 + 363.49915 363.52017 363.54202 363.56467 363.58817 363.61255 363.63788 + 363.66412 363.69138 363.71967 363.749 363.785 363.821 363.857 + 363.893 363.929 363.965 364.001 364.037 364.073 364.109 + 364.145 364.181 364.217 364.253 364.289 364.325 364.361 + 364.397 364.433 364.469 364.505 364.541 364.577 364.613 + 364.649 364.685 364.721 364.757 364.793 364.829 364.865 + 364.901 364.937 364.973 365.009 365.045 365.081 365.117 + 365.153 365.189 ] + x_lower_bound: [353.0345 353.0705 353.1065 353.1425 353.1785 353.2145 353.2505 + 353.2865 353.3225 353.3585 353.3945 353.4305 353.4665 353.5025 + 353.5385 353.5745 353.6105 353.6465 353.6825 353.7185 353.7545 + 353.7905 353.8265 353.8625 353.8985 353.9345 353.9705 354.0065 + 354.0425 354.0785 354.1145 354.1505 354.1865 354.2225 354.2585 + 354.2945 354.3305 354.3665 354.4025 354.4385 354.4745 354.50717 + 354.53598 354.56375 354.5905 354.61627 354.64114 354.66507 354.68817 + 354.7104 354.73184 354.7525 354.7724 354.7916 354.81006 354.82788 + 354.84506 354.8616 354.87753 354.8929 354.9077 354.922 354.93576 + 354.94925 354.96274 354.97626 354.98975 355.00323 355.01675 355.03024 + 355.04376 355.05725 355.07074 355.08426 355.09775 355.11124 355.12476 + 355.13824 355.15176 355.16525 355.17874 355.19226 355.20575 355.21924 + 355.23276 355.24625 355.25974 355.27325 355.28674 355.30026 355.31375 + 355.32724 355.34076 355.35425 355.36774 355.38126 355.39474 355.40826 + 355.42175 355.43524 355.44876 355.46225 355.47574 355.48926 355.50275 + 355.51624 355.52975 355.54324 355.55676 355.57025 355.58374 355.59726 + 355.61075 355.62424 355.63776 355.65125 355.66476 355.67825 355.69174 + 355.70526 355.71875 355.73224 355.74576 355.75925 355.77274 355.78625 + 355.79974 355.81326 355.82675 355.84024 355.85376 355.86725 355.88074 + 355.89426 355.90775 355.92126 355.93475 355.94824 355.96176 355.97525 + 355.98874 356.00226 356.01575 356.02924 356.04276 356.05624 356.06976 + 356.08325 356.09674 356.11026 356.12375 356.13724 356.15076 356.16425 + 356.17776 356.19125 356.20474 356.21826 356.23175 356.24524 356.25876 + 356.27225 356.28574 356.29926 356.31274 356.32626 356.33975 356.35324 + 356.36676 356.38025 356.39374 356.40726 356.42075 356.43427 356.44775 + 356.46124 356.47476 356.48825 356.50174 356.51526 356.52875 356.54224 + 356.55576 356.56924 356.58276 356.59625 356.60974 356.62326 356.63675 + 356.65024 356.66376 356.67725 356.69073 356.70425 356.71774 356.73126 + 356.74475 356.75824 356.77176 356.78525 356.79874 356.81226 356.82574 + 356.83926 356.85275 356.86624 356.87976 356.89325 356.90674 356.92026 + 356.93375 356.94724 356.96075 356.97424 356.98776 357.00125 357.01474 + 357.02826 357.04175 357.05524 357.06876 357.08224 357.09576 357.10925 + 357.12274 357.13626 357.14975 357.16324 357.17676 357.19025 357.20374 + 357.21725 357.23074 357.24426 357.25775 357.27124 357.28476 357.29825 + 357.31174 357.32526 357.33875 357.35226 357.36575 357.37924 357.39276 + 357.40625 357.41974 357.43326 357.44675 357.46024 357.47375 357.48724 + 357.50076 357.51425 357.52774 357.54126 357.55475 357.56824 357.58176 + 357.59525 357.60876 357.62225 357.63574 357.64926 357.66275 357.67624 + 357.68976 357.70325 357.71674 357.73026 357.74374 357.75726 357.77075 + 357.78424 357.79776 357.81125 357.82474 357.83826 357.85175 357.86526 + 357.87875 357.89224 357.90576 357.91925 357.93274 357.94626 357.95975 + 357.97324 357.98676 358.00024 358.01376 358.02725 358.04074 358.05426 + 358.06775 358.08124 358.09476 358.10825 358.12177 358.13525 358.14874 + 358.16226 358.17575 358.18924 358.20276 358.21625 358.22974 358.24326 + 358.25674 358.27026 358.28375 358.29724 358.31076 358.32425 358.33774 + 358.35126 358.36475 358.37823 358.39175 358.40524 358.41876 358.43225 + 358.44574 358.45926 358.47275 358.48624 358.49976 358.51324 358.52676 + 358.54025 358.55374 358.56726 358.58075 358.59424 358.60776 358.62125 + 358.63474 358.64825 358.66174 358.67526 358.68875 358.70224 358.71576 + 358.72925 358.74274 358.75626 358.76974 358.78326 358.79675 358.81024 + 358.82376 358.83725 358.85074 358.86426 358.87775 358.89124 358.90475 + 358.91824 358.93176 358.94525 358.95874 358.97226 358.98575 358.99924 + 359.01276 359.02625 359.03976 359.05325 359.06674 359.08026 359.09375 + 359.10724 359.12076 359.13425 359.14774 359.16125 359.17474 359.18826 + 359.20175 359.21524 359.22876 359.24225 359.25574 359.26926 359.28275 + 359.29626 359.30975 359.32324 359.33676 359.35025 359.36374 359.37726 + 359.39075 359.40424 359.41776 359.43124 359.44476 359.45825 359.47174 + 359.48526 359.49875 359.51224 359.52576 359.53925 359.55276 359.56625 + 359.57974 359.59326 359.60675 359.62024 359.63376 359.64725 359.66074 + 359.67426 359.68774 359.70126 359.71475 359.72824 359.74176 359.75525 + 359.76874 359.78226 359.79575 359.80927 359.82275 359.83624 359.84976 + 359.86325 359.87674 359.89026 359.90375 359.91724 359.93076 359.94424 + 359.95776 359.97125 359.98474 359.99826 360.01175 360.02524 360.03876 + 360.05225 360.06573 360.07925 360.09274 360.10626 360.11975 360.13324 + 360.14676 360.16025 360.17374 360.18726 360.20074 360.21426 360.22775 + 360.24124 360.25476 360.26825 360.28174 360.29526 360.30875 360.32224 + 360.33575 360.34924 360.36276 360.37625 360.38974 360.40326 360.41675 + 360.43024 360.44376 360.45724 360.47076 360.48425 360.49774 360.51126 + 360.52475 360.53824 360.55176 360.56525 360.57874 360.59225 360.60574 + 360.61926 360.63275 360.64624 360.65976 360.67325 360.68674 360.70026 + 360.71375 360.72726 360.74075 360.75424 360.76776 360.78125 360.79474 + 360.80826 360.82175 360.83524 360.84875 360.86224 360.87576 360.88925 + 360.90274 360.91626 360.92975 360.94324 360.95676 360.97025 360.98376 + 360.99725 361.01074 361.02426 361.03775 361.05124 361.06476 361.07825 + 361.09174 361.10526 361.11874 361.13226 361.14575 361.15924 361.17276 + 361.18625 361.19974 361.21326 361.22675 361.24026 361.25375 361.26724 + 361.28076 361.29425 361.30774 361.32126 361.33475 361.34824 361.36176 + 361.37524 361.38876 361.40225 361.41574 361.42926 361.44275 361.45624 + 361.46976 361.48325 361.49677 361.51025 361.52374 361.53726 361.55075 + 361.56424 361.57776 361.59125 361.60474 361.61826 361.63174 361.64526 + 361.65875 361.67224 361.68576 361.69925 361.71274 361.72626 361.73975 + 361.75323 361.76675 361.78024 361.79376 361.80725 361.82074 361.83426 + 361.84775 361.86124 361.87476 361.88824 361.90176 361.91525 361.92874 + 361.94226 361.95575 361.96924 361.98276 361.99625 362.00974 362.02325 + 362.03674 362.05026 362.06375 362.07724 362.09076 362.10425 362.11774 + 362.13126 362.14474 362.15826 362.17175 362.18524 362.19876 362.21225 + 362.22574 362.23926 362.25275 362.26624 362.27975 362.29324 362.30676 + 362.32025 362.33374 362.34726 362.36075 362.37424 362.38776 362.40125 + 362.41476 362.42825 362.44174 362.45526 362.46875 362.48224 362.49576 + 362.50925 362.52274 362.53625 362.54974 362.56326 362.57675 362.59024 + 362.60376 362.61725 362.63074 362.64426 362.65775 362.67126 362.68475 + 362.69824 362.71176 362.72525 362.73874 362.75226 362.76575 362.77924 + 362.79276 362.80624 362.81976 362.83325 362.84674 362.86026 362.87375 + 362.88724 362.90076 362.91425 362.92776 362.94125 362.95474 362.96826 + 362.98175 362.99524 363.00876 363.02225 363.03574 363.04926 363.06274 + 363.07626 363.08975 363.10324 363.11676 363.13025 363.14374 363.15726 + 363.17075 363.18427 363.19775 363.21124 363.22476 363.23825 363.25174 + 363.26526 363.27875 363.29224 363.30576 363.31952 363.33377 363.34857 + 363.36395 363.3799 363.39645 363.4136 363.43143 363.44992 363.46912 + 363.489 363.50967 363.5311 363.55334 363.57642 363.60037 363.6252 + 363.651 363.67776 363.7055 363.7343 363.767 363.803 363.839 + 363.875 363.911 363.947 363.983 364.019 364.055 364.091 + 364.127 364.163 364.199 364.235 364.271 364.307 364.343 + 364.379 364.415 364.451 364.487 364.523 364.559 364.595 + 364.631 364.667 364.703 364.739 364.775 364.811 364.847 + 364.883 364.919 364.955 364.991 365.027 365.063 365.099 + 365.135 365.171 ] + x_upper_bound: [353.0705 353.1065 353.1425 353.1785 353.2145 353.2505 353.2865 + 353.3225 353.3585 353.3945 353.4305 353.4665 353.5025 353.5385 + 353.5745 353.6105 353.6465 353.6825 353.7185 353.7545 353.7905 + 353.8265 353.8625 353.8985 353.9345 353.9705 354.0065 354.0425 + 354.0785 354.1145 354.1505 354.1865 354.2225 354.2585 354.2945 + 354.3305 354.3665 354.4025 354.4385 354.4745 354.50717 354.53598 + 354.56375 354.5905 354.61627 354.64114 354.66507 354.68817 354.7104 + 354.73184 354.7525 354.7724 354.7916 354.81006 354.82788 354.84506 + 354.8616 354.87753 354.8929 354.9077 354.922 354.93576 354.94925 + 354.96274 354.97626 354.98975 355.00323 355.01675 355.03024 355.04376 + 355.05725 355.07074 355.08426 355.09775 355.11124 355.12476 355.13824 + 355.15176 355.16525 355.17874 355.19226 355.20575 355.21924 355.23276 + 355.24625 355.25974 355.27325 355.28674 355.30026 355.31375 355.32724 + 355.34076 355.35425 355.36774 355.38126 355.39474 355.40826 355.42175 + 355.43524 355.44876 355.46225 355.47574 355.48926 355.50275 355.51624 + 355.52975 355.54324 355.55676 355.57025 355.58374 355.59726 355.61075 + 355.62424 355.63776 355.65125 355.66476 355.67825 355.69174 355.70526 + 355.71875 355.73224 355.74576 355.75925 355.77274 355.78625 355.79974 + 355.81326 355.82675 355.84024 355.85376 355.86725 355.88074 355.89426 + 355.90775 355.92126 355.93475 355.94824 355.96176 355.97525 355.98874 + 356.00226 356.01575 356.02924 356.04276 356.05624 356.06976 356.08325 + 356.09674 356.11026 356.12375 356.13724 356.15076 356.16425 356.17776 + 356.19125 356.20474 356.21826 356.23175 356.24524 356.25876 356.27225 + 356.28574 356.29926 356.31274 356.32626 356.33975 356.35324 356.36676 + 356.38025 356.39374 356.40726 356.42075 356.43427 356.44775 356.46124 + 356.47476 356.48825 356.50174 356.51526 356.52875 356.54224 356.55576 + 356.56924 356.58276 356.59625 356.60974 356.62326 356.63675 356.65024 + 356.66376 356.67725 356.69073 356.70425 356.71774 356.73126 356.74475 + 356.75824 356.77176 356.78525 356.79874 356.81226 356.82574 356.83926 + 356.85275 356.86624 356.87976 356.89325 356.90674 356.92026 356.93375 + 356.94724 356.96075 356.97424 356.98776 357.00125 357.01474 357.02826 + 357.04175 357.05524 357.06876 357.08224 357.09576 357.10925 357.12274 + 357.13626 357.14975 357.16324 357.17676 357.19025 357.20374 357.21725 + 357.23074 357.24426 357.25775 357.27124 357.28476 357.29825 357.31174 + 357.32526 357.33875 357.35226 357.36575 357.37924 357.39276 357.40625 + 357.41974 357.43326 357.44675 357.46024 357.47375 357.48724 357.50076 + 357.51425 357.52774 357.54126 357.55475 357.56824 357.58176 357.59525 + 357.60876 357.62225 357.63574 357.64926 357.66275 357.67624 357.68976 + 357.70325 357.71674 357.73026 357.74374 357.75726 357.77075 357.78424 + 357.79776 357.81125 357.82474 357.83826 357.85175 357.86526 357.87875 + 357.89224 357.90576 357.91925 357.93274 357.94626 357.95975 357.97324 + 357.98676 358.00024 358.01376 358.02725 358.04074 358.05426 358.06775 + 358.08124 358.09476 358.10825 358.12177 358.13525 358.14874 358.16226 + 358.17575 358.18924 358.20276 358.21625 358.22974 358.24326 358.25674 + 358.27026 358.28375 358.29724 358.31076 358.32425 358.33774 358.35126 + 358.36475 358.37823 358.39175 358.40524 358.41876 358.43225 358.44574 + 358.45926 358.47275 358.48624 358.49976 358.51324 358.52676 358.54025 + 358.55374 358.56726 358.58075 358.59424 358.60776 358.62125 358.63474 + 358.64825 358.66174 358.67526 358.68875 358.70224 358.71576 358.72925 + 358.74274 358.75626 358.76974 358.78326 358.79675 358.81024 358.82376 + 358.83725 358.85074 358.86426 358.87775 358.89124 358.90475 358.91824 + 358.93176 358.94525 358.95874 358.97226 358.98575 358.99924 359.01276 + 359.02625 359.03976 359.05325 359.06674 359.08026 359.09375 359.10724 + 359.12076 359.13425 359.14774 359.16125 359.17474 359.18826 359.20175 + 359.21524 359.22876 359.24225 359.25574 359.26926 359.28275 359.29626 + 359.30975 359.32324 359.33676 359.35025 359.36374 359.37726 359.39075 + 359.40424 359.41776 359.43124 359.44476 359.45825 359.47174 359.48526 + 359.49875 359.51224 359.52576 359.53925 359.55276 359.56625 359.57974 + 359.59326 359.60675 359.62024 359.63376 359.64725 359.66074 359.67426 + 359.68774 359.70126 359.71475 359.72824 359.74176 359.75525 359.76874 + 359.78226 359.79575 359.80927 359.82275 359.83624 359.84976 359.86325 + 359.87674 359.89026 359.90375 359.91724 359.93076 359.94424 359.95776 + 359.97125 359.98474 359.99826 360.01175 360.02524 360.03876 360.05225 + 360.06573 360.07925 360.09274 360.10626 360.11975 360.13324 360.14676 + 360.16025 360.17374 360.18726 360.20074 360.21426 360.22775 360.24124 + 360.25476 360.26825 360.28174 360.29526 360.30875 360.32224 360.33575 + 360.34924 360.36276 360.37625 360.38974 360.40326 360.41675 360.43024 + 360.44376 360.45724 360.47076 360.48425 360.49774 360.51126 360.52475 + 360.53824 360.55176 360.56525 360.57874 360.59225 360.60574 360.61926 + 360.63275 360.64624 360.65976 360.67325 360.68674 360.70026 360.71375 + 360.72726 360.74075 360.75424 360.76776 360.78125 360.79474 360.80826 + 360.82175 360.83524 360.84875 360.86224 360.87576 360.88925 360.90274 + 360.91626 360.92975 360.94324 360.95676 360.97025 360.98376 360.99725 + 361.01074 361.02426 361.03775 361.05124 361.06476 361.07825 361.09174 + 361.10526 361.11874 361.13226 361.14575 361.15924 361.17276 361.18625 + 361.19974 361.21326 361.22675 361.24026 361.25375 361.26724 361.28076 + 361.29425 361.30774 361.32126 361.33475 361.34824 361.36176 361.37524 + 361.38876 361.40225 361.41574 361.42926 361.44275 361.45624 361.46976 + 361.48325 361.49677 361.51025 361.52374 361.53726 361.55075 361.56424 + 361.57776 361.59125 361.60474 361.61826 361.63174 361.64526 361.65875 + 361.67224 361.68576 361.69925 361.71274 361.72626 361.73975 361.75323 + 361.76675 361.78024 361.79376 361.80725 361.82074 361.83426 361.84775 + 361.86124 361.87476 361.88824 361.90176 361.91525 361.92874 361.94226 + 361.95575 361.96924 361.98276 361.99625 362.00974 362.02325 362.03674 + 362.05026 362.06375 362.07724 362.09076 362.10425 362.11774 362.13126 + 362.14474 362.15826 362.17175 362.18524 362.19876 362.21225 362.22574 + 362.23926 362.25275 362.26624 362.27975 362.29324 362.30676 362.32025 + 362.33374 362.34726 362.36075 362.37424 362.38776 362.40125 362.41476 + 362.42825 362.44174 362.45526 362.46875 362.48224 362.49576 362.50925 + 362.52274 362.53625 362.54974 362.56326 362.57675 362.59024 362.60376 + 362.61725 362.63074 362.64426 362.65775 362.67126 362.68475 362.69824 + 362.71176 362.72525 362.73874 362.75226 362.76575 362.77924 362.79276 + 362.80624 362.81976 362.83325 362.84674 362.86026 362.87375 362.88724 + 362.90076 362.91425 362.92776 362.94125 362.95474 362.96826 362.98175 + 362.99524 363.00876 363.02225 363.03574 363.04926 363.06274 363.07626 + 363.08975 363.10324 363.11676 363.13025 363.14374 363.15726 363.17075 + 363.18427 363.19775 363.21124 363.22476 363.23825 363.25174 363.26526 + 363.27875 363.29224 363.30576 363.31952 363.33377 363.34857 363.36395 + 363.3799 363.39645 363.4136 363.43143 363.44992 363.46912 363.489 + 363.50967 363.5311 363.55334 363.57642 363.60037 363.6252 363.651 + 363.67776 363.7055 363.7343 363.767 363.803 363.839 363.875 + 363.911 363.947 363.983 364.019 364.055 364.091 364.127 + 364.163 364.199 364.235 364.271 364.307 364.343 364.379 + 364.415 364.451 364.487 364.523 364.559 364.595 364.631 + 364.667 364.703 364.739 364.775 364.811 364.847 364.883 + 364.919 364.955 364.991 365.027 365.063 365.099 365.135 + 365.171 365.207 ] + y: [-5.5932002e+00 -5.5572000e+00 -5.5212002e+00 -5.4851999e+00 + -5.4492002e+00 -5.4131999e+00 -5.3772001e+00 -5.3411999e+00 + -5.3052001e+00 -5.2691998e+00 -5.2332001e+00 -5.1971998e+00 + -5.1612000e+00 -5.1251998e+00 -5.0892000e+00 -5.0531998e+00 + -5.0172000e+00 -4.9812002e+00 -4.9452000e+00 -4.9092002e+00 + -4.8731999e+00 -4.8372002e+00 -4.8011999e+00 -4.7652001e+00 + -4.7291999e+00 -4.6932001e+00 -4.6571999e+00 -4.6212001e+00 + -4.5851998e+00 -4.5492001e+00 -4.5131998e+00 -4.4772000e+00 + -4.4411998e+00 -4.4052000e+00 -4.3692002e+00 -4.3332000e+00 + -4.2972002e+00 -4.2612000e+00 -4.2252002e+00 -4.1937799e+00 + -4.1635985e+00 -4.1346073e+00 -4.1067591e+00 -4.0800085e+00 + -4.0543132e+00 -4.0296307e+00 -4.0059214e+00 -3.9831471e+00 + -3.9612706e+00 -3.9402568e+00 -3.9200714e+00 -3.9006820e+00 + -3.8820570e+00 -3.8641663e+00 -3.8469810e+00 -3.8304734e+00 + -3.8146167e+00 -3.7993851e+00 -3.7847540e+00 -3.7707000e+00 + -3.7572000e+00 -3.7437000e+00 -3.7302001e+00 -3.7167001e+00 + -3.7032001e+00 -3.6896999e+00 -3.6761999e+00 -3.6626999e+00 + -3.6492000e+00 -3.6357000e+00 -3.6222000e+00 -3.6087000e+00 + -3.5952001e+00 -3.5817001e+00 -3.5682001e+00 -3.5546999e+00 + -3.5411999e+00 -3.5276999e+00 -3.5142000e+00 -3.5007000e+00 + -3.4872000e+00 -3.4737000e+00 -3.4602001e+00 -3.4467001e+00 + -3.4331999e+00 -3.4196999e+00 -3.4061999e+00 -3.3927000e+00 + -3.3792000e+00 -3.3657000e+00 -3.3522000e+00 -3.3387001e+00 + -3.3252001e+00 -3.3117001e+00 -3.2981999e+00 -3.2846999e+00 + -3.2711999e+00 -3.2577000e+00 -3.2442000e+00 -3.2307000e+00 + -3.2172000e+00 -3.2037001e+00 -3.1902001e+00 -3.1767001e+00 + -3.1631999e+00 -3.1496999e+00 -3.1362000e+00 -3.1227000e+00 + -3.1092000e+00 -3.0957000e+00 -3.0822001e+00 -3.0687001e+00 + -3.0552001e+00 -3.0416999e+00 -3.0281999e+00 -3.0146999e+00 + -3.0012000e+00 -2.9877000e+00 -2.9742000e+00 -2.9607000e+00 + -2.9472001e+00 -2.9337001e+00 -2.9202001e+00 -2.9066999e+00 + -2.8931999e+00 -2.8796999e+00 -2.8662000e+00 -2.8527000e+00 + -2.8392000e+00 -2.8257000e+00 -2.8122001e+00 -2.7987001e+00 + -2.7852001e+00 -2.7716999e+00 -2.7581999e+00 -2.7447000e+00 + -2.7312000e+00 -2.7177000e+00 -2.7042000e+00 -2.6907001e+00 + -2.6772001e+00 -2.6637001e+00 -2.6501999e+00 -2.6366999e+00 + -2.6231999e+00 -2.6097000e+00 -2.5962000e+00 -2.5827000e+00 + -2.5692000e+00 -2.5557001e+00 -2.5422001e+00 -2.5287001e+00 + -2.5151999e+00 -2.5016999e+00 -2.4881999e+00 -2.4747000e+00 + -2.4612000e+00 -2.4477000e+00 -2.4342000e+00 -2.4207001e+00 + -2.4072001e+00 -2.3936999e+00 -2.3801999e+00 -2.3666999e+00 + -2.3532000e+00 -2.3397000e+00 -2.3262000e+00 -2.3127000e+00 + -2.2992001e+00 -2.2857001e+00 -2.2722001e+00 -2.2586999e+00 + -2.2451999e+00 -2.2316999e+00 -2.2182000e+00 -2.2047000e+00 + -2.1912000e+00 -2.1777000e+00 -2.1642001e+00 -2.1507001e+00 + -2.1372001e+00 -2.1236999e+00 -2.1101999e+00 -2.0967000e+00 + -2.0832000e+00 -2.0697000e+00 -2.0562000e+00 -2.0427001e+00 + -2.0292001e+00 -2.0157001e+00 -2.0021999e+00 -1.9887000e+00 + -1.9752001e+00 -1.9617000e+00 -1.9482000e+00 -1.9347000e+00 + -1.9212000e+00 -1.9076999e+00 -1.8942000e+00 -1.8807000e+00 + -1.8672000e+00 -1.8537000e+00 -1.8401999e+00 -1.8267000e+00 + -1.8132000e+00 -1.7997000e+00 -1.7862000e+00 -1.7727000e+00 + -1.7592000e+00 -1.7457000e+00 -1.7322000e+00 -1.7187001e+00 + -1.7052000e+00 -1.6917000e+00 -1.6782000e+00 -1.6647000e+00 + -1.6512001e+00 -1.6377000e+00 -1.6242000e+00 -1.6107000e+00 + -1.5972000e+00 -1.5836999e+00 -1.5702000e+00 -1.5567000e+00 + -1.5432000e+00 -1.5297000e+00 -1.5161999e+00 -1.5027000e+00 + -1.4892000e+00 -1.4757000e+00 -1.4622000e+00 -1.4487000e+00 + -1.4352000e+00 -1.4217000e+00 -1.4082000e+00 -1.3947001e+00 + -1.3812000e+00 -1.3677000e+00 -1.3542000e+00 -1.3407000e+00 + -1.3272001e+00 -1.3137000e+00 -1.3002000e+00 -1.2867000e+00 + -1.2732000e+00 -1.2596999e+00 -1.2462000e+00 -1.2327000e+00 + -1.2192000e+00 -1.2057000e+00 -1.1921999e+00 -1.1787000e+00 + -1.1652000e+00 -1.1517000e+00 -1.1382000e+00 -1.1247000e+00 + -1.1112000e+00 -1.0977000e+00 -1.0842000e+00 -1.0707000e+00 + -1.0572000e+00 -1.0437000e+00 -1.0302000e+00 -1.0167000e+00 + -1.0032001e+00 -9.8970002e-01 -9.7619998e-01 -9.6270001e-01 + -9.4919997e-01 -9.3570000e-01 -9.2220002e-01 -9.0869999e-01 + -8.9520001e-01 -8.8169998e-01 -8.6820000e-01 -8.5470003e-01 + -8.4119999e-01 -8.2770002e-01 -8.1419998e-01 -8.0070001e-01 + -7.8719997e-01 -7.7370000e-01 -7.6020002e-01 -7.4669999e-01 + -7.3320001e-01 -7.1969998e-01 -7.0620000e-01 -6.9270003e-01 + -6.7919999e-01 -6.6570002e-01 -6.5219998e-01 -6.3870001e-01 + -6.2519997e-01 -6.1170000e-01 -5.9820002e-01 -5.8469999e-01 + -5.7120001e-01 -5.5769998e-01 -5.4420000e-01 -5.3070003e-01 + -5.1719999e-01 -5.0370002e-01 -4.9020001e-01 -4.7670001e-01 + -4.6320000e-01 -4.4970000e-01 -4.3619999e-01 -4.2269999e-01 + -4.0920001e-01 -3.9570001e-01 -3.8220000e-01 -3.6870000e-01 + -3.5519999e-01 -3.4169999e-01 -3.2820001e-01 -3.1470001e-01 + -3.0120000e-01 -2.8770000e-01 -2.7419999e-01 -2.6069999e-01 + -2.4720000e-01 -2.3370001e-01 -2.2020000e-01 -2.0670000e-01 + -1.9320001e-01 -1.7970000e-01 -1.6620000e-01 -1.5270001e-01 + -1.3920000e-01 -1.2570000e-01 -1.1220000e-01 -9.8700002e-02 + -8.5199997e-02 -7.1699999e-02 -5.8200002e-02 -4.4700000e-02 + -3.1199999e-02 -1.7700000e-02 -4.1999999e-03 9.3000000e-03 + 2.2800000e-02 3.6300000e-02 4.9800001e-02 6.3299999e-02 + 7.6800004e-02 9.0300001e-02 1.0380000e-01 1.1730000e-01 + 1.3079999e-01 1.4430000e-01 1.5780000e-01 1.7129999e-01 + 1.8480000e-01 1.9830000e-01 2.1179999e-01 2.2530000e-01 + 2.3880000e-01 2.5229999e-01 2.6580000e-01 2.7930000e-01 + 2.9280001e-01 3.0630001e-01 3.1979999e-01 3.3329999e-01 + 3.4680000e-01 3.6030000e-01 3.7380001e-01 3.8730001e-01 + 4.0079999e-01 4.1429999e-01 4.2780000e-01 4.4130000e-01 + 4.5480001e-01 4.6830001e-01 4.8179999e-01 4.9529999e-01 + 5.0880003e-01 5.2230000e-01 5.3579998e-01 5.4930001e-01 + 5.6279999e-01 5.7630002e-01 5.8980000e-01 6.0329998e-01 + 6.1680001e-01 6.3029999e-01 6.4380002e-01 6.5730000e-01 + 6.7079997e-01 6.8430001e-01 6.9779998e-01 7.1130002e-01 + 7.2479999e-01 7.3830003e-01 7.5180000e-01 7.6529998e-01 + 7.7880001e-01 7.9229999e-01 8.0580002e-01 8.1930000e-01 + 8.3279997e-01 8.4630001e-01 8.5979998e-01 8.7330002e-01 + 8.8679999e-01 9.0030003e-01 9.1380000e-01 9.2729998e-01 + 9.4080001e-01 9.5429999e-01 9.6780002e-01 9.8130000e-01 + 9.9479997e-01 1.0082999e+00 1.0218000e+00 1.0353000e+00 + 1.0488000e+00 1.0623000e+00 1.0757999e+00 1.0893000e+00 + 1.1028000e+00 1.1163000e+00 1.1298000e+00 1.1433001e+00 + 1.1568000e+00 1.1703000e+00 1.1838000e+00 1.1973000e+00 + 1.2108001e+00 1.2243000e+00 1.2378000e+00 1.2513000e+00 + 1.2648000e+00 1.2783000e+00 1.2918000e+00 1.3053000e+00 + 1.3188000e+00 1.3322999e+00 1.3458000e+00 1.3593000e+00 + 1.3728000e+00 1.3863000e+00 1.3997999e+00 1.4133000e+00 + 1.4268000e+00 1.4403000e+00 1.4538000e+00 1.4673001e+00 + 1.4808000e+00 1.4943000e+00 1.5078000e+00 1.5213000e+00 + 1.5348001e+00 1.5483000e+00 1.5618000e+00 1.5753000e+00 + 1.5888000e+00 1.6023000e+00 1.6158000e+00 1.6293000e+00 + 1.6428000e+00 1.6562999e+00 1.6698000e+00 1.6833000e+00 + 1.6968000e+00 1.7103000e+00 1.7237999e+00 1.7373000e+00 + 1.7508000e+00 1.7643000e+00 1.7778000e+00 1.7913001e+00 + 1.8048000e+00 1.8183000e+00 1.8318000e+00 1.8453000e+00 + 1.8588001e+00 1.8723000e+00 1.8858000e+00 1.8993000e+00 + 1.9128000e+00 1.9263000e+00 1.9398000e+00 1.9533000e+00 + 1.9668000e+00 1.9802999e+00 1.9938000e+00 2.0072999e+00 + 2.0208001e+00 2.0343001e+00 2.0478001e+00 2.0613000e+00 + 2.0748000e+00 2.0883000e+00 2.1018000e+00 2.1152999e+00 + 2.1287999e+00 2.1422999e+00 2.1558001e+00 2.1693001e+00 + 2.1828001e+00 2.1963000e+00 2.2098000e+00 2.2233000e+00 + 2.2368000e+00 2.2502999e+00 2.2637999e+00 2.2772999e+00 + 2.2908001e+00 2.3043001e+00 2.3178000e+00 2.3313000e+00 + 2.3448000e+00 2.3583000e+00 2.3717999e+00 2.3852999e+00 + 2.3987999e+00 2.4123001e+00 2.4258001e+00 2.4393001e+00 + 2.4528000e+00 2.4663000e+00 2.4798000e+00 2.4933000e+00 + 2.5067999e+00 2.5202999e+00 2.5337999e+00 2.5473001e+00 + 2.5608001e+00 2.5743001e+00 2.5878000e+00 2.6013000e+00 + 2.6148000e+00 2.6283000e+00 2.6417999e+00 2.6552999e+00 + 2.6688001e+00 2.6823001e+00 2.6958001e+00 2.7093000e+00 + 2.7228000e+00 2.7363000e+00 2.7498000e+00 2.7632999e+00 + 2.7767999e+00 2.7902999e+00 2.8038001e+00 2.8173001e+00 + 2.8308001e+00 2.8443000e+00 2.8578000e+00 2.8713000e+00 + 2.8848000e+00 2.8982999e+00 2.9117999e+00 2.9252999e+00 + 2.9388001e+00 2.9523001e+00 2.9658000e+00 2.9793000e+00 + 2.9928000e+00 3.0063000e+00 3.0197999e+00 3.0332999e+00 + 3.0467999e+00 3.0603001e+00 3.0738001e+00 3.0873001e+00 + 3.1008000e+00 3.1143000e+00 3.1278000e+00 3.1413000e+00 + 3.1547999e+00 3.1682999e+00 3.1817999e+00 3.1953001e+00 + 3.2088001e+00 3.2223001e+00 3.2358000e+00 3.2493000e+00 + 3.2628000e+00 3.2763000e+00 3.2897999e+00 3.3032999e+00 + 3.3168001e+00 3.3303001e+00 3.3438001e+00 3.3573000e+00 + 3.3708000e+00 3.3843000e+00 3.3978000e+00 3.4112999e+00 + 3.4247999e+00 3.4382999e+00 3.4518001e+00 3.4653001e+00 + 3.4788001e+00 3.4923000e+00 3.5058000e+00 3.5193000e+00 + 3.5328000e+00 3.5462999e+00 3.5597999e+00 3.5732999e+00 + 3.5868001e+00 3.6003001e+00 3.6138000e+00 3.6273000e+00 + 3.6408000e+00 3.6543000e+00 3.6677999e+00 3.6812999e+00 + 3.6947999e+00 3.7083001e+00 3.7218001e+00 3.7353001e+00 + 3.7488000e+00 3.7623000e+00 3.7758000e+00 3.7893000e+00 + 3.8027999e+00 3.8162999e+00 3.8297999e+00 3.8433001e+00 + 3.8568001e+00 3.8703001e+00 3.8838000e+00 3.8973000e+00 + 3.9108000e+00 3.9243000e+00 3.9377999e+00 3.9512999e+00 + 3.9647999e+00 3.9783001e+00 3.9918001e+00 4.0053000e+00 + 4.0187998e+00 4.0323000e+00 4.0458002e+00 4.0592999e+00 + 4.0728002e+00 4.0862999e+00 4.0998001e+00 4.1132998e+00 + 4.1268001e+00 4.1402998e+00 4.1538000e+00 4.1673002e+00 + 4.1808000e+00 4.1943002e+00 4.2077999e+00 4.2213001e+00 + 4.2347999e+00 4.2483001e+00 4.2617998e+00 4.2753000e+00 + 4.2887998e+00 4.3023000e+00 4.3158002e+00 4.3292999e+00 + 4.3428001e+00 4.3562999e+00 4.3698001e+00 4.3832998e+00 + 4.3968000e+00 4.4102998e+00 4.4238000e+00 4.4373002e+00 + 4.4507999e+00 4.4643002e+00 4.4777999e+00 4.4913001e+00 + 4.5047998e+00 4.5183001e+00 4.5317998e+00 4.5453000e+00 + 4.5588002e+00 4.5723000e+00 4.5858002e+00 4.5992999e+00 + 4.6128001e+00 4.6262999e+00 4.6398001e+00 4.6532998e+00 + 4.6668000e+00 4.6803002e+00 4.6938000e+00 4.7073002e+00 + 4.7207999e+00 4.7343001e+00 4.7477999e+00 4.7613001e+00 + 4.7747998e+00 4.7883000e+00 4.8017998e+00 4.8153000e+00 + 4.8288002e+00 4.8422999e+00 4.8558002e+00 4.8692999e+00 + 4.8828001e+00 4.8962998e+00 4.9098001e+00 4.9232998e+00 + 4.9368000e+00 4.9503002e+00 4.9638000e+00 4.9773002e+00 + 4.9907999e+00 5.0043001e+00 5.0177999e+00 5.0313001e+00 + 5.0447998e+00 5.0583000e+00 5.0718002e+00 5.0853000e+00 + 5.0988002e+00 5.1122999e+00 5.1258001e+00 5.1392999e+00 + 5.1528001e+00 5.1662998e+00 5.1798000e+00 5.1932998e+00 + 5.2068000e+00 5.2203002e+00 5.2337999e+00 5.2473001e+00 + 5.2607999e+00 5.2743001e+00 5.2877998e+00 5.3013000e+00 + 5.3147998e+00 5.3283000e+00 5.3418002e+00 5.3552999e+00 + 5.3688002e+00 5.3822999e+00 5.3958001e+00 5.4092999e+00 + 5.4228001e+00 5.4362998e+00 5.4498000e+00 5.4633002e+00 + 5.4768000e+00 5.4903002e+00 5.5037999e+00 5.5173001e+00 + 5.5307999e+00 5.5443001e+00 5.5577998e+00 5.5713000e+00 + 5.5847998e+00 5.5983000e+00 5.6118002e+00 5.6252999e+00 + 5.6388001e+00 5.6522999e+00 5.6658001e+00 5.6792998e+00 + 5.6928000e+00 5.7062998e+00 5.7198000e+00 5.7333002e+00 + 5.7467999e+00 5.7603002e+00 5.7737999e+00 5.7873001e+00 + 5.8007998e+00 5.8143001e+00 5.8277998e+00 5.8413000e+00 + 5.8548002e+00 5.8683000e+00 5.8818002e+00 5.8952999e+00 + 5.9088001e+00 5.9222999e+00 5.9358001e+00 5.9492998e+00 + 5.9628000e+00 5.9762998e+00 5.9898000e+00 6.0033002e+00 + 6.0167999e+00 6.0303001e+00 6.0437999e+00 6.0573001e+00 + 6.0707998e+00 6.0843000e+00 6.0977998e+00 6.1113000e+00 + 6.1248002e+00 6.1382999e+00 6.1518002e+00 6.1652999e+00 + 6.1788001e+00 6.1922998e+00 6.2058001e+00 6.2192998e+00 + 6.2328000e+00 6.2463002e+00 6.2598000e+00 6.2733002e+00 + 6.2867999e+00 6.3003001e+00 6.3137999e+00 6.3273001e+00 + 6.3407998e+00 6.3543000e+00 6.3678002e+00 6.3813000e+00 + 6.3948002e+00 6.4082999e+00 6.4218001e+00 6.4352999e+00 + 6.4488001e+00 6.4622998e+00 6.4758000e+00 6.4892998e+00 + 6.5028000e+00 6.5163002e+00 6.5297999e+00 6.5433002e+00 + 6.5567999e+00 6.5703001e+00 6.5837998e+00 6.5973001e+00 + 6.6107998e+00 6.6243000e+00 6.6378002e+00 6.6513000e+00 + 6.6648002e+00 6.6782999e+00 6.6918001e+00 6.7052999e+00 + 6.7188001e+00 6.7322998e+00 6.7458000e+00 6.7593002e+00 + 6.7728000e+00 6.7863002e+00 6.7997999e+00 6.8133001e+00 + 6.8267999e+00 6.8403001e+00 6.8537998e+00 6.8673000e+00 + 6.8807998e+00 6.8943000e+00 6.9078002e+00 6.9212999e+00 + 6.9348001e+00 6.9482999e+00 6.9618001e+00 6.9752998e+00 + 6.9888000e+00 7.0022998e+00 7.0158000e+00 7.0293002e+00 + 7.0427999e+00 7.0563002e+00 7.0697999e+00 7.0833001e+00 + 7.0967999e+00 7.1103001e+00 7.1237998e+00 7.1373000e+00 + 7.1508002e+00 7.1648540e+00 7.1794853e+00 7.1947169e+00 + 7.2105737e+00 7.2270813e+00 7.2442665e+00 7.2621570e+00 + 7.2807817e+00 7.3001714e+00 7.3203568e+00 7.3413706e+00 + 7.3632469e+00 7.3860216e+00 7.4097309e+00 7.4344130e+00 + 7.4601088e+00 7.4868588e+00 7.5147071e+00 7.5436983e+00 + 7.5738797e+00 7.6052999e+00 7.6413002e+00 7.6773000e+00 + 7.7133002e+00 7.7493000e+00 7.7852998e+00 7.8213000e+00 + 7.8572998e+00 7.8933001e+00 7.9292998e+00 7.9653001e+00 + 8.0012999e+00 8.0373001e+00 8.0733004e+00 8.1092997e+00 + 8.1452999e+00 8.1813002e+00 8.2173004e+00 8.2532997e+00 + 8.2893000e+00 8.3253002e+00 8.3613005e+00 8.3972998e+00 + 8.4333000e+00 8.4693003e+00 8.5052996e+00 8.5412998e+00 + 8.5773001e+00 8.6133003e+00 8.6492996e+00 8.6852999e+00 + 8.7213001e+00 8.7573004e+00 8.7932997e+00 8.8292999e+00 + 8.8653002e+00 8.9013004e+00 8.9372997e+00 8.9733000e+00] + y_lower_bound: [-5.6112003e+00 -5.5752001e+00 -5.5391998e+00 -5.5032001e+00 + -5.4671998e+00 -5.4312000e+00 -5.3951998e+00 -5.3592000e+00 + -5.3232002e+00 -5.2872000e+00 -5.2512002e+00 -5.2151999e+00 + -5.1792002e+00 -5.1431999e+00 -5.1072001e+00 -5.0711999e+00 + -5.0352001e+00 -4.9991999e+00 -4.9632001e+00 -4.9271998e+00 + -4.8912001e+00 -4.8551998e+00 -4.8192000e+00 -4.7831998e+00 + -4.7472000e+00 -4.7112002e+00 -4.6752000e+00 -4.6392002e+00 + -4.6032000e+00 -4.5672002e+00 -4.5311999e+00 -4.4952002e+00 + -4.4591999e+00 -4.4232001e+00 -4.3871999e+00 -4.3512001e+00 + -4.3151999e+00 -4.2792001e+00 -4.2431998e+00 -4.2094898e+00 + -4.1786890e+00 -4.1491027e+00 -4.1206832e+00 -4.0933838e+00 + -4.0671611e+00 -4.0419717e+00 -4.0177760e+00 -3.9945343e+00 + -3.9722090e+00 -3.9507637e+00 -3.9301641e+00 -3.9103768e+00 + -3.8913693e+00 -3.8731117e+00 -3.8555737e+00 -3.8387272e+00 + -3.8225451e+00 -3.8070009e+00 -3.7920697e+00 -3.7777271e+00 + -3.7639501e+00 -3.7504499e+00 -3.7369499e+00 -3.7234499e+00 + -3.7099500e+00 -3.6964500e+00 -3.6829500e+00 -3.6694500e+00 + -3.6559501e+00 -3.6424501e+00 -3.6289501e+00 -3.6154499e+00 + -3.6019499e+00 -3.5884500e+00 -3.5749500e+00 -3.5614500e+00 + -3.5479500e+00 -3.5344501e+00 -3.5209501e+00 -3.5074501e+00 + -3.4939499e+00 -3.4804499e+00 -3.4669499e+00 -3.4534500e+00 + -3.4399500e+00 -3.4264500e+00 -3.4129500e+00 -3.3994501e+00 + -3.3859501e+00 -3.3724501e+00 -3.3589499e+00 -3.3454499e+00 + -3.3319499e+00 -3.3184500e+00 -3.3049500e+00 -3.2914500e+00 + -3.2779500e+00 -3.2644501e+00 -3.2509501e+00 -3.2374499e+00 + -3.2239499e+00 -3.2104499e+00 -3.1969500e+00 -3.1834500e+00 + -3.1699500e+00 -3.1564500e+00 -3.1429501e+00 -3.1294501e+00 + -3.1159501e+00 -3.1024499e+00 -3.0889499e+00 -3.0754499e+00 + -3.0619500e+00 -3.0484500e+00 -3.0349500e+00 -3.0214500e+00 + -3.0079501e+00 -2.9944501e+00 -2.9809501e+00 -2.9674499e+00 + -2.9539499e+00 -2.9404500e+00 -2.9269500e+00 -2.9134500e+00 + -2.8999500e+00 -2.8864501e+00 -2.8729501e+00 -2.8594501e+00 + -2.8459499e+00 -2.8324499e+00 -2.8189499e+00 -2.8054500e+00 + -2.7919500e+00 -2.7784500e+00 -2.7649500e+00 -2.7514501e+00 + -2.7379501e+00 -2.7244501e+00 -2.7109499e+00 -2.6974499e+00 + -2.6839499e+00 -2.6704500e+00 -2.6569500e+00 -2.6434500e+00 + -2.6299500e+00 -2.6164501e+00 -2.6029501e+00 -2.5894499e+00 + -2.5759499e+00 -2.5624499e+00 -2.5489500e+00 -2.5354500e+00 + -2.5219500e+00 -2.5084500e+00 -2.4949501e+00 -2.4814501e+00 + -2.4679501e+00 -2.4544499e+00 -2.4409499e+00 -2.4274499e+00 + -2.4139500e+00 -2.4004500e+00 -2.3869500e+00 -2.3734500e+00 + -2.3599501e+00 -2.3464501e+00 -2.3329501e+00 -2.3194499e+00 + -2.3059499e+00 -2.2924500e+00 -2.2789500e+00 -2.2654500e+00 + -2.2519500e+00 -2.2384501e+00 -2.2249501e+00 -2.2114501e+00 + -2.1979499e+00 -2.1844499e+00 -2.1709499e+00 -2.1574500e+00 + -2.1439500e+00 -2.1304500e+00 -2.1169500e+00 -2.1034501e+00 + -2.0899501e+00 -2.0764501e+00 -2.0629499e+00 -2.0494499e+00 + -2.0359499e+00 -2.0224500e+00 -2.0089500e+00 -1.9954500e+00 + -1.9819500e+00 -1.9684500e+00 -1.9549500e+00 -1.9414500e+00 + -1.9279500e+00 -1.9144500e+00 -1.9009500e+00 -1.8874500e+00 + -1.8739500e+00 -1.8604500e+00 -1.8469501e+00 -1.8334500e+00 + -1.8199500e+00 -1.8064500e+00 -1.7929500e+00 -1.7794501e+00 + -1.7659500e+00 -1.7524500e+00 -1.7389500e+00 -1.7254500e+00 + -1.7119499e+00 -1.6984500e+00 -1.6849500e+00 -1.6714500e+00 + -1.6579500e+00 -1.6444499e+00 -1.6309500e+00 -1.6174500e+00 + -1.6039500e+00 -1.5904500e+00 -1.5769500e+00 -1.5634500e+00 + -1.5499500e+00 -1.5364500e+00 -1.5229501e+00 -1.5094500e+00 + -1.4959500e+00 -1.4824500e+00 -1.4689500e+00 -1.4554501e+00 + -1.4419500e+00 -1.4284500e+00 -1.4149500e+00 -1.4014500e+00 + -1.3879499e+00 -1.3744500e+00 -1.3609500e+00 -1.3474500e+00 + -1.3339500e+00 -1.3204499e+00 -1.3069500e+00 -1.2934500e+00 + -1.2799500e+00 -1.2664500e+00 -1.2529500e+00 -1.2394500e+00 + -1.2259500e+00 -1.2124500e+00 -1.1989501e+00 -1.1854500e+00 + -1.1719500e+00 -1.1584500e+00 -1.1449500e+00 -1.1314501e+00 + -1.1179500e+00 -1.1044500e+00 -1.0909500e+00 -1.0774500e+00 + -1.0639499e+00 -1.0504500e+00 -1.0369500e+00 -1.0234500e+00 + -1.0099500e+00 -9.9645001e-01 -9.8294997e-01 -9.6945000e-01 + -9.5595002e-01 -9.4244999e-01 -9.2895001e-01 -9.1544998e-01 + -9.0195000e-01 -8.8845003e-01 -8.7494999e-01 -8.6145002e-01 + -8.4794998e-01 -8.3445001e-01 -8.2094997e-01 -8.0745000e-01 + -7.9395002e-01 -7.8044999e-01 -7.6695001e-01 -7.5344998e-01 + -7.3995000e-01 -7.2645003e-01 -7.1294999e-01 -6.9945002e-01 + -6.8594998e-01 -6.7245001e-01 -6.5894997e-01 -6.4545000e-01 + -6.3195002e-01 -6.1844999e-01 -6.0495001e-01 -5.9144998e-01 + -5.7795000e-01 -5.6445003e-01 -5.5094999e-01 -5.3745002e-01 + -5.2394998e-01 -5.1045001e-01 -4.9695000e-01 -4.8345000e-01 + -4.6994999e-01 -4.5644999e-01 -4.4295001e-01 -4.2945001e-01 + -4.1595000e-01 -4.0245000e-01 -3.8894999e-01 -3.7544999e-01 + -3.6195001e-01 -3.4845001e-01 -3.3495000e-01 -3.2145000e-01 + -3.0794999e-01 -2.9445001e-01 -2.8095001e-01 -2.6745000e-01 + -2.5395000e-01 -2.4044999e-01 -2.2695000e-01 -2.1345000e-01 + -1.9994999e-01 -1.8645000e-01 -1.7295000e-01 -1.5944999e-01 + -1.4595000e-01 -1.3245000e-01 -1.1895000e-01 -1.0545000e-01 + -9.1949999e-02 -7.8450002e-02 -6.4949997e-02 -5.1449999e-02 + -3.7950002e-02 -2.4450000e-02 -1.0950000e-02 2.5500001e-03 + 1.6050000e-02 2.9549999e-02 4.3049999e-02 5.6550000e-02 + 7.0050001e-02 8.3549999e-02 9.7050004e-02 1.1055000e-01 + 1.2405000e-01 1.3755000e-01 1.5105000e-01 1.6455001e-01 + 1.7805000e-01 1.9155000e-01 2.0505001e-01 2.1855000e-01 + 2.3205000e-01 2.4555001e-01 2.5905001e-01 2.7254999e-01 + 2.8604999e-01 2.9955000e-01 3.1305000e-01 3.2655001e-01 + 3.4005001e-01 3.5354999e-01 3.6704999e-01 3.8055000e-01 + 3.9405000e-01 4.0755001e-01 4.2105001e-01 4.3454999e-01 + 4.4804999e-01 4.6155000e-01 4.7505000e-01 4.8855001e-01 + 5.0204998e-01 5.1555002e-01 5.2904999e-01 5.4255003e-01 + 5.5605000e-01 5.6954998e-01 5.8305001e-01 5.9654999e-01 + 6.1005002e-01 6.2355000e-01 6.3704997e-01 6.5055001e-01 + 6.6404998e-01 6.7755002e-01 6.9104999e-01 7.0455003e-01 + 7.1805000e-01 7.3154998e-01 7.4505001e-01 7.5854999e-01 + 7.7205002e-01 7.8555000e-01 7.9904997e-01 8.1255001e-01 + 8.2604998e-01 8.3955002e-01 8.5304999e-01 8.6655003e-01 + 8.8005000e-01 8.9354998e-01 9.0705001e-01 9.2054999e-01 + 9.3405002e-01 9.4755000e-01 9.6104997e-01 9.7455001e-01 + 9.8804998e-01 1.0015500e+00 1.0150501e+00 1.0285500e+00 + 1.0420500e+00 1.0555500e+00 1.0690500e+00 1.0825500e+00 + 1.0960500e+00 1.1095500e+00 1.1230500e+00 1.1365499e+00 + 1.1500500e+00 1.1635500e+00 1.1770500e+00 1.1905500e+00 + 1.2040499e+00 1.2175500e+00 1.2310500e+00 1.2445500e+00 + 1.2580500e+00 1.2715501e+00 1.2850500e+00 1.2985500e+00 + 1.3120500e+00 1.3255500e+00 1.3390501e+00 1.3525500e+00 + 1.3660500e+00 1.3795500e+00 1.3930500e+00 1.4065500e+00 + 1.4200500e+00 1.4335500e+00 1.4470500e+00 1.4605500e+00 + 1.4740500e+00 1.4875500e+00 1.5010500e+00 1.5145500e+00 + 1.5280499e+00 1.5415500e+00 1.5550500e+00 1.5685500e+00 + 1.5820500e+00 1.5955499e+00 1.6090500e+00 1.6225500e+00 + 1.6360500e+00 1.6495500e+00 1.6630501e+00 1.6765500e+00 + 1.6900500e+00 1.7035500e+00 1.7170500e+00 1.7305501e+00 + 1.7440500e+00 1.7575500e+00 1.7710500e+00 1.7845500e+00 + 1.7980500e+00 1.8115500e+00 1.8250500e+00 1.8385500e+00 + 1.8520499e+00 1.8655500e+00 1.8790500e+00 1.8925500e+00 + 1.9060500e+00 1.9195499e+00 1.9330500e+00 1.9465500e+00 + 1.9600500e+00 1.9735500e+00 1.9870501e+00 2.0005500e+00 + 2.0140500e+00 2.0275500e+00 2.0410500e+00 2.0545499e+00 + 2.0680499e+00 2.0815499e+00 2.0950501e+00 2.1085501e+00 + 2.1220500e+00 2.1355500e+00 2.1490500e+00 2.1625500e+00 + 2.1760499e+00 2.1895499e+00 2.2030499e+00 2.2165501e+00 + 2.2300501e+00 2.2435501e+00 2.2570500e+00 2.2705500e+00 + 2.2840500e+00 2.2975500e+00 2.3110499e+00 2.3245499e+00 + 2.3380499e+00 2.3515501e+00 2.3650501e+00 2.3785501e+00 + 2.3920500e+00 2.4055500e+00 2.4190500e+00 2.4325500e+00 + 2.4460499e+00 2.4595499e+00 2.4730501e+00 2.4865501e+00 + 2.5000501e+00 2.5135500e+00 2.5270500e+00 2.5405500e+00 + 2.5540500e+00 2.5675499e+00 2.5810499e+00 2.5945499e+00 + 2.6080501e+00 2.6215501e+00 2.6350501e+00 2.6485500e+00 + 2.6620500e+00 2.6755500e+00 2.6890500e+00 2.7025499e+00 + 2.7160499e+00 2.7295499e+00 2.7430501e+00 2.7565501e+00 + 2.7700500e+00 2.7835500e+00 2.7970500e+00 2.8105500e+00 + 2.8240499e+00 2.8375499e+00 2.8510499e+00 2.8645501e+00 + 2.8780501e+00 2.8915501e+00 2.9050500e+00 2.9185500e+00 + 2.9320500e+00 2.9455500e+00 2.9590499e+00 2.9725499e+00 + 2.9860499e+00 2.9995501e+00 3.0130501e+00 3.0265501e+00 + 3.0400500e+00 3.0535500e+00 3.0670500e+00 3.0805500e+00 + 3.0940499e+00 3.1075499e+00 3.1210499e+00 3.1345501e+00 + 3.1480501e+00 3.1615500e+00 3.1750500e+00 3.1885500e+00 + 3.2020500e+00 3.2155499e+00 3.2290499e+00 3.2425499e+00 + 3.2560501e+00 3.2695501e+00 3.2830501e+00 3.2965500e+00 + 3.3100500e+00 3.3235500e+00 3.3370500e+00 3.3505499e+00 + 3.3640499e+00 3.3775499e+00 3.3910501e+00 3.4045501e+00 + 3.4180501e+00 3.4315500e+00 3.4450500e+00 3.4585500e+00 + 3.4720500e+00 3.4855499e+00 3.4990499e+00 3.5125501e+00 + 3.5260501e+00 3.5395501e+00 3.5530500e+00 3.5665500e+00 + 3.5800500e+00 3.5935500e+00 3.6070499e+00 3.6205499e+00 + 3.6340499e+00 3.6475501e+00 3.6610501e+00 3.6745501e+00 + 3.6880500e+00 3.7015500e+00 3.7150500e+00 3.7285500e+00 + 3.7420499e+00 3.7555499e+00 3.7690499e+00 3.7825501e+00 + 3.7960501e+00 3.8095500e+00 3.8230500e+00 3.8365500e+00 + 3.8500500e+00 3.8635499e+00 3.8770499e+00 3.8905499e+00 + 3.9040501e+00 3.9175501e+00 3.9310501e+00 3.9445500e+00 + 3.9580500e+00 3.9715500e+00 3.9850500e+00 3.9985499e+00 + 4.0120502e+00 4.0255499e+00 4.0390501e+00 4.0525498e+00 + 4.0660501e+00 4.0795498e+00 4.0930500e+00 4.1065502e+00 + 4.1200500e+00 4.1335502e+00 4.1470499e+00 4.1605501e+00 + 4.1740499e+00 4.1875501e+00 4.2010498e+00 4.2145500e+00 + 4.2280502e+00 4.2415500e+00 4.2550502e+00 4.2685499e+00 + 4.2820501e+00 4.2955499e+00 4.3090501e+00 4.3225498e+00 + 4.3360500e+00 4.3495498e+00 4.3630500e+00 4.3765502e+00 + 4.3900499e+00 4.4035501e+00 4.4170499e+00 4.4305501e+00 + 4.4440498e+00 4.4575500e+00 4.4710498e+00 4.4845500e+00 + 4.4980502e+00 4.5115499e+00 4.5250502e+00 4.5385499e+00 + 4.5520501e+00 4.5655499e+00 4.5790501e+00 4.5925498e+00 + 4.6060500e+00 4.6195502e+00 4.6330500e+00 4.6465502e+00 + 4.6600499e+00 4.6735501e+00 4.6870499e+00 4.7005501e+00 + 4.7140498e+00 4.7275500e+00 4.7410498e+00 4.7545500e+00 + 4.7680502e+00 4.7815499e+00 4.7950501e+00 4.8085499e+00 + 4.8220501e+00 4.8355498e+00 4.8490500e+00 4.8625498e+00 + 4.8760500e+00 4.8895502e+00 4.9030499e+00 4.9165502e+00 + 4.9300499e+00 4.9435501e+00 4.9570498e+00 4.9705501e+00 + 4.9840498e+00 4.9975500e+00 5.0110502e+00 5.0245500e+00 + 5.0380502e+00 5.0515499e+00 5.0650501e+00 5.0785499e+00 + 5.0920501e+00 5.1055498e+00 5.1190500e+00 5.1325498e+00 + 5.1460500e+00 5.1595502e+00 5.1730499e+00 5.1865501e+00 + 5.2000499e+00 5.2135501e+00 5.2270498e+00 5.2405500e+00 + 5.2540498e+00 5.2675500e+00 5.2810502e+00 5.2945499e+00 + 5.3080502e+00 5.3215499e+00 5.3350501e+00 5.3485498e+00 + 5.3620501e+00 5.3755498e+00 5.3890500e+00 5.4025502e+00 + 5.4160500e+00 5.4295502e+00 5.4430499e+00 5.4565501e+00 + 5.4700499e+00 5.4835501e+00 5.4970498e+00 5.5105500e+00 + 5.5240502e+00 5.5375500e+00 5.5510502e+00 5.5645499e+00 + 5.5780501e+00 5.5915499e+00 5.6050501e+00 5.6185498e+00 + 5.6320500e+00 5.6455498e+00 5.6590500e+00 5.6725502e+00 + 5.6860499e+00 5.6995502e+00 5.7130499e+00 5.7265501e+00 + 5.7400498e+00 5.7535501e+00 5.7670498e+00 5.7805500e+00 + 5.7940502e+00 5.8075500e+00 5.8210502e+00 5.8345499e+00 + 5.8480501e+00 5.8615499e+00 5.8750501e+00 5.8885498e+00 + 5.9020500e+00 5.9155502e+00 5.9290500e+00 5.9425502e+00 + 5.9560499e+00 5.9695501e+00 5.9830499e+00 5.9965501e+00 + 6.0100498e+00 6.0235500e+00 6.0370498e+00 6.0505500e+00 + 6.0640502e+00 6.0775499e+00 6.0910501e+00 6.1045499e+00 + 6.1180501e+00 6.1315498e+00 6.1450500e+00 6.1585498e+00 + 6.1720500e+00 6.1855502e+00 6.1990499e+00 6.2125502e+00 + 6.2260499e+00 6.2395501e+00 6.2530499e+00 6.2665501e+00 + 6.2800498e+00 6.2935500e+00 6.3070502e+00 6.3205500e+00 + 6.3340502e+00 6.3475499e+00 6.3610501e+00 6.3745499e+00 + 6.3880501e+00 6.4015498e+00 6.4150500e+00 6.4285498e+00 + 6.4420500e+00 6.4555502e+00 6.4690499e+00 6.4825501e+00 + 6.4960499e+00 6.5095501e+00 6.5230498e+00 6.5365500e+00 + 6.5500498e+00 6.5635500e+00 6.5770502e+00 6.5905499e+00 + 6.6040502e+00 6.6175499e+00 6.6310501e+00 6.6445498e+00 + 6.6580501e+00 6.6715498e+00 6.6850500e+00 6.6985502e+00 + 6.7120500e+00 6.7255502e+00 6.7390499e+00 6.7525501e+00 + 6.7660499e+00 6.7795501e+00 6.7930498e+00 6.8065500e+00 + 6.8200498e+00 6.8335500e+00 6.8470502e+00 6.8605499e+00 + 6.8740501e+00 6.8875499e+00 6.9010501e+00 6.9145498e+00 + 6.9280500e+00 6.9415498e+00 6.9550500e+00 6.9685502e+00 + 6.9820499e+00 6.9955502e+00 7.0090499e+00 7.0225501e+00 + 7.0360498e+00 7.0495501e+00 7.0630498e+00 7.0765500e+00 + 7.0900502e+00 7.1035500e+00 7.1170502e+00 7.1305499e+00 + 7.1440501e+00 7.1578269e+00 7.1721697e+00 7.1871009e+00 + 7.2026453e+00 7.2188272e+00 7.2356739e+00 7.2532115e+00 + 7.2714696e+00 7.2904768e+00 7.3102641e+00 7.3308635e+00 + 7.3523088e+00 7.3746343e+00 7.3978763e+00 7.4220719e+00 + 7.4472609e+00 7.4734836e+00 7.5007830e+00 7.5292029e+00 + 7.5587893e+00 7.5895901e+00 7.6233001e+00 7.6592999e+00 + 7.6953001e+00 7.7312999e+00 7.7673001e+00 7.8032999e+00 + 7.8393002e+00 7.8752999e+00 7.9113002e+00 7.9473000e+00 + 7.9833002e+00 8.0193005e+00 8.0552998e+00 8.0913000e+00 + 8.1273003e+00 8.1632996e+00 8.1992998e+00 8.2353001e+00 + 8.2713003e+00 8.3072996e+00 8.3432999e+00 8.3793001e+00 + 8.4153004e+00 8.4512997e+00 8.4872999e+00 8.5233002e+00 + 8.5593004e+00 8.5952997e+00 8.6313000e+00 8.6673002e+00 + 8.7033005e+00 8.7392998e+00 8.7753000e+00 8.8113003e+00 + 8.8472996e+00 8.8832998e+00 8.9193001e+00 8.9553003e+00] + y_upper_bound: [-5.5752001e+00 -5.5391998e+00 -5.5032001e+00 -5.4671998e+00 + -5.4312000e+00 -5.3951998e+00 -5.3592000e+00 -5.3232002e+00 + -5.2872000e+00 -5.2512002e+00 -5.2151999e+00 -5.1792002e+00 + -5.1431999e+00 -5.1072001e+00 -5.0711999e+00 -5.0352001e+00 + -4.9991999e+00 -4.9632001e+00 -4.9271998e+00 -4.8912001e+00 + -4.8551998e+00 -4.8192000e+00 -4.7831998e+00 -4.7472000e+00 + -4.7112002e+00 -4.6752000e+00 -4.6392002e+00 -4.6032000e+00 + -4.5672002e+00 -4.5311999e+00 -4.4952002e+00 -4.4591999e+00 + -4.4232001e+00 -4.3871999e+00 -4.3512001e+00 -4.3151999e+00 + -4.2792001e+00 -4.2431998e+00 -4.2094898e+00 -4.1786890e+00 + -4.1491027e+00 -4.1206832e+00 -4.0933838e+00 -4.0671611e+00 + -4.0419717e+00 -4.0177760e+00 -3.9945343e+00 -3.9722090e+00 + -3.9507637e+00 -3.9301641e+00 -3.9103768e+00 -3.8913693e+00 + -3.8731117e+00 -3.8555737e+00 -3.8387272e+00 -3.8225451e+00 + -3.8070009e+00 -3.7920697e+00 -3.7777271e+00 -3.7639501e+00 + -3.7504499e+00 -3.7369499e+00 -3.7234499e+00 -3.7099500e+00 + -3.6964500e+00 -3.6829500e+00 -3.6694500e+00 -3.6559501e+00 + -3.6424501e+00 -3.6289501e+00 -3.6154499e+00 -3.6019499e+00 + -3.5884500e+00 -3.5749500e+00 -3.5614500e+00 -3.5479500e+00 + -3.5344501e+00 -3.5209501e+00 -3.5074501e+00 -3.4939499e+00 + -3.4804499e+00 -3.4669499e+00 -3.4534500e+00 -3.4399500e+00 + -3.4264500e+00 -3.4129500e+00 -3.3994501e+00 -3.3859501e+00 + -3.3724501e+00 -3.3589499e+00 -3.3454499e+00 -3.3319499e+00 + -3.3184500e+00 -3.3049500e+00 -3.2914500e+00 -3.2779500e+00 + -3.2644501e+00 -3.2509501e+00 -3.2374499e+00 -3.2239499e+00 + -3.2104499e+00 -3.1969500e+00 -3.1834500e+00 -3.1699500e+00 + -3.1564500e+00 -3.1429501e+00 -3.1294501e+00 -3.1159501e+00 + -3.1024499e+00 -3.0889499e+00 -3.0754499e+00 -3.0619500e+00 + -3.0484500e+00 -3.0349500e+00 -3.0214500e+00 -3.0079501e+00 + -2.9944501e+00 -2.9809501e+00 -2.9674499e+00 -2.9539499e+00 + -2.9404500e+00 -2.9269500e+00 -2.9134500e+00 -2.8999500e+00 + -2.8864501e+00 -2.8729501e+00 -2.8594501e+00 -2.8459499e+00 + -2.8324499e+00 -2.8189499e+00 -2.8054500e+00 -2.7919500e+00 + -2.7784500e+00 -2.7649500e+00 -2.7514501e+00 -2.7379501e+00 + -2.7244501e+00 -2.7109499e+00 -2.6974499e+00 -2.6839499e+00 + -2.6704500e+00 -2.6569500e+00 -2.6434500e+00 -2.6299500e+00 + -2.6164501e+00 -2.6029501e+00 -2.5894499e+00 -2.5759499e+00 + -2.5624499e+00 -2.5489500e+00 -2.5354500e+00 -2.5219500e+00 + -2.5084500e+00 -2.4949501e+00 -2.4814501e+00 -2.4679501e+00 + -2.4544499e+00 -2.4409499e+00 -2.4274499e+00 -2.4139500e+00 + -2.4004500e+00 -2.3869500e+00 -2.3734500e+00 -2.3599501e+00 + -2.3464501e+00 -2.3329501e+00 -2.3194499e+00 -2.3059499e+00 + -2.2924500e+00 -2.2789500e+00 -2.2654500e+00 -2.2519500e+00 + -2.2384501e+00 -2.2249501e+00 -2.2114501e+00 -2.1979499e+00 + -2.1844499e+00 -2.1709499e+00 -2.1574500e+00 -2.1439500e+00 + -2.1304500e+00 -2.1169500e+00 -2.1034501e+00 -2.0899501e+00 + -2.0764501e+00 -2.0629499e+00 -2.0494499e+00 -2.0359499e+00 + -2.0224500e+00 -2.0089500e+00 -1.9954500e+00 -1.9819500e+00 + -1.9684500e+00 -1.9549500e+00 -1.9414500e+00 -1.9279500e+00 + -1.9144500e+00 -1.9009500e+00 -1.8874500e+00 -1.8739500e+00 + -1.8604500e+00 -1.8469501e+00 -1.8334500e+00 -1.8199500e+00 + -1.8064500e+00 -1.7929500e+00 -1.7794501e+00 -1.7659500e+00 + -1.7524500e+00 -1.7389500e+00 -1.7254500e+00 -1.7119499e+00 + -1.6984500e+00 -1.6849500e+00 -1.6714500e+00 -1.6579500e+00 + -1.6444499e+00 -1.6309500e+00 -1.6174500e+00 -1.6039500e+00 + -1.5904500e+00 -1.5769500e+00 -1.5634500e+00 -1.5499500e+00 + -1.5364500e+00 -1.5229501e+00 -1.5094500e+00 -1.4959500e+00 + -1.4824500e+00 -1.4689500e+00 -1.4554501e+00 -1.4419500e+00 + -1.4284500e+00 -1.4149500e+00 -1.4014500e+00 -1.3879499e+00 + -1.3744500e+00 -1.3609500e+00 -1.3474500e+00 -1.3339500e+00 + -1.3204499e+00 -1.3069500e+00 -1.2934500e+00 -1.2799500e+00 + -1.2664500e+00 -1.2529500e+00 -1.2394500e+00 -1.2259500e+00 + -1.2124500e+00 -1.1989501e+00 -1.1854500e+00 -1.1719500e+00 + -1.1584500e+00 -1.1449500e+00 -1.1314501e+00 -1.1179500e+00 + -1.1044500e+00 -1.0909500e+00 -1.0774500e+00 -1.0639499e+00 + -1.0504500e+00 -1.0369500e+00 -1.0234500e+00 -1.0099500e+00 + -9.9645001e-01 -9.8294997e-01 -9.6945000e-01 -9.5595002e-01 + -9.4244999e-01 -9.2895001e-01 -9.1544998e-01 -9.0195000e-01 + -8.8845003e-01 -8.7494999e-01 -8.6145002e-01 -8.4794998e-01 + -8.3445001e-01 -8.2094997e-01 -8.0745000e-01 -7.9395002e-01 + -7.8044999e-01 -7.6695001e-01 -7.5344998e-01 -7.3995000e-01 + -7.2645003e-01 -7.1294999e-01 -6.9945002e-01 -6.8594998e-01 + -6.7245001e-01 -6.5894997e-01 -6.4545000e-01 -6.3195002e-01 + -6.1844999e-01 -6.0495001e-01 -5.9144998e-01 -5.7795000e-01 + -5.6445003e-01 -5.5094999e-01 -5.3745002e-01 -5.2394998e-01 + -5.1045001e-01 -4.9695000e-01 -4.8345000e-01 -4.6994999e-01 + -4.5644999e-01 -4.4295001e-01 -4.2945001e-01 -4.1595000e-01 + -4.0245000e-01 -3.8894999e-01 -3.7544999e-01 -3.6195001e-01 + -3.4845001e-01 -3.3495000e-01 -3.2145000e-01 -3.0794999e-01 + -2.9445001e-01 -2.8095001e-01 -2.6745000e-01 -2.5395000e-01 + -2.4044999e-01 -2.2695000e-01 -2.1345000e-01 -1.9994999e-01 + -1.8645000e-01 -1.7295000e-01 -1.5944999e-01 -1.4595000e-01 + -1.3245000e-01 -1.1895000e-01 -1.0545000e-01 -9.1949999e-02 + -7.8450002e-02 -6.4949997e-02 -5.1449999e-02 -3.7950002e-02 + -2.4450000e-02 -1.0950000e-02 2.5500001e-03 1.6050000e-02 + 2.9549999e-02 4.3049999e-02 5.6550000e-02 7.0050001e-02 + 8.3549999e-02 9.7050004e-02 1.1055000e-01 1.2405000e-01 + 1.3755000e-01 1.5105000e-01 1.6455001e-01 1.7805000e-01 + 1.9155000e-01 2.0505001e-01 2.1855000e-01 2.3205000e-01 + 2.4555001e-01 2.5905001e-01 2.7254999e-01 2.8604999e-01 + 2.9955000e-01 3.1305000e-01 3.2655001e-01 3.4005001e-01 + 3.5354999e-01 3.6704999e-01 3.8055000e-01 3.9405000e-01 + 4.0755001e-01 4.2105001e-01 4.3454999e-01 4.4804999e-01 + 4.6155000e-01 4.7505000e-01 4.8855001e-01 5.0204998e-01 + 5.1555002e-01 5.2904999e-01 5.4255003e-01 5.5605000e-01 + 5.6954998e-01 5.8305001e-01 5.9654999e-01 6.1005002e-01 + 6.2355000e-01 6.3704997e-01 6.5055001e-01 6.6404998e-01 + 6.7755002e-01 6.9104999e-01 7.0455003e-01 7.1805000e-01 + 7.3154998e-01 7.4505001e-01 7.5854999e-01 7.7205002e-01 + 7.8555000e-01 7.9904997e-01 8.1255001e-01 8.2604998e-01 + 8.3955002e-01 8.5304999e-01 8.6655003e-01 8.8005000e-01 + 8.9354998e-01 9.0705001e-01 9.2054999e-01 9.3405002e-01 + 9.4755000e-01 9.6104997e-01 9.7455001e-01 9.8804998e-01 + 1.0015500e+00 1.0150501e+00 1.0285500e+00 1.0420500e+00 + 1.0555500e+00 1.0690500e+00 1.0825500e+00 1.0960500e+00 + 1.1095500e+00 1.1230500e+00 1.1365499e+00 1.1500500e+00 + 1.1635500e+00 1.1770500e+00 1.1905500e+00 1.2040499e+00 + 1.2175500e+00 1.2310500e+00 1.2445500e+00 1.2580500e+00 + 1.2715501e+00 1.2850500e+00 1.2985500e+00 1.3120500e+00 + 1.3255500e+00 1.3390501e+00 1.3525500e+00 1.3660500e+00 + 1.3795500e+00 1.3930500e+00 1.4065500e+00 1.4200500e+00 + 1.4335500e+00 1.4470500e+00 1.4605500e+00 1.4740500e+00 + 1.4875500e+00 1.5010500e+00 1.5145500e+00 1.5280499e+00 + 1.5415500e+00 1.5550500e+00 1.5685500e+00 1.5820500e+00 + 1.5955499e+00 1.6090500e+00 1.6225500e+00 1.6360500e+00 + 1.6495500e+00 1.6630501e+00 1.6765500e+00 1.6900500e+00 + 1.7035500e+00 1.7170500e+00 1.7305501e+00 1.7440500e+00 + 1.7575500e+00 1.7710500e+00 1.7845500e+00 1.7980500e+00 + 1.8115500e+00 1.8250500e+00 1.8385500e+00 1.8520499e+00 + 1.8655500e+00 1.8790500e+00 1.8925500e+00 1.9060500e+00 + 1.9195499e+00 1.9330500e+00 1.9465500e+00 1.9600500e+00 + 1.9735500e+00 1.9870501e+00 2.0005500e+00 2.0140500e+00 + 2.0275500e+00 2.0410500e+00 2.0545499e+00 2.0680499e+00 + 2.0815499e+00 2.0950501e+00 2.1085501e+00 2.1220500e+00 + 2.1355500e+00 2.1490500e+00 2.1625500e+00 2.1760499e+00 + 2.1895499e+00 2.2030499e+00 2.2165501e+00 2.2300501e+00 + 2.2435501e+00 2.2570500e+00 2.2705500e+00 2.2840500e+00 + 2.2975500e+00 2.3110499e+00 2.3245499e+00 2.3380499e+00 + 2.3515501e+00 2.3650501e+00 2.3785501e+00 2.3920500e+00 + 2.4055500e+00 2.4190500e+00 2.4325500e+00 2.4460499e+00 + 2.4595499e+00 2.4730501e+00 2.4865501e+00 2.5000501e+00 + 2.5135500e+00 2.5270500e+00 2.5405500e+00 2.5540500e+00 + 2.5675499e+00 2.5810499e+00 2.5945499e+00 2.6080501e+00 + 2.6215501e+00 2.6350501e+00 2.6485500e+00 2.6620500e+00 + 2.6755500e+00 2.6890500e+00 2.7025499e+00 2.7160499e+00 + 2.7295499e+00 2.7430501e+00 2.7565501e+00 2.7700500e+00 + 2.7835500e+00 2.7970500e+00 2.8105500e+00 2.8240499e+00 + 2.8375499e+00 2.8510499e+00 2.8645501e+00 2.8780501e+00 + 2.8915501e+00 2.9050500e+00 2.9185500e+00 2.9320500e+00 + 2.9455500e+00 2.9590499e+00 2.9725499e+00 2.9860499e+00 + 2.9995501e+00 3.0130501e+00 3.0265501e+00 3.0400500e+00 + 3.0535500e+00 3.0670500e+00 3.0805500e+00 3.0940499e+00 + 3.1075499e+00 3.1210499e+00 3.1345501e+00 3.1480501e+00 + 3.1615500e+00 3.1750500e+00 3.1885500e+00 3.2020500e+00 + 3.2155499e+00 3.2290499e+00 3.2425499e+00 3.2560501e+00 + 3.2695501e+00 3.2830501e+00 3.2965500e+00 3.3100500e+00 + 3.3235500e+00 3.3370500e+00 3.3505499e+00 3.3640499e+00 + 3.3775499e+00 3.3910501e+00 3.4045501e+00 3.4180501e+00 + 3.4315500e+00 3.4450500e+00 3.4585500e+00 3.4720500e+00 + 3.4855499e+00 3.4990499e+00 3.5125501e+00 3.5260501e+00 + 3.5395501e+00 3.5530500e+00 3.5665500e+00 3.5800500e+00 + 3.5935500e+00 3.6070499e+00 3.6205499e+00 3.6340499e+00 + 3.6475501e+00 3.6610501e+00 3.6745501e+00 3.6880500e+00 + 3.7015500e+00 3.7150500e+00 3.7285500e+00 3.7420499e+00 + 3.7555499e+00 3.7690499e+00 3.7825501e+00 3.7960501e+00 + 3.8095500e+00 3.8230500e+00 3.8365500e+00 3.8500500e+00 + 3.8635499e+00 3.8770499e+00 3.8905499e+00 3.9040501e+00 + 3.9175501e+00 3.9310501e+00 3.9445500e+00 3.9580500e+00 + 3.9715500e+00 3.9850500e+00 3.9985499e+00 4.0120502e+00 + 4.0255499e+00 4.0390501e+00 4.0525498e+00 4.0660501e+00 + 4.0795498e+00 4.0930500e+00 4.1065502e+00 4.1200500e+00 + 4.1335502e+00 4.1470499e+00 4.1605501e+00 4.1740499e+00 + 4.1875501e+00 4.2010498e+00 4.2145500e+00 4.2280502e+00 + 4.2415500e+00 4.2550502e+00 4.2685499e+00 4.2820501e+00 + 4.2955499e+00 4.3090501e+00 4.3225498e+00 4.3360500e+00 + 4.3495498e+00 4.3630500e+00 4.3765502e+00 4.3900499e+00 + 4.4035501e+00 4.4170499e+00 4.4305501e+00 4.4440498e+00 + 4.4575500e+00 4.4710498e+00 4.4845500e+00 4.4980502e+00 + 4.5115499e+00 4.5250502e+00 4.5385499e+00 4.5520501e+00 + 4.5655499e+00 4.5790501e+00 4.5925498e+00 4.6060500e+00 + 4.6195502e+00 4.6330500e+00 4.6465502e+00 4.6600499e+00 + 4.6735501e+00 4.6870499e+00 4.7005501e+00 4.7140498e+00 + 4.7275500e+00 4.7410498e+00 4.7545500e+00 4.7680502e+00 + 4.7815499e+00 4.7950501e+00 4.8085499e+00 4.8220501e+00 + 4.8355498e+00 4.8490500e+00 4.8625498e+00 4.8760500e+00 + 4.8895502e+00 4.9030499e+00 4.9165502e+00 4.9300499e+00 + 4.9435501e+00 4.9570498e+00 4.9705501e+00 4.9840498e+00 + 4.9975500e+00 5.0110502e+00 5.0245500e+00 5.0380502e+00 + 5.0515499e+00 5.0650501e+00 5.0785499e+00 5.0920501e+00 + 5.1055498e+00 5.1190500e+00 5.1325498e+00 5.1460500e+00 + 5.1595502e+00 5.1730499e+00 5.1865501e+00 5.2000499e+00 + 5.2135501e+00 5.2270498e+00 5.2405500e+00 5.2540498e+00 + 5.2675500e+00 5.2810502e+00 5.2945499e+00 5.3080502e+00 + 5.3215499e+00 5.3350501e+00 5.3485498e+00 5.3620501e+00 + 5.3755498e+00 5.3890500e+00 5.4025502e+00 5.4160500e+00 + 5.4295502e+00 5.4430499e+00 5.4565501e+00 5.4700499e+00 + 5.4835501e+00 5.4970498e+00 5.5105500e+00 5.5240502e+00 + 5.5375500e+00 5.5510502e+00 5.5645499e+00 5.5780501e+00 + 5.5915499e+00 5.6050501e+00 5.6185498e+00 5.6320500e+00 + 5.6455498e+00 5.6590500e+00 5.6725502e+00 5.6860499e+00 + 5.6995502e+00 5.7130499e+00 5.7265501e+00 5.7400498e+00 + 5.7535501e+00 5.7670498e+00 5.7805500e+00 5.7940502e+00 + 5.8075500e+00 5.8210502e+00 5.8345499e+00 5.8480501e+00 + 5.8615499e+00 5.8750501e+00 5.8885498e+00 5.9020500e+00 + 5.9155502e+00 5.9290500e+00 5.9425502e+00 5.9560499e+00 + 5.9695501e+00 5.9830499e+00 5.9965501e+00 6.0100498e+00 + 6.0235500e+00 6.0370498e+00 6.0505500e+00 6.0640502e+00 + 6.0775499e+00 6.0910501e+00 6.1045499e+00 6.1180501e+00 + 6.1315498e+00 6.1450500e+00 6.1585498e+00 6.1720500e+00 + 6.1855502e+00 6.1990499e+00 6.2125502e+00 6.2260499e+00 + 6.2395501e+00 6.2530499e+00 6.2665501e+00 6.2800498e+00 + 6.2935500e+00 6.3070502e+00 6.3205500e+00 6.3340502e+00 + 6.3475499e+00 6.3610501e+00 6.3745499e+00 6.3880501e+00 + 6.4015498e+00 6.4150500e+00 6.4285498e+00 6.4420500e+00 + 6.4555502e+00 6.4690499e+00 6.4825501e+00 6.4960499e+00 + 6.5095501e+00 6.5230498e+00 6.5365500e+00 6.5500498e+00 + 6.5635500e+00 6.5770502e+00 6.5905499e+00 6.6040502e+00 + 6.6175499e+00 6.6310501e+00 6.6445498e+00 6.6580501e+00 + 6.6715498e+00 6.6850500e+00 6.6985502e+00 6.7120500e+00 + 6.7255502e+00 6.7390499e+00 6.7525501e+00 6.7660499e+00 + 6.7795501e+00 6.7930498e+00 6.8065500e+00 6.8200498e+00 + 6.8335500e+00 6.8470502e+00 6.8605499e+00 6.8740501e+00 + 6.8875499e+00 6.9010501e+00 6.9145498e+00 6.9280500e+00 + 6.9415498e+00 6.9550500e+00 6.9685502e+00 6.9820499e+00 + 6.9955502e+00 7.0090499e+00 7.0225501e+00 7.0360498e+00 + 7.0495501e+00 7.0630498e+00 7.0765500e+00 7.0900502e+00 + 7.1035500e+00 7.1170502e+00 7.1305499e+00 7.1440501e+00 + 7.1578269e+00 7.1721697e+00 7.1871009e+00 7.2026453e+00 + 7.2188272e+00 7.2356739e+00 7.2532115e+00 7.2714696e+00 + 7.2904768e+00 7.3102641e+00 7.3308635e+00 7.3523088e+00 + 7.3746343e+00 7.3978763e+00 7.4220719e+00 7.4472609e+00 + 7.4734836e+00 7.5007830e+00 7.5292029e+00 7.5587893e+00 + 7.5895901e+00 7.6233001e+00 7.6592999e+00 7.6953001e+00 + 7.7312999e+00 7.7673001e+00 7.8032999e+00 7.8393002e+00 + 7.8752999e+00 7.9113002e+00 7.9473000e+00 7.9833002e+00 + 8.0193005e+00 8.0552998e+00 8.0913000e+00 8.1273003e+00 + 8.1632996e+00 8.1992998e+00 8.2353001e+00 8.2713003e+00 + 8.3072996e+00 8.3432999e+00 8.3793001e+00 8.4153004e+00 + 8.4512997e+00 8.4872999e+00 8.5233002e+00 8.5593004e+00 + 8.5952997e+00 8.6313000e+00 8.6673002e+00 8.7033005e+00 + 8.7392998e+00 8.7753000e+00 8.8113003e+00 8.8472996e+00 + 8.8832998e+00 8.9193001e+00 8.9553003e+00 8.9912996e+00] , PP Field lbyr: 2010 lbmon: 2 @@ -2455,1158 +2203,1032 @@ bdy: 0.0 bzx: 0.0 bdx: 0.0 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 100054. 100054. 100054. ..., 100979. 100982. 100983.] - [ 100054. 100054. 100054. ..., 100982. 100984. 100984.] - [ 100054. 100054. 100054. ..., 100984. 100987. 100986.] - ..., - [ 102198. 102205. 102212. ..., 101691. 101664. 101661.] - [ 102204. 102211. 102218. ..., 101693. 101673. 101668.] - [ 102210. 102217. 102225. ..., 101705. 101682. 101675.]] - x: [ 353.05249023 353.08850098 353.12451172 353.16049194 353.19650269 - 353.23251343 353.26849365 353.30450439 353.34051514 353.37649536 - 353.4125061 353.44848633 353.48449707 353.52050781 353.55648804 - 353.59249878 353.62850952 353.66448975 353.70050049 353.73651123 - 353.77249146 353.8085022 353.84451294 353.88049316 353.91650391 - 353.95251465 353.98849487 354.02450562 354.06048584 354.09649658 - 354.13250732 354.16848755 354.20449829 354.24050903 354.27648926 - 354.3125 354.34851074 354.38449097 354.42050171 354.45651245 - 354.49249268 354.52185059 354.55010986 354.57736206 354.6036377 - 354.62893677 354.65332031 354.67684937 354.69949341 354.72131348 - 354.74234009 354.76263428 354.78216553 354.80099487 354.81915283 - 354.8366394 354.85348511 354.86972046 354.88537598 354.90045166 - 354.91497803 354.9289856 354.94250488 354.95599365 354.96951294 - 354.98300171 354.99649048 355.01000977 355.02349854 355.0369873 - 355.05050659 355.06399536 355.07751465 355.09100342 355.10449219 - 355.11801147 355.13150024 355.14498901 355.1585083 355.17199707 - 355.18548584 355.19900513 355.2124939 355.22601318 355.23950195 - 355.25299072 355.26651001 355.27999878 355.29348755 355.30700684 - 355.32049561 355.33401489 355.34750366 355.36099243 355.37451172 - 355.38800049 355.40148926 355.41500854 355.42849731 355.44198608 - 355.45550537 355.46899414 355.48251343 355.4960022 355.50949097 - 355.52301025 355.53649902 355.54998779 355.56350708 355.57699585 - 355.59051514 355.60400391 355.61749268 355.63101196 355.64450073 - 355.6579895 355.67150879 355.68499756 355.69848633 355.71200562 - 355.72549438 355.73901367 355.75250244 355.76599121 355.7795105 - 355.79299927 355.80648804 355.82000732 355.83349609 355.84698486 - 355.86050415 355.87399292 355.88751221 355.90100098 355.91448975 - 355.92800903 355.9414978 355.95498657 355.96850586 355.98199463 - 355.99551392 356.00900269 356.02249146 356.03601074 356.04949951 - 356.06298828 356.07650757 356.08999634 356.10348511 356.11700439 - 356.13049316 356.14401245 356.15750122 356.17098999 356.18450928 - 356.19799805 356.21148682 356.2250061 356.23849487 356.25201416 - 356.26550293 356.2789917 356.29251099 356.30599976 356.31948853 - 356.33300781 356.34649658 356.35998535 356.37350464 356.38699341 - 356.4005127 356.41400146 356.42749023 356.44100952 356.45449829 - 356.46798706 356.48150635 356.49499512 356.5085144 356.52200317 - 356.53549194 356.54901123 356.5625 356.57598877 356.58950806 - 356.60299683 356.6164856 356.63000488 356.64349365 356.65701294 - 356.67050171 356.68399048 356.69750977 356.71099854 356.7244873 - 356.73800659 356.75149536 356.76501465 356.77850342 356.79199219 - 356.80551147 356.81900024 356.83248901 356.8460083 356.85949707 - 356.87298584 356.88650513 356.8999939 356.91351318 356.92700195 - 356.94049072 356.95401001 356.96749878 356.98098755 356.99450684 - 357.00799561 357.02151489 357.03500366 357.04849243 357.06201172 - 357.07550049 357.08898926 357.10250854 357.11599731 357.12948608 - 357.14300537 357.15649414 357.17001343 357.1835022 357.19699097 - 357.21051025 357.22399902 357.23748779 357.25100708 357.26449585 - 357.27801514 357.29150391 357.30499268 357.31851196 357.33200073 - 357.3454895 357.35900879 357.37249756 357.38598633 357.39950562 - 357.41299438 357.42651367 357.44000244 357.45349121 357.4670105 - 357.48049927 357.49398804 357.50750732 357.52099609 357.53448486 - 357.54800415 357.56149292 357.57501221 357.58850098 357.60198975 - 357.61550903 357.6289978 357.64248657 357.65600586 357.66949463 - 357.68301392 357.69650269 357.70999146 357.72351074 357.73699951 - 357.75048828 357.76400757 357.77749634 357.79098511 357.80450439 - 357.81799316 357.83151245 357.84500122 357.85848999 357.87200928 - 357.88549805 357.89898682 357.9125061 357.92599487 357.93951416 - 357.95300293 357.9664917 357.98001099 357.99349976 358.00698853 - 358.02050781 358.03399658 358.04748535 358.06100464 358.07449341 - 358.0880127 358.10150146 358.11499023 358.12850952 358.14199829 - 358.15548706 358.16900635 358.18249512 358.1960144 358.20950317 - 358.22299194 358.23651123 358.25 358.26348877 358.27700806 - 358.29049683 358.3039856 358.31750488 358.33099365 358.34451294 - 358.35800171 358.37149048 358.38500977 358.39849854 358.4119873 - 358.42550659 358.43899536 358.45251465 358.46600342 358.47949219 - 358.49301147 358.50650024 358.51998901 358.5335083 358.54699707 - 358.56048584 358.57400513 358.5874939 358.60101318 358.61450195 - 358.62799072 358.64151001 358.65499878 358.66848755 358.68200684 - 358.69549561 358.70901489 358.72250366 358.73599243 358.74951172 - 358.76300049 358.77648926 358.79000854 358.80349731 358.81698608 - 358.83050537 358.84399414 358.85751343 358.8710022 358.88449097 - 358.89801025 358.91149902 358.92498779 358.93850708 358.95199585 - 358.96551514 358.97900391 358.99249268 359.00601196 359.01950073 - 359.0329895 359.04650879 359.05999756 359.07348633 359.08700562 - 359.10049438 359.11401367 359.12750244 359.14099121 359.1545105 - 359.16799927 359.18148804 359.19500732 359.20849609 359.22198486 - 359.23550415 359.24899292 359.26251221 359.27600098 359.28948975 - 359.30300903 359.3164978 359.32998657 359.34350586 359.35699463 - 359.37051392 359.38400269 359.39749146 359.41101074 359.42449951 - 359.43798828 359.45150757 359.46499634 359.47848511 359.49200439 - 359.50549316 359.51901245 359.53250122 359.54598999 359.55950928 - 359.57299805 359.58648682 359.6000061 359.61349487 359.62701416 - 359.64050293 359.6539917 359.66751099 359.68099976 359.69448853 - 359.70800781 359.72149658 359.73498535 359.74850464 359.76199341 - 359.7755127 359.78900146 359.80249023 359.81600952 359.82949829 - 359.84298706 359.85650635 359.86999512 359.8835144 359.89700317 - 359.91049194 359.92401123 359.9375 359.95098877 359.96450806 - 359.97799683 359.9914856 360.00500488 360.01849365 360.03201294 - 360.04550171 360.05899048 360.07250977 360.08599854 360.0994873 - 360.11300659 360.12649536 360.14001465 360.15350342 360.16699219 - 360.18051147 360.19400024 360.20748901 360.2210083 360.23449707 - 360.24798584 360.26150513 360.2749939 360.28851318 360.30200195 - 360.31549072 360.32901001 360.34249878 360.35598755 360.36950684 - 360.38299561 360.39651489 360.41000366 360.42349243 360.43701172 - 360.45050049 360.46398926 360.47750854 360.49099731 360.50448608 - 360.51800537 360.53149414 360.54501343 360.5585022 360.57199097 - 360.58551025 360.59899902 360.61248779 360.62600708 360.63949585 - 360.65301514 360.66650391 360.67999268 360.69351196 360.70700073 - 360.7204895 360.73400879 360.74749756 360.76098633 360.77450562 - 360.78799438 360.80151367 360.81500244 360.82849121 360.8420105 - 360.85549927 360.86898804 360.88250732 360.89599609 360.90948486 - 360.92300415 360.93649292 360.95001221 360.96350098 360.97698975 - 360.99050903 361.0039978 361.01748657 361.03100586 361.04449463 - 361.05801392 361.07150269 361.08499146 361.09851074 361.11199951 - 361.12548828 361.13900757 361.15249634 361.16598511 361.17950439 - 361.19299316 361.20651245 361.22000122 361.23348999 361.24700928 - 361.26049805 361.27398682 361.2875061 361.30099487 361.31451416 - 361.32800293 361.3414917 361.35501099 361.36849976 361.38198853 - 361.39550781 361.40899658 361.42248535 361.43600464 361.44949341 - 361.4630127 361.47650146 361.48999023 361.50350952 361.51699829 - 361.53048706 361.54400635 361.55749512 361.5710144 361.58450317 - 361.59799194 361.61151123 361.625 361.63848877 361.65200806 - 361.66549683 361.6789856 361.69250488 361.70599365 361.71951294 - 361.73300171 361.74649048 361.76000977 361.77349854 361.7869873 - 361.80050659 361.81399536 361.82751465 361.84100342 361.85449219 - 361.86801147 361.88150024 361.89498901 361.9085083 361.92199707 - 361.93548584 361.94900513 361.9624939 361.97601318 361.98950195 - 362.00299072 362.01651001 362.02999878 362.04348755 362.05700684 - 362.07049561 362.08401489 362.09750366 362.11099243 362.12451172 - 362.13800049 362.15148926 362.16500854 362.17849731 362.19198608 - 362.20550537 362.21899414 362.23251343 362.2460022 362.25949097 - 362.27301025 362.28649902 362.29998779 362.31350708 362.32699585 - 362.34051514 362.35400391 362.36749268 362.38101196 362.39450073 - 362.4079895 362.42150879 362.43499756 362.44848633 362.46200562 - 362.47549438 362.48901367 362.50250244 362.51599121 362.5295105 - 362.54299927 362.55648804 362.57000732 362.58349609 362.59698486 - 362.61050415 362.62399292 362.63751221 362.65100098 362.66448975 - 362.67800903 362.6914978 362.70498657 362.71850586 362.73199463 - 362.74551392 362.75900269 362.77249146 362.78601074 362.79949951 - 362.81298828 362.82650757 362.83999634 362.85348511 362.86700439 - 362.88049316 362.89401245 362.90750122 362.92098999 362.93450928 - 362.94799805 362.96148682 362.9750061 362.98849487 363.00201416 - 363.01550293 363.0289917 363.04251099 363.05599976 363.06948853 - 363.08300781 363.09649658 363.10998535 363.12350464 363.13699341 - 363.1505127 363.16400146 363.17749023 363.19100952 363.20449829 - 363.21798706 363.23150635 363.24499512 363.2585144 363.27200317 - 363.28549194 363.29901123 363.3125 363.32650757 363.34103394 - 363.35614014 363.37176514 363.38803101 363.40487671 363.42236328 - 363.44049072 363.45932007 363.47888184 363.49914551 363.52017212 - 363.54202271 363.56466675 363.58816528 363.61254883 363.63787842 - 363.66412354 363.69137573 363.71966553 363.74899292 363.78500366 - 363.8210144 363.85699463 363.89300537 363.9289856 363.96499634 - 364.00100708 364.0369873 364.07299805 364.10900879 364.14498901 - 364.18099976 364.2170105 364.25299072 364.28900146 364.32501221 - 364.36099243 364.39700317 364.43301392 364.46899414 364.50500488 - 364.54098511 364.57699585 364.61300659 364.64898682 364.68499756 - 364.7210083 364.75698853 364.79299927 364.82901001 364.86499023 - 364.90100098 364.93701172 364.97299194 365.00900269 365.04501343 - 365.08099365 365.11700439 365.15301514 365.18899536] - x_lower_bound: [ 353.03448486 353.07049561 353.10650635 353.14248657 353.17849731 - 353.21450806 353.25048828 353.28649902 353.32250977 353.35848999 - 353.39450073 353.43051147 353.4664917 353.50250244 353.53851318 - 353.57449341 353.61050415 353.64651489 353.68249512 353.71850586 - 353.75448608 353.79049683 353.82650757 353.86248779 353.89849854 - 353.93450928 353.9704895 354.00650024 354.04251099 354.07849121 - 354.11450195 354.1505127 354.18649292 354.22250366 354.2585144 - 354.29449463 354.33050537 354.3664856 354.40249634 354.43850708 - 354.4744873 354.50717163 354.53598022 354.56375122 354.59051514 - 354.61627197 354.6411438 354.66506958 354.68817139 354.71038818 - 354.73184204 354.75250244 354.7723999 354.79159546 354.81005859 - 354.82788086 354.84506226 354.86160278 354.87753296 354.89291382 - 354.90771484 354.92199707 354.9357605 354.94924927 354.96273804 - 354.97625732 354.98974609 355.00323486 355.01675415 355.03024292 - 355.04376221 355.05725098 355.07073975 355.08425903 355.0977478 - 355.11123657 355.12475586 355.13824463 355.15176392 355.16525269 - 355.17874146 355.19226074 355.20574951 355.21923828 355.23275757 - 355.24624634 355.25973511 355.27325439 355.28674316 355.30026245 - 355.31375122 355.32723999 355.34075928 355.35424805 355.36773682 - 355.3812561 355.39474487 355.40826416 355.42175293 355.4352417 - 355.44876099 355.46224976 355.47573853 355.48925781 355.50274658 - 355.51623535 355.52975464 355.54324341 355.5567627 355.57025146 - 355.58374023 355.59725952 355.61074829 355.62423706 355.63775635 - 355.65124512 355.6647644 355.67825317 355.69174194 355.70526123 - 355.71875 355.73223877 355.74575806 355.75924683 355.7727356 - 355.78625488 355.79974365 355.81326294 355.82675171 355.84024048 - 355.85375977 355.86724854 355.8807373 355.89425659 355.90774536 - 355.92126465 355.93475342 355.94824219 355.96176147 355.97525024 - 355.98873901 356.0022583 356.01574707 356.02923584 356.04275513 - 356.0562439 356.06976318 356.08325195 356.09674072 356.11026001 - 356.12374878 356.13723755 356.15075684 356.16424561 356.17776489 - 356.19125366 356.20474243 356.21826172 356.23175049 356.24523926 - 356.25875854 356.27224731 356.28573608 356.29925537 356.31274414 - 356.32626343 356.3397522 356.35324097 356.36676025 356.38024902 - 356.39373779 356.40725708 356.42074585 356.43426514 356.44775391 - 356.46124268 356.47476196 356.48825073 356.5017395 356.51525879 - 356.52874756 356.54223633 356.55575562 356.56924438 356.58276367 - 356.59625244 356.60974121 356.6232605 356.63674927 356.65023804 - 356.66375732 356.67724609 356.69073486 356.70425415 356.71774292 - 356.73126221 356.74475098 356.75823975 356.77175903 356.7852478 - 356.79873657 356.81225586 356.82574463 356.83926392 356.85275269 - 356.86624146 356.87976074 356.89324951 356.90673828 356.92025757 - 356.93374634 356.94723511 356.96075439 356.97424316 356.98776245 - 357.00125122 357.01473999 357.02825928 357.04174805 357.05523682 - 357.0687561 357.08224487 357.09576416 357.10925293 357.1227417 - 357.13626099 357.14974976 357.16323853 357.17675781 357.19024658 - 357.20373535 357.21725464 357.23074341 357.2442627 357.25775146 - 357.27124023 357.28475952 357.29824829 357.31173706 357.32525635 - 357.33874512 357.3522644 357.36575317 357.37924194 357.39276123 - 357.40625 357.41973877 357.43325806 357.44674683 357.4602356 - 357.47375488 357.48724365 357.50076294 357.51425171 357.52774048 - 357.54125977 357.55474854 357.5682373 357.58175659 357.59524536 - 357.60876465 357.62225342 357.63574219 357.64926147 357.66275024 - 357.67623901 357.6897583 357.70324707 357.71673584 357.73025513 - 357.7437439 357.75726318 357.77075195 357.78424072 357.79776001 - 357.81124878 357.82473755 357.83825684 357.85174561 357.86526489 - 357.87875366 357.89224243 357.90576172 357.91925049 357.93273926 - 357.94625854 357.95974731 357.97323608 357.98675537 358.00024414 - 358.01376343 358.0272522 358.04074097 358.05426025 358.06774902 - 358.08123779 358.09475708 358.10824585 358.12176514 358.13525391 - 358.14874268 358.16226196 358.17575073 358.1892395 358.20275879 - 358.21624756 358.22973633 358.24325562 358.25674438 358.27026367 - 358.28375244 358.29724121 358.3107605 358.32424927 358.33773804 - 358.35125732 358.36474609 358.37823486 358.39175415 358.40524292 - 358.41876221 358.43225098 358.44573975 358.45925903 358.4727478 - 358.48623657 358.49975586 358.51324463 358.52676392 358.54025269 - 358.55374146 358.56726074 358.58074951 358.59423828 358.60775757 - 358.62124634 358.63473511 358.64825439 358.66174316 358.67526245 - 358.68875122 358.70223999 358.71575928 358.72924805 358.74273682 - 358.7562561 358.76974487 358.78326416 358.79675293 358.8102417 - 358.82376099 358.83724976 358.85073853 358.86425781 358.87774658 - 358.89123535 358.90475464 358.91824341 358.9317627 358.94525146 - 358.95874023 358.97225952 358.98574829 358.99923706 359.01275635 - 359.02624512 359.0397644 359.05325317 359.06674194 359.08026123 - 359.09375 359.10723877 359.12075806 359.13424683 359.1477356 - 359.16125488 359.17474365 359.18826294 359.20175171 359.21524048 - 359.22875977 359.24224854 359.2557373 359.26925659 359.28274536 - 359.29626465 359.30975342 359.32324219 359.33676147 359.35025024 - 359.36373901 359.3772583 359.39074707 359.40423584 359.41775513 - 359.4312439 359.44476318 359.45825195 359.47174072 359.48526001 - 359.49874878 359.51223755 359.52575684 359.53924561 359.55276489 - 359.56625366 359.57974243 359.59326172 359.60675049 359.62023926 - 359.63375854 359.64724731 359.66073608 359.67425537 359.68774414 - 359.70126343 359.7147522 359.72824097 359.74176025 359.75524902 - 359.76873779 359.78225708 359.79574585 359.80926514 359.82275391 - 359.83624268 359.84976196 359.86325073 359.8767395 359.89025879 - 359.90374756 359.91723633 359.93075562 359.94424438 359.95776367 - 359.97125244 359.98474121 359.9982605 360.01174927 360.02523804 - 360.03875732 360.05224609 360.06573486 360.07925415 360.09274292 - 360.10626221 360.11975098 360.13323975 360.14675903 360.1602478 - 360.17373657 360.18725586 360.20074463 360.21426392 360.22775269 - 360.24124146 360.25476074 360.26824951 360.28173828 360.29525757 - 360.30874634 360.32223511 360.33575439 360.34924316 360.36276245 - 360.37625122 360.38973999 360.40325928 360.41674805 360.43023682 - 360.4437561 360.45724487 360.47076416 360.48425293 360.4977417 - 360.51126099 360.52474976 360.53823853 360.55175781 360.56524658 - 360.57873535 360.59225464 360.60574341 360.6192627 360.63275146 - 360.64624023 360.65975952 360.67324829 360.68673706 360.70025635 - 360.71374512 360.7272644 360.74075317 360.75424194 360.76776123 - 360.78125 360.79473877 360.80825806 360.82174683 360.8352356 - 360.84875488 360.86224365 360.87576294 360.88925171 360.90274048 - 360.91625977 360.92974854 360.9432373 360.95675659 360.97024536 - 360.98376465 360.99725342 361.01074219 361.02426147 361.03775024 - 361.05123901 361.0647583 361.07824707 361.09173584 361.10525513 - 361.1187439 361.13226318 361.14575195 361.15924072 361.17276001 - 361.18624878 361.19973755 361.21325684 361.22674561 361.24026489 - 361.25375366 361.26724243 361.28076172 361.29425049 361.30773926 - 361.32125854 361.33474731 361.34823608 361.36175537 361.37524414 - 361.38876343 361.4022522 361.41574097 361.42926025 361.44274902 - 361.45623779 361.46975708 361.48324585 361.49676514 361.51025391 - 361.52374268 361.53726196 361.55075073 361.5642395 361.57775879 - 361.59124756 361.60473633 361.61825562 361.63174438 361.64526367 - 361.65875244 361.67224121 361.6857605 361.69924927 361.71273804 - 361.72625732 361.73974609 361.75323486 361.76675415 361.78024292 - 361.79376221 361.80725098 361.82073975 361.83425903 361.8477478 - 361.86123657 361.87475586 361.88824463 361.90176392 361.91525269 - 361.92874146 361.94226074 361.95574951 361.96923828 361.98275757 - 361.99624634 362.00973511 362.02325439 362.03674316 362.05026245 - 362.06375122 362.07723999 362.09075928 362.10424805 362.11773682 - 362.1312561 362.14474487 362.15826416 362.17175293 362.1852417 - 362.19876099 362.21224976 362.22573853 362.23925781 362.25274658 - 362.26623535 362.27975464 362.29324341 362.3067627 362.32025146 - 362.33374023 362.34725952 362.36074829 362.37423706 362.38775635 - 362.40124512 362.4147644 362.42825317 362.44174194 362.45526123 - 362.46875 362.48223877 362.49575806 362.50924683 362.5227356 - 362.53625488 362.54974365 362.56326294 362.57675171 362.59024048 - 362.60375977 362.61724854 362.6307373 362.64425659 362.65774536 - 362.67126465 362.68475342 362.69824219 362.71176147 362.72525024 - 362.73873901 362.7522583 362.76574707 362.77923584 362.79275513 - 362.8062439 362.81976318 362.83325195 362.84674072 362.86026001 - 362.87374878 362.88723755 362.90075684 362.91424561 362.92776489 - 362.94125366 362.95474243 362.96826172 362.98175049 362.99523926 - 363.00875854 363.02224731 363.03573608 363.04925537 363.06274414 - 363.07626343 363.0897522 363.10324097 363.11676025 363.13024902 - 363.14373779 363.15725708 363.17074585 363.18426514 363.19775391 - 363.21124268 363.22476196 363.23825073 363.2517395 363.26525879 - 363.27874756 363.29223633 363.30575562 363.31951904 363.33377075 - 363.34857178 363.36395264 363.37991333 363.39645386 363.41360474 - 363.431427 363.44992065 363.46911621 363.48901367 363.50967407 - 363.53109741 363.55334473 363.57641602 363.60037231 363.62521362 - 363.65100098 363.67776489 363.70550537 363.73431396 363.76699829 - 363.80300903 363.83898926 363.875 363.91101074 363.94699097 - 363.98300171 364.01901245 364.05499268 364.09100342 364.12701416 - 364.16299438 364.19900513 364.23498535 364.27099609 364.30700684 - 364.34298706 364.3789978 364.41500854 364.45098877 364.48699951 - 364.52301025 364.55899048 364.59500122 364.63101196 364.66699219 - 364.70300293 364.73901367 364.7749939 364.81100464 364.84698486 - 364.88299561 364.91900635 364.95498657 364.99099731 365.02700806 - 365.06298828 365.09899902 365.13500977 365.17098999] - x_upper_bound: [ 353.07049561 353.10650635 353.14248657 353.17849731 353.21450806 - 353.25048828 353.28649902 353.32250977 353.35848999 353.39450073 - 353.43051147 353.4664917 353.50250244 353.53851318 353.57449341 - 353.61050415 353.64651489 353.68249512 353.71850586 353.75448608 - 353.79049683 353.82650757 353.86248779 353.89849854 353.93450928 - 353.9704895 354.00650024 354.04251099 354.07849121 354.11450195 - 354.1505127 354.18649292 354.22250366 354.2585144 354.29449463 - 354.33050537 354.3664856 354.40249634 354.43850708 354.4744873 - 354.50717163 354.53598022 354.56375122 354.59051514 354.61627197 - 354.6411438 354.66506958 354.68817139 354.71038818 354.73184204 - 354.75250244 354.7723999 354.79159546 354.81005859 354.82788086 - 354.84506226 354.86160278 354.87753296 354.89291382 354.90771484 - 354.92199707 354.9357605 354.94924927 354.96273804 354.97625732 - 354.98974609 355.00323486 355.01675415 355.03024292 355.04376221 - 355.05725098 355.07073975 355.08425903 355.0977478 355.11123657 - 355.12475586 355.13824463 355.15176392 355.16525269 355.17874146 - 355.19226074 355.20574951 355.21923828 355.23275757 355.24624634 - 355.25973511 355.27325439 355.28674316 355.30026245 355.31375122 - 355.32723999 355.34075928 355.35424805 355.36773682 355.3812561 - 355.39474487 355.40826416 355.42175293 355.4352417 355.44876099 - 355.46224976 355.47573853 355.48925781 355.50274658 355.51623535 - 355.52975464 355.54324341 355.5567627 355.57025146 355.58374023 - 355.59725952 355.61074829 355.62423706 355.63775635 355.65124512 - 355.6647644 355.67825317 355.69174194 355.70526123 355.71875 - 355.73223877 355.74575806 355.75924683 355.7727356 355.78625488 - 355.79974365 355.81326294 355.82675171 355.84024048 355.85375977 - 355.86724854 355.8807373 355.89425659 355.90774536 355.92126465 - 355.93475342 355.94824219 355.96176147 355.97525024 355.98873901 - 356.0022583 356.01574707 356.02923584 356.04275513 356.0562439 - 356.06976318 356.08325195 356.09674072 356.11026001 356.12374878 - 356.13723755 356.15075684 356.16424561 356.17776489 356.19125366 - 356.20474243 356.21826172 356.23175049 356.24523926 356.25875854 - 356.27224731 356.28573608 356.29925537 356.31274414 356.32626343 - 356.3397522 356.35324097 356.36676025 356.38024902 356.39373779 - 356.40725708 356.42074585 356.43426514 356.44775391 356.46124268 - 356.47476196 356.48825073 356.5017395 356.51525879 356.52874756 - 356.54223633 356.55575562 356.56924438 356.58276367 356.59625244 - 356.60974121 356.6232605 356.63674927 356.65023804 356.66375732 - 356.67724609 356.69073486 356.70425415 356.71774292 356.73126221 - 356.74475098 356.75823975 356.77175903 356.7852478 356.79873657 - 356.81225586 356.82574463 356.83926392 356.85275269 356.86624146 - 356.87976074 356.89324951 356.90673828 356.92025757 356.93374634 - 356.94723511 356.96075439 356.97424316 356.98776245 357.00125122 - 357.01473999 357.02825928 357.04174805 357.05523682 357.0687561 - 357.08224487 357.09576416 357.10925293 357.1227417 357.13626099 - 357.14974976 357.16323853 357.17675781 357.19024658 357.20373535 - 357.21725464 357.23074341 357.2442627 357.25775146 357.27124023 - 357.28475952 357.29824829 357.31173706 357.32525635 357.33874512 - 357.3522644 357.36575317 357.37924194 357.39276123 357.40625 - 357.41973877 357.43325806 357.44674683 357.4602356 357.47375488 - 357.48724365 357.50076294 357.51425171 357.52774048 357.54125977 - 357.55474854 357.5682373 357.58175659 357.59524536 357.60876465 - 357.62225342 357.63574219 357.64926147 357.66275024 357.67623901 - 357.6897583 357.70324707 357.71673584 357.73025513 357.7437439 - 357.75726318 357.77075195 357.78424072 357.79776001 357.81124878 - 357.82473755 357.83825684 357.85174561 357.86526489 357.87875366 - 357.89224243 357.90576172 357.91925049 357.93273926 357.94625854 - 357.95974731 357.97323608 357.98675537 358.00024414 358.01376343 - 358.0272522 358.04074097 358.05426025 358.06774902 358.08123779 - 358.09475708 358.10824585 358.12176514 358.13525391 358.14874268 - 358.16226196 358.17575073 358.1892395 358.20275879 358.21624756 - 358.22973633 358.24325562 358.25674438 358.27026367 358.28375244 - 358.29724121 358.3107605 358.32424927 358.33773804 358.35125732 - 358.36474609 358.37823486 358.39175415 358.40524292 358.41876221 - 358.43225098 358.44573975 358.45925903 358.4727478 358.48623657 - 358.49975586 358.51324463 358.52676392 358.54025269 358.55374146 - 358.56726074 358.58074951 358.59423828 358.60775757 358.62124634 - 358.63473511 358.64825439 358.66174316 358.67526245 358.68875122 - 358.70223999 358.71575928 358.72924805 358.74273682 358.7562561 - 358.76974487 358.78326416 358.79675293 358.8102417 358.82376099 - 358.83724976 358.85073853 358.86425781 358.87774658 358.89123535 - 358.90475464 358.91824341 358.9317627 358.94525146 358.95874023 - 358.97225952 358.98574829 358.99923706 359.01275635 359.02624512 - 359.0397644 359.05325317 359.06674194 359.08026123 359.09375 - 359.10723877 359.12075806 359.13424683 359.1477356 359.16125488 - 359.17474365 359.18826294 359.20175171 359.21524048 359.22875977 - 359.24224854 359.2557373 359.26925659 359.28274536 359.29626465 - 359.30975342 359.32324219 359.33676147 359.35025024 359.36373901 - 359.3772583 359.39074707 359.40423584 359.41775513 359.4312439 - 359.44476318 359.45825195 359.47174072 359.48526001 359.49874878 - 359.51223755 359.52575684 359.53924561 359.55276489 359.56625366 - 359.57974243 359.59326172 359.60675049 359.62023926 359.63375854 - 359.64724731 359.66073608 359.67425537 359.68774414 359.70126343 - 359.7147522 359.72824097 359.74176025 359.75524902 359.76873779 - 359.78225708 359.79574585 359.80926514 359.82275391 359.83624268 - 359.84976196 359.86325073 359.8767395 359.89025879 359.90374756 - 359.91723633 359.93075562 359.94424438 359.95776367 359.97125244 - 359.98474121 359.9982605 360.01174927 360.02523804 360.03875732 - 360.05224609 360.06573486 360.07925415 360.09274292 360.10626221 - 360.11975098 360.13323975 360.14675903 360.1602478 360.17373657 - 360.18725586 360.20074463 360.21426392 360.22775269 360.24124146 - 360.25476074 360.26824951 360.28173828 360.29525757 360.30874634 - 360.32223511 360.33575439 360.34924316 360.36276245 360.37625122 - 360.38973999 360.40325928 360.41674805 360.43023682 360.4437561 - 360.45724487 360.47076416 360.48425293 360.4977417 360.51126099 - 360.52474976 360.53823853 360.55175781 360.56524658 360.57873535 - 360.59225464 360.60574341 360.6192627 360.63275146 360.64624023 - 360.65975952 360.67324829 360.68673706 360.70025635 360.71374512 - 360.7272644 360.74075317 360.75424194 360.76776123 360.78125 - 360.79473877 360.80825806 360.82174683 360.8352356 360.84875488 - 360.86224365 360.87576294 360.88925171 360.90274048 360.91625977 - 360.92974854 360.9432373 360.95675659 360.97024536 360.98376465 - 360.99725342 361.01074219 361.02426147 361.03775024 361.05123901 - 361.0647583 361.07824707 361.09173584 361.10525513 361.1187439 - 361.13226318 361.14575195 361.15924072 361.17276001 361.18624878 - 361.19973755 361.21325684 361.22674561 361.24026489 361.25375366 - 361.26724243 361.28076172 361.29425049 361.30773926 361.32125854 - 361.33474731 361.34823608 361.36175537 361.37524414 361.38876343 - 361.4022522 361.41574097 361.42926025 361.44274902 361.45623779 - 361.46975708 361.48324585 361.49676514 361.51025391 361.52374268 - 361.53726196 361.55075073 361.5642395 361.57775879 361.59124756 - 361.60473633 361.61825562 361.63174438 361.64526367 361.65875244 - 361.67224121 361.6857605 361.69924927 361.71273804 361.72625732 - 361.73974609 361.75323486 361.76675415 361.78024292 361.79376221 - 361.80725098 361.82073975 361.83425903 361.8477478 361.86123657 - 361.87475586 361.88824463 361.90176392 361.91525269 361.92874146 - 361.94226074 361.95574951 361.96923828 361.98275757 361.99624634 - 362.00973511 362.02325439 362.03674316 362.05026245 362.06375122 - 362.07723999 362.09075928 362.10424805 362.11773682 362.1312561 - 362.14474487 362.15826416 362.17175293 362.1852417 362.19876099 - 362.21224976 362.22573853 362.23925781 362.25274658 362.26623535 - 362.27975464 362.29324341 362.3067627 362.32025146 362.33374023 - 362.34725952 362.36074829 362.37423706 362.38775635 362.40124512 - 362.4147644 362.42825317 362.44174194 362.45526123 362.46875 - 362.48223877 362.49575806 362.50924683 362.5227356 362.53625488 - 362.54974365 362.56326294 362.57675171 362.59024048 362.60375977 - 362.61724854 362.6307373 362.64425659 362.65774536 362.67126465 - 362.68475342 362.69824219 362.71176147 362.72525024 362.73873901 - 362.7522583 362.76574707 362.77923584 362.79275513 362.8062439 - 362.81976318 362.83325195 362.84674072 362.86026001 362.87374878 - 362.88723755 362.90075684 362.91424561 362.92776489 362.94125366 - 362.95474243 362.96826172 362.98175049 362.99523926 363.00875854 - 363.02224731 363.03573608 363.04925537 363.06274414 363.07626343 - 363.0897522 363.10324097 363.11676025 363.13024902 363.14373779 - 363.15725708 363.17074585 363.18426514 363.19775391 363.21124268 - 363.22476196 363.23825073 363.2517395 363.26525879 363.27874756 - 363.29223633 363.30575562 363.31951904 363.33377075 363.34857178 - 363.36395264 363.37991333 363.39645386 363.41360474 363.431427 - 363.44992065 363.46911621 363.48901367 363.50967407 363.53109741 - 363.55334473 363.57641602 363.60037231 363.62521362 363.65100098 - 363.67776489 363.70550537 363.73431396 363.76699829 363.80300903 - 363.83898926 363.875 363.91101074 363.94699097 363.98300171 - 364.01901245 364.05499268 364.09100342 364.12701416 364.16299438 - 364.19900513 364.23498535 364.27099609 364.30700684 364.34298706 - 364.3789978 364.41500854 364.45098877 364.48699951 364.52301025 - 364.55899048 364.59500122 364.63101196 364.66699219 364.70300293 - 364.73901367 364.7749939 364.81100464 364.84698486 364.88299561 - 364.91900635 364.95498657 364.99099731 365.02700806 365.06298828 - 365.09899902 365.13500977 365.17098999 365.20700073] - y: [ -5.59320021e+00 -5.55719995e+00 -5.52120018e+00 -5.48519993e+00 - -5.44920015e+00 -5.41319990e+00 -5.37720013e+00 -5.34119987e+00 - -5.30520010e+00 -5.26919985e+00 -5.23320007e+00 -5.19719982e+00 - -5.16120005e+00 -5.12519979e+00 -5.08920002e+00 -5.05319977e+00 - -5.01719999e+00 -4.98120022e+00 -4.94519997e+00 -4.90920019e+00 - -4.87319994e+00 -4.83720016e+00 -4.80119991e+00 -4.76520014e+00 - -4.72919989e+00 -4.69320011e+00 -4.65719986e+00 -4.62120008e+00 - -4.58519983e+00 -4.54920006e+00 -4.51319981e+00 -4.47720003e+00 - -4.44119978e+00 -4.40520000e+00 -4.36920023e+00 -4.33319998e+00 - -4.29720020e+00 -4.26119995e+00 -4.22520018e+00 -4.19377995e+00 - -4.16359854e+00 -4.13460732e+00 -4.10675907e+00 -4.08000851e+00 - -4.05431318e+00 -4.02963066e+00 -4.00592136e+00 -3.98314714e+00 - -3.96127057e+00 -3.94025683e+00 -3.92007136e+00 -3.90068197e+00 - -3.88205695e+00 -3.86416626e+00 -3.84698105e+00 -3.83047342e+00 - -3.81461668e+00 -3.79938507e+00 -3.78475404e+00 -3.77069998e+00 - -3.75720000e+00 -3.74370003e+00 -3.73020005e+00 -3.71670008e+00 - -3.70320010e+00 -3.68969989e+00 -3.67619991e+00 -3.66269994e+00 - -3.64919996e+00 -3.63569999e+00 -3.62220001e+00 -3.60870004e+00 - -3.59520006e+00 -3.58170009e+00 -3.56820011e+00 -3.55469990e+00 - -3.54119992e+00 -3.52769995e+00 -3.51419997e+00 -3.50070000e+00 - -3.48720002e+00 -3.47370005e+00 -3.46020007e+00 -3.44670010e+00 - -3.43319988e+00 -3.41969991e+00 -3.40619993e+00 -3.39269996e+00 - -3.37919998e+00 -3.36570001e+00 -3.35220003e+00 -3.33870006e+00 - -3.32520008e+00 -3.31170011e+00 -3.29819989e+00 -3.28469992e+00 - -3.27119994e+00 -3.25769997e+00 -3.24419999e+00 -3.23070002e+00 - -3.21720004e+00 -3.20370007e+00 -3.19020009e+00 -3.17670012e+00 - -3.16319990e+00 -3.14969993e+00 -3.13619995e+00 -3.12269998e+00 - -3.10920000e+00 -3.09570003e+00 -3.08220005e+00 -3.06870008e+00 - -3.05520010e+00 -3.04169989e+00 -3.02819991e+00 -3.01469994e+00 - -3.00119996e+00 -2.98769999e+00 -2.97420001e+00 -2.96070004e+00 - -2.94720006e+00 -2.93370008e+00 -2.92020011e+00 -2.90669990e+00 - -2.89319992e+00 -2.87969995e+00 -2.86619997e+00 -2.85270000e+00 - -2.83920002e+00 -2.82570004e+00 -2.81220007e+00 -2.79870009e+00 - -2.78520012e+00 -2.77169991e+00 -2.75819993e+00 -2.74469995e+00 - -2.73119998e+00 -2.71770000e+00 -2.70420003e+00 -2.69070005e+00 - -2.67720008e+00 -2.66370010e+00 -2.65019989e+00 -2.63669991e+00 - -2.62319994e+00 -2.60969996e+00 -2.59619999e+00 -2.58270001e+00 - -2.56920004e+00 -2.55570006e+00 -2.54220009e+00 -2.52870011e+00 - -2.51519990e+00 -2.50169992e+00 -2.48819995e+00 -2.47469997e+00 - -2.46120000e+00 -2.44770002e+00 -2.43420005e+00 -2.42070007e+00 - -2.40720010e+00 -2.39369988e+00 -2.38019991e+00 -2.36669993e+00 - -2.35319996e+00 -2.33969998e+00 -2.32620001e+00 -2.31270003e+00 - -2.29920006e+00 -2.28570008e+00 -2.27220011e+00 -2.25869989e+00 - -2.24519992e+00 -2.23169994e+00 -2.21819997e+00 -2.20469999e+00 - -2.19120002e+00 -2.17770004e+00 -2.16420007e+00 -2.15070009e+00 - -2.13720012e+00 -2.12369990e+00 -2.11019993e+00 -2.09669995e+00 - -2.08319998e+00 -2.06970000e+00 -2.05620003e+00 -2.04270005e+00 - -2.02920008e+00 -2.01570010e+00 -2.00219989e+00 -1.98870003e+00 - -1.97520006e+00 -1.96169996e+00 -1.94819999e+00 -1.93470001e+00 - -1.92120004e+00 -1.90769994e+00 -1.89419997e+00 -1.88069999e+00 - -1.86720002e+00 -1.85370004e+00 -1.84019995e+00 -1.82669997e+00 - -1.81320000e+00 -1.79970002e+00 -1.78620005e+00 -1.77269995e+00 - -1.75919998e+00 -1.74570000e+00 -1.73220003e+00 -1.71870005e+00 - -1.70519996e+00 -1.69169998e+00 -1.67820001e+00 -1.66470003e+00 - -1.65120006e+00 -1.63769996e+00 -1.62419999e+00 -1.61070001e+00 - -1.59720004e+00 -1.58369994e+00 -1.57019997e+00 -1.55669999e+00 - -1.54320002e+00 -1.52970004e+00 -1.51619995e+00 -1.50269997e+00 - -1.48920000e+00 -1.47570002e+00 -1.46220005e+00 -1.44869995e+00 - -1.43519998e+00 -1.42170000e+00 -1.40820003e+00 -1.39470005e+00 - -1.38119996e+00 -1.36769998e+00 -1.35420001e+00 -1.34070003e+00 - -1.32720006e+00 -1.31369996e+00 -1.30019999e+00 -1.28670001e+00 - -1.27320004e+00 -1.25969994e+00 -1.24619997e+00 -1.23269999e+00 - -1.21920002e+00 -1.20570004e+00 -1.19219995e+00 -1.17869997e+00 - -1.16520000e+00 -1.15170002e+00 -1.13820004e+00 -1.12469995e+00 - -1.11119998e+00 -1.09770000e+00 -1.08420002e+00 -1.07070005e+00 - -1.05719995e+00 -1.04369998e+00 -1.03020000e+00 -1.01670003e+00 - -1.00320005e+00 -9.89700019e-01 -9.76199985e-01 -9.62700009e-01 - -9.49199975e-01 -9.35699999e-01 -9.22200024e-01 -9.08699989e-01 - -8.95200014e-01 -8.81699979e-01 -8.68200004e-01 -8.54700029e-01 - -8.41199994e-01 -8.27700019e-01 -8.14199984e-01 -8.00700009e-01 - -7.87199974e-01 -7.73699999e-01 -7.60200024e-01 -7.46699989e-01 - -7.33200014e-01 -7.19699979e-01 -7.06200004e-01 -6.92700028e-01 - -6.79199994e-01 -6.65700018e-01 -6.52199984e-01 -6.38700008e-01 - -6.25199974e-01 -6.11699998e-01 -5.98200023e-01 -5.84699988e-01 - -5.71200013e-01 -5.57699978e-01 -5.44200003e-01 -5.30700028e-01 - -5.17199993e-01 -5.03700018e-01 -4.90200013e-01 -4.76700008e-01 - -4.63200003e-01 -4.49699998e-01 -4.36199993e-01 -4.22699988e-01 - -4.09200013e-01 -3.95700008e-01 -3.82200003e-01 -3.68699998e-01 - -3.55199993e-01 -3.41699988e-01 -3.28200012e-01 -3.14700007e-01 - -3.01200002e-01 -2.87699997e-01 -2.74199992e-01 -2.60699987e-01 - -2.47199997e-01 -2.33700007e-01 -2.20200002e-01 -2.06699997e-01 - -1.93200007e-01 -1.79700002e-01 -1.66199997e-01 -1.52700007e-01 - -1.39200002e-01 -1.25699997e-01 -1.12199999e-01 -9.87000018e-02 - -8.51999968e-02 -7.16999993e-02 -5.82000017e-02 -4.47000004e-02 - -3.11999992e-02 -1.76999997e-02 -4.19999985e-03 9.30000003e-03 - 2.28000004e-02 3.62999998e-02 4.98000011e-02 6.32999986e-02 - 7.68000036e-02 9.03000012e-02 1.03799999e-01 1.17299996e-01 - 1.30799994e-01 1.44299999e-01 1.57800004e-01 1.71299994e-01 - 1.84799999e-01 1.98300004e-01 2.11799994e-01 2.25299999e-01 - 2.38800004e-01 2.52299994e-01 2.65799999e-01 2.79300004e-01 - 2.92800009e-01 3.06300014e-01 3.19799989e-01 3.33299994e-01 - 3.46799999e-01 3.60300004e-01 3.73800009e-01 3.87300014e-01 - 4.00799990e-01 4.14299995e-01 4.27800000e-01 4.41300005e-01 - 4.54800010e-01 4.68300015e-01 4.81799990e-01 4.95299995e-01 - 5.08800030e-01 5.22300005e-01 5.35799980e-01 5.49300015e-01 - 5.62799990e-01 5.76300025e-01 5.89800000e-01 6.03299975e-01 - 6.16800010e-01 6.30299985e-01 6.43800020e-01 6.57299995e-01 - 6.70799971e-01 6.84300005e-01 6.97799981e-01 7.11300015e-01 - 7.24799991e-01 7.38300025e-01 7.51800001e-01 7.65299976e-01 - 7.78800011e-01 7.92299986e-01 8.05800021e-01 8.19299996e-01 - 8.32799971e-01 8.46300006e-01 8.59799981e-01 8.73300016e-01 - 8.86799991e-01 9.00300026e-01 9.13800001e-01 9.27299976e-01 - 9.40800011e-01 9.54299986e-01 9.67800021e-01 9.81299996e-01 - 9.94799972e-01 1.00829995e+00 1.02180004e+00 1.03530002e+00 - 1.04879999e+00 1.06229997e+00 1.07579994e+00 1.08930004e+00 - 1.10280001e+00 1.11629999e+00 1.12979996e+00 1.14330006e+00 - 1.15680003e+00 1.17030001e+00 1.18379998e+00 1.19729996e+00 - 1.21080005e+00 1.22430003e+00 1.23780000e+00 1.25129998e+00 - 1.26479995e+00 1.27830005e+00 1.29180002e+00 1.30530000e+00 - 1.31879997e+00 1.33229995e+00 1.34580004e+00 1.35930002e+00 - 1.37279999e+00 1.38629997e+00 1.39979994e+00 1.41330004e+00 - 1.42680001e+00 1.44029999e+00 1.45379996e+00 1.46730006e+00 - 1.48080003e+00 1.49430001e+00 1.50779998e+00 1.52129996e+00 - 1.53480005e+00 1.54830003e+00 1.56180000e+00 1.57529998e+00 - 1.58879995e+00 1.60230005e+00 1.61580002e+00 1.62930000e+00 - 1.64279997e+00 1.65629995e+00 1.66980004e+00 1.68330002e+00 - 1.69679999e+00 1.71029997e+00 1.72379994e+00 1.73730004e+00 - 1.75080001e+00 1.76429999e+00 1.77779996e+00 1.79130006e+00 - 1.80480003e+00 1.81830001e+00 1.83179998e+00 1.84529996e+00 - 1.85880005e+00 1.87230003e+00 1.88580000e+00 1.89929998e+00 - 1.91279995e+00 1.92630005e+00 1.93980002e+00 1.95330000e+00 - 1.96679997e+00 1.98029995e+00 1.99380004e+00 2.00729990e+00 - 2.02080011e+00 2.03430009e+00 2.04780006e+00 2.06130004e+00 - 2.07480001e+00 2.08829999e+00 2.10179996e+00 2.11529994e+00 - 2.12879992e+00 2.14229989e+00 2.15580010e+00 2.16930008e+00 - 2.18280005e+00 2.19630003e+00 2.20980000e+00 2.22329998e+00 - 2.23679996e+00 2.25029993e+00 2.26379991e+00 2.27729988e+00 - 2.29080009e+00 2.30430007e+00 2.31780005e+00 2.33130002e+00 - 2.34480000e+00 2.35829997e+00 2.37179995e+00 2.38529992e+00 - 2.39879990e+00 2.41230011e+00 2.42580009e+00 2.43930006e+00 - 2.45280004e+00 2.46630001e+00 2.47979999e+00 2.49329996e+00 - 2.50679994e+00 2.52029991e+00 2.53379989e+00 2.54730010e+00 - 2.56080008e+00 2.57430005e+00 2.58780003e+00 2.60130000e+00 - 2.61479998e+00 2.62829995e+00 2.64179993e+00 2.65529990e+00 - 2.66880012e+00 2.68230009e+00 2.69580007e+00 2.70930004e+00 - 2.72280002e+00 2.73629999e+00 2.74979997e+00 2.76329994e+00 - 2.77679992e+00 2.79029989e+00 2.80380011e+00 2.81730008e+00 - 2.83080006e+00 2.84430003e+00 2.85780001e+00 2.87129998e+00 - 2.88479996e+00 2.89829993e+00 2.91179991e+00 2.92529988e+00 - 2.93880010e+00 2.95230007e+00 2.96580005e+00 2.97930002e+00 - 2.99280000e+00 3.00629997e+00 3.01979995e+00 3.03329992e+00 - 3.04679990e+00 3.06030011e+00 3.07380009e+00 3.08730006e+00 - 3.10080004e+00 3.11430001e+00 3.12779999e+00 3.14129996e+00 - 3.15479994e+00 3.16829991e+00 3.18179989e+00 3.19530010e+00 - 3.20880008e+00 3.22230005e+00 3.23580003e+00 3.24930000e+00 - 3.26279998e+00 3.27629995e+00 3.28979993e+00 3.30329990e+00 - 3.31680012e+00 3.33030009e+00 3.34380007e+00 3.35730004e+00 - 3.37080002e+00 3.38429999e+00 3.39779997e+00 3.41129994e+00 - 3.42479992e+00 3.43829989e+00 3.45180011e+00 3.46530008e+00 - 3.47880006e+00 3.49230003e+00 3.50580001e+00 3.51929998e+00 - 3.53279996e+00 3.54629993e+00 3.55979991e+00 3.57329988e+00 - 3.58680010e+00 3.60030007e+00 3.61380005e+00 3.62730002e+00 - 3.64080000e+00 3.65429997e+00 3.66779995e+00 3.68129992e+00 - 3.69479990e+00 3.70830011e+00 3.72180009e+00 3.73530006e+00 - 3.74880004e+00 3.76230001e+00 3.77579999e+00 3.78929996e+00 - 3.80279994e+00 3.81629992e+00 3.82979989e+00 3.84330010e+00 - 3.85680008e+00 3.87030005e+00 3.88380003e+00 3.89730000e+00 - 3.91079998e+00 3.92429996e+00 3.93779993e+00 3.95129991e+00 - 3.96479988e+00 3.97830009e+00 3.99180007e+00 4.00530005e+00 - 4.01879978e+00 4.03230000e+00 4.04580021e+00 4.05929995e+00 - 4.07280016e+00 4.08629990e+00 4.09980011e+00 4.11329985e+00 - 4.12680006e+00 4.14029980e+00 4.15380001e+00 4.16730022e+00 - 4.18079996e+00 4.19430017e+00 4.20779991e+00 4.22130013e+00 - 4.23479986e+00 4.24830008e+00 4.26179981e+00 4.27530003e+00 - 4.28879976e+00 4.30229998e+00 4.31580019e+00 4.32929993e+00 - 4.34280014e+00 4.35629988e+00 4.36980009e+00 4.38329983e+00 - 4.39680004e+00 4.41029978e+00 4.42379999e+00 4.43730021e+00 - 4.45079994e+00 4.46430016e+00 4.47779989e+00 4.49130011e+00 - 4.50479984e+00 4.51830006e+00 4.53179979e+00 4.54530001e+00 - 4.55880022e+00 4.57229996e+00 4.58580017e+00 4.59929991e+00 - 4.61280012e+00 4.62629986e+00 4.63980007e+00 4.65329981e+00 - 4.66680002e+00 4.68030024e+00 4.69379997e+00 4.70730019e+00 - 4.72079992e+00 4.73430014e+00 4.74779987e+00 4.76130009e+00 - 4.77479982e+00 4.78830004e+00 4.80179977e+00 4.81529999e+00 - 4.82880020e+00 4.84229994e+00 4.85580015e+00 4.86929989e+00 - 4.88280010e+00 4.89629984e+00 4.90980005e+00 4.92329979e+00 - 4.93680000e+00 4.95030022e+00 4.96379995e+00 4.97730017e+00 - 4.99079990e+00 5.00430012e+00 5.01779985e+00 5.03130007e+00 - 5.04479980e+00 5.05830002e+00 5.07180023e+00 5.08529997e+00 - 5.09880018e+00 5.11229992e+00 5.12580013e+00 5.13929987e+00 - 5.15280008e+00 5.16629982e+00 5.17980003e+00 5.19329977e+00 - 5.20679998e+00 5.22030020e+00 5.23379993e+00 5.24730015e+00 - 5.26079988e+00 5.27430010e+00 5.28779984e+00 5.30130005e+00 - 5.31479979e+00 5.32830000e+00 5.34180021e+00 5.35529995e+00 - 5.36880016e+00 5.38229990e+00 5.39580011e+00 5.40929985e+00 - 5.42280006e+00 5.43629980e+00 5.44980001e+00 5.46330023e+00 - 5.47679996e+00 5.49030018e+00 5.50379992e+00 5.51730013e+00 - 5.53079987e+00 5.54430008e+00 5.55779982e+00 5.57130003e+00 - 5.58479977e+00 5.59829998e+00 5.61180019e+00 5.62529993e+00 - 5.63880014e+00 5.65229988e+00 5.66580009e+00 5.67929983e+00 - 5.69280005e+00 5.70629978e+00 5.71980000e+00 5.73330021e+00 - 5.74679995e+00 5.76030016e+00 5.77379990e+00 5.78730011e+00 - 5.80079985e+00 5.81430006e+00 5.82779980e+00 5.84130001e+00 - 5.85480022e+00 5.86829996e+00 5.88180017e+00 5.89529991e+00 - 5.90880013e+00 5.92229986e+00 5.93580008e+00 5.94929981e+00 - 5.96280003e+00 5.97629976e+00 5.98979998e+00 6.00330019e+00 - 6.01679993e+00 6.03030014e+00 6.04379988e+00 6.05730009e+00 - 6.07079983e+00 6.08430004e+00 6.09779978e+00 6.11129999e+00 - 6.12480021e+00 6.13829994e+00 6.15180016e+00 6.16529989e+00 - 6.17880011e+00 6.19229984e+00 6.20580006e+00 6.21929979e+00 - 6.23280001e+00 6.24630022e+00 6.25979996e+00 6.27330017e+00 - 6.28679991e+00 6.30030012e+00 6.31379986e+00 6.32730007e+00 - 6.34079981e+00 6.35430002e+00 6.36780024e+00 6.38129997e+00 - 6.39480019e+00 6.40829992e+00 6.42180014e+00 6.43529987e+00 - 6.44880009e+00 6.46229982e+00 6.47580004e+00 6.48929977e+00 - 6.50279999e+00 6.51630020e+00 6.52979994e+00 6.54330015e+00 - 6.55679989e+00 6.57030010e+00 6.58379984e+00 6.59730005e+00 - 6.61079979e+00 6.62430000e+00 6.63780022e+00 6.65129995e+00 - 6.66480017e+00 6.67829990e+00 6.69180012e+00 6.70529985e+00 - 6.71880007e+00 6.73229980e+00 6.74580002e+00 6.75930023e+00 - 6.77279997e+00 6.78630018e+00 6.79979992e+00 6.81330013e+00 - 6.82679987e+00 6.84030008e+00 6.85379982e+00 6.86730003e+00 - 6.88079977e+00 6.89429998e+00 6.90780020e+00 6.92129993e+00 - 6.93480015e+00 6.94829988e+00 6.96180010e+00 6.97529984e+00 - 6.98880005e+00 7.00229979e+00 7.01580000e+00 7.02930021e+00 - 7.04279995e+00 7.05630016e+00 7.06979990e+00 7.08330011e+00 - 7.09679985e+00 7.11030006e+00 7.12379980e+00 7.13730001e+00 - 7.15080023e+00 7.16485405e+00 7.17948532e+00 7.19471693e+00 - 7.21057367e+00 7.22708130e+00 7.24426651e+00 7.26215696e+00 - 7.28078175e+00 7.30017138e+00 7.32035685e+00 7.34137058e+00 - 7.36324692e+00 7.38602161e+00 7.40973091e+00 7.43441296e+00 - 7.46010876e+00 7.48685884e+00 7.51470709e+00 7.54369831e+00 - 7.57387972e+00 7.60529995e+00 7.64130020e+00 7.67729998e+00 - 7.71330023e+00 7.74930000e+00 7.78529978e+00 7.82130003e+00 - 7.85729980e+00 7.89330006e+00 7.92929983e+00 7.96530008e+00 - 8.00129986e+00 8.03730011e+00 8.07330036e+00 8.10929966e+00 - 8.14529991e+00 8.18130016e+00 8.21730042e+00 8.25329971e+00 - 8.28929996e+00 8.32530022e+00 8.36130047e+00 8.39729977e+00 - 8.43330002e+00 8.46930027e+00 8.50529957e+00 8.54129982e+00 - 8.57730007e+00 8.61330032e+00 8.64929962e+00 8.68529987e+00 - 8.72130013e+00 8.75730038e+00 8.79329967e+00 8.82929993e+00 - 8.86530018e+00 8.90130043e+00 8.93729973e+00 8.97329998e+00] - y_lower_bound: [ -5.61120033e+00 -5.57520008e+00 -5.53919983e+00 -5.50320005e+00 - -5.46719980e+00 -5.43120003e+00 -5.39519978e+00 -5.35920000e+00 - -5.32320023e+00 -5.28719997e+00 -5.25120020e+00 -5.21519995e+00 - -5.17920017e+00 -5.14319992e+00 -5.10720015e+00 -5.07119989e+00 - -5.03520012e+00 -4.99919987e+00 -4.96320009e+00 -4.92719984e+00 - -4.89120007e+00 -4.85519981e+00 -4.81920004e+00 -4.78319979e+00 - -4.74720001e+00 -4.71120024e+00 -4.67519999e+00 -4.63920021e+00 - -4.60319996e+00 -4.56720018e+00 -4.53119993e+00 -4.49520016e+00 - -4.45919991e+00 -4.42320013e+00 -4.38719988e+00 -4.35120010e+00 - -4.31519985e+00 -4.27920008e+00 -4.24319983e+00 -4.20948982e+00 - -4.17868900e+00 -4.14910269e+00 -4.12068319e+00 -4.09338379e+00 - -4.06716108e+00 -4.04197168e+00 -4.01777601e+00 -3.99453425e+00 - -3.97220898e+00 -3.95076370e+00 -3.93016410e+00 -3.91037679e+00 - -3.89136934e+00 -3.87311172e+00 -3.85557365e+00 -3.83872724e+00 - -3.82254505e+00 -3.80700088e+00 -3.79206967e+00 -3.77772713e+00 - -3.76395011e+00 -3.75044990e+00 -3.73694992e+00 -3.72344995e+00 - -3.70994997e+00 -3.69645000e+00 -3.68295002e+00 -3.66945004e+00 - -3.65595007e+00 -3.64245009e+00 -3.62895012e+00 -3.61544991e+00 - -3.60194993e+00 -3.58844995e+00 -3.57494998e+00 -3.56145000e+00 - -3.54795003e+00 -3.53445005e+00 -3.52095008e+00 -3.50745010e+00 - -3.49394989e+00 -3.48044991e+00 -3.46694994e+00 -3.45344996e+00 - -3.43994999e+00 -3.42645001e+00 -3.41295004e+00 -3.39945006e+00 - -3.38595009e+00 -3.37245011e+00 -3.35894990e+00 -3.34544992e+00 - -3.33194995e+00 -3.31844997e+00 -3.30495000e+00 -3.29145002e+00 - -3.27795005e+00 -3.26445007e+00 -3.25095010e+00 -3.23744988e+00 - -3.22394991e+00 -3.21044993e+00 -3.19694996e+00 -3.18344998e+00 - -3.16995001e+00 -3.15645003e+00 -3.14295006e+00 -3.12945008e+00 - -3.11595011e+00 -3.10244989e+00 -3.08894992e+00 -3.07544994e+00 - -3.06194997e+00 -3.04844999e+00 -3.03495002e+00 -3.02145004e+00 - -3.00795007e+00 -2.99445009e+00 -2.98095012e+00 -2.96744990e+00 - -2.95394993e+00 -2.94044995e+00 -2.92694998e+00 -2.91345000e+00 - -2.89995003e+00 -2.88645005e+00 -2.87295008e+00 -2.85945010e+00 - -2.84594989e+00 -2.83244991e+00 -2.81894994e+00 -2.80544996e+00 - -2.79194999e+00 -2.77845001e+00 -2.76495004e+00 -2.75145006e+00 - -2.73795009e+00 -2.72445011e+00 -2.71094990e+00 -2.69744992e+00 - -2.68394995e+00 -2.67044997e+00 -2.65695000e+00 -2.64345002e+00 - -2.62995005e+00 -2.61645007e+00 -2.60295010e+00 -2.58944988e+00 - -2.57594991e+00 -2.56244993e+00 -2.54894996e+00 -2.53544998e+00 - -2.52195001e+00 -2.50845003e+00 -2.49495006e+00 -2.48145008e+00 - -2.46795011e+00 -2.45444989e+00 -2.44094992e+00 -2.42744994e+00 - -2.41394997e+00 -2.40044999e+00 -2.38695002e+00 -2.37345004e+00 - -2.35995007e+00 -2.34645009e+00 -2.33295012e+00 -2.31944990e+00 - -2.30594993e+00 -2.29244995e+00 -2.27894998e+00 -2.26545000e+00 - -2.25195003e+00 -2.23845005e+00 -2.22495008e+00 -2.21145010e+00 - -2.19794989e+00 -2.18444991e+00 -2.17094994e+00 -2.15744996e+00 - -2.14394999e+00 -2.13045001e+00 -2.11695004e+00 -2.10345006e+00 - -2.08995008e+00 -2.07645011e+00 -2.06294990e+00 -2.04944992e+00 - -2.03594995e+00 -2.02244997e+00 -2.00895000e+00 -1.99545002e+00 - -1.98195004e+00 -1.96844995e+00 -1.95494998e+00 -1.94145000e+00 - -1.92795002e+00 -1.91445005e+00 -1.90094995e+00 -1.88744998e+00 - -1.87395000e+00 -1.86045003e+00 -1.84695005e+00 -1.83344996e+00 - -1.81994998e+00 -1.80645001e+00 -1.79295003e+00 -1.77945006e+00 - -1.76594996e+00 -1.75244999e+00 -1.73895001e+00 -1.72545004e+00 - -1.71194994e+00 -1.69844997e+00 -1.68494999e+00 -1.67145002e+00 - -1.65795004e+00 -1.64444995e+00 -1.63094997e+00 -1.61745000e+00 - -1.60395002e+00 -1.59045005e+00 -1.57694995e+00 -1.56344998e+00 - -1.54995000e+00 -1.53645003e+00 -1.52295005e+00 -1.50944996e+00 - -1.49594998e+00 -1.48245001e+00 -1.46895003e+00 -1.45545006e+00 - -1.44194996e+00 -1.42844999e+00 -1.41495001e+00 -1.40145004e+00 - -1.38794994e+00 -1.37444997e+00 -1.36094999e+00 -1.34745002e+00 - -1.33395004e+00 -1.32044995e+00 -1.30694997e+00 -1.29345000e+00 - -1.27995002e+00 -1.26645005e+00 -1.25294995e+00 -1.23944998e+00 - -1.22595000e+00 -1.21245003e+00 -1.19895005e+00 -1.18544996e+00 - -1.17194998e+00 -1.15845001e+00 -1.14495003e+00 -1.13145006e+00 - -1.11794996e+00 -1.10444999e+00 -1.09095001e+00 -1.07745004e+00 - -1.06394994e+00 -1.05044997e+00 -1.03694999e+00 -1.02345002e+00 - -1.00995004e+00 -9.96450007e-01 -9.82949972e-01 -9.69449997e-01 - -9.55950022e-01 -9.42449987e-01 -9.28950012e-01 -9.15449977e-01 - -9.01950002e-01 -8.88450027e-01 -8.74949992e-01 -8.61450016e-01 - -8.47949982e-01 -8.34450006e-01 -8.20949972e-01 -8.07449996e-01 - -7.93950021e-01 -7.80449986e-01 -7.66950011e-01 -7.53449976e-01 - -7.39950001e-01 -7.26450026e-01 -7.12949991e-01 -6.99450016e-01 - -6.85949981e-01 -6.72450006e-01 -6.58949971e-01 -6.45449996e-01 - -6.31950021e-01 -6.18449986e-01 -6.04950011e-01 -5.91449976e-01 - -5.77950001e-01 -5.64450026e-01 -5.50949991e-01 -5.37450016e-01 - -5.23949981e-01 -5.10450006e-01 -4.96950001e-01 -4.83449996e-01 - -4.69949991e-01 -4.56449986e-01 -4.42950010e-01 -4.29450005e-01 - -4.15950000e-01 -4.02449995e-01 -3.88949990e-01 -3.75449985e-01 - -3.61950010e-01 -3.48450005e-01 -3.34950000e-01 -3.21449995e-01 - -3.07949990e-01 -2.94450015e-01 -2.80950010e-01 -2.67450005e-01 - -2.53950000e-01 -2.40449995e-01 -2.26950005e-01 -2.13450000e-01 - -1.99949995e-01 -1.86450005e-01 -1.72950000e-01 -1.59449995e-01 - -1.45950004e-01 -1.32449999e-01 -1.18950002e-01 -1.05449997e-01 - -9.19499993e-02 -7.84500018e-02 -6.49499968e-02 -5.14499992e-02 - -3.79500017e-02 -2.44500004e-02 -1.09500000e-02 2.55000009e-03 - 1.60499997e-02 2.95499992e-02 4.30499986e-02 5.65499999e-02 - 7.00500011e-02 8.35499987e-02 9.70500037e-02 1.10550001e-01 - 1.24049999e-01 1.37549996e-01 1.51050001e-01 1.64550006e-01 - 1.78049996e-01 1.91550002e-01 2.05050007e-01 2.18549997e-01 - 2.32050002e-01 2.45550007e-01 2.59050012e-01 2.72549987e-01 - 2.86049992e-01 2.99549997e-01 3.13050002e-01 3.26550007e-01 - 3.40050012e-01 3.53549987e-01 3.67049992e-01 3.80549997e-01 - 3.94050002e-01 4.07550007e-01 4.21050012e-01 4.34549987e-01 - 4.48049992e-01 4.61549997e-01 4.75050002e-01 4.88550007e-01 - 5.02049983e-01 5.15550017e-01 5.29049993e-01 5.42550027e-01 - 5.56050003e-01 5.69549978e-01 5.83050013e-01 5.96549988e-01 - 6.10050023e-01 6.23549998e-01 6.37049973e-01 6.50550008e-01 - 6.64049983e-01 6.77550018e-01 6.91049993e-01 7.04550028e-01 - 7.18050003e-01 7.31549978e-01 7.45050013e-01 7.58549988e-01 - 7.72050023e-01 7.85549998e-01 7.99049973e-01 8.12550008e-01 - 8.26049984e-01 8.39550018e-01 8.53049994e-01 8.66550028e-01 - 8.80050004e-01 8.93549979e-01 9.07050014e-01 9.20549989e-01 - 9.34050024e-01 9.47549999e-01 9.61049974e-01 9.74550009e-01 - 9.88049984e-01 1.00154996e+00 1.01505005e+00 1.02855003e+00 - 1.04205000e+00 1.05554998e+00 1.06904995e+00 1.08255005e+00 - 1.09605002e+00 1.10955000e+00 1.12304997e+00 1.13654995e+00 - 1.15005004e+00 1.16355002e+00 1.17704999e+00 1.19054997e+00 - 1.20404994e+00 1.21755004e+00 1.23105001e+00 1.24454999e+00 - 1.25804996e+00 1.27155006e+00 1.28505003e+00 1.29855001e+00 - 1.31204998e+00 1.32554996e+00 1.33905005e+00 1.35255003e+00 - 1.36605000e+00 1.37954998e+00 1.39304996e+00 1.40655005e+00 - 1.42005002e+00 1.43355000e+00 1.44704998e+00 1.46054995e+00 - 1.47405005e+00 1.48755002e+00 1.50105000e+00 1.51454997e+00 - 1.52804995e+00 1.54155004e+00 1.55505002e+00 1.56854999e+00 - 1.58204997e+00 1.59554994e+00 1.60905004e+00 1.62255001e+00 - 1.63604999e+00 1.64954996e+00 1.66305006e+00 1.67655003e+00 - 1.69005001e+00 1.70354998e+00 1.71704996e+00 1.73055005e+00 - 1.74405003e+00 1.75755000e+00 1.77104998e+00 1.78454995e+00 - 1.79805005e+00 1.81155002e+00 1.82505000e+00 1.83854997e+00 - 1.85204995e+00 1.86555004e+00 1.87905002e+00 1.89254999e+00 - 1.90604997e+00 1.91954994e+00 1.93305004e+00 1.94655001e+00 - 1.96004999e+00 1.97354996e+00 1.98705006e+00 2.00055003e+00 - 2.01405001e+00 2.02754998e+00 2.04104996e+00 2.05454993e+00 - 2.06804991e+00 2.08154988e+00 2.09505010e+00 2.10855007e+00 - 2.12205005e+00 2.13555002e+00 2.14905000e+00 2.16254997e+00 - 2.17604995e+00 2.18954992e+00 2.20304990e+00 2.21655011e+00 - 2.23005009e+00 2.24355006e+00 2.25705004e+00 2.27055001e+00 - 2.28404999e+00 2.29754996e+00 2.31104994e+00 2.32454991e+00 - 2.33804989e+00 2.35155010e+00 2.36505008e+00 2.37855005e+00 - 2.39205003e+00 2.40555000e+00 2.41904998e+00 2.43254995e+00 - 2.44604993e+00 2.45954990e+00 2.47305012e+00 2.48655009e+00 - 2.50005007e+00 2.51355004e+00 2.52705002e+00 2.54054999e+00 - 2.55404997e+00 2.56754994e+00 2.58104992e+00 2.59454989e+00 - 2.60805011e+00 2.62155008e+00 2.63505006e+00 2.64855003e+00 - 2.66205001e+00 2.67554998e+00 2.68904996e+00 2.70254993e+00 - 2.71604991e+00 2.72954988e+00 2.74305010e+00 2.75655007e+00 - 2.77005005e+00 2.78355002e+00 2.79705000e+00 2.81054997e+00 - 2.82404995e+00 2.83754992e+00 2.85104990e+00 2.86455011e+00 - 2.87805009e+00 2.89155006e+00 2.90505004e+00 2.91855001e+00 - 2.93204999e+00 2.94554996e+00 2.95904994e+00 2.97254992e+00 - 2.98604989e+00 2.99955010e+00 3.01305008e+00 3.02655005e+00 - 3.04005003e+00 3.05355000e+00 3.06704998e+00 3.08054996e+00 - 3.09404993e+00 3.10754991e+00 3.12104988e+00 3.13455009e+00 - 3.14805007e+00 3.16155005e+00 3.17505002e+00 3.18855000e+00 - 3.20204997e+00 3.21554995e+00 3.22904992e+00 3.24254990e+00 - 3.25605011e+00 3.26955009e+00 3.28305006e+00 3.29655004e+00 - 3.31005001e+00 3.32354999e+00 3.33704996e+00 3.35054994e+00 - 3.36404991e+00 3.37754989e+00 3.39105010e+00 3.40455008e+00 - 3.41805005e+00 3.43155003e+00 3.44505000e+00 3.45854998e+00 - 3.47204995e+00 3.48554993e+00 3.49904990e+00 3.51255012e+00 - 3.52605009e+00 3.53955007e+00 3.55305004e+00 3.56655002e+00 - 3.58004999e+00 3.59354997e+00 3.60704994e+00 3.62054992e+00 - 3.63404989e+00 3.64755011e+00 3.66105008e+00 3.67455006e+00 - 3.68805003e+00 3.70155001e+00 3.71504998e+00 3.72854996e+00 - 3.74204993e+00 3.75554991e+00 3.76904988e+00 3.78255010e+00 - 3.79605007e+00 3.80955005e+00 3.82305002e+00 3.83655000e+00 - 3.85004997e+00 3.86354995e+00 3.87704992e+00 3.89054990e+00 - 3.90405011e+00 3.91755009e+00 3.93105006e+00 3.94455004e+00 - 3.95805001e+00 3.97154999e+00 3.98504996e+00 3.99854994e+00 - 4.01205015e+00 4.02554989e+00 4.03905010e+00 4.05254984e+00 - 4.06605005e+00 4.07954979e+00 4.09305000e+00 4.10655022e+00 - 4.12004995e+00 4.13355017e+00 4.14704990e+00 4.16055012e+00 - 4.17404985e+00 4.18755007e+00 4.20104980e+00 4.21455002e+00 - 4.22805023e+00 4.24154997e+00 4.25505018e+00 4.26854992e+00 - 4.28205013e+00 4.29554987e+00 4.30905008e+00 4.32254982e+00 - 4.33605003e+00 4.34954977e+00 4.36304998e+00 4.37655020e+00 - 4.39004993e+00 4.40355015e+00 4.41704988e+00 4.43055010e+00 - 4.44404984e+00 4.45755005e+00 4.47104979e+00 4.48455000e+00 - 4.49805021e+00 4.51154995e+00 4.52505016e+00 4.53854990e+00 - 4.55205011e+00 4.56554985e+00 4.57905006e+00 4.59254980e+00 - 4.60605001e+00 4.61955023e+00 4.63304996e+00 4.64655018e+00 - 4.66004992e+00 4.67355013e+00 4.68704987e+00 4.70055008e+00 - 4.71404982e+00 4.72755003e+00 4.74104977e+00 4.75454998e+00 - 4.76805019e+00 4.78154993e+00 4.79505014e+00 4.80854988e+00 - 4.82205009e+00 4.83554983e+00 4.84905005e+00 4.86254978e+00 - 4.87605000e+00 4.88955021e+00 4.90304995e+00 4.91655016e+00 - 4.93004990e+00 4.94355011e+00 4.95704985e+00 4.97055006e+00 - 4.98404980e+00 4.99755001e+00 5.01105022e+00 5.02454996e+00 - 5.03805017e+00 5.05154991e+00 5.06505013e+00 5.07854986e+00 - 5.09205008e+00 5.10554981e+00 5.11905003e+00 5.13254976e+00 - 5.14604998e+00 5.15955019e+00 5.17304993e+00 5.18655014e+00 - 5.20004988e+00 5.21355009e+00 5.22704983e+00 5.24055004e+00 - 5.25404978e+00 5.26754999e+00 5.28105021e+00 5.29454994e+00 - 5.30805016e+00 5.32154989e+00 5.33505011e+00 5.34854984e+00 - 5.36205006e+00 5.37554979e+00 5.38905001e+00 5.40255022e+00 - 5.41604996e+00 5.42955017e+00 5.44304991e+00 5.45655012e+00 - 5.47004986e+00 5.48355007e+00 5.49704981e+00 5.51055002e+00 - 5.52405024e+00 5.53754997e+00 5.55105019e+00 5.56454992e+00 - 5.57805014e+00 5.59154987e+00 5.60505009e+00 5.61854982e+00 - 5.63205004e+00 5.64554977e+00 5.65904999e+00 5.67255020e+00 - 5.68604994e+00 5.69955015e+00 5.71304989e+00 5.72655010e+00 - 5.74004984e+00 5.75355005e+00 5.76704979e+00 5.78055000e+00 - 5.79405022e+00 5.80754995e+00 5.82105017e+00 5.83454990e+00 - 5.84805012e+00 5.86154985e+00 5.87505007e+00 5.88854980e+00 - 5.90205002e+00 5.91555023e+00 5.92904997e+00 5.94255018e+00 - 5.95604992e+00 5.96955013e+00 5.98304987e+00 5.99655008e+00 - 6.01004982e+00 6.02355003e+00 6.03704977e+00 6.05054998e+00 - 6.06405020e+00 6.07754993e+00 6.09105015e+00 6.10454988e+00 - 6.11805010e+00 6.13154984e+00 6.14505005e+00 6.15854979e+00 - 6.17205000e+00 6.18555021e+00 6.19904995e+00 6.21255016e+00 - 6.22604990e+00 6.23955011e+00 6.25304985e+00 6.26655006e+00 - 6.28004980e+00 6.29355001e+00 6.30705023e+00 6.32054996e+00 - 6.33405018e+00 6.34754992e+00 6.36105013e+00 6.37454987e+00 - 6.38805008e+00 6.40154982e+00 6.41505003e+00 6.42854977e+00 - 6.44204998e+00 6.45555019e+00 6.46904993e+00 6.48255014e+00 - 6.49604988e+00 6.50955009e+00 6.52304983e+00 6.53655005e+00 - 6.55004978e+00 6.56355000e+00 6.57705021e+00 6.59054995e+00 - 6.60405016e+00 6.61754990e+00 6.63105011e+00 6.64454985e+00 - 6.65805006e+00 6.67154980e+00 6.68505001e+00 6.69855022e+00 - 6.71204996e+00 6.72555017e+00 6.73904991e+00 6.75255013e+00 - 6.76604986e+00 6.77955008e+00 6.79304981e+00 6.80655003e+00 - 6.82004976e+00 6.83354998e+00 6.84705019e+00 6.86054993e+00 - 6.87405014e+00 6.88754988e+00 6.90105009e+00 6.91454983e+00 - 6.92805004e+00 6.94154978e+00 6.95504999e+00 6.96855021e+00 - 6.98204994e+00 6.99555016e+00 7.00904989e+00 7.02255011e+00 - 7.03604984e+00 7.04955006e+00 7.06304979e+00 7.07655001e+00 - 7.09005022e+00 7.10354996e+00 7.11705017e+00 7.13054991e+00 - 7.14405012e+00 7.15782690e+00 7.17216969e+00 7.18710089e+00 - 7.20264530e+00 7.21882725e+00 7.23567390e+00 7.25321150e+00 - 7.27146959e+00 7.29047680e+00 7.31026411e+00 7.33086348e+00 - 7.35230875e+00 7.37463427e+00 7.39787626e+00 7.42207193e+00 - 7.44726086e+00 7.47348356e+00 7.50078297e+00 7.52920294e+00 - 7.55878925e+00 7.58959007e+00 7.62330008e+00 7.65929985e+00 - 7.69530010e+00 7.73129988e+00 7.76730013e+00 7.80329990e+00 - 7.83930016e+00 7.87529993e+00 7.91130018e+00 7.94729996e+00 - 7.98330021e+00 8.01930046e+00 8.05529976e+00 8.09130001e+00 - 8.12730026e+00 8.16329956e+00 8.19929981e+00 8.23530006e+00 - 8.27130032e+00 8.30729961e+00 8.34329987e+00 8.37930012e+00 - 8.41530037e+00 8.45129967e+00 8.48729992e+00 8.52330017e+00 - 8.55930042e+00 8.59529972e+00 8.63129997e+00 8.66730022e+00 - 8.70330048e+00 8.73929977e+00 8.77530003e+00 8.81130028e+00 - 8.84729958e+00 8.88329983e+00 8.91930008e+00 8.95530033e+00] - y_upper_bound: [ -5.57520008e+00 -5.53919983e+00 -5.50320005e+00 -5.46719980e+00 - -5.43120003e+00 -5.39519978e+00 -5.35920000e+00 -5.32320023e+00 - -5.28719997e+00 -5.25120020e+00 -5.21519995e+00 -5.17920017e+00 - -5.14319992e+00 -5.10720015e+00 -5.07119989e+00 -5.03520012e+00 - -4.99919987e+00 -4.96320009e+00 -4.92719984e+00 -4.89120007e+00 - -4.85519981e+00 -4.81920004e+00 -4.78319979e+00 -4.74720001e+00 - -4.71120024e+00 -4.67519999e+00 -4.63920021e+00 -4.60319996e+00 - -4.56720018e+00 -4.53119993e+00 -4.49520016e+00 -4.45919991e+00 - -4.42320013e+00 -4.38719988e+00 -4.35120010e+00 -4.31519985e+00 - -4.27920008e+00 -4.24319983e+00 -4.20948982e+00 -4.17868900e+00 - -4.14910269e+00 -4.12068319e+00 -4.09338379e+00 -4.06716108e+00 - -4.04197168e+00 -4.01777601e+00 -3.99453425e+00 -3.97220898e+00 - -3.95076370e+00 -3.93016410e+00 -3.91037679e+00 -3.89136934e+00 - -3.87311172e+00 -3.85557365e+00 -3.83872724e+00 -3.82254505e+00 - -3.80700088e+00 -3.79206967e+00 -3.77772713e+00 -3.76395011e+00 - -3.75044990e+00 -3.73694992e+00 -3.72344995e+00 -3.70994997e+00 - -3.69645000e+00 -3.68295002e+00 -3.66945004e+00 -3.65595007e+00 - -3.64245009e+00 -3.62895012e+00 -3.61544991e+00 -3.60194993e+00 - -3.58844995e+00 -3.57494998e+00 -3.56145000e+00 -3.54795003e+00 - -3.53445005e+00 -3.52095008e+00 -3.50745010e+00 -3.49394989e+00 - -3.48044991e+00 -3.46694994e+00 -3.45344996e+00 -3.43994999e+00 - -3.42645001e+00 -3.41295004e+00 -3.39945006e+00 -3.38595009e+00 - -3.37245011e+00 -3.35894990e+00 -3.34544992e+00 -3.33194995e+00 - -3.31844997e+00 -3.30495000e+00 -3.29145002e+00 -3.27795005e+00 - -3.26445007e+00 -3.25095010e+00 -3.23744988e+00 -3.22394991e+00 - -3.21044993e+00 -3.19694996e+00 -3.18344998e+00 -3.16995001e+00 - -3.15645003e+00 -3.14295006e+00 -3.12945008e+00 -3.11595011e+00 - -3.10244989e+00 -3.08894992e+00 -3.07544994e+00 -3.06194997e+00 - -3.04844999e+00 -3.03495002e+00 -3.02145004e+00 -3.00795007e+00 - -2.99445009e+00 -2.98095012e+00 -2.96744990e+00 -2.95394993e+00 - -2.94044995e+00 -2.92694998e+00 -2.91345000e+00 -2.89995003e+00 - -2.88645005e+00 -2.87295008e+00 -2.85945010e+00 -2.84594989e+00 - -2.83244991e+00 -2.81894994e+00 -2.80544996e+00 -2.79194999e+00 - -2.77845001e+00 -2.76495004e+00 -2.75145006e+00 -2.73795009e+00 - -2.72445011e+00 -2.71094990e+00 -2.69744992e+00 -2.68394995e+00 - -2.67044997e+00 -2.65695000e+00 -2.64345002e+00 -2.62995005e+00 - -2.61645007e+00 -2.60295010e+00 -2.58944988e+00 -2.57594991e+00 - -2.56244993e+00 -2.54894996e+00 -2.53544998e+00 -2.52195001e+00 - -2.50845003e+00 -2.49495006e+00 -2.48145008e+00 -2.46795011e+00 - -2.45444989e+00 -2.44094992e+00 -2.42744994e+00 -2.41394997e+00 - -2.40044999e+00 -2.38695002e+00 -2.37345004e+00 -2.35995007e+00 - -2.34645009e+00 -2.33295012e+00 -2.31944990e+00 -2.30594993e+00 - -2.29244995e+00 -2.27894998e+00 -2.26545000e+00 -2.25195003e+00 - -2.23845005e+00 -2.22495008e+00 -2.21145010e+00 -2.19794989e+00 - -2.18444991e+00 -2.17094994e+00 -2.15744996e+00 -2.14394999e+00 - -2.13045001e+00 -2.11695004e+00 -2.10345006e+00 -2.08995008e+00 - -2.07645011e+00 -2.06294990e+00 -2.04944992e+00 -2.03594995e+00 - -2.02244997e+00 -2.00895000e+00 -1.99545002e+00 -1.98195004e+00 - -1.96844995e+00 -1.95494998e+00 -1.94145000e+00 -1.92795002e+00 - -1.91445005e+00 -1.90094995e+00 -1.88744998e+00 -1.87395000e+00 - -1.86045003e+00 -1.84695005e+00 -1.83344996e+00 -1.81994998e+00 - -1.80645001e+00 -1.79295003e+00 -1.77945006e+00 -1.76594996e+00 - -1.75244999e+00 -1.73895001e+00 -1.72545004e+00 -1.71194994e+00 - -1.69844997e+00 -1.68494999e+00 -1.67145002e+00 -1.65795004e+00 - -1.64444995e+00 -1.63094997e+00 -1.61745000e+00 -1.60395002e+00 - -1.59045005e+00 -1.57694995e+00 -1.56344998e+00 -1.54995000e+00 - -1.53645003e+00 -1.52295005e+00 -1.50944996e+00 -1.49594998e+00 - -1.48245001e+00 -1.46895003e+00 -1.45545006e+00 -1.44194996e+00 - -1.42844999e+00 -1.41495001e+00 -1.40145004e+00 -1.38794994e+00 - -1.37444997e+00 -1.36094999e+00 -1.34745002e+00 -1.33395004e+00 - -1.32044995e+00 -1.30694997e+00 -1.29345000e+00 -1.27995002e+00 - -1.26645005e+00 -1.25294995e+00 -1.23944998e+00 -1.22595000e+00 - -1.21245003e+00 -1.19895005e+00 -1.18544996e+00 -1.17194998e+00 - -1.15845001e+00 -1.14495003e+00 -1.13145006e+00 -1.11794996e+00 - -1.10444999e+00 -1.09095001e+00 -1.07745004e+00 -1.06394994e+00 - -1.05044997e+00 -1.03694999e+00 -1.02345002e+00 -1.00995004e+00 - -9.96450007e-01 -9.82949972e-01 -9.69449997e-01 -9.55950022e-01 - -9.42449987e-01 -9.28950012e-01 -9.15449977e-01 -9.01950002e-01 - -8.88450027e-01 -8.74949992e-01 -8.61450016e-01 -8.47949982e-01 - -8.34450006e-01 -8.20949972e-01 -8.07449996e-01 -7.93950021e-01 - -7.80449986e-01 -7.66950011e-01 -7.53449976e-01 -7.39950001e-01 - -7.26450026e-01 -7.12949991e-01 -6.99450016e-01 -6.85949981e-01 - -6.72450006e-01 -6.58949971e-01 -6.45449996e-01 -6.31950021e-01 - -6.18449986e-01 -6.04950011e-01 -5.91449976e-01 -5.77950001e-01 - -5.64450026e-01 -5.50949991e-01 -5.37450016e-01 -5.23949981e-01 - -5.10450006e-01 -4.96950001e-01 -4.83449996e-01 -4.69949991e-01 - -4.56449986e-01 -4.42950010e-01 -4.29450005e-01 -4.15950000e-01 - -4.02449995e-01 -3.88949990e-01 -3.75449985e-01 -3.61950010e-01 - -3.48450005e-01 -3.34950000e-01 -3.21449995e-01 -3.07949990e-01 - -2.94450015e-01 -2.80950010e-01 -2.67450005e-01 -2.53950000e-01 - -2.40449995e-01 -2.26950005e-01 -2.13450000e-01 -1.99949995e-01 - -1.86450005e-01 -1.72950000e-01 -1.59449995e-01 -1.45950004e-01 - -1.32449999e-01 -1.18950002e-01 -1.05449997e-01 -9.19499993e-02 - -7.84500018e-02 -6.49499968e-02 -5.14499992e-02 -3.79500017e-02 - -2.44500004e-02 -1.09500000e-02 2.55000009e-03 1.60499997e-02 - 2.95499992e-02 4.30499986e-02 5.65499999e-02 7.00500011e-02 - 8.35499987e-02 9.70500037e-02 1.10550001e-01 1.24049999e-01 - 1.37549996e-01 1.51050001e-01 1.64550006e-01 1.78049996e-01 - 1.91550002e-01 2.05050007e-01 2.18549997e-01 2.32050002e-01 - 2.45550007e-01 2.59050012e-01 2.72549987e-01 2.86049992e-01 - 2.99549997e-01 3.13050002e-01 3.26550007e-01 3.40050012e-01 - 3.53549987e-01 3.67049992e-01 3.80549997e-01 3.94050002e-01 - 4.07550007e-01 4.21050012e-01 4.34549987e-01 4.48049992e-01 - 4.61549997e-01 4.75050002e-01 4.88550007e-01 5.02049983e-01 - 5.15550017e-01 5.29049993e-01 5.42550027e-01 5.56050003e-01 - 5.69549978e-01 5.83050013e-01 5.96549988e-01 6.10050023e-01 - 6.23549998e-01 6.37049973e-01 6.50550008e-01 6.64049983e-01 - 6.77550018e-01 6.91049993e-01 7.04550028e-01 7.18050003e-01 - 7.31549978e-01 7.45050013e-01 7.58549988e-01 7.72050023e-01 - 7.85549998e-01 7.99049973e-01 8.12550008e-01 8.26049984e-01 - 8.39550018e-01 8.53049994e-01 8.66550028e-01 8.80050004e-01 - 8.93549979e-01 9.07050014e-01 9.20549989e-01 9.34050024e-01 - 9.47549999e-01 9.61049974e-01 9.74550009e-01 9.88049984e-01 - 1.00154996e+00 1.01505005e+00 1.02855003e+00 1.04205000e+00 - 1.05554998e+00 1.06904995e+00 1.08255005e+00 1.09605002e+00 - 1.10955000e+00 1.12304997e+00 1.13654995e+00 1.15005004e+00 - 1.16355002e+00 1.17704999e+00 1.19054997e+00 1.20404994e+00 - 1.21755004e+00 1.23105001e+00 1.24454999e+00 1.25804996e+00 - 1.27155006e+00 1.28505003e+00 1.29855001e+00 1.31204998e+00 - 1.32554996e+00 1.33905005e+00 1.35255003e+00 1.36605000e+00 - 1.37954998e+00 1.39304996e+00 1.40655005e+00 1.42005002e+00 - 1.43355000e+00 1.44704998e+00 1.46054995e+00 1.47405005e+00 - 1.48755002e+00 1.50105000e+00 1.51454997e+00 1.52804995e+00 - 1.54155004e+00 1.55505002e+00 1.56854999e+00 1.58204997e+00 - 1.59554994e+00 1.60905004e+00 1.62255001e+00 1.63604999e+00 - 1.64954996e+00 1.66305006e+00 1.67655003e+00 1.69005001e+00 - 1.70354998e+00 1.71704996e+00 1.73055005e+00 1.74405003e+00 - 1.75755000e+00 1.77104998e+00 1.78454995e+00 1.79805005e+00 - 1.81155002e+00 1.82505000e+00 1.83854997e+00 1.85204995e+00 - 1.86555004e+00 1.87905002e+00 1.89254999e+00 1.90604997e+00 - 1.91954994e+00 1.93305004e+00 1.94655001e+00 1.96004999e+00 - 1.97354996e+00 1.98705006e+00 2.00055003e+00 2.01405001e+00 - 2.02754998e+00 2.04104996e+00 2.05454993e+00 2.06804991e+00 - 2.08154988e+00 2.09505010e+00 2.10855007e+00 2.12205005e+00 - 2.13555002e+00 2.14905000e+00 2.16254997e+00 2.17604995e+00 - 2.18954992e+00 2.20304990e+00 2.21655011e+00 2.23005009e+00 - 2.24355006e+00 2.25705004e+00 2.27055001e+00 2.28404999e+00 - 2.29754996e+00 2.31104994e+00 2.32454991e+00 2.33804989e+00 - 2.35155010e+00 2.36505008e+00 2.37855005e+00 2.39205003e+00 - 2.40555000e+00 2.41904998e+00 2.43254995e+00 2.44604993e+00 - 2.45954990e+00 2.47305012e+00 2.48655009e+00 2.50005007e+00 - 2.51355004e+00 2.52705002e+00 2.54054999e+00 2.55404997e+00 - 2.56754994e+00 2.58104992e+00 2.59454989e+00 2.60805011e+00 - 2.62155008e+00 2.63505006e+00 2.64855003e+00 2.66205001e+00 - 2.67554998e+00 2.68904996e+00 2.70254993e+00 2.71604991e+00 - 2.72954988e+00 2.74305010e+00 2.75655007e+00 2.77005005e+00 - 2.78355002e+00 2.79705000e+00 2.81054997e+00 2.82404995e+00 - 2.83754992e+00 2.85104990e+00 2.86455011e+00 2.87805009e+00 - 2.89155006e+00 2.90505004e+00 2.91855001e+00 2.93204999e+00 - 2.94554996e+00 2.95904994e+00 2.97254992e+00 2.98604989e+00 - 2.99955010e+00 3.01305008e+00 3.02655005e+00 3.04005003e+00 - 3.05355000e+00 3.06704998e+00 3.08054996e+00 3.09404993e+00 - 3.10754991e+00 3.12104988e+00 3.13455009e+00 3.14805007e+00 - 3.16155005e+00 3.17505002e+00 3.18855000e+00 3.20204997e+00 - 3.21554995e+00 3.22904992e+00 3.24254990e+00 3.25605011e+00 - 3.26955009e+00 3.28305006e+00 3.29655004e+00 3.31005001e+00 - 3.32354999e+00 3.33704996e+00 3.35054994e+00 3.36404991e+00 - 3.37754989e+00 3.39105010e+00 3.40455008e+00 3.41805005e+00 - 3.43155003e+00 3.44505000e+00 3.45854998e+00 3.47204995e+00 - 3.48554993e+00 3.49904990e+00 3.51255012e+00 3.52605009e+00 - 3.53955007e+00 3.55305004e+00 3.56655002e+00 3.58004999e+00 - 3.59354997e+00 3.60704994e+00 3.62054992e+00 3.63404989e+00 - 3.64755011e+00 3.66105008e+00 3.67455006e+00 3.68805003e+00 - 3.70155001e+00 3.71504998e+00 3.72854996e+00 3.74204993e+00 - 3.75554991e+00 3.76904988e+00 3.78255010e+00 3.79605007e+00 - 3.80955005e+00 3.82305002e+00 3.83655000e+00 3.85004997e+00 - 3.86354995e+00 3.87704992e+00 3.89054990e+00 3.90405011e+00 - 3.91755009e+00 3.93105006e+00 3.94455004e+00 3.95805001e+00 - 3.97154999e+00 3.98504996e+00 3.99854994e+00 4.01205015e+00 - 4.02554989e+00 4.03905010e+00 4.05254984e+00 4.06605005e+00 - 4.07954979e+00 4.09305000e+00 4.10655022e+00 4.12004995e+00 - 4.13355017e+00 4.14704990e+00 4.16055012e+00 4.17404985e+00 - 4.18755007e+00 4.20104980e+00 4.21455002e+00 4.22805023e+00 - 4.24154997e+00 4.25505018e+00 4.26854992e+00 4.28205013e+00 - 4.29554987e+00 4.30905008e+00 4.32254982e+00 4.33605003e+00 - 4.34954977e+00 4.36304998e+00 4.37655020e+00 4.39004993e+00 - 4.40355015e+00 4.41704988e+00 4.43055010e+00 4.44404984e+00 - 4.45755005e+00 4.47104979e+00 4.48455000e+00 4.49805021e+00 - 4.51154995e+00 4.52505016e+00 4.53854990e+00 4.55205011e+00 - 4.56554985e+00 4.57905006e+00 4.59254980e+00 4.60605001e+00 - 4.61955023e+00 4.63304996e+00 4.64655018e+00 4.66004992e+00 - 4.67355013e+00 4.68704987e+00 4.70055008e+00 4.71404982e+00 - 4.72755003e+00 4.74104977e+00 4.75454998e+00 4.76805019e+00 - 4.78154993e+00 4.79505014e+00 4.80854988e+00 4.82205009e+00 - 4.83554983e+00 4.84905005e+00 4.86254978e+00 4.87605000e+00 - 4.88955021e+00 4.90304995e+00 4.91655016e+00 4.93004990e+00 - 4.94355011e+00 4.95704985e+00 4.97055006e+00 4.98404980e+00 - 4.99755001e+00 5.01105022e+00 5.02454996e+00 5.03805017e+00 - 5.05154991e+00 5.06505013e+00 5.07854986e+00 5.09205008e+00 - 5.10554981e+00 5.11905003e+00 5.13254976e+00 5.14604998e+00 - 5.15955019e+00 5.17304993e+00 5.18655014e+00 5.20004988e+00 - 5.21355009e+00 5.22704983e+00 5.24055004e+00 5.25404978e+00 - 5.26754999e+00 5.28105021e+00 5.29454994e+00 5.30805016e+00 - 5.32154989e+00 5.33505011e+00 5.34854984e+00 5.36205006e+00 - 5.37554979e+00 5.38905001e+00 5.40255022e+00 5.41604996e+00 - 5.42955017e+00 5.44304991e+00 5.45655012e+00 5.47004986e+00 - 5.48355007e+00 5.49704981e+00 5.51055002e+00 5.52405024e+00 - 5.53754997e+00 5.55105019e+00 5.56454992e+00 5.57805014e+00 - 5.59154987e+00 5.60505009e+00 5.61854982e+00 5.63205004e+00 - 5.64554977e+00 5.65904999e+00 5.67255020e+00 5.68604994e+00 - 5.69955015e+00 5.71304989e+00 5.72655010e+00 5.74004984e+00 - 5.75355005e+00 5.76704979e+00 5.78055000e+00 5.79405022e+00 - 5.80754995e+00 5.82105017e+00 5.83454990e+00 5.84805012e+00 - 5.86154985e+00 5.87505007e+00 5.88854980e+00 5.90205002e+00 - 5.91555023e+00 5.92904997e+00 5.94255018e+00 5.95604992e+00 - 5.96955013e+00 5.98304987e+00 5.99655008e+00 6.01004982e+00 - 6.02355003e+00 6.03704977e+00 6.05054998e+00 6.06405020e+00 - 6.07754993e+00 6.09105015e+00 6.10454988e+00 6.11805010e+00 - 6.13154984e+00 6.14505005e+00 6.15854979e+00 6.17205000e+00 - 6.18555021e+00 6.19904995e+00 6.21255016e+00 6.22604990e+00 - 6.23955011e+00 6.25304985e+00 6.26655006e+00 6.28004980e+00 - 6.29355001e+00 6.30705023e+00 6.32054996e+00 6.33405018e+00 - 6.34754992e+00 6.36105013e+00 6.37454987e+00 6.38805008e+00 - 6.40154982e+00 6.41505003e+00 6.42854977e+00 6.44204998e+00 - 6.45555019e+00 6.46904993e+00 6.48255014e+00 6.49604988e+00 - 6.50955009e+00 6.52304983e+00 6.53655005e+00 6.55004978e+00 - 6.56355000e+00 6.57705021e+00 6.59054995e+00 6.60405016e+00 - 6.61754990e+00 6.63105011e+00 6.64454985e+00 6.65805006e+00 - 6.67154980e+00 6.68505001e+00 6.69855022e+00 6.71204996e+00 - 6.72555017e+00 6.73904991e+00 6.75255013e+00 6.76604986e+00 - 6.77955008e+00 6.79304981e+00 6.80655003e+00 6.82004976e+00 - 6.83354998e+00 6.84705019e+00 6.86054993e+00 6.87405014e+00 - 6.88754988e+00 6.90105009e+00 6.91454983e+00 6.92805004e+00 - 6.94154978e+00 6.95504999e+00 6.96855021e+00 6.98204994e+00 - 6.99555016e+00 7.00904989e+00 7.02255011e+00 7.03604984e+00 - 7.04955006e+00 7.06304979e+00 7.07655001e+00 7.09005022e+00 - 7.10354996e+00 7.11705017e+00 7.13054991e+00 7.14405012e+00 - 7.15782690e+00 7.17216969e+00 7.18710089e+00 7.20264530e+00 - 7.21882725e+00 7.23567390e+00 7.25321150e+00 7.27146959e+00 - 7.29047680e+00 7.31026411e+00 7.33086348e+00 7.35230875e+00 - 7.37463427e+00 7.39787626e+00 7.42207193e+00 7.44726086e+00 - 7.47348356e+00 7.50078297e+00 7.52920294e+00 7.55878925e+00 - 7.58959007e+00 7.62330008e+00 7.65929985e+00 7.69530010e+00 - 7.73129988e+00 7.76730013e+00 7.80329990e+00 7.83930016e+00 - 7.87529993e+00 7.91130018e+00 7.94729996e+00 7.98330021e+00 - 8.01930046e+00 8.05529976e+00 8.09130001e+00 8.12730026e+00 - 8.16329956e+00 8.19929981e+00 8.23530006e+00 8.27130032e+00 - 8.30729961e+00 8.34329987e+00 8.37930012e+00 8.41530037e+00 - 8.45129967e+00 8.48729992e+00 8.52330017e+00 8.55930042e+00 - 8.59529972e+00 8.63129997e+00 8.66730022e+00 8.70330048e+00 - 8.73929977e+00 8.77530003e+00 8.81130028e+00 8.84729958e+00 - 8.88329983e+00 8.91930008e+00 8.95530033e+00 8.99129963e+00] + data: [[100054. 100054. 100054. ... 100979. 100982. 100983.] + [100054. 100054. 100054. ... 100982. 100984. 100984.] + [100054. 100054. 100054. ... 100984. 100987. 100986.] + ... + [102198. 102205. 102212. ... 101691. 101664. 101661.] + [102204. 102211. 102218. ... 101693. 101673. 101668.] + [102210. 102217. 102225. ... 101705. 101682. 101675.]] + x: [353.0525 353.0885 353.1245 353.1605 353.1965 353.2325 353.2685 + 353.3045 353.3405 353.3765 353.4125 353.4485 353.4845 353.5205 + 353.5565 353.5925 353.6285 353.6645 353.7005 353.7365 353.7725 + 353.8085 353.8445 353.8805 353.9165 353.9525 353.9885 354.0245 + 354.0605 354.0965 354.1325 354.1685 354.2045 354.2405 354.2765 + 354.3125 354.3485 354.3845 354.4205 354.4565 354.4925 354.52185 + 354.5501 354.57736 354.60364 354.62894 354.65332 354.67685 354.6995 + 354.7213 354.74234 354.76263 354.78217 354.801 354.81915 354.83664 + 354.8535 354.86972 354.88538 354.90045 354.91498 354.929 354.9425 + 354.956 354.9695 354.983 354.9965 355.01 355.0235 355.037 + 355.0505 355.064 355.0775 355.091 355.1045 355.118 355.1315 + 355.145 355.1585 355.172 355.1855 355.199 355.2125 355.226 + 355.2395 355.253 355.2665 355.28 355.2935 355.307 355.3205 + 355.334 355.3475 355.361 355.3745 355.388 355.4015 355.415 + 355.4285 355.442 355.4555 355.469 355.4825 355.496 355.5095 + 355.523 355.5365 355.55 355.5635 355.577 355.5905 355.604 + 355.6175 355.631 355.6445 355.658 355.6715 355.685 355.6985 + 355.712 355.7255 355.739 355.7525 355.766 355.7795 355.793 + 355.8065 355.82 355.8335 355.847 355.8605 355.874 355.8875 + 355.901 355.9145 355.928 355.9415 355.955 355.9685 355.982 + 355.9955 356.009 356.0225 356.036 356.0495 356.063 356.0765 + 356.09 356.1035 356.117 356.1305 356.144 356.1575 356.171 + 356.1845 356.198 356.2115 356.225 356.2385 356.252 356.2655 + 356.279 356.2925 356.306 356.3195 356.333 356.3465 356.36 + 356.3735 356.387 356.4005 356.414 356.4275 356.441 356.4545 + 356.468 356.4815 356.495 356.5085 356.522 356.5355 356.549 + 356.5625 356.576 356.5895 356.603 356.6165 356.63 356.6435 + 356.657 356.6705 356.684 356.6975 356.711 356.7245 356.738 + 356.7515 356.765 356.7785 356.792 356.8055 356.819 356.8325 + 356.846 356.8595 356.873 356.8865 356.9 356.9135 356.927 + 356.9405 356.954 356.9675 356.981 356.9945 357.008 357.0215 + 357.035 357.0485 357.062 357.0755 357.089 357.1025 357.116 + 357.1295 357.143 357.1565 357.17 357.1835 357.197 357.2105 + 357.224 357.2375 357.251 357.2645 357.278 357.2915 357.305 + 357.3185 357.332 357.3455 357.359 357.3725 357.386 357.3995 + 357.413 357.4265 357.44 357.4535 357.467 357.4805 357.494 + 357.5075 357.521 357.5345 357.548 357.5615 357.575 357.5885 + 357.602 357.6155 357.629 357.6425 357.656 357.6695 357.683 + 357.6965 357.71 357.7235 357.737 357.7505 357.764 357.7775 + 357.791 357.8045 357.818 357.8315 357.845 357.8585 357.872 + 357.8855 357.899 357.9125 357.926 357.9395 357.953 357.9665 + 357.98 357.9935 358.007 358.0205 358.034 358.0475 358.061 + 358.0745 358.088 358.1015 358.115 358.1285 358.142 358.1555 + 358.169 358.1825 358.196 358.2095 358.223 358.2365 358.25 + 358.2635 358.277 358.2905 358.304 358.3175 358.331 358.3445 + 358.358 358.3715 358.385 358.3985 358.412 358.4255 358.439 + 358.4525 358.466 358.4795 358.493 358.5065 358.52 358.5335 + 358.547 358.5605 358.574 358.5875 358.601 358.6145 358.628 + 358.6415 358.655 358.6685 358.682 358.6955 358.709 358.7225 + 358.736 358.7495 358.763 358.7765 358.79 358.8035 358.817 + 358.8305 358.844 358.8575 358.871 358.8845 358.898 358.9115 + 358.925 358.9385 358.952 358.9655 358.979 358.9925 359.006 + 359.0195 359.033 359.0465 359.06 359.0735 359.087 359.1005 + 359.114 359.1275 359.141 359.1545 359.168 359.1815 359.195 + 359.2085 359.222 359.2355 359.249 359.2625 359.276 359.2895 + 359.303 359.3165 359.33 359.3435 359.357 359.3705 359.384 + 359.3975 359.411 359.4245 359.438 359.4515 359.465 359.4785 + 359.492 359.5055 359.519 359.5325 359.546 359.5595 359.573 + 359.5865 359.6 359.6135 359.627 359.6405 359.654 359.6675 + 359.681 359.6945 359.708 359.7215 359.735 359.7485 359.762 + 359.7755 359.789 359.8025 359.816 359.8295 359.843 359.8565 + 359.87 359.8835 359.897 359.9105 359.924 359.9375 359.951 + 359.9645 359.978 359.9915 360.005 360.0185 360.032 360.0455 + 360.059 360.0725 360.086 360.0995 360.113 360.1265 360.14 + 360.1535 360.167 360.1805 360.194 360.2075 360.221 360.2345 + 360.248 360.2615 360.275 360.2885 360.302 360.3155 360.329 + 360.3425 360.356 360.3695 360.383 360.3965 360.41 360.4235 + 360.437 360.4505 360.464 360.4775 360.491 360.5045 360.518 + 360.5315 360.545 360.5585 360.572 360.5855 360.599 360.6125 + 360.626 360.6395 360.653 360.6665 360.68 360.6935 360.707 + 360.7205 360.734 360.7475 360.761 360.7745 360.788 360.8015 + 360.815 360.8285 360.842 360.8555 360.869 360.8825 360.896 + 360.9095 360.923 360.9365 360.95 360.9635 360.977 360.9905 + 361.004 361.0175 361.031 361.0445 361.058 361.0715 361.085 + 361.0985 361.112 361.1255 361.139 361.1525 361.166 361.1795 + 361.193 361.2065 361.22 361.2335 361.247 361.2605 361.274 + 361.2875 361.301 361.3145 361.328 361.3415 361.355 361.3685 + 361.382 361.3955 361.409 361.4225 361.436 361.4495 361.463 + 361.4765 361.49 361.5035 361.517 361.5305 361.544 361.5575 + 361.571 361.5845 361.598 361.6115 361.625 361.6385 361.652 + 361.6655 361.679 361.6925 361.706 361.7195 361.733 361.7465 + 361.76 361.7735 361.787 361.8005 361.814 361.8275 361.841 + 361.8545 361.868 361.8815 361.895 361.9085 361.922 361.9355 + 361.949 361.9625 361.976 361.9895 362.003 362.0165 362.03 + 362.0435 362.057 362.0705 362.084 362.0975 362.111 362.1245 + 362.138 362.1515 362.165 362.1785 362.192 362.2055 362.219 + 362.2325 362.246 362.2595 362.273 362.2865 362.3 362.3135 + 362.327 362.3405 362.354 362.3675 362.381 362.3945 362.408 + 362.4215 362.435 362.4485 362.462 362.4755 362.489 362.5025 + 362.516 362.5295 362.543 362.5565 362.57 362.5835 362.597 + 362.6105 362.624 362.6375 362.651 362.6645 362.678 362.6915 + 362.705 362.7185 362.732 362.7455 362.759 362.7725 362.786 + 362.7995 362.813 362.8265 362.84 362.8535 362.867 362.8805 + 362.894 362.9075 362.921 362.9345 362.948 362.9615 362.975 + 362.9885 363.002 363.0155 363.029 363.0425 363.056 363.0695 + 363.083 363.0965 363.11 363.1235 363.137 363.1505 363.164 + 363.1775 363.191 363.2045 363.218 363.2315 363.245 363.2585 + 363.272 363.2855 363.299 363.3125 363.3265 363.34103 363.35614 + 363.37177 363.38803 363.40488 363.42236 363.4405 363.45932 363.47888 + 363.49915 363.52017 363.54202 363.56467 363.58817 363.61255 363.63788 + 363.66412 363.69138 363.71967 363.749 363.785 363.821 363.857 + 363.893 363.929 363.965 364.001 364.037 364.073 364.109 + 364.145 364.181 364.217 364.253 364.289 364.325 364.361 + 364.397 364.433 364.469 364.505 364.541 364.577 364.613 + 364.649 364.685 364.721 364.757 364.793 364.829 364.865 + 364.901 364.937 364.973 365.009 365.045 365.081 365.117 + 365.153 365.189 ] + x_lower_bound: [353.0345 353.0705 353.1065 353.1425 353.1785 353.2145 353.2505 + 353.2865 353.3225 353.3585 353.3945 353.4305 353.4665 353.5025 + 353.5385 353.5745 353.6105 353.6465 353.6825 353.7185 353.7545 + 353.7905 353.8265 353.8625 353.8985 353.9345 353.9705 354.0065 + 354.0425 354.0785 354.1145 354.1505 354.1865 354.2225 354.2585 + 354.2945 354.3305 354.3665 354.4025 354.4385 354.4745 354.50717 + 354.53598 354.56375 354.5905 354.61627 354.64114 354.66507 354.68817 + 354.7104 354.73184 354.7525 354.7724 354.7916 354.81006 354.82788 + 354.84506 354.8616 354.87753 354.8929 354.9077 354.922 354.93576 + 354.94925 354.96274 354.97626 354.98975 355.00323 355.01675 355.03024 + 355.04376 355.05725 355.07074 355.08426 355.09775 355.11124 355.12476 + 355.13824 355.15176 355.16525 355.17874 355.19226 355.20575 355.21924 + 355.23276 355.24625 355.25974 355.27325 355.28674 355.30026 355.31375 + 355.32724 355.34076 355.35425 355.36774 355.38126 355.39474 355.40826 + 355.42175 355.43524 355.44876 355.46225 355.47574 355.48926 355.50275 + 355.51624 355.52975 355.54324 355.55676 355.57025 355.58374 355.59726 + 355.61075 355.62424 355.63776 355.65125 355.66476 355.67825 355.69174 + 355.70526 355.71875 355.73224 355.74576 355.75925 355.77274 355.78625 + 355.79974 355.81326 355.82675 355.84024 355.85376 355.86725 355.88074 + 355.89426 355.90775 355.92126 355.93475 355.94824 355.96176 355.97525 + 355.98874 356.00226 356.01575 356.02924 356.04276 356.05624 356.06976 + 356.08325 356.09674 356.11026 356.12375 356.13724 356.15076 356.16425 + 356.17776 356.19125 356.20474 356.21826 356.23175 356.24524 356.25876 + 356.27225 356.28574 356.29926 356.31274 356.32626 356.33975 356.35324 + 356.36676 356.38025 356.39374 356.40726 356.42075 356.43427 356.44775 + 356.46124 356.47476 356.48825 356.50174 356.51526 356.52875 356.54224 + 356.55576 356.56924 356.58276 356.59625 356.60974 356.62326 356.63675 + 356.65024 356.66376 356.67725 356.69073 356.70425 356.71774 356.73126 + 356.74475 356.75824 356.77176 356.78525 356.79874 356.81226 356.82574 + 356.83926 356.85275 356.86624 356.87976 356.89325 356.90674 356.92026 + 356.93375 356.94724 356.96075 356.97424 356.98776 357.00125 357.01474 + 357.02826 357.04175 357.05524 357.06876 357.08224 357.09576 357.10925 + 357.12274 357.13626 357.14975 357.16324 357.17676 357.19025 357.20374 + 357.21725 357.23074 357.24426 357.25775 357.27124 357.28476 357.29825 + 357.31174 357.32526 357.33875 357.35226 357.36575 357.37924 357.39276 + 357.40625 357.41974 357.43326 357.44675 357.46024 357.47375 357.48724 + 357.50076 357.51425 357.52774 357.54126 357.55475 357.56824 357.58176 + 357.59525 357.60876 357.62225 357.63574 357.64926 357.66275 357.67624 + 357.68976 357.70325 357.71674 357.73026 357.74374 357.75726 357.77075 + 357.78424 357.79776 357.81125 357.82474 357.83826 357.85175 357.86526 + 357.87875 357.89224 357.90576 357.91925 357.93274 357.94626 357.95975 + 357.97324 357.98676 358.00024 358.01376 358.02725 358.04074 358.05426 + 358.06775 358.08124 358.09476 358.10825 358.12177 358.13525 358.14874 + 358.16226 358.17575 358.18924 358.20276 358.21625 358.22974 358.24326 + 358.25674 358.27026 358.28375 358.29724 358.31076 358.32425 358.33774 + 358.35126 358.36475 358.37823 358.39175 358.40524 358.41876 358.43225 + 358.44574 358.45926 358.47275 358.48624 358.49976 358.51324 358.52676 + 358.54025 358.55374 358.56726 358.58075 358.59424 358.60776 358.62125 + 358.63474 358.64825 358.66174 358.67526 358.68875 358.70224 358.71576 + 358.72925 358.74274 358.75626 358.76974 358.78326 358.79675 358.81024 + 358.82376 358.83725 358.85074 358.86426 358.87775 358.89124 358.90475 + 358.91824 358.93176 358.94525 358.95874 358.97226 358.98575 358.99924 + 359.01276 359.02625 359.03976 359.05325 359.06674 359.08026 359.09375 + 359.10724 359.12076 359.13425 359.14774 359.16125 359.17474 359.18826 + 359.20175 359.21524 359.22876 359.24225 359.25574 359.26926 359.28275 + 359.29626 359.30975 359.32324 359.33676 359.35025 359.36374 359.37726 + 359.39075 359.40424 359.41776 359.43124 359.44476 359.45825 359.47174 + 359.48526 359.49875 359.51224 359.52576 359.53925 359.55276 359.56625 + 359.57974 359.59326 359.60675 359.62024 359.63376 359.64725 359.66074 + 359.67426 359.68774 359.70126 359.71475 359.72824 359.74176 359.75525 + 359.76874 359.78226 359.79575 359.80927 359.82275 359.83624 359.84976 + 359.86325 359.87674 359.89026 359.90375 359.91724 359.93076 359.94424 + 359.95776 359.97125 359.98474 359.99826 360.01175 360.02524 360.03876 + 360.05225 360.06573 360.07925 360.09274 360.10626 360.11975 360.13324 + 360.14676 360.16025 360.17374 360.18726 360.20074 360.21426 360.22775 + 360.24124 360.25476 360.26825 360.28174 360.29526 360.30875 360.32224 + 360.33575 360.34924 360.36276 360.37625 360.38974 360.40326 360.41675 + 360.43024 360.44376 360.45724 360.47076 360.48425 360.49774 360.51126 + 360.52475 360.53824 360.55176 360.56525 360.57874 360.59225 360.60574 + 360.61926 360.63275 360.64624 360.65976 360.67325 360.68674 360.70026 + 360.71375 360.72726 360.74075 360.75424 360.76776 360.78125 360.79474 + 360.80826 360.82175 360.83524 360.84875 360.86224 360.87576 360.88925 + 360.90274 360.91626 360.92975 360.94324 360.95676 360.97025 360.98376 + 360.99725 361.01074 361.02426 361.03775 361.05124 361.06476 361.07825 + 361.09174 361.10526 361.11874 361.13226 361.14575 361.15924 361.17276 + 361.18625 361.19974 361.21326 361.22675 361.24026 361.25375 361.26724 + 361.28076 361.29425 361.30774 361.32126 361.33475 361.34824 361.36176 + 361.37524 361.38876 361.40225 361.41574 361.42926 361.44275 361.45624 + 361.46976 361.48325 361.49677 361.51025 361.52374 361.53726 361.55075 + 361.56424 361.57776 361.59125 361.60474 361.61826 361.63174 361.64526 + 361.65875 361.67224 361.68576 361.69925 361.71274 361.72626 361.73975 + 361.75323 361.76675 361.78024 361.79376 361.80725 361.82074 361.83426 + 361.84775 361.86124 361.87476 361.88824 361.90176 361.91525 361.92874 + 361.94226 361.95575 361.96924 361.98276 361.99625 362.00974 362.02325 + 362.03674 362.05026 362.06375 362.07724 362.09076 362.10425 362.11774 + 362.13126 362.14474 362.15826 362.17175 362.18524 362.19876 362.21225 + 362.22574 362.23926 362.25275 362.26624 362.27975 362.29324 362.30676 + 362.32025 362.33374 362.34726 362.36075 362.37424 362.38776 362.40125 + 362.41476 362.42825 362.44174 362.45526 362.46875 362.48224 362.49576 + 362.50925 362.52274 362.53625 362.54974 362.56326 362.57675 362.59024 + 362.60376 362.61725 362.63074 362.64426 362.65775 362.67126 362.68475 + 362.69824 362.71176 362.72525 362.73874 362.75226 362.76575 362.77924 + 362.79276 362.80624 362.81976 362.83325 362.84674 362.86026 362.87375 + 362.88724 362.90076 362.91425 362.92776 362.94125 362.95474 362.96826 + 362.98175 362.99524 363.00876 363.02225 363.03574 363.04926 363.06274 + 363.07626 363.08975 363.10324 363.11676 363.13025 363.14374 363.15726 + 363.17075 363.18427 363.19775 363.21124 363.22476 363.23825 363.25174 + 363.26526 363.27875 363.29224 363.30576 363.31952 363.33377 363.34857 + 363.36395 363.3799 363.39645 363.4136 363.43143 363.44992 363.46912 + 363.489 363.50967 363.5311 363.55334 363.57642 363.60037 363.6252 + 363.651 363.67776 363.7055 363.7343 363.767 363.803 363.839 + 363.875 363.911 363.947 363.983 364.019 364.055 364.091 + 364.127 364.163 364.199 364.235 364.271 364.307 364.343 + 364.379 364.415 364.451 364.487 364.523 364.559 364.595 + 364.631 364.667 364.703 364.739 364.775 364.811 364.847 + 364.883 364.919 364.955 364.991 365.027 365.063 365.099 + 365.135 365.171 ] + x_upper_bound: [353.0705 353.1065 353.1425 353.1785 353.2145 353.2505 353.2865 + 353.3225 353.3585 353.3945 353.4305 353.4665 353.5025 353.5385 + 353.5745 353.6105 353.6465 353.6825 353.7185 353.7545 353.7905 + 353.8265 353.8625 353.8985 353.9345 353.9705 354.0065 354.0425 + 354.0785 354.1145 354.1505 354.1865 354.2225 354.2585 354.2945 + 354.3305 354.3665 354.4025 354.4385 354.4745 354.50717 354.53598 + 354.56375 354.5905 354.61627 354.64114 354.66507 354.68817 354.7104 + 354.73184 354.7525 354.7724 354.7916 354.81006 354.82788 354.84506 + 354.8616 354.87753 354.8929 354.9077 354.922 354.93576 354.94925 + 354.96274 354.97626 354.98975 355.00323 355.01675 355.03024 355.04376 + 355.05725 355.07074 355.08426 355.09775 355.11124 355.12476 355.13824 + 355.15176 355.16525 355.17874 355.19226 355.20575 355.21924 355.23276 + 355.24625 355.25974 355.27325 355.28674 355.30026 355.31375 355.32724 + 355.34076 355.35425 355.36774 355.38126 355.39474 355.40826 355.42175 + 355.43524 355.44876 355.46225 355.47574 355.48926 355.50275 355.51624 + 355.52975 355.54324 355.55676 355.57025 355.58374 355.59726 355.61075 + 355.62424 355.63776 355.65125 355.66476 355.67825 355.69174 355.70526 + 355.71875 355.73224 355.74576 355.75925 355.77274 355.78625 355.79974 + 355.81326 355.82675 355.84024 355.85376 355.86725 355.88074 355.89426 + 355.90775 355.92126 355.93475 355.94824 355.96176 355.97525 355.98874 + 356.00226 356.01575 356.02924 356.04276 356.05624 356.06976 356.08325 + 356.09674 356.11026 356.12375 356.13724 356.15076 356.16425 356.17776 + 356.19125 356.20474 356.21826 356.23175 356.24524 356.25876 356.27225 + 356.28574 356.29926 356.31274 356.32626 356.33975 356.35324 356.36676 + 356.38025 356.39374 356.40726 356.42075 356.43427 356.44775 356.46124 + 356.47476 356.48825 356.50174 356.51526 356.52875 356.54224 356.55576 + 356.56924 356.58276 356.59625 356.60974 356.62326 356.63675 356.65024 + 356.66376 356.67725 356.69073 356.70425 356.71774 356.73126 356.74475 + 356.75824 356.77176 356.78525 356.79874 356.81226 356.82574 356.83926 + 356.85275 356.86624 356.87976 356.89325 356.90674 356.92026 356.93375 + 356.94724 356.96075 356.97424 356.98776 357.00125 357.01474 357.02826 + 357.04175 357.05524 357.06876 357.08224 357.09576 357.10925 357.12274 + 357.13626 357.14975 357.16324 357.17676 357.19025 357.20374 357.21725 + 357.23074 357.24426 357.25775 357.27124 357.28476 357.29825 357.31174 + 357.32526 357.33875 357.35226 357.36575 357.37924 357.39276 357.40625 + 357.41974 357.43326 357.44675 357.46024 357.47375 357.48724 357.50076 + 357.51425 357.52774 357.54126 357.55475 357.56824 357.58176 357.59525 + 357.60876 357.62225 357.63574 357.64926 357.66275 357.67624 357.68976 + 357.70325 357.71674 357.73026 357.74374 357.75726 357.77075 357.78424 + 357.79776 357.81125 357.82474 357.83826 357.85175 357.86526 357.87875 + 357.89224 357.90576 357.91925 357.93274 357.94626 357.95975 357.97324 + 357.98676 358.00024 358.01376 358.02725 358.04074 358.05426 358.06775 + 358.08124 358.09476 358.10825 358.12177 358.13525 358.14874 358.16226 + 358.17575 358.18924 358.20276 358.21625 358.22974 358.24326 358.25674 + 358.27026 358.28375 358.29724 358.31076 358.32425 358.33774 358.35126 + 358.36475 358.37823 358.39175 358.40524 358.41876 358.43225 358.44574 + 358.45926 358.47275 358.48624 358.49976 358.51324 358.52676 358.54025 + 358.55374 358.56726 358.58075 358.59424 358.60776 358.62125 358.63474 + 358.64825 358.66174 358.67526 358.68875 358.70224 358.71576 358.72925 + 358.74274 358.75626 358.76974 358.78326 358.79675 358.81024 358.82376 + 358.83725 358.85074 358.86426 358.87775 358.89124 358.90475 358.91824 + 358.93176 358.94525 358.95874 358.97226 358.98575 358.99924 359.01276 + 359.02625 359.03976 359.05325 359.06674 359.08026 359.09375 359.10724 + 359.12076 359.13425 359.14774 359.16125 359.17474 359.18826 359.20175 + 359.21524 359.22876 359.24225 359.25574 359.26926 359.28275 359.29626 + 359.30975 359.32324 359.33676 359.35025 359.36374 359.37726 359.39075 + 359.40424 359.41776 359.43124 359.44476 359.45825 359.47174 359.48526 + 359.49875 359.51224 359.52576 359.53925 359.55276 359.56625 359.57974 + 359.59326 359.60675 359.62024 359.63376 359.64725 359.66074 359.67426 + 359.68774 359.70126 359.71475 359.72824 359.74176 359.75525 359.76874 + 359.78226 359.79575 359.80927 359.82275 359.83624 359.84976 359.86325 + 359.87674 359.89026 359.90375 359.91724 359.93076 359.94424 359.95776 + 359.97125 359.98474 359.99826 360.01175 360.02524 360.03876 360.05225 + 360.06573 360.07925 360.09274 360.10626 360.11975 360.13324 360.14676 + 360.16025 360.17374 360.18726 360.20074 360.21426 360.22775 360.24124 + 360.25476 360.26825 360.28174 360.29526 360.30875 360.32224 360.33575 + 360.34924 360.36276 360.37625 360.38974 360.40326 360.41675 360.43024 + 360.44376 360.45724 360.47076 360.48425 360.49774 360.51126 360.52475 + 360.53824 360.55176 360.56525 360.57874 360.59225 360.60574 360.61926 + 360.63275 360.64624 360.65976 360.67325 360.68674 360.70026 360.71375 + 360.72726 360.74075 360.75424 360.76776 360.78125 360.79474 360.80826 + 360.82175 360.83524 360.84875 360.86224 360.87576 360.88925 360.90274 + 360.91626 360.92975 360.94324 360.95676 360.97025 360.98376 360.99725 + 361.01074 361.02426 361.03775 361.05124 361.06476 361.07825 361.09174 + 361.10526 361.11874 361.13226 361.14575 361.15924 361.17276 361.18625 + 361.19974 361.21326 361.22675 361.24026 361.25375 361.26724 361.28076 + 361.29425 361.30774 361.32126 361.33475 361.34824 361.36176 361.37524 + 361.38876 361.40225 361.41574 361.42926 361.44275 361.45624 361.46976 + 361.48325 361.49677 361.51025 361.52374 361.53726 361.55075 361.56424 + 361.57776 361.59125 361.60474 361.61826 361.63174 361.64526 361.65875 + 361.67224 361.68576 361.69925 361.71274 361.72626 361.73975 361.75323 + 361.76675 361.78024 361.79376 361.80725 361.82074 361.83426 361.84775 + 361.86124 361.87476 361.88824 361.90176 361.91525 361.92874 361.94226 + 361.95575 361.96924 361.98276 361.99625 362.00974 362.02325 362.03674 + 362.05026 362.06375 362.07724 362.09076 362.10425 362.11774 362.13126 + 362.14474 362.15826 362.17175 362.18524 362.19876 362.21225 362.22574 + 362.23926 362.25275 362.26624 362.27975 362.29324 362.30676 362.32025 + 362.33374 362.34726 362.36075 362.37424 362.38776 362.40125 362.41476 + 362.42825 362.44174 362.45526 362.46875 362.48224 362.49576 362.50925 + 362.52274 362.53625 362.54974 362.56326 362.57675 362.59024 362.60376 + 362.61725 362.63074 362.64426 362.65775 362.67126 362.68475 362.69824 + 362.71176 362.72525 362.73874 362.75226 362.76575 362.77924 362.79276 + 362.80624 362.81976 362.83325 362.84674 362.86026 362.87375 362.88724 + 362.90076 362.91425 362.92776 362.94125 362.95474 362.96826 362.98175 + 362.99524 363.00876 363.02225 363.03574 363.04926 363.06274 363.07626 + 363.08975 363.10324 363.11676 363.13025 363.14374 363.15726 363.17075 + 363.18427 363.19775 363.21124 363.22476 363.23825 363.25174 363.26526 + 363.27875 363.29224 363.30576 363.31952 363.33377 363.34857 363.36395 + 363.3799 363.39645 363.4136 363.43143 363.44992 363.46912 363.489 + 363.50967 363.5311 363.55334 363.57642 363.60037 363.6252 363.651 + 363.67776 363.7055 363.7343 363.767 363.803 363.839 363.875 + 363.911 363.947 363.983 364.019 364.055 364.091 364.127 + 364.163 364.199 364.235 364.271 364.307 364.343 364.379 + 364.415 364.451 364.487 364.523 364.559 364.595 364.631 + 364.667 364.703 364.739 364.775 364.811 364.847 364.883 + 364.919 364.955 364.991 365.027 365.063 365.099 365.135 + 365.171 365.207 ] + y: [-5.5932002e+00 -5.5572000e+00 -5.5212002e+00 -5.4851999e+00 + -5.4492002e+00 -5.4131999e+00 -5.3772001e+00 -5.3411999e+00 + -5.3052001e+00 -5.2691998e+00 -5.2332001e+00 -5.1971998e+00 + -5.1612000e+00 -5.1251998e+00 -5.0892000e+00 -5.0531998e+00 + -5.0172000e+00 -4.9812002e+00 -4.9452000e+00 -4.9092002e+00 + -4.8731999e+00 -4.8372002e+00 -4.8011999e+00 -4.7652001e+00 + -4.7291999e+00 -4.6932001e+00 -4.6571999e+00 -4.6212001e+00 + -4.5851998e+00 -4.5492001e+00 -4.5131998e+00 -4.4772000e+00 + -4.4411998e+00 -4.4052000e+00 -4.3692002e+00 -4.3332000e+00 + -4.2972002e+00 -4.2612000e+00 -4.2252002e+00 -4.1937799e+00 + -4.1635985e+00 -4.1346073e+00 -4.1067591e+00 -4.0800085e+00 + -4.0543132e+00 -4.0296307e+00 -4.0059214e+00 -3.9831471e+00 + -3.9612706e+00 -3.9402568e+00 -3.9200714e+00 -3.9006820e+00 + -3.8820570e+00 -3.8641663e+00 -3.8469810e+00 -3.8304734e+00 + -3.8146167e+00 -3.7993851e+00 -3.7847540e+00 -3.7707000e+00 + -3.7572000e+00 -3.7437000e+00 -3.7302001e+00 -3.7167001e+00 + -3.7032001e+00 -3.6896999e+00 -3.6761999e+00 -3.6626999e+00 + -3.6492000e+00 -3.6357000e+00 -3.6222000e+00 -3.6087000e+00 + -3.5952001e+00 -3.5817001e+00 -3.5682001e+00 -3.5546999e+00 + -3.5411999e+00 -3.5276999e+00 -3.5142000e+00 -3.5007000e+00 + -3.4872000e+00 -3.4737000e+00 -3.4602001e+00 -3.4467001e+00 + -3.4331999e+00 -3.4196999e+00 -3.4061999e+00 -3.3927000e+00 + -3.3792000e+00 -3.3657000e+00 -3.3522000e+00 -3.3387001e+00 + -3.3252001e+00 -3.3117001e+00 -3.2981999e+00 -3.2846999e+00 + -3.2711999e+00 -3.2577000e+00 -3.2442000e+00 -3.2307000e+00 + -3.2172000e+00 -3.2037001e+00 -3.1902001e+00 -3.1767001e+00 + -3.1631999e+00 -3.1496999e+00 -3.1362000e+00 -3.1227000e+00 + -3.1092000e+00 -3.0957000e+00 -3.0822001e+00 -3.0687001e+00 + -3.0552001e+00 -3.0416999e+00 -3.0281999e+00 -3.0146999e+00 + -3.0012000e+00 -2.9877000e+00 -2.9742000e+00 -2.9607000e+00 + -2.9472001e+00 -2.9337001e+00 -2.9202001e+00 -2.9066999e+00 + -2.8931999e+00 -2.8796999e+00 -2.8662000e+00 -2.8527000e+00 + -2.8392000e+00 -2.8257000e+00 -2.8122001e+00 -2.7987001e+00 + -2.7852001e+00 -2.7716999e+00 -2.7581999e+00 -2.7447000e+00 + -2.7312000e+00 -2.7177000e+00 -2.7042000e+00 -2.6907001e+00 + -2.6772001e+00 -2.6637001e+00 -2.6501999e+00 -2.6366999e+00 + -2.6231999e+00 -2.6097000e+00 -2.5962000e+00 -2.5827000e+00 + -2.5692000e+00 -2.5557001e+00 -2.5422001e+00 -2.5287001e+00 + -2.5151999e+00 -2.5016999e+00 -2.4881999e+00 -2.4747000e+00 + -2.4612000e+00 -2.4477000e+00 -2.4342000e+00 -2.4207001e+00 + -2.4072001e+00 -2.3936999e+00 -2.3801999e+00 -2.3666999e+00 + -2.3532000e+00 -2.3397000e+00 -2.3262000e+00 -2.3127000e+00 + -2.2992001e+00 -2.2857001e+00 -2.2722001e+00 -2.2586999e+00 + -2.2451999e+00 -2.2316999e+00 -2.2182000e+00 -2.2047000e+00 + -2.1912000e+00 -2.1777000e+00 -2.1642001e+00 -2.1507001e+00 + -2.1372001e+00 -2.1236999e+00 -2.1101999e+00 -2.0967000e+00 + -2.0832000e+00 -2.0697000e+00 -2.0562000e+00 -2.0427001e+00 + -2.0292001e+00 -2.0157001e+00 -2.0021999e+00 -1.9887000e+00 + -1.9752001e+00 -1.9617000e+00 -1.9482000e+00 -1.9347000e+00 + -1.9212000e+00 -1.9076999e+00 -1.8942000e+00 -1.8807000e+00 + -1.8672000e+00 -1.8537000e+00 -1.8401999e+00 -1.8267000e+00 + -1.8132000e+00 -1.7997000e+00 -1.7862000e+00 -1.7727000e+00 + -1.7592000e+00 -1.7457000e+00 -1.7322000e+00 -1.7187001e+00 + -1.7052000e+00 -1.6917000e+00 -1.6782000e+00 -1.6647000e+00 + -1.6512001e+00 -1.6377000e+00 -1.6242000e+00 -1.6107000e+00 + -1.5972000e+00 -1.5836999e+00 -1.5702000e+00 -1.5567000e+00 + -1.5432000e+00 -1.5297000e+00 -1.5161999e+00 -1.5027000e+00 + -1.4892000e+00 -1.4757000e+00 -1.4622000e+00 -1.4487000e+00 + -1.4352000e+00 -1.4217000e+00 -1.4082000e+00 -1.3947001e+00 + -1.3812000e+00 -1.3677000e+00 -1.3542000e+00 -1.3407000e+00 + -1.3272001e+00 -1.3137000e+00 -1.3002000e+00 -1.2867000e+00 + -1.2732000e+00 -1.2596999e+00 -1.2462000e+00 -1.2327000e+00 + -1.2192000e+00 -1.2057000e+00 -1.1921999e+00 -1.1787000e+00 + -1.1652000e+00 -1.1517000e+00 -1.1382000e+00 -1.1247000e+00 + -1.1112000e+00 -1.0977000e+00 -1.0842000e+00 -1.0707000e+00 + -1.0572000e+00 -1.0437000e+00 -1.0302000e+00 -1.0167000e+00 + -1.0032001e+00 -9.8970002e-01 -9.7619998e-01 -9.6270001e-01 + -9.4919997e-01 -9.3570000e-01 -9.2220002e-01 -9.0869999e-01 + -8.9520001e-01 -8.8169998e-01 -8.6820000e-01 -8.5470003e-01 + -8.4119999e-01 -8.2770002e-01 -8.1419998e-01 -8.0070001e-01 + -7.8719997e-01 -7.7370000e-01 -7.6020002e-01 -7.4669999e-01 + -7.3320001e-01 -7.1969998e-01 -7.0620000e-01 -6.9270003e-01 + -6.7919999e-01 -6.6570002e-01 -6.5219998e-01 -6.3870001e-01 + -6.2519997e-01 -6.1170000e-01 -5.9820002e-01 -5.8469999e-01 + -5.7120001e-01 -5.5769998e-01 -5.4420000e-01 -5.3070003e-01 + -5.1719999e-01 -5.0370002e-01 -4.9020001e-01 -4.7670001e-01 + -4.6320000e-01 -4.4970000e-01 -4.3619999e-01 -4.2269999e-01 + -4.0920001e-01 -3.9570001e-01 -3.8220000e-01 -3.6870000e-01 + -3.5519999e-01 -3.4169999e-01 -3.2820001e-01 -3.1470001e-01 + -3.0120000e-01 -2.8770000e-01 -2.7419999e-01 -2.6069999e-01 + -2.4720000e-01 -2.3370001e-01 -2.2020000e-01 -2.0670000e-01 + -1.9320001e-01 -1.7970000e-01 -1.6620000e-01 -1.5270001e-01 + -1.3920000e-01 -1.2570000e-01 -1.1220000e-01 -9.8700002e-02 + -8.5199997e-02 -7.1699999e-02 -5.8200002e-02 -4.4700000e-02 + -3.1199999e-02 -1.7700000e-02 -4.1999999e-03 9.3000000e-03 + 2.2800000e-02 3.6300000e-02 4.9800001e-02 6.3299999e-02 + 7.6800004e-02 9.0300001e-02 1.0380000e-01 1.1730000e-01 + 1.3079999e-01 1.4430000e-01 1.5780000e-01 1.7129999e-01 + 1.8480000e-01 1.9830000e-01 2.1179999e-01 2.2530000e-01 + 2.3880000e-01 2.5229999e-01 2.6580000e-01 2.7930000e-01 + 2.9280001e-01 3.0630001e-01 3.1979999e-01 3.3329999e-01 + 3.4680000e-01 3.6030000e-01 3.7380001e-01 3.8730001e-01 + 4.0079999e-01 4.1429999e-01 4.2780000e-01 4.4130000e-01 + 4.5480001e-01 4.6830001e-01 4.8179999e-01 4.9529999e-01 + 5.0880003e-01 5.2230000e-01 5.3579998e-01 5.4930001e-01 + 5.6279999e-01 5.7630002e-01 5.8980000e-01 6.0329998e-01 + 6.1680001e-01 6.3029999e-01 6.4380002e-01 6.5730000e-01 + 6.7079997e-01 6.8430001e-01 6.9779998e-01 7.1130002e-01 + 7.2479999e-01 7.3830003e-01 7.5180000e-01 7.6529998e-01 + 7.7880001e-01 7.9229999e-01 8.0580002e-01 8.1930000e-01 + 8.3279997e-01 8.4630001e-01 8.5979998e-01 8.7330002e-01 + 8.8679999e-01 9.0030003e-01 9.1380000e-01 9.2729998e-01 + 9.4080001e-01 9.5429999e-01 9.6780002e-01 9.8130000e-01 + 9.9479997e-01 1.0082999e+00 1.0218000e+00 1.0353000e+00 + 1.0488000e+00 1.0623000e+00 1.0757999e+00 1.0893000e+00 + 1.1028000e+00 1.1163000e+00 1.1298000e+00 1.1433001e+00 + 1.1568000e+00 1.1703000e+00 1.1838000e+00 1.1973000e+00 + 1.2108001e+00 1.2243000e+00 1.2378000e+00 1.2513000e+00 + 1.2648000e+00 1.2783000e+00 1.2918000e+00 1.3053000e+00 + 1.3188000e+00 1.3322999e+00 1.3458000e+00 1.3593000e+00 + 1.3728000e+00 1.3863000e+00 1.3997999e+00 1.4133000e+00 + 1.4268000e+00 1.4403000e+00 1.4538000e+00 1.4673001e+00 + 1.4808000e+00 1.4943000e+00 1.5078000e+00 1.5213000e+00 + 1.5348001e+00 1.5483000e+00 1.5618000e+00 1.5753000e+00 + 1.5888000e+00 1.6023000e+00 1.6158000e+00 1.6293000e+00 + 1.6428000e+00 1.6562999e+00 1.6698000e+00 1.6833000e+00 + 1.6968000e+00 1.7103000e+00 1.7237999e+00 1.7373000e+00 + 1.7508000e+00 1.7643000e+00 1.7778000e+00 1.7913001e+00 + 1.8048000e+00 1.8183000e+00 1.8318000e+00 1.8453000e+00 + 1.8588001e+00 1.8723000e+00 1.8858000e+00 1.8993000e+00 + 1.9128000e+00 1.9263000e+00 1.9398000e+00 1.9533000e+00 + 1.9668000e+00 1.9802999e+00 1.9938000e+00 2.0072999e+00 + 2.0208001e+00 2.0343001e+00 2.0478001e+00 2.0613000e+00 + 2.0748000e+00 2.0883000e+00 2.1018000e+00 2.1152999e+00 + 2.1287999e+00 2.1422999e+00 2.1558001e+00 2.1693001e+00 + 2.1828001e+00 2.1963000e+00 2.2098000e+00 2.2233000e+00 + 2.2368000e+00 2.2502999e+00 2.2637999e+00 2.2772999e+00 + 2.2908001e+00 2.3043001e+00 2.3178000e+00 2.3313000e+00 + 2.3448000e+00 2.3583000e+00 2.3717999e+00 2.3852999e+00 + 2.3987999e+00 2.4123001e+00 2.4258001e+00 2.4393001e+00 + 2.4528000e+00 2.4663000e+00 2.4798000e+00 2.4933000e+00 + 2.5067999e+00 2.5202999e+00 2.5337999e+00 2.5473001e+00 + 2.5608001e+00 2.5743001e+00 2.5878000e+00 2.6013000e+00 + 2.6148000e+00 2.6283000e+00 2.6417999e+00 2.6552999e+00 + 2.6688001e+00 2.6823001e+00 2.6958001e+00 2.7093000e+00 + 2.7228000e+00 2.7363000e+00 2.7498000e+00 2.7632999e+00 + 2.7767999e+00 2.7902999e+00 2.8038001e+00 2.8173001e+00 + 2.8308001e+00 2.8443000e+00 2.8578000e+00 2.8713000e+00 + 2.8848000e+00 2.8982999e+00 2.9117999e+00 2.9252999e+00 + 2.9388001e+00 2.9523001e+00 2.9658000e+00 2.9793000e+00 + 2.9928000e+00 3.0063000e+00 3.0197999e+00 3.0332999e+00 + 3.0467999e+00 3.0603001e+00 3.0738001e+00 3.0873001e+00 + 3.1008000e+00 3.1143000e+00 3.1278000e+00 3.1413000e+00 + 3.1547999e+00 3.1682999e+00 3.1817999e+00 3.1953001e+00 + 3.2088001e+00 3.2223001e+00 3.2358000e+00 3.2493000e+00 + 3.2628000e+00 3.2763000e+00 3.2897999e+00 3.3032999e+00 + 3.3168001e+00 3.3303001e+00 3.3438001e+00 3.3573000e+00 + 3.3708000e+00 3.3843000e+00 3.3978000e+00 3.4112999e+00 + 3.4247999e+00 3.4382999e+00 3.4518001e+00 3.4653001e+00 + 3.4788001e+00 3.4923000e+00 3.5058000e+00 3.5193000e+00 + 3.5328000e+00 3.5462999e+00 3.5597999e+00 3.5732999e+00 + 3.5868001e+00 3.6003001e+00 3.6138000e+00 3.6273000e+00 + 3.6408000e+00 3.6543000e+00 3.6677999e+00 3.6812999e+00 + 3.6947999e+00 3.7083001e+00 3.7218001e+00 3.7353001e+00 + 3.7488000e+00 3.7623000e+00 3.7758000e+00 3.7893000e+00 + 3.8027999e+00 3.8162999e+00 3.8297999e+00 3.8433001e+00 + 3.8568001e+00 3.8703001e+00 3.8838000e+00 3.8973000e+00 + 3.9108000e+00 3.9243000e+00 3.9377999e+00 3.9512999e+00 + 3.9647999e+00 3.9783001e+00 3.9918001e+00 4.0053000e+00 + 4.0187998e+00 4.0323000e+00 4.0458002e+00 4.0592999e+00 + 4.0728002e+00 4.0862999e+00 4.0998001e+00 4.1132998e+00 + 4.1268001e+00 4.1402998e+00 4.1538000e+00 4.1673002e+00 + 4.1808000e+00 4.1943002e+00 4.2077999e+00 4.2213001e+00 + 4.2347999e+00 4.2483001e+00 4.2617998e+00 4.2753000e+00 + 4.2887998e+00 4.3023000e+00 4.3158002e+00 4.3292999e+00 + 4.3428001e+00 4.3562999e+00 4.3698001e+00 4.3832998e+00 + 4.3968000e+00 4.4102998e+00 4.4238000e+00 4.4373002e+00 + 4.4507999e+00 4.4643002e+00 4.4777999e+00 4.4913001e+00 + 4.5047998e+00 4.5183001e+00 4.5317998e+00 4.5453000e+00 + 4.5588002e+00 4.5723000e+00 4.5858002e+00 4.5992999e+00 + 4.6128001e+00 4.6262999e+00 4.6398001e+00 4.6532998e+00 + 4.6668000e+00 4.6803002e+00 4.6938000e+00 4.7073002e+00 + 4.7207999e+00 4.7343001e+00 4.7477999e+00 4.7613001e+00 + 4.7747998e+00 4.7883000e+00 4.8017998e+00 4.8153000e+00 + 4.8288002e+00 4.8422999e+00 4.8558002e+00 4.8692999e+00 + 4.8828001e+00 4.8962998e+00 4.9098001e+00 4.9232998e+00 + 4.9368000e+00 4.9503002e+00 4.9638000e+00 4.9773002e+00 + 4.9907999e+00 5.0043001e+00 5.0177999e+00 5.0313001e+00 + 5.0447998e+00 5.0583000e+00 5.0718002e+00 5.0853000e+00 + 5.0988002e+00 5.1122999e+00 5.1258001e+00 5.1392999e+00 + 5.1528001e+00 5.1662998e+00 5.1798000e+00 5.1932998e+00 + 5.2068000e+00 5.2203002e+00 5.2337999e+00 5.2473001e+00 + 5.2607999e+00 5.2743001e+00 5.2877998e+00 5.3013000e+00 + 5.3147998e+00 5.3283000e+00 5.3418002e+00 5.3552999e+00 + 5.3688002e+00 5.3822999e+00 5.3958001e+00 5.4092999e+00 + 5.4228001e+00 5.4362998e+00 5.4498000e+00 5.4633002e+00 + 5.4768000e+00 5.4903002e+00 5.5037999e+00 5.5173001e+00 + 5.5307999e+00 5.5443001e+00 5.5577998e+00 5.5713000e+00 + 5.5847998e+00 5.5983000e+00 5.6118002e+00 5.6252999e+00 + 5.6388001e+00 5.6522999e+00 5.6658001e+00 5.6792998e+00 + 5.6928000e+00 5.7062998e+00 5.7198000e+00 5.7333002e+00 + 5.7467999e+00 5.7603002e+00 5.7737999e+00 5.7873001e+00 + 5.8007998e+00 5.8143001e+00 5.8277998e+00 5.8413000e+00 + 5.8548002e+00 5.8683000e+00 5.8818002e+00 5.8952999e+00 + 5.9088001e+00 5.9222999e+00 5.9358001e+00 5.9492998e+00 + 5.9628000e+00 5.9762998e+00 5.9898000e+00 6.0033002e+00 + 6.0167999e+00 6.0303001e+00 6.0437999e+00 6.0573001e+00 + 6.0707998e+00 6.0843000e+00 6.0977998e+00 6.1113000e+00 + 6.1248002e+00 6.1382999e+00 6.1518002e+00 6.1652999e+00 + 6.1788001e+00 6.1922998e+00 6.2058001e+00 6.2192998e+00 + 6.2328000e+00 6.2463002e+00 6.2598000e+00 6.2733002e+00 + 6.2867999e+00 6.3003001e+00 6.3137999e+00 6.3273001e+00 + 6.3407998e+00 6.3543000e+00 6.3678002e+00 6.3813000e+00 + 6.3948002e+00 6.4082999e+00 6.4218001e+00 6.4352999e+00 + 6.4488001e+00 6.4622998e+00 6.4758000e+00 6.4892998e+00 + 6.5028000e+00 6.5163002e+00 6.5297999e+00 6.5433002e+00 + 6.5567999e+00 6.5703001e+00 6.5837998e+00 6.5973001e+00 + 6.6107998e+00 6.6243000e+00 6.6378002e+00 6.6513000e+00 + 6.6648002e+00 6.6782999e+00 6.6918001e+00 6.7052999e+00 + 6.7188001e+00 6.7322998e+00 6.7458000e+00 6.7593002e+00 + 6.7728000e+00 6.7863002e+00 6.7997999e+00 6.8133001e+00 + 6.8267999e+00 6.8403001e+00 6.8537998e+00 6.8673000e+00 + 6.8807998e+00 6.8943000e+00 6.9078002e+00 6.9212999e+00 + 6.9348001e+00 6.9482999e+00 6.9618001e+00 6.9752998e+00 + 6.9888000e+00 7.0022998e+00 7.0158000e+00 7.0293002e+00 + 7.0427999e+00 7.0563002e+00 7.0697999e+00 7.0833001e+00 + 7.0967999e+00 7.1103001e+00 7.1237998e+00 7.1373000e+00 + 7.1508002e+00 7.1648540e+00 7.1794853e+00 7.1947169e+00 + 7.2105737e+00 7.2270813e+00 7.2442665e+00 7.2621570e+00 + 7.2807817e+00 7.3001714e+00 7.3203568e+00 7.3413706e+00 + 7.3632469e+00 7.3860216e+00 7.4097309e+00 7.4344130e+00 + 7.4601088e+00 7.4868588e+00 7.5147071e+00 7.5436983e+00 + 7.5738797e+00 7.6052999e+00 7.6413002e+00 7.6773000e+00 + 7.7133002e+00 7.7493000e+00 7.7852998e+00 7.8213000e+00 + 7.8572998e+00 7.8933001e+00 7.9292998e+00 7.9653001e+00 + 8.0012999e+00 8.0373001e+00 8.0733004e+00 8.1092997e+00 + 8.1452999e+00 8.1813002e+00 8.2173004e+00 8.2532997e+00 + 8.2893000e+00 8.3253002e+00 8.3613005e+00 8.3972998e+00 + 8.4333000e+00 8.4693003e+00 8.5052996e+00 8.5412998e+00 + 8.5773001e+00 8.6133003e+00 8.6492996e+00 8.6852999e+00 + 8.7213001e+00 8.7573004e+00 8.7932997e+00 8.8292999e+00 + 8.8653002e+00 8.9013004e+00 8.9372997e+00 8.9733000e+00] + y_lower_bound: [-5.6112003e+00 -5.5752001e+00 -5.5391998e+00 -5.5032001e+00 + -5.4671998e+00 -5.4312000e+00 -5.3951998e+00 -5.3592000e+00 + -5.3232002e+00 -5.2872000e+00 -5.2512002e+00 -5.2151999e+00 + -5.1792002e+00 -5.1431999e+00 -5.1072001e+00 -5.0711999e+00 + -5.0352001e+00 -4.9991999e+00 -4.9632001e+00 -4.9271998e+00 + -4.8912001e+00 -4.8551998e+00 -4.8192000e+00 -4.7831998e+00 + -4.7472000e+00 -4.7112002e+00 -4.6752000e+00 -4.6392002e+00 + -4.6032000e+00 -4.5672002e+00 -4.5311999e+00 -4.4952002e+00 + -4.4591999e+00 -4.4232001e+00 -4.3871999e+00 -4.3512001e+00 + -4.3151999e+00 -4.2792001e+00 -4.2431998e+00 -4.2094898e+00 + -4.1786890e+00 -4.1491027e+00 -4.1206832e+00 -4.0933838e+00 + -4.0671611e+00 -4.0419717e+00 -4.0177760e+00 -3.9945343e+00 + -3.9722090e+00 -3.9507637e+00 -3.9301641e+00 -3.9103768e+00 + -3.8913693e+00 -3.8731117e+00 -3.8555737e+00 -3.8387272e+00 + -3.8225451e+00 -3.8070009e+00 -3.7920697e+00 -3.7777271e+00 + -3.7639501e+00 -3.7504499e+00 -3.7369499e+00 -3.7234499e+00 + -3.7099500e+00 -3.6964500e+00 -3.6829500e+00 -3.6694500e+00 + -3.6559501e+00 -3.6424501e+00 -3.6289501e+00 -3.6154499e+00 + -3.6019499e+00 -3.5884500e+00 -3.5749500e+00 -3.5614500e+00 + -3.5479500e+00 -3.5344501e+00 -3.5209501e+00 -3.5074501e+00 + -3.4939499e+00 -3.4804499e+00 -3.4669499e+00 -3.4534500e+00 + -3.4399500e+00 -3.4264500e+00 -3.4129500e+00 -3.3994501e+00 + -3.3859501e+00 -3.3724501e+00 -3.3589499e+00 -3.3454499e+00 + -3.3319499e+00 -3.3184500e+00 -3.3049500e+00 -3.2914500e+00 + -3.2779500e+00 -3.2644501e+00 -3.2509501e+00 -3.2374499e+00 + -3.2239499e+00 -3.2104499e+00 -3.1969500e+00 -3.1834500e+00 + -3.1699500e+00 -3.1564500e+00 -3.1429501e+00 -3.1294501e+00 + -3.1159501e+00 -3.1024499e+00 -3.0889499e+00 -3.0754499e+00 + -3.0619500e+00 -3.0484500e+00 -3.0349500e+00 -3.0214500e+00 + -3.0079501e+00 -2.9944501e+00 -2.9809501e+00 -2.9674499e+00 + -2.9539499e+00 -2.9404500e+00 -2.9269500e+00 -2.9134500e+00 + -2.8999500e+00 -2.8864501e+00 -2.8729501e+00 -2.8594501e+00 + -2.8459499e+00 -2.8324499e+00 -2.8189499e+00 -2.8054500e+00 + -2.7919500e+00 -2.7784500e+00 -2.7649500e+00 -2.7514501e+00 + -2.7379501e+00 -2.7244501e+00 -2.7109499e+00 -2.6974499e+00 + -2.6839499e+00 -2.6704500e+00 -2.6569500e+00 -2.6434500e+00 + -2.6299500e+00 -2.6164501e+00 -2.6029501e+00 -2.5894499e+00 + -2.5759499e+00 -2.5624499e+00 -2.5489500e+00 -2.5354500e+00 + -2.5219500e+00 -2.5084500e+00 -2.4949501e+00 -2.4814501e+00 + -2.4679501e+00 -2.4544499e+00 -2.4409499e+00 -2.4274499e+00 + -2.4139500e+00 -2.4004500e+00 -2.3869500e+00 -2.3734500e+00 + -2.3599501e+00 -2.3464501e+00 -2.3329501e+00 -2.3194499e+00 + -2.3059499e+00 -2.2924500e+00 -2.2789500e+00 -2.2654500e+00 + -2.2519500e+00 -2.2384501e+00 -2.2249501e+00 -2.2114501e+00 + -2.1979499e+00 -2.1844499e+00 -2.1709499e+00 -2.1574500e+00 + -2.1439500e+00 -2.1304500e+00 -2.1169500e+00 -2.1034501e+00 + -2.0899501e+00 -2.0764501e+00 -2.0629499e+00 -2.0494499e+00 + -2.0359499e+00 -2.0224500e+00 -2.0089500e+00 -1.9954500e+00 + -1.9819500e+00 -1.9684500e+00 -1.9549500e+00 -1.9414500e+00 + -1.9279500e+00 -1.9144500e+00 -1.9009500e+00 -1.8874500e+00 + -1.8739500e+00 -1.8604500e+00 -1.8469501e+00 -1.8334500e+00 + -1.8199500e+00 -1.8064500e+00 -1.7929500e+00 -1.7794501e+00 + -1.7659500e+00 -1.7524500e+00 -1.7389500e+00 -1.7254500e+00 + -1.7119499e+00 -1.6984500e+00 -1.6849500e+00 -1.6714500e+00 + -1.6579500e+00 -1.6444499e+00 -1.6309500e+00 -1.6174500e+00 + -1.6039500e+00 -1.5904500e+00 -1.5769500e+00 -1.5634500e+00 + -1.5499500e+00 -1.5364500e+00 -1.5229501e+00 -1.5094500e+00 + -1.4959500e+00 -1.4824500e+00 -1.4689500e+00 -1.4554501e+00 + -1.4419500e+00 -1.4284500e+00 -1.4149500e+00 -1.4014500e+00 + -1.3879499e+00 -1.3744500e+00 -1.3609500e+00 -1.3474500e+00 + -1.3339500e+00 -1.3204499e+00 -1.3069500e+00 -1.2934500e+00 + -1.2799500e+00 -1.2664500e+00 -1.2529500e+00 -1.2394500e+00 + -1.2259500e+00 -1.2124500e+00 -1.1989501e+00 -1.1854500e+00 + -1.1719500e+00 -1.1584500e+00 -1.1449500e+00 -1.1314501e+00 + -1.1179500e+00 -1.1044500e+00 -1.0909500e+00 -1.0774500e+00 + -1.0639499e+00 -1.0504500e+00 -1.0369500e+00 -1.0234500e+00 + -1.0099500e+00 -9.9645001e-01 -9.8294997e-01 -9.6945000e-01 + -9.5595002e-01 -9.4244999e-01 -9.2895001e-01 -9.1544998e-01 + -9.0195000e-01 -8.8845003e-01 -8.7494999e-01 -8.6145002e-01 + -8.4794998e-01 -8.3445001e-01 -8.2094997e-01 -8.0745000e-01 + -7.9395002e-01 -7.8044999e-01 -7.6695001e-01 -7.5344998e-01 + -7.3995000e-01 -7.2645003e-01 -7.1294999e-01 -6.9945002e-01 + -6.8594998e-01 -6.7245001e-01 -6.5894997e-01 -6.4545000e-01 + -6.3195002e-01 -6.1844999e-01 -6.0495001e-01 -5.9144998e-01 + -5.7795000e-01 -5.6445003e-01 -5.5094999e-01 -5.3745002e-01 + -5.2394998e-01 -5.1045001e-01 -4.9695000e-01 -4.8345000e-01 + -4.6994999e-01 -4.5644999e-01 -4.4295001e-01 -4.2945001e-01 + -4.1595000e-01 -4.0245000e-01 -3.8894999e-01 -3.7544999e-01 + -3.6195001e-01 -3.4845001e-01 -3.3495000e-01 -3.2145000e-01 + -3.0794999e-01 -2.9445001e-01 -2.8095001e-01 -2.6745000e-01 + -2.5395000e-01 -2.4044999e-01 -2.2695000e-01 -2.1345000e-01 + -1.9994999e-01 -1.8645000e-01 -1.7295000e-01 -1.5944999e-01 + -1.4595000e-01 -1.3245000e-01 -1.1895000e-01 -1.0545000e-01 + -9.1949999e-02 -7.8450002e-02 -6.4949997e-02 -5.1449999e-02 + -3.7950002e-02 -2.4450000e-02 -1.0950000e-02 2.5500001e-03 + 1.6050000e-02 2.9549999e-02 4.3049999e-02 5.6550000e-02 + 7.0050001e-02 8.3549999e-02 9.7050004e-02 1.1055000e-01 + 1.2405000e-01 1.3755000e-01 1.5105000e-01 1.6455001e-01 + 1.7805000e-01 1.9155000e-01 2.0505001e-01 2.1855000e-01 + 2.3205000e-01 2.4555001e-01 2.5905001e-01 2.7254999e-01 + 2.8604999e-01 2.9955000e-01 3.1305000e-01 3.2655001e-01 + 3.4005001e-01 3.5354999e-01 3.6704999e-01 3.8055000e-01 + 3.9405000e-01 4.0755001e-01 4.2105001e-01 4.3454999e-01 + 4.4804999e-01 4.6155000e-01 4.7505000e-01 4.8855001e-01 + 5.0204998e-01 5.1555002e-01 5.2904999e-01 5.4255003e-01 + 5.5605000e-01 5.6954998e-01 5.8305001e-01 5.9654999e-01 + 6.1005002e-01 6.2355000e-01 6.3704997e-01 6.5055001e-01 + 6.6404998e-01 6.7755002e-01 6.9104999e-01 7.0455003e-01 + 7.1805000e-01 7.3154998e-01 7.4505001e-01 7.5854999e-01 + 7.7205002e-01 7.8555000e-01 7.9904997e-01 8.1255001e-01 + 8.2604998e-01 8.3955002e-01 8.5304999e-01 8.6655003e-01 + 8.8005000e-01 8.9354998e-01 9.0705001e-01 9.2054999e-01 + 9.3405002e-01 9.4755000e-01 9.6104997e-01 9.7455001e-01 + 9.8804998e-01 1.0015500e+00 1.0150501e+00 1.0285500e+00 + 1.0420500e+00 1.0555500e+00 1.0690500e+00 1.0825500e+00 + 1.0960500e+00 1.1095500e+00 1.1230500e+00 1.1365499e+00 + 1.1500500e+00 1.1635500e+00 1.1770500e+00 1.1905500e+00 + 1.2040499e+00 1.2175500e+00 1.2310500e+00 1.2445500e+00 + 1.2580500e+00 1.2715501e+00 1.2850500e+00 1.2985500e+00 + 1.3120500e+00 1.3255500e+00 1.3390501e+00 1.3525500e+00 + 1.3660500e+00 1.3795500e+00 1.3930500e+00 1.4065500e+00 + 1.4200500e+00 1.4335500e+00 1.4470500e+00 1.4605500e+00 + 1.4740500e+00 1.4875500e+00 1.5010500e+00 1.5145500e+00 + 1.5280499e+00 1.5415500e+00 1.5550500e+00 1.5685500e+00 + 1.5820500e+00 1.5955499e+00 1.6090500e+00 1.6225500e+00 + 1.6360500e+00 1.6495500e+00 1.6630501e+00 1.6765500e+00 + 1.6900500e+00 1.7035500e+00 1.7170500e+00 1.7305501e+00 + 1.7440500e+00 1.7575500e+00 1.7710500e+00 1.7845500e+00 + 1.7980500e+00 1.8115500e+00 1.8250500e+00 1.8385500e+00 + 1.8520499e+00 1.8655500e+00 1.8790500e+00 1.8925500e+00 + 1.9060500e+00 1.9195499e+00 1.9330500e+00 1.9465500e+00 + 1.9600500e+00 1.9735500e+00 1.9870501e+00 2.0005500e+00 + 2.0140500e+00 2.0275500e+00 2.0410500e+00 2.0545499e+00 + 2.0680499e+00 2.0815499e+00 2.0950501e+00 2.1085501e+00 + 2.1220500e+00 2.1355500e+00 2.1490500e+00 2.1625500e+00 + 2.1760499e+00 2.1895499e+00 2.2030499e+00 2.2165501e+00 + 2.2300501e+00 2.2435501e+00 2.2570500e+00 2.2705500e+00 + 2.2840500e+00 2.2975500e+00 2.3110499e+00 2.3245499e+00 + 2.3380499e+00 2.3515501e+00 2.3650501e+00 2.3785501e+00 + 2.3920500e+00 2.4055500e+00 2.4190500e+00 2.4325500e+00 + 2.4460499e+00 2.4595499e+00 2.4730501e+00 2.4865501e+00 + 2.5000501e+00 2.5135500e+00 2.5270500e+00 2.5405500e+00 + 2.5540500e+00 2.5675499e+00 2.5810499e+00 2.5945499e+00 + 2.6080501e+00 2.6215501e+00 2.6350501e+00 2.6485500e+00 + 2.6620500e+00 2.6755500e+00 2.6890500e+00 2.7025499e+00 + 2.7160499e+00 2.7295499e+00 2.7430501e+00 2.7565501e+00 + 2.7700500e+00 2.7835500e+00 2.7970500e+00 2.8105500e+00 + 2.8240499e+00 2.8375499e+00 2.8510499e+00 2.8645501e+00 + 2.8780501e+00 2.8915501e+00 2.9050500e+00 2.9185500e+00 + 2.9320500e+00 2.9455500e+00 2.9590499e+00 2.9725499e+00 + 2.9860499e+00 2.9995501e+00 3.0130501e+00 3.0265501e+00 + 3.0400500e+00 3.0535500e+00 3.0670500e+00 3.0805500e+00 + 3.0940499e+00 3.1075499e+00 3.1210499e+00 3.1345501e+00 + 3.1480501e+00 3.1615500e+00 3.1750500e+00 3.1885500e+00 + 3.2020500e+00 3.2155499e+00 3.2290499e+00 3.2425499e+00 + 3.2560501e+00 3.2695501e+00 3.2830501e+00 3.2965500e+00 + 3.3100500e+00 3.3235500e+00 3.3370500e+00 3.3505499e+00 + 3.3640499e+00 3.3775499e+00 3.3910501e+00 3.4045501e+00 + 3.4180501e+00 3.4315500e+00 3.4450500e+00 3.4585500e+00 + 3.4720500e+00 3.4855499e+00 3.4990499e+00 3.5125501e+00 + 3.5260501e+00 3.5395501e+00 3.5530500e+00 3.5665500e+00 + 3.5800500e+00 3.5935500e+00 3.6070499e+00 3.6205499e+00 + 3.6340499e+00 3.6475501e+00 3.6610501e+00 3.6745501e+00 + 3.6880500e+00 3.7015500e+00 3.7150500e+00 3.7285500e+00 + 3.7420499e+00 3.7555499e+00 3.7690499e+00 3.7825501e+00 + 3.7960501e+00 3.8095500e+00 3.8230500e+00 3.8365500e+00 + 3.8500500e+00 3.8635499e+00 3.8770499e+00 3.8905499e+00 + 3.9040501e+00 3.9175501e+00 3.9310501e+00 3.9445500e+00 + 3.9580500e+00 3.9715500e+00 3.9850500e+00 3.9985499e+00 + 4.0120502e+00 4.0255499e+00 4.0390501e+00 4.0525498e+00 + 4.0660501e+00 4.0795498e+00 4.0930500e+00 4.1065502e+00 + 4.1200500e+00 4.1335502e+00 4.1470499e+00 4.1605501e+00 + 4.1740499e+00 4.1875501e+00 4.2010498e+00 4.2145500e+00 + 4.2280502e+00 4.2415500e+00 4.2550502e+00 4.2685499e+00 + 4.2820501e+00 4.2955499e+00 4.3090501e+00 4.3225498e+00 + 4.3360500e+00 4.3495498e+00 4.3630500e+00 4.3765502e+00 + 4.3900499e+00 4.4035501e+00 4.4170499e+00 4.4305501e+00 + 4.4440498e+00 4.4575500e+00 4.4710498e+00 4.4845500e+00 + 4.4980502e+00 4.5115499e+00 4.5250502e+00 4.5385499e+00 + 4.5520501e+00 4.5655499e+00 4.5790501e+00 4.5925498e+00 + 4.6060500e+00 4.6195502e+00 4.6330500e+00 4.6465502e+00 + 4.6600499e+00 4.6735501e+00 4.6870499e+00 4.7005501e+00 + 4.7140498e+00 4.7275500e+00 4.7410498e+00 4.7545500e+00 + 4.7680502e+00 4.7815499e+00 4.7950501e+00 4.8085499e+00 + 4.8220501e+00 4.8355498e+00 4.8490500e+00 4.8625498e+00 + 4.8760500e+00 4.8895502e+00 4.9030499e+00 4.9165502e+00 + 4.9300499e+00 4.9435501e+00 4.9570498e+00 4.9705501e+00 + 4.9840498e+00 4.9975500e+00 5.0110502e+00 5.0245500e+00 + 5.0380502e+00 5.0515499e+00 5.0650501e+00 5.0785499e+00 + 5.0920501e+00 5.1055498e+00 5.1190500e+00 5.1325498e+00 + 5.1460500e+00 5.1595502e+00 5.1730499e+00 5.1865501e+00 + 5.2000499e+00 5.2135501e+00 5.2270498e+00 5.2405500e+00 + 5.2540498e+00 5.2675500e+00 5.2810502e+00 5.2945499e+00 + 5.3080502e+00 5.3215499e+00 5.3350501e+00 5.3485498e+00 + 5.3620501e+00 5.3755498e+00 5.3890500e+00 5.4025502e+00 + 5.4160500e+00 5.4295502e+00 5.4430499e+00 5.4565501e+00 + 5.4700499e+00 5.4835501e+00 5.4970498e+00 5.5105500e+00 + 5.5240502e+00 5.5375500e+00 5.5510502e+00 5.5645499e+00 + 5.5780501e+00 5.5915499e+00 5.6050501e+00 5.6185498e+00 + 5.6320500e+00 5.6455498e+00 5.6590500e+00 5.6725502e+00 + 5.6860499e+00 5.6995502e+00 5.7130499e+00 5.7265501e+00 + 5.7400498e+00 5.7535501e+00 5.7670498e+00 5.7805500e+00 + 5.7940502e+00 5.8075500e+00 5.8210502e+00 5.8345499e+00 + 5.8480501e+00 5.8615499e+00 5.8750501e+00 5.8885498e+00 + 5.9020500e+00 5.9155502e+00 5.9290500e+00 5.9425502e+00 + 5.9560499e+00 5.9695501e+00 5.9830499e+00 5.9965501e+00 + 6.0100498e+00 6.0235500e+00 6.0370498e+00 6.0505500e+00 + 6.0640502e+00 6.0775499e+00 6.0910501e+00 6.1045499e+00 + 6.1180501e+00 6.1315498e+00 6.1450500e+00 6.1585498e+00 + 6.1720500e+00 6.1855502e+00 6.1990499e+00 6.2125502e+00 + 6.2260499e+00 6.2395501e+00 6.2530499e+00 6.2665501e+00 + 6.2800498e+00 6.2935500e+00 6.3070502e+00 6.3205500e+00 + 6.3340502e+00 6.3475499e+00 6.3610501e+00 6.3745499e+00 + 6.3880501e+00 6.4015498e+00 6.4150500e+00 6.4285498e+00 + 6.4420500e+00 6.4555502e+00 6.4690499e+00 6.4825501e+00 + 6.4960499e+00 6.5095501e+00 6.5230498e+00 6.5365500e+00 + 6.5500498e+00 6.5635500e+00 6.5770502e+00 6.5905499e+00 + 6.6040502e+00 6.6175499e+00 6.6310501e+00 6.6445498e+00 + 6.6580501e+00 6.6715498e+00 6.6850500e+00 6.6985502e+00 + 6.7120500e+00 6.7255502e+00 6.7390499e+00 6.7525501e+00 + 6.7660499e+00 6.7795501e+00 6.7930498e+00 6.8065500e+00 + 6.8200498e+00 6.8335500e+00 6.8470502e+00 6.8605499e+00 + 6.8740501e+00 6.8875499e+00 6.9010501e+00 6.9145498e+00 + 6.9280500e+00 6.9415498e+00 6.9550500e+00 6.9685502e+00 + 6.9820499e+00 6.9955502e+00 7.0090499e+00 7.0225501e+00 + 7.0360498e+00 7.0495501e+00 7.0630498e+00 7.0765500e+00 + 7.0900502e+00 7.1035500e+00 7.1170502e+00 7.1305499e+00 + 7.1440501e+00 7.1578269e+00 7.1721697e+00 7.1871009e+00 + 7.2026453e+00 7.2188272e+00 7.2356739e+00 7.2532115e+00 + 7.2714696e+00 7.2904768e+00 7.3102641e+00 7.3308635e+00 + 7.3523088e+00 7.3746343e+00 7.3978763e+00 7.4220719e+00 + 7.4472609e+00 7.4734836e+00 7.5007830e+00 7.5292029e+00 + 7.5587893e+00 7.5895901e+00 7.6233001e+00 7.6592999e+00 + 7.6953001e+00 7.7312999e+00 7.7673001e+00 7.8032999e+00 + 7.8393002e+00 7.8752999e+00 7.9113002e+00 7.9473000e+00 + 7.9833002e+00 8.0193005e+00 8.0552998e+00 8.0913000e+00 + 8.1273003e+00 8.1632996e+00 8.1992998e+00 8.2353001e+00 + 8.2713003e+00 8.3072996e+00 8.3432999e+00 8.3793001e+00 + 8.4153004e+00 8.4512997e+00 8.4872999e+00 8.5233002e+00 + 8.5593004e+00 8.5952997e+00 8.6313000e+00 8.6673002e+00 + 8.7033005e+00 8.7392998e+00 8.7753000e+00 8.8113003e+00 + 8.8472996e+00 8.8832998e+00 8.9193001e+00 8.9553003e+00] + y_upper_bound: [-5.5752001e+00 -5.5391998e+00 -5.5032001e+00 -5.4671998e+00 + -5.4312000e+00 -5.3951998e+00 -5.3592000e+00 -5.3232002e+00 + -5.2872000e+00 -5.2512002e+00 -5.2151999e+00 -5.1792002e+00 + -5.1431999e+00 -5.1072001e+00 -5.0711999e+00 -5.0352001e+00 + -4.9991999e+00 -4.9632001e+00 -4.9271998e+00 -4.8912001e+00 + -4.8551998e+00 -4.8192000e+00 -4.7831998e+00 -4.7472000e+00 + -4.7112002e+00 -4.6752000e+00 -4.6392002e+00 -4.6032000e+00 + -4.5672002e+00 -4.5311999e+00 -4.4952002e+00 -4.4591999e+00 + -4.4232001e+00 -4.3871999e+00 -4.3512001e+00 -4.3151999e+00 + -4.2792001e+00 -4.2431998e+00 -4.2094898e+00 -4.1786890e+00 + -4.1491027e+00 -4.1206832e+00 -4.0933838e+00 -4.0671611e+00 + -4.0419717e+00 -4.0177760e+00 -3.9945343e+00 -3.9722090e+00 + -3.9507637e+00 -3.9301641e+00 -3.9103768e+00 -3.8913693e+00 + -3.8731117e+00 -3.8555737e+00 -3.8387272e+00 -3.8225451e+00 + -3.8070009e+00 -3.7920697e+00 -3.7777271e+00 -3.7639501e+00 + -3.7504499e+00 -3.7369499e+00 -3.7234499e+00 -3.7099500e+00 + -3.6964500e+00 -3.6829500e+00 -3.6694500e+00 -3.6559501e+00 + -3.6424501e+00 -3.6289501e+00 -3.6154499e+00 -3.6019499e+00 + -3.5884500e+00 -3.5749500e+00 -3.5614500e+00 -3.5479500e+00 + -3.5344501e+00 -3.5209501e+00 -3.5074501e+00 -3.4939499e+00 + -3.4804499e+00 -3.4669499e+00 -3.4534500e+00 -3.4399500e+00 + -3.4264500e+00 -3.4129500e+00 -3.3994501e+00 -3.3859501e+00 + -3.3724501e+00 -3.3589499e+00 -3.3454499e+00 -3.3319499e+00 + -3.3184500e+00 -3.3049500e+00 -3.2914500e+00 -3.2779500e+00 + -3.2644501e+00 -3.2509501e+00 -3.2374499e+00 -3.2239499e+00 + -3.2104499e+00 -3.1969500e+00 -3.1834500e+00 -3.1699500e+00 + -3.1564500e+00 -3.1429501e+00 -3.1294501e+00 -3.1159501e+00 + -3.1024499e+00 -3.0889499e+00 -3.0754499e+00 -3.0619500e+00 + -3.0484500e+00 -3.0349500e+00 -3.0214500e+00 -3.0079501e+00 + -2.9944501e+00 -2.9809501e+00 -2.9674499e+00 -2.9539499e+00 + -2.9404500e+00 -2.9269500e+00 -2.9134500e+00 -2.8999500e+00 + -2.8864501e+00 -2.8729501e+00 -2.8594501e+00 -2.8459499e+00 + -2.8324499e+00 -2.8189499e+00 -2.8054500e+00 -2.7919500e+00 + -2.7784500e+00 -2.7649500e+00 -2.7514501e+00 -2.7379501e+00 + -2.7244501e+00 -2.7109499e+00 -2.6974499e+00 -2.6839499e+00 + -2.6704500e+00 -2.6569500e+00 -2.6434500e+00 -2.6299500e+00 + -2.6164501e+00 -2.6029501e+00 -2.5894499e+00 -2.5759499e+00 + -2.5624499e+00 -2.5489500e+00 -2.5354500e+00 -2.5219500e+00 + -2.5084500e+00 -2.4949501e+00 -2.4814501e+00 -2.4679501e+00 + -2.4544499e+00 -2.4409499e+00 -2.4274499e+00 -2.4139500e+00 + -2.4004500e+00 -2.3869500e+00 -2.3734500e+00 -2.3599501e+00 + -2.3464501e+00 -2.3329501e+00 -2.3194499e+00 -2.3059499e+00 + -2.2924500e+00 -2.2789500e+00 -2.2654500e+00 -2.2519500e+00 + -2.2384501e+00 -2.2249501e+00 -2.2114501e+00 -2.1979499e+00 + -2.1844499e+00 -2.1709499e+00 -2.1574500e+00 -2.1439500e+00 + -2.1304500e+00 -2.1169500e+00 -2.1034501e+00 -2.0899501e+00 + -2.0764501e+00 -2.0629499e+00 -2.0494499e+00 -2.0359499e+00 + -2.0224500e+00 -2.0089500e+00 -1.9954500e+00 -1.9819500e+00 + -1.9684500e+00 -1.9549500e+00 -1.9414500e+00 -1.9279500e+00 + -1.9144500e+00 -1.9009500e+00 -1.8874500e+00 -1.8739500e+00 + -1.8604500e+00 -1.8469501e+00 -1.8334500e+00 -1.8199500e+00 + -1.8064500e+00 -1.7929500e+00 -1.7794501e+00 -1.7659500e+00 + -1.7524500e+00 -1.7389500e+00 -1.7254500e+00 -1.7119499e+00 + -1.6984500e+00 -1.6849500e+00 -1.6714500e+00 -1.6579500e+00 + -1.6444499e+00 -1.6309500e+00 -1.6174500e+00 -1.6039500e+00 + -1.5904500e+00 -1.5769500e+00 -1.5634500e+00 -1.5499500e+00 + -1.5364500e+00 -1.5229501e+00 -1.5094500e+00 -1.4959500e+00 + -1.4824500e+00 -1.4689500e+00 -1.4554501e+00 -1.4419500e+00 + -1.4284500e+00 -1.4149500e+00 -1.4014500e+00 -1.3879499e+00 + -1.3744500e+00 -1.3609500e+00 -1.3474500e+00 -1.3339500e+00 + -1.3204499e+00 -1.3069500e+00 -1.2934500e+00 -1.2799500e+00 + -1.2664500e+00 -1.2529500e+00 -1.2394500e+00 -1.2259500e+00 + -1.2124500e+00 -1.1989501e+00 -1.1854500e+00 -1.1719500e+00 + -1.1584500e+00 -1.1449500e+00 -1.1314501e+00 -1.1179500e+00 + -1.1044500e+00 -1.0909500e+00 -1.0774500e+00 -1.0639499e+00 + -1.0504500e+00 -1.0369500e+00 -1.0234500e+00 -1.0099500e+00 + -9.9645001e-01 -9.8294997e-01 -9.6945000e-01 -9.5595002e-01 + -9.4244999e-01 -9.2895001e-01 -9.1544998e-01 -9.0195000e-01 + -8.8845003e-01 -8.7494999e-01 -8.6145002e-01 -8.4794998e-01 + -8.3445001e-01 -8.2094997e-01 -8.0745000e-01 -7.9395002e-01 + -7.8044999e-01 -7.6695001e-01 -7.5344998e-01 -7.3995000e-01 + -7.2645003e-01 -7.1294999e-01 -6.9945002e-01 -6.8594998e-01 + -6.7245001e-01 -6.5894997e-01 -6.4545000e-01 -6.3195002e-01 + -6.1844999e-01 -6.0495001e-01 -5.9144998e-01 -5.7795000e-01 + -5.6445003e-01 -5.5094999e-01 -5.3745002e-01 -5.2394998e-01 + -5.1045001e-01 -4.9695000e-01 -4.8345000e-01 -4.6994999e-01 + -4.5644999e-01 -4.4295001e-01 -4.2945001e-01 -4.1595000e-01 + -4.0245000e-01 -3.8894999e-01 -3.7544999e-01 -3.6195001e-01 + -3.4845001e-01 -3.3495000e-01 -3.2145000e-01 -3.0794999e-01 + -2.9445001e-01 -2.8095001e-01 -2.6745000e-01 -2.5395000e-01 + -2.4044999e-01 -2.2695000e-01 -2.1345000e-01 -1.9994999e-01 + -1.8645000e-01 -1.7295000e-01 -1.5944999e-01 -1.4595000e-01 + -1.3245000e-01 -1.1895000e-01 -1.0545000e-01 -9.1949999e-02 + -7.8450002e-02 -6.4949997e-02 -5.1449999e-02 -3.7950002e-02 + -2.4450000e-02 -1.0950000e-02 2.5500001e-03 1.6050000e-02 + 2.9549999e-02 4.3049999e-02 5.6550000e-02 7.0050001e-02 + 8.3549999e-02 9.7050004e-02 1.1055000e-01 1.2405000e-01 + 1.3755000e-01 1.5105000e-01 1.6455001e-01 1.7805000e-01 + 1.9155000e-01 2.0505001e-01 2.1855000e-01 2.3205000e-01 + 2.4555001e-01 2.5905001e-01 2.7254999e-01 2.8604999e-01 + 2.9955000e-01 3.1305000e-01 3.2655001e-01 3.4005001e-01 + 3.5354999e-01 3.6704999e-01 3.8055000e-01 3.9405000e-01 + 4.0755001e-01 4.2105001e-01 4.3454999e-01 4.4804999e-01 + 4.6155000e-01 4.7505000e-01 4.8855001e-01 5.0204998e-01 + 5.1555002e-01 5.2904999e-01 5.4255003e-01 5.5605000e-01 + 5.6954998e-01 5.8305001e-01 5.9654999e-01 6.1005002e-01 + 6.2355000e-01 6.3704997e-01 6.5055001e-01 6.6404998e-01 + 6.7755002e-01 6.9104999e-01 7.0455003e-01 7.1805000e-01 + 7.3154998e-01 7.4505001e-01 7.5854999e-01 7.7205002e-01 + 7.8555000e-01 7.9904997e-01 8.1255001e-01 8.2604998e-01 + 8.3955002e-01 8.5304999e-01 8.6655003e-01 8.8005000e-01 + 8.9354998e-01 9.0705001e-01 9.2054999e-01 9.3405002e-01 + 9.4755000e-01 9.6104997e-01 9.7455001e-01 9.8804998e-01 + 1.0015500e+00 1.0150501e+00 1.0285500e+00 1.0420500e+00 + 1.0555500e+00 1.0690500e+00 1.0825500e+00 1.0960500e+00 + 1.1095500e+00 1.1230500e+00 1.1365499e+00 1.1500500e+00 + 1.1635500e+00 1.1770500e+00 1.1905500e+00 1.2040499e+00 + 1.2175500e+00 1.2310500e+00 1.2445500e+00 1.2580500e+00 + 1.2715501e+00 1.2850500e+00 1.2985500e+00 1.3120500e+00 + 1.3255500e+00 1.3390501e+00 1.3525500e+00 1.3660500e+00 + 1.3795500e+00 1.3930500e+00 1.4065500e+00 1.4200500e+00 + 1.4335500e+00 1.4470500e+00 1.4605500e+00 1.4740500e+00 + 1.4875500e+00 1.5010500e+00 1.5145500e+00 1.5280499e+00 + 1.5415500e+00 1.5550500e+00 1.5685500e+00 1.5820500e+00 + 1.5955499e+00 1.6090500e+00 1.6225500e+00 1.6360500e+00 + 1.6495500e+00 1.6630501e+00 1.6765500e+00 1.6900500e+00 + 1.7035500e+00 1.7170500e+00 1.7305501e+00 1.7440500e+00 + 1.7575500e+00 1.7710500e+00 1.7845500e+00 1.7980500e+00 + 1.8115500e+00 1.8250500e+00 1.8385500e+00 1.8520499e+00 + 1.8655500e+00 1.8790500e+00 1.8925500e+00 1.9060500e+00 + 1.9195499e+00 1.9330500e+00 1.9465500e+00 1.9600500e+00 + 1.9735500e+00 1.9870501e+00 2.0005500e+00 2.0140500e+00 + 2.0275500e+00 2.0410500e+00 2.0545499e+00 2.0680499e+00 + 2.0815499e+00 2.0950501e+00 2.1085501e+00 2.1220500e+00 + 2.1355500e+00 2.1490500e+00 2.1625500e+00 2.1760499e+00 + 2.1895499e+00 2.2030499e+00 2.2165501e+00 2.2300501e+00 + 2.2435501e+00 2.2570500e+00 2.2705500e+00 2.2840500e+00 + 2.2975500e+00 2.3110499e+00 2.3245499e+00 2.3380499e+00 + 2.3515501e+00 2.3650501e+00 2.3785501e+00 2.3920500e+00 + 2.4055500e+00 2.4190500e+00 2.4325500e+00 2.4460499e+00 + 2.4595499e+00 2.4730501e+00 2.4865501e+00 2.5000501e+00 + 2.5135500e+00 2.5270500e+00 2.5405500e+00 2.5540500e+00 + 2.5675499e+00 2.5810499e+00 2.5945499e+00 2.6080501e+00 + 2.6215501e+00 2.6350501e+00 2.6485500e+00 2.6620500e+00 + 2.6755500e+00 2.6890500e+00 2.7025499e+00 2.7160499e+00 + 2.7295499e+00 2.7430501e+00 2.7565501e+00 2.7700500e+00 + 2.7835500e+00 2.7970500e+00 2.8105500e+00 2.8240499e+00 + 2.8375499e+00 2.8510499e+00 2.8645501e+00 2.8780501e+00 + 2.8915501e+00 2.9050500e+00 2.9185500e+00 2.9320500e+00 + 2.9455500e+00 2.9590499e+00 2.9725499e+00 2.9860499e+00 + 2.9995501e+00 3.0130501e+00 3.0265501e+00 3.0400500e+00 + 3.0535500e+00 3.0670500e+00 3.0805500e+00 3.0940499e+00 + 3.1075499e+00 3.1210499e+00 3.1345501e+00 3.1480501e+00 + 3.1615500e+00 3.1750500e+00 3.1885500e+00 3.2020500e+00 + 3.2155499e+00 3.2290499e+00 3.2425499e+00 3.2560501e+00 + 3.2695501e+00 3.2830501e+00 3.2965500e+00 3.3100500e+00 + 3.3235500e+00 3.3370500e+00 3.3505499e+00 3.3640499e+00 + 3.3775499e+00 3.3910501e+00 3.4045501e+00 3.4180501e+00 + 3.4315500e+00 3.4450500e+00 3.4585500e+00 3.4720500e+00 + 3.4855499e+00 3.4990499e+00 3.5125501e+00 3.5260501e+00 + 3.5395501e+00 3.5530500e+00 3.5665500e+00 3.5800500e+00 + 3.5935500e+00 3.6070499e+00 3.6205499e+00 3.6340499e+00 + 3.6475501e+00 3.6610501e+00 3.6745501e+00 3.6880500e+00 + 3.7015500e+00 3.7150500e+00 3.7285500e+00 3.7420499e+00 + 3.7555499e+00 3.7690499e+00 3.7825501e+00 3.7960501e+00 + 3.8095500e+00 3.8230500e+00 3.8365500e+00 3.8500500e+00 + 3.8635499e+00 3.8770499e+00 3.8905499e+00 3.9040501e+00 + 3.9175501e+00 3.9310501e+00 3.9445500e+00 3.9580500e+00 + 3.9715500e+00 3.9850500e+00 3.9985499e+00 4.0120502e+00 + 4.0255499e+00 4.0390501e+00 4.0525498e+00 4.0660501e+00 + 4.0795498e+00 4.0930500e+00 4.1065502e+00 4.1200500e+00 + 4.1335502e+00 4.1470499e+00 4.1605501e+00 4.1740499e+00 + 4.1875501e+00 4.2010498e+00 4.2145500e+00 4.2280502e+00 + 4.2415500e+00 4.2550502e+00 4.2685499e+00 4.2820501e+00 + 4.2955499e+00 4.3090501e+00 4.3225498e+00 4.3360500e+00 + 4.3495498e+00 4.3630500e+00 4.3765502e+00 4.3900499e+00 + 4.4035501e+00 4.4170499e+00 4.4305501e+00 4.4440498e+00 + 4.4575500e+00 4.4710498e+00 4.4845500e+00 4.4980502e+00 + 4.5115499e+00 4.5250502e+00 4.5385499e+00 4.5520501e+00 + 4.5655499e+00 4.5790501e+00 4.5925498e+00 4.6060500e+00 + 4.6195502e+00 4.6330500e+00 4.6465502e+00 4.6600499e+00 + 4.6735501e+00 4.6870499e+00 4.7005501e+00 4.7140498e+00 + 4.7275500e+00 4.7410498e+00 4.7545500e+00 4.7680502e+00 + 4.7815499e+00 4.7950501e+00 4.8085499e+00 4.8220501e+00 + 4.8355498e+00 4.8490500e+00 4.8625498e+00 4.8760500e+00 + 4.8895502e+00 4.9030499e+00 4.9165502e+00 4.9300499e+00 + 4.9435501e+00 4.9570498e+00 4.9705501e+00 4.9840498e+00 + 4.9975500e+00 5.0110502e+00 5.0245500e+00 5.0380502e+00 + 5.0515499e+00 5.0650501e+00 5.0785499e+00 5.0920501e+00 + 5.1055498e+00 5.1190500e+00 5.1325498e+00 5.1460500e+00 + 5.1595502e+00 5.1730499e+00 5.1865501e+00 5.2000499e+00 + 5.2135501e+00 5.2270498e+00 5.2405500e+00 5.2540498e+00 + 5.2675500e+00 5.2810502e+00 5.2945499e+00 5.3080502e+00 + 5.3215499e+00 5.3350501e+00 5.3485498e+00 5.3620501e+00 + 5.3755498e+00 5.3890500e+00 5.4025502e+00 5.4160500e+00 + 5.4295502e+00 5.4430499e+00 5.4565501e+00 5.4700499e+00 + 5.4835501e+00 5.4970498e+00 5.5105500e+00 5.5240502e+00 + 5.5375500e+00 5.5510502e+00 5.5645499e+00 5.5780501e+00 + 5.5915499e+00 5.6050501e+00 5.6185498e+00 5.6320500e+00 + 5.6455498e+00 5.6590500e+00 5.6725502e+00 5.6860499e+00 + 5.6995502e+00 5.7130499e+00 5.7265501e+00 5.7400498e+00 + 5.7535501e+00 5.7670498e+00 5.7805500e+00 5.7940502e+00 + 5.8075500e+00 5.8210502e+00 5.8345499e+00 5.8480501e+00 + 5.8615499e+00 5.8750501e+00 5.8885498e+00 5.9020500e+00 + 5.9155502e+00 5.9290500e+00 5.9425502e+00 5.9560499e+00 + 5.9695501e+00 5.9830499e+00 5.9965501e+00 6.0100498e+00 + 6.0235500e+00 6.0370498e+00 6.0505500e+00 6.0640502e+00 + 6.0775499e+00 6.0910501e+00 6.1045499e+00 6.1180501e+00 + 6.1315498e+00 6.1450500e+00 6.1585498e+00 6.1720500e+00 + 6.1855502e+00 6.1990499e+00 6.2125502e+00 6.2260499e+00 + 6.2395501e+00 6.2530499e+00 6.2665501e+00 6.2800498e+00 + 6.2935500e+00 6.3070502e+00 6.3205500e+00 6.3340502e+00 + 6.3475499e+00 6.3610501e+00 6.3745499e+00 6.3880501e+00 + 6.4015498e+00 6.4150500e+00 6.4285498e+00 6.4420500e+00 + 6.4555502e+00 6.4690499e+00 6.4825501e+00 6.4960499e+00 + 6.5095501e+00 6.5230498e+00 6.5365500e+00 6.5500498e+00 + 6.5635500e+00 6.5770502e+00 6.5905499e+00 6.6040502e+00 + 6.6175499e+00 6.6310501e+00 6.6445498e+00 6.6580501e+00 + 6.6715498e+00 6.6850500e+00 6.6985502e+00 6.7120500e+00 + 6.7255502e+00 6.7390499e+00 6.7525501e+00 6.7660499e+00 + 6.7795501e+00 6.7930498e+00 6.8065500e+00 6.8200498e+00 + 6.8335500e+00 6.8470502e+00 6.8605499e+00 6.8740501e+00 + 6.8875499e+00 6.9010501e+00 6.9145498e+00 6.9280500e+00 + 6.9415498e+00 6.9550500e+00 6.9685502e+00 6.9820499e+00 + 6.9955502e+00 7.0090499e+00 7.0225501e+00 7.0360498e+00 + 7.0495501e+00 7.0630498e+00 7.0765500e+00 7.0900502e+00 + 7.1035500e+00 7.1170502e+00 7.1305499e+00 7.1440501e+00 + 7.1578269e+00 7.1721697e+00 7.1871009e+00 7.2026453e+00 + 7.2188272e+00 7.2356739e+00 7.2532115e+00 7.2714696e+00 + 7.2904768e+00 7.3102641e+00 7.3308635e+00 7.3523088e+00 + 7.3746343e+00 7.3978763e+00 7.4220719e+00 7.4472609e+00 + 7.4734836e+00 7.5007830e+00 7.5292029e+00 7.5587893e+00 + 7.5895901e+00 7.6233001e+00 7.6592999e+00 7.6953001e+00 + 7.7312999e+00 7.7673001e+00 7.8032999e+00 7.8393002e+00 + 7.8752999e+00 7.9113002e+00 7.9473000e+00 7.9833002e+00 + 8.0193005e+00 8.0552998e+00 8.0913000e+00 8.1273003e+00 + 8.1632996e+00 8.1992998e+00 8.2353001e+00 8.2713003e+00 + 8.3072996e+00 8.3432999e+00 8.3793001e+00 8.4153004e+00 + 8.4512997e+00 8.4872999e+00 8.5233002e+00 8.5593004e+00 + 8.5952997e+00 8.6313000e+00 8.6673002e+00 8.7033005e+00 + 8.7392998e+00 8.7753000e+00 8.8113003e+00 8.8472996e+00 + 8.8832998e+00 8.9193001e+00 8.9553003e+00 8.9912996e+00] , PP Field lbyr: 2010 lbmon: 2 @@ -3658,1158 +3280,1032 @@ bdy: 0.0 bzx: 0.0 bdx: 0.0 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 100016. 100016. 100016. ..., 100926. 100931. 100932.] - [ 100014. 100014. 100014. ..., 100930. 100934. 100934.] - [ 100015. 100015. 100015. ..., 100932. 100937. 100936.] - ..., - [ 102204. 102212. 102219. ..., 101650. 101623. 101623.] - [ 102210. 102218. 102225. ..., 101657. 101639. 101635.] - [ 102216. 102224. 102231. ..., 101675. 101654. 101648.]] - x: [ 353.05249023 353.08850098 353.12451172 353.16049194 353.19650269 - 353.23251343 353.26849365 353.30450439 353.34051514 353.37649536 - 353.4125061 353.44848633 353.48449707 353.52050781 353.55648804 - 353.59249878 353.62850952 353.66448975 353.70050049 353.73651123 - 353.77249146 353.8085022 353.84451294 353.88049316 353.91650391 - 353.95251465 353.98849487 354.02450562 354.06048584 354.09649658 - 354.13250732 354.16848755 354.20449829 354.24050903 354.27648926 - 354.3125 354.34851074 354.38449097 354.42050171 354.45651245 - 354.49249268 354.52185059 354.55010986 354.57736206 354.6036377 - 354.62893677 354.65332031 354.67684937 354.69949341 354.72131348 - 354.74234009 354.76263428 354.78216553 354.80099487 354.81915283 - 354.8366394 354.85348511 354.86972046 354.88537598 354.90045166 - 354.91497803 354.9289856 354.94250488 354.95599365 354.96951294 - 354.98300171 354.99649048 355.01000977 355.02349854 355.0369873 - 355.05050659 355.06399536 355.07751465 355.09100342 355.10449219 - 355.11801147 355.13150024 355.14498901 355.1585083 355.17199707 - 355.18548584 355.19900513 355.2124939 355.22601318 355.23950195 - 355.25299072 355.26651001 355.27999878 355.29348755 355.30700684 - 355.32049561 355.33401489 355.34750366 355.36099243 355.37451172 - 355.38800049 355.40148926 355.41500854 355.42849731 355.44198608 - 355.45550537 355.46899414 355.48251343 355.4960022 355.50949097 - 355.52301025 355.53649902 355.54998779 355.56350708 355.57699585 - 355.59051514 355.60400391 355.61749268 355.63101196 355.64450073 - 355.6579895 355.67150879 355.68499756 355.69848633 355.71200562 - 355.72549438 355.73901367 355.75250244 355.76599121 355.7795105 - 355.79299927 355.80648804 355.82000732 355.83349609 355.84698486 - 355.86050415 355.87399292 355.88751221 355.90100098 355.91448975 - 355.92800903 355.9414978 355.95498657 355.96850586 355.98199463 - 355.99551392 356.00900269 356.02249146 356.03601074 356.04949951 - 356.06298828 356.07650757 356.08999634 356.10348511 356.11700439 - 356.13049316 356.14401245 356.15750122 356.17098999 356.18450928 - 356.19799805 356.21148682 356.2250061 356.23849487 356.25201416 - 356.26550293 356.2789917 356.29251099 356.30599976 356.31948853 - 356.33300781 356.34649658 356.35998535 356.37350464 356.38699341 - 356.4005127 356.41400146 356.42749023 356.44100952 356.45449829 - 356.46798706 356.48150635 356.49499512 356.5085144 356.52200317 - 356.53549194 356.54901123 356.5625 356.57598877 356.58950806 - 356.60299683 356.6164856 356.63000488 356.64349365 356.65701294 - 356.67050171 356.68399048 356.69750977 356.71099854 356.7244873 - 356.73800659 356.75149536 356.76501465 356.77850342 356.79199219 - 356.80551147 356.81900024 356.83248901 356.8460083 356.85949707 - 356.87298584 356.88650513 356.8999939 356.91351318 356.92700195 - 356.94049072 356.95401001 356.96749878 356.98098755 356.99450684 - 357.00799561 357.02151489 357.03500366 357.04849243 357.06201172 - 357.07550049 357.08898926 357.10250854 357.11599731 357.12948608 - 357.14300537 357.15649414 357.17001343 357.1835022 357.19699097 - 357.21051025 357.22399902 357.23748779 357.25100708 357.26449585 - 357.27801514 357.29150391 357.30499268 357.31851196 357.33200073 - 357.3454895 357.35900879 357.37249756 357.38598633 357.39950562 - 357.41299438 357.42651367 357.44000244 357.45349121 357.4670105 - 357.48049927 357.49398804 357.50750732 357.52099609 357.53448486 - 357.54800415 357.56149292 357.57501221 357.58850098 357.60198975 - 357.61550903 357.6289978 357.64248657 357.65600586 357.66949463 - 357.68301392 357.69650269 357.70999146 357.72351074 357.73699951 - 357.75048828 357.76400757 357.77749634 357.79098511 357.80450439 - 357.81799316 357.83151245 357.84500122 357.85848999 357.87200928 - 357.88549805 357.89898682 357.9125061 357.92599487 357.93951416 - 357.95300293 357.9664917 357.98001099 357.99349976 358.00698853 - 358.02050781 358.03399658 358.04748535 358.06100464 358.07449341 - 358.0880127 358.10150146 358.11499023 358.12850952 358.14199829 - 358.15548706 358.16900635 358.18249512 358.1960144 358.20950317 - 358.22299194 358.23651123 358.25 358.26348877 358.27700806 - 358.29049683 358.3039856 358.31750488 358.33099365 358.34451294 - 358.35800171 358.37149048 358.38500977 358.39849854 358.4119873 - 358.42550659 358.43899536 358.45251465 358.46600342 358.47949219 - 358.49301147 358.50650024 358.51998901 358.5335083 358.54699707 - 358.56048584 358.57400513 358.5874939 358.60101318 358.61450195 - 358.62799072 358.64151001 358.65499878 358.66848755 358.68200684 - 358.69549561 358.70901489 358.72250366 358.73599243 358.74951172 - 358.76300049 358.77648926 358.79000854 358.80349731 358.81698608 - 358.83050537 358.84399414 358.85751343 358.8710022 358.88449097 - 358.89801025 358.91149902 358.92498779 358.93850708 358.95199585 - 358.96551514 358.97900391 358.99249268 359.00601196 359.01950073 - 359.0329895 359.04650879 359.05999756 359.07348633 359.08700562 - 359.10049438 359.11401367 359.12750244 359.14099121 359.1545105 - 359.16799927 359.18148804 359.19500732 359.20849609 359.22198486 - 359.23550415 359.24899292 359.26251221 359.27600098 359.28948975 - 359.30300903 359.3164978 359.32998657 359.34350586 359.35699463 - 359.37051392 359.38400269 359.39749146 359.41101074 359.42449951 - 359.43798828 359.45150757 359.46499634 359.47848511 359.49200439 - 359.50549316 359.51901245 359.53250122 359.54598999 359.55950928 - 359.57299805 359.58648682 359.6000061 359.61349487 359.62701416 - 359.64050293 359.6539917 359.66751099 359.68099976 359.69448853 - 359.70800781 359.72149658 359.73498535 359.74850464 359.76199341 - 359.7755127 359.78900146 359.80249023 359.81600952 359.82949829 - 359.84298706 359.85650635 359.86999512 359.8835144 359.89700317 - 359.91049194 359.92401123 359.9375 359.95098877 359.96450806 - 359.97799683 359.9914856 360.00500488 360.01849365 360.03201294 - 360.04550171 360.05899048 360.07250977 360.08599854 360.0994873 - 360.11300659 360.12649536 360.14001465 360.15350342 360.16699219 - 360.18051147 360.19400024 360.20748901 360.2210083 360.23449707 - 360.24798584 360.26150513 360.2749939 360.28851318 360.30200195 - 360.31549072 360.32901001 360.34249878 360.35598755 360.36950684 - 360.38299561 360.39651489 360.41000366 360.42349243 360.43701172 - 360.45050049 360.46398926 360.47750854 360.49099731 360.50448608 - 360.51800537 360.53149414 360.54501343 360.5585022 360.57199097 - 360.58551025 360.59899902 360.61248779 360.62600708 360.63949585 - 360.65301514 360.66650391 360.67999268 360.69351196 360.70700073 - 360.7204895 360.73400879 360.74749756 360.76098633 360.77450562 - 360.78799438 360.80151367 360.81500244 360.82849121 360.8420105 - 360.85549927 360.86898804 360.88250732 360.89599609 360.90948486 - 360.92300415 360.93649292 360.95001221 360.96350098 360.97698975 - 360.99050903 361.0039978 361.01748657 361.03100586 361.04449463 - 361.05801392 361.07150269 361.08499146 361.09851074 361.11199951 - 361.12548828 361.13900757 361.15249634 361.16598511 361.17950439 - 361.19299316 361.20651245 361.22000122 361.23348999 361.24700928 - 361.26049805 361.27398682 361.2875061 361.30099487 361.31451416 - 361.32800293 361.3414917 361.35501099 361.36849976 361.38198853 - 361.39550781 361.40899658 361.42248535 361.43600464 361.44949341 - 361.4630127 361.47650146 361.48999023 361.50350952 361.51699829 - 361.53048706 361.54400635 361.55749512 361.5710144 361.58450317 - 361.59799194 361.61151123 361.625 361.63848877 361.65200806 - 361.66549683 361.6789856 361.69250488 361.70599365 361.71951294 - 361.73300171 361.74649048 361.76000977 361.77349854 361.7869873 - 361.80050659 361.81399536 361.82751465 361.84100342 361.85449219 - 361.86801147 361.88150024 361.89498901 361.9085083 361.92199707 - 361.93548584 361.94900513 361.9624939 361.97601318 361.98950195 - 362.00299072 362.01651001 362.02999878 362.04348755 362.05700684 - 362.07049561 362.08401489 362.09750366 362.11099243 362.12451172 - 362.13800049 362.15148926 362.16500854 362.17849731 362.19198608 - 362.20550537 362.21899414 362.23251343 362.2460022 362.25949097 - 362.27301025 362.28649902 362.29998779 362.31350708 362.32699585 - 362.34051514 362.35400391 362.36749268 362.38101196 362.39450073 - 362.4079895 362.42150879 362.43499756 362.44848633 362.46200562 - 362.47549438 362.48901367 362.50250244 362.51599121 362.5295105 - 362.54299927 362.55648804 362.57000732 362.58349609 362.59698486 - 362.61050415 362.62399292 362.63751221 362.65100098 362.66448975 - 362.67800903 362.6914978 362.70498657 362.71850586 362.73199463 - 362.74551392 362.75900269 362.77249146 362.78601074 362.79949951 - 362.81298828 362.82650757 362.83999634 362.85348511 362.86700439 - 362.88049316 362.89401245 362.90750122 362.92098999 362.93450928 - 362.94799805 362.96148682 362.9750061 362.98849487 363.00201416 - 363.01550293 363.0289917 363.04251099 363.05599976 363.06948853 - 363.08300781 363.09649658 363.10998535 363.12350464 363.13699341 - 363.1505127 363.16400146 363.17749023 363.19100952 363.20449829 - 363.21798706 363.23150635 363.24499512 363.2585144 363.27200317 - 363.28549194 363.29901123 363.3125 363.32650757 363.34103394 - 363.35614014 363.37176514 363.38803101 363.40487671 363.42236328 - 363.44049072 363.45932007 363.47888184 363.49914551 363.52017212 - 363.54202271 363.56466675 363.58816528 363.61254883 363.63787842 - 363.66412354 363.69137573 363.71966553 363.74899292 363.78500366 - 363.8210144 363.85699463 363.89300537 363.9289856 363.96499634 - 364.00100708 364.0369873 364.07299805 364.10900879 364.14498901 - 364.18099976 364.2170105 364.25299072 364.28900146 364.32501221 - 364.36099243 364.39700317 364.43301392 364.46899414 364.50500488 - 364.54098511 364.57699585 364.61300659 364.64898682 364.68499756 - 364.7210083 364.75698853 364.79299927 364.82901001 364.86499023 - 364.90100098 364.93701172 364.97299194 365.00900269 365.04501343 - 365.08099365 365.11700439 365.15301514 365.18899536] - x_lower_bound: [ 353.03448486 353.07049561 353.10650635 353.14248657 353.17849731 - 353.21450806 353.25048828 353.28649902 353.32250977 353.35848999 - 353.39450073 353.43051147 353.4664917 353.50250244 353.53851318 - 353.57449341 353.61050415 353.64651489 353.68249512 353.71850586 - 353.75448608 353.79049683 353.82650757 353.86248779 353.89849854 - 353.93450928 353.9704895 354.00650024 354.04251099 354.07849121 - 354.11450195 354.1505127 354.18649292 354.22250366 354.2585144 - 354.29449463 354.33050537 354.3664856 354.40249634 354.43850708 - 354.4744873 354.50717163 354.53598022 354.56375122 354.59051514 - 354.61627197 354.6411438 354.66506958 354.68817139 354.71038818 - 354.73184204 354.75250244 354.7723999 354.79159546 354.81005859 - 354.82788086 354.84506226 354.86160278 354.87753296 354.89291382 - 354.90771484 354.92199707 354.9357605 354.94924927 354.96273804 - 354.97625732 354.98974609 355.00323486 355.01675415 355.03024292 - 355.04376221 355.05725098 355.07073975 355.08425903 355.0977478 - 355.11123657 355.12475586 355.13824463 355.15176392 355.16525269 - 355.17874146 355.19226074 355.20574951 355.21923828 355.23275757 - 355.24624634 355.25973511 355.27325439 355.28674316 355.30026245 - 355.31375122 355.32723999 355.34075928 355.35424805 355.36773682 - 355.3812561 355.39474487 355.40826416 355.42175293 355.4352417 - 355.44876099 355.46224976 355.47573853 355.48925781 355.50274658 - 355.51623535 355.52975464 355.54324341 355.5567627 355.57025146 - 355.58374023 355.59725952 355.61074829 355.62423706 355.63775635 - 355.65124512 355.6647644 355.67825317 355.69174194 355.70526123 - 355.71875 355.73223877 355.74575806 355.75924683 355.7727356 - 355.78625488 355.79974365 355.81326294 355.82675171 355.84024048 - 355.85375977 355.86724854 355.8807373 355.89425659 355.90774536 - 355.92126465 355.93475342 355.94824219 355.96176147 355.97525024 - 355.98873901 356.0022583 356.01574707 356.02923584 356.04275513 - 356.0562439 356.06976318 356.08325195 356.09674072 356.11026001 - 356.12374878 356.13723755 356.15075684 356.16424561 356.17776489 - 356.19125366 356.20474243 356.21826172 356.23175049 356.24523926 - 356.25875854 356.27224731 356.28573608 356.29925537 356.31274414 - 356.32626343 356.3397522 356.35324097 356.36676025 356.38024902 - 356.39373779 356.40725708 356.42074585 356.43426514 356.44775391 - 356.46124268 356.47476196 356.48825073 356.5017395 356.51525879 - 356.52874756 356.54223633 356.55575562 356.56924438 356.58276367 - 356.59625244 356.60974121 356.6232605 356.63674927 356.65023804 - 356.66375732 356.67724609 356.69073486 356.70425415 356.71774292 - 356.73126221 356.74475098 356.75823975 356.77175903 356.7852478 - 356.79873657 356.81225586 356.82574463 356.83926392 356.85275269 - 356.86624146 356.87976074 356.89324951 356.90673828 356.92025757 - 356.93374634 356.94723511 356.96075439 356.97424316 356.98776245 - 357.00125122 357.01473999 357.02825928 357.04174805 357.05523682 - 357.0687561 357.08224487 357.09576416 357.10925293 357.1227417 - 357.13626099 357.14974976 357.16323853 357.17675781 357.19024658 - 357.20373535 357.21725464 357.23074341 357.2442627 357.25775146 - 357.27124023 357.28475952 357.29824829 357.31173706 357.32525635 - 357.33874512 357.3522644 357.36575317 357.37924194 357.39276123 - 357.40625 357.41973877 357.43325806 357.44674683 357.4602356 - 357.47375488 357.48724365 357.50076294 357.51425171 357.52774048 - 357.54125977 357.55474854 357.5682373 357.58175659 357.59524536 - 357.60876465 357.62225342 357.63574219 357.64926147 357.66275024 - 357.67623901 357.6897583 357.70324707 357.71673584 357.73025513 - 357.7437439 357.75726318 357.77075195 357.78424072 357.79776001 - 357.81124878 357.82473755 357.83825684 357.85174561 357.86526489 - 357.87875366 357.89224243 357.90576172 357.91925049 357.93273926 - 357.94625854 357.95974731 357.97323608 357.98675537 358.00024414 - 358.01376343 358.0272522 358.04074097 358.05426025 358.06774902 - 358.08123779 358.09475708 358.10824585 358.12176514 358.13525391 - 358.14874268 358.16226196 358.17575073 358.1892395 358.20275879 - 358.21624756 358.22973633 358.24325562 358.25674438 358.27026367 - 358.28375244 358.29724121 358.3107605 358.32424927 358.33773804 - 358.35125732 358.36474609 358.37823486 358.39175415 358.40524292 - 358.41876221 358.43225098 358.44573975 358.45925903 358.4727478 - 358.48623657 358.49975586 358.51324463 358.52676392 358.54025269 - 358.55374146 358.56726074 358.58074951 358.59423828 358.60775757 - 358.62124634 358.63473511 358.64825439 358.66174316 358.67526245 - 358.68875122 358.70223999 358.71575928 358.72924805 358.74273682 - 358.7562561 358.76974487 358.78326416 358.79675293 358.8102417 - 358.82376099 358.83724976 358.85073853 358.86425781 358.87774658 - 358.89123535 358.90475464 358.91824341 358.9317627 358.94525146 - 358.95874023 358.97225952 358.98574829 358.99923706 359.01275635 - 359.02624512 359.0397644 359.05325317 359.06674194 359.08026123 - 359.09375 359.10723877 359.12075806 359.13424683 359.1477356 - 359.16125488 359.17474365 359.18826294 359.20175171 359.21524048 - 359.22875977 359.24224854 359.2557373 359.26925659 359.28274536 - 359.29626465 359.30975342 359.32324219 359.33676147 359.35025024 - 359.36373901 359.3772583 359.39074707 359.40423584 359.41775513 - 359.4312439 359.44476318 359.45825195 359.47174072 359.48526001 - 359.49874878 359.51223755 359.52575684 359.53924561 359.55276489 - 359.56625366 359.57974243 359.59326172 359.60675049 359.62023926 - 359.63375854 359.64724731 359.66073608 359.67425537 359.68774414 - 359.70126343 359.7147522 359.72824097 359.74176025 359.75524902 - 359.76873779 359.78225708 359.79574585 359.80926514 359.82275391 - 359.83624268 359.84976196 359.86325073 359.8767395 359.89025879 - 359.90374756 359.91723633 359.93075562 359.94424438 359.95776367 - 359.97125244 359.98474121 359.9982605 360.01174927 360.02523804 - 360.03875732 360.05224609 360.06573486 360.07925415 360.09274292 - 360.10626221 360.11975098 360.13323975 360.14675903 360.1602478 - 360.17373657 360.18725586 360.20074463 360.21426392 360.22775269 - 360.24124146 360.25476074 360.26824951 360.28173828 360.29525757 - 360.30874634 360.32223511 360.33575439 360.34924316 360.36276245 - 360.37625122 360.38973999 360.40325928 360.41674805 360.43023682 - 360.4437561 360.45724487 360.47076416 360.48425293 360.4977417 - 360.51126099 360.52474976 360.53823853 360.55175781 360.56524658 - 360.57873535 360.59225464 360.60574341 360.6192627 360.63275146 - 360.64624023 360.65975952 360.67324829 360.68673706 360.70025635 - 360.71374512 360.7272644 360.74075317 360.75424194 360.76776123 - 360.78125 360.79473877 360.80825806 360.82174683 360.8352356 - 360.84875488 360.86224365 360.87576294 360.88925171 360.90274048 - 360.91625977 360.92974854 360.9432373 360.95675659 360.97024536 - 360.98376465 360.99725342 361.01074219 361.02426147 361.03775024 - 361.05123901 361.0647583 361.07824707 361.09173584 361.10525513 - 361.1187439 361.13226318 361.14575195 361.15924072 361.17276001 - 361.18624878 361.19973755 361.21325684 361.22674561 361.24026489 - 361.25375366 361.26724243 361.28076172 361.29425049 361.30773926 - 361.32125854 361.33474731 361.34823608 361.36175537 361.37524414 - 361.38876343 361.4022522 361.41574097 361.42926025 361.44274902 - 361.45623779 361.46975708 361.48324585 361.49676514 361.51025391 - 361.52374268 361.53726196 361.55075073 361.5642395 361.57775879 - 361.59124756 361.60473633 361.61825562 361.63174438 361.64526367 - 361.65875244 361.67224121 361.6857605 361.69924927 361.71273804 - 361.72625732 361.73974609 361.75323486 361.76675415 361.78024292 - 361.79376221 361.80725098 361.82073975 361.83425903 361.8477478 - 361.86123657 361.87475586 361.88824463 361.90176392 361.91525269 - 361.92874146 361.94226074 361.95574951 361.96923828 361.98275757 - 361.99624634 362.00973511 362.02325439 362.03674316 362.05026245 - 362.06375122 362.07723999 362.09075928 362.10424805 362.11773682 - 362.1312561 362.14474487 362.15826416 362.17175293 362.1852417 - 362.19876099 362.21224976 362.22573853 362.23925781 362.25274658 - 362.26623535 362.27975464 362.29324341 362.3067627 362.32025146 - 362.33374023 362.34725952 362.36074829 362.37423706 362.38775635 - 362.40124512 362.4147644 362.42825317 362.44174194 362.45526123 - 362.46875 362.48223877 362.49575806 362.50924683 362.5227356 - 362.53625488 362.54974365 362.56326294 362.57675171 362.59024048 - 362.60375977 362.61724854 362.6307373 362.64425659 362.65774536 - 362.67126465 362.68475342 362.69824219 362.71176147 362.72525024 - 362.73873901 362.7522583 362.76574707 362.77923584 362.79275513 - 362.8062439 362.81976318 362.83325195 362.84674072 362.86026001 - 362.87374878 362.88723755 362.90075684 362.91424561 362.92776489 - 362.94125366 362.95474243 362.96826172 362.98175049 362.99523926 - 363.00875854 363.02224731 363.03573608 363.04925537 363.06274414 - 363.07626343 363.0897522 363.10324097 363.11676025 363.13024902 - 363.14373779 363.15725708 363.17074585 363.18426514 363.19775391 - 363.21124268 363.22476196 363.23825073 363.2517395 363.26525879 - 363.27874756 363.29223633 363.30575562 363.31951904 363.33377075 - 363.34857178 363.36395264 363.37991333 363.39645386 363.41360474 - 363.431427 363.44992065 363.46911621 363.48901367 363.50967407 - 363.53109741 363.55334473 363.57641602 363.60037231 363.62521362 - 363.65100098 363.67776489 363.70550537 363.73431396 363.76699829 - 363.80300903 363.83898926 363.875 363.91101074 363.94699097 - 363.98300171 364.01901245 364.05499268 364.09100342 364.12701416 - 364.16299438 364.19900513 364.23498535 364.27099609 364.30700684 - 364.34298706 364.3789978 364.41500854 364.45098877 364.48699951 - 364.52301025 364.55899048 364.59500122 364.63101196 364.66699219 - 364.70300293 364.73901367 364.7749939 364.81100464 364.84698486 - 364.88299561 364.91900635 364.95498657 364.99099731 365.02700806 - 365.06298828 365.09899902 365.13500977 365.17098999] - x_upper_bound: [ 353.07049561 353.10650635 353.14248657 353.17849731 353.21450806 - 353.25048828 353.28649902 353.32250977 353.35848999 353.39450073 - 353.43051147 353.4664917 353.50250244 353.53851318 353.57449341 - 353.61050415 353.64651489 353.68249512 353.71850586 353.75448608 - 353.79049683 353.82650757 353.86248779 353.89849854 353.93450928 - 353.9704895 354.00650024 354.04251099 354.07849121 354.11450195 - 354.1505127 354.18649292 354.22250366 354.2585144 354.29449463 - 354.33050537 354.3664856 354.40249634 354.43850708 354.4744873 - 354.50717163 354.53598022 354.56375122 354.59051514 354.61627197 - 354.6411438 354.66506958 354.68817139 354.71038818 354.73184204 - 354.75250244 354.7723999 354.79159546 354.81005859 354.82788086 - 354.84506226 354.86160278 354.87753296 354.89291382 354.90771484 - 354.92199707 354.9357605 354.94924927 354.96273804 354.97625732 - 354.98974609 355.00323486 355.01675415 355.03024292 355.04376221 - 355.05725098 355.07073975 355.08425903 355.0977478 355.11123657 - 355.12475586 355.13824463 355.15176392 355.16525269 355.17874146 - 355.19226074 355.20574951 355.21923828 355.23275757 355.24624634 - 355.25973511 355.27325439 355.28674316 355.30026245 355.31375122 - 355.32723999 355.34075928 355.35424805 355.36773682 355.3812561 - 355.39474487 355.40826416 355.42175293 355.4352417 355.44876099 - 355.46224976 355.47573853 355.48925781 355.50274658 355.51623535 - 355.52975464 355.54324341 355.5567627 355.57025146 355.58374023 - 355.59725952 355.61074829 355.62423706 355.63775635 355.65124512 - 355.6647644 355.67825317 355.69174194 355.70526123 355.71875 - 355.73223877 355.74575806 355.75924683 355.7727356 355.78625488 - 355.79974365 355.81326294 355.82675171 355.84024048 355.85375977 - 355.86724854 355.8807373 355.89425659 355.90774536 355.92126465 - 355.93475342 355.94824219 355.96176147 355.97525024 355.98873901 - 356.0022583 356.01574707 356.02923584 356.04275513 356.0562439 - 356.06976318 356.08325195 356.09674072 356.11026001 356.12374878 - 356.13723755 356.15075684 356.16424561 356.17776489 356.19125366 - 356.20474243 356.21826172 356.23175049 356.24523926 356.25875854 - 356.27224731 356.28573608 356.29925537 356.31274414 356.32626343 - 356.3397522 356.35324097 356.36676025 356.38024902 356.39373779 - 356.40725708 356.42074585 356.43426514 356.44775391 356.46124268 - 356.47476196 356.48825073 356.5017395 356.51525879 356.52874756 - 356.54223633 356.55575562 356.56924438 356.58276367 356.59625244 - 356.60974121 356.6232605 356.63674927 356.65023804 356.66375732 - 356.67724609 356.69073486 356.70425415 356.71774292 356.73126221 - 356.74475098 356.75823975 356.77175903 356.7852478 356.79873657 - 356.81225586 356.82574463 356.83926392 356.85275269 356.86624146 - 356.87976074 356.89324951 356.90673828 356.92025757 356.93374634 - 356.94723511 356.96075439 356.97424316 356.98776245 357.00125122 - 357.01473999 357.02825928 357.04174805 357.05523682 357.0687561 - 357.08224487 357.09576416 357.10925293 357.1227417 357.13626099 - 357.14974976 357.16323853 357.17675781 357.19024658 357.20373535 - 357.21725464 357.23074341 357.2442627 357.25775146 357.27124023 - 357.28475952 357.29824829 357.31173706 357.32525635 357.33874512 - 357.3522644 357.36575317 357.37924194 357.39276123 357.40625 - 357.41973877 357.43325806 357.44674683 357.4602356 357.47375488 - 357.48724365 357.50076294 357.51425171 357.52774048 357.54125977 - 357.55474854 357.5682373 357.58175659 357.59524536 357.60876465 - 357.62225342 357.63574219 357.64926147 357.66275024 357.67623901 - 357.6897583 357.70324707 357.71673584 357.73025513 357.7437439 - 357.75726318 357.77075195 357.78424072 357.79776001 357.81124878 - 357.82473755 357.83825684 357.85174561 357.86526489 357.87875366 - 357.89224243 357.90576172 357.91925049 357.93273926 357.94625854 - 357.95974731 357.97323608 357.98675537 358.00024414 358.01376343 - 358.0272522 358.04074097 358.05426025 358.06774902 358.08123779 - 358.09475708 358.10824585 358.12176514 358.13525391 358.14874268 - 358.16226196 358.17575073 358.1892395 358.20275879 358.21624756 - 358.22973633 358.24325562 358.25674438 358.27026367 358.28375244 - 358.29724121 358.3107605 358.32424927 358.33773804 358.35125732 - 358.36474609 358.37823486 358.39175415 358.40524292 358.41876221 - 358.43225098 358.44573975 358.45925903 358.4727478 358.48623657 - 358.49975586 358.51324463 358.52676392 358.54025269 358.55374146 - 358.56726074 358.58074951 358.59423828 358.60775757 358.62124634 - 358.63473511 358.64825439 358.66174316 358.67526245 358.68875122 - 358.70223999 358.71575928 358.72924805 358.74273682 358.7562561 - 358.76974487 358.78326416 358.79675293 358.8102417 358.82376099 - 358.83724976 358.85073853 358.86425781 358.87774658 358.89123535 - 358.90475464 358.91824341 358.9317627 358.94525146 358.95874023 - 358.97225952 358.98574829 358.99923706 359.01275635 359.02624512 - 359.0397644 359.05325317 359.06674194 359.08026123 359.09375 - 359.10723877 359.12075806 359.13424683 359.1477356 359.16125488 - 359.17474365 359.18826294 359.20175171 359.21524048 359.22875977 - 359.24224854 359.2557373 359.26925659 359.28274536 359.29626465 - 359.30975342 359.32324219 359.33676147 359.35025024 359.36373901 - 359.3772583 359.39074707 359.40423584 359.41775513 359.4312439 - 359.44476318 359.45825195 359.47174072 359.48526001 359.49874878 - 359.51223755 359.52575684 359.53924561 359.55276489 359.56625366 - 359.57974243 359.59326172 359.60675049 359.62023926 359.63375854 - 359.64724731 359.66073608 359.67425537 359.68774414 359.70126343 - 359.7147522 359.72824097 359.74176025 359.75524902 359.76873779 - 359.78225708 359.79574585 359.80926514 359.82275391 359.83624268 - 359.84976196 359.86325073 359.8767395 359.89025879 359.90374756 - 359.91723633 359.93075562 359.94424438 359.95776367 359.97125244 - 359.98474121 359.9982605 360.01174927 360.02523804 360.03875732 - 360.05224609 360.06573486 360.07925415 360.09274292 360.10626221 - 360.11975098 360.13323975 360.14675903 360.1602478 360.17373657 - 360.18725586 360.20074463 360.21426392 360.22775269 360.24124146 - 360.25476074 360.26824951 360.28173828 360.29525757 360.30874634 - 360.32223511 360.33575439 360.34924316 360.36276245 360.37625122 - 360.38973999 360.40325928 360.41674805 360.43023682 360.4437561 - 360.45724487 360.47076416 360.48425293 360.4977417 360.51126099 - 360.52474976 360.53823853 360.55175781 360.56524658 360.57873535 - 360.59225464 360.60574341 360.6192627 360.63275146 360.64624023 - 360.65975952 360.67324829 360.68673706 360.70025635 360.71374512 - 360.7272644 360.74075317 360.75424194 360.76776123 360.78125 - 360.79473877 360.80825806 360.82174683 360.8352356 360.84875488 - 360.86224365 360.87576294 360.88925171 360.90274048 360.91625977 - 360.92974854 360.9432373 360.95675659 360.97024536 360.98376465 - 360.99725342 361.01074219 361.02426147 361.03775024 361.05123901 - 361.0647583 361.07824707 361.09173584 361.10525513 361.1187439 - 361.13226318 361.14575195 361.15924072 361.17276001 361.18624878 - 361.19973755 361.21325684 361.22674561 361.24026489 361.25375366 - 361.26724243 361.28076172 361.29425049 361.30773926 361.32125854 - 361.33474731 361.34823608 361.36175537 361.37524414 361.38876343 - 361.4022522 361.41574097 361.42926025 361.44274902 361.45623779 - 361.46975708 361.48324585 361.49676514 361.51025391 361.52374268 - 361.53726196 361.55075073 361.5642395 361.57775879 361.59124756 - 361.60473633 361.61825562 361.63174438 361.64526367 361.65875244 - 361.67224121 361.6857605 361.69924927 361.71273804 361.72625732 - 361.73974609 361.75323486 361.76675415 361.78024292 361.79376221 - 361.80725098 361.82073975 361.83425903 361.8477478 361.86123657 - 361.87475586 361.88824463 361.90176392 361.91525269 361.92874146 - 361.94226074 361.95574951 361.96923828 361.98275757 361.99624634 - 362.00973511 362.02325439 362.03674316 362.05026245 362.06375122 - 362.07723999 362.09075928 362.10424805 362.11773682 362.1312561 - 362.14474487 362.15826416 362.17175293 362.1852417 362.19876099 - 362.21224976 362.22573853 362.23925781 362.25274658 362.26623535 - 362.27975464 362.29324341 362.3067627 362.32025146 362.33374023 - 362.34725952 362.36074829 362.37423706 362.38775635 362.40124512 - 362.4147644 362.42825317 362.44174194 362.45526123 362.46875 - 362.48223877 362.49575806 362.50924683 362.5227356 362.53625488 - 362.54974365 362.56326294 362.57675171 362.59024048 362.60375977 - 362.61724854 362.6307373 362.64425659 362.65774536 362.67126465 - 362.68475342 362.69824219 362.71176147 362.72525024 362.73873901 - 362.7522583 362.76574707 362.77923584 362.79275513 362.8062439 - 362.81976318 362.83325195 362.84674072 362.86026001 362.87374878 - 362.88723755 362.90075684 362.91424561 362.92776489 362.94125366 - 362.95474243 362.96826172 362.98175049 362.99523926 363.00875854 - 363.02224731 363.03573608 363.04925537 363.06274414 363.07626343 - 363.0897522 363.10324097 363.11676025 363.13024902 363.14373779 - 363.15725708 363.17074585 363.18426514 363.19775391 363.21124268 - 363.22476196 363.23825073 363.2517395 363.26525879 363.27874756 - 363.29223633 363.30575562 363.31951904 363.33377075 363.34857178 - 363.36395264 363.37991333 363.39645386 363.41360474 363.431427 - 363.44992065 363.46911621 363.48901367 363.50967407 363.53109741 - 363.55334473 363.57641602 363.60037231 363.62521362 363.65100098 - 363.67776489 363.70550537 363.73431396 363.76699829 363.80300903 - 363.83898926 363.875 363.91101074 363.94699097 363.98300171 - 364.01901245 364.05499268 364.09100342 364.12701416 364.16299438 - 364.19900513 364.23498535 364.27099609 364.30700684 364.34298706 - 364.3789978 364.41500854 364.45098877 364.48699951 364.52301025 - 364.55899048 364.59500122 364.63101196 364.66699219 364.70300293 - 364.73901367 364.7749939 364.81100464 364.84698486 364.88299561 - 364.91900635 364.95498657 364.99099731 365.02700806 365.06298828 - 365.09899902 365.13500977 365.17098999 365.20700073] - y: [ -5.59320021e+00 -5.55719995e+00 -5.52120018e+00 -5.48519993e+00 - -5.44920015e+00 -5.41319990e+00 -5.37720013e+00 -5.34119987e+00 - -5.30520010e+00 -5.26919985e+00 -5.23320007e+00 -5.19719982e+00 - -5.16120005e+00 -5.12519979e+00 -5.08920002e+00 -5.05319977e+00 - -5.01719999e+00 -4.98120022e+00 -4.94519997e+00 -4.90920019e+00 - -4.87319994e+00 -4.83720016e+00 -4.80119991e+00 -4.76520014e+00 - -4.72919989e+00 -4.69320011e+00 -4.65719986e+00 -4.62120008e+00 - -4.58519983e+00 -4.54920006e+00 -4.51319981e+00 -4.47720003e+00 - -4.44119978e+00 -4.40520000e+00 -4.36920023e+00 -4.33319998e+00 - -4.29720020e+00 -4.26119995e+00 -4.22520018e+00 -4.19377995e+00 - -4.16359854e+00 -4.13460732e+00 -4.10675907e+00 -4.08000851e+00 - -4.05431318e+00 -4.02963066e+00 -4.00592136e+00 -3.98314714e+00 - -3.96127057e+00 -3.94025683e+00 -3.92007136e+00 -3.90068197e+00 - -3.88205695e+00 -3.86416626e+00 -3.84698105e+00 -3.83047342e+00 - -3.81461668e+00 -3.79938507e+00 -3.78475404e+00 -3.77069998e+00 - -3.75720000e+00 -3.74370003e+00 -3.73020005e+00 -3.71670008e+00 - -3.70320010e+00 -3.68969989e+00 -3.67619991e+00 -3.66269994e+00 - -3.64919996e+00 -3.63569999e+00 -3.62220001e+00 -3.60870004e+00 - -3.59520006e+00 -3.58170009e+00 -3.56820011e+00 -3.55469990e+00 - -3.54119992e+00 -3.52769995e+00 -3.51419997e+00 -3.50070000e+00 - -3.48720002e+00 -3.47370005e+00 -3.46020007e+00 -3.44670010e+00 - -3.43319988e+00 -3.41969991e+00 -3.40619993e+00 -3.39269996e+00 - -3.37919998e+00 -3.36570001e+00 -3.35220003e+00 -3.33870006e+00 - -3.32520008e+00 -3.31170011e+00 -3.29819989e+00 -3.28469992e+00 - -3.27119994e+00 -3.25769997e+00 -3.24419999e+00 -3.23070002e+00 - -3.21720004e+00 -3.20370007e+00 -3.19020009e+00 -3.17670012e+00 - -3.16319990e+00 -3.14969993e+00 -3.13619995e+00 -3.12269998e+00 - -3.10920000e+00 -3.09570003e+00 -3.08220005e+00 -3.06870008e+00 - -3.05520010e+00 -3.04169989e+00 -3.02819991e+00 -3.01469994e+00 - -3.00119996e+00 -2.98769999e+00 -2.97420001e+00 -2.96070004e+00 - -2.94720006e+00 -2.93370008e+00 -2.92020011e+00 -2.90669990e+00 - -2.89319992e+00 -2.87969995e+00 -2.86619997e+00 -2.85270000e+00 - -2.83920002e+00 -2.82570004e+00 -2.81220007e+00 -2.79870009e+00 - -2.78520012e+00 -2.77169991e+00 -2.75819993e+00 -2.74469995e+00 - -2.73119998e+00 -2.71770000e+00 -2.70420003e+00 -2.69070005e+00 - -2.67720008e+00 -2.66370010e+00 -2.65019989e+00 -2.63669991e+00 - -2.62319994e+00 -2.60969996e+00 -2.59619999e+00 -2.58270001e+00 - -2.56920004e+00 -2.55570006e+00 -2.54220009e+00 -2.52870011e+00 - -2.51519990e+00 -2.50169992e+00 -2.48819995e+00 -2.47469997e+00 - -2.46120000e+00 -2.44770002e+00 -2.43420005e+00 -2.42070007e+00 - -2.40720010e+00 -2.39369988e+00 -2.38019991e+00 -2.36669993e+00 - -2.35319996e+00 -2.33969998e+00 -2.32620001e+00 -2.31270003e+00 - -2.29920006e+00 -2.28570008e+00 -2.27220011e+00 -2.25869989e+00 - -2.24519992e+00 -2.23169994e+00 -2.21819997e+00 -2.20469999e+00 - -2.19120002e+00 -2.17770004e+00 -2.16420007e+00 -2.15070009e+00 - -2.13720012e+00 -2.12369990e+00 -2.11019993e+00 -2.09669995e+00 - -2.08319998e+00 -2.06970000e+00 -2.05620003e+00 -2.04270005e+00 - -2.02920008e+00 -2.01570010e+00 -2.00219989e+00 -1.98870003e+00 - -1.97520006e+00 -1.96169996e+00 -1.94819999e+00 -1.93470001e+00 - -1.92120004e+00 -1.90769994e+00 -1.89419997e+00 -1.88069999e+00 - -1.86720002e+00 -1.85370004e+00 -1.84019995e+00 -1.82669997e+00 - -1.81320000e+00 -1.79970002e+00 -1.78620005e+00 -1.77269995e+00 - -1.75919998e+00 -1.74570000e+00 -1.73220003e+00 -1.71870005e+00 - -1.70519996e+00 -1.69169998e+00 -1.67820001e+00 -1.66470003e+00 - -1.65120006e+00 -1.63769996e+00 -1.62419999e+00 -1.61070001e+00 - -1.59720004e+00 -1.58369994e+00 -1.57019997e+00 -1.55669999e+00 - -1.54320002e+00 -1.52970004e+00 -1.51619995e+00 -1.50269997e+00 - -1.48920000e+00 -1.47570002e+00 -1.46220005e+00 -1.44869995e+00 - -1.43519998e+00 -1.42170000e+00 -1.40820003e+00 -1.39470005e+00 - -1.38119996e+00 -1.36769998e+00 -1.35420001e+00 -1.34070003e+00 - -1.32720006e+00 -1.31369996e+00 -1.30019999e+00 -1.28670001e+00 - -1.27320004e+00 -1.25969994e+00 -1.24619997e+00 -1.23269999e+00 - -1.21920002e+00 -1.20570004e+00 -1.19219995e+00 -1.17869997e+00 - -1.16520000e+00 -1.15170002e+00 -1.13820004e+00 -1.12469995e+00 - -1.11119998e+00 -1.09770000e+00 -1.08420002e+00 -1.07070005e+00 - -1.05719995e+00 -1.04369998e+00 -1.03020000e+00 -1.01670003e+00 - -1.00320005e+00 -9.89700019e-01 -9.76199985e-01 -9.62700009e-01 - -9.49199975e-01 -9.35699999e-01 -9.22200024e-01 -9.08699989e-01 - -8.95200014e-01 -8.81699979e-01 -8.68200004e-01 -8.54700029e-01 - -8.41199994e-01 -8.27700019e-01 -8.14199984e-01 -8.00700009e-01 - -7.87199974e-01 -7.73699999e-01 -7.60200024e-01 -7.46699989e-01 - -7.33200014e-01 -7.19699979e-01 -7.06200004e-01 -6.92700028e-01 - -6.79199994e-01 -6.65700018e-01 -6.52199984e-01 -6.38700008e-01 - -6.25199974e-01 -6.11699998e-01 -5.98200023e-01 -5.84699988e-01 - -5.71200013e-01 -5.57699978e-01 -5.44200003e-01 -5.30700028e-01 - -5.17199993e-01 -5.03700018e-01 -4.90200013e-01 -4.76700008e-01 - -4.63200003e-01 -4.49699998e-01 -4.36199993e-01 -4.22699988e-01 - -4.09200013e-01 -3.95700008e-01 -3.82200003e-01 -3.68699998e-01 - -3.55199993e-01 -3.41699988e-01 -3.28200012e-01 -3.14700007e-01 - -3.01200002e-01 -2.87699997e-01 -2.74199992e-01 -2.60699987e-01 - -2.47199997e-01 -2.33700007e-01 -2.20200002e-01 -2.06699997e-01 - -1.93200007e-01 -1.79700002e-01 -1.66199997e-01 -1.52700007e-01 - -1.39200002e-01 -1.25699997e-01 -1.12199999e-01 -9.87000018e-02 - -8.51999968e-02 -7.16999993e-02 -5.82000017e-02 -4.47000004e-02 - -3.11999992e-02 -1.76999997e-02 -4.19999985e-03 9.30000003e-03 - 2.28000004e-02 3.62999998e-02 4.98000011e-02 6.32999986e-02 - 7.68000036e-02 9.03000012e-02 1.03799999e-01 1.17299996e-01 - 1.30799994e-01 1.44299999e-01 1.57800004e-01 1.71299994e-01 - 1.84799999e-01 1.98300004e-01 2.11799994e-01 2.25299999e-01 - 2.38800004e-01 2.52299994e-01 2.65799999e-01 2.79300004e-01 - 2.92800009e-01 3.06300014e-01 3.19799989e-01 3.33299994e-01 - 3.46799999e-01 3.60300004e-01 3.73800009e-01 3.87300014e-01 - 4.00799990e-01 4.14299995e-01 4.27800000e-01 4.41300005e-01 - 4.54800010e-01 4.68300015e-01 4.81799990e-01 4.95299995e-01 - 5.08800030e-01 5.22300005e-01 5.35799980e-01 5.49300015e-01 - 5.62799990e-01 5.76300025e-01 5.89800000e-01 6.03299975e-01 - 6.16800010e-01 6.30299985e-01 6.43800020e-01 6.57299995e-01 - 6.70799971e-01 6.84300005e-01 6.97799981e-01 7.11300015e-01 - 7.24799991e-01 7.38300025e-01 7.51800001e-01 7.65299976e-01 - 7.78800011e-01 7.92299986e-01 8.05800021e-01 8.19299996e-01 - 8.32799971e-01 8.46300006e-01 8.59799981e-01 8.73300016e-01 - 8.86799991e-01 9.00300026e-01 9.13800001e-01 9.27299976e-01 - 9.40800011e-01 9.54299986e-01 9.67800021e-01 9.81299996e-01 - 9.94799972e-01 1.00829995e+00 1.02180004e+00 1.03530002e+00 - 1.04879999e+00 1.06229997e+00 1.07579994e+00 1.08930004e+00 - 1.10280001e+00 1.11629999e+00 1.12979996e+00 1.14330006e+00 - 1.15680003e+00 1.17030001e+00 1.18379998e+00 1.19729996e+00 - 1.21080005e+00 1.22430003e+00 1.23780000e+00 1.25129998e+00 - 1.26479995e+00 1.27830005e+00 1.29180002e+00 1.30530000e+00 - 1.31879997e+00 1.33229995e+00 1.34580004e+00 1.35930002e+00 - 1.37279999e+00 1.38629997e+00 1.39979994e+00 1.41330004e+00 - 1.42680001e+00 1.44029999e+00 1.45379996e+00 1.46730006e+00 - 1.48080003e+00 1.49430001e+00 1.50779998e+00 1.52129996e+00 - 1.53480005e+00 1.54830003e+00 1.56180000e+00 1.57529998e+00 - 1.58879995e+00 1.60230005e+00 1.61580002e+00 1.62930000e+00 - 1.64279997e+00 1.65629995e+00 1.66980004e+00 1.68330002e+00 - 1.69679999e+00 1.71029997e+00 1.72379994e+00 1.73730004e+00 - 1.75080001e+00 1.76429999e+00 1.77779996e+00 1.79130006e+00 - 1.80480003e+00 1.81830001e+00 1.83179998e+00 1.84529996e+00 - 1.85880005e+00 1.87230003e+00 1.88580000e+00 1.89929998e+00 - 1.91279995e+00 1.92630005e+00 1.93980002e+00 1.95330000e+00 - 1.96679997e+00 1.98029995e+00 1.99380004e+00 2.00729990e+00 - 2.02080011e+00 2.03430009e+00 2.04780006e+00 2.06130004e+00 - 2.07480001e+00 2.08829999e+00 2.10179996e+00 2.11529994e+00 - 2.12879992e+00 2.14229989e+00 2.15580010e+00 2.16930008e+00 - 2.18280005e+00 2.19630003e+00 2.20980000e+00 2.22329998e+00 - 2.23679996e+00 2.25029993e+00 2.26379991e+00 2.27729988e+00 - 2.29080009e+00 2.30430007e+00 2.31780005e+00 2.33130002e+00 - 2.34480000e+00 2.35829997e+00 2.37179995e+00 2.38529992e+00 - 2.39879990e+00 2.41230011e+00 2.42580009e+00 2.43930006e+00 - 2.45280004e+00 2.46630001e+00 2.47979999e+00 2.49329996e+00 - 2.50679994e+00 2.52029991e+00 2.53379989e+00 2.54730010e+00 - 2.56080008e+00 2.57430005e+00 2.58780003e+00 2.60130000e+00 - 2.61479998e+00 2.62829995e+00 2.64179993e+00 2.65529990e+00 - 2.66880012e+00 2.68230009e+00 2.69580007e+00 2.70930004e+00 - 2.72280002e+00 2.73629999e+00 2.74979997e+00 2.76329994e+00 - 2.77679992e+00 2.79029989e+00 2.80380011e+00 2.81730008e+00 - 2.83080006e+00 2.84430003e+00 2.85780001e+00 2.87129998e+00 - 2.88479996e+00 2.89829993e+00 2.91179991e+00 2.92529988e+00 - 2.93880010e+00 2.95230007e+00 2.96580005e+00 2.97930002e+00 - 2.99280000e+00 3.00629997e+00 3.01979995e+00 3.03329992e+00 - 3.04679990e+00 3.06030011e+00 3.07380009e+00 3.08730006e+00 - 3.10080004e+00 3.11430001e+00 3.12779999e+00 3.14129996e+00 - 3.15479994e+00 3.16829991e+00 3.18179989e+00 3.19530010e+00 - 3.20880008e+00 3.22230005e+00 3.23580003e+00 3.24930000e+00 - 3.26279998e+00 3.27629995e+00 3.28979993e+00 3.30329990e+00 - 3.31680012e+00 3.33030009e+00 3.34380007e+00 3.35730004e+00 - 3.37080002e+00 3.38429999e+00 3.39779997e+00 3.41129994e+00 - 3.42479992e+00 3.43829989e+00 3.45180011e+00 3.46530008e+00 - 3.47880006e+00 3.49230003e+00 3.50580001e+00 3.51929998e+00 - 3.53279996e+00 3.54629993e+00 3.55979991e+00 3.57329988e+00 - 3.58680010e+00 3.60030007e+00 3.61380005e+00 3.62730002e+00 - 3.64080000e+00 3.65429997e+00 3.66779995e+00 3.68129992e+00 - 3.69479990e+00 3.70830011e+00 3.72180009e+00 3.73530006e+00 - 3.74880004e+00 3.76230001e+00 3.77579999e+00 3.78929996e+00 - 3.80279994e+00 3.81629992e+00 3.82979989e+00 3.84330010e+00 - 3.85680008e+00 3.87030005e+00 3.88380003e+00 3.89730000e+00 - 3.91079998e+00 3.92429996e+00 3.93779993e+00 3.95129991e+00 - 3.96479988e+00 3.97830009e+00 3.99180007e+00 4.00530005e+00 - 4.01879978e+00 4.03230000e+00 4.04580021e+00 4.05929995e+00 - 4.07280016e+00 4.08629990e+00 4.09980011e+00 4.11329985e+00 - 4.12680006e+00 4.14029980e+00 4.15380001e+00 4.16730022e+00 - 4.18079996e+00 4.19430017e+00 4.20779991e+00 4.22130013e+00 - 4.23479986e+00 4.24830008e+00 4.26179981e+00 4.27530003e+00 - 4.28879976e+00 4.30229998e+00 4.31580019e+00 4.32929993e+00 - 4.34280014e+00 4.35629988e+00 4.36980009e+00 4.38329983e+00 - 4.39680004e+00 4.41029978e+00 4.42379999e+00 4.43730021e+00 - 4.45079994e+00 4.46430016e+00 4.47779989e+00 4.49130011e+00 - 4.50479984e+00 4.51830006e+00 4.53179979e+00 4.54530001e+00 - 4.55880022e+00 4.57229996e+00 4.58580017e+00 4.59929991e+00 - 4.61280012e+00 4.62629986e+00 4.63980007e+00 4.65329981e+00 - 4.66680002e+00 4.68030024e+00 4.69379997e+00 4.70730019e+00 - 4.72079992e+00 4.73430014e+00 4.74779987e+00 4.76130009e+00 - 4.77479982e+00 4.78830004e+00 4.80179977e+00 4.81529999e+00 - 4.82880020e+00 4.84229994e+00 4.85580015e+00 4.86929989e+00 - 4.88280010e+00 4.89629984e+00 4.90980005e+00 4.92329979e+00 - 4.93680000e+00 4.95030022e+00 4.96379995e+00 4.97730017e+00 - 4.99079990e+00 5.00430012e+00 5.01779985e+00 5.03130007e+00 - 5.04479980e+00 5.05830002e+00 5.07180023e+00 5.08529997e+00 - 5.09880018e+00 5.11229992e+00 5.12580013e+00 5.13929987e+00 - 5.15280008e+00 5.16629982e+00 5.17980003e+00 5.19329977e+00 - 5.20679998e+00 5.22030020e+00 5.23379993e+00 5.24730015e+00 - 5.26079988e+00 5.27430010e+00 5.28779984e+00 5.30130005e+00 - 5.31479979e+00 5.32830000e+00 5.34180021e+00 5.35529995e+00 - 5.36880016e+00 5.38229990e+00 5.39580011e+00 5.40929985e+00 - 5.42280006e+00 5.43629980e+00 5.44980001e+00 5.46330023e+00 - 5.47679996e+00 5.49030018e+00 5.50379992e+00 5.51730013e+00 - 5.53079987e+00 5.54430008e+00 5.55779982e+00 5.57130003e+00 - 5.58479977e+00 5.59829998e+00 5.61180019e+00 5.62529993e+00 - 5.63880014e+00 5.65229988e+00 5.66580009e+00 5.67929983e+00 - 5.69280005e+00 5.70629978e+00 5.71980000e+00 5.73330021e+00 - 5.74679995e+00 5.76030016e+00 5.77379990e+00 5.78730011e+00 - 5.80079985e+00 5.81430006e+00 5.82779980e+00 5.84130001e+00 - 5.85480022e+00 5.86829996e+00 5.88180017e+00 5.89529991e+00 - 5.90880013e+00 5.92229986e+00 5.93580008e+00 5.94929981e+00 - 5.96280003e+00 5.97629976e+00 5.98979998e+00 6.00330019e+00 - 6.01679993e+00 6.03030014e+00 6.04379988e+00 6.05730009e+00 - 6.07079983e+00 6.08430004e+00 6.09779978e+00 6.11129999e+00 - 6.12480021e+00 6.13829994e+00 6.15180016e+00 6.16529989e+00 - 6.17880011e+00 6.19229984e+00 6.20580006e+00 6.21929979e+00 - 6.23280001e+00 6.24630022e+00 6.25979996e+00 6.27330017e+00 - 6.28679991e+00 6.30030012e+00 6.31379986e+00 6.32730007e+00 - 6.34079981e+00 6.35430002e+00 6.36780024e+00 6.38129997e+00 - 6.39480019e+00 6.40829992e+00 6.42180014e+00 6.43529987e+00 - 6.44880009e+00 6.46229982e+00 6.47580004e+00 6.48929977e+00 - 6.50279999e+00 6.51630020e+00 6.52979994e+00 6.54330015e+00 - 6.55679989e+00 6.57030010e+00 6.58379984e+00 6.59730005e+00 - 6.61079979e+00 6.62430000e+00 6.63780022e+00 6.65129995e+00 - 6.66480017e+00 6.67829990e+00 6.69180012e+00 6.70529985e+00 - 6.71880007e+00 6.73229980e+00 6.74580002e+00 6.75930023e+00 - 6.77279997e+00 6.78630018e+00 6.79979992e+00 6.81330013e+00 - 6.82679987e+00 6.84030008e+00 6.85379982e+00 6.86730003e+00 - 6.88079977e+00 6.89429998e+00 6.90780020e+00 6.92129993e+00 - 6.93480015e+00 6.94829988e+00 6.96180010e+00 6.97529984e+00 - 6.98880005e+00 7.00229979e+00 7.01580000e+00 7.02930021e+00 - 7.04279995e+00 7.05630016e+00 7.06979990e+00 7.08330011e+00 - 7.09679985e+00 7.11030006e+00 7.12379980e+00 7.13730001e+00 - 7.15080023e+00 7.16485405e+00 7.17948532e+00 7.19471693e+00 - 7.21057367e+00 7.22708130e+00 7.24426651e+00 7.26215696e+00 - 7.28078175e+00 7.30017138e+00 7.32035685e+00 7.34137058e+00 - 7.36324692e+00 7.38602161e+00 7.40973091e+00 7.43441296e+00 - 7.46010876e+00 7.48685884e+00 7.51470709e+00 7.54369831e+00 - 7.57387972e+00 7.60529995e+00 7.64130020e+00 7.67729998e+00 - 7.71330023e+00 7.74930000e+00 7.78529978e+00 7.82130003e+00 - 7.85729980e+00 7.89330006e+00 7.92929983e+00 7.96530008e+00 - 8.00129986e+00 8.03730011e+00 8.07330036e+00 8.10929966e+00 - 8.14529991e+00 8.18130016e+00 8.21730042e+00 8.25329971e+00 - 8.28929996e+00 8.32530022e+00 8.36130047e+00 8.39729977e+00 - 8.43330002e+00 8.46930027e+00 8.50529957e+00 8.54129982e+00 - 8.57730007e+00 8.61330032e+00 8.64929962e+00 8.68529987e+00 - 8.72130013e+00 8.75730038e+00 8.79329967e+00 8.82929993e+00 - 8.86530018e+00 8.90130043e+00 8.93729973e+00 8.97329998e+00] - y_lower_bound: [ -5.61120033e+00 -5.57520008e+00 -5.53919983e+00 -5.50320005e+00 - -5.46719980e+00 -5.43120003e+00 -5.39519978e+00 -5.35920000e+00 - -5.32320023e+00 -5.28719997e+00 -5.25120020e+00 -5.21519995e+00 - -5.17920017e+00 -5.14319992e+00 -5.10720015e+00 -5.07119989e+00 - -5.03520012e+00 -4.99919987e+00 -4.96320009e+00 -4.92719984e+00 - -4.89120007e+00 -4.85519981e+00 -4.81920004e+00 -4.78319979e+00 - -4.74720001e+00 -4.71120024e+00 -4.67519999e+00 -4.63920021e+00 - -4.60319996e+00 -4.56720018e+00 -4.53119993e+00 -4.49520016e+00 - -4.45919991e+00 -4.42320013e+00 -4.38719988e+00 -4.35120010e+00 - -4.31519985e+00 -4.27920008e+00 -4.24319983e+00 -4.20948982e+00 - -4.17868900e+00 -4.14910269e+00 -4.12068319e+00 -4.09338379e+00 - -4.06716108e+00 -4.04197168e+00 -4.01777601e+00 -3.99453425e+00 - -3.97220898e+00 -3.95076370e+00 -3.93016410e+00 -3.91037679e+00 - -3.89136934e+00 -3.87311172e+00 -3.85557365e+00 -3.83872724e+00 - -3.82254505e+00 -3.80700088e+00 -3.79206967e+00 -3.77772713e+00 - -3.76395011e+00 -3.75044990e+00 -3.73694992e+00 -3.72344995e+00 - -3.70994997e+00 -3.69645000e+00 -3.68295002e+00 -3.66945004e+00 - -3.65595007e+00 -3.64245009e+00 -3.62895012e+00 -3.61544991e+00 - -3.60194993e+00 -3.58844995e+00 -3.57494998e+00 -3.56145000e+00 - -3.54795003e+00 -3.53445005e+00 -3.52095008e+00 -3.50745010e+00 - -3.49394989e+00 -3.48044991e+00 -3.46694994e+00 -3.45344996e+00 - -3.43994999e+00 -3.42645001e+00 -3.41295004e+00 -3.39945006e+00 - -3.38595009e+00 -3.37245011e+00 -3.35894990e+00 -3.34544992e+00 - -3.33194995e+00 -3.31844997e+00 -3.30495000e+00 -3.29145002e+00 - -3.27795005e+00 -3.26445007e+00 -3.25095010e+00 -3.23744988e+00 - -3.22394991e+00 -3.21044993e+00 -3.19694996e+00 -3.18344998e+00 - -3.16995001e+00 -3.15645003e+00 -3.14295006e+00 -3.12945008e+00 - -3.11595011e+00 -3.10244989e+00 -3.08894992e+00 -3.07544994e+00 - -3.06194997e+00 -3.04844999e+00 -3.03495002e+00 -3.02145004e+00 - -3.00795007e+00 -2.99445009e+00 -2.98095012e+00 -2.96744990e+00 - -2.95394993e+00 -2.94044995e+00 -2.92694998e+00 -2.91345000e+00 - -2.89995003e+00 -2.88645005e+00 -2.87295008e+00 -2.85945010e+00 - -2.84594989e+00 -2.83244991e+00 -2.81894994e+00 -2.80544996e+00 - -2.79194999e+00 -2.77845001e+00 -2.76495004e+00 -2.75145006e+00 - -2.73795009e+00 -2.72445011e+00 -2.71094990e+00 -2.69744992e+00 - -2.68394995e+00 -2.67044997e+00 -2.65695000e+00 -2.64345002e+00 - -2.62995005e+00 -2.61645007e+00 -2.60295010e+00 -2.58944988e+00 - -2.57594991e+00 -2.56244993e+00 -2.54894996e+00 -2.53544998e+00 - -2.52195001e+00 -2.50845003e+00 -2.49495006e+00 -2.48145008e+00 - -2.46795011e+00 -2.45444989e+00 -2.44094992e+00 -2.42744994e+00 - -2.41394997e+00 -2.40044999e+00 -2.38695002e+00 -2.37345004e+00 - -2.35995007e+00 -2.34645009e+00 -2.33295012e+00 -2.31944990e+00 - -2.30594993e+00 -2.29244995e+00 -2.27894998e+00 -2.26545000e+00 - -2.25195003e+00 -2.23845005e+00 -2.22495008e+00 -2.21145010e+00 - -2.19794989e+00 -2.18444991e+00 -2.17094994e+00 -2.15744996e+00 - -2.14394999e+00 -2.13045001e+00 -2.11695004e+00 -2.10345006e+00 - -2.08995008e+00 -2.07645011e+00 -2.06294990e+00 -2.04944992e+00 - -2.03594995e+00 -2.02244997e+00 -2.00895000e+00 -1.99545002e+00 - -1.98195004e+00 -1.96844995e+00 -1.95494998e+00 -1.94145000e+00 - -1.92795002e+00 -1.91445005e+00 -1.90094995e+00 -1.88744998e+00 - -1.87395000e+00 -1.86045003e+00 -1.84695005e+00 -1.83344996e+00 - -1.81994998e+00 -1.80645001e+00 -1.79295003e+00 -1.77945006e+00 - -1.76594996e+00 -1.75244999e+00 -1.73895001e+00 -1.72545004e+00 - -1.71194994e+00 -1.69844997e+00 -1.68494999e+00 -1.67145002e+00 - -1.65795004e+00 -1.64444995e+00 -1.63094997e+00 -1.61745000e+00 - -1.60395002e+00 -1.59045005e+00 -1.57694995e+00 -1.56344998e+00 - -1.54995000e+00 -1.53645003e+00 -1.52295005e+00 -1.50944996e+00 - -1.49594998e+00 -1.48245001e+00 -1.46895003e+00 -1.45545006e+00 - -1.44194996e+00 -1.42844999e+00 -1.41495001e+00 -1.40145004e+00 - -1.38794994e+00 -1.37444997e+00 -1.36094999e+00 -1.34745002e+00 - -1.33395004e+00 -1.32044995e+00 -1.30694997e+00 -1.29345000e+00 - -1.27995002e+00 -1.26645005e+00 -1.25294995e+00 -1.23944998e+00 - -1.22595000e+00 -1.21245003e+00 -1.19895005e+00 -1.18544996e+00 - -1.17194998e+00 -1.15845001e+00 -1.14495003e+00 -1.13145006e+00 - -1.11794996e+00 -1.10444999e+00 -1.09095001e+00 -1.07745004e+00 - -1.06394994e+00 -1.05044997e+00 -1.03694999e+00 -1.02345002e+00 - -1.00995004e+00 -9.96450007e-01 -9.82949972e-01 -9.69449997e-01 - -9.55950022e-01 -9.42449987e-01 -9.28950012e-01 -9.15449977e-01 - -9.01950002e-01 -8.88450027e-01 -8.74949992e-01 -8.61450016e-01 - -8.47949982e-01 -8.34450006e-01 -8.20949972e-01 -8.07449996e-01 - -7.93950021e-01 -7.80449986e-01 -7.66950011e-01 -7.53449976e-01 - -7.39950001e-01 -7.26450026e-01 -7.12949991e-01 -6.99450016e-01 - -6.85949981e-01 -6.72450006e-01 -6.58949971e-01 -6.45449996e-01 - -6.31950021e-01 -6.18449986e-01 -6.04950011e-01 -5.91449976e-01 - -5.77950001e-01 -5.64450026e-01 -5.50949991e-01 -5.37450016e-01 - -5.23949981e-01 -5.10450006e-01 -4.96950001e-01 -4.83449996e-01 - -4.69949991e-01 -4.56449986e-01 -4.42950010e-01 -4.29450005e-01 - -4.15950000e-01 -4.02449995e-01 -3.88949990e-01 -3.75449985e-01 - -3.61950010e-01 -3.48450005e-01 -3.34950000e-01 -3.21449995e-01 - -3.07949990e-01 -2.94450015e-01 -2.80950010e-01 -2.67450005e-01 - -2.53950000e-01 -2.40449995e-01 -2.26950005e-01 -2.13450000e-01 - -1.99949995e-01 -1.86450005e-01 -1.72950000e-01 -1.59449995e-01 - -1.45950004e-01 -1.32449999e-01 -1.18950002e-01 -1.05449997e-01 - -9.19499993e-02 -7.84500018e-02 -6.49499968e-02 -5.14499992e-02 - -3.79500017e-02 -2.44500004e-02 -1.09500000e-02 2.55000009e-03 - 1.60499997e-02 2.95499992e-02 4.30499986e-02 5.65499999e-02 - 7.00500011e-02 8.35499987e-02 9.70500037e-02 1.10550001e-01 - 1.24049999e-01 1.37549996e-01 1.51050001e-01 1.64550006e-01 - 1.78049996e-01 1.91550002e-01 2.05050007e-01 2.18549997e-01 - 2.32050002e-01 2.45550007e-01 2.59050012e-01 2.72549987e-01 - 2.86049992e-01 2.99549997e-01 3.13050002e-01 3.26550007e-01 - 3.40050012e-01 3.53549987e-01 3.67049992e-01 3.80549997e-01 - 3.94050002e-01 4.07550007e-01 4.21050012e-01 4.34549987e-01 - 4.48049992e-01 4.61549997e-01 4.75050002e-01 4.88550007e-01 - 5.02049983e-01 5.15550017e-01 5.29049993e-01 5.42550027e-01 - 5.56050003e-01 5.69549978e-01 5.83050013e-01 5.96549988e-01 - 6.10050023e-01 6.23549998e-01 6.37049973e-01 6.50550008e-01 - 6.64049983e-01 6.77550018e-01 6.91049993e-01 7.04550028e-01 - 7.18050003e-01 7.31549978e-01 7.45050013e-01 7.58549988e-01 - 7.72050023e-01 7.85549998e-01 7.99049973e-01 8.12550008e-01 - 8.26049984e-01 8.39550018e-01 8.53049994e-01 8.66550028e-01 - 8.80050004e-01 8.93549979e-01 9.07050014e-01 9.20549989e-01 - 9.34050024e-01 9.47549999e-01 9.61049974e-01 9.74550009e-01 - 9.88049984e-01 1.00154996e+00 1.01505005e+00 1.02855003e+00 - 1.04205000e+00 1.05554998e+00 1.06904995e+00 1.08255005e+00 - 1.09605002e+00 1.10955000e+00 1.12304997e+00 1.13654995e+00 - 1.15005004e+00 1.16355002e+00 1.17704999e+00 1.19054997e+00 - 1.20404994e+00 1.21755004e+00 1.23105001e+00 1.24454999e+00 - 1.25804996e+00 1.27155006e+00 1.28505003e+00 1.29855001e+00 - 1.31204998e+00 1.32554996e+00 1.33905005e+00 1.35255003e+00 - 1.36605000e+00 1.37954998e+00 1.39304996e+00 1.40655005e+00 - 1.42005002e+00 1.43355000e+00 1.44704998e+00 1.46054995e+00 - 1.47405005e+00 1.48755002e+00 1.50105000e+00 1.51454997e+00 - 1.52804995e+00 1.54155004e+00 1.55505002e+00 1.56854999e+00 - 1.58204997e+00 1.59554994e+00 1.60905004e+00 1.62255001e+00 - 1.63604999e+00 1.64954996e+00 1.66305006e+00 1.67655003e+00 - 1.69005001e+00 1.70354998e+00 1.71704996e+00 1.73055005e+00 - 1.74405003e+00 1.75755000e+00 1.77104998e+00 1.78454995e+00 - 1.79805005e+00 1.81155002e+00 1.82505000e+00 1.83854997e+00 - 1.85204995e+00 1.86555004e+00 1.87905002e+00 1.89254999e+00 - 1.90604997e+00 1.91954994e+00 1.93305004e+00 1.94655001e+00 - 1.96004999e+00 1.97354996e+00 1.98705006e+00 2.00055003e+00 - 2.01405001e+00 2.02754998e+00 2.04104996e+00 2.05454993e+00 - 2.06804991e+00 2.08154988e+00 2.09505010e+00 2.10855007e+00 - 2.12205005e+00 2.13555002e+00 2.14905000e+00 2.16254997e+00 - 2.17604995e+00 2.18954992e+00 2.20304990e+00 2.21655011e+00 - 2.23005009e+00 2.24355006e+00 2.25705004e+00 2.27055001e+00 - 2.28404999e+00 2.29754996e+00 2.31104994e+00 2.32454991e+00 - 2.33804989e+00 2.35155010e+00 2.36505008e+00 2.37855005e+00 - 2.39205003e+00 2.40555000e+00 2.41904998e+00 2.43254995e+00 - 2.44604993e+00 2.45954990e+00 2.47305012e+00 2.48655009e+00 - 2.50005007e+00 2.51355004e+00 2.52705002e+00 2.54054999e+00 - 2.55404997e+00 2.56754994e+00 2.58104992e+00 2.59454989e+00 - 2.60805011e+00 2.62155008e+00 2.63505006e+00 2.64855003e+00 - 2.66205001e+00 2.67554998e+00 2.68904996e+00 2.70254993e+00 - 2.71604991e+00 2.72954988e+00 2.74305010e+00 2.75655007e+00 - 2.77005005e+00 2.78355002e+00 2.79705000e+00 2.81054997e+00 - 2.82404995e+00 2.83754992e+00 2.85104990e+00 2.86455011e+00 - 2.87805009e+00 2.89155006e+00 2.90505004e+00 2.91855001e+00 - 2.93204999e+00 2.94554996e+00 2.95904994e+00 2.97254992e+00 - 2.98604989e+00 2.99955010e+00 3.01305008e+00 3.02655005e+00 - 3.04005003e+00 3.05355000e+00 3.06704998e+00 3.08054996e+00 - 3.09404993e+00 3.10754991e+00 3.12104988e+00 3.13455009e+00 - 3.14805007e+00 3.16155005e+00 3.17505002e+00 3.18855000e+00 - 3.20204997e+00 3.21554995e+00 3.22904992e+00 3.24254990e+00 - 3.25605011e+00 3.26955009e+00 3.28305006e+00 3.29655004e+00 - 3.31005001e+00 3.32354999e+00 3.33704996e+00 3.35054994e+00 - 3.36404991e+00 3.37754989e+00 3.39105010e+00 3.40455008e+00 - 3.41805005e+00 3.43155003e+00 3.44505000e+00 3.45854998e+00 - 3.47204995e+00 3.48554993e+00 3.49904990e+00 3.51255012e+00 - 3.52605009e+00 3.53955007e+00 3.55305004e+00 3.56655002e+00 - 3.58004999e+00 3.59354997e+00 3.60704994e+00 3.62054992e+00 - 3.63404989e+00 3.64755011e+00 3.66105008e+00 3.67455006e+00 - 3.68805003e+00 3.70155001e+00 3.71504998e+00 3.72854996e+00 - 3.74204993e+00 3.75554991e+00 3.76904988e+00 3.78255010e+00 - 3.79605007e+00 3.80955005e+00 3.82305002e+00 3.83655000e+00 - 3.85004997e+00 3.86354995e+00 3.87704992e+00 3.89054990e+00 - 3.90405011e+00 3.91755009e+00 3.93105006e+00 3.94455004e+00 - 3.95805001e+00 3.97154999e+00 3.98504996e+00 3.99854994e+00 - 4.01205015e+00 4.02554989e+00 4.03905010e+00 4.05254984e+00 - 4.06605005e+00 4.07954979e+00 4.09305000e+00 4.10655022e+00 - 4.12004995e+00 4.13355017e+00 4.14704990e+00 4.16055012e+00 - 4.17404985e+00 4.18755007e+00 4.20104980e+00 4.21455002e+00 - 4.22805023e+00 4.24154997e+00 4.25505018e+00 4.26854992e+00 - 4.28205013e+00 4.29554987e+00 4.30905008e+00 4.32254982e+00 - 4.33605003e+00 4.34954977e+00 4.36304998e+00 4.37655020e+00 - 4.39004993e+00 4.40355015e+00 4.41704988e+00 4.43055010e+00 - 4.44404984e+00 4.45755005e+00 4.47104979e+00 4.48455000e+00 - 4.49805021e+00 4.51154995e+00 4.52505016e+00 4.53854990e+00 - 4.55205011e+00 4.56554985e+00 4.57905006e+00 4.59254980e+00 - 4.60605001e+00 4.61955023e+00 4.63304996e+00 4.64655018e+00 - 4.66004992e+00 4.67355013e+00 4.68704987e+00 4.70055008e+00 - 4.71404982e+00 4.72755003e+00 4.74104977e+00 4.75454998e+00 - 4.76805019e+00 4.78154993e+00 4.79505014e+00 4.80854988e+00 - 4.82205009e+00 4.83554983e+00 4.84905005e+00 4.86254978e+00 - 4.87605000e+00 4.88955021e+00 4.90304995e+00 4.91655016e+00 - 4.93004990e+00 4.94355011e+00 4.95704985e+00 4.97055006e+00 - 4.98404980e+00 4.99755001e+00 5.01105022e+00 5.02454996e+00 - 5.03805017e+00 5.05154991e+00 5.06505013e+00 5.07854986e+00 - 5.09205008e+00 5.10554981e+00 5.11905003e+00 5.13254976e+00 - 5.14604998e+00 5.15955019e+00 5.17304993e+00 5.18655014e+00 - 5.20004988e+00 5.21355009e+00 5.22704983e+00 5.24055004e+00 - 5.25404978e+00 5.26754999e+00 5.28105021e+00 5.29454994e+00 - 5.30805016e+00 5.32154989e+00 5.33505011e+00 5.34854984e+00 - 5.36205006e+00 5.37554979e+00 5.38905001e+00 5.40255022e+00 - 5.41604996e+00 5.42955017e+00 5.44304991e+00 5.45655012e+00 - 5.47004986e+00 5.48355007e+00 5.49704981e+00 5.51055002e+00 - 5.52405024e+00 5.53754997e+00 5.55105019e+00 5.56454992e+00 - 5.57805014e+00 5.59154987e+00 5.60505009e+00 5.61854982e+00 - 5.63205004e+00 5.64554977e+00 5.65904999e+00 5.67255020e+00 - 5.68604994e+00 5.69955015e+00 5.71304989e+00 5.72655010e+00 - 5.74004984e+00 5.75355005e+00 5.76704979e+00 5.78055000e+00 - 5.79405022e+00 5.80754995e+00 5.82105017e+00 5.83454990e+00 - 5.84805012e+00 5.86154985e+00 5.87505007e+00 5.88854980e+00 - 5.90205002e+00 5.91555023e+00 5.92904997e+00 5.94255018e+00 - 5.95604992e+00 5.96955013e+00 5.98304987e+00 5.99655008e+00 - 6.01004982e+00 6.02355003e+00 6.03704977e+00 6.05054998e+00 - 6.06405020e+00 6.07754993e+00 6.09105015e+00 6.10454988e+00 - 6.11805010e+00 6.13154984e+00 6.14505005e+00 6.15854979e+00 - 6.17205000e+00 6.18555021e+00 6.19904995e+00 6.21255016e+00 - 6.22604990e+00 6.23955011e+00 6.25304985e+00 6.26655006e+00 - 6.28004980e+00 6.29355001e+00 6.30705023e+00 6.32054996e+00 - 6.33405018e+00 6.34754992e+00 6.36105013e+00 6.37454987e+00 - 6.38805008e+00 6.40154982e+00 6.41505003e+00 6.42854977e+00 - 6.44204998e+00 6.45555019e+00 6.46904993e+00 6.48255014e+00 - 6.49604988e+00 6.50955009e+00 6.52304983e+00 6.53655005e+00 - 6.55004978e+00 6.56355000e+00 6.57705021e+00 6.59054995e+00 - 6.60405016e+00 6.61754990e+00 6.63105011e+00 6.64454985e+00 - 6.65805006e+00 6.67154980e+00 6.68505001e+00 6.69855022e+00 - 6.71204996e+00 6.72555017e+00 6.73904991e+00 6.75255013e+00 - 6.76604986e+00 6.77955008e+00 6.79304981e+00 6.80655003e+00 - 6.82004976e+00 6.83354998e+00 6.84705019e+00 6.86054993e+00 - 6.87405014e+00 6.88754988e+00 6.90105009e+00 6.91454983e+00 - 6.92805004e+00 6.94154978e+00 6.95504999e+00 6.96855021e+00 - 6.98204994e+00 6.99555016e+00 7.00904989e+00 7.02255011e+00 - 7.03604984e+00 7.04955006e+00 7.06304979e+00 7.07655001e+00 - 7.09005022e+00 7.10354996e+00 7.11705017e+00 7.13054991e+00 - 7.14405012e+00 7.15782690e+00 7.17216969e+00 7.18710089e+00 - 7.20264530e+00 7.21882725e+00 7.23567390e+00 7.25321150e+00 - 7.27146959e+00 7.29047680e+00 7.31026411e+00 7.33086348e+00 - 7.35230875e+00 7.37463427e+00 7.39787626e+00 7.42207193e+00 - 7.44726086e+00 7.47348356e+00 7.50078297e+00 7.52920294e+00 - 7.55878925e+00 7.58959007e+00 7.62330008e+00 7.65929985e+00 - 7.69530010e+00 7.73129988e+00 7.76730013e+00 7.80329990e+00 - 7.83930016e+00 7.87529993e+00 7.91130018e+00 7.94729996e+00 - 7.98330021e+00 8.01930046e+00 8.05529976e+00 8.09130001e+00 - 8.12730026e+00 8.16329956e+00 8.19929981e+00 8.23530006e+00 - 8.27130032e+00 8.30729961e+00 8.34329987e+00 8.37930012e+00 - 8.41530037e+00 8.45129967e+00 8.48729992e+00 8.52330017e+00 - 8.55930042e+00 8.59529972e+00 8.63129997e+00 8.66730022e+00 - 8.70330048e+00 8.73929977e+00 8.77530003e+00 8.81130028e+00 - 8.84729958e+00 8.88329983e+00 8.91930008e+00 8.95530033e+00] - y_upper_bound: [ -5.57520008e+00 -5.53919983e+00 -5.50320005e+00 -5.46719980e+00 - -5.43120003e+00 -5.39519978e+00 -5.35920000e+00 -5.32320023e+00 - -5.28719997e+00 -5.25120020e+00 -5.21519995e+00 -5.17920017e+00 - -5.14319992e+00 -5.10720015e+00 -5.07119989e+00 -5.03520012e+00 - -4.99919987e+00 -4.96320009e+00 -4.92719984e+00 -4.89120007e+00 - -4.85519981e+00 -4.81920004e+00 -4.78319979e+00 -4.74720001e+00 - -4.71120024e+00 -4.67519999e+00 -4.63920021e+00 -4.60319996e+00 - -4.56720018e+00 -4.53119993e+00 -4.49520016e+00 -4.45919991e+00 - -4.42320013e+00 -4.38719988e+00 -4.35120010e+00 -4.31519985e+00 - -4.27920008e+00 -4.24319983e+00 -4.20948982e+00 -4.17868900e+00 - -4.14910269e+00 -4.12068319e+00 -4.09338379e+00 -4.06716108e+00 - -4.04197168e+00 -4.01777601e+00 -3.99453425e+00 -3.97220898e+00 - -3.95076370e+00 -3.93016410e+00 -3.91037679e+00 -3.89136934e+00 - -3.87311172e+00 -3.85557365e+00 -3.83872724e+00 -3.82254505e+00 - -3.80700088e+00 -3.79206967e+00 -3.77772713e+00 -3.76395011e+00 - -3.75044990e+00 -3.73694992e+00 -3.72344995e+00 -3.70994997e+00 - -3.69645000e+00 -3.68295002e+00 -3.66945004e+00 -3.65595007e+00 - -3.64245009e+00 -3.62895012e+00 -3.61544991e+00 -3.60194993e+00 - -3.58844995e+00 -3.57494998e+00 -3.56145000e+00 -3.54795003e+00 - -3.53445005e+00 -3.52095008e+00 -3.50745010e+00 -3.49394989e+00 - -3.48044991e+00 -3.46694994e+00 -3.45344996e+00 -3.43994999e+00 - -3.42645001e+00 -3.41295004e+00 -3.39945006e+00 -3.38595009e+00 - -3.37245011e+00 -3.35894990e+00 -3.34544992e+00 -3.33194995e+00 - -3.31844997e+00 -3.30495000e+00 -3.29145002e+00 -3.27795005e+00 - -3.26445007e+00 -3.25095010e+00 -3.23744988e+00 -3.22394991e+00 - -3.21044993e+00 -3.19694996e+00 -3.18344998e+00 -3.16995001e+00 - -3.15645003e+00 -3.14295006e+00 -3.12945008e+00 -3.11595011e+00 - -3.10244989e+00 -3.08894992e+00 -3.07544994e+00 -3.06194997e+00 - -3.04844999e+00 -3.03495002e+00 -3.02145004e+00 -3.00795007e+00 - -2.99445009e+00 -2.98095012e+00 -2.96744990e+00 -2.95394993e+00 - -2.94044995e+00 -2.92694998e+00 -2.91345000e+00 -2.89995003e+00 - -2.88645005e+00 -2.87295008e+00 -2.85945010e+00 -2.84594989e+00 - -2.83244991e+00 -2.81894994e+00 -2.80544996e+00 -2.79194999e+00 - -2.77845001e+00 -2.76495004e+00 -2.75145006e+00 -2.73795009e+00 - -2.72445011e+00 -2.71094990e+00 -2.69744992e+00 -2.68394995e+00 - -2.67044997e+00 -2.65695000e+00 -2.64345002e+00 -2.62995005e+00 - -2.61645007e+00 -2.60295010e+00 -2.58944988e+00 -2.57594991e+00 - -2.56244993e+00 -2.54894996e+00 -2.53544998e+00 -2.52195001e+00 - -2.50845003e+00 -2.49495006e+00 -2.48145008e+00 -2.46795011e+00 - -2.45444989e+00 -2.44094992e+00 -2.42744994e+00 -2.41394997e+00 - -2.40044999e+00 -2.38695002e+00 -2.37345004e+00 -2.35995007e+00 - -2.34645009e+00 -2.33295012e+00 -2.31944990e+00 -2.30594993e+00 - -2.29244995e+00 -2.27894998e+00 -2.26545000e+00 -2.25195003e+00 - -2.23845005e+00 -2.22495008e+00 -2.21145010e+00 -2.19794989e+00 - -2.18444991e+00 -2.17094994e+00 -2.15744996e+00 -2.14394999e+00 - -2.13045001e+00 -2.11695004e+00 -2.10345006e+00 -2.08995008e+00 - -2.07645011e+00 -2.06294990e+00 -2.04944992e+00 -2.03594995e+00 - -2.02244997e+00 -2.00895000e+00 -1.99545002e+00 -1.98195004e+00 - -1.96844995e+00 -1.95494998e+00 -1.94145000e+00 -1.92795002e+00 - -1.91445005e+00 -1.90094995e+00 -1.88744998e+00 -1.87395000e+00 - -1.86045003e+00 -1.84695005e+00 -1.83344996e+00 -1.81994998e+00 - -1.80645001e+00 -1.79295003e+00 -1.77945006e+00 -1.76594996e+00 - -1.75244999e+00 -1.73895001e+00 -1.72545004e+00 -1.71194994e+00 - -1.69844997e+00 -1.68494999e+00 -1.67145002e+00 -1.65795004e+00 - -1.64444995e+00 -1.63094997e+00 -1.61745000e+00 -1.60395002e+00 - -1.59045005e+00 -1.57694995e+00 -1.56344998e+00 -1.54995000e+00 - -1.53645003e+00 -1.52295005e+00 -1.50944996e+00 -1.49594998e+00 - -1.48245001e+00 -1.46895003e+00 -1.45545006e+00 -1.44194996e+00 - -1.42844999e+00 -1.41495001e+00 -1.40145004e+00 -1.38794994e+00 - -1.37444997e+00 -1.36094999e+00 -1.34745002e+00 -1.33395004e+00 - -1.32044995e+00 -1.30694997e+00 -1.29345000e+00 -1.27995002e+00 - -1.26645005e+00 -1.25294995e+00 -1.23944998e+00 -1.22595000e+00 - -1.21245003e+00 -1.19895005e+00 -1.18544996e+00 -1.17194998e+00 - -1.15845001e+00 -1.14495003e+00 -1.13145006e+00 -1.11794996e+00 - -1.10444999e+00 -1.09095001e+00 -1.07745004e+00 -1.06394994e+00 - -1.05044997e+00 -1.03694999e+00 -1.02345002e+00 -1.00995004e+00 - -9.96450007e-01 -9.82949972e-01 -9.69449997e-01 -9.55950022e-01 - -9.42449987e-01 -9.28950012e-01 -9.15449977e-01 -9.01950002e-01 - -8.88450027e-01 -8.74949992e-01 -8.61450016e-01 -8.47949982e-01 - -8.34450006e-01 -8.20949972e-01 -8.07449996e-01 -7.93950021e-01 - -7.80449986e-01 -7.66950011e-01 -7.53449976e-01 -7.39950001e-01 - -7.26450026e-01 -7.12949991e-01 -6.99450016e-01 -6.85949981e-01 - -6.72450006e-01 -6.58949971e-01 -6.45449996e-01 -6.31950021e-01 - -6.18449986e-01 -6.04950011e-01 -5.91449976e-01 -5.77950001e-01 - -5.64450026e-01 -5.50949991e-01 -5.37450016e-01 -5.23949981e-01 - -5.10450006e-01 -4.96950001e-01 -4.83449996e-01 -4.69949991e-01 - -4.56449986e-01 -4.42950010e-01 -4.29450005e-01 -4.15950000e-01 - -4.02449995e-01 -3.88949990e-01 -3.75449985e-01 -3.61950010e-01 - -3.48450005e-01 -3.34950000e-01 -3.21449995e-01 -3.07949990e-01 - -2.94450015e-01 -2.80950010e-01 -2.67450005e-01 -2.53950000e-01 - -2.40449995e-01 -2.26950005e-01 -2.13450000e-01 -1.99949995e-01 - -1.86450005e-01 -1.72950000e-01 -1.59449995e-01 -1.45950004e-01 - -1.32449999e-01 -1.18950002e-01 -1.05449997e-01 -9.19499993e-02 - -7.84500018e-02 -6.49499968e-02 -5.14499992e-02 -3.79500017e-02 - -2.44500004e-02 -1.09500000e-02 2.55000009e-03 1.60499997e-02 - 2.95499992e-02 4.30499986e-02 5.65499999e-02 7.00500011e-02 - 8.35499987e-02 9.70500037e-02 1.10550001e-01 1.24049999e-01 - 1.37549996e-01 1.51050001e-01 1.64550006e-01 1.78049996e-01 - 1.91550002e-01 2.05050007e-01 2.18549997e-01 2.32050002e-01 - 2.45550007e-01 2.59050012e-01 2.72549987e-01 2.86049992e-01 - 2.99549997e-01 3.13050002e-01 3.26550007e-01 3.40050012e-01 - 3.53549987e-01 3.67049992e-01 3.80549997e-01 3.94050002e-01 - 4.07550007e-01 4.21050012e-01 4.34549987e-01 4.48049992e-01 - 4.61549997e-01 4.75050002e-01 4.88550007e-01 5.02049983e-01 - 5.15550017e-01 5.29049993e-01 5.42550027e-01 5.56050003e-01 - 5.69549978e-01 5.83050013e-01 5.96549988e-01 6.10050023e-01 - 6.23549998e-01 6.37049973e-01 6.50550008e-01 6.64049983e-01 - 6.77550018e-01 6.91049993e-01 7.04550028e-01 7.18050003e-01 - 7.31549978e-01 7.45050013e-01 7.58549988e-01 7.72050023e-01 - 7.85549998e-01 7.99049973e-01 8.12550008e-01 8.26049984e-01 - 8.39550018e-01 8.53049994e-01 8.66550028e-01 8.80050004e-01 - 8.93549979e-01 9.07050014e-01 9.20549989e-01 9.34050024e-01 - 9.47549999e-01 9.61049974e-01 9.74550009e-01 9.88049984e-01 - 1.00154996e+00 1.01505005e+00 1.02855003e+00 1.04205000e+00 - 1.05554998e+00 1.06904995e+00 1.08255005e+00 1.09605002e+00 - 1.10955000e+00 1.12304997e+00 1.13654995e+00 1.15005004e+00 - 1.16355002e+00 1.17704999e+00 1.19054997e+00 1.20404994e+00 - 1.21755004e+00 1.23105001e+00 1.24454999e+00 1.25804996e+00 - 1.27155006e+00 1.28505003e+00 1.29855001e+00 1.31204998e+00 - 1.32554996e+00 1.33905005e+00 1.35255003e+00 1.36605000e+00 - 1.37954998e+00 1.39304996e+00 1.40655005e+00 1.42005002e+00 - 1.43355000e+00 1.44704998e+00 1.46054995e+00 1.47405005e+00 - 1.48755002e+00 1.50105000e+00 1.51454997e+00 1.52804995e+00 - 1.54155004e+00 1.55505002e+00 1.56854999e+00 1.58204997e+00 - 1.59554994e+00 1.60905004e+00 1.62255001e+00 1.63604999e+00 - 1.64954996e+00 1.66305006e+00 1.67655003e+00 1.69005001e+00 - 1.70354998e+00 1.71704996e+00 1.73055005e+00 1.74405003e+00 - 1.75755000e+00 1.77104998e+00 1.78454995e+00 1.79805005e+00 - 1.81155002e+00 1.82505000e+00 1.83854997e+00 1.85204995e+00 - 1.86555004e+00 1.87905002e+00 1.89254999e+00 1.90604997e+00 - 1.91954994e+00 1.93305004e+00 1.94655001e+00 1.96004999e+00 - 1.97354996e+00 1.98705006e+00 2.00055003e+00 2.01405001e+00 - 2.02754998e+00 2.04104996e+00 2.05454993e+00 2.06804991e+00 - 2.08154988e+00 2.09505010e+00 2.10855007e+00 2.12205005e+00 - 2.13555002e+00 2.14905000e+00 2.16254997e+00 2.17604995e+00 - 2.18954992e+00 2.20304990e+00 2.21655011e+00 2.23005009e+00 - 2.24355006e+00 2.25705004e+00 2.27055001e+00 2.28404999e+00 - 2.29754996e+00 2.31104994e+00 2.32454991e+00 2.33804989e+00 - 2.35155010e+00 2.36505008e+00 2.37855005e+00 2.39205003e+00 - 2.40555000e+00 2.41904998e+00 2.43254995e+00 2.44604993e+00 - 2.45954990e+00 2.47305012e+00 2.48655009e+00 2.50005007e+00 - 2.51355004e+00 2.52705002e+00 2.54054999e+00 2.55404997e+00 - 2.56754994e+00 2.58104992e+00 2.59454989e+00 2.60805011e+00 - 2.62155008e+00 2.63505006e+00 2.64855003e+00 2.66205001e+00 - 2.67554998e+00 2.68904996e+00 2.70254993e+00 2.71604991e+00 - 2.72954988e+00 2.74305010e+00 2.75655007e+00 2.77005005e+00 - 2.78355002e+00 2.79705000e+00 2.81054997e+00 2.82404995e+00 - 2.83754992e+00 2.85104990e+00 2.86455011e+00 2.87805009e+00 - 2.89155006e+00 2.90505004e+00 2.91855001e+00 2.93204999e+00 - 2.94554996e+00 2.95904994e+00 2.97254992e+00 2.98604989e+00 - 2.99955010e+00 3.01305008e+00 3.02655005e+00 3.04005003e+00 - 3.05355000e+00 3.06704998e+00 3.08054996e+00 3.09404993e+00 - 3.10754991e+00 3.12104988e+00 3.13455009e+00 3.14805007e+00 - 3.16155005e+00 3.17505002e+00 3.18855000e+00 3.20204997e+00 - 3.21554995e+00 3.22904992e+00 3.24254990e+00 3.25605011e+00 - 3.26955009e+00 3.28305006e+00 3.29655004e+00 3.31005001e+00 - 3.32354999e+00 3.33704996e+00 3.35054994e+00 3.36404991e+00 - 3.37754989e+00 3.39105010e+00 3.40455008e+00 3.41805005e+00 - 3.43155003e+00 3.44505000e+00 3.45854998e+00 3.47204995e+00 - 3.48554993e+00 3.49904990e+00 3.51255012e+00 3.52605009e+00 - 3.53955007e+00 3.55305004e+00 3.56655002e+00 3.58004999e+00 - 3.59354997e+00 3.60704994e+00 3.62054992e+00 3.63404989e+00 - 3.64755011e+00 3.66105008e+00 3.67455006e+00 3.68805003e+00 - 3.70155001e+00 3.71504998e+00 3.72854996e+00 3.74204993e+00 - 3.75554991e+00 3.76904988e+00 3.78255010e+00 3.79605007e+00 - 3.80955005e+00 3.82305002e+00 3.83655000e+00 3.85004997e+00 - 3.86354995e+00 3.87704992e+00 3.89054990e+00 3.90405011e+00 - 3.91755009e+00 3.93105006e+00 3.94455004e+00 3.95805001e+00 - 3.97154999e+00 3.98504996e+00 3.99854994e+00 4.01205015e+00 - 4.02554989e+00 4.03905010e+00 4.05254984e+00 4.06605005e+00 - 4.07954979e+00 4.09305000e+00 4.10655022e+00 4.12004995e+00 - 4.13355017e+00 4.14704990e+00 4.16055012e+00 4.17404985e+00 - 4.18755007e+00 4.20104980e+00 4.21455002e+00 4.22805023e+00 - 4.24154997e+00 4.25505018e+00 4.26854992e+00 4.28205013e+00 - 4.29554987e+00 4.30905008e+00 4.32254982e+00 4.33605003e+00 - 4.34954977e+00 4.36304998e+00 4.37655020e+00 4.39004993e+00 - 4.40355015e+00 4.41704988e+00 4.43055010e+00 4.44404984e+00 - 4.45755005e+00 4.47104979e+00 4.48455000e+00 4.49805021e+00 - 4.51154995e+00 4.52505016e+00 4.53854990e+00 4.55205011e+00 - 4.56554985e+00 4.57905006e+00 4.59254980e+00 4.60605001e+00 - 4.61955023e+00 4.63304996e+00 4.64655018e+00 4.66004992e+00 - 4.67355013e+00 4.68704987e+00 4.70055008e+00 4.71404982e+00 - 4.72755003e+00 4.74104977e+00 4.75454998e+00 4.76805019e+00 - 4.78154993e+00 4.79505014e+00 4.80854988e+00 4.82205009e+00 - 4.83554983e+00 4.84905005e+00 4.86254978e+00 4.87605000e+00 - 4.88955021e+00 4.90304995e+00 4.91655016e+00 4.93004990e+00 - 4.94355011e+00 4.95704985e+00 4.97055006e+00 4.98404980e+00 - 4.99755001e+00 5.01105022e+00 5.02454996e+00 5.03805017e+00 - 5.05154991e+00 5.06505013e+00 5.07854986e+00 5.09205008e+00 - 5.10554981e+00 5.11905003e+00 5.13254976e+00 5.14604998e+00 - 5.15955019e+00 5.17304993e+00 5.18655014e+00 5.20004988e+00 - 5.21355009e+00 5.22704983e+00 5.24055004e+00 5.25404978e+00 - 5.26754999e+00 5.28105021e+00 5.29454994e+00 5.30805016e+00 - 5.32154989e+00 5.33505011e+00 5.34854984e+00 5.36205006e+00 - 5.37554979e+00 5.38905001e+00 5.40255022e+00 5.41604996e+00 - 5.42955017e+00 5.44304991e+00 5.45655012e+00 5.47004986e+00 - 5.48355007e+00 5.49704981e+00 5.51055002e+00 5.52405024e+00 - 5.53754997e+00 5.55105019e+00 5.56454992e+00 5.57805014e+00 - 5.59154987e+00 5.60505009e+00 5.61854982e+00 5.63205004e+00 - 5.64554977e+00 5.65904999e+00 5.67255020e+00 5.68604994e+00 - 5.69955015e+00 5.71304989e+00 5.72655010e+00 5.74004984e+00 - 5.75355005e+00 5.76704979e+00 5.78055000e+00 5.79405022e+00 - 5.80754995e+00 5.82105017e+00 5.83454990e+00 5.84805012e+00 - 5.86154985e+00 5.87505007e+00 5.88854980e+00 5.90205002e+00 - 5.91555023e+00 5.92904997e+00 5.94255018e+00 5.95604992e+00 - 5.96955013e+00 5.98304987e+00 5.99655008e+00 6.01004982e+00 - 6.02355003e+00 6.03704977e+00 6.05054998e+00 6.06405020e+00 - 6.07754993e+00 6.09105015e+00 6.10454988e+00 6.11805010e+00 - 6.13154984e+00 6.14505005e+00 6.15854979e+00 6.17205000e+00 - 6.18555021e+00 6.19904995e+00 6.21255016e+00 6.22604990e+00 - 6.23955011e+00 6.25304985e+00 6.26655006e+00 6.28004980e+00 - 6.29355001e+00 6.30705023e+00 6.32054996e+00 6.33405018e+00 - 6.34754992e+00 6.36105013e+00 6.37454987e+00 6.38805008e+00 - 6.40154982e+00 6.41505003e+00 6.42854977e+00 6.44204998e+00 - 6.45555019e+00 6.46904993e+00 6.48255014e+00 6.49604988e+00 - 6.50955009e+00 6.52304983e+00 6.53655005e+00 6.55004978e+00 - 6.56355000e+00 6.57705021e+00 6.59054995e+00 6.60405016e+00 - 6.61754990e+00 6.63105011e+00 6.64454985e+00 6.65805006e+00 - 6.67154980e+00 6.68505001e+00 6.69855022e+00 6.71204996e+00 - 6.72555017e+00 6.73904991e+00 6.75255013e+00 6.76604986e+00 - 6.77955008e+00 6.79304981e+00 6.80655003e+00 6.82004976e+00 - 6.83354998e+00 6.84705019e+00 6.86054993e+00 6.87405014e+00 - 6.88754988e+00 6.90105009e+00 6.91454983e+00 6.92805004e+00 - 6.94154978e+00 6.95504999e+00 6.96855021e+00 6.98204994e+00 - 6.99555016e+00 7.00904989e+00 7.02255011e+00 7.03604984e+00 - 7.04955006e+00 7.06304979e+00 7.07655001e+00 7.09005022e+00 - 7.10354996e+00 7.11705017e+00 7.13054991e+00 7.14405012e+00 - 7.15782690e+00 7.17216969e+00 7.18710089e+00 7.20264530e+00 - 7.21882725e+00 7.23567390e+00 7.25321150e+00 7.27146959e+00 - 7.29047680e+00 7.31026411e+00 7.33086348e+00 7.35230875e+00 - 7.37463427e+00 7.39787626e+00 7.42207193e+00 7.44726086e+00 - 7.47348356e+00 7.50078297e+00 7.52920294e+00 7.55878925e+00 - 7.58959007e+00 7.62330008e+00 7.65929985e+00 7.69530010e+00 - 7.73129988e+00 7.76730013e+00 7.80329990e+00 7.83930016e+00 - 7.87529993e+00 7.91130018e+00 7.94729996e+00 7.98330021e+00 - 8.01930046e+00 8.05529976e+00 8.09130001e+00 8.12730026e+00 - 8.16329956e+00 8.19929981e+00 8.23530006e+00 8.27130032e+00 - 8.30729961e+00 8.34329987e+00 8.37930012e+00 8.41530037e+00 - 8.45129967e+00 8.48729992e+00 8.52330017e+00 8.55930042e+00 - 8.59529972e+00 8.63129997e+00 8.66730022e+00 8.70330048e+00 - 8.73929977e+00 8.77530003e+00 8.81130028e+00 8.84729958e+00 - 8.88329983e+00 8.91930008e+00 8.95530033e+00 8.99129963e+00] + data: [[100016. 100016. 100016. ... 100926. 100931. 100932.] + [100014. 100014. 100014. ... 100930. 100934. 100934.] + [100015. 100015. 100015. ... 100932. 100937. 100936.] + ... + [102204. 102212. 102219. ... 101650. 101623. 101623.] + [102210. 102218. 102225. ... 101657. 101639. 101635.] + [102216. 102224. 102231. ... 101675. 101654. 101648.]] + x: [353.0525 353.0885 353.1245 353.1605 353.1965 353.2325 353.2685 + 353.3045 353.3405 353.3765 353.4125 353.4485 353.4845 353.5205 + 353.5565 353.5925 353.6285 353.6645 353.7005 353.7365 353.7725 + 353.8085 353.8445 353.8805 353.9165 353.9525 353.9885 354.0245 + 354.0605 354.0965 354.1325 354.1685 354.2045 354.2405 354.2765 + 354.3125 354.3485 354.3845 354.4205 354.4565 354.4925 354.52185 + 354.5501 354.57736 354.60364 354.62894 354.65332 354.67685 354.6995 + 354.7213 354.74234 354.76263 354.78217 354.801 354.81915 354.83664 + 354.8535 354.86972 354.88538 354.90045 354.91498 354.929 354.9425 + 354.956 354.9695 354.983 354.9965 355.01 355.0235 355.037 + 355.0505 355.064 355.0775 355.091 355.1045 355.118 355.1315 + 355.145 355.1585 355.172 355.1855 355.199 355.2125 355.226 + 355.2395 355.253 355.2665 355.28 355.2935 355.307 355.3205 + 355.334 355.3475 355.361 355.3745 355.388 355.4015 355.415 + 355.4285 355.442 355.4555 355.469 355.4825 355.496 355.5095 + 355.523 355.5365 355.55 355.5635 355.577 355.5905 355.604 + 355.6175 355.631 355.6445 355.658 355.6715 355.685 355.6985 + 355.712 355.7255 355.739 355.7525 355.766 355.7795 355.793 + 355.8065 355.82 355.8335 355.847 355.8605 355.874 355.8875 + 355.901 355.9145 355.928 355.9415 355.955 355.9685 355.982 + 355.9955 356.009 356.0225 356.036 356.0495 356.063 356.0765 + 356.09 356.1035 356.117 356.1305 356.144 356.1575 356.171 + 356.1845 356.198 356.2115 356.225 356.2385 356.252 356.2655 + 356.279 356.2925 356.306 356.3195 356.333 356.3465 356.36 + 356.3735 356.387 356.4005 356.414 356.4275 356.441 356.4545 + 356.468 356.4815 356.495 356.5085 356.522 356.5355 356.549 + 356.5625 356.576 356.5895 356.603 356.6165 356.63 356.6435 + 356.657 356.6705 356.684 356.6975 356.711 356.7245 356.738 + 356.7515 356.765 356.7785 356.792 356.8055 356.819 356.8325 + 356.846 356.8595 356.873 356.8865 356.9 356.9135 356.927 + 356.9405 356.954 356.9675 356.981 356.9945 357.008 357.0215 + 357.035 357.0485 357.062 357.0755 357.089 357.1025 357.116 + 357.1295 357.143 357.1565 357.17 357.1835 357.197 357.2105 + 357.224 357.2375 357.251 357.2645 357.278 357.2915 357.305 + 357.3185 357.332 357.3455 357.359 357.3725 357.386 357.3995 + 357.413 357.4265 357.44 357.4535 357.467 357.4805 357.494 + 357.5075 357.521 357.5345 357.548 357.5615 357.575 357.5885 + 357.602 357.6155 357.629 357.6425 357.656 357.6695 357.683 + 357.6965 357.71 357.7235 357.737 357.7505 357.764 357.7775 + 357.791 357.8045 357.818 357.8315 357.845 357.8585 357.872 + 357.8855 357.899 357.9125 357.926 357.9395 357.953 357.9665 + 357.98 357.9935 358.007 358.0205 358.034 358.0475 358.061 + 358.0745 358.088 358.1015 358.115 358.1285 358.142 358.1555 + 358.169 358.1825 358.196 358.2095 358.223 358.2365 358.25 + 358.2635 358.277 358.2905 358.304 358.3175 358.331 358.3445 + 358.358 358.3715 358.385 358.3985 358.412 358.4255 358.439 + 358.4525 358.466 358.4795 358.493 358.5065 358.52 358.5335 + 358.547 358.5605 358.574 358.5875 358.601 358.6145 358.628 + 358.6415 358.655 358.6685 358.682 358.6955 358.709 358.7225 + 358.736 358.7495 358.763 358.7765 358.79 358.8035 358.817 + 358.8305 358.844 358.8575 358.871 358.8845 358.898 358.9115 + 358.925 358.9385 358.952 358.9655 358.979 358.9925 359.006 + 359.0195 359.033 359.0465 359.06 359.0735 359.087 359.1005 + 359.114 359.1275 359.141 359.1545 359.168 359.1815 359.195 + 359.2085 359.222 359.2355 359.249 359.2625 359.276 359.2895 + 359.303 359.3165 359.33 359.3435 359.357 359.3705 359.384 + 359.3975 359.411 359.4245 359.438 359.4515 359.465 359.4785 + 359.492 359.5055 359.519 359.5325 359.546 359.5595 359.573 + 359.5865 359.6 359.6135 359.627 359.6405 359.654 359.6675 + 359.681 359.6945 359.708 359.7215 359.735 359.7485 359.762 + 359.7755 359.789 359.8025 359.816 359.8295 359.843 359.8565 + 359.87 359.8835 359.897 359.9105 359.924 359.9375 359.951 + 359.9645 359.978 359.9915 360.005 360.0185 360.032 360.0455 + 360.059 360.0725 360.086 360.0995 360.113 360.1265 360.14 + 360.1535 360.167 360.1805 360.194 360.2075 360.221 360.2345 + 360.248 360.2615 360.275 360.2885 360.302 360.3155 360.329 + 360.3425 360.356 360.3695 360.383 360.3965 360.41 360.4235 + 360.437 360.4505 360.464 360.4775 360.491 360.5045 360.518 + 360.5315 360.545 360.5585 360.572 360.5855 360.599 360.6125 + 360.626 360.6395 360.653 360.6665 360.68 360.6935 360.707 + 360.7205 360.734 360.7475 360.761 360.7745 360.788 360.8015 + 360.815 360.8285 360.842 360.8555 360.869 360.8825 360.896 + 360.9095 360.923 360.9365 360.95 360.9635 360.977 360.9905 + 361.004 361.0175 361.031 361.0445 361.058 361.0715 361.085 + 361.0985 361.112 361.1255 361.139 361.1525 361.166 361.1795 + 361.193 361.2065 361.22 361.2335 361.247 361.2605 361.274 + 361.2875 361.301 361.3145 361.328 361.3415 361.355 361.3685 + 361.382 361.3955 361.409 361.4225 361.436 361.4495 361.463 + 361.4765 361.49 361.5035 361.517 361.5305 361.544 361.5575 + 361.571 361.5845 361.598 361.6115 361.625 361.6385 361.652 + 361.6655 361.679 361.6925 361.706 361.7195 361.733 361.7465 + 361.76 361.7735 361.787 361.8005 361.814 361.8275 361.841 + 361.8545 361.868 361.8815 361.895 361.9085 361.922 361.9355 + 361.949 361.9625 361.976 361.9895 362.003 362.0165 362.03 + 362.0435 362.057 362.0705 362.084 362.0975 362.111 362.1245 + 362.138 362.1515 362.165 362.1785 362.192 362.2055 362.219 + 362.2325 362.246 362.2595 362.273 362.2865 362.3 362.3135 + 362.327 362.3405 362.354 362.3675 362.381 362.3945 362.408 + 362.4215 362.435 362.4485 362.462 362.4755 362.489 362.5025 + 362.516 362.5295 362.543 362.5565 362.57 362.5835 362.597 + 362.6105 362.624 362.6375 362.651 362.6645 362.678 362.6915 + 362.705 362.7185 362.732 362.7455 362.759 362.7725 362.786 + 362.7995 362.813 362.8265 362.84 362.8535 362.867 362.8805 + 362.894 362.9075 362.921 362.9345 362.948 362.9615 362.975 + 362.9885 363.002 363.0155 363.029 363.0425 363.056 363.0695 + 363.083 363.0965 363.11 363.1235 363.137 363.1505 363.164 + 363.1775 363.191 363.2045 363.218 363.2315 363.245 363.2585 + 363.272 363.2855 363.299 363.3125 363.3265 363.34103 363.35614 + 363.37177 363.38803 363.40488 363.42236 363.4405 363.45932 363.47888 + 363.49915 363.52017 363.54202 363.56467 363.58817 363.61255 363.63788 + 363.66412 363.69138 363.71967 363.749 363.785 363.821 363.857 + 363.893 363.929 363.965 364.001 364.037 364.073 364.109 + 364.145 364.181 364.217 364.253 364.289 364.325 364.361 + 364.397 364.433 364.469 364.505 364.541 364.577 364.613 + 364.649 364.685 364.721 364.757 364.793 364.829 364.865 + 364.901 364.937 364.973 365.009 365.045 365.081 365.117 + 365.153 365.189 ] + x_lower_bound: [353.0345 353.0705 353.1065 353.1425 353.1785 353.2145 353.2505 + 353.2865 353.3225 353.3585 353.3945 353.4305 353.4665 353.5025 + 353.5385 353.5745 353.6105 353.6465 353.6825 353.7185 353.7545 + 353.7905 353.8265 353.8625 353.8985 353.9345 353.9705 354.0065 + 354.0425 354.0785 354.1145 354.1505 354.1865 354.2225 354.2585 + 354.2945 354.3305 354.3665 354.4025 354.4385 354.4745 354.50717 + 354.53598 354.56375 354.5905 354.61627 354.64114 354.66507 354.68817 + 354.7104 354.73184 354.7525 354.7724 354.7916 354.81006 354.82788 + 354.84506 354.8616 354.87753 354.8929 354.9077 354.922 354.93576 + 354.94925 354.96274 354.97626 354.98975 355.00323 355.01675 355.03024 + 355.04376 355.05725 355.07074 355.08426 355.09775 355.11124 355.12476 + 355.13824 355.15176 355.16525 355.17874 355.19226 355.20575 355.21924 + 355.23276 355.24625 355.25974 355.27325 355.28674 355.30026 355.31375 + 355.32724 355.34076 355.35425 355.36774 355.38126 355.39474 355.40826 + 355.42175 355.43524 355.44876 355.46225 355.47574 355.48926 355.50275 + 355.51624 355.52975 355.54324 355.55676 355.57025 355.58374 355.59726 + 355.61075 355.62424 355.63776 355.65125 355.66476 355.67825 355.69174 + 355.70526 355.71875 355.73224 355.74576 355.75925 355.77274 355.78625 + 355.79974 355.81326 355.82675 355.84024 355.85376 355.86725 355.88074 + 355.89426 355.90775 355.92126 355.93475 355.94824 355.96176 355.97525 + 355.98874 356.00226 356.01575 356.02924 356.04276 356.05624 356.06976 + 356.08325 356.09674 356.11026 356.12375 356.13724 356.15076 356.16425 + 356.17776 356.19125 356.20474 356.21826 356.23175 356.24524 356.25876 + 356.27225 356.28574 356.29926 356.31274 356.32626 356.33975 356.35324 + 356.36676 356.38025 356.39374 356.40726 356.42075 356.43427 356.44775 + 356.46124 356.47476 356.48825 356.50174 356.51526 356.52875 356.54224 + 356.55576 356.56924 356.58276 356.59625 356.60974 356.62326 356.63675 + 356.65024 356.66376 356.67725 356.69073 356.70425 356.71774 356.73126 + 356.74475 356.75824 356.77176 356.78525 356.79874 356.81226 356.82574 + 356.83926 356.85275 356.86624 356.87976 356.89325 356.90674 356.92026 + 356.93375 356.94724 356.96075 356.97424 356.98776 357.00125 357.01474 + 357.02826 357.04175 357.05524 357.06876 357.08224 357.09576 357.10925 + 357.12274 357.13626 357.14975 357.16324 357.17676 357.19025 357.20374 + 357.21725 357.23074 357.24426 357.25775 357.27124 357.28476 357.29825 + 357.31174 357.32526 357.33875 357.35226 357.36575 357.37924 357.39276 + 357.40625 357.41974 357.43326 357.44675 357.46024 357.47375 357.48724 + 357.50076 357.51425 357.52774 357.54126 357.55475 357.56824 357.58176 + 357.59525 357.60876 357.62225 357.63574 357.64926 357.66275 357.67624 + 357.68976 357.70325 357.71674 357.73026 357.74374 357.75726 357.77075 + 357.78424 357.79776 357.81125 357.82474 357.83826 357.85175 357.86526 + 357.87875 357.89224 357.90576 357.91925 357.93274 357.94626 357.95975 + 357.97324 357.98676 358.00024 358.01376 358.02725 358.04074 358.05426 + 358.06775 358.08124 358.09476 358.10825 358.12177 358.13525 358.14874 + 358.16226 358.17575 358.18924 358.20276 358.21625 358.22974 358.24326 + 358.25674 358.27026 358.28375 358.29724 358.31076 358.32425 358.33774 + 358.35126 358.36475 358.37823 358.39175 358.40524 358.41876 358.43225 + 358.44574 358.45926 358.47275 358.48624 358.49976 358.51324 358.52676 + 358.54025 358.55374 358.56726 358.58075 358.59424 358.60776 358.62125 + 358.63474 358.64825 358.66174 358.67526 358.68875 358.70224 358.71576 + 358.72925 358.74274 358.75626 358.76974 358.78326 358.79675 358.81024 + 358.82376 358.83725 358.85074 358.86426 358.87775 358.89124 358.90475 + 358.91824 358.93176 358.94525 358.95874 358.97226 358.98575 358.99924 + 359.01276 359.02625 359.03976 359.05325 359.06674 359.08026 359.09375 + 359.10724 359.12076 359.13425 359.14774 359.16125 359.17474 359.18826 + 359.20175 359.21524 359.22876 359.24225 359.25574 359.26926 359.28275 + 359.29626 359.30975 359.32324 359.33676 359.35025 359.36374 359.37726 + 359.39075 359.40424 359.41776 359.43124 359.44476 359.45825 359.47174 + 359.48526 359.49875 359.51224 359.52576 359.53925 359.55276 359.56625 + 359.57974 359.59326 359.60675 359.62024 359.63376 359.64725 359.66074 + 359.67426 359.68774 359.70126 359.71475 359.72824 359.74176 359.75525 + 359.76874 359.78226 359.79575 359.80927 359.82275 359.83624 359.84976 + 359.86325 359.87674 359.89026 359.90375 359.91724 359.93076 359.94424 + 359.95776 359.97125 359.98474 359.99826 360.01175 360.02524 360.03876 + 360.05225 360.06573 360.07925 360.09274 360.10626 360.11975 360.13324 + 360.14676 360.16025 360.17374 360.18726 360.20074 360.21426 360.22775 + 360.24124 360.25476 360.26825 360.28174 360.29526 360.30875 360.32224 + 360.33575 360.34924 360.36276 360.37625 360.38974 360.40326 360.41675 + 360.43024 360.44376 360.45724 360.47076 360.48425 360.49774 360.51126 + 360.52475 360.53824 360.55176 360.56525 360.57874 360.59225 360.60574 + 360.61926 360.63275 360.64624 360.65976 360.67325 360.68674 360.70026 + 360.71375 360.72726 360.74075 360.75424 360.76776 360.78125 360.79474 + 360.80826 360.82175 360.83524 360.84875 360.86224 360.87576 360.88925 + 360.90274 360.91626 360.92975 360.94324 360.95676 360.97025 360.98376 + 360.99725 361.01074 361.02426 361.03775 361.05124 361.06476 361.07825 + 361.09174 361.10526 361.11874 361.13226 361.14575 361.15924 361.17276 + 361.18625 361.19974 361.21326 361.22675 361.24026 361.25375 361.26724 + 361.28076 361.29425 361.30774 361.32126 361.33475 361.34824 361.36176 + 361.37524 361.38876 361.40225 361.41574 361.42926 361.44275 361.45624 + 361.46976 361.48325 361.49677 361.51025 361.52374 361.53726 361.55075 + 361.56424 361.57776 361.59125 361.60474 361.61826 361.63174 361.64526 + 361.65875 361.67224 361.68576 361.69925 361.71274 361.72626 361.73975 + 361.75323 361.76675 361.78024 361.79376 361.80725 361.82074 361.83426 + 361.84775 361.86124 361.87476 361.88824 361.90176 361.91525 361.92874 + 361.94226 361.95575 361.96924 361.98276 361.99625 362.00974 362.02325 + 362.03674 362.05026 362.06375 362.07724 362.09076 362.10425 362.11774 + 362.13126 362.14474 362.15826 362.17175 362.18524 362.19876 362.21225 + 362.22574 362.23926 362.25275 362.26624 362.27975 362.29324 362.30676 + 362.32025 362.33374 362.34726 362.36075 362.37424 362.38776 362.40125 + 362.41476 362.42825 362.44174 362.45526 362.46875 362.48224 362.49576 + 362.50925 362.52274 362.53625 362.54974 362.56326 362.57675 362.59024 + 362.60376 362.61725 362.63074 362.64426 362.65775 362.67126 362.68475 + 362.69824 362.71176 362.72525 362.73874 362.75226 362.76575 362.77924 + 362.79276 362.80624 362.81976 362.83325 362.84674 362.86026 362.87375 + 362.88724 362.90076 362.91425 362.92776 362.94125 362.95474 362.96826 + 362.98175 362.99524 363.00876 363.02225 363.03574 363.04926 363.06274 + 363.07626 363.08975 363.10324 363.11676 363.13025 363.14374 363.15726 + 363.17075 363.18427 363.19775 363.21124 363.22476 363.23825 363.25174 + 363.26526 363.27875 363.29224 363.30576 363.31952 363.33377 363.34857 + 363.36395 363.3799 363.39645 363.4136 363.43143 363.44992 363.46912 + 363.489 363.50967 363.5311 363.55334 363.57642 363.60037 363.6252 + 363.651 363.67776 363.7055 363.7343 363.767 363.803 363.839 + 363.875 363.911 363.947 363.983 364.019 364.055 364.091 + 364.127 364.163 364.199 364.235 364.271 364.307 364.343 + 364.379 364.415 364.451 364.487 364.523 364.559 364.595 + 364.631 364.667 364.703 364.739 364.775 364.811 364.847 + 364.883 364.919 364.955 364.991 365.027 365.063 365.099 + 365.135 365.171 ] + x_upper_bound: [353.0705 353.1065 353.1425 353.1785 353.2145 353.2505 353.2865 + 353.3225 353.3585 353.3945 353.4305 353.4665 353.5025 353.5385 + 353.5745 353.6105 353.6465 353.6825 353.7185 353.7545 353.7905 + 353.8265 353.8625 353.8985 353.9345 353.9705 354.0065 354.0425 + 354.0785 354.1145 354.1505 354.1865 354.2225 354.2585 354.2945 + 354.3305 354.3665 354.4025 354.4385 354.4745 354.50717 354.53598 + 354.56375 354.5905 354.61627 354.64114 354.66507 354.68817 354.7104 + 354.73184 354.7525 354.7724 354.7916 354.81006 354.82788 354.84506 + 354.8616 354.87753 354.8929 354.9077 354.922 354.93576 354.94925 + 354.96274 354.97626 354.98975 355.00323 355.01675 355.03024 355.04376 + 355.05725 355.07074 355.08426 355.09775 355.11124 355.12476 355.13824 + 355.15176 355.16525 355.17874 355.19226 355.20575 355.21924 355.23276 + 355.24625 355.25974 355.27325 355.28674 355.30026 355.31375 355.32724 + 355.34076 355.35425 355.36774 355.38126 355.39474 355.40826 355.42175 + 355.43524 355.44876 355.46225 355.47574 355.48926 355.50275 355.51624 + 355.52975 355.54324 355.55676 355.57025 355.58374 355.59726 355.61075 + 355.62424 355.63776 355.65125 355.66476 355.67825 355.69174 355.70526 + 355.71875 355.73224 355.74576 355.75925 355.77274 355.78625 355.79974 + 355.81326 355.82675 355.84024 355.85376 355.86725 355.88074 355.89426 + 355.90775 355.92126 355.93475 355.94824 355.96176 355.97525 355.98874 + 356.00226 356.01575 356.02924 356.04276 356.05624 356.06976 356.08325 + 356.09674 356.11026 356.12375 356.13724 356.15076 356.16425 356.17776 + 356.19125 356.20474 356.21826 356.23175 356.24524 356.25876 356.27225 + 356.28574 356.29926 356.31274 356.32626 356.33975 356.35324 356.36676 + 356.38025 356.39374 356.40726 356.42075 356.43427 356.44775 356.46124 + 356.47476 356.48825 356.50174 356.51526 356.52875 356.54224 356.55576 + 356.56924 356.58276 356.59625 356.60974 356.62326 356.63675 356.65024 + 356.66376 356.67725 356.69073 356.70425 356.71774 356.73126 356.74475 + 356.75824 356.77176 356.78525 356.79874 356.81226 356.82574 356.83926 + 356.85275 356.86624 356.87976 356.89325 356.90674 356.92026 356.93375 + 356.94724 356.96075 356.97424 356.98776 357.00125 357.01474 357.02826 + 357.04175 357.05524 357.06876 357.08224 357.09576 357.10925 357.12274 + 357.13626 357.14975 357.16324 357.17676 357.19025 357.20374 357.21725 + 357.23074 357.24426 357.25775 357.27124 357.28476 357.29825 357.31174 + 357.32526 357.33875 357.35226 357.36575 357.37924 357.39276 357.40625 + 357.41974 357.43326 357.44675 357.46024 357.47375 357.48724 357.50076 + 357.51425 357.52774 357.54126 357.55475 357.56824 357.58176 357.59525 + 357.60876 357.62225 357.63574 357.64926 357.66275 357.67624 357.68976 + 357.70325 357.71674 357.73026 357.74374 357.75726 357.77075 357.78424 + 357.79776 357.81125 357.82474 357.83826 357.85175 357.86526 357.87875 + 357.89224 357.90576 357.91925 357.93274 357.94626 357.95975 357.97324 + 357.98676 358.00024 358.01376 358.02725 358.04074 358.05426 358.06775 + 358.08124 358.09476 358.10825 358.12177 358.13525 358.14874 358.16226 + 358.17575 358.18924 358.20276 358.21625 358.22974 358.24326 358.25674 + 358.27026 358.28375 358.29724 358.31076 358.32425 358.33774 358.35126 + 358.36475 358.37823 358.39175 358.40524 358.41876 358.43225 358.44574 + 358.45926 358.47275 358.48624 358.49976 358.51324 358.52676 358.54025 + 358.55374 358.56726 358.58075 358.59424 358.60776 358.62125 358.63474 + 358.64825 358.66174 358.67526 358.68875 358.70224 358.71576 358.72925 + 358.74274 358.75626 358.76974 358.78326 358.79675 358.81024 358.82376 + 358.83725 358.85074 358.86426 358.87775 358.89124 358.90475 358.91824 + 358.93176 358.94525 358.95874 358.97226 358.98575 358.99924 359.01276 + 359.02625 359.03976 359.05325 359.06674 359.08026 359.09375 359.10724 + 359.12076 359.13425 359.14774 359.16125 359.17474 359.18826 359.20175 + 359.21524 359.22876 359.24225 359.25574 359.26926 359.28275 359.29626 + 359.30975 359.32324 359.33676 359.35025 359.36374 359.37726 359.39075 + 359.40424 359.41776 359.43124 359.44476 359.45825 359.47174 359.48526 + 359.49875 359.51224 359.52576 359.53925 359.55276 359.56625 359.57974 + 359.59326 359.60675 359.62024 359.63376 359.64725 359.66074 359.67426 + 359.68774 359.70126 359.71475 359.72824 359.74176 359.75525 359.76874 + 359.78226 359.79575 359.80927 359.82275 359.83624 359.84976 359.86325 + 359.87674 359.89026 359.90375 359.91724 359.93076 359.94424 359.95776 + 359.97125 359.98474 359.99826 360.01175 360.02524 360.03876 360.05225 + 360.06573 360.07925 360.09274 360.10626 360.11975 360.13324 360.14676 + 360.16025 360.17374 360.18726 360.20074 360.21426 360.22775 360.24124 + 360.25476 360.26825 360.28174 360.29526 360.30875 360.32224 360.33575 + 360.34924 360.36276 360.37625 360.38974 360.40326 360.41675 360.43024 + 360.44376 360.45724 360.47076 360.48425 360.49774 360.51126 360.52475 + 360.53824 360.55176 360.56525 360.57874 360.59225 360.60574 360.61926 + 360.63275 360.64624 360.65976 360.67325 360.68674 360.70026 360.71375 + 360.72726 360.74075 360.75424 360.76776 360.78125 360.79474 360.80826 + 360.82175 360.83524 360.84875 360.86224 360.87576 360.88925 360.90274 + 360.91626 360.92975 360.94324 360.95676 360.97025 360.98376 360.99725 + 361.01074 361.02426 361.03775 361.05124 361.06476 361.07825 361.09174 + 361.10526 361.11874 361.13226 361.14575 361.15924 361.17276 361.18625 + 361.19974 361.21326 361.22675 361.24026 361.25375 361.26724 361.28076 + 361.29425 361.30774 361.32126 361.33475 361.34824 361.36176 361.37524 + 361.38876 361.40225 361.41574 361.42926 361.44275 361.45624 361.46976 + 361.48325 361.49677 361.51025 361.52374 361.53726 361.55075 361.56424 + 361.57776 361.59125 361.60474 361.61826 361.63174 361.64526 361.65875 + 361.67224 361.68576 361.69925 361.71274 361.72626 361.73975 361.75323 + 361.76675 361.78024 361.79376 361.80725 361.82074 361.83426 361.84775 + 361.86124 361.87476 361.88824 361.90176 361.91525 361.92874 361.94226 + 361.95575 361.96924 361.98276 361.99625 362.00974 362.02325 362.03674 + 362.05026 362.06375 362.07724 362.09076 362.10425 362.11774 362.13126 + 362.14474 362.15826 362.17175 362.18524 362.19876 362.21225 362.22574 + 362.23926 362.25275 362.26624 362.27975 362.29324 362.30676 362.32025 + 362.33374 362.34726 362.36075 362.37424 362.38776 362.40125 362.41476 + 362.42825 362.44174 362.45526 362.46875 362.48224 362.49576 362.50925 + 362.52274 362.53625 362.54974 362.56326 362.57675 362.59024 362.60376 + 362.61725 362.63074 362.64426 362.65775 362.67126 362.68475 362.69824 + 362.71176 362.72525 362.73874 362.75226 362.76575 362.77924 362.79276 + 362.80624 362.81976 362.83325 362.84674 362.86026 362.87375 362.88724 + 362.90076 362.91425 362.92776 362.94125 362.95474 362.96826 362.98175 + 362.99524 363.00876 363.02225 363.03574 363.04926 363.06274 363.07626 + 363.08975 363.10324 363.11676 363.13025 363.14374 363.15726 363.17075 + 363.18427 363.19775 363.21124 363.22476 363.23825 363.25174 363.26526 + 363.27875 363.29224 363.30576 363.31952 363.33377 363.34857 363.36395 + 363.3799 363.39645 363.4136 363.43143 363.44992 363.46912 363.489 + 363.50967 363.5311 363.55334 363.57642 363.60037 363.6252 363.651 + 363.67776 363.7055 363.7343 363.767 363.803 363.839 363.875 + 363.911 363.947 363.983 364.019 364.055 364.091 364.127 + 364.163 364.199 364.235 364.271 364.307 364.343 364.379 + 364.415 364.451 364.487 364.523 364.559 364.595 364.631 + 364.667 364.703 364.739 364.775 364.811 364.847 364.883 + 364.919 364.955 364.991 365.027 365.063 365.099 365.135 + 365.171 365.207 ] + y: [-5.5932002e+00 -5.5572000e+00 -5.5212002e+00 -5.4851999e+00 + -5.4492002e+00 -5.4131999e+00 -5.3772001e+00 -5.3411999e+00 + -5.3052001e+00 -5.2691998e+00 -5.2332001e+00 -5.1971998e+00 + -5.1612000e+00 -5.1251998e+00 -5.0892000e+00 -5.0531998e+00 + -5.0172000e+00 -4.9812002e+00 -4.9452000e+00 -4.9092002e+00 + -4.8731999e+00 -4.8372002e+00 -4.8011999e+00 -4.7652001e+00 + -4.7291999e+00 -4.6932001e+00 -4.6571999e+00 -4.6212001e+00 + -4.5851998e+00 -4.5492001e+00 -4.5131998e+00 -4.4772000e+00 + -4.4411998e+00 -4.4052000e+00 -4.3692002e+00 -4.3332000e+00 + -4.2972002e+00 -4.2612000e+00 -4.2252002e+00 -4.1937799e+00 + -4.1635985e+00 -4.1346073e+00 -4.1067591e+00 -4.0800085e+00 + -4.0543132e+00 -4.0296307e+00 -4.0059214e+00 -3.9831471e+00 + -3.9612706e+00 -3.9402568e+00 -3.9200714e+00 -3.9006820e+00 + -3.8820570e+00 -3.8641663e+00 -3.8469810e+00 -3.8304734e+00 + -3.8146167e+00 -3.7993851e+00 -3.7847540e+00 -3.7707000e+00 + -3.7572000e+00 -3.7437000e+00 -3.7302001e+00 -3.7167001e+00 + -3.7032001e+00 -3.6896999e+00 -3.6761999e+00 -3.6626999e+00 + -3.6492000e+00 -3.6357000e+00 -3.6222000e+00 -3.6087000e+00 + -3.5952001e+00 -3.5817001e+00 -3.5682001e+00 -3.5546999e+00 + -3.5411999e+00 -3.5276999e+00 -3.5142000e+00 -3.5007000e+00 + -3.4872000e+00 -3.4737000e+00 -3.4602001e+00 -3.4467001e+00 + -3.4331999e+00 -3.4196999e+00 -3.4061999e+00 -3.3927000e+00 + -3.3792000e+00 -3.3657000e+00 -3.3522000e+00 -3.3387001e+00 + -3.3252001e+00 -3.3117001e+00 -3.2981999e+00 -3.2846999e+00 + -3.2711999e+00 -3.2577000e+00 -3.2442000e+00 -3.2307000e+00 + -3.2172000e+00 -3.2037001e+00 -3.1902001e+00 -3.1767001e+00 + -3.1631999e+00 -3.1496999e+00 -3.1362000e+00 -3.1227000e+00 + -3.1092000e+00 -3.0957000e+00 -3.0822001e+00 -3.0687001e+00 + -3.0552001e+00 -3.0416999e+00 -3.0281999e+00 -3.0146999e+00 + -3.0012000e+00 -2.9877000e+00 -2.9742000e+00 -2.9607000e+00 + -2.9472001e+00 -2.9337001e+00 -2.9202001e+00 -2.9066999e+00 + -2.8931999e+00 -2.8796999e+00 -2.8662000e+00 -2.8527000e+00 + -2.8392000e+00 -2.8257000e+00 -2.8122001e+00 -2.7987001e+00 + -2.7852001e+00 -2.7716999e+00 -2.7581999e+00 -2.7447000e+00 + -2.7312000e+00 -2.7177000e+00 -2.7042000e+00 -2.6907001e+00 + -2.6772001e+00 -2.6637001e+00 -2.6501999e+00 -2.6366999e+00 + -2.6231999e+00 -2.6097000e+00 -2.5962000e+00 -2.5827000e+00 + -2.5692000e+00 -2.5557001e+00 -2.5422001e+00 -2.5287001e+00 + -2.5151999e+00 -2.5016999e+00 -2.4881999e+00 -2.4747000e+00 + -2.4612000e+00 -2.4477000e+00 -2.4342000e+00 -2.4207001e+00 + -2.4072001e+00 -2.3936999e+00 -2.3801999e+00 -2.3666999e+00 + -2.3532000e+00 -2.3397000e+00 -2.3262000e+00 -2.3127000e+00 + -2.2992001e+00 -2.2857001e+00 -2.2722001e+00 -2.2586999e+00 + -2.2451999e+00 -2.2316999e+00 -2.2182000e+00 -2.2047000e+00 + -2.1912000e+00 -2.1777000e+00 -2.1642001e+00 -2.1507001e+00 + -2.1372001e+00 -2.1236999e+00 -2.1101999e+00 -2.0967000e+00 + -2.0832000e+00 -2.0697000e+00 -2.0562000e+00 -2.0427001e+00 + -2.0292001e+00 -2.0157001e+00 -2.0021999e+00 -1.9887000e+00 + -1.9752001e+00 -1.9617000e+00 -1.9482000e+00 -1.9347000e+00 + -1.9212000e+00 -1.9076999e+00 -1.8942000e+00 -1.8807000e+00 + -1.8672000e+00 -1.8537000e+00 -1.8401999e+00 -1.8267000e+00 + -1.8132000e+00 -1.7997000e+00 -1.7862000e+00 -1.7727000e+00 + -1.7592000e+00 -1.7457000e+00 -1.7322000e+00 -1.7187001e+00 + -1.7052000e+00 -1.6917000e+00 -1.6782000e+00 -1.6647000e+00 + -1.6512001e+00 -1.6377000e+00 -1.6242000e+00 -1.6107000e+00 + -1.5972000e+00 -1.5836999e+00 -1.5702000e+00 -1.5567000e+00 + -1.5432000e+00 -1.5297000e+00 -1.5161999e+00 -1.5027000e+00 + -1.4892000e+00 -1.4757000e+00 -1.4622000e+00 -1.4487000e+00 + -1.4352000e+00 -1.4217000e+00 -1.4082000e+00 -1.3947001e+00 + -1.3812000e+00 -1.3677000e+00 -1.3542000e+00 -1.3407000e+00 + -1.3272001e+00 -1.3137000e+00 -1.3002000e+00 -1.2867000e+00 + -1.2732000e+00 -1.2596999e+00 -1.2462000e+00 -1.2327000e+00 + -1.2192000e+00 -1.2057000e+00 -1.1921999e+00 -1.1787000e+00 + -1.1652000e+00 -1.1517000e+00 -1.1382000e+00 -1.1247000e+00 + -1.1112000e+00 -1.0977000e+00 -1.0842000e+00 -1.0707000e+00 + -1.0572000e+00 -1.0437000e+00 -1.0302000e+00 -1.0167000e+00 + -1.0032001e+00 -9.8970002e-01 -9.7619998e-01 -9.6270001e-01 + -9.4919997e-01 -9.3570000e-01 -9.2220002e-01 -9.0869999e-01 + -8.9520001e-01 -8.8169998e-01 -8.6820000e-01 -8.5470003e-01 + -8.4119999e-01 -8.2770002e-01 -8.1419998e-01 -8.0070001e-01 + -7.8719997e-01 -7.7370000e-01 -7.6020002e-01 -7.4669999e-01 + -7.3320001e-01 -7.1969998e-01 -7.0620000e-01 -6.9270003e-01 + -6.7919999e-01 -6.6570002e-01 -6.5219998e-01 -6.3870001e-01 + -6.2519997e-01 -6.1170000e-01 -5.9820002e-01 -5.8469999e-01 + -5.7120001e-01 -5.5769998e-01 -5.4420000e-01 -5.3070003e-01 + -5.1719999e-01 -5.0370002e-01 -4.9020001e-01 -4.7670001e-01 + -4.6320000e-01 -4.4970000e-01 -4.3619999e-01 -4.2269999e-01 + -4.0920001e-01 -3.9570001e-01 -3.8220000e-01 -3.6870000e-01 + -3.5519999e-01 -3.4169999e-01 -3.2820001e-01 -3.1470001e-01 + -3.0120000e-01 -2.8770000e-01 -2.7419999e-01 -2.6069999e-01 + -2.4720000e-01 -2.3370001e-01 -2.2020000e-01 -2.0670000e-01 + -1.9320001e-01 -1.7970000e-01 -1.6620000e-01 -1.5270001e-01 + -1.3920000e-01 -1.2570000e-01 -1.1220000e-01 -9.8700002e-02 + -8.5199997e-02 -7.1699999e-02 -5.8200002e-02 -4.4700000e-02 + -3.1199999e-02 -1.7700000e-02 -4.1999999e-03 9.3000000e-03 + 2.2800000e-02 3.6300000e-02 4.9800001e-02 6.3299999e-02 + 7.6800004e-02 9.0300001e-02 1.0380000e-01 1.1730000e-01 + 1.3079999e-01 1.4430000e-01 1.5780000e-01 1.7129999e-01 + 1.8480000e-01 1.9830000e-01 2.1179999e-01 2.2530000e-01 + 2.3880000e-01 2.5229999e-01 2.6580000e-01 2.7930000e-01 + 2.9280001e-01 3.0630001e-01 3.1979999e-01 3.3329999e-01 + 3.4680000e-01 3.6030000e-01 3.7380001e-01 3.8730001e-01 + 4.0079999e-01 4.1429999e-01 4.2780000e-01 4.4130000e-01 + 4.5480001e-01 4.6830001e-01 4.8179999e-01 4.9529999e-01 + 5.0880003e-01 5.2230000e-01 5.3579998e-01 5.4930001e-01 + 5.6279999e-01 5.7630002e-01 5.8980000e-01 6.0329998e-01 + 6.1680001e-01 6.3029999e-01 6.4380002e-01 6.5730000e-01 + 6.7079997e-01 6.8430001e-01 6.9779998e-01 7.1130002e-01 + 7.2479999e-01 7.3830003e-01 7.5180000e-01 7.6529998e-01 + 7.7880001e-01 7.9229999e-01 8.0580002e-01 8.1930000e-01 + 8.3279997e-01 8.4630001e-01 8.5979998e-01 8.7330002e-01 + 8.8679999e-01 9.0030003e-01 9.1380000e-01 9.2729998e-01 + 9.4080001e-01 9.5429999e-01 9.6780002e-01 9.8130000e-01 + 9.9479997e-01 1.0082999e+00 1.0218000e+00 1.0353000e+00 + 1.0488000e+00 1.0623000e+00 1.0757999e+00 1.0893000e+00 + 1.1028000e+00 1.1163000e+00 1.1298000e+00 1.1433001e+00 + 1.1568000e+00 1.1703000e+00 1.1838000e+00 1.1973000e+00 + 1.2108001e+00 1.2243000e+00 1.2378000e+00 1.2513000e+00 + 1.2648000e+00 1.2783000e+00 1.2918000e+00 1.3053000e+00 + 1.3188000e+00 1.3322999e+00 1.3458000e+00 1.3593000e+00 + 1.3728000e+00 1.3863000e+00 1.3997999e+00 1.4133000e+00 + 1.4268000e+00 1.4403000e+00 1.4538000e+00 1.4673001e+00 + 1.4808000e+00 1.4943000e+00 1.5078000e+00 1.5213000e+00 + 1.5348001e+00 1.5483000e+00 1.5618000e+00 1.5753000e+00 + 1.5888000e+00 1.6023000e+00 1.6158000e+00 1.6293000e+00 + 1.6428000e+00 1.6562999e+00 1.6698000e+00 1.6833000e+00 + 1.6968000e+00 1.7103000e+00 1.7237999e+00 1.7373000e+00 + 1.7508000e+00 1.7643000e+00 1.7778000e+00 1.7913001e+00 + 1.8048000e+00 1.8183000e+00 1.8318000e+00 1.8453000e+00 + 1.8588001e+00 1.8723000e+00 1.8858000e+00 1.8993000e+00 + 1.9128000e+00 1.9263000e+00 1.9398000e+00 1.9533000e+00 + 1.9668000e+00 1.9802999e+00 1.9938000e+00 2.0072999e+00 + 2.0208001e+00 2.0343001e+00 2.0478001e+00 2.0613000e+00 + 2.0748000e+00 2.0883000e+00 2.1018000e+00 2.1152999e+00 + 2.1287999e+00 2.1422999e+00 2.1558001e+00 2.1693001e+00 + 2.1828001e+00 2.1963000e+00 2.2098000e+00 2.2233000e+00 + 2.2368000e+00 2.2502999e+00 2.2637999e+00 2.2772999e+00 + 2.2908001e+00 2.3043001e+00 2.3178000e+00 2.3313000e+00 + 2.3448000e+00 2.3583000e+00 2.3717999e+00 2.3852999e+00 + 2.3987999e+00 2.4123001e+00 2.4258001e+00 2.4393001e+00 + 2.4528000e+00 2.4663000e+00 2.4798000e+00 2.4933000e+00 + 2.5067999e+00 2.5202999e+00 2.5337999e+00 2.5473001e+00 + 2.5608001e+00 2.5743001e+00 2.5878000e+00 2.6013000e+00 + 2.6148000e+00 2.6283000e+00 2.6417999e+00 2.6552999e+00 + 2.6688001e+00 2.6823001e+00 2.6958001e+00 2.7093000e+00 + 2.7228000e+00 2.7363000e+00 2.7498000e+00 2.7632999e+00 + 2.7767999e+00 2.7902999e+00 2.8038001e+00 2.8173001e+00 + 2.8308001e+00 2.8443000e+00 2.8578000e+00 2.8713000e+00 + 2.8848000e+00 2.8982999e+00 2.9117999e+00 2.9252999e+00 + 2.9388001e+00 2.9523001e+00 2.9658000e+00 2.9793000e+00 + 2.9928000e+00 3.0063000e+00 3.0197999e+00 3.0332999e+00 + 3.0467999e+00 3.0603001e+00 3.0738001e+00 3.0873001e+00 + 3.1008000e+00 3.1143000e+00 3.1278000e+00 3.1413000e+00 + 3.1547999e+00 3.1682999e+00 3.1817999e+00 3.1953001e+00 + 3.2088001e+00 3.2223001e+00 3.2358000e+00 3.2493000e+00 + 3.2628000e+00 3.2763000e+00 3.2897999e+00 3.3032999e+00 + 3.3168001e+00 3.3303001e+00 3.3438001e+00 3.3573000e+00 + 3.3708000e+00 3.3843000e+00 3.3978000e+00 3.4112999e+00 + 3.4247999e+00 3.4382999e+00 3.4518001e+00 3.4653001e+00 + 3.4788001e+00 3.4923000e+00 3.5058000e+00 3.5193000e+00 + 3.5328000e+00 3.5462999e+00 3.5597999e+00 3.5732999e+00 + 3.5868001e+00 3.6003001e+00 3.6138000e+00 3.6273000e+00 + 3.6408000e+00 3.6543000e+00 3.6677999e+00 3.6812999e+00 + 3.6947999e+00 3.7083001e+00 3.7218001e+00 3.7353001e+00 + 3.7488000e+00 3.7623000e+00 3.7758000e+00 3.7893000e+00 + 3.8027999e+00 3.8162999e+00 3.8297999e+00 3.8433001e+00 + 3.8568001e+00 3.8703001e+00 3.8838000e+00 3.8973000e+00 + 3.9108000e+00 3.9243000e+00 3.9377999e+00 3.9512999e+00 + 3.9647999e+00 3.9783001e+00 3.9918001e+00 4.0053000e+00 + 4.0187998e+00 4.0323000e+00 4.0458002e+00 4.0592999e+00 + 4.0728002e+00 4.0862999e+00 4.0998001e+00 4.1132998e+00 + 4.1268001e+00 4.1402998e+00 4.1538000e+00 4.1673002e+00 + 4.1808000e+00 4.1943002e+00 4.2077999e+00 4.2213001e+00 + 4.2347999e+00 4.2483001e+00 4.2617998e+00 4.2753000e+00 + 4.2887998e+00 4.3023000e+00 4.3158002e+00 4.3292999e+00 + 4.3428001e+00 4.3562999e+00 4.3698001e+00 4.3832998e+00 + 4.3968000e+00 4.4102998e+00 4.4238000e+00 4.4373002e+00 + 4.4507999e+00 4.4643002e+00 4.4777999e+00 4.4913001e+00 + 4.5047998e+00 4.5183001e+00 4.5317998e+00 4.5453000e+00 + 4.5588002e+00 4.5723000e+00 4.5858002e+00 4.5992999e+00 + 4.6128001e+00 4.6262999e+00 4.6398001e+00 4.6532998e+00 + 4.6668000e+00 4.6803002e+00 4.6938000e+00 4.7073002e+00 + 4.7207999e+00 4.7343001e+00 4.7477999e+00 4.7613001e+00 + 4.7747998e+00 4.7883000e+00 4.8017998e+00 4.8153000e+00 + 4.8288002e+00 4.8422999e+00 4.8558002e+00 4.8692999e+00 + 4.8828001e+00 4.8962998e+00 4.9098001e+00 4.9232998e+00 + 4.9368000e+00 4.9503002e+00 4.9638000e+00 4.9773002e+00 + 4.9907999e+00 5.0043001e+00 5.0177999e+00 5.0313001e+00 + 5.0447998e+00 5.0583000e+00 5.0718002e+00 5.0853000e+00 + 5.0988002e+00 5.1122999e+00 5.1258001e+00 5.1392999e+00 + 5.1528001e+00 5.1662998e+00 5.1798000e+00 5.1932998e+00 + 5.2068000e+00 5.2203002e+00 5.2337999e+00 5.2473001e+00 + 5.2607999e+00 5.2743001e+00 5.2877998e+00 5.3013000e+00 + 5.3147998e+00 5.3283000e+00 5.3418002e+00 5.3552999e+00 + 5.3688002e+00 5.3822999e+00 5.3958001e+00 5.4092999e+00 + 5.4228001e+00 5.4362998e+00 5.4498000e+00 5.4633002e+00 + 5.4768000e+00 5.4903002e+00 5.5037999e+00 5.5173001e+00 + 5.5307999e+00 5.5443001e+00 5.5577998e+00 5.5713000e+00 + 5.5847998e+00 5.5983000e+00 5.6118002e+00 5.6252999e+00 + 5.6388001e+00 5.6522999e+00 5.6658001e+00 5.6792998e+00 + 5.6928000e+00 5.7062998e+00 5.7198000e+00 5.7333002e+00 + 5.7467999e+00 5.7603002e+00 5.7737999e+00 5.7873001e+00 + 5.8007998e+00 5.8143001e+00 5.8277998e+00 5.8413000e+00 + 5.8548002e+00 5.8683000e+00 5.8818002e+00 5.8952999e+00 + 5.9088001e+00 5.9222999e+00 5.9358001e+00 5.9492998e+00 + 5.9628000e+00 5.9762998e+00 5.9898000e+00 6.0033002e+00 + 6.0167999e+00 6.0303001e+00 6.0437999e+00 6.0573001e+00 + 6.0707998e+00 6.0843000e+00 6.0977998e+00 6.1113000e+00 + 6.1248002e+00 6.1382999e+00 6.1518002e+00 6.1652999e+00 + 6.1788001e+00 6.1922998e+00 6.2058001e+00 6.2192998e+00 + 6.2328000e+00 6.2463002e+00 6.2598000e+00 6.2733002e+00 + 6.2867999e+00 6.3003001e+00 6.3137999e+00 6.3273001e+00 + 6.3407998e+00 6.3543000e+00 6.3678002e+00 6.3813000e+00 + 6.3948002e+00 6.4082999e+00 6.4218001e+00 6.4352999e+00 + 6.4488001e+00 6.4622998e+00 6.4758000e+00 6.4892998e+00 + 6.5028000e+00 6.5163002e+00 6.5297999e+00 6.5433002e+00 + 6.5567999e+00 6.5703001e+00 6.5837998e+00 6.5973001e+00 + 6.6107998e+00 6.6243000e+00 6.6378002e+00 6.6513000e+00 + 6.6648002e+00 6.6782999e+00 6.6918001e+00 6.7052999e+00 + 6.7188001e+00 6.7322998e+00 6.7458000e+00 6.7593002e+00 + 6.7728000e+00 6.7863002e+00 6.7997999e+00 6.8133001e+00 + 6.8267999e+00 6.8403001e+00 6.8537998e+00 6.8673000e+00 + 6.8807998e+00 6.8943000e+00 6.9078002e+00 6.9212999e+00 + 6.9348001e+00 6.9482999e+00 6.9618001e+00 6.9752998e+00 + 6.9888000e+00 7.0022998e+00 7.0158000e+00 7.0293002e+00 + 7.0427999e+00 7.0563002e+00 7.0697999e+00 7.0833001e+00 + 7.0967999e+00 7.1103001e+00 7.1237998e+00 7.1373000e+00 + 7.1508002e+00 7.1648540e+00 7.1794853e+00 7.1947169e+00 + 7.2105737e+00 7.2270813e+00 7.2442665e+00 7.2621570e+00 + 7.2807817e+00 7.3001714e+00 7.3203568e+00 7.3413706e+00 + 7.3632469e+00 7.3860216e+00 7.4097309e+00 7.4344130e+00 + 7.4601088e+00 7.4868588e+00 7.5147071e+00 7.5436983e+00 + 7.5738797e+00 7.6052999e+00 7.6413002e+00 7.6773000e+00 + 7.7133002e+00 7.7493000e+00 7.7852998e+00 7.8213000e+00 + 7.8572998e+00 7.8933001e+00 7.9292998e+00 7.9653001e+00 + 8.0012999e+00 8.0373001e+00 8.0733004e+00 8.1092997e+00 + 8.1452999e+00 8.1813002e+00 8.2173004e+00 8.2532997e+00 + 8.2893000e+00 8.3253002e+00 8.3613005e+00 8.3972998e+00 + 8.4333000e+00 8.4693003e+00 8.5052996e+00 8.5412998e+00 + 8.5773001e+00 8.6133003e+00 8.6492996e+00 8.6852999e+00 + 8.7213001e+00 8.7573004e+00 8.7932997e+00 8.8292999e+00 + 8.8653002e+00 8.9013004e+00 8.9372997e+00 8.9733000e+00] + y_lower_bound: [-5.6112003e+00 -5.5752001e+00 -5.5391998e+00 -5.5032001e+00 + -5.4671998e+00 -5.4312000e+00 -5.3951998e+00 -5.3592000e+00 + -5.3232002e+00 -5.2872000e+00 -5.2512002e+00 -5.2151999e+00 + -5.1792002e+00 -5.1431999e+00 -5.1072001e+00 -5.0711999e+00 + -5.0352001e+00 -4.9991999e+00 -4.9632001e+00 -4.9271998e+00 + -4.8912001e+00 -4.8551998e+00 -4.8192000e+00 -4.7831998e+00 + -4.7472000e+00 -4.7112002e+00 -4.6752000e+00 -4.6392002e+00 + -4.6032000e+00 -4.5672002e+00 -4.5311999e+00 -4.4952002e+00 + -4.4591999e+00 -4.4232001e+00 -4.3871999e+00 -4.3512001e+00 + -4.3151999e+00 -4.2792001e+00 -4.2431998e+00 -4.2094898e+00 + -4.1786890e+00 -4.1491027e+00 -4.1206832e+00 -4.0933838e+00 + -4.0671611e+00 -4.0419717e+00 -4.0177760e+00 -3.9945343e+00 + -3.9722090e+00 -3.9507637e+00 -3.9301641e+00 -3.9103768e+00 + -3.8913693e+00 -3.8731117e+00 -3.8555737e+00 -3.8387272e+00 + -3.8225451e+00 -3.8070009e+00 -3.7920697e+00 -3.7777271e+00 + -3.7639501e+00 -3.7504499e+00 -3.7369499e+00 -3.7234499e+00 + -3.7099500e+00 -3.6964500e+00 -3.6829500e+00 -3.6694500e+00 + -3.6559501e+00 -3.6424501e+00 -3.6289501e+00 -3.6154499e+00 + -3.6019499e+00 -3.5884500e+00 -3.5749500e+00 -3.5614500e+00 + -3.5479500e+00 -3.5344501e+00 -3.5209501e+00 -3.5074501e+00 + -3.4939499e+00 -3.4804499e+00 -3.4669499e+00 -3.4534500e+00 + -3.4399500e+00 -3.4264500e+00 -3.4129500e+00 -3.3994501e+00 + -3.3859501e+00 -3.3724501e+00 -3.3589499e+00 -3.3454499e+00 + -3.3319499e+00 -3.3184500e+00 -3.3049500e+00 -3.2914500e+00 + -3.2779500e+00 -3.2644501e+00 -3.2509501e+00 -3.2374499e+00 + -3.2239499e+00 -3.2104499e+00 -3.1969500e+00 -3.1834500e+00 + -3.1699500e+00 -3.1564500e+00 -3.1429501e+00 -3.1294501e+00 + -3.1159501e+00 -3.1024499e+00 -3.0889499e+00 -3.0754499e+00 + -3.0619500e+00 -3.0484500e+00 -3.0349500e+00 -3.0214500e+00 + -3.0079501e+00 -2.9944501e+00 -2.9809501e+00 -2.9674499e+00 + -2.9539499e+00 -2.9404500e+00 -2.9269500e+00 -2.9134500e+00 + -2.8999500e+00 -2.8864501e+00 -2.8729501e+00 -2.8594501e+00 + -2.8459499e+00 -2.8324499e+00 -2.8189499e+00 -2.8054500e+00 + -2.7919500e+00 -2.7784500e+00 -2.7649500e+00 -2.7514501e+00 + -2.7379501e+00 -2.7244501e+00 -2.7109499e+00 -2.6974499e+00 + -2.6839499e+00 -2.6704500e+00 -2.6569500e+00 -2.6434500e+00 + -2.6299500e+00 -2.6164501e+00 -2.6029501e+00 -2.5894499e+00 + -2.5759499e+00 -2.5624499e+00 -2.5489500e+00 -2.5354500e+00 + -2.5219500e+00 -2.5084500e+00 -2.4949501e+00 -2.4814501e+00 + -2.4679501e+00 -2.4544499e+00 -2.4409499e+00 -2.4274499e+00 + -2.4139500e+00 -2.4004500e+00 -2.3869500e+00 -2.3734500e+00 + -2.3599501e+00 -2.3464501e+00 -2.3329501e+00 -2.3194499e+00 + -2.3059499e+00 -2.2924500e+00 -2.2789500e+00 -2.2654500e+00 + -2.2519500e+00 -2.2384501e+00 -2.2249501e+00 -2.2114501e+00 + -2.1979499e+00 -2.1844499e+00 -2.1709499e+00 -2.1574500e+00 + -2.1439500e+00 -2.1304500e+00 -2.1169500e+00 -2.1034501e+00 + -2.0899501e+00 -2.0764501e+00 -2.0629499e+00 -2.0494499e+00 + -2.0359499e+00 -2.0224500e+00 -2.0089500e+00 -1.9954500e+00 + -1.9819500e+00 -1.9684500e+00 -1.9549500e+00 -1.9414500e+00 + -1.9279500e+00 -1.9144500e+00 -1.9009500e+00 -1.8874500e+00 + -1.8739500e+00 -1.8604500e+00 -1.8469501e+00 -1.8334500e+00 + -1.8199500e+00 -1.8064500e+00 -1.7929500e+00 -1.7794501e+00 + -1.7659500e+00 -1.7524500e+00 -1.7389500e+00 -1.7254500e+00 + -1.7119499e+00 -1.6984500e+00 -1.6849500e+00 -1.6714500e+00 + -1.6579500e+00 -1.6444499e+00 -1.6309500e+00 -1.6174500e+00 + -1.6039500e+00 -1.5904500e+00 -1.5769500e+00 -1.5634500e+00 + -1.5499500e+00 -1.5364500e+00 -1.5229501e+00 -1.5094500e+00 + -1.4959500e+00 -1.4824500e+00 -1.4689500e+00 -1.4554501e+00 + -1.4419500e+00 -1.4284500e+00 -1.4149500e+00 -1.4014500e+00 + -1.3879499e+00 -1.3744500e+00 -1.3609500e+00 -1.3474500e+00 + -1.3339500e+00 -1.3204499e+00 -1.3069500e+00 -1.2934500e+00 + -1.2799500e+00 -1.2664500e+00 -1.2529500e+00 -1.2394500e+00 + -1.2259500e+00 -1.2124500e+00 -1.1989501e+00 -1.1854500e+00 + -1.1719500e+00 -1.1584500e+00 -1.1449500e+00 -1.1314501e+00 + -1.1179500e+00 -1.1044500e+00 -1.0909500e+00 -1.0774500e+00 + -1.0639499e+00 -1.0504500e+00 -1.0369500e+00 -1.0234500e+00 + -1.0099500e+00 -9.9645001e-01 -9.8294997e-01 -9.6945000e-01 + -9.5595002e-01 -9.4244999e-01 -9.2895001e-01 -9.1544998e-01 + -9.0195000e-01 -8.8845003e-01 -8.7494999e-01 -8.6145002e-01 + -8.4794998e-01 -8.3445001e-01 -8.2094997e-01 -8.0745000e-01 + -7.9395002e-01 -7.8044999e-01 -7.6695001e-01 -7.5344998e-01 + -7.3995000e-01 -7.2645003e-01 -7.1294999e-01 -6.9945002e-01 + -6.8594998e-01 -6.7245001e-01 -6.5894997e-01 -6.4545000e-01 + -6.3195002e-01 -6.1844999e-01 -6.0495001e-01 -5.9144998e-01 + -5.7795000e-01 -5.6445003e-01 -5.5094999e-01 -5.3745002e-01 + -5.2394998e-01 -5.1045001e-01 -4.9695000e-01 -4.8345000e-01 + -4.6994999e-01 -4.5644999e-01 -4.4295001e-01 -4.2945001e-01 + -4.1595000e-01 -4.0245000e-01 -3.8894999e-01 -3.7544999e-01 + -3.6195001e-01 -3.4845001e-01 -3.3495000e-01 -3.2145000e-01 + -3.0794999e-01 -2.9445001e-01 -2.8095001e-01 -2.6745000e-01 + -2.5395000e-01 -2.4044999e-01 -2.2695000e-01 -2.1345000e-01 + -1.9994999e-01 -1.8645000e-01 -1.7295000e-01 -1.5944999e-01 + -1.4595000e-01 -1.3245000e-01 -1.1895000e-01 -1.0545000e-01 + -9.1949999e-02 -7.8450002e-02 -6.4949997e-02 -5.1449999e-02 + -3.7950002e-02 -2.4450000e-02 -1.0950000e-02 2.5500001e-03 + 1.6050000e-02 2.9549999e-02 4.3049999e-02 5.6550000e-02 + 7.0050001e-02 8.3549999e-02 9.7050004e-02 1.1055000e-01 + 1.2405000e-01 1.3755000e-01 1.5105000e-01 1.6455001e-01 + 1.7805000e-01 1.9155000e-01 2.0505001e-01 2.1855000e-01 + 2.3205000e-01 2.4555001e-01 2.5905001e-01 2.7254999e-01 + 2.8604999e-01 2.9955000e-01 3.1305000e-01 3.2655001e-01 + 3.4005001e-01 3.5354999e-01 3.6704999e-01 3.8055000e-01 + 3.9405000e-01 4.0755001e-01 4.2105001e-01 4.3454999e-01 + 4.4804999e-01 4.6155000e-01 4.7505000e-01 4.8855001e-01 + 5.0204998e-01 5.1555002e-01 5.2904999e-01 5.4255003e-01 + 5.5605000e-01 5.6954998e-01 5.8305001e-01 5.9654999e-01 + 6.1005002e-01 6.2355000e-01 6.3704997e-01 6.5055001e-01 + 6.6404998e-01 6.7755002e-01 6.9104999e-01 7.0455003e-01 + 7.1805000e-01 7.3154998e-01 7.4505001e-01 7.5854999e-01 + 7.7205002e-01 7.8555000e-01 7.9904997e-01 8.1255001e-01 + 8.2604998e-01 8.3955002e-01 8.5304999e-01 8.6655003e-01 + 8.8005000e-01 8.9354998e-01 9.0705001e-01 9.2054999e-01 + 9.3405002e-01 9.4755000e-01 9.6104997e-01 9.7455001e-01 + 9.8804998e-01 1.0015500e+00 1.0150501e+00 1.0285500e+00 + 1.0420500e+00 1.0555500e+00 1.0690500e+00 1.0825500e+00 + 1.0960500e+00 1.1095500e+00 1.1230500e+00 1.1365499e+00 + 1.1500500e+00 1.1635500e+00 1.1770500e+00 1.1905500e+00 + 1.2040499e+00 1.2175500e+00 1.2310500e+00 1.2445500e+00 + 1.2580500e+00 1.2715501e+00 1.2850500e+00 1.2985500e+00 + 1.3120500e+00 1.3255500e+00 1.3390501e+00 1.3525500e+00 + 1.3660500e+00 1.3795500e+00 1.3930500e+00 1.4065500e+00 + 1.4200500e+00 1.4335500e+00 1.4470500e+00 1.4605500e+00 + 1.4740500e+00 1.4875500e+00 1.5010500e+00 1.5145500e+00 + 1.5280499e+00 1.5415500e+00 1.5550500e+00 1.5685500e+00 + 1.5820500e+00 1.5955499e+00 1.6090500e+00 1.6225500e+00 + 1.6360500e+00 1.6495500e+00 1.6630501e+00 1.6765500e+00 + 1.6900500e+00 1.7035500e+00 1.7170500e+00 1.7305501e+00 + 1.7440500e+00 1.7575500e+00 1.7710500e+00 1.7845500e+00 + 1.7980500e+00 1.8115500e+00 1.8250500e+00 1.8385500e+00 + 1.8520499e+00 1.8655500e+00 1.8790500e+00 1.8925500e+00 + 1.9060500e+00 1.9195499e+00 1.9330500e+00 1.9465500e+00 + 1.9600500e+00 1.9735500e+00 1.9870501e+00 2.0005500e+00 + 2.0140500e+00 2.0275500e+00 2.0410500e+00 2.0545499e+00 + 2.0680499e+00 2.0815499e+00 2.0950501e+00 2.1085501e+00 + 2.1220500e+00 2.1355500e+00 2.1490500e+00 2.1625500e+00 + 2.1760499e+00 2.1895499e+00 2.2030499e+00 2.2165501e+00 + 2.2300501e+00 2.2435501e+00 2.2570500e+00 2.2705500e+00 + 2.2840500e+00 2.2975500e+00 2.3110499e+00 2.3245499e+00 + 2.3380499e+00 2.3515501e+00 2.3650501e+00 2.3785501e+00 + 2.3920500e+00 2.4055500e+00 2.4190500e+00 2.4325500e+00 + 2.4460499e+00 2.4595499e+00 2.4730501e+00 2.4865501e+00 + 2.5000501e+00 2.5135500e+00 2.5270500e+00 2.5405500e+00 + 2.5540500e+00 2.5675499e+00 2.5810499e+00 2.5945499e+00 + 2.6080501e+00 2.6215501e+00 2.6350501e+00 2.6485500e+00 + 2.6620500e+00 2.6755500e+00 2.6890500e+00 2.7025499e+00 + 2.7160499e+00 2.7295499e+00 2.7430501e+00 2.7565501e+00 + 2.7700500e+00 2.7835500e+00 2.7970500e+00 2.8105500e+00 + 2.8240499e+00 2.8375499e+00 2.8510499e+00 2.8645501e+00 + 2.8780501e+00 2.8915501e+00 2.9050500e+00 2.9185500e+00 + 2.9320500e+00 2.9455500e+00 2.9590499e+00 2.9725499e+00 + 2.9860499e+00 2.9995501e+00 3.0130501e+00 3.0265501e+00 + 3.0400500e+00 3.0535500e+00 3.0670500e+00 3.0805500e+00 + 3.0940499e+00 3.1075499e+00 3.1210499e+00 3.1345501e+00 + 3.1480501e+00 3.1615500e+00 3.1750500e+00 3.1885500e+00 + 3.2020500e+00 3.2155499e+00 3.2290499e+00 3.2425499e+00 + 3.2560501e+00 3.2695501e+00 3.2830501e+00 3.2965500e+00 + 3.3100500e+00 3.3235500e+00 3.3370500e+00 3.3505499e+00 + 3.3640499e+00 3.3775499e+00 3.3910501e+00 3.4045501e+00 + 3.4180501e+00 3.4315500e+00 3.4450500e+00 3.4585500e+00 + 3.4720500e+00 3.4855499e+00 3.4990499e+00 3.5125501e+00 + 3.5260501e+00 3.5395501e+00 3.5530500e+00 3.5665500e+00 + 3.5800500e+00 3.5935500e+00 3.6070499e+00 3.6205499e+00 + 3.6340499e+00 3.6475501e+00 3.6610501e+00 3.6745501e+00 + 3.6880500e+00 3.7015500e+00 3.7150500e+00 3.7285500e+00 + 3.7420499e+00 3.7555499e+00 3.7690499e+00 3.7825501e+00 + 3.7960501e+00 3.8095500e+00 3.8230500e+00 3.8365500e+00 + 3.8500500e+00 3.8635499e+00 3.8770499e+00 3.8905499e+00 + 3.9040501e+00 3.9175501e+00 3.9310501e+00 3.9445500e+00 + 3.9580500e+00 3.9715500e+00 3.9850500e+00 3.9985499e+00 + 4.0120502e+00 4.0255499e+00 4.0390501e+00 4.0525498e+00 + 4.0660501e+00 4.0795498e+00 4.0930500e+00 4.1065502e+00 + 4.1200500e+00 4.1335502e+00 4.1470499e+00 4.1605501e+00 + 4.1740499e+00 4.1875501e+00 4.2010498e+00 4.2145500e+00 + 4.2280502e+00 4.2415500e+00 4.2550502e+00 4.2685499e+00 + 4.2820501e+00 4.2955499e+00 4.3090501e+00 4.3225498e+00 + 4.3360500e+00 4.3495498e+00 4.3630500e+00 4.3765502e+00 + 4.3900499e+00 4.4035501e+00 4.4170499e+00 4.4305501e+00 + 4.4440498e+00 4.4575500e+00 4.4710498e+00 4.4845500e+00 + 4.4980502e+00 4.5115499e+00 4.5250502e+00 4.5385499e+00 + 4.5520501e+00 4.5655499e+00 4.5790501e+00 4.5925498e+00 + 4.6060500e+00 4.6195502e+00 4.6330500e+00 4.6465502e+00 + 4.6600499e+00 4.6735501e+00 4.6870499e+00 4.7005501e+00 + 4.7140498e+00 4.7275500e+00 4.7410498e+00 4.7545500e+00 + 4.7680502e+00 4.7815499e+00 4.7950501e+00 4.8085499e+00 + 4.8220501e+00 4.8355498e+00 4.8490500e+00 4.8625498e+00 + 4.8760500e+00 4.8895502e+00 4.9030499e+00 4.9165502e+00 + 4.9300499e+00 4.9435501e+00 4.9570498e+00 4.9705501e+00 + 4.9840498e+00 4.9975500e+00 5.0110502e+00 5.0245500e+00 + 5.0380502e+00 5.0515499e+00 5.0650501e+00 5.0785499e+00 + 5.0920501e+00 5.1055498e+00 5.1190500e+00 5.1325498e+00 + 5.1460500e+00 5.1595502e+00 5.1730499e+00 5.1865501e+00 + 5.2000499e+00 5.2135501e+00 5.2270498e+00 5.2405500e+00 + 5.2540498e+00 5.2675500e+00 5.2810502e+00 5.2945499e+00 + 5.3080502e+00 5.3215499e+00 5.3350501e+00 5.3485498e+00 + 5.3620501e+00 5.3755498e+00 5.3890500e+00 5.4025502e+00 + 5.4160500e+00 5.4295502e+00 5.4430499e+00 5.4565501e+00 + 5.4700499e+00 5.4835501e+00 5.4970498e+00 5.5105500e+00 + 5.5240502e+00 5.5375500e+00 5.5510502e+00 5.5645499e+00 + 5.5780501e+00 5.5915499e+00 5.6050501e+00 5.6185498e+00 + 5.6320500e+00 5.6455498e+00 5.6590500e+00 5.6725502e+00 + 5.6860499e+00 5.6995502e+00 5.7130499e+00 5.7265501e+00 + 5.7400498e+00 5.7535501e+00 5.7670498e+00 5.7805500e+00 + 5.7940502e+00 5.8075500e+00 5.8210502e+00 5.8345499e+00 + 5.8480501e+00 5.8615499e+00 5.8750501e+00 5.8885498e+00 + 5.9020500e+00 5.9155502e+00 5.9290500e+00 5.9425502e+00 + 5.9560499e+00 5.9695501e+00 5.9830499e+00 5.9965501e+00 + 6.0100498e+00 6.0235500e+00 6.0370498e+00 6.0505500e+00 + 6.0640502e+00 6.0775499e+00 6.0910501e+00 6.1045499e+00 + 6.1180501e+00 6.1315498e+00 6.1450500e+00 6.1585498e+00 + 6.1720500e+00 6.1855502e+00 6.1990499e+00 6.2125502e+00 + 6.2260499e+00 6.2395501e+00 6.2530499e+00 6.2665501e+00 + 6.2800498e+00 6.2935500e+00 6.3070502e+00 6.3205500e+00 + 6.3340502e+00 6.3475499e+00 6.3610501e+00 6.3745499e+00 + 6.3880501e+00 6.4015498e+00 6.4150500e+00 6.4285498e+00 + 6.4420500e+00 6.4555502e+00 6.4690499e+00 6.4825501e+00 + 6.4960499e+00 6.5095501e+00 6.5230498e+00 6.5365500e+00 + 6.5500498e+00 6.5635500e+00 6.5770502e+00 6.5905499e+00 + 6.6040502e+00 6.6175499e+00 6.6310501e+00 6.6445498e+00 + 6.6580501e+00 6.6715498e+00 6.6850500e+00 6.6985502e+00 + 6.7120500e+00 6.7255502e+00 6.7390499e+00 6.7525501e+00 + 6.7660499e+00 6.7795501e+00 6.7930498e+00 6.8065500e+00 + 6.8200498e+00 6.8335500e+00 6.8470502e+00 6.8605499e+00 + 6.8740501e+00 6.8875499e+00 6.9010501e+00 6.9145498e+00 + 6.9280500e+00 6.9415498e+00 6.9550500e+00 6.9685502e+00 + 6.9820499e+00 6.9955502e+00 7.0090499e+00 7.0225501e+00 + 7.0360498e+00 7.0495501e+00 7.0630498e+00 7.0765500e+00 + 7.0900502e+00 7.1035500e+00 7.1170502e+00 7.1305499e+00 + 7.1440501e+00 7.1578269e+00 7.1721697e+00 7.1871009e+00 + 7.2026453e+00 7.2188272e+00 7.2356739e+00 7.2532115e+00 + 7.2714696e+00 7.2904768e+00 7.3102641e+00 7.3308635e+00 + 7.3523088e+00 7.3746343e+00 7.3978763e+00 7.4220719e+00 + 7.4472609e+00 7.4734836e+00 7.5007830e+00 7.5292029e+00 + 7.5587893e+00 7.5895901e+00 7.6233001e+00 7.6592999e+00 + 7.6953001e+00 7.7312999e+00 7.7673001e+00 7.8032999e+00 + 7.8393002e+00 7.8752999e+00 7.9113002e+00 7.9473000e+00 + 7.9833002e+00 8.0193005e+00 8.0552998e+00 8.0913000e+00 + 8.1273003e+00 8.1632996e+00 8.1992998e+00 8.2353001e+00 + 8.2713003e+00 8.3072996e+00 8.3432999e+00 8.3793001e+00 + 8.4153004e+00 8.4512997e+00 8.4872999e+00 8.5233002e+00 + 8.5593004e+00 8.5952997e+00 8.6313000e+00 8.6673002e+00 + 8.7033005e+00 8.7392998e+00 8.7753000e+00 8.8113003e+00 + 8.8472996e+00 8.8832998e+00 8.9193001e+00 8.9553003e+00] + y_upper_bound: [-5.5752001e+00 -5.5391998e+00 -5.5032001e+00 -5.4671998e+00 + -5.4312000e+00 -5.3951998e+00 -5.3592000e+00 -5.3232002e+00 + -5.2872000e+00 -5.2512002e+00 -5.2151999e+00 -5.1792002e+00 + -5.1431999e+00 -5.1072001e+00 -5.0711999e+00 -5.0352001e+00 + -4.9991999e+00 -4.9632001e+00 -4.9271998e+00 -4.8912001e+00 + -4.8551998e+00 -4.8192000e+00 -4.7831998e+00 -4.7472000e+00 + -4.7112002e+00 -4.6752000e+00 -4.6392002e+00 -4.6032000e+00 + -4.5672002e+00 -4.5311999e+00 -4.4952002e+00 -4.4591999e+00 + -4.4232001e+00 -4.3871999e+00 -4.3512001e+00 -4.3151999e+00 + -4.2792001e+00 -4.2431998e+00 -4.2094898e+00 -4.1786890e+00 + -4.1491027e+00 -4.1206832e+00 -4.0933838e+00 -4.0671611e+00 + -4.0419717e+00 -4.0177760e+00 -3.9945343e+00 -3.9722090e+00 + -3.9507637e+00 -3.9301641e+00 -3.9103768e+00 -3.8913693e+00 + -3.8731117e+00 -3.8555737e+00 -3.8387272e+00 -3.8225451e+00 + -3.8070009e+00 -3.7920697e+00 -3.7777271e+00 -3.7639501e+00 + -3.7504499e+00 -3.7369499e+00 -3.7234499e+00 -3.7099500e+00 + -3.6964500e+00 -3.6829500e+00 -3.6694500e+00 -3.6559501e+00 + -3.6424501e+00 -3.6289501e+00 -3.6154499e+00 -3.6019499e+00 + -3.5884500e+00 -3.5749500e+00 -3.5614500e+00 -3.5479500e+00 + -3.5344501e+00 -3.5209501e+00 -3.5074501e+00 -3.4939499e+00 + -3.4804499e+00 -3.4669499e+00 -3.4534500e+00 -3.4399500e+00 + -3.4264500e+00 -3.4129500e+00 -3.3994501e+00 -3.3859501e+00 + -3.3724501e+00 -3.3589499e+00 -3.3454499e+00 -3.3319499e+00 + -3.3184500e+00 -3.3049500e+00 -3.2914500e+00 -3.2779500e+00 + -3.2644501e+00 -3.2509501e+00 -3.2374499e+00 -3.2239499e+00 + -3.2104499e+00 -3.1969500e+00 -3.1834500e+00 -3.1699500e+00 + -3.1564500e+00 -3.1429501e+00 -3.1294501e+00 -3.1159501e+00 + -3.1024499e+00 -3.0889499e+00 -3.0754499e+00 -3.0619500e+00 + -3.0484500e+00 -3.0349500e+00 -3.0214500e+00 -3.0079501e+00 + -2.9944501e+00 -2.9809501e+00 -2.9674499e+00 -2.9539499e+00 + -2.9404500e+00 -2.9269500e+00 -2.9134500e+00 -2.8999500e+00 + -2.8864501e+00 -2.8729501e+00 -2.8594501e+00 -2.8459499e+00 + -2.8324499e+00 -2.8189499e+00 -2.8054500e+00 -2.7919500e+00 + -2.7784500e+00 -2.7649500e+00 -2.7514501e+00 -2.7379501e+00 + -2.7244501e+00 -2.7109499e+00 -2.6974499e+00 -2.6839499e+00 + -2.6704500e+00 -2.6569500e+00 -2.6434500e+00 -2.6299500e+00 + -2.6164501e+00 -2.6029501e+00 -2.5894499e+00 -2.5759499e+00 + -2.5624499e+00 -2.5489500e+00 -2.5354500e+00 -2.5219500e+00 + -2.5084500e+00 -2.4949501e+00 -2.4814501e+00 -2.4679501e+00 + -2.4544499e+00 -2.4409499e+00 -2.4274499e+00 -2.4139500e+00 + -2.4004500e+00 -2.3869500e+00 -2.3734500e+00 -2.3599501e+00 + -2.3464501e+00 -2.3329501e+00 -2.3194499e+00 -2.3059499e+00 + -2.2924500e+00 -2.2789500e+00 -2.2654500e+00 -2.2519500e+00 + -2.2384501e+00 -2.2249501e+00 -2.2114501e+00 -2.1979499e+00 + -2.1844499e+00 -2.1709499e+00 -2.1574500e+00 -2.1439500e+00 + -2.1304500e+00 -2.1169500e+00 -2.1034501e+00 -2.0899501e+00 + -2.0764501e+00 -2.0629499e+00 -2.0494499e+00 -2.0359499e+00 + -2.0224500e+00 -2.0089500e+00 -1.9954500e+00 -1.9819500e+00 + -1.9684500e+00 -1.9549500e+00 -1.9414500e+00 -1.9279500e+00 + -1.9144500e+00 -1.9009500e+00 -1.8874500e+00 -1.8739500e+00 + -1.8604500e+00 -1.8469501e+00 -1.8334500e+00 -1.8199500e+00 + -1.8064500e+00 -1.7929500e+00 -1.7794501e+00 -1.7659500e+00 + -1.7524500e+00 -1.7389500e+00 -1.7254500e+00 -1.7119499e+00 + -1.6984500e+00 -1.6849500e+00 -1.6714500e+00 -1.6579500e+00 + -1.6444499e+00 -1.6309500e+00 -1.6174500e+00 -1.6039500e+00 + -1.5904500e+00 -1.5769500e+00 -1.5634500e+00 -1.5499500e+00 + -1.5364500e+00 -1.5229501e+00 -1.5094500e+00 -1.4959500e+00 + -1.4824500e+00 -1.4689500e+00 -1.4554501e+00 -1.4419500e+00 + -1.4284500e+00 -1.4149500e+00 -1.4014500e+00 -1.3879499e+00 + -1.3744500e+00 -1.3609500e+00 -1.3474500e+00 -1.3339500e+00 + -1.3204499e+00 -1.3069500e+00 -1.2934500e+00 -1.2799500e+00 + -1.2664500e+00 -1.2529500e+00 -1.2394500e+00 -1.2259500e+00 + -1.2124500e+00 -1.1989501e+00 -1.1854500e+00 -1.1719500e+00 + -1.1584500e+00 -1.1449500e+00 -1.1314501e+00 -1.1179500e+00 + -1.1044500e+00 -1.0909500e+00 -1.0774500e+00 -1.0639499e+00 + -1.0504500e+00 -1.0369500e+00 -1.0234500e+00 -1.0099500e+00 + -9.9645001e-01 -9.8294997e-01 -9.6945000e-01 -9.5595002e-01 + -9.4244999e-01 -9.2895001e-01 -9.1544998e-01 -9.0195000e-01 + -8.8845003e-01 -8.7494999e-01 -8.6145002e-01 -8.4794998e-01 + -8.3445001e-01 -8.2094997e-01 -8.0745000e-01 -7.9395002e-01 + -7.8044999e-01 -7.6695001e-01 -7.5344998e-01 -7.3995000e-01 + -7.2645003e-01 -7.1294999e-01 -6.9945002e-01 -6.8594998e-01 + -6.7245001e-01 -6.5894997e-01 -6.4545000e-01 -6.3195002e-01 + -6.1844999e-01 -6.0495001e-01 -5.9144998e-01 -5.7795000e-01 + -5.6445003e-01 -5.5094999e-01 -5.3745002e-01 -5.2394998e-01 + -5.1045001e-01 -4.9695000e-01 -4.8345000e-01 -4.6994999e-01 + -4.5644999e-01 -4.4295001e-01 -4.2945001e-01 -4.1595000e-01 + -4.0245000e-01 -3.8894999e-01 -3.7544999e-01 -3.6195001e-01 + -3.4845001e-01 -3.3495000e-01 -3.2145000e-01 -3.0794999e-01 + -2.9445001e-01 -2.8095001e-01 -2.6745000e-01 -2.5395000e-01 + -2.4044999e-01 -2.2695000e-01 -2.1345000e-01 -1.9994999e-01 + -1.8645000e-01 -1.7295000e-01 -1.5944999e-01 -1.4595000e-01 + -1.3245000e-01 -1.1895000e-01 -1.0545000e-01 -9.1949999e-02 + -7.8450002e-02 -6.4949997e-02 -5.1449999e-02 -3.7950002e-02 + -2.4450000e-02 -1.0950000e-02 2.5500001e-03 1.6050000e-02 + 2.9549999e-02 4.3049999e-02 5.6550000e-02 7.0050001e-02 + 8.3549999e-02 9.7050004e-02 1.1055000e-01 1.2405000e-01 + 1.3755000e-01 1.5105000e-01 1.6455001e-01 1.7805000e-01 + 1.9155000e-01 2.0505001e-01 2.1855000e-01 2.3205000e-01 + 2.4555001e-01 2.5905001e-01 2.7254999e-01 2.8604999e-01 + 2.9955000e-01 3.1305000e-01 3.2655001e-01 3.4005001e-01 + 3.5354999e-01 3.6704999e-01 3.8055000e-01 3.9405000e-01 + 4.0755001e-01 4.2105001e-01 4.3454999e-01 4.4804999e-01 + 4.6155000e-01 4.7505000e-01 4.8855001e-01 5.0204998e-01 + 5.1555002e-01 5.2904999e-01 5.4255003e-01 5.5605000e-01 + 5.6954998e-01 5.8305001e-01 5.9654999e-01 6.1005002e-01 + 6.2355000e-01 6.3704997e-01 6.5055001e-01 6.6404998e-01 + 6.7755002e-01 6.9104999e-01 7.0455003e-01 7.1805000e-01 + 7.3154998e-01 7.4505001e-01 7.5854999e-01 7.7205002e-01 + 7.8555000e-01 7.9904997e-01 8.1255001e-01 8.2604998e-01 + 8.3955002e-01 8.5304999e-01 8.6655003e-01 8.8005000e-01 + 8.9354998e-01 9.0705001e-01 9.2054999e-01 9.3405002e-01 + 9.4755000e-01 9.6104997e-01 9.7455001e-01 9.8804998e-01 + 1.0015500e+00 1.0150501e+00 1.0285500e+00 1.0420500e+00 + 1.0555500e+00 1.0690500e+00 1.0825500e+00 1.0960500e+00 + 1.1095500e+00 1.1230500e+00 1.1365499e+00 1.1500500e+00 + 1.1635500e+00 1.1770500e+00 1.1905500e+00 1.2040499e+00 + 1.2175500e+00 1.2310500e+00 1.2445500e+00 1.2580500e+00 + 1.2715501e+00 1.2850500e+00 1.2985500e+00 1.3120500e+00 + 1.3255500e+00 1.3390501e+00 1.3525500e+00 1.3660500e+00 + 1.3795500e+00 1.3930500e+00 1.4065500e+00 1.4200500e+00 + 1.4335500e+00 1.4470500e+00 1.4605500e+00 1.4740500e+00 + 1.4875500e+00 1.5010500e+00 1.5145500e+00 1.5280499e+00 + 1.5415500e+00 1.5550500e+00 1.5685500e+00 1.5820500e+00 + 1.5955499e+00 1.6090500e+00 1.6225500e+00 1.6360500e+00 + 1.6495500e+00 1.6630501e+00 1.6765500e+00 1.6900500e+00 + 1.7035500e+00 1.7170500e+00 1.7305501e+00 1.7440500e+00 + 1.7575500e+00 1.7710500e+00 1.7845500e+00 1.7980500e+00 + 1.8115500e+00 1.8250500e+00 1.8385500e+00 1.8520499e+00 + 1.8655500e+00 1.8790500e+00 1.8925500e+00 1.9060500e+00 + 1.9195499e+00 1.9330500e+00 1.9465500e+00 1.9600500e+00 + 1.9735500e+00 1.9870501e+00 2.0005500e+00 2.0140500e+00 + 2.0275500e+00 2.0410500e+00 2.0545499e+00 2.0680499e+00 + 2.0815499e+00 2.0950501e+00 2.1085501e+00 2.1220500e+00 + 2.1355500e+00 2.1490500e+00 2.1625500e+00 2.1760499e+00 + 2.1895499e+00 2.2030499e+00 2.2165501e+00 2.2300501e+00 + 2.2435501e+00 2.2570500e+00 2.2705500e+00 2.2840500e+00 + 2.2975500e+00 2.3110499e+00 2.3245499e+00 2.3380499e+00 + 2.3515501e+00 2.3650501e+00 2.3785501e+00 2.3920500e+00 + 2.4055500e+00 2.4190500e+00 2.4325500e+00 2.4460499e+00 + 2.4595499e+00 2.4730501e+00 2.4865501e+00 2.5000501e+00 + 2.5135500e+00 2.5270500e+00 2.5405500e+00 2.5540500e+00 + 2.5675499e+00 2.5810499e+00 2.5945499e+00 2.6080501e+00 + 2.6215501e+00 2.6350501e+00 2.6485500e+00 2.6620500e+00 + 2.6755500e+00 2.6890500e+00 2.7025499e+00 2.7160499e+00 + 2.7295499e+00 2.7430501e+00 2.7565501e+00 2.7700500e+00 + 2.7835500e+00 2.7970500e+00 2.8105500e+00 2.8240499e+00 + 2.8375499e+00 2.8510499e+00 2.8645501e+00 2.8780501e+00 + 2.8915501e+00 2.9050500e+00 2.9185500e+00 2.9320500e+00 + 2.9455500e+00 2.9590499e+00 2.9725499e+00 2.9860499e+00 + 2.9995501e+00 3.0130501e+00 3.0265501e+00 3.0400500e+00 + 3.0535500e+00 3.0670500e+00 3.0805500e+00 3.0940499e+00 + 3.1075499e+00 3.1210499e+00 3.1345501e+00 3.1480501e+00 + 3.1615500e+00 3.1750500e+00 3.1885500e+00 3.2020500e+00 + 3.2155499e+00 3.2290499e+00 3.2425499e+00 3.2560501e+00 + 3.2695501e+00 3.2830501e+00 3.2965500e+00 3.3100500e+00 + 3.3235500e+00 3.3370500e+00 3.3505499e+00 3.3640499e+00 + 3.3775499e+00 3.3910501e+00 3.4045501e+00 3.4180501e+00 + 3.4315500e+00 3.4450500e+00 3.4585500e+00 3.4720500e+00 + 3.4855499e+00 3.4990499e+00 3.5125501e+00 3.5260501e+00 + 3.5395501e+00 3.5530500e+00 3.5665500e+00 3.5800500e+00 + 3.5935500e+00 3.6070499e+00 3.6205499e+00 3.6340499e+00 + 3.6475501e+00 3.6610501e+00 3.6745501e+00 3.6880500e+00 + 3.7015500e+00 3.7150500e+00 3.7285500e+00 3.7420499e+00 + 3.7555499e+00 3.7690499e+00 3.7825501e+00 3.7960501e+00 + 3.8095500e+00 3.8230500e+00 3.8365500e+00 3.8500500e+00 + 3.8635499e+00 3.8770499e+00 3.8905499e+00 3.9040501e+00 + 3.9175501e+00 3.9310501e+00 3.9445500e+00 3.9580500e+00 + 3.9715500e+00 3.9850500e+00 3.9985499e+00 4.0120502e+00 + 4.0255499e+00 4.0390501e+00 4.0525498e+00 4.0660501e+00 + 4.0795498e+00 4.0930500e+00 4.1065502e+00 4.1200500e+00 + 4.1335502e+00 4.1470499e+00 4.1605501e+00 4.1740499e+00 + 4.1875501e+00 4.2010498e+00 4.2145500e+00 4.2280502e+00 + 4.2415500e+00 4.2550502e+00 4.2685499e+00 4.2820501e+00 + 4.2955499e+00 4.3090501e+00 4.3225498e+00 4.3360500e+00 + 4.3495498e+00 4.3630500e+00 4.3765502e+00 4.3900499e+00 + 4.4035501e+00 4.4170499e+00 4.4305501e+00 4.4440498e+00 + 4.4575500e+00 4.4710498e+00 4.4845500e+00 4.4980502e+00 + 4.5115499e+00 4.5250502e+00 4.5385499e+00 4.5520501e+00 + 4.5655499e+00 4.5790501e+00 4.5925498e+00 4.6060500e+00 + 4.6195502e+00 4.6330500e+00 4.6465502e+00 4.6600499e+00 + 4.6735501e+00 4.6870499e+00 4.7005501e+00 4.7140498e+00 + 4.7275500e+00 4.7410498e+00 4.7545500e+00 4.7680502e+00 + 4.7815499e+00 4.7950501e+00 4.8085499e+00 4.8220501e+00 + 4.8355498e+00 4.8490500e+00 4.8625498e+00 4.8760500e+00 + 4.8895502e+00 4.9030499e+00 4.9165502e+00 4.9300499e+00 + 4.9435501e+00 4.9570498e+00 4.9705501e+00 4.9840498e+00 + 4.9975500e+00 5.0110502e+00 5.0245500e+00 5.0380502e+00 + 5.0515499e+00 5.0650501e+00 5.0785499e+00 5.0920501e+00 + 5.1055498e+00 5.1190500e+00 5.1325498e+00 5.1460500e+00 + 5.1595502e+00 5.1730499e+00 5.1865501e+00 5.2000499e+00 + 5.2135501e+00 5.2270498e+00 5.2405500e+00 5.2540498e+00 + 5.2675500e+00 5.2810502e+00 5.2945499e+00 5.3080502e+00 + 5.3215499e+00 5.3350501e+00 5.3485498e+00 5.3620501e+00 + 5.3755498e+00 5.3890500e+00 5.4025502e+00 5.4160500e+00 + 5.4295502e+00 5.4430499e+00 5.4565501e+00 5.4700499e+00 + 5.4835501e+00 5.4970498e+00 5.5105500e+00 5.5240502e+00 + 5.5375500e+00 5.5510502e+00 5.5645499e+00 5.5780501e+00 + 5.5915499e+00 5.6050501e+00 5.6185498e+00 5.6320500e+00 + 5.6455498e+00 5.6590500e+00 5.6725502e+00 5.6860499e+00 + 5.6995502e+00 5.7130499e+00 5.7265501e+00 5.7400498e+00 + 5.7535501e+00 5.7670498e+00 5.7805500e+00 5.7940502e+00 + 5.8075500e+00 5.8210502e+00 5.8345499e+00 5.8480501e+00 + 5.8615499e+00 5.8750501e+00 5.8885498e+00 5.9020500e+00 + 5.9155502e+00 5.9290500e+00 5.9425502e+00 5.9560499e+00 + 5.9695501e+00 5.9830499e+00 5.9965501e+00 6.0100498e+00 + 6.0235500e+00 6.0370498e+00 6.0505500e+00 6.0640502e+00 + 6.0775499e+00 6.0910501e+00 6.1045499e+00 6.1180501e+00 + 6.1315498e+00 6.1450500e+00 6.1585498e+00 6.1720500e+00 + 6.1855502e+00 6.1990499e+00 6.2125502e+00 6.2260499e+00 + 6.2395501e+00 6.2530499e+00 6.2665501e+00 6.2800498e+00 + 6.2935500e+00 6.3070502e+00 6.3205500e+00 6.3340502e+00 + 6.3475499e+00 6.3610501e+00 6.3745499e+00 6.3880501e+00 + 6.4015498e+00 6.4150500e+00 6.4285498e+00 6.4420500e+00 + 6.4555502e+00 6.4690499e+00 6.4825501e+00 6.4960499e+00 + 6.5095501e+00 6.5230498e+00 6.5365500e+00 6.5500498e+00 + 6.5635500e+00 6.5770502e+00 6.5905499e+00 6.6040502e+00 + 6.6175499e+00 6.6310501e+00 6.6445498e+00 6.6580501e+00 + 6.6715498e+00 6.6850500e+00 6.6985502e+00 6.7120500e+00 + 6.7255502e+00 6.7390499e+00 6.7525501e+00 6.7660499e+00 + 6.7795501e+00 6.7930498e+00 6.8065500e+00 6.8200498e+00 + 6.8335500e+00 6.8470502e+00 6.8605499e+00 6.8740501e+00 + 6.8875499e+00 6.9010501e+00 6.9145498e+00 6.9280500e+00 + 6.9415498e+00 6.9550500e+00 6.9685502e+00 6.9820499e+00 + 6.9955502e+00 7.0090499e+00 7.0225501e+00 7.0360498e+00 + 7.0495501e+00 7.0630498e+00 7.0765500e+00 7.0900502e+00 + 7.1035500e+00 7.1170502e+00 7.1305499e+00 7.1440501e+00 + 7.1578269e+00 7.1721697e+00 7.1871009e+00 7.2026453e+00 + 7.2188272e+00 7.2356739e+00 7.2532115e+00 7.2714696e+00 + 7.2904768e+00 7.3102641e+00 7.3308635e+00 7.3523088e+00 + 7.3746343e+00 7.3978763e+00 7.4220719e+00 7.4472609e+00 + 7.4734836e+00 7.5007830e+00 7.5292029e+00 7.5587893e+00 + 7.5895901e+00 7.6233001e+00 7.6592999e+00 7.6953001e+00 + 7.7312999e+00 7.7673001e+00 7.8032999e+00 7.8393002e+00 + 7.8752999e+00 7.9113002e+00 7.9473000e+00 7.9833002e+00 + 8.0193005e+00 8.0552998e+00 8.0913000e+00 8.1273003e+00 + 8.1632996e+00 8.1992998e+00 8.2353001e+00 8.2713003e+00 + 8.3072996e+00 8.3432999e+00 8.3793001e+00 8.4153004e+00 + 8.4512997e+00 8.4872999e+00 8.5233002e+00 8.5593004e+00 + 8.5952997e+00 8.6313000e+00 8.6673002e+00 8.7033005e+00 + 8.7392998e+00 8.7753000e+00 8.8113003e+00 8.8472996e+00 + 8.8832998e+00 8.9193001e+00 8.9553003e+00 8.9912996e+00] , PP Field lbyr: 2010 lbmon: 2 @@ -4861,1156 +4357,1030 @@ bdy: 0.0 bzx: 0.0 bdx: 0.0 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 100008. 100008. 100007. ..., 100871. 100875. 100876.] - [ 100007. 100007. 100006. ..., 100874. 100877. 100878.] - [ 100008. 100007. 100007. ..., 100876. 100880. 100880.] - ..., - [ 102193. 102201. 102208. ..., 101695. 101671. 101671.] - [ 102199. 102206. 102213. ..., 101706. 101689. 101686.] - [ 102204. 102211. 102218. ..., 101727. 101707. 101701.]] - x: [ 353.05249023 353.08850098 353.12451172 353.16049194 353.19650269 - 353.23251343 353.26849365 353.30450439 353.34051514 353.37649536 - 353.4125061 353.44848633 353.48449707 353.52050781 353.55648804 - 353.59249878 353.62850952 353.66448975 353.70050049 353.73651123 - 353.77249146 353.8085022 353.84451294 353.88049316 353.91650391 - 353.95251465 353.98849487 354.02450562 354.06048584 354.09649658 - 354.13250732 354.16848755 354.20449829 354.24050903 354.27648926 - 354.3125 354.34851074 354.38449097 354.42050171 354.45651245 - 354.49249268 354.52185059 354.55010986 354.57736206 354.6036377 - 354.62893677 354.65332031 354.67684937 354.69949341 354.72131348 - 354.74234009 354.76263428 354.78216553 354.80099487 354.81915283 - 354.8366394 354.85348511 354.86972046 354.88537598 354.90045166 - 354.91497803 354.9289856 354.94250488 354.95599365 354.96951294 - 354.98300171 354.99649048 355.01000977 355.02349854 355.0369873 - 355.05050659 355.06399536 355.07751465 355.09100342 355.10449219 - 355.11801147 355.13150024 355.14498901 355.1585083 355.17199707 - 355.18548584 355.19900513 355.2124939 355.22601318 355.23950195 - 355.25299072 355.26651001 355.27999878 355.29348755 355.30700684 - 355.32049561 355.33401489 355.34750366 355.36099243 355.37451172 - 355.38800049 355.40148926 355.41500854 355.42849731 355.44198608 - 355.45550537 355.46899414 355.48251343 355.4960022 355.50949097 - 355.52301025 355.53649902 355.54998779 355.56350708 355.57699585 - 355.59051514 355.60400391 355.61749268 355.63101196 355.64450073 - 355.6579895 355.67150879 355.68499756 355.69848633 355.71200562 - 355.72549438 355.73901367 355.75250244 355.76599121 355.7795105 - 355.79299927 355.80648804 355.82000732 355.83349609 355.84698486 - 355.86050415 355.87399292 355.88751221 355.90100098 355.91448975 - 355.92800903 355.9414978 355.95498657 355.96850586 355.98199463 - 355.99551392 356.00900269 356.02249146 356.03601074 356.04949951 - 356.06298828 356.07650757 356.08999634 356.10348511 356.11700439 - 356.13049316 356.14401245 356.15750122 356.17098999 356.18450928 - 356.19799805 356.21148682 356.2250061 356.23849487 356.25201416 - 356.26550293 356.2789917 356.29251099 356.30599976 356.31948853 - 356.33300781 356.34649658 356.35998535 356.37350464 356.38699341 - 356.4005127 356.41400146 356.42749023 356.44100952 356.45449829 - 356.46798706 356.48150635 356.49499512 356.5085144 356.52200317 - 356.53549194 356.54901123 356.5625 356.57598877 356.58950806 - 356.60299683 356.6164856 356.63000488 356.64349365 356.65701294 - 356.67050171 356.68399048 356.69750977 356.71099854 356.7244873 - 356.73800659 356.75149536 356.76501465 356.77850342 356.79199219 - 356.80551147 356.81900024 356.83248901 356.8460083 356.85949707 - 356.87298584 356.88650513 356.8999939 356.91351318 356.92700195 - 356.94049072 356.95401001 356.96749878 356.98098755 356.99450684 - 357.00799561 357.02151489 357.03500366 357.04849243 357.06201172 - 357.07550049 357.08898926 357.10250854 357.11599731 357.12948608 - 357.14300537 357.15649414 357.17001343 357.1835022 357.19699097 - 357.21051025 357.22399902 357.23748779 357.25100708 357.26449585 - 357.27801514 357.29150391 357.30499268 357.31851196 357.33200073 - 357.3454895 357.35900879 357.37249756 357.38598633 357.39950562 - 357.41299438 357.42651367 357.44000244 357.45349121 357.4670105 - 357.48049927 357.49398804 357.50750732 357.52099609 357.53448486 - 357.54800415 357.56149292 357.57501221 357.58850098 357.60198975 - 357.61550903 357.6289978 357.64248657 357.65600586 357.66949463 - 357.68301392 357.69650269 357.70999146 357.72351074 357.73699951 - 357.75048828 357.76400757 357.77749634 357.79098511 357.80450439 - 357.81799316 357.83151245 357.84500122 357.85848999 357.87200928 - 357.88549805 357.89898682 357.9125061 357.92599487 357.93951416 - 357.95300293 357.9664917 357.98001099 357.99349976 358.00698853 - 358.02050781 358.03399658 358.04748535 358.06100464 358.07449341 - 358.0880127 358.10150146 358.11499023 358.12850952 358.14199829 - 358.15548706 358.16900635 358.18249512 358.1960144 358.20950317 - 358.22299194 358.23651123 358.25 358.26348877 358.27700806 - 358.29049683 358.3039856 358.31750488 358.33099365 358.34451294 - 358.35800171 358.37149048 358.38500977 358.39849854 358.4119873 - 358.42550659 358.43899536 358.45251465 358.46600342 358.47949219 - 358.49301147 358.50650024 358.51998901 358.5335083 358.54699707 - 358.56048584 358.57400513 358.5874939 358.60101318 358.61450195 - 358.62799072 358.64151001 358.65499878 358.66848755 358.68200684 - 358.69549561 358.70901489 358.72250366 358.73599243 358.74951172 - 358.76300049 358.77648926 358.79000854 358.80349731 358.81698608 - 358.83050537 358.84399414 358.85751343 358.8710022 358.88449097 - 358.89801025 358.91149902 358.92498779 358.93850708 358.95199585 - 358.96551514 358.97900391 358.99249268 359.00601196 359.01950073 - 359.0329895 359.04650879 359.05999756 359.07348633 359.08700562 - 359.10049438 359.11401367 359.12750244 359.14099121 359.1545105 - 359.16799927 359.18148804 359.19500732 359.20849609 359.22198486 - 359.23550415 359.24899292 359.26251221 359.27600098 359.28948975 - 359.30300903 359.3164978 359.32998657 359.34350586 359.35699463 - 359.37051392 359.38400269 359.39749146 359.41101074 359.42449951 - 359.43798828 359.45150757 359.46499634 359.47848511 359.49200439 - 359.50549316 359.51901245 359.53250122 359.54598999 359.55950928 - 359.57299805 359.58648682 359.6000061 359.61349487 359.62701416 - 359.64050293 359.6539917 359.66751099 359.68099976 359.69448853 - 359.70800781 359.72149658 359.73498535 359.74850464 359.76199341 - 359.7755127 359.78900146 359.80249023 359.81600952 359.82949829 - 359.84298706 359.85650635 359.86999512 359.8835144 359.89700317 - 359.91049194 359.92401123 359.9375 359.95098877 359.96450806 - 359.97799683 359.9914856 360.00500488 360.01849365 360.03201294 - 360.04550171 360.05899048 360.07250977 360.08599854 360.0994873 - 360.11300659 360.12649536 360.14001465 360.15350342 360.16699219 - 360.18051147 360.19400024 360.20748901 360.2210083 360.23449707 - 360.24798584 360.26150513 360.2749939 360.28851318 360.30200195 - 360.31549072 360.32901001 360.34249878 360.35598755 360.36950684 - 360.38299561 360.39651489 360.41000366 360.42349243 360.43701172 - 360.45050049 360.46398926 360.47750854 360.49099731 360.50448608 - 360.51800537 360.53149414 360.54501343 360.5585022 360.57199097 - 360.58551025 360.59899902 360.61248779 360.62600708 360.63949585 - 360.65301514 360.66650391 360.67999268 360.69351196 360.70700073 - 360.7204895 360.73400879 360.74749756 360.76098633 360.77450562 - 360.78799438 360.80151367 360.81500244 360.82849121 360.8420105 - 360.85549927 360.86898804 360.88250732 360.89599609 360.90948486 - 360.92300415 360.93649292 360.95001221 360.96350098 360.97698975 - 360.99050903 361.0039978 361.01748657 361.03100586 361.04449463 - 361.05801392 361.07150269 361.08499146 361.09851074 361.11199951 - 361.12548828 361.13900757 361.15249634 361.16598511 361.17950439 - 361.19299316 361.20651245 361.22000122 361.23348999 361.24700928 - 361.26049805 361.27398682 361.2875061 361.30099487 361.31451416 - 361.32800293 361.3414917 361.35501099 361.36849976 361.38198853 - 361.39550781 361.40899658 361.42248535 361.43600464 361.44949341 - 361.4630127 361.47650146 361.48999023 361.50350952 361.51699829 - 361.53048706 361.54400635 361.55749512 361.5710144 361.58450317 - 361.59799194 361.61151123 361.625 361.63848877 361.65200806 - 361.66549683 361.6789856 361.69250488 361.70599365 361.71951294 - 361.73300171 361.74649048 361.76000977 361.77349854 361.7869873 - 361.80050659 361.81399536 361.82751465 361.84100342 361.85449219 - 361.86801147 361.88150024 361.89498901 361.9085083 361.92199707 - 361.93548584 361.94900513 361.9624939 361.97601318 361.98950195 - 362.00299072 362.01651001 362.02999878 362.04348755 362.05700684 - 362.07049561 362.08401489 362.09750366 362.11099243 362.12451172 - 362.13800049 362.15148926 362.16500854 362.17849731 362.19198608 - 362.20550537 362.21899414 362.23251343 362.2460022 362.25949097 - 362.27301025 362.28649902 362.29998779 362.31350708 362.32699585 - 362.34051514 362.35400391 362.36749268 362.38101196 362.39450073 - 362.4079895 362.42150879 362.43499756 362.44848633 362.46200562 - 362.47549438 362.48901367 362.50250244 362.51599121 362.5295105 - 362.54299927 362.55648804 362.57000732 362.58349609 362.59698486 - 362.61050415 362.62399292 362.63751221 362.65100098 362.66448975 - 362.67800903 362.6914978 362.70498657 362.71850586 362.73199463 - 362.74551392 362.75900269 362.77249146 362.78601074 362.79949951 - 362.81298828 362.82650757 362.83999634 362.85348511 362.86700439 - 362.88049316 362.89401245 362.90750122 362.92098999 362.93450928 - 362.94799805 362.96148682 362.9750061 362.98849487 363.00201416 - 363.01550293 363.0289917 363.04251099 363.05599976 363.06948853 - 363.08300781 363.09649658 363.10998535 363.12350464 363.13699341 - 363.1505127 363.16400146 363.17749023 363.19100952 363.20449829 - 363.21798706 363.23150635 363.24499512 363.2585144 363.27200317 - 363.28549194 363.29901123 363.3125 363.32650757 363.34103394 - 363.35614014 363.37176514 363.38803101 363.40487671 363.42236328 - 363.44049072 363.45932007 363.47888184 363.49914551 363.52017212 - 363.54202271 363.56466675 363.58816528 363.61254883 363.63787842 - 363.66412354 363.69137573 363.71966553 363.74899292 363.78500366 - 363.8210144 363.85699463 363.89300537 363.9289856 363.96499634 - 364.00100708 364.0369873 364.07299805 364.10900879 364.14498901 - 364.18099976 364.2170105 364.25299072 364.28900146 364.32501221 - 364.36099243 364.39700317 364.43301392 364.46899414 364.50500488 - 364.54098511 364.57699585 364.61300659 364.64898682 364.68499756 - 364.7210083 364.75698853 364.79299927 364.82901001 364.86499023 - 364.90100098 364.93701172 364.97299194 365.00900269 365.04501343 - 365.08099365 365.11700439 365.15301514 365.18899536] - x_lower_bound: [ 353.03448486 353.07049561 353.10650635 353.14248657 353.17849731 - 353.21450806 353.25048828 353.28649902 353.32250977 353.35848999 - 353.39450073 353.43051147 353.4664917 353.50250244 353.53851318 - 353.57449341 353.61050415 353.64651489 353.68249512 353.71850586 - 353.75448608 353.79049683 353.82650757 353.86248779 353.89849854 - 353.93450928 353.9704895 354.00650024 354.04251099 354.07849121 - 354.11450195 354.1505127 354.18649292 354.22250366 354.2585144 - 354.29449463 354.33050537 354.3664856 354.40249634 354.43850708 - 354.4744873 354.50717163 354.53598022 354.56375122 354.59051514 - 354.61627197 354.6411438 354.66506958 354.68817139 354.71038818 - 354.73184204 354.75250244 354.7723999 354.79159546 354.81005859 - 354.82788086 354.84506226 354.86160278 354.87753296 354.89291382 - 354.90771484 354.92199707 354.9357605 354.94924927 354.96273804 - 354.97625732 354.98974609 355.00323486 355.01675415 355.03024292 - 355.04376221 355.05725098 355.07073975 355.08425903 355.0977478 - 355.11123657 355.12475586 355.13824463 355.15176392 355.16525269 - 355.17874146 355.19226074 355.20574951 355.21923828 355.23275757 - 355.24624634 355.25973511 355.27325439 355.28674316 355.30026245 - 355.31375122 355.32723999 355.34075928 355.35424805 355.36773682 - 355.3812561 355.39474487 355.40826416 355.42175293 355.4352417 - 355.44876099 355.46224976 355.47573853 355.48925781 355.50274658 - 355.51623535 355.52975464 355.54324341 355.5567627 355.57025146 - 355.58374023 355.59725952 355.61074829 355.62423706 355.63775635 - 355.65124512 355.6647644 355.67825317 355.69174194 355.70526123 - 355.71875 355.73223877 355.74575806 355.75924683 355.7727356 - 355.78625488 355.79974365 355.81326294 355.82675171 355.84024048 - 355.85375977 355.86724854 355.8807373 355.89425659 355.90774536 - 355.92126465 355.93475342 355.94824219 355.96176147 355.97525024 - 355.98873901 356.0022583 356.01574707 356.02923584 356.04275513 - 356.0562439 356.06976318 356.08325195 356.09674072 356.11026001 - 356.12374878 356.13723755 356.15075684 356.16424561 356.17776489 - 356.19125366 356.20474243 356.21826172 356.23175049 356.24523926 - 356.25875854 356.27224731 356.28573608 356.29925537 356.31274414 - 356.32626343 356.3397522 356.35324097 356.36676025 356.38024902 - 356.39373779 356.40725708 356.42074585 356.43426514 356.44775391 - 356.46124268 356.47476196 356.48825073 356.5017395 356.51525879 - 356.52874756 356.54223633 356.55575562 356.56924438 356.58276367 - 356.59625244 356.60974121 356.6232605 356.63674927 356.65023804 - 356.66375732 356.67724609 356.69073486 356.70425415 356.71774292 - 356.73126221 356.74475098 356.75823975 356.77175903 356.7852478 - 356.79873657 356.81225586 356.82574463 356.83926392 356.85275269 - 356.86624146 356.87976074 356.89324951 356.90673828 356.92025757 - 356.93374634 356.94723511 356.96075439 356.97424316 356.98776245 - 357.00125122 357.01473999 357.02825928 357.04174805 357.05523682 - 357.0687561 357.08224487 357.09576416 357.10925293 357.1227417 - 357.13626099 357.14974976 357.16323853 357.17675781 357.19024658 - 357.20373535 357.21725464 357.23074341 357.2442627 357.25775146 - 357.27124023 357.28475952 357.29824829 357.31173706 357.32525635 - 357.33874512 357.3522644 357.36575317 357.37924194 357.39276123 - 357.40625 357.41973877 357.43325806 357.44674683 357.4602356 - 357.47375488 357.48724365 357.50076294 357.51425171 357.52774048 - 357.54125977 357.55474854 357.5682373 357.58175659 357.59524536 - 357.60876465 357.62225342 357.63574219 357.64926147 357.66275024 - 357.67623901 357.6897583 357.70324707 357.71673584 357.73025513 - 357.7437439 357.75726318 357.77075195 357.78424072 357.79776001 - 357.81124878 357.82473755 357.83825684 357.85174561 357.86526489 - 357.87875366 357.89224243 357.90576172 357.91925049 357.93273926 - 357.94625854 357.95974731 357.97323608 357.98675537 358.00024414 - 358.01376343 358.0272522 358.04074097 358.05426025 358.06774902 - 358.08123779 358.09475708 358.10824585 358.12176514 358.13525391 - 358.14874268 358.16226196 358.17575073 358.1892395 358.20275879 - 358.21624756 358.22973633 358.24325562 358.25674438 358.27026367 - 358.28375244 358.29724121 358.3107605 358.32424927 358.33773804 - 358.35125732 358.36474609 358.37823486 358.39175415 358.40524292 - 358.41876221 358.43225098 358.44573975 358.45925903 358.4727478 - 358.48623657 358.49975586 358.51324463 358.52676392 358.54025269 - 358.55374146 358.56726074 358.58074951 358.59423828 358.60775757 - 358.62124634 358.63473511 358.64825439 358.66174316 358.67526245 - 358.68875122 358.70223999 358.71575928 358.72924805 358.74273682 - 358.7562561 358.76974487 358.78326416 358.79675293 358.8102417 - 358.82376099 358.83724976 358.85073853 358.86425781 358.87774658 - 358.89123535 358.90475464 358.91824341 358.9317627 358.94525146 - 358.95874023 358.97225952 358.98574829 358.99923706 359.01275635 - 359.02624512 359.0397644 359.05325317 359.06674194 359.08026123 - 359.09375 359.10723877 359.12075806 359.13424683 359.1477356 - 359.16125488 359.17474365 359.18826294 359.20175171 359.21524048 - 359.22875977 359.24224854 359.2557373 359.26925659 359.28274536 - 359.29626465 359.30975342 359.32324219 359.33676147 359.35025024 - 359.36373901 359.3772583 359.39074707 359.40423584 359.41775513 - 359.4312439 359.44476318 359.45825195 359.47174072 359.48526001 - 359.49874878 359.51223755 359.52575684 359.53924561 359.55276489 - 359.56625366 359.57974243 359.59326172 359.60675049 359.62023926 - 359.63375854 359.64724731 359.66073608 359.67425537 359.68774414 - 359.70126343 359.7147522 359.72824097 359.74176025 359.75524902 - 359.76873779 359.78225708 359.79574585 359.80926514 359.82275391 - 359.83624268 359.84976196 359.86325073 359.8767395 359.89025879 - 359.90374756 359.91723633 359.93075562 359.94424438 359.95776367 - 359.97125244 359.98474121 359.9982605 360.01174927 360.02523804 - 360.03875732 360.05224609 360.06573486 360.07925415 360.09274292 - 360.10626221 360.11975098 360.13323975 360.14675903 360.1602478 - 360.17373657 360.18725586 360.20074463 360.21426392 360.22775269 - 360.24124146 360.25476074 360.26824951 360.28173828 360.29525757 - 360.30874634 360.32223511 360.33575439 360.34924316 360.36276245 - 360.37625122 360.38973999 360.40325928 360.41674805 360.43023682 - 360.4437561 360.45724487 360.47076416 360.48425293 360.4977417 - 360.51126099 360.52474976 360.53823853 360.55175781 360.56524658 - 360.57873535 360.59225464 360.60574341 360.6192627 360.63275146 - 360.64624023 360.65975952 360.67324829 360.68673706 360.70025635 - 360.71374512 360.7272644 360.74075317 360.75424194 360.76776123 - 360.78125 360.79473877 360.80825806 360.82174683 360.8352356 - 360.84875488 360.86224365 360.87576294 360.88925171 360.90274048 - 360.91625977 360.92974854 360.9432373 360.95675659 360.97024536 - 360.98376465 360.99725342 361.01074219 361.02426147 361.03775024 - 361.05123901 361.0647583 361.07824707 361.09173584 361.10525513 - 361.1187439 361.13226318 361.14575195 361.15924072 361.17276001 - 361.18624878 361.19973755 361.21325684 361.22674561 361.24026489 - 361.25375366 361.26724243 361.28076172 361.29425049 361.30773926 - 361.32125854 361.33474731 361.34823608 361.36175537 361.37524414 - 361.38876343 361.4022522 361.41574097 361.42926025 361.44274902 - 361.45623779 361.46975708 361.48324585 361.49676514 361.51025391 - 361.52374268 361.53726196 361.55075073 361.5642395 361.57775879 - 361.59124756 361.60473633 361.61825562 361.63174438 361.64526367 - 361.65875244 361.67224121 361.6857605 361.69924927 361.71273804 - 361.72625732 361.73974609 361.75323486 361.76675415 361.78024292 - 361.79376221 361.80725098 361.82073975 361.83425903 361.8477478 - 361.86123657 361.87475586 361.88824463 361.90176392 361.91525269 - 361.92874146 361.94226074 361.95574951 361.96923828 361.98275757 - 361.99624634 362.00973511 362.02325439 362.03674316 362.05026245 - 362.06375122 362.07723999 362.09075928 362.10424805 362.11773682 - 362.1312561 362.14474487 362.15826416 362.17175293 362.1852417 - 362.19876099 362.21224976 362.22573853 362.23925781 362.25274658 - 362.26623535 362.27975464 362.29324341 362.3067627 362.32025146 - 362.33374023 362.34725952 362.36074829 362.37423706 362.38775635 - 362.40124512 362.4147644 362.42825317 362.44174194 362.45526123 - 362.46875 362.48223877 362.49575806 362.50924683 362.5227356 - 362.53625488 362.54974365 362.56326294 362.57675171 362.59024048 - 362.60375977 362.61724854 362.6307373 362.64425659 362.65774536 - 362.67126465 362.68475342 362.69824219 362.71176147 362.72525024 - 362.73873901 362.7522583 362.76574707 362.77923584 362.79275513 - 362.8062439 362.81976318 362.83325195 362.84674072 362.86026001 - 362.87374878 362.88723755 362.90075684 362.91424561 362.92776489 - 362.94125366 362.95474243 362.96826172 362.98175049 362.99523926 - 363.00875854 363.02224731 363.03573608 363.04925537 363.06274414 - 363.07626343 363.0897522 363.10324097 363.11676025 363.13024902 - 363.14373779 363.15725708 363.17074585 363.18426514 363.19775391 - 363.21124268 363.22476196 363.23825073 363.2517395 363.26525879 - 363.27874756 363.29223633 363.30575562 363.31951904 363.33377075 - 363.34857178 363.36395264 363.37991333 363.39645386 363.41360474 - 363.431427 363.44992065 363.46911621 363.48901367 363.50967407 - 363.53109741 363.55334473 363.57641602 363.60037231 363.62521362 - 363.65100098 363.67776489 363.70550537 363.73431396 363.76699829 - 363.80300903 363.83898926 363.875 363.91101074 363.94699097 - 363.98300171 364.01901245 364.05499268 364.09100342 364.12701416 - 364.16299438 364.19900513 364.23498535 364.27099609 364.30700684 - 364.34298706 364.3789978 364.41500854 364.45098877 364.48699951 - 364.52301025 364.55899048 364.59500122 364.63101196 364.66699219 - 364.70300293 364.73901367 364.7749939 364.81100464 364.84698486 - 364.88299561 364.91900635 364.95498657 364.99099731 365.02700806 - 365.06298828 365.09899902 365.13500977 365.17098999] - x_upper_bound: [ 353.07049561 353.10650635 353.14248657 353.17849731 353.21450806 - 353.25048828 353.28649902 353.32250977 353.35848999 353.39450073 - 353.43051147 353.4664917 353.50250244 353.53851318 353.57449341 - 353.61050415 353.64651489 353.68249512 353.71850586 353.75448608 - 353.79049683 353.82650757 353.86248779 353.89849854 353.93450928 - 353.9704895 354.00650024 354.04251099 354.07849121 354.11450195 - 354.1505127 354.18649292 354.22250366 354.2585144 354.29449463 - 354.33050537 354.3664856 354.40249634 354.43850708 354.4744873 - 354.50717163 354.53598022 354.56375122 354.59051514 354.61627197 - 354.6411438 354.66506958 354.68817139 354.71038818 354.73184204 - 354.75250244 354.7723999 354.79159546 354.81005859 354.82788086 - 354.84506226 354.86160278 354.87753296 354.89291382 354.90771484 - 354.92199707 354.9357605 354.94924927 354.96273804 354.97625732 - 354.98974609 355.00323486 355.01675415 355.03024292 355.04376221 - 355.05725098 355.07073975 355.08425903 355.0977478 355.11123657 - 355.12475586 355.13824463 355.15176392 355.16525269 355.17874146 - 355.19226074 355.20574951 355.21923828 355.23275757 355.24624634 - 355.25973511 355.27325439 355.28674316 355.30026245 355.31375122 - 355.32723999 355.34075928 355.35424805 355.36773682 355.3812561 - 355.39474487 355.40826416 355.42175293 355.4352417 355.44876099 - 355.46224976 355.47573853 355.48925781 355.50274658 355.51623535 - 355.52975464 355.54324341 355.5567627 355.57025146 355.58374023 - 355.59725952 355.61074829 355.62423706 355.63775635 355.65124512 - 355.6647644 355.67825317 355.69174194 355.70526123 355.71875 - 355.73223877 355.74575806 355.75924683 355.7727356 355.78625488 - 355.79974365 355.81326294 355.82675171 355.84024048 355.85375977 - 355.86724854 355.8807373 355.89425659 355.90774536 355.92126465 - 355.93475342 355.94824219 355.96176147 355.97525024 355.98873901 - 356.0022583 356.01574707 356.02923584 356.04275513 356.0562439 - 356.06976318 356.08325195 356.09674072 356.11026001 356.12374878 - 356.13723755 356.15075684 356.16424561 356.17776489 356.19125366 - 356.20474243 356.21826172 356.23175049 356.24523926 356.25875854 - 356.27224731 356.28573608 356.29925537 356.31274414 356.32626343 - 356.3397522 356.35324097 356.36676025 356.38024902 356.39373779 - 356.40725708 356.42074585 356.43426514 356.44775391 356.46124268 - 356.47476196 356.48825073 356.5017395 356.51525879 356.52874756 - 356.54223633 356.55575562 356.56924438 356.58276367 356.59625244 - 356.60974121 356.6232605 356.63674927 356.65023804 356.66375732 - 356.67724609 356.69073486 356.70425415 356.71774292 356.73126221 - 356.74475098 356.75823975 356.77175903 356.7852478 356.79873657 - 356.81225586 356.82574463 356.83926392 356.85275269 356.86624146 - 356.87976074 356.89324951 356.90673828 356.92025757 356.93374634 - 356.94723511 356.96075439 356.97424316 356.98776245 357.00125122 - 357.01473999 357.02825928 357.04174805 357.05523682 357.0687561 - 357.08224487 357.09576416 357.10925293 357.1227417 357.13626099 - 357.14974976 357.16323853 357.17675781 357.19024658 357.20373535 - 357.21725464 357.23074341 357.2442627 357.25775146 357.27124023 - 357.28475952 357.29824829 357.31173706 357.32525635 357.33874512 - 357.3522644 357.36575317 357.37924194 357.39276123 357.40625 - 357.41973877 357.43325806 357.44674683 357.4602356 357.47375488 - 357.48724365 357.50076294 357.51425171 357.52774048 357.54125977 - 357.55474854 357.5682373 357.58175659 357.59524536 357.60876465 - 357.62225342 357.63574219 357.64926147 357.66275024 357.67623901 - 357.6897583 357.70324707 357.71673584 357.73025513 357.7437439 - 357.75726318 357.77075195 357.78424072 357.79776001 357.81124878 - 357.82473755 357.83825684 357.85174561 357.86526489 357.87875366 - 357.89224243 357.90576172 357.91925049 357.93273926 357.94625854 - 357.95974731 357.97323608 357.98675537 358.00024414 358.01376343 - 358.0272522 358.04074097 358.05426025 358.06774902 358.08123779 - 358.09475708 358.10824585 358.12176514 358.13525391 358.14874268 - 358.16226196 358.17575073 358.1892395 358.20275879 358.21624756 - 358.22973633 358.24325562 358.25674438 358.27026367 358.28375244 - 358.29724121 358.3107605 358.32424927 358.33773804 358.35125732 - 358.36474609 358.37823486 358.39175415 358.40524292 358.41876221 - 358.43225098 358.44573975 358.45925903 358.4727478 358.48623657 - 358.49975586 358.51324463 358.52676392 358.54025269 358.55374146 - 358.56726074 358.58074951 358.59423828 358.60775757 358.62124634 - 358.63473511 358.64825439 358.66174316 358.67526245 358.68875122 - 358.70223999 358.71575928 358.72924805 358.74273682 358.7562561 - 358.76974487 358.78326416 358.79675293 358.8102417 358.82376099 - 358.83724976 358.85073853 358.86425781 358.87774658 358.89123535 - 358.90475464 358.91824341 358.9317627 358.94525146 358.95874023 - 358.97225952 358.98574829 358.99923706 359.01275635 359.02624512 - 359.0397644 359.05325317 359.06674194 359.08026123 359.09375 - 359.10723877 359.12075806 359.13424683 359.1477356 359.16125488 - 359.17474365 359.18826294 359.20175171 359.21524048 359.22875977 - 359.24224854 359.2557373 359.26925659 359.28274536 359.29626465 - 359.30975342 359.32324219 359.33676147 359.35025024 359.36373901 - 359.3772583 359.39074707 359.40423584 359.41775513 359.4312439 - 359.44476318 359.45825195 359.47174072 359.48526001 359.49874878 - 359.51223755 359.52575684 359.53924561 359.55276489 359.56625366 - 359.57974243 359.59326172 359.60675049 359.62023926 359.63375854 - 359.64724731 359.66073608 359.67425537 359.68774414 359.70126343 - 359.7147522 359.72824097 359.74176025 359.75524902 359.76873779 - 359.78225708 359.79574585 359.80926514 359.82275391 359.83624268 - 359.84976196 359.86325073 359.8767395 359.89025879 359.90374756 - 359.91723633 359.93075562 359.94424438 359.95776367 359.97125244 - 359.98474121 359.9982605 360.01174927 360.02523804 360.03875732 - 360.05224609 360.06573486 360.07925415 360.09274292 360.10626221 - 360.11975098 360.13323975 360.14675903 360.1602478 360.17373657 - 360.18725586 360.20074463 360.21426392 360.22775269 360.24124146 - 360.25476074 360.26824951 360.28173828 360.29525757 360.30874634 - 360.32223511 360.33575439 360.34924316 360.36276245 360.37625122 - 360.38973999 360.40325928 360.41674805 360.43023682 360.4437561 - 360.45724487 360.47076416 360.48425293 360.4977417 360.51126099 - 360.52474976 360.53823853 360.55175781 360.56524658 360.57873535 - 360.59225464 360.60574341 360.6192627 360.63275146 360.64624023 - 360.65975952 360.67324829 360.68673706 360.70025635 360.71374512 - 360.7272644 360.74075317 360.75424194 360.76776123 360.78125 - 360.79473877 360.80825806 360.82174683 360.8352356 360.84875488 - 360.86224365 360.87576294 360.88925171 360.90274048 360.91625977 - 360.92974854 360.9432373 360.95675659 360.97024536 360.98376465 - 360.99725342 361.01074219 361.02426147 361.03775024 361.05123901 - 361.0647583 361.07824707 361.09173584 361.10525513 361.1187439 - 361.13226318 361.14575195 361.15924072 361.17276001 361.18624878 - 361.19973755 361.21325684 361.22674561 361.24026489 361.25375366 - 361.26724243 361.28076172 361.29425049 361.30773926 361.32125854 - 361.33474731 361.34823608 361.36175537 361.37524414 361.38876343 - 361.4022522 361.41574097 361.42926025 361.44274902 361.45623779 - 361.46975708 361.48324585 361.49676514 361.51025391 361.52374268 - 361.53726196 361.55075073 361.5642395 361.57775879 361.59124756 - 361.60473633 361.61825562 361.63174438 361.64526367 361.65875244 - 361.67224121 361.6857605 361.69924927 361.71273804 361.72625732 - 361.73974609 361.75323486 361.76675415 361.78024292 361.79376221 - 361.80725098 361.82073975 361.83425903 361.8477478 361.86123657 - 361.87475586 361.88824463 361.90176392 361.91525269 361.92874146 - 361.94226074 361.95574951 361.96923828 361.98275757 361.99624634 - 362.00973511 362.02325439 362.03674316 362.05026245 362.06375122 - 362.07723999 362.09075928 362.10424805 362.11773682 362.1312561 - 362.14474487 362.15826416 362.17175293 362.1852417 362.19876099 - 362.21224976 362.22573853 362.23925781 362.25274658 362.26623535 - 362.27975464 362.29324341 362.3067627 362.32025146 362.33374023 - 362.34725952 362.36074829 362.37423706 362.38775635 362.40124512 - 362.4147644 362.42825317 362.44174194 362.45526123 362.46875 - 362.48223877 362.49575806 362.50924683 362.5227356 362.53625488 - 362.54974365 362.56326294 362.57675171 362.59024048 362.60375977 - 362.61724854 362.6307373 362.64425659 362.65774536 362.67126465 - 362.68475342 362.69824219 362.71176147 362.72525024 362.73873901 - 362.7522583 362.76574707 362.77923584 362.79275513 362.8062439 - 362.81976318 362.83325195 362.84674072 362.86026001 362.87374878 - 362.88723755 362.90075684 362.91424561 362.92776489 362.94125366 - 362.95474243 362.96826172 362.98175049 362.99523926 363.00875854 - 363.02224731 363.03573608 363.04925537 363.06274414 363.07626343 - 363.0897522 363.10324097 363.11676025 363.13024902 363.14373779 - 363.15725708 363.17074585 363.18426514 363.19775391 363.21124268 - 363.22476196 363.23825073 363.2517395 363.26525879 363.27874756 - 363.29223633 363.30575562 363.31951904 363.33377075 363.34857178 - 363.36395264 363.37991333 363.39645386 363.41360474 363.431427 - 363.44992065 363.46911621 363.48901367 363.50967407 363.53109741 - 363.55334473 363.57641602 363.60037231 363.62521362 363.65100098 - 363.67776489 363.70550537 363.73431396 363.76699829 363.80300903 - 363.83898926 363.875 363.91101074 363.94699097 363.98300171 - 364.01901245 364.05499268 364.09100342 364.12701416 364.16299438 - 364.19900513 364.23498535 364.27099609 364.30700684 364.34298706 - 364.3789978 364.41500854 364.45098877 364.48699951 364.52301025 - 364.55899048 364.59500122 364.63101196 364.66699219 364.70300293 - 364.73901367 364.7749939 364.81100464 364.84698486 364.88299561 - 364.91900635 364.95498657 364.99099731 365.02700806 365.06298828 - 365.09899902 365.13500977 365.17098999 365.20700073] - y: [ -5.59320021e+00 -5.55719995e+00 -5.52120018e+00 -5.48519993e+00 - -5.44920015e+00 -5.41319990e+00 -5.37720013e+00 -5.34119987e+00 - -5.30520010e+00 -5.26919985e+00 -5.23320007e+00 -5.19719982e+00 - -5.16120005e+00 -5.12519979e+00 -5.08920002e+00 -5.05319977e+00 - -5.01719999e+00 -4.98120022e+00 -4.94519997e+00 -4.90920019e+00 - -4.87319994e+00 -4.83720016e+00 -4.80119991e+00 -4.76520014e+00 - -4.72919989e+00 -4.69320011e+00 -4.65719986e+00 -4.62120008e+00 - -4.58519983e+00 -4.54920006e+00 -4.51319981e+00 -4.47720003e+00 - -4.44119978e+00 -4.40520000e+00 -4.36920023e+00 -4.33319998e+00 - -4.29720020e+00 -4.26119995e+00 -4.22520018e+00 -4.19377995e+00 - -4.16359854e+00 -4.13460732e+00 -4.10675907e+00 -4.08000851e+00 - -4.05431318e+00 -4.02963066e+00 -4.00592136e+00 -3.98314714e+00 - -3.96127057e+00 -3.94025683e+00 -3.92007136e+00 -3.90068197e+00 - -3.88205695e+00 -3.86416626e+00 -3.84698105e+00 -3.83047342e+00 - -3.81461668e+00 -3.79938507e+00 -3.78475404e+00 -3.77069998e+00 - -3.75720000e+00 -3.74370003e+00 -3.73020005e+00 -3.71670008e+00 - -3.70320010e+00 -3.68969989e+00 -3.67619991e+00 -3.66269994e+00 - -3.64919996e+00 -3.63569999e+00 -3.62220001e+00 -3.60870004e+00 - -3.59520006e+00 -3.58170009e+00 -3.56820011e+00 -3.55469990e+00 - -3.54119992e+00 -3.52769995e+00 -3.51419997e+00 -3.50070000e+00 - -3.48720002e+00 -3.47370005e+00 -3.46020007e+00 -3.44670010e+00 - -3.43319988e+00 -3.41969991e+00 -3.40619993e+00 -3.39269996e+00 - -3.37919998e+00 -3.36570001e+00 -3.35220003e+00 -3.33870006e+00 - -3.32520008e+00 -3.31170011e+00 -3.29819989e+00 -3.28469992e+00 - -3.27119994e+00 -3.25769997e+00 -3.24419999e+00 -3.23070002e+00 - -3.21720004e+00 -3.20370007e+00 -3.19020009e+00 -3.17670012e+00 - -3.16319990e+00 -3.14969993e+00 -3.13619995e+00 -3.12269998e+00 - -3.10920000e+00 -3.09570003e+00 -3.08220005e+00 -3.06870008e+00 - -3.05520010e+00 -3.04169989e+00 -3.02819991e+00 -3.01469994e+00 - -3.00119996e+00 -2.98769999e+00 -2.97420001e+00 -2.96070004e+00 - -2.94720006e+00 -2.93370008e+00 -2.92020011e+00 -2.90669990e+00 - -2.89319992e+00 -2.87969995e+00 -2.86619997e+00 -2.85270000e+00 - -2.83920002e+00 -2.82570004e+00 -2.81220007e+00 -2.79870009e+00 - -2.78520012e+00 -2.77169991e+00 -2.75819993e+00 -2.74469995e+00 - -2.73119998e+00 -2.71770000e+00 -2.70420003e+00 -2.69070005e+00 - -2.67720008e+00 -2.66370010e+00 -2.65019989e+00 -2.63669991e+00 - -2.62319994e+00 -2.60969996e+00 -2.59619999e+00 -2.58270001e+00 - -2.56920004e+00 -2.55570006e+00 -2.54220009e+00 -2.52870011e+00 - -2.51519990e+00 -2.50169992e+00 -2.48819995e+00 -2.47469997e+00 - -2.46120000e+00 -2.44770002e+00 -2.43420005e+00 -2.42070007e+00 - -2.40720010e+00 -2.39369988e+00 -2.38019991e+00 -2.36669993e+00 - -2.35319996e+00 -2.33969998e+00 -2.32620001e+00 -2.31270003e+00 - -2.29920006e+00 -2.28570008e+00 -2.27220011e+00 -2.25869989e+00 - -2.24519992e+00 -2.23169994e+00 -2.21819997e+00 -2.20469999e+00 - -2.19120002e+00 -2.17770004e+00 -2.16420007e+00 -2.15070009e+00 - -2.13720012e+00 -2.12369990e+00 -2.11019993e+00 -2.09669995e+00 - -2.08319998e+00 -2.06970000e+00 -2.05620003e+00 -2.04270005e+00 - -2.02920008e+00 -2.01570010e+00 -2.00219989e+00 -1.98870003e+00 - -1.97520006e+00 -1.96169996e+00 -1.94819999e+00 -1.93470001e+00 - -1.92120004e+00 -1.90769994e+00 -1.89419997e+00 -1.88069999e+00 - -1.86720002e+00 -1.85370004e+00 -1.84019995e+00 -1.82669997e+00 - -1.81320000e+00 -1.79970002e+00 -1.78620005e+00 -1.77269995e+00 - -1.75919998e+00 -1.74570000e+00 -1.73220003e+00 -1.71870005e+00 - -1.70519996e+00 -1.69169998e+00 -1.67820001e+00 -1.66470003e+00 - -1.65120006e+00 -1.63769996e+00 -1.62419999e+00 -1.61070001e+00 - -1.59720004e+00 -1.58369994e+00 -1.57019997e+00 -1.55669999e+00 - -1.54320002e+00 -1.52970004e+00 -1.51619995e+00 -1.50269997e+00 - -1.48920000e+00 -1.47570002e+00 -1.46220005e+00 -1.44869995e+00 - -1.43519998e+00 -1.42170000e+00 -1.40820003e+00 -1.39470005e+00 - -1.38119996e+00 -1.36769998e+00 -1.35420001e+00 -1.34070003e+00 - -1.32720006e+00 -1.31369996e+00 -1.30019999e+00 -1.28670001e+00 - -1.27320004e+00 -1.25969994e+00 -1.24619997e+00 -1.23269999e+00 - -1.21920002e+00 -1.20570004e+00 -1.19219995e+00 -1.17869997e+00 - -1.16520000e+00 -1.15170002e+00 -1.13820004e+00 -1.12469995e+00 - -1.11119998e+00 -1.09770000e+00 -1.08420002e+00 -1.07070005e+00 - -1.05719995e+00 -1.04369998e+00 -1.03020000e+00 -1.01670003e+00 - -1.00320005e+00 -9.89700019e-01 -9.76199985e-01 -9.62700009e-01 - -9.49199975e-01 -9.35699999e-01 -9.22200024e-01 -9.08699989e-01 - -8.95200014e-01 -8.81699979e-01 -8.68200004e-01 -8.54700029e-01 - -8.41199994e-01 -8.27700019e-01 -8.14199984e-01 -8.00700009e-01 - -7.87199974e-01 -7.73699999e-01 -7.60200024e-01 -7.46699989e-01 - -7.33200014e-01 -7.19699979e-01 -7.06200004e-01 -6.92700028e-01 - -6.79199994e-01 -6.65700018e-01 -6.52199984e-01 -6.38700008e-01 - -6.25199974e-01 -6.11699998e-01 -5.98200023e-01 -5.84699988e-01 - -5.71200013e-01 -5.57699978e-01 -5.44200003e-01 -5.30700028e-01 - -5.17199993e-01 -5.03700018e-01 -4.90200013e-01 -4.76700008e-01 - -4.63200003e-01 -4.49699998e-01 -4.36199993e-01 -4.22699988e-01 - -4.09200013e-01 -3.95700008e-01 -3.82200003e-01 -3.68699998e-01 - -3.55199993e-01 -3.41699988e-01 -3.28200012e-01 -3.14700007e-01 - -3.01200002e-01 -2.87699997e-01 -2.74199992e-01 -2.60699987e-01 - -2.47199997e-01 -2.33700007e-01 -2.20200002e-01 -2.06699997e-01 - -1.93200007e-01 -1.79700002e-01 -1.66199997e-01 -1.52700007e-01 - -1.39200002e-01 -1.25699997e-01 -1.12199999e-01 -9.87000018e-02 - -8.51999968e-02 -7.16999993e-02 -5.82000017e-02 -4.47000004e-02 - -3.11999992e-02 -1.76999997e-02 -4.19999985e-03 9.30000003e-03 - 2.28000004e-02 3.62999998e-02 4.98000011e-02 6.32999986e-02 - 7.68000036e-02 9.03000012e-02 1.03799999e-01 1.17299996e-01 - 1.30799994e-01 1.44299999e-01 1.57800004e-01 1.71299994e-01 - 1.84799999e-01 1.98300004e-01 2.11799994e-01 2.25299999e-01 - 2.38800004e-01 2.52299994e-01 2.65799999e-01 2.79300004e-01 - 2.92800009e-01 3.06300014e-01 3.19799989e-01 3.33299994e-01 - 3.46799999e-01 3.60300004e-01 3.73800009e-01 3.87300014e-01 - 4.00799990e-01 4.14299995e-01 4.27800000e-01 4.41300005e-01 - 4.54800010e-01 4.68300015e-01 4.81799990e-01 4.95299995e-01 - 5.08800030e-01 5.22300005e-01 5.35799980e-01 5.49300015e-01 - 5.62799990e-01 5.76300025e-01 5.89800000e-01 6.03299975e-01 - 6.16800010e-01 6.30299985e-01 6.43800020e-01 6.57299995e-01 - 6.70799971e-01 6.84300005e-01 6.97799981e-01 7.11300015e-01 - 7.24799991e-01 7.38300025e-01 7.51800001e-01 7.65299976e-01 - 7.78800011e-01 7.92299986e-01 8.05800021e-01 8.19299996e-01 - 8.32799971e-01 8.46300006e-01 8.59799981e-01 8.73300016e-01 - 8.86799991e-01 9.00300026e-01 9.13800001e-01 9.27299976e-01 - 9.40800011e-01 9.54299986e-01 9.67800021e-01 9.81299996e-01 - 9.94799972e-01 1.00829995e+00 1.02180004e+00 1.03530002e+00 - 1.04879999e+00 1.06229997e+00 1.07579994e+00 1.08930004e+00 - 1.10280001e+00 1.11629999e+00 1.12979996e+00 1.14330006e+00 - 1.15680003e+00 1.17030001e+00 1.18379998e+00 1.19729996e+00 - 1.21080005e+00 1.22430003e+00 1.23780000e+00 1.25129998e+00 - 1.26479995e+00 1.27830005e+00 1.29180002e+00 1.30530000e+00 - 1.31879997e+00 1.33229995e+00 1.34580004e+00 1.35930002e+00 - 1.37279999e+00 1.38629997e+00 1.39979994e+00 1.41330004e+00 - 1.42680001e+00 1.44029999e+00 1.45379996e+00 1.46730006e+00 - 1.48080003e+00 1.49430001e+00 1.50779998e+00 1.52129996e+00 - 1.53480005e+00 1.54830003e+00 1.56180000e+00 1.57529998e+00 - 1.58879995e+00 1.60230005e+00 1.61580002e+00 1.62930000e+00 - 1.64279997e+00 1.65629995e+00 1.66980004e+00 1.68330002e+00 - 1.69679999e+00 1.71029997e+00 1.72379994e+00 1.73730004e+00 - 1.75080001e+00 1.76429999e+00 1.77779996e+00 1.79130006e+00 - 1.80480003e+00 1.81830001e+00 1.83179998e+00 1.84529996e+00 - 1.85880005e+00 1.87230003e+00 1.88580000e+00 1.89929998e+00 - 1.91279995e+00 1.92630005e+00 1.93980002e+00 1.95330000e+00 - 1.96679997e+00 1.98029995e+00 1.99380004e+00 2.00729990e+00 - 2.02080011e+00 2.03430009e+00 2.04780006e+00 2.06130004e+00 - 2.07480001e+00 2.08829999e+00 2.10179996e+00 2.11529994e+00 - 2.12879992e+00 2.14229989e+00 2.15580010e+00 2.16930008e+00 - 2.18280005e+00 2.19630003e+00 2.20980000e+00 2.22329998e+00 - 2.23679996e+00 2.25029993e+00 2.26379991e+00 2.27729988e+00 - 2.29080009e+00 2.30430007e+00 2.31780005e+00 2.33130002e+00 - 2.34480000e+00 2.35829997e+00 2.37179995e+00 2.38529992e+00 - 2.39879990e+00 2.41230011e+00 2.42580009e+00 2.43930006e+00 - 2.45280004e+00 2.46630001e+00 2.47979999e+00 2.49329996e+00 - 2.50679994e+00 2.52029991e+00 2.53379989e+00 2.54730010e+00 - 2.56080008e+00 2.57430005e+00 2.58780003e+00 2.60130000e+00 - 2.61479998e+00 2.62829995e+00 2.64179993e+00 2.65529990e+00 - 2.66880012e+00 2.68230009e+00 2.69580007e+00 2.70930004e+00 - 2.72280002e+00 2.73629999e+00 2.74979997e+00 2.76329994e+00 - 2.77679992e+00 2.79029989e+00 2.80380011e+00 2.81730008e+00 - 2.83080006e+00 2.84430003e+00 2.85780001e+00 2.87129998e+00 - 2.88479996e+00 2.89829993e+00 2.91179991e+00 2.92529988e+00 - 2.93880010e+00 2.95230007e+00 2.96580005e+00 2.97930002e+00 - 2.99280000e+00 3.00629997e+00 3.01979995e+00 3.03329992e+00 - 3.04679990e+00 3.06030011e+00 3.07380009e+00 3.08730006e+00 - 3.10080004e+00 3.11430001e+00 3.12779999e+00 3.14129996e+00 - 3.15479994e+00 3.16829991e+00 3.18179989e+00 3.19530010e+00 - 3.20880008e+00 3.22230005e+00 3.23580003e+00 3.24930000e+00 - 3.26279998e+00 3.27629995e+00 3.28979993e+00 3.30329990e+00 - 3.31680012e+00 3.33030009e+00 3.34380007e+00 3.35730004e+00 - 3.37080002e+00 3.38429999e+00 3.39779997e+00 3.41129994e+00 - 3.42479992e+00 3.43829989e+00 3.45180011e+00 3.46530008e+00 - 3.47880006e+00 3.49230003e+00 3.50580001e+00 3.51929998e+00 - 3.53279996e+00 3.54629993e+00 3.55979991e+00 3.57329988e+00 - 3.58680010e+00 3.60030007e+00 3.61380005e+00 3.62730002e+00 - 3.64080000e+00 3.65429997e+00 3.66779995e+00 3.68129992e+00 - 3.69479990e+00 3.70830011e+00 3.72180009e+00 3.73530006e+00 - 3.74880004e+00 3.76230001e+00 3.77579999e+00 3.78929996e+00 - 3.80279994e+00 3.81629992e+00 3.82979989e+00 3.84330010e+00 - 3.85680008e+00 3.87030005e+00 3.88380003e+00 3.89730000e+00 - 3.91079998e+00 3.92429996e+00 3.93779993e+00 3.95129991e+00 - 3.96479988e+00 3.97830009e+00 3.99180007e+00 4.00530005e+00 - 4.01879978e+00 4.03230000e+00 4.04580021e+00 4.05929995e+00 - 4.07280016e+00 4.08629990e+00 4.09980011e+00 4.11329985e+00 - 4.12680006e+00 4.14029980e+00 4.15380001e+00 4.16730022e+00 - 4.18079996e+00 4.19430017e+00 4.20779991e+00 4.22130013e+00 - 4.23479986e+00 4.24830008e+00 4.26179981e+00 4.27530003e+00 - 4.28879976e+00 4.30229998e+00 4.31580019e+00 4.32929993e+00 - 4.34280014e+00 4.35629988e+00 4.36980009e+00 4.38329983e+00 - 4.39680004e+00 4.41029978e+00 4.42379999e+00 4.43730021e+00 - 4.45079994e+00 4.46430016e+00 4.47779989e+00 4.49130011e+00 - 4.50479984e+00 4.51830006e+00 4.53179979e+00 4.54530001e+00 - 4.55880022e+00 4.57229996e+00 4.58580017e+00 4.59929991e+00 - 4.61280012e+00 4.62629986e+00 4.63980007e+00 4.65329981e+00 - 4.66680002e+00 4.68030024e+00 4.69379997e+00 4.70730019e+00 - 4.72079992e+00 4.73430014e+00 4.74779987e+00 4.76130009e+00 - 4.77479982e+00 4.78830004e+00 4.80179977e+00 4.81529999e+00 - 4.82880020e+00 4.84229994e+00 4.85580015e+00 4.86929989e+00 - 4.88280010e+00 4.89629984e+00 4.90980005e+00 4.92329979e+00 - 4.93680000e+00 4.95030022e+00 4.96379995e+00 4.97730017e+00 - 4.99079990e+00 5.00430012e+00 5.01779985e+00 5.03130007e+00 - 5.04479980e+00 5.05830002e+00 5.07180023e+00 5.08529997e+00 - 5.09880018e+00 5.11229992e+00 5.12580013e+00 5.13929987e+00 - 5.15280008e+00 5.16629982e+00 5.17980003e+00 5.19329977e+00 - 5.20679998e+00 5.22030020e+00 5.23379993e+00 5.24730015e+00 - 5.26079988e+00 5.27430010e+00 5.28779984e+00 5.30130005e+00 - 5.31479979e+00 5.32830000e+00 5.34180021e+00 5.35529995e+00 - 5.36880016e+00 5.38229990e+00 5.39580011e+00 5.40929985e+00 - 5.42280006e+00 5.43629980e+00 5.44980001e+00 5.46330023e+00 - 5.47679996e+00 5.49030018e+00 5.50379992e+00 5.51730013e+00 - 5.53079987e+00 5.54430008e+00 5.55779982e+00 5.57130003e+00 - 5.58479977e+00 5.59829998e+00 5.61180019e+00 5.62529993e+00 - 5.63880014e+00 5.65229988e+00 5.66580009e+00 5.67929983e+00 - 5.69280005e+00 5.70629978e+00 5.71980000e+00 5.73330021e+00 - 5.74679995e+00 5.76030016e+00 5.77379990e+00 5.78730011e+00 - 5.80079985e+00 5.81430006e+00 5.82779980e+00 5.84130001e+00 - 5.85480022e+00 5.86829996e+00 5.88180017e+00 5.89529991e+00 - 5.90880013e+00 5.92229986e+00 5.93580008e+00 5.94929981e+00 - 5.96280003e+00 5.97629976e+00 5.98979998e+00 6.00330019e+00 - 6.01679993e+00 6.03030014e+00 6.04379988e+00 6.05730009e+00 - 6.07079983e+00 6.08430004e+00 6.09779978e+00 6.11129999e+00 - 6.12480021e+00 6.13829994e+00 6.15180016e+00 6.16529989e+00 - 6.17880011e+00 6.19229984e+00 6.20580006e+00 6.21929979e+00 - 6.23280001e+00 6.24630022e+00 6.25979996e+00 6.27330017e+00 - 6.28679991e+00 6.30030012e+00 6.31379986e+00 6.32730007e+00 - 6.34079981e+00 6.35430002e+00 6.36780024e+00 6.38129997e+00 - 6.39480019e+00 6.40829992e+00 6.42180014e+00 6.43529987e+00 - 6.44880009e+00 6.46229982e+00 6.47580004e+00 6.48929977e+00 - 6.50279999e+00 6.51630020e+00 6.52979994e+00 6.54330015e+00 - 6.55679989e+00 6.57030010e+00 6.58379984e+00 6.59730005e+00 - 6.61079979e+00 6.62430000e+00 6.63780022e+00 6.65129995e+00 - 6.66480017e+00 6.67829990e+00 6.69180012e+00 6.70529985e+00 - 6.71880007e+00 6.73229980e+00 6.74580002e+00 6.75930023e+00 - 6.77279997e+00 6.78630018e+00 6.79979992e+00 6.81330013e+00 - 6.82679987e+00 6.84030008e+00 6.85379982e+00 6.86730003e+00 - 6.88079977e+00 6.89429998e+00 6.90780020e+00 6.92129993e+00 - 6.93480015e+00 6.94829988e+00 6.96180010e+00 6.97529984e+00 - 6.98880005e+00 7.00229979e+00 7.01580000e+00 7.02930021e+00 - 7.04279995e+00 7.05630016e+00 7.06979990e+00 7.08330011e+00 - 7.09679985e+00 7.11030006e+00 7.12379980e+00 7.13730001e+00 - 7.15080023e+00 7.16485405e+00 7.17948532e+00 7.19471693e+00 - 7.21057367e+00 7.22708130e+00 7.24426651e+00 7.26215696e+00 - 7.28078175e+00 7.30017138e+00 7.32035685e+00 7.34137058e+00 - 7.36324692e+00 7.38602161e+00 7.40973091e+00 7.43441296e+00 - 7.46010876e+00 7.48685884e+00 7.51470709e+00 7.54369831e+00 - 7.57387972e+00 7.60529995e+00 7.64130020e+00 7.67729998e+00 - 7.71330023e+00 7.74930000e+00 7.78529978e+00 7.82130003e+00 - 7.85729980e+00 7.89330006e+00 7.92929983e+00 7.96530008e+00 - 8.00129986e+00 8.03730011e+00 8.07330036e+00 8.10929966e+00 - 8.14529991e+00 8.18130016e+00 8.21730042e+00 8.25329971e+00 - 8.28929996e+00 8.32530022e+00 8.36130047e+00 8.39729977e+00 - 8.43330002e+00 8.46930027e+00 8.50529957e+00 8.54129982e+00 - 8.57730007e+00 8.61330032e+00 8.64929962e+00 8.68529987e+00 - 8.72130013e+00 8.75730038e+00 8.79329967e+00 8.82929993e+00 - 8.86530018e+00 8.90130043e+00 8.93729973e+00 8.97329998e+00] - y_lower_bound: [ -5.61120033e+00 -5.57520008e+00 -5.53919983e+00 -5.50320005e+00 - -5.46719980e+00 -5.43120003e+00 -5.39519978e+00 -5.35920000e+00 - -5.32320023e+00 -5.28719997e+00 -5.25120020e+00 -5.21519995e+00 - -5.17920017e+00 -5.14319992e+00 -5.10720015e+00 -5.07119989e+00 - -5.03520012e+00 -4.99919987e+00 -4.96320009e+00 -4.92719984e+00 - -4.89120007e+00 -4.85519981e+00 -4.81920004e+00 -4.78319979e+00 - -4.74720001e+00 -4.71120024e+00 -4.67519999e+00 -4.63920021e+00 - -4.60319996e+00 -4.56720018e+00 -4.53119993e+00 -4.49520016e+00 - -4.45919991e+00 -4.42320013e+00 -4.38719988e+00 -4.35120010e+00 - -4.31519985e+00 -4.27920008e+00 -4.24319983e+00 -4.20948982e+00 - -4.17868900e+00 -4.14910269e+00 -4.12068319e+00 -4.09338379e+00 - -4.06716108e+00 -4.04197168e+00 -4.01777601e+00 -3.99453425e+00 - -3.97220898e+00 -3.95076370e+00 -3.93016410e+00 -3.91037679e+00 - -3.89136934e+00 -3.87311172e+00 -3.85557365e+00 -3.83872724e+00 - -3.82254505e+00 -3.80700088e+00 -3.79206967e+00 -3.77772713e+00 - -3.76395011e+00 -3.75044990e+00 -3.73694992e+00 -3.72344995e+00 - -3.70994997e+00 -3.69645000e+00 -3.68295002e+00 -3.66945004e+00 - -3.65595007e+00 -3.64245009e+00 -3.62895012e+00 -3.61544991e+00 - -3.60194993e+00 -3.58844995e+00 -3.57494998e+00 -3.56145000e+00 - -3.54795003e+00 -3.53445005e+00 -3.52095008e+00 -3.50745010e+00 - -3.49394989e+00 -3.48044991e+00 -3.46694994e+00 -3.45344996e+00 - -3.43994999e+00 -3.42645001e+00 -3.41295004e+00 -3.39945006e+00 - -3.38595009e+00 -3.37245011e+00 -3.35894990e+00 -3.34544992e+00 - -3.33194995e+00 -3.31844997e+00 -3.30495000e+00 -3.29145002e+00 - -3.27795005e+00 -3.26445007e+00 -3.25095010e+00 -3.23744988e+00 - -3.22394991e+00 -3.21044993e+00 -3.19694996e+00 -3.18344998e+00 - -3.16995001e+00 -3.15645003e+00 -3.14295006e+00 -3.12945008e+00 - -3.11595011e+00 -3.10244989e+00 -3.08894992e+00 -3.07544994e+00 - -3.06194997e+00 -3.04844999e+00 -3.03495002e+00 -3.02145004e+00 - -3.00795007e+00 -2.99445009e+00 -2.98095012e+00 -2.96744990e+00 - -2.95394993e+00 -2.94044995e+00 -2.92694998e+00 -2.91345000e+00 - -2.89995003e+00 -2.88645005e+00 -2.87295008e+00 -2.85945010e+00 - -2.84594989e+00 -2.83244991e+00 -2.81894994e+00 -2.80544996e+00 - -2.79194999e+00 -2.77845001e+00 -2.76495004e+00 -2.75145006e+00 - -2.73795009e+00 -2.72445011e+00 -2.71094990e+00 -2.69744992e+00 - -2.68394995e+00 -2.67044997e+00 -2.65695000e+00 -2.64345002e+00 - -2.62995005e+00 -2.61645007e+00 -2.60295010e+00 -2.58944988e+00 - -2.57594991e+00 -2.56244993e+00 -2.54894996e+00 -2.53544998e+00 - -2.52195001e+00 -2.50845003e+00 -2.49495006e+00 -2.48145008e+00 - -2.46795011e+00 -2.45444989e+00 -2.44094992e+00 -2.42744994e+00 - -2.41394997e+00 -2.40044999e+00 -2.38695002e+00 -2.37345004e+00 - -2.35995007e+00 -2.34645009e+00 -2.33295012e+00 -2.31944990e+00 - -2.30594993e+00 -2.29244995e+00 -2.27894998e+00 -2.26545000e+00 - -2.25195003e+00 -2.23845005e+00 -2.22495008e+00 -2.21145010e+00 - -2.19794989e+00 -2.18444991e+00 -2.17094994e+00 -2.15744996e+00 - -2.14394999e+00 -2.13045001e+00 -2.11695004e+00 -2.10345006e+00 - -2.08995008e+00 -2.07645011e+00 -2.06294990e+00 -2.04944992e+00 - -2.03594995e+00 -2.02244997e+00 -2.00895000e+00 -1.99545002e+00 - -1.98195004e+00 -1.96844995e+00 -1.95494998e+00 -1.94145000e+00 - -1.92795002e+00 -1.91445005e+00 -1.90094995e+00 -1.88744998e+00 - -1.87395000e+00 -1.86045003e+00 -1.84695005e+00 -1.83344996e+00 - -1.81994998e+00 -1.80645001e+00 -1.79295003e+00 -1.77945006e+00 - -1.76594996e+00 -1.75244999e+00 -1.73895001e+00 -1.72545004e+00 - -1.71194994e+00 -1.69844997e+00 -1.68494999e+00 -1.67145002e+00 - -1.65795004e+00 -1.64444995e+00 -1.63094997e+00 -1.61745000e+00 - -1.60395002e+00 -1.59045005e+00 -1.57694995e+00 -1.56344998e+00 - -1.54995000e+00 -1.53645003e+00 -1.52295005e+00 -1.50944996e+00 - -1.49594998e+00 -1.48245001e+00 -1.46895003e+00 -1.45545006e+00 - -1.44194996e+00 -1.42844999e+00 -1.41495001e+00 -1.40145004e+00 - -1.38794994e+00 -1.37444997e+00 -1.36094999e+00 -1.34745002e+00 - -1.33395004e+00 -1.32044995e+00 -1.30694997e+00 -1.29345000e+00 - -1.27995002e+00 -1.26645005e+00 -1.25294995e+00 -1.23944998e+00 - -1.22595000e+00 -1.21245003e+00 -1.19895005e+00 -1.18544996e+00 - -1.17194998e+00 -1.15845001e+00 -1.14495003e+00 -1.13145006e+00 - -1.11794996e+00 -1.10444999e+00 -1.09095001e+00 -1.07745004e+00 - -1.06394994e+00 -1.05044997e+00 -1.03694999e+00 -1.02345002e+00 - -1.00995004e+00 -9.96450007e-01 -9.82949972e-01 -9.69449997e-01 - -9.55950022e-01 -9.42449987e-01 -9.28950012e-01 -9.15449977e-01 - -9.01950002e-01 -8.88450027e-01 -8.74949992e-01 -8.61450016e-01 - -8.47949982e-01 -8.34450006e-01 -8.20949972e-01 -8.07449996e-01 - -7.93950021e-01 -7.80449986e-01 -7.66950011e-01 -7.53449976e-01 - -7.39950001e-01 -7.26450026e-01 -7.12949991e-01 -6.99450016e-01 - -6.85949981e-01 -6.72450006e-01 -6.58949971e-01 -6.45449996e-01 - -6.31950021e-01 -6.18449986e-01 -6.04950011e-01 -5.91449976e-01 - -5.77950001e-01 -5.64450026e-01 -5.50949991e-01 -5.37450016e-01 - -5.23949981e-01 -5.10450006e-01 -4.96950001e-01 -4.83449996e-01 - -4.69949991e-01 -4.56449986e-01 -4.42950010e-01 -4.29450005e-01 - -4.15950000e-01 -4.02449995e-01 -3.88949990e-01 -3.75449985e-01 - -3.61950010e-01 -3.48450005e-01 -3.34950000e-01 -3.21449995e-01 - -3.07949990e-01 -2.94450015e-01 -2.80950010e-01 -2.67450005e-01 - -2.53950000e-01 -2.40449995e-01 -2.26950005e-01 -2.13450000e-01 - -1.99949995e-01 -1.86450005e-01 -1.72950000e-01 -1.59449995e-01 - -1.45950004e-01 -1.32449999e-01 -1.18950002e-01 -1.05449997e-01 - -9.19499993e-02 -7.84500018e-02 -6.49499968e-02 -5.14499992e-02 - -3.79500017e-02 -2.44500004e-02 -1.09500000e-02 2.55000009e-03 - 1.60499997e-02 2.95499992e-02 4.30499986e-02 5.65499999e-02 - 7.00500011e-02 8.35499987e-02 9.70500037e-02 1.10550001e-01 - 1.24049999e-01 1.37549996e-01 1.51050001e-01 1.64550006e-01 - 1.78049996e-01 1.91550002e-01 2.05050007e-01 2.18549997e-01 - 2.32050002e-01 2.45550007e-01 2.59050012e-01 2.72549987e-01 - 2.86049992e-01 2.99549997e-01 3.13050002e-01 3.26550007e-01 - 3.40050012e-01 3.53549987e-01 3.67049992e-01 3.80549997e-01 - 3.94050002e-01 4.07550007e-01 4.21050012e-01 4.34549987e-01 - 4.48049992e-01 4.61549997e-01 4.75050002e-01 4.88550007e-01 - 5.02049983e-01 5.15550017e-01 5.29049993e-01 5.42550027e-01 - 5.56050003e-01 5.69549978e-01 5.83050013e-01 5.96549988e-01 - 6.10050023e-01 6.23549998e-01 6.37049973e-01 6.50550008e-01 - 6.64049983e-01 6.77550018e-01 6.91049993e-01 7.04550028e-01 - 7.18050003e-01 7.31549978e-01 7.45050013e-01 7.58549988e-01 - 7.72050023e-01 7.85549998e-01 7.99049973e-01 8.12550008e-01 - 8.26049984e-01 8.39550018e-01 8.53049994e-01 8.66550028e-01 - 8.80050004e-01 8.93549979e-01 9.07050014e-01 9.20549989e-01 - 9.34050024e-01 9.47549999e-01 9.61049974e-01 9.74550009e-01 - 9.88049984e-01 1.00154996e+00 1.01505005e+00 1.02855003e+00 - 1.04205000e+00 1.05554998e+00 1.06904995e+00 1.08255005e+00 - 1.09605002e+00 1.10955000e+00 1.12304997e+00 1.13654995e+00 - 1.15005004e+00 1.16355002e+00 1.17704999e+00 1.19054997e+00 - 1.20404994e+00 1.21755004e+00 1.23105001e+00 1.24454999e+00 - 1.25804996e+00 1.27155006e+00 1.28505003e+00 1.29855001e+00 - 1.31204998e+00 1.32554996e+00 1.33905005e+00 1.35255003e+00 - 1.36605000e+00 1.37954998e+00 1.39304996e+00 1.40655005e+00 - 1.42005002e+00 1.43355000e+00 1.44704998e+00 1.46054995e+00 - 1.47405005e+00 1.48755002e+00 1.50105000e+00 1.51454997e+00 - 1.52804995e+00 1.54155004e+00 1.55505002e+00 1.56854999e+00 - 1.58204997e+00 1.59554994e+00 1.60905004e+00 1.62255001e+00 - 1.63604999e+00 1.64954996e+00 1.66305006e+00 1.67655003e+00 - 1.69005001e+00 1.70354998e+00 1.71704996e+00 1.73055005e+00 - 1.74405003e+00 1.75755000e+00 1.77104998e+00 1.78454995e+00 - 1.79805005e+00 1.81155002e+00 1.82505000e+00 1.83854997e+00 - 1.85204995e+00 1.86555004e+00 1.87905002e+00 1.89254999e+00 - 1.90604997e+00 1.91954994e+00 1.93305004e+00 1.94655001e+00 - 1.96004999e+00 1.97354996e+00 1.98705006e+00 2.00055003e+00 - 2.01405001e+00 2.02754998e+00 2.04104996e+00 2.05454993e+00 - 2.06804991e+00 2.08154988e+00 2.09505010e+00 2.10855007e+00 - 2.12205005e+00 2.13555002e+00 2.14905000e+00 2.16254997e+00 - 2.17604995e+00 2.18954992e+00 2.20304990e+00 2.21655011e+00 - 2.23005009e+00 2.24355006e+00 2.25705004e+00 2.27055001e+00 - 2.28404999e+00 2.29754996e+00 2.31104994e+00 2.32454991e+00 - 2.33804989e+00 2.35155010e+00 2.36505008e+00 2.37855005e+00 - 2.39205003e+00 2.40555000e+00 2.41904998e+00 2.43254995e+00 - 2.44604993e+00 2.45954990e+00 2.47305012e+00 2.48655009e+00 - 2.50005007e+00 2.51355004e+00 2.52705002e+00 2.54054999e+00 - 2.55404997e+00 2.56754994e+00 2.58104992e+00 2.59454989e+00 - 2.60805011e+00 2.62155008e+00 2.63505006e+00 2.64855003e+00 - 2.66205001e+00 2.67554998e+00 2.68904996e+00 2.70254993e+00 - 2.71604991e+00 2.72954988e+00 2.74305010e+00 2.75655007e+00 - 2.77005005e+00 2.78355002e+00 2.79705000e+00 2.81054997e+00 - 2.82404995e+00 2.83754992e+00 2.85104990e+00 2.86455011e+00 - 2.87805009e+00 2.89155006e+00 2.90505004e+00 2.91855001e+00 - 2.93204999e+00 2.94554996e+00 2.95904994e+00 2.97254992e+00 - 2.98604989e+00 2.99955010e+00 3.01305008e+00 3.02655005e+00 - 3.04005003e+00 3.05355000e+00 3.06704998e+00 3.08054996e+00 - 3.09404993e+00 3.10754991e+00 3.12104988e+00 3.13455009e+00 - 3.14805007e+00 3.16155005e+00 3.17505002e+00 3.18855000e+00 - 3.20204997e+00 3.21554995e+00 3.22904992e+00 3.24254990e+00 - 3.25605011e+00 3.26955009e+00 3.28305006e+00 3.29655004e+00 - 3.31005001e+00 3.32354999e+00 3.33704996e+00 3.35054994e+00 - 3.36404991e+00 3.37754989e+00 3.39105010e+00 3.40455008e+00 - 3.41805005e+00 3.43155003e+00 3.44505000e+00 3.45854998e+00 - 3.47204995e+00 3.48554993e+00 3.49904990e+00 3.51255012e+00 - 3.52605009e+00 3.53955007e+00 3.55305004e+00 3.56655002e+00 - 3.58004999e+00 3.59354997e+00 3.60704994e+00 3.62054992e+00 - 3.63404989e+00 3.64755011e+00 3.66105008e+00 3.67455006e+00 - 3.68805003e+00 3.70155001e+00 3.71504998e+00 3.72854996e+00 - 3.74204993e+00 3.75554991e+00 3.76904988e+00 3.78255010e+00 - 3.79605007e+00 3.80955005e+00 3.82305002e+00 3.83655000e+00 - 3.85004997e+00 3.86354995e+00 3.87704992e+00 3.89054990e+00 - 3.90405011e+00 3.91755009e+00 3.93105006e+00 3.94455004e+00 - 3.95805001e+00 3.97154999e+00 3.98504996e+00 3.99854994e+00 - 4.01205015e+00 4.02554989e+00 4.03905010e+00 4.05254984e+00 - 4.06605005e+00 4.07954979e+00 4.09305000e+00 4.10655022e+00 - 4.12004995e+00 4.13355017e+00 4.14704990e+00 4.16055012e+00 - 4.17404985e+00 4.18755007e+00 4.20104980e+00 4.21455002e+00 - 4.22805023e+00 4.24154997e+00 4.25505018e+00 4.26854992e+00 - 4.28205013e+00 4.29554987e+00 4.30905008e+00 4.32254982e+00 - 4.33605003e+00 4.34954977e+00 4.36304998e+00 4.37655020e+00 - 4.39004993e+00 4.40355015e+00 4.41704988e+00 4.43055010e+00 - 4.44404984e+00 4.45755005e+00 4.47104979e+00 4.48455000e+00 - 4.49805021e+00 4.51154995e+00 4.52505016e+00 4.53854990e+00 - 4.55205011e+00 4.56554985e+00 4.57905006e+00 4.59254980e+00 - 4.60605001e+00 4.61955023e+00 4.63304996e+00 4.64655018e+00 - 4.66004992e+00 4.67355013e+00 4.68704987e+00 4.70055008e+00 - 4.71404982e+00 4.72755003e+00 4.74104977e+00 4.75454998e+00 - 4.76805019e+00 4.78154993e+00 4.79505014e+00 4.80854988e+00 - 4.82205009e+00 4.83554983e+00 4.84905005e+00 4.86254978e+00 - 4.87605000e+00 4.88955021e+00 4.90304995e+00 4.91655016e+00 - 4.93004990e+00 4.94355011e+00 4.95704985e+00 4.97055006e+00 - 4.98404980e+00 4.99755001e+00 5.01105022e+00 5.02454996e+00 - 5.03805017e+00 5.05154991e+00 5.06505013e+00 5.07854986e+00 - 5.09205008e+00 5.10554981e+00 5.11905003e+00 5.13254976e+00 - 5.14604998e+00 5.15955019e+00 5.17304993e+00 5.18655014e+00 - 5.20004988e+00 5.21355009e+00 5.22704983e+00 5.24055004e+00 - 5.25404978e+00 5.26754999e+00 5.28105021e+00 5.29454994e+00 - 5.30805016e+00 5.32154989e+00 5.33505011e+00 5.34854984e+00 - 5.36205006e+00 5.37554979e+00 5.38905001e+00 5.40255022e+00 - 5.41604996e+00 5.42955017e+00 5.44304991e+00 5.45655012e+00 - 5.47004986e+00 5.48355007e+00 5.49704981e+00 5.51055002e+00 - 5.52405024e+00 5.53754997e+00 5.55105019e+00 5.56454992e+00 - 5.57805014e+00 5.59154987e+00 5.60505009e+00 5.61854982e+00 - 5.63205004e+00 5.64554977e+00 5.65904999e+00 5.67255020e+00 - 5.68604994e+00 5.69955015e+00 5.71304989e+00 5.72655010e+00 - 5.74004984e+00 5.75355005e+00 5.76704979e+00 5.78055000e+00 - 5.79405022e+00 5.80754995e+00 5.82105017e+00 5.83454990e+00 - 5.84805012e+00 5.86154985e+00 5.87505007e+00 5.88854980e+00 - 5.90205002e+00 5.91555023e+00 5.92904997e+00 5.94255018e+00 - 5.95604992e+00 5.96955013e+00 5.98304987e+00 5.99655008e+00 - 6.01004982e+00 6.02355003e+00 6.03704977e+00 6.05054998e+00 - 6.06405020e+00 6.07754993e+00 6.09105015e+00 6.10454988e+00 - 6.11805010e+00 6.13154984e+00 6.14505005e+00 6.15854979e+00 - 6.17205000e+00 6.18555021e+00 6.19904995e+00 6.21255016e+00 - 6.22604990e+00 6.23955011e+00 6.25304985e+00 6.26655006e+00 - 6.28004980e+00 6.29355001e+00 6.30705023e+00 6.32054996e+00 - 6.33405018e+00 6.34754992e+00 6.36105013e+00 6.37454987e+00 - 6.38805008e+00 6.40154982e+00 6.41505003e+00 6.42854977e+00 - 6.44204998e+00 6.45555019e+00 6.46904993e+00 6.48255014e+00 - 6.49604988e+00 6.50955009e+00 6.52304983e+00 6.53655005e+00 - 6.55004978e+00 6.56355000e+00 6.57705021e+00 6.59054995e+00 - 6.60405016e+00 6.61754990e+00 6.63105011e+00 6.64454985e+00 - 6.65805006e+00 6.67154980e+00 6.68505001e+00 6.69855022e+00 - 6.71204996e+00 6.72555017e+00 6.73904991e+00 6.75255013e+00 - 6.76604986e+00 6.77955008e+00 6.79304981e+00 6.80655003e+00 - 6.82004976e+00 6.83354998e+00 6.84705019e+00 6.86054993e+00 - 6.87405014e+00 6.88754988e+00 6.90105009e+00 6.91454983e+00 - 6.92805004e+00 6.94154978e+00 6.95504999e+00 6.96855021e+00 - 6.98204994e+00 6.99555016e+00 7.00904989e+00 7.02255011e+00 - 7.03604984e+00 7.04955006e+00 7.06304979e+00 7.07655001e+00 - 7.09005022e+00 7.10354996e+00 7.11705017e+00 7.13054991e+00 - 7.14405012e+00 7.15782690e+00 7.17216969e+00 7.18710089e+00 - 7.20264530e+00 7.21882725e+00 7.23567390e+00 7.25321150e+00 - 7.27146959e+00 7.29047680e+00 7.31026411e+00 7.33086348e+00 - 7.35230875e+00 7.37463427e+00 7.39787626e+00 7.42207193e+00 - 7.44726086e+00 7.47348356e+00 7.50078297e+00 7.52920294e+00 - 7.55878925e+00 7.58959007e+00 7.62330008e+00 7.65929985e+00 - 7.69530010e+00 7.73129988e+00 7.76730013e+00 7.80329990e+00 - 7.83930016e+00 7.87529993e+00 7.91130018e+00 7.94729996e+00 - 7.98330021e+00 8.01930046e+00 8.05529976e+00 8.09130001e+00 - 8.12730026e+00 8.16329956e+00 8.19929981e+00 8.23530006e+00 - 8.27130032e+00 8.30729961e+00 8.34329987e+00 8.37930012e+00 - 8.41530037e+00 8.45129967e+00 8.48729992e+00 8.52330017e+00 - 8.55930042e+00 8.59529972e+00 8.63129997e+00 8.66730022e+00 - 8.70330048e+00 8.73929977e+00 8.77530003e+00 8.81130028e+00 - 8.84729958e+00 8.88329983e+00 8.91930008e+00 8.95530033e+00] - y_upper_bound: [ -5.57520008e+00 -5.53919983e+00 -5.50320005e+00 -5.46719980e+00 - -5.43120003e+00 -5.39519978e+00 -5.35920000e+00 -5.32320023e+00 - -5.28719997e+00 -5.25120020e+00 -5.21519995e+00 -5.17920017e+00 - -5.14319992e+00 -5.10720015e+00 -5.07119989e+00 -5.03520012e+00 - -4.99919987e+00 -4.96320009e+00 -4.92719984e+00 -4.89120007e+00 - -4.85519981e+00 -4.81920004e+00 -4.78319979e+00 -4.74720001e+00 - -4.71120024e+00 -4.67519999e+00 -4.63920021e+00 -4.60319996e+00 - -4.56720018e+00 -4.53119993e+00 -4.49520016e+00 -4.45919991e+00 - -4.42320013e+00 -4.38719988e+00 -4.35120010e+00 -4.31519985e+00 - -4.27920008e+00 -4.24319983e+00 -4.20948982e+00 -4.17868900e+00 - -4.14910269e+00 -4.12068319e+00 -4.09338379e+00 -4.06716108e+00 - -4.04197168e+00 -4.01777601e+00 -3.99453425e+00 -3.97220898e+00 - -3.95076370e+00 -3.93016410e+00 -3.91037679e+00 -3.89136934e+00 - -3.87311172e+00 -3.85557365e+00 -3.83872724e+00 -3.82254505e+00 - -3.80700088e+00 -3.79206967e+00 -3.77772713e+00 -3.76395011e+00 - -3.75044990e+00 -3.73694992e+00 -3.72344995e+00 -3.70994997e+00 - -3.69645000e+00 -3.68295002e+00 -3.66945004e+00 -3.65595007e+00 - -3.64245009e+00 -3.62895012e+00 -3.61544991e+00 -3.60194993e+00 - -3.58844995e+00 -3.57494998e+00 -3.56145000e+00 -3.54795003e+00 - -3.53445005e+00 -3.52095008e+00 -3.50745010e+00 -3.49394989e+00 - -3.48044991e+00 -3.46694994e+00 -3.45344996e+00 -3.43994999e+00 - -3.42645001e+00 -3.41295004e+00 -3.39945006e+00 -3.38595009e+00 - -3.37245011e+00 -3.35894990e+00 -3.34544992e+00 -3.33194995e+00 - -3.31844997e+00 -3.30495000e+00 -3.29145002e+00 -3.27795005e+00 - -3.26445007e+00 -3.25095010e+00 -3.23744988e+00 -3.22394991e+00 - -3.21044993e+00 -3.19694996e+00 -3.18344998e+00 -3.16995001e+00 - -3.15645003e+00 -3.14295006e+00 -3.12945008e+00 -3.11595011e+00 - -3.10244989e+00 -3.08894992e+00 -3.07544994e+00 -3.06194997e+00 - -3.04844999e+00 -3.03495002e+00 -3.02145004e+00 -3.00795007e+00 - -2.99445009e+00 -2.98095012e+00 -2.96744990e+00 -2.95394993e+00 - -2.94044995e+00 -2.92694998e+00 -2.91345000e+00 -2.89995003e+00 - -2.88645005e+00 -2.87295008e+00 -2.85945010e+00 -2.84594989e+00 - -2.83244991e+00 -2.81894994e+00 -2.80544996e+00 -2.79194999e+00 - -2.77845001e+00 -2.76495004e+00 -2.75145006e+00 -2.73795009e+00 - -2.72445011e+00 -2.71094990e+00 -2.69744992e+00 -2.68394995e+00 - -2.67044997e+00 -2.65695000e+00 -2.64345002e+00 -2.62995005e+00 - -2.61645007e+00 -2.60295010e+00 -2.58944988e+00 -2.57594991e+00 - -2.56244993e+00 -2.54894996e+00 -2.53544998e+00 -2.52195001e+00 - -2.50845003e+00 -2.49495006e+00 -2.48145008e+00 -2.46795011e+00 - -2.45444989e+00 -2.44094992e+00 -2.42744994e+00 -2.41394997e+00 - -2.40044999e+00 -2.38695002e+00 -2.37345004e+00 -2.35995007e+00 - -2.34645009e+00 -2.33295012e+00 -2.31944990e+00 -2.30594993e+00 - -2.29244995e+00 -2.27894998e+00 -2.26545000e+00 -2.25195003e+00 - -2.23845005e+00 -2.22495008e+00 -2.21145010e+00 -2.19794989e+00 - -2.18444991e+00 -2.17094994e+00 -2.15744996e+00 -2.14394999e+00 - -2.13045001e+00 -2.11695004e+00 -2.10345006e+00 -2.08995008e+00 - -2.07645011e+00 -2.06294990e+00 -2.04944992e+00 -2.03594995e+00 - -2.02244997e+00 -2.00895000e+00 -1.99545002e+00 -1.98195004e+00 - -1.96844995e+00 -1.95494998e+00 -1.94145000e+00 -1.92795002e+00 - -1.91445005e+00 -1.90094995e+00 -1.88744998e+00 -1.87395000e+00 - -1.86045003e+00 -1.84695005e+00 -1.83344996e+00 -1.81994998e+00 - -1.80645001e+00 -1.79295003e+00 -1.77945006e+00 -1.76594996e+00 - -1.75244999e+00 -1.73895001e+00 -1.72545004e+00 -1.71194994e+00 - -1.69844997e+00 -1.68494999e+00 -1.67145002e+00 -1.65795004e+00 - -1.64444995e+00 -1.63094997e+00 -1.61745000e+00 -1.60395002e+00 - -1.59045005e+00 -1.57694995e+00 -1.56344998e+00 -1.54995000e+00 - -1.53645003e+00 -1.52295005e+00 -1.50944996e+00 -1.49594998e+00 - -1.48245001e+00 -1.46895003e+00 -1.45545006e+00 -1.44194996e+00 - -1.42844999e+00 -1.41495001e+00 -1.40145004e+00 -1.38794994e+00 - -1.37444997e+00 -1.36094999e+00 -1.34745002e+00 -1.33395004e+00 - -1.32044995e+00 -1.30694997e+00 -1.29345000e+00 -1.27995002e+00 - -1.26645005e+00 -1.25294995e+00 -1.23944998e+00 -1.22595000e+00 - -1.21245003e+00 -1.19895005e+00 -1.18544996e+00 -1.17194998e+00 - -1.15845001e+00 -1.14495003e+00 -1.13145006e+00 -1.11794996e+00 - -1.10444999e+00 -1.09095001e+00 -1.07745004e+00 -1.06394994e+00 - -1.05044997e+00 -1.03694999e+00 -1.02345002e+00 -1.00995004e+00 - -9.96450007e-01 -9.82949972e-01 -9.69449997e-01 -9.55950022e-01 - -9.42449987e-01 -9.28950012e-01 -9.15449977e-01 -9.01950002e-01 - -8.88450027e-01 -8.74949992e-01 -8.61450016e-01 -8.47949982e-01 - -8.34450006e-01 -8.20949972e-01 -8.07449996e-01 -7.93950021e-01 - -7.80449986e-01 -7.66950011e-01 -7.53449976e-01 -7.39950001e-01 - -7.26450026e-01 -7.12949991e-01 -6.99450016e-01 -6.85949981e-01 - -6.72450006e-01 -6.58949971e-01 -6.45449996e-01 -6.31950021e-01 - -6.18449986e-01 -6.04950011e-01 -5.91449976e-01 -5.77950001e-01 - -5.64450026e-01 -5.50949991e-01 -5.37450016e-01 -5.23949981e-01 - -5.10450006e-01 -4.96950001e-01 -4.83449996e-01 -4.69949991e-01 - -4.56449986e-01 -4.42950010e-01 -4.29450005e-01 -4.15950000e-01 - -4.02449995e-01 -3.88949990e-01 -3.75449985e-01 -3.61950010e-01 - -3.48450005e-01 -3.34950000e-01 -3.21449995e-01 -3.07949990e-01 - -2.94450015e-01 -2.80950010e-01 -2.67450005e-01 -2.53950000e-01 - -2.40449995e-01 -2.26950005e-01 -2.13450000e-01 -1.99949995e-01 - -1.86450005e-01 -1.72950000e-01 -1.59449995e-01 -1.45950004e-01 - -1.32449999e-01 -1.18950002e-01 -1.05449997e-01 -9.19499993e-02 - -7.84500018e-02 -6.49499968e-02 -5.14499992e-02 -3.79500017e-02 - -2.44500004e-02 -1.09500000e-02 2.55000009e-03 1.60499997e-02 - 2.95499992e-02 4.30499986e-02 5.65499999e-02 7.00500011e-02 - 8.35499987e-02 9.70500037e-02 1.10550001e-01 1.24049999e-01 - 1.37549996e-01 1.51050001e-01 1.64550006e-01 1.78049996e-01 - 1.91550002e-01 2.05050007e-01 2.18549997e-01 2.32050002e-01 - 2.45550007e-01 2.59050012e-01 2.72549987e-01 2.86049992e-01 - 2.99549997e-01 3.13050002e-01 3.26550007e-01 3.40050012e-01 - 3.53549987e-01 3.67049992e-01 3.80549997e-01 3.94050002e-01 - 4.07550007e-01 4.21050012e-01 4.34549987e-01 4.48049992e-01 - 4.61549997e-01 4.75050002e-01 4.88550007e-01 5.02049983e-01 - 5.15550017e-01 5.29049993e-01 5.42550027e-01 5.56050003e-01 - 5.69549978e-01 5.83050013e-01 5.96549988e-01 6.10050023e-01 - 6.23549998e-01 6.37049973e-01 6.50550008e-01 6.64049983e-01 - 6.77550018e-01 6.91049993e-01 7.04550028e-01 7.18050003e-01 - 7.31549978e-01 7.45050013e-01 7.58549988e-01 7.72050023e-01 - 7.85549998e-01 7.99049973e-01 8.12550008e-01 8.26049984e-01 - 8.39550018e-01 8.53049994e-01 8.66550028e-01 8.80050004e-01 - 8.93549979e-01 9.07050014e-01 9.20549989e-01 9.34050024e-01 - 9.47549999e-01 9.61049974e-01 9.74550009e-01 9.88049984e-01 - 1.00154996e+00 1.01505005e+00 1.02855003e+00 1.04205000e+00 - 1.05554998e+00 1.06904995e+00 1.08255005e+00 1.09605002e+00 - 1.10955000e+00 1.12304997e+00 1.13654995e+00 1.15005004e+00 - 1.16355002e+00 1.17704999e+00 1.19054997e+00 1.20404994e+00 - 1.21755004e+00 1.23105001e+00 1.24454999e+00 1.25804996e+00 - 1.27155006e+00 1.28505003e+00 1.29855001e+00 1.31204998e+00 - 1.32554996e+00 1.33905005e+00 1.35255003e+00 1.36605000e+00 - 1.37954998e+00 1.39304996e+00 1.40655005e+00 1.42005002e+00 - 1.43355000e+00 1.44704998e+00 1.46054995e+00 1.47405005e+00 - 1.48755002e+00 1.50105000e+00 1.51454997e+00 1.52804995e+00 - 1.54155004e+00 1.55505002e+00 1.56854999e+00 1.58204997e+00 - 1.59554994e+00 1.60905004e+00 1.62255001e+00 1.63604999e+00 - 1.64954996e+00 1.66305006e+00 1.67655003e+00 1.69005001e+00 - 1.70354998e+00 1.71704996e+00 1.73055005e+00 1.74405003e+00 - 1.75755000e+00 1.77104998e+00 1.78454995e+00 1.79805005e+00 - 1.81155002e+00 1.82505000e+00 1.83854997e+00 1.85204995e+00 - 1.86555004e+00 1.87905002e+00 1.89254999e+00 1.90604997e+00 - 1.91954994e+00 1.93305004e+00 1.94655001e+00 1.96004999e+00 - 1.97354996e+00 1.98705006e+00 2.00055003e+00 2.01405001e+00 - 2.02754998e+00 2.04104996e+00 2.05454993e+00 2.06804991e+00 - 2.08154988e+00 2.09505010e+00 2.10855007e+00 2.12205005e+00 - 2.13555002e+00 2.14905000e+00 2.16254997e+00 2.17604995e+00 - 2.18954992e+00 2.20304990e+00 2.21655011e+00 2.23005009e+00 - 2.24355006e+00 2.25705004e+00 2.27055001e+00 2.28404999e+00 - 2.29754996e+00 2.31104994e+00 2.32454991e+00 2.33804989e+00 - 2.35155010e+00 2.36505008e+00 2.37855005e+00 2.39205003e+00 - 2.40555000e+00 2.41904998e+00 2.43254995e+00 2.44604993e+00 - 2.45954990e+00 2.47305012e+00 2.48655009e+00 2.50005007e+00 - 2.51355004e+00 2.52705002e+00 2.54054999e+00 2.55404997e+00 - 2.56754994e+00 2.58104992e+00 2.59454989e+00 2.60805011e+00 - 2.62155008e+00 2.63505006e+00 2.64855003e+00 2.66205001e+00 - 2.67554998e+00 2.68904996e+00 2.70254993e+00 2.71604991e+00 - 2.72954988e+00 2.74305010e+00 2.75655007e+00 2.77005005e+00 - 2.78355002e+00 2.79705000e+00 2.81054997e+00 2.82404995e+00 - 2.83754992e+00 2.85104990e+00 2.86455011e+00 2.87805009e+00 - 2.89155006e+00 2.90505004e+00 2.91855001e+00 2.93204999e+00 - 2.94554996e+00 2.95904994e+00 2.97254992e+00 2.98604989e+00 - 2.99955010e+00 3.01305008e+00 3.02655005e+00 3.04005003e+00 - 3.05355000e+00 3.06704998e+00 3.08054996e+00 3.09404993e+00 - 3.10754991e+00 3.12104988e+00 3.13455009e+00 3.14805007e+00 - 3.16155005e+00 3.17505002e+00 3.18855000e+00 3.20204997e+00 - 3.21554995e+00 3.22904992e+00 3.24254990e+00 3.25605011e+00 - 3.26955009e+00 3.28305006e+00 3.29655004e+00 3.31005001e+00 - 3.32354999e+00 3.33704996e+00 3.35054994e+00 3.36404991e+00 - 3.37754989e+00 3.39105010e+00 3.40455008e+00 3.41805005e+00 - 3.43155003e+00 3.44505000e+00 3.45854998e+00 3.47204995e+00 - 3.48554993e+00 3.49904990e+00 3.51255012e+00 3.52605009e+00 - 3.53955007e+00 3.55305004e+00 3.56655002e+00 3.58004999e+00 - 3.59354997e+00 3.60704994e+00 3.62054992e+00 3.63404989e+00 - 3.64755011e+00 3.66105008e+00 3.67455006e+00 3.68805003e+00 - 3.70155001e+00 3.71504998e+00 3.72854996e+00 3.74204993e+00 - 3.75554991e+00 3.76904988e+00 3.78255010e+00 3.79605007e+00 - 3.80955005e+00 3.82305002e+00 3.83655000e+00 3.85004997e+00 - 3.86354995e+00 3.87704992e+00 3.89054990e+00 3.90405011e+00 - 3.91755009e+00 3.93105006e+00 3.94455004e+00 3.95805001e+00 - 3.97154999e+00 3.98504996e+00 3.99854994e+00 4.01205015e+00 - 4.02554989e+00 4.03905010e+00 4.05254984e+00 4.06605005e+00 - 4.07954979e+00 4.09305000e+00 4.10655022e+00 4.12004995e+00 - 4.13355017e+00 4.14704990e+00 4.16055012e+00 4.17404985e+00 - 4.18755007e+00 4.20104980e+00 4.21455002e+00 4.22805023e+00 - 4.24154997e+00 4.25505018e+00 4.26854992e+00 4.28205013e+00 - 4.29554987e+00 4.30905008e+00 4.32254982e+00 4.33605003e+00 - 4.34954977e+00 4.36304998e+00 4.37655020e+00 4.39004993e+00 - 4.40355015e+00 4.41704988e+00 4.43055010e+00 4.44404984e+00 - 4.45755005e+00 4.47104979e+00 4.48455000e+00 4.49805021e+00 - 4.51154995e+00 4.52505016e+00 4.53854990e+00 4.55205011e+00 - 4.56554985e+00 4.57905006e+00 4.59254980e+00 4.60605001e+00 - 4.61955023e+00 4.63304996e+00 4.64655018e+00 4.66004992e+00 - 4.67355013e+00 4.68704987e+00 4.70055008e+00 4.71404982e+00 - 4.72755003e+00 4.74104977e+00 4.75454998e+00 4.76805019e+00 - 4.78154993e+00 4.79505014e+00 4.80854988e+00 4.82205009e+00 - 4.83554983e+00 4.84905005e+00 4.86254978e+00 4.87605000e+00 - 4.88955021e+00 4.90304995e+00 4.91655016e+00 4.93004990e+00 - 4.94355011e+00 4.95704985e+00 4.97055006e+00 4.98404980e+00 - 4.99755001e+00 5.01105022e+00 5.02454996e+00 5.03805017e+00 - 5.05154991e+00 5.06505013e+00 5.07854986e+00 5.09205008e+00 - 5.10554981e+00 5.11905003e+00 5.13254976e+00 5.14604998e+00 - 5.15955019e+00 5.17304993e+00 5.18655014e+00 5.20004988e+00 - 5.21355009e+00 5.22704983e+00 5.24055004e+00 5.25404978e+00 - 5.26754999e+00 5.28105021e+00 5.29454994e+00 5.30805016e+00 - 5.32154989e+00 5.33505011e+00 5.34854984e+00 5.36205006e+00 - 5.37554979e+00 5.38905001e+00 5.40255022e+00 5.41604996e+00 - 5.42955017e+00 5.44304991e+00 5.45655012e+00 5.47004986e+00 - 5.48355007e+00 5.49704981e+00 5.51055002e+00 5.52405024e+00 - 5.53754997e+00 5.55105019e+00 5.56454992e+00 5.57805014e+00 - 5.59154987e+00 5.60505009e+00 5.61854982e+00 5.63205004e+00 - 5.64554977e+00 5.65904999e+00 5.67255020e+00 5.68604994e+00 - 5.69955015e+00 5.71304989e+00 5.72655010e+00 5.74004984e+00 - 5.75355005e+00 5.76704979e+00 5.78055000e+00 5.79405022e+00 - 5.80754995e+00 5.82105017e+00 5.83454990e+00 5.84805012e+00 - 5.86154985e+00 5.87505007e+00 5.88854980e+00 5.90205002e+00 - 5.91555023e+00 5.92904997e+00 5.94255018e+00 5.95604992e+00 - 5.96955013e+00 5.98304987e+00 5.99655008e+00 6.01004982e+00 - 6.02355003e+00 6.03704977e+00 6.05054998e+00 6.06405020e+00 - 6.07754993e+00 6.09105015e+00 6.10454988e+00 6.11805010e+00 - 6.13154984e+00 6.14505005e+00 6.15854979e+00 6.17205000e+00 - 6.18555021e+00 6.19904995e+00 6.21255016e+00 6.22604990e+00 - 6.23955011e+00 6.25304985e+00 6.26655006e+00 6.28004980e+00 - 6.29355001e+00 6.30705023e+00 6.32054996e+00 6.33405018e+00 - 6.34754992e+00 6.36105013e+00 6.37454987e+00 6.38805008e+00 - 6.40154982e+00 6.41505003e+00 6.42854977e+00 6.44204998e+00 - 6.45555019e+00 6.46904993e+00 6.48255014e+00 6.49604988e+00 - 6.50955009e+00 6.52304983e+00 6.53655005e+00 6.55004978e+00 - 6.56355000e+00 6.57705021e+00 6.59054995e+00 6.60405016e+00 - 6.61754990e+00 6.63105011e+00 6.64454985e+00 6.65805006e+00 - 6.67154980e+00 6.68505001e+00 6.69855022e+00 6.71204996e+00 - 6.72555017e+00 6.73904991e+00 6.75255013e+00 6.76604986e+00 - 6.77955008e+00 6.79304981e+00 6.80655003e+00 6.82004976e+00 - 6.83354998e+00 6.84705019e+00 6.86054993e+00 6.87405014e+00 - 6.88754988e+00 6.90105009e+00 6.91454983e+00 6.92805004e+00 - 6.94154978e+00 6.95504999e+00 6.96855021e+00 6.98204994e+00 - 6.99555016e+00 7.00904989e+00 7.02255011e+00 7.03604984e+00 - 7.04955006e+00 7.06304979e+00 7.07655001e+00 7.09005022e+00 - 7.10354996e+00 7.11705017e+00 7.13054991e+00 7.14405012e+00 - 7.15782690e+00 7.17216969e+00 7.18710089e+00 7.20264530e+00 - 7.21882725e+00 7.23567390e+00 7.25321150e+00 7.27146959e+00 - 7.29047680e+00 7.31026411e+00 7.33086348e+00 7.35230875e+00 - 7.37463427e+00 7.39787626e+00 7.42207193e+00 7.44726086e+00 - 7.47348356e+00 7.50078297e+00 7.52920294e+00 7.55878925e+00 - 7.58959007e+00 7.62330008e+00 7.65929985e+00 7.69530010e+00 - 7.73129988e+00 7.76730013e+00 7.80329990e+00 7.83930016e+00 - 7.87529993e+00 7.91130018e+00 7.94729996e+00 7.98330021e+00 - 8.01930046e+00 8.05529976e+00 8.09130001e+00 8.12730026e+00 - 8.16329956e+00 8.19929981e+00 8.23530006e+00 8.27130032e+00 - 8.30729961e+00 8.34329987e+00 8.37930012e+00 8.41530037e+00 - 8.45129967e+00 8.48729992e+00 8.52330017e+00 8.55930042e+00 - 8.59529972e+00 8.63129997e+00 8.66730022e+00 8.70330048e+00 - 8.73929977e+00 8.77530003e+00 8.81130028e+00 8.84729958e+00 - 8.88329983e+00 8.91930008e+00 8.95530033e+00 8.99129963e+00] + data: [[100008. 100008. 100007. ... 100871. 100875. 100876.] + [100007. 100007. 100006. ... 100874. 100877. 100878.] + [100008. 100007. 100007. ... 100876. 100880. 100880.] + ... + [102193. 102201. 102208. ... 101695. 101671. 101671.] + [102199. 102206. 102213. ... 101706. 101689. 101686.] + [102204. 102211. 102218. ... 101727. 101707. 101701.]] + x: [353.0525 353.0885 353.1245 353.1605 353.1965 353.2325 353.2685 + 353.3045 353.3405 353.3765 353.4125 353.4485 353.4845 353.5205 + 353.5565 353.5925 353.6285 353.6645 353.7005 353.7365 353.7725 + 353.8085 353.8445 353.8805 353.9165 353.9525 353.9885 354.0245 + 354.0605 354.0965 354.1325 354.1685 354.2045 354.2405 354.2765 + 354.3125 354.3485 354.3845 354.4205 354.4565 354.4925 354.52185 + 354.5501 354.57736 354.60364 354.62894 354.65332 354.67685 354.6995 + 354.7213 354.74234 354.76263 354.78217 354.801 354.81915 354.83664 + 354.8535 354.86972 354.88538 354.90045 354.91498 354.929 354.9425 + 354.956 354.9695 354.983 354.9965 355.01 355.0235 355.037 + 355.0505 355.064 355.0775 355.091 355.1045 355.118 355.1315 + 355.145 355.1585 355.172 355.1855 355.199 355.2125 355.226 + 355.2395 355.253 355.2665 355.28 355.2935 355.307 355.3205 + 355.334 355.3475 355.361 355.3745 355.388 355.4015 355.415 + 355.4285 355.442 355.4555 355.469 355.4825 355.496 355.5095 + 355.523 355.5365 355.55 355.5635 355.577 355.5905 355.604 + 355.6175 355.631 355.6445 355.658 355.6715 355.685 355.6985 + 355.712 355.7255 355.739 355.7525 355.766 355.7795 355.793 + 355.8065 355.82 355.8335 355.847 355.8605 355.874 355.8875 + 355.901 355.9145 355.928 355.9415 355.955 355.9685 355.982 + 355.9955 356.009 356.0225 356.036 356.0495 356.063 356.0765 + 356.09 356.1035 356.117 356.1305 356.144 356.1575 356.171 + 356.1845 356.198 356.2115 356.225 356.2385 356.252 356.2655 + 356.279 356.2925 356.306 356.3195 356.333 356.3465 356.36 + 356.3735 356.387 356.4005 356.414 356.4275 356.441 356.4545 + 356.468 356.4815 356.495 356.5085 356.522 356.5355 356.549 + 356.5625 356.576 356.5895 356.603 356.6165 356.63 356.6435 + 356.657 356.6705 356.684 356.6975 356.711 356.7245 356.738 + 356.7515 356.765 356.7785 356.792 356.8055 356.819 356.8325 + 356.846 356.8595 356.873 356.8865 356.9 356.9135 356.927 + 356.9405 356.954 356.9675 356.981 356.9945 357.008 357.0215 + 357.035 357.0485 357.062 357.0755 357.089 357.1025 357.116 + 357.1295 357.143 357.1565 357.17 357.1835 357.197 357.2105 + 357.224 357.2375 357.251 357.2645 357.278 357.2915 357.305 + 357.3185 357.332 357.3455 357.359 357.3725 357.386 357.3995 + 357.413 357.4265 357.44 357.4535 357.467 357.4805 357.494 + 357.5075 357.521 357.5345 357.548 357.5615 357.575 357.5885 + 357.602 357.6155 357.629 357.6425 357.656 357.6695 357.683 + 357.6965 357.71 357.7235 357.737 357.7505 357.764 357.7775 + 357.791 357.8045 357.818 357.8315 357.845 357.8585 357.872 + 357.8855 357.899 357.9125 357.926 357.9395 357.953 357.9665 + 357.98 357.9935 358.007 358.0205 358.034 358.0475 358.061 + 358.0745 358.088 358.1015 358.115 358.1285 358.142 358.1555 + 358.169 358.1825 358.196 358.2095 358.223 358.2365 358.25 + 358.2635 358.277 358.2905 358.304 358.3175 358.331 358.3445 + 358.358 358.3715 358.385 358.3985 358.412 358.4255 358.439 + 358.4525 358.466 358.4795 358.493 358.5065 358.52 358.5335 + 358.547 358.5605 358.574 358.5875 358.601 358.6145 358.628 + 358.6415 358.655 358.6685 358.682 358.6955 358.709 358.7225 + 358.736 358.7495 358.763 358.7765 358.79 358.8035 358.817 + 358.8305 358.844 358.8575 358.871 358.8845 358.898 358.9115 + 358.925 358.9385 358.952 358.9655 358.979 358.9925 359.006 + 359.0195 359.033 359.0465 359.06 359.0735 359.087 359.1005 + 359.114 359.1275 359.141 359.1545 359.168 359.1815 359.195 + 359.2085 359.222 359.2355 359.249 359.2625 359.276 359.2895 + 359.303 359.3165 359.33 359.3435 359.357 359.3705 359.384 + 359.3975 359.411 359.4245 359.438 359.4515 359.465 359.4785 + 359.492 359.5055 359.519 359.5325 359.546 359.5595 359.573 + 359.5865 359.6 359.6135 359.627 359.6405 359.654 359.6675 + 359.681 359.6945 359.708 359.7215 359.735 359.7485 359.762 + 359.7755 359.789 359.8025 359.816 359.8295 359.843 359.8565 + 359.87 359.8835 359.897 359.9105 359.924 359.9375 359.951 + 359.9645 359.978 359.9915 360.005 360.0185 360.032 360.0455 + 360.059 360.0725 360.086 360.0995 360.113 360.1265 360.14 + 360.1535 360.167 360.1805 360.194 360.2075 360.221 360.2345 + 360.248 360.2615 360.275 360.2885 360.302 360.3155 360.329 + 360.3425 360.356 360.3695 360.383 360.3965 360.41 360.4235 + 360.437 360.4505 360.464 360.4775 360.491 360.5045 360.518 + 360.5315 360.545 360.5585 360.572 360.5855 360.599 360.6125 + 360.626 360.6395 360.653 360.6665 360.68 360.6935 360.707 + 360.7205 360.734 360.7475 360.761 360.7745 360.788 360.8015 + 360.815 360.8285 360.842 360.8555 360.869 360.8825 360.896 + 360.9095 360.923 360.9365 360.95 360.9635 360.977 360.9905 + 361.004 361.0175 361.031 361.0445 361.058 361.0715 361.085 + 361.0985 361.112 361.1255 361.139 361.1525 361.166 361.1795 + 361.193 361.2065 361.22 361.2335 361.247 361.2605 361.274 + 361.2875 361.301 361.3145 361.328 361.3415 361.355 361.3685 + 361.382 361.3955 361.409 361.4225 361.436 361.4495 361.463 + 361.4765 361.49 361.5035 361.517 361.5305 361.544 361.5575 + 361.571 361.5845 361.598 361.6115 361.625 361.6385 361.652 + 361.6655 361.679 361.6925 361.706 361.7195 361.733 361.7465 + 361.76 361.7735 361.787 361.8005 361.814 361.8275 361.841 + 361.8545 361.868 361.8815 361.895 361.9085 361.922 361.9355 + 361.949 361.9625 361.976 361.9895 362.003 362.0165 362.03 + 362.0435 362.057 362.0705 362.084 362.0975 362.111 362.1245 + 362.138 362.1515 362.165 362.1785 362.192 362.2055 362.219 + 362.2325 362.246 362.2595 362.273 362.2865 362.3 362.3135 + 362.327 362.3405 362.354 362.3675 362.381 362.3945 362.408 + 362.4215 362.435 362.4485 362.462 362.4755 362.489 362.5025 + 362.516 362.5295 362.543 362.5565 362.57 362.5835 362.597 + 362.6105 362.624 362.6375 362.651 362.6645 362.678 362.6915 + 362.705 362.7185 362.732 362.7455 362.759 362.7725 362.786 + 362.7995 362.813 362.8265 362.84 362.8535 362.867 362.8805 + 362.894 362.9075 362.921 362.9345 362.948 362.9615 362.975 + 362.9885 363.002 363.0155 363.029 363.0425 363.056 363.0695 + 363.083 363.0965 363.11 363.1235 363.137 363.1505 363.164 + 363.1775 363.191 363.2045 363.218 363.2315 363.245 363.2585 + 363.272 363.2855 363.299 363.3125 363.3265 363.34103 363.35614 + 363.37177 363.38803 363.40488 363.42236 363.4405 363.45932 363.47888 + 363.49915 363.52017 363.54202 363.56467 363.58817 363.61255 363.63788 + 363.66412 363.69138 363.71967 363.749 363.785 363.821 363.857 + 363.893 363.929 363.965 364.001 364.037 364.073 364.109 + 364.145 364.181 364.217 364.253 364.289 364.325 364.361 + 364.397 364.433 364.469 364.505 364.541 364.577 364.613 + 364.649 364.685 364.721 364.757 364.793 364.829 364.865 + 364.901 364.937 364.973 365.009 365.045 365.081 365.117 + 365.153 365.189 ] + x_lower_bound: [353.0345 353.0705 353.1065 353.1425 353.1785 353.2145 353.2505 + 353.2865 353.3225 353.3585 353.3945 353.4305 353.4665 353.5025 + 353.5385 353.5745 353.6105 353.6465 353.6825 353.7185 353.7545 + 353.7905 353.8265 353.8625 353.8985 353.9345 353.9705 354.0065 + 354.0425 354.0785 354.1145 354.1505 354.1865 354.2225 354.2585 + 354.2945 354.3305 354.3665 354.4025 354.4385 354.4745 354.50717 + 354.53598 354.56375 354.5905 354.61627 354.64114 354.66507 354.68817 + 354.7104 354.73184 354.7525 354.7724 354.7916 354.81006 354.82788 + 354.84506 354.8616 354.87753 354.8929 354.9077 354.922 354.93576 + 354.94925 354.96274 354.97626 354.98975 355.00323 355.01675 355.03024 + 355.04376 355.05725 355.07074 355.08426 355.09775 355.11124 355.12476 + 355.13824 355.15176 355.16525 355.17874 355.19226 355.20575 355.21924 + 355.23276 355.24625 355.25974 355.27325 355.28674 355.30026 355.31375 + 355.32724 355.34076 355.35425 355.36774 355.38126 355.39474 355.40826 + 355.42175 355.43524 355.44876 355.46225 355.47574 355.48926 355.50275 + 355.51624 355.52975 355.54324 355.55676 355.57025 355.58374 355.59726 + 355.61075 355.62424 355.63776 355.65125 355.66476 355.67825 355.69174 + 355.70526 355.71875 355.73224 355.74576 355.75925 355.77274 355.78625 + 355.79974 355.81326 355.82675 355.84024 355.85376 355.86725 355.88074 + 355.89426 355.90775 355.92126 355.93475 355.94824 355.96176 355.97525 + 355.98874 356.00226 356.01575 356.02924 356.04276 356.05624 356.06976 + 356.08325 356.09674 356.11026 356.12375 356.13724 356.15076 356.16425 + 356.17776 356.19125 356.20474 356.21826 356.23175 356.24524 356.25876 + 356.27225 356.28574 356.29926 356.31274 356.32626 356.33975 356.35324 + 356.36676 356.38025 356.39374 356.40726 356.42075 356.43427 356.44775 + 356.46124 356.47476 356.48825 356.50174 356.51526 356.52875 356.54224 + 356.55576 356.56924 356.58276 356.59625 356.60974 356.62326 356.63675 + 356.65024 356.66376 356.67725 356.69073 356.70425 356.71774 356.73126 + 356.74475 356.75824 356.77176 356.78525 356.79874 356.81226 356.82574 + 356.83926 356.85275 356.86624 356.87976 356.89325 356.90674 356.92026 + 356.93375 356.94724 356.96075 356.97424 356.98776 357.00125 357.01474 + 357.02826 357.04175 357.05524 357.06876 357.08224 357.09576 357.10925 + 357.12274 357.13626 357.14975 357.16324 357.17676 357.19025 357.20374 + 357.21725 357.23074 357.24426 357.25775 357.27124 357.28476 357.29825 + 357.31174 357.32526 357.33875 357.35226 357.36575 357.37924 357.39276 + 357.40625 357.41974 357.43326 357.44675 357.46024 357.47375 357.48724 + 357.50076 357.51425 357.52774 357.54126 357.55475 357.56824 357.58176 + 357.59525 357.60876 357.62225 357.63574 357.64926 357.66275 357.67624 + 357.68976 357.70325 357.71674 357.73026 357.74374 357.75726 357.77075 + 357.78424 357.79776 357.81125 357.82474 357.83826 357.85175 357.86526 + 357.87875 357.89224 357.90576 357.91925 357.93274 357.94626 357.95975 + 357.97324 357.98676 358.00024 358.01376 358.02725 358.04074 358.05426 + 358.06775 358.08124 358.09476 358.10825 358.12177 358.13525 358.14874 + 358.16226 358.17575 358.18924 358.20276 358.21625 358.22974 358.24326 + 358.25674 358.27026 358.28375 358.29724 358.31076 358.32425 358.33774 + 358.35126 358.36475 358.37823 358.39175 358.40524 358.41876 358.43225 + 358.44574 358.45926 358.47275 358.48624 358.49976 358.51324 358.52676 + 358.54025 358.55374 358.56726 358.58075 358.59424 358.60776 358.62125 + 358.63474 358.64825 358.66174 358.67526 358.68875 358.70224 358.71576 + 358.72925 358.74274 358.75626 358.76974 358.78326 358.79675 358.81024 + 358.82376 358.83725 358.85074 358.86426 358.87775 358.89124 358.90475 + 358.91824 358.93176 358.94525 358.95874 358.97226 358.98575 358.99924 + 359.01276 359.02625 359.03976 359.05325 359.06674 359.08026 359.09375 + 359.10724 359.12076 359.13425 359.14774 359.16125 359.17474 359.18826 + 359.20175 359.21524 359.22876 359.24225 359.25574 359.26926 359.28275 + 359.29626 359.30975 359.32324 359.33676 359.35025 359.36374 359.37726 + 359.39075 359.40424 359.41776 359.43124 359.44476 359.45825 359.47174 + 359.48526 359.49875 359.51224 359.52576 359.53925 359.55276 359.56625 + 359.57974 359.59326 359.60675 359.62024 359.63376 359.64725 359.66074 + 359.67426 359.68774 359.70126 359.71475 359.72824 359.74176 359.75525 + 359.76874 359.78226 359.79575 359.80927 359.82275 359.83624 359.84976 + 359.86325 359.87674 359.89026 359.90375 359.91724 359.93076 359.94424 + 359.95776 359.97125 359.98474 359.99826 360.01175 360.02524 360.03876 + 360.05225 360.06573 360.07925 360.09274 360.10626 360.11975 360.13324 + 360.14676 360.16025 360.17374 360.18726 360.20074 360.21426 360.22775 + 360.24124 360.25476 360.26825 360.28174 360.29526 360.30875 360.32224 + 360.33575 360.34924 360.36276 360.37625 360.38974 360.40326 360.41675 + 360.43024 360.44376 360.45724 360.47076 360.48425 360.49774 360.51126 + 360.52475 360.53824 360.55176 360.56525 360.57874 360.59225 360.60574 + 360.61926 360.63275 360.64624 360.65976 360.67325 360.68674 360.70026 + 360.71375 360.72726 360.74075 360.75424 360.76776 360.78125 360.79474 + 360.80826 360.82175 360.83524 360.84875 360.86224 360.87576 360.88925 + 360.90274 360.91626 360.92975 360.94324 360.95676 360.97025 360.98376 + 360.99725 361.01074 361.02426 361.03775 361.05124 361.06476 361.07825 + 361.09174 361.10526 361.11874 361.13226 361.14575 361.15924 361.17276 + 361.18625 361.19974 361.21326 361.22675 361.24026 361.25375 361.26724 + 361.28076 361.29425 361.30774 361.32126 361.33475 361.34824 361.36176 + 361.37524 361.38876 361.40225 361.41574 361.42926 361.44275 361.45624 + 361.46976 361.48325 361.49677 361.51025 361.52374 361.53726 361.55075 + 361.56424 361.57776 361.59125 361.60474 361.61826 361.63174 361.64526 + 361.65875 361.67224 361.68576 361.69925 361.71274 361.72626 361.73975 + 361.75323 361.76675 361.78024 361.79376 361.80725 361.82074 361.83426 + 361.84775 361.86124 361.87476 361.88824 361.90176 361.91525 361.92874 + 361.94226 361.95575 361.96924 361.98276 361.99625 362.00974 362.02325 + 362.03674 362.05026 362.06375 362.07724 362.09076 362.10425 362.11774 + 362.13126 362.14474 362.15826 362.17175 362.18524 362.19876 362.21225 + 362.22574 362.23926 362.25275 362.26624 362.27975 362.29324 362.30676 + 362.32025 362.33374 362.34726 362.36075 362.37424 362.38776 362.40125 + 362.41476 362.42825 362.44174 362.45526 362.46875 362.48224 362.49576 + 362.50925 362.52274 362.53625 362.54974 362.56326 362.57675 362.59024 + 362.60376 362.61725 362.63074 362.64426 362.65775 362.67126 362.68475 + 362.69824 362.71176 362.72525 362.73874 362.75226 362.76575 362.77924 + 362.79276 362.80624 362.81976 362.83325 362.84674 362.86026 362.87375 + 362.88724 362.90076 362.91425 362.92776 362.94125 362.95474 362.96826 + 362.98175 362.99524 363.00876 363.02225 363.03574 363.04926 363.06274 + 363.07626 363.08975 363.10324 363.11676 363.13025 363.14374 363.15726 + 363.17075 363.18427 363.19775 363.21124 363.22476 363.23825 363.25174 + 363.26526 363.27875 363.29224 363.30576 363.31952 363.33377 363.34857 + 363.36395 363.3799 363.39645 363.4136 363.43143 363.44992 363.46912 + 363.489 363.50967 363.5311 363.55334 363.57642 363.60037 363.6252 + 363.651 363.67776 363.7055 363.7343 363.767 363.803 363.839 + 363.875 363.911 363.947 363.983 364.019 364.055 364.091 + 364.127 364.163 364.199 364.235 364.271 364.307 364.343 + 364.379 364.415 364.451 364.487 364.523 364.559 364.595 + 364.631 364.667 364.703 364.739 364.775 364.811 364.847 + 364.883 364.919 364.955 364.991 365.027 365.063 365.099 + 365.135 365.171 ] + x_upper_bound: [353.0705 353.1065 353.1425 353.1785 353.2145 353.2505 353.2865 + 353.3225 353.3585 353.3945 353.4305 353.4665 353.5025 353.5385 + 353.5745 353.6105 353.6465 353.6825 353.7185 353.7545 353.7905 + 353.8265 353.8625 353.8985 353.9345 353.9705 354.0065 354.0425 + 354.0785 354.1145 354.1505 354.1865 354.2225 354.2585 354.2945 + 354.3305 354.3665 354.4025 354.4385 354.4745 354.50717 354.53598 + 354.56375 354.5905 354.61627 354.64114 354.66507 354.68817 354.7104 + 354.73184 354.7525 354.7724 354.7916 354.81006 354.82788 354.84506 + 354.8616 354.87753 354.8929 354.9077 354.922 354.93576 354.94925 + 354.96274 354.97626 354.98975 355.00323 355.01675 355.03024 355.04376 + 355.05725 355.07074 355.08426 355.09775 355.11124 355.12476 355.13824 + 355.15176 355.16525 355.17874 355.19226 355.20575 355.21924 355.23276 + 355.24625 355.25974 355.27325 355.28674 355.30026 355.31375 355.32724 + 355.34076 355.35425 355.36774 355.38126 355.39474 355.40826 355.42175 + 355.43524 355.44876 355.46225 355.47574 355.48926 355.50275 355.51624 + 355.52975 355.54324 355.55676 355.57025 355.58374 355.59726 355.61075 + 355.62424 355.63776 355.65125 355.66476 355.67825 355.69174 355.70526 + 355.71875 355.73224 355.74576 355.75925 355.77274 355.78625 355.79974 + 355.81326 355.82675 355.84024 355.85376 355.86725 355.88074 355.89426 + 355.90775 355.92126 355.93475 355.94824 355.96176 355.97525 355.98874 + 356.00226 356.01575 356.02924 356.04276 356.05624 356.06976 356.08325 + 356.09674 356.11026 356.12375 356.13724 356.15076 356.16425 356.17776 + 356.19125 356.20474 356.21826 356.23175 356.24524 356.25876 356.27225 + 356.28574 356.29926 356.31274 356.32626 356.33975 356.35324 356.36676 + 356.38025 356.39374 356.40726 356.42075 356.43427 356.44775 356.46124 + 356.47476 356.48825 356.50174 356.51526 356.52875 356.54224 356.55576 + 356.56924 356.58276 356.59625 356.60974 356.62326 356.63675 356.65024 + 356.66376 356.67725 356.69073 356.70425 356.71774 356.73126 356.74475 + 356.75824 356.77176 356.78525 356.79874 356.81226 356.82574 356.83926 + 356.85275 356.86624 356.87976 356.89325 356.90674 356.92026 356.93375 + 356.94724 356.96075 356.97424 356.98776 357.00125 357.01474 357.02826 + 357.04175 357.05524 357.06876 357.08224 357.09576 357.10925 357.12274 + 357.13626 357.14975 357.16324 357.17676 357.19025 357.20374 357.21725 + 357.23074 357.24426 357.25775 357.27124 357.28476 357.29825 357.31174 + 357.32526 357.33875 357.35226 357.36575 357.37924 357.39276 357.40625 + 357.41974 357.43326 357.44675 357.46024 357.47375 357.48724 357.50076 + 357.51425 357.52774 357.54126 357.55475 357.56824 357.58176 357.59525 + 357.60876 357.62225 357.63574 357.64926 357.66275 357.67624 357.68976 + 357.70325 357.71674 357.73026 357.74374 357.75726 357.77075 357.78424 + 357.79776 357.81125 357.82474 357.83826 357.85175 357.86526 357.87875 + 357.89224 357.90576 357.91925 357.93274 357.94626 357.95975 357.97324 + 357.98676 358.00024 358.01376 358.02725 358.04074 358.05426 358.06775 + 358.08124 358.09476 358.10825 358.12177 358.13525 358.14874 358.16226 + 358.17575 358.18924 358.20276 358.21625 358.22974 358.24326 358.25674 + 358.27026 358.28375 358.29724 358.31076 358.32425 358.33774 358.35126 + 358.36475 358.37823 358.39175 358.40524 358.41876 358.43225 358.44574 + 358.45926 358.47275 358.48624 358.49976 358.51324 358.52676 358.54025 + 358.55374 358.56726 358.58075 358.59424 358.60776 358.62125 358.63474 + 358.64825 358.66174 358.67526 358.68875 358.70224 358.71576 358.72925 + 358.74274 358.75626 358.76974 358.78326 358.79675 358.81024 358.82376 + 358.83725 358.85074 358.86426 358.87775 358.89124 358.90475 358.91824 + 358.93176 358.94525 358.95874 358.97226 358.98575 358.99924 359.01276 + 359.02625 359.03976 359.05325 359.06674 359.08026 359.09375 359.10724 + 359.12076 359.13425 359.14774 359.16125 359.17474 359.18826 359.20175 + 359.21524 359.22876 359.24225 359.25574 359.26926 359.28275 359.29626 + 359.30975 359.32324 359.33676 359.35025 359.36374 359.37726 359.39075 + 359.40424 359.41776 359.43124 359.44476 359.45825 359.47174 359.48526 + 359.49875 359.51224 359.52576 359.53925 359.55276 359.56625 359.57974 + 359.59326 359.60675 359.62024 359.63376 359.64725 359.66074 359.67426 + 359.68774 359.70126 359.71475 359.72824 359.74176 359.75525 359.76874 + 359.78226 359.79575 359.80927 359.82275 359.83624 359.84976 359.86325 + 359.87674 359.89026 359.90375 359.91724 359.93076 359.94424 359.95776 + 359.97125 359.98474 359.99826 360.01175 360.02524 360.03876 360.05225 + 360.06573 360.07925 360.09274 360.10626 360.11975 360.13324 360.14676 + 360.16025 360.17374 360.18726 360.20074 360.21426 360.22775 360.24124 + 360.25476 360.26825 360.28174 360.29526 360.30875 360.32224 360.33575 + 360.34924 360.36276 360.37625 360.38974 360.40326 360.41675 360.43024 + 360.44376 360.45724 360.47076 360.48425 360.49774 360.51126 360.52475 + 360.53824 360.55176 360.56525 360.57874 360.59225 360.60574 360.61926 + 360.63275 360.64624 360.65976 360.67325 360.68674 360.70026 360.71375 + 360.72726 360.74075 360.75424 360.76776 360.78125 360.79474 360.80826 + 360.82175 360.83524 360.84875 360.86224 360.87576 360.88925 360.90274 + 360.91626 360.92975 360.94324 360.95676 360.97025 360.98376 360.99725 + 361.01074 361.02426 361.03775 361.05124 361.06476 361.07825 361.09174 + 361.10526 361.11874 361.13226 361.14575 361.15924 361.17276 361.18625 + 361.19974 361.21326 361.22675 361.24026 361.25375 361.26724 361.28076 + 361.29425 361.30774 361.32126 361.33475 361.34824 361.36176 361.37524 + 361.38876 361.40225 361.41574 361.42926 361.44275 361.45624 361.46976 + 361.48325 361.49677 361.51025 361.52374 361.53726 361.55075 361.56424 + 361.57776 361.59125 361.60474 361.61826 361.63174 361.64526 361.65875 + 361.67224 361.68576 361.69925 361.71274 361.72626 361.73975 361.75323 + 361.76675 361.78024 361.79376 361.80725 361.82074 361.83426 361.84775 + 361.86124 361.87476 361.88824 361.90176 361.91525 361.92874 361.94226 + 361.95575 361.96924 361.98276 361.99625 362.00974 362.02325 362.03674 + 362.05026 362.06375 362.07724 362.09076 362.10425 362.11774 362.13126 + 362.14474 362.15826 362.17175 362.18524 362.19876 362.21225 362.22574 + 362.23926 362.25275 362.26624 362.27975 362.29324 362.30676 362.32025 + 362.33374 362.34726 362.36075 362.37424 362.38776 362.40125 362.41476 + 362.42825 362.44174 362.45526 362.46875 362.48224 362.49576 362.50925 + 362.52274 362.53625 362.54974 362.56326 362.57675 362.59024 362.60376 + 362.61725 362.63074 362.64426 362.65775 362.67126 362.68475 362.69824 + 362.71176 362.72525 362.73874 362.75226 362.76575 362.77924 362.79276 + 362.80624 362.81976 362.83325 362.84674 362.86026 362.87375 362.88724 + 362.90076 362.91425 362.92776 362.94125 362.95474 362.96826 362.98175 + 362.99524 363.00876 363.02225 363.03574 363.04926 363.06274 363.07626 + 363.08975 363.10324 363.11676 363.13025 363.14374 363.15726 363.17075 + 363.18427 363.19775 363.21124 363.22476 363.23825 363.25174 363.26526 + 363.27875 363.29224 363.30576 363.31952 363.33377 363.34857 363.36395 + 363.3799 363.39645 363.4136 363.43143 363.44992 363.46912 363.489 + 363.50967 363.5311 363.55334 363.57642 363.60037 363.6252 363.651 + 363.67776 363.7055 363.7343 363.767 363.803 363.839 363.875 + 363.911 363.947 363.983 364.019 364.055 364.091 364.127 + 364.163 364.199 364.235 364.271 364.307 364.343 364.379 + 364.415 364.451 364.487 364.523 364.559 364.595 364.631 + 364.667 364.703 364.739 364.775 364.811 364.847 364.883 + 364.919 364.955 364.991 365.027 365.063 365.099 365.135 + 365.171 365.207 ] + y: [-5.5932002e+00 -5.5572000e+00 -5.5212002e+00 -5.4851999e+00 + -5.4492002e+00 -5.4131999e+00 -5.3772001e+00 -5.3411999e+00 + -5.3052001e+00 -5.2691998e+00 -5.2332001e+00 -5.1971998e+00 + -5.1612000e+00 -5.1251998e+00 -5.0892000e+00 -5.0531998e+00 + -5.0172000e+00 -4.9812002e+00 -4.9452000e+00 -4.9092002e+00 + -4.8731999e+00 -4.8372002e+00 -4.8011999e+00 -4.7652001e+00 + -4.7291999e+00 -4.6932001e+00 -4.6571999e+00 -4.6212001e+00 + -4.5851998e+00 -4.5492001e+00 -4.5131998e+00 -4.4772000e+00 + -4.4411998e+00 -4.4052000e+00 -4.3692002e+00 -4.3332000e+00 + -4.2972002e+00 -4.2612000e+00 -4.2252002e+00 -4.1937799e+00 + -4.1635985e+00 -4.1346073e+00 -4.1067591e+00 -4.0800085e+00 + -4.0543132e+00 -4.0296307e+00 -4.0059214e+00 -3.9831471e+00 + -3.9612706e+00 -3.9402568e+00 -3.9200714e+00 -3.9006820e+00 + -3.8820570e+00 -3.8641663e+00 -3.8469810e+00 -3.8304734e+00 + -3.8146167e+00 -3.7993851e+00 -3.7847540e+00 -3.7707000e+00 + -3.7572000e+00 -3.7437000e+00 -3.7302001e+00 -3.7167001e+00 + -3.7032001e+00 -3.6896999e+00 -3.6761999e+00 -3.6626999e+00 + -3.6492000e+00 -3.6357000e+00 -3.6222000e+00 -3.6087000e+00 + -3.5952001e+00 -3.5817001e+00 -3.5682001e+00 -3.5546999e+00 + -3.5411999e+00 -3.5276999e+00 -3.5142000e+00 -3.5007000e+00 + -3.4872000e+00 -3.4737000e+00 -3.4602001e+00 -3.4467001e+00 + -3.4331999e+00 -3.4196999e+00 -3.4061999e+00 -3.3927000e+00 + -3.3792000e+00 -3.3657000e+00 -3.3522000e+00 -3.3387001e+00 + -3.3252001e+00 -3.3117001e+00 -3.2981999e+00 -3.2846999e+00 + -3.2711999e+00 -3.2577000e+00 -3.2442000e+00 -3.2307000e+00 + -3.2172000e+00 -3.2037001e+00 -3.1902001e+00 -3.1767001e+00 + -3.1631999e+00 -3.1496999e+00 -3.1362000e+00 -3.1227000e+00 + -3.1092000e+00 -3.0957000e+00 -3.0822001e+00 -3.0687001e+00 + -3.0552001e+00 -3.0416999e+00 -3.0281999e+00 -3.0146999e+00 + -3.0012000e+00 -2.9877000e+00 -2.9742000e+00 -2.9607000e+00 + -2.9472001e+00 -2.9337001e+00 -2.9202001e+00 -2.9066999e+00 + -2.8931999e+00 -2.8796999e+00 -2.8662000e+00 -2.8527000e+00 + -2.8392000e+00 -2.8257000e+00 -2.8122001e+00 -2.7987001e+00 + -2.7852001e+00 -2.7716999e+00 -2.7581999e+00 -2.7447000e+00 + -2.7312000e+00 -2.7177000e+00 -2.7042000e+00 -2.6907001e+00 + -2.6772001e+00 -2.6637001e+00 -2.6501999e+00 -2.6366999e+00 + -2.6231999e+00 -2.6097000e+00 -2.5962000e+00 -2.5827000e+00 + -2.5692000e+00 -2.5557001e+00 -2.5422001e+00 -2.5287001e+00 + -2.5151999e+00 -2.5016999e+00 -2.4881999e+00 -2.4747000e+00 + -2.4612000e+00 -2.4477000e+00 -2.4342000e+00 -2.4207001e+00 + -2.4072001e+00 -2.3936999e+00 -2.3801999e+00 -2.3666999e+00 + -2.3532000e+00 -2.3397000e+00 -2.3262000e+00 -2.3127000e+00 + -2.2992001e+00 -2.2857001e+00 -2.2722001e+00 -2.2586999e+00 + -2.2451999e+00 -2.2316999e+00 -2.2182000e+00 -2.2047000e+00 + -2.1912000e+00 -2.1777000e+00 -2.1642001e+00 -2.1507001e+00 + -2.1372001e+00 -2.1236999e+00 -2.1101999e+00 -2.0967000e+00 + -2.0832000e+00 -2.0697000e+00 -2.0562000e+00 -2.0427001e+00 + -2.0292001e+00 -2.0157001e+00 -2.0021999e+00 -1.9887000e+00 + -1.9752001e+00 -1.9617000e+00 -1.9482000e+00 -1.9347000e+00 + -1.9212000e+00 -1.9076999e+00 -1.8942000e+00 -1.8807000e+00 + -1.8672000e+00 -1.8537000e+00 -1.8401999e+00 -1.8267000e+00 + -1.8132000e+00 -1.7997000e+00 -1.7862000e+00 -1.7727000e+00 + -1.7592000e+00 -1.7457000e+00 -1.7322000e+00 -1.7187001e+00 + -1.7052000e+00 -1.6917000e+00 -1.6782000e+00 -1.6647000e+00 + -1.6512001e+00 -1.6377000e+00 -1.6242000e+00 -1.6107000e+00 + -1.5972000e+00 -1.5836999e+00 -1.5702000e+00 -1.5567000e+00 + -1.5432000e+00 -1.5297000e+00 -1.5161999e+00 -1.5027000e+00 + -1.4892000e+00 -1.4757000e+00 -1.4622000e+00 -1.4487000e+00 + -1.4352000e+00 -1.4217000e+00 -1.4082000e+00 -1.3947001e+00 + -1.3812000e+00 -1.3677000e+00 -1.3542000e+00 -1.3407000e+00 + -1.3272001e+00 -1.3137000e+00 -1.3002000e+00 -1.2867000e+00 + -1.2732000e+00 -1.2596999e+00 -1.2462000e+00 -1.2327000e+00 + -1.2192000e+00 -1.2057000e+00 -1.1921999e+00 -1.1787000e+00 + -1.1652000e+00 -1.1517000e+00 -1.1382000e+00 -1.1247000e+00 + -1.1112000e+00 -1.0977000e+00 -1.0842000e+00 -1.0707000e+00 + -1.0572000e+00 -1.0437000e+00 -1.0302000e+00 -1.0167000e+00 + -1.0032001e+00 -9.8970002e-01 -9.7619998e-01 -9.6270001e-01 + -9.4919997e-01 -9.3570000e-01 -9.2220002e-01 -9.0869999e-01 + -8.9520001e-01 -8.8169998e-01 -8.6820000e-01 -8.5470003e-01 + -8.4119999e-01 -8.2770002e-01 -8.1419998e-01 -8.0070001e-01 + -7.8719997e-01 -7.7370000e-01 -7.6020002e-01 -7.4669999e-01 + -7.3320001e-01 -7.1969998e-01 -7.0620000e-01 -6.9270003e-01 + -6.7919999e-01 -6.6570002e-01 -6.5219998e-01 -6.3870001e-01 + -6.2519997e-01 -6.1170000e-01 -5.9820002e-01 -5.8469999e-01 + -5.7120001e-01 -5.5769998e-01 -5.4420000e-01 -5.3070003e-01 + -5.1719999e-01 -5.0370002e-01 -4.9020001e-01 -4.7670001e-01 + -4.6320000e-01 -4.4970000e-01 -4.3619999e-01 -4.2269999e-01 + -4.0920001e-01 -3.9570001e-01 -3.8220000e-01 -3.6870000e-01 + -3.5519999e-01 -3.4169999e-01 -3.2820001e-01 -3.1470001e-01 + -3.0120000e-01 -2.8770000e-01 -2.7419999e-01 -2.6069999e-01 + -2.4720000e-01 -2.3370001e-01 -2.2020000e-01 -2.0670000e-01 + -1.9320001e-01 -1.7970000e-01 -1.6620000e-01 -1.5270001e-01 + -1.3920000e-01 -1.2570000e-01 -1.1220000e-01 -9.8700002e-02 + -8.5199997e-02 -7.1699999e-02 -5.8200002e-02 -4.4700000e-02 + -3.1199999e-02 -1.7700000e-02 -4.1999999e-03 9.3000000e-03 + 2.2800000e-02 3.6300000e-02 4.9800001e-02 6.3299999e-02 + 7.6800004e-02 9.0300001e-02 1.0380000e-01 1.1730000e-01 + 1.3079999e-01 1.4430000e-01 1.5780000e-01 1.7129999e-01 + 1.8480000e-01 1.9830000e-01 2.1179999e-01 2.2530000e-01 + 2.3880000e-01 2.5229999e-01 2.6580000e-01 2.7930000e-01 + 2.9280001e-01 3.0630001e-01 3.1979999e-01 3.3329999e-01 + 3.4680000e-01 3.6030000e-01 3.7380001e-01 3.8730001e-01 + 4.0079999e-01 4.1429999e-01 4.2780000e-01 4.4130000e-01 + 4.5480001e-01 4.6830001e-01 4.8179999e-01 4.9529999e-01 + 5.0880003e-01 5.2230000e-01 5.3579998e-01 5.4930001e-01 + 5.6279999e-01 5.7630002e-01 5.8980000e-01 6.0329998e-01 + 6.1680001e-01 6.3029999e-01 6.4380002e-01 6.5730000e-01 + 6.7079997e-01 6.8430001e-01 6.9779998e-01 7.1130002e-01 + 7.2479999e-01 7.3830003e-01 7.5180000e-01 7.6529998e-01 + 7.7880001e-01 7.9229999e-01 8.0580002e-01 8.1930000e-01 + 8.3279997e-01 8.4630001e-01 8.5979998e-01 8.7330002e-01 + 8.8679999e-01 9.0030003e-01 9.1380000e-01 9.2729998e-01 + 9.4080001e-01 9.5429999e-01 9.6780002e-01 9.8130000e-01 + 9.9479997e-01 1.0082999e+00 1.0218000e+00 1.0353000e+00 + 1.0488000e+00 1.0623000e+00 1.0757999e+00 1.0893000e+00 + 1.1028000e+00 1.1163000e+00 1.1298000e+00 1.1433001e+00 + 1.1568000e+00 1.1703000e+00 1.1838000e+00 1.1973000e+00 + 1.2108001e+00 1.2243000e+00 1.2378000e+00 1.2513000e+00 + 1.2648000e+00 1.2783000e+00 1.2918000e+00 1.3053000e+00 + 1.3188000e+00 1.3322999e+00 1.3458000e+00 1.3593000e+00 + 1.3728000e+00 1.3863000e+00 1.3997999e+00 1.4133000e+00 + 1.4268000e+00 1.4403000e+00 1.4538000e+00 1.4673001e+00 + 1.4808000e+00 1.4943000e+00 1.5078000e+00 1.5213000e+00 + 1.5348001e+00 1.5483000e+00 1.5618000e+00 1.5753000e+00 + 1.5888000e+00 1.6023000e+00 1.6158000e+00 1.6293000e+00 + 1.6428000e+00 1.6562999e+00 1.6698000e+00 1.6833000e+00 + 1.6968000e+00 1.7103000e+00 1.7237999e+00 1.7373000e+00 + 1.7508000e+00 1.7643000e+00 1.7778000e+00 1.7913001e+00 + 1.8048000e+00 1.8183000e+00 1.8318000e+00 1.8453000e+00 + 1.8588001e+00 1.8723000e+00 1.8858000e+00 1.8993000e+00 + 1.9128000e+00 1.9263000e+00 1.9398000e+00 1.9533000e+00 + 1.9668000e+00 1.9802999e+00 1.9938000e+00 2.0072999e+00 + 2.0208001e+00 2.0343001e+00 2.0478001e+00 2.0613000e+00 + 2.0748000e+00 2.0883000e+00 2.1018000e+00 2.1152999e+00 + 2.1287999e+00 2.1422999e+00 2.1558001e+00 2.1693001e+00 + 2.1828001e+00 2.1963000e+00 2.2098000e+00 2.2233000e+00 + 2.2368000e+00 2.2502999e+00 2.2637999e+00 2.2772999e+00 + 2.2908001e+00 2.3043001e+00 2.3178000e+00 2.3313000e+00 + 2.3448000e+00 2.3583000e+00 2.3717999e+00 2.3852999e+00 + 2.3987999e+00 2.4123001e+00 2.4258001e+00 2.4393001e+00 + 2.4528000e+00 2.4663000e+00 2.4798000e+00 2.4933000e+00 + 2.5067999e+00 2.5202999e+00 2.5337999e+00 2.5473001e+00 + 2.5608001e+00 2.5743001e+00 2.5878000e+00 2.6013000e+00 + 2.6148000e+00 2.6283000e+00 2.6417999e+00 2.6552999e+00 + 2.6688001e+00 2.6823001e+00 2.6958001e+00 2.7093000e+00 + 2.7228000e+00 2.7363000e+00 2.7498000e+00 2.7632999e+00 + 2.7767999e+00 2.7902999e+00 2.8038001e+00 2.8173001e+00 + 2.8308001e+00 2.8443000e+00 2.8578000e+00 2.8713000e+00 + 2.8848000e+00 2.8982999e+00 2.9117999e+00 2.9252999e+00 + 2.9388001e+00 2.9523001e+00 2.9658000e+00 2.9793000e+00 + 2.9928000e+00 3.0063000e+00 3.0197999e+00 3.0332999e+00 + 3.0467999e+00 3.0603001e+00 3.0738001e+00 3.0873001e+00 + 3.1008000e+00 3.1143000e+00 3.1278000e+00 3.1413000e+00 + 3.1547999e+00 3.1682999e+00 3.1817999e+00 3.1953001e+00 + 3.2088001e+00 3.2223001e+00 3.2358000e+00 3.2493000e+00 + 3.2628000e+00 3.2763000e+00 3.2897999e+00 3.3032999e+00 + 3.3168001e+00 3.3303001e+00 3.3438001e+00 3.3573000e+00 + 3.3708000e+00 3.3843000e+00 3.3978000e+00 3.4112999e+00 + 3.4247999e+00 3.4382999e+00 3.4518001e+00 3.4653001e+00 + 3.4788001e+00 3.4923000e+00 3.5058000e+00 3.5193000e+00 + 3.5328000e+00 3.5462999e+00 3.5597999e+00 3.5732999e+00 + 3.5868001e+00 3.6003001e+00 3.6138000e+00 3.6273000e+00 + 3.6408000e+00 3.6543000e+00 3.6677999e+00 3.6812999e+00 + 3.6947999e+00 3.7083001e+00 3.7218001e+00 3.7353001e+00 + 3.7488000e+00 3.7623000e+00 3.7758000e+00 3.7893000e+00 + 3.8027999e+00 3.8162999e+00 3.8297999e+00 3.8433001e+00 + 3.8568001e+00 3.8703001e+00 3.8838000e+00 3.8973000e+00 + 3.9108000e+00 3.9243000e+00 3.9377999e+00 3.9512999e+00 + 3.9647999e+00 3.9783001e+00 3.9918001e+00 4.0053000e+00 + 4.0187998e+00 4.0323000e+00 4.0458002e+00 4.0592999e+00 + 4.0728002e+00 4.0862999e+00 4.0998001e+00 4.1132998e+00 + 4.1268001e+00 4.1402998e+00 4.1538000e+00 4.1673002e+00 + 4.1808000e+00 4.1943002e+00 4.2077999e+00 4.2213001e+00 + 4.2347999e+00 4.2483001e+00 4.2617998e+00 4.2753000e+00 + 4.2887998e+00 4.3023000e+00 4.3158002e+00 4.3292999e+00 + 4.3428001e+00 4.3562999e+00 4.3698001e+00 4.3832998e+00 + 4.3968000e+00 4.4102998e+00 4.4238000e+00 4.4373002e+00 + 4.4507999e+00 4.4643002e+00 4.4777999e+00 4.4913001e+00 + 4.5047998e+00 4.5183001e+00 4.5317998e+00 4.5453000e+00 + 4.5588002e+00 4.5723000e+00 4.5858002e+00 4.5992999e+00 + 4.6128001e+00 4.6262999e+00 4.6398001e+00 4.6532998e+00 + 4.6668000e+00 4.6803002e+00 4.6938000e+00 4.7073002e+00 + 4.7207999e+00 4.7343001e+00 4.7477999e+00 4.7613001e+00 + 4.7747998e+00 4.7883000e+00 4.8017998e+00 4.8153000e+00 + 4.8288002e+00 4.8422999e+00 4.8558002e+00 4.8692999e+00 + 4.8828001e+00 4.8962998e+00 4.9098001e+00 4.9232998e+00 + 4.9368000e+00 4.9503002e+00 4.9638000e+00 4.9773002e+00 + 4.9907999e+00 5.0043001e+00 5.0177999e+00 5.0313001e+00 + 5.0447998e+00 5.0583000e+00 5.0718002e+00 5.0853000e+00 + 5.0988002e+00 5.1122999e+00 5.1258001e+00 5.1392999e+00 + 5.1528001e+00 5.1662998e+00 5.1798000e+00 5.1932998e+00 + 5.2068000e+00 5.2203002e+00 5.2337999e+00 5.2473001e+00 + 5.2607999e+00 5.2743001e+00 5.2877998e+00 5.3013000e+00 + 5.3147998e+00 5.3283000e+00 5.3418002e+00 5.3552999e+00 + 5.3688002e+00 5.3822999e+00 5.3958001e+00 5.4092999e+00 + 5.4228001e+00 5.4362998e+00 5.4498000e+00 5.4633002e+00 + 5.4768000e+00 5.4903002e+00 5.5037999e+00 5.5173001e+00 + 5.5307999e+00 5.5443001e+00 5.5577998e+00 5.5713000e+00 + 5.5847998e+00 5.5983000e+00 5.6118002e+00 5.6252999e+00 + 5.6388001e+00 5.6522999e+00 5.6658001e+00 5.6792998e+00 + 5.6928000e+00 5.7062998e+00 5.7198000e+00 5.7333002e+00 + 5.7467999e+00 5.7603002e+00 5.7737999e+00 5.7873001e+00 + 5.8007998e+00 5.8143001e+00 5.8277998e+00 5.8413000e+00 + 5.8548002e+00 5.8683000e+00 5.8818002e+00 5.8952999e+00 + 5.9088001e+00 5.9222999e+00 5.9358001e+00 5.9492998e+00 + 5.9628000e+00 5.9762998e+00 5.9898000e+00 6.0033002e+00 + 6.0167999e+00 6.0303001e+00 6.0437999e+00 6.0573001e+00 + 6.0707998e+00 6.0843000e+00 6.0977998e+00 6.1113000e+00 + 6.1248002e+00 6.1382999e+00 6.1518002e+00 6.1652999e+00 + 6.1788001e+00 6.1922998e+00 6.2058001e+00 6.2192998e+00 + 6.2328000e+00 6.2463002e+00 6.2598000e+00 6.2733002e+00 + 6.2867999e+00 6.3003001e+00 6.3137999e+00 6.3273001e+00 + 6.3407998e+00 6.3543000e+00 6.3678002e+00 6.3813000e+00 + 6.3948002e+00 6.4082999e+00 6.4218001e+00 6.4352999e+00 + 6.4488001e+00 6.4622998e+00 6.4758000e+00 6.4892998e+00 + 6.5028000e+00 6.5163002e+00 6.5297999e+00 6.5433002e+00 + 6.5567999e+00 6.5703001e+00 6.5837998e+00 6.5973001e+00 + 6.6107998e+00 6.6243000e+00 6.6378002e+00 6.6513000e+00 + 6.6648002e+00 6.6782999e+00 6.6918001e+00 6.7052999e+00 + 6.7188001e+00 6.7322998e+00 6.7458000e+00 6.7593002e+00 + 6.7728000e+00 6.7863002e+00 6.7997999e+00 6.8133001e+00 + 6.8267999e+00 6.8403001e+00 6.8537998e+00 6.8673000e+00 + 6.8807998e+00 6.8943000e+00 6.9078002e+00 6.9212999e+00 + 6.9348001e+00 6.9482999e+00 6.9618001e+00 6.9752998e+00 + 6.9888000e+00 7.0022998e+00 7.0158000e+00 7.0293002e+00 + 7.0427999e+00 7.0563002e+00 7.0697999e+00 7.0833001e+00 + 7.0967999e+00 7.1103001e+00 7.1237998e+00 7.1373000e+00 + 7.1508002e+00 7.1648540e+00 7.1794853e+00 7.1947169e+00 + 7.2105737e+00 7.2270813e+00 7.2442665e+00 7.2621570e+00 + 7.2807817e+00 7.3001714e+00 7.3203568e+00 7.3413706e+00 + 7.3632469e+00 7.3860216e+00 7.4097309e+00 7.4344130e+00 + 7.4601088e+00 7.4868588e+00 7.5147071e+00 7.5436983e+00 + 7.5738797e+00 7.6052999e+00 7.6413002e+00 7.6773000e+00 + 7.7133002e+00 7.7493000e+00 7.7852998e+00 7.8213000e+00 + 7.8572998e+00 7.8933001e+00 7.9292998e+00 7.9653001e+00 + 8.0012999e+00 8.0373001e+00 8.0733004e+00 8.1092997e+00 + 8.1452999e+00 8.1813002e+00 8.2173004e+00 8.2532997e+00 + 8.2893000e+00 8.3253002e+00 8.3613005e+00 8.3972998e+00 + 8.4333000e+00 8.4693003e+00 8.5052996e+00 8.5412998e+00 + 8.5773001e+00 8.6133003e+00 8.6492996e+00 8.6852999e+00 + 8.7213001e+00 8.7573004e+00 8.7932997e+00 8.8292999e+00 + 8.8653002e+00 8.9013004e+00 8.9372997e+00 8.9733000e+00] + y_lower_bound: [-5.6112003e+00 -5.5752001e+00 -5.5391998e+00 -5.5032001e+00 + -5.4671998e+00 -5.4312000e+00 -5.3951998e+00 -5.3592000e+00 + -5.3232002e+00 -5.2872000e+00 -5.2512002e+00 -5.2151999e+00 + -5.1792002e+00 -5.1431999e+00 -5.1072001e+00 -5.0711999e+00 + -5.0352001e+00 -4.9991999e+00 -4.9632001e+00 -4.9271998e+00 + -4.8912001e+00 -4.8551998e+00 -4.8192000e+00 -4.7831998e+00 + -4.7472000e+00 -4.7112002e+00 -4.6752000e+00 -4.6392002e+00 + -4.6032000e+00 -4.5672002e+00 -4.5311999e+00 -4.4952002e+00 + -4.4591999e+00 -4.4232001e+00 -4.3871999e+00 -4.3512001e+00 + -4.3151999e+00 -4.2792001e+00 -4.2431998e+00 -4.2094898e+00 + -4.1786890e+00 -4.1491027e+00 -4.1206832e+00 -4.0933838e+00 + -4.0671611e+00 -4.0419717e+00 -4.0177760e+00 -3.9945343e+00 + -3.9722090e+00 -3.9507637e+00 -3.9301641e+00 -3.9103768e+00 + -3.8913693e+00 -3.8731117e+00 -3.8555737e+00 -3.8387272e+00 + -3.8225451e+00 -3.8070009e+00 -3.7920697e+00 -3.7777271e+00 + -3.7639501e+00 -3.7504499e+00 -3.7369499e+00 -3.7234499e+00 + -3.7099500e+00 -3.6964500e+00 -3.6829500e+00 -3.6694500e+00 + -3.6559501e+00 -3.6424501e+00 -3.6289501e+00 -3.6154499e+00 + -3.6019499e+00 -3.5884500e+00 -3.5749500e+00 -3.5614500e+00 + -3.5479500e+00 -3.5344501e+00 -3.5209501e+00 -3.5074501e+00 + -3.4939499e+00 -3.4804499e+00 -3.4669499e+00 -3.4534500e+00 + -3.4399500e+00 -3.4264500e+00 -3.4129500e+00 -3.3994501e+00 + -3.3859501e+00 -3.3724501e+00 -3.3589499e+00 -3.3454499e+00 + -3.3319499e+00 -3.3184500e+00 -3.3049500e+00 -3.2914500e+00 + -3.2779500e+00 -3.2644501e+00 -3.2509501e+00 -3.2374499e+00 + -3.2239499e+00 -3.2104499e+00 -3.1969500e+00 -3.1834500e+00 + -3.1699500e+00 -3.1564500e+00 -3.1429501e+00 -3.1294501e+00 + -3.1159501e+00 -3.1024499e+00 -3.0889499e+00 -3.0754499e+00 + -3.0619500e+00 -3.0484500e+00 -3.0349500e+00 -3.0214500e+00 + -3.0079501e+00 -2.9944501e+00 -2.9809501e+00 -2.9674499e+00 + -2.9539499e+00 -2.9404500e+00 -2.9269500e+00 -2.9134500e+00 + -2.8999500e+00 -2.8864501e+00 -2.8729501e+00 -2.8594501e+00 + -2.8459499e+00 -2.8324499e+00 -2.8189499e+00 -2.8054500e+00 + -2.7919500e+00 -2.7784500e+00 -2.7649500e+00 -2.7514501e+00 + -2.7379501e+00 -2.7244501e+00 -2.7109499e+00 -2.6974499e+00 + -2.6839499e+00 -2.6704500e+00 -2.6569500e+00 -2.6434500e+00 + -2.6299500e+00 -2.6164501e+00 -2.6029501e+00 -2.5894499e+00 + -2.5759499e+00 -2.5624499e+00 -2.5489500e+00 -2.5354500e+00 + -2.5219500e+00 -2.5084500e+00 -2.4949501e+00 -2.4814501e+00 + -2.4679501e+00 -2.4544499e+00 -2.4409499e+00 -2.4274499e+00 + -2.4139500e+00 -2.4004500e+00 -2.3869500e+00 -2.3734500e+00 + -2.3599501e+00 -2.3464501e+00 -2.3329501e+00 -2.3194499e+00 + -2.3059499e+00 -2.2924500e+00 -2.2789500e+00 -2.2654500e+00 + -2.2519500e+00 -2.2384501e+00 -2.2249501e+00 -2.2114501e+00 + -2.1979499e+00 -2.1844499e+00 -2.1709499e+00 -2.1574500e+00 + -2.1439500e+00 -2.1304500e+00 -2.1169500e+00 -2.1034501e+00 + -2.0899501e+00 -2.0764501e+00 -2.0629499e+00 -2.0494499e+00 + -2.0359499e+00 -2.0224500e+00 -2.0089500e+00 -1.9954500e+00 + -1.9819500e+00 -1.9684500e+00 -1.9549500e+00 -1.9414500e+00 + -1.9279500e+00 -1.9144500e+00 -1.9009500e+00 -1.8874500e+00 + -1.8739500e+00 -1.8604500e+00 -1.8469501e+00 -1.8334500e+00 + -1.8199500e+00 -1.8064500e+00 -1.7929500e+00 -1.7794501e+00 + -1.7659500e+00 -1.7524500e+00 -1.7389500e+00 -1.7254500e+00 + -1.7119499e+00 -1.6984500e+00 -1.6849500e+00 -1.6714500e+00 + -1.6579500e+00 -1.6444499e+00 -1.6309500e+00 -1.6174500e+00 + -1.6039500e+00 -1.5904500e+00 -1.5769500e+00 -1.5634500e+00 + -1.5499500e+00 -1.5364500e+00 -1.5229501e+00 -1.5094500e+00 + -1.4959500e+00 -1.4824500e+00 -1.4689500e+00 -1.4554501e+00 + -1.4419500e+00 -1.4284500e+00 -1.4149500e+00 -1.4014500e+00 + -1.3879499e+00 -1.3744500e+00 -1.3609500e+00 -1.3474500e+00 + -1.3339500e+00 -1.3204499e+00 -1.3069500e+00 -1.2934500e+00 + -1.2799500e+00 -1.2664500e+00 -1.2529500e+00 -1.2394500e+00 + -1.2259500e+00 -1.2124500e+00 -1.1989501e+00 -1.1854500e+00 + -1.1719500e+00 -1.1584500e+00 -1.1449500e+00 -1.1314501e+00 + -1.1179500e+00 -1.1044500e+00 -1.0909500e+00 -1.0774500e+00 + -1.0639499e+00 -1.0504500e+00 -1.0369500e+00 -1.0234500e+00 + -1.0099500e+00 -9.9645001e-01 -9.8294997e-01 -9.6945000e-01 + -9.5595002e-01 -9.4244999e-01 -9.2895001e-01 -9.1544998e-01 + -9.0195000e-01 -8.8845003e-01 -8.7494999e-01 -8.6145002e-01 + -8.4794998e-01 -8.3445001e-01 -8.2094997e-01 -8.0745000e-01 + -7.9395002e-01 -7.8044999e-01 -7.6695001e-01 -7.5344998e-01 + -7.3995000e-01 -7.2645003e-01 -7.1294999e-01 -6.9945002e-01 + -6.8594998e-01 -6.7245001e-01 -6.5894997e-01 -6.4545000e-01 + -6.3195002e-01 -6.1844999e-01 -6.0495001e-01 -5.9144998e-01 + -5.7795000e-01 -5.6445003e-01 -5.5094999e-01 -5.3745002e-01 + -5.2394998e-01 -5.1045001e-01 -4.9695000e-01 -4.8345000e-01 + -4.6994999e-01 -4.5644999e-01 -4.4295001e-01 -4.2945001e-01 + -4.1595000e-01 -4.0245000e-01 -3.8894999e-01 -3.7544999e-01 + -3.6195001e-01 -3.4845001e-01 -3.3495000e-01 -3.2145000e-01 + -3.0794999e-01 -2.9445001e-01 -2.8095001e-01 -2.6745000e-01 + -2.5395000e-01 -2.4044999e-01 -2.2695000e-01 -2.1345000e-01 + -1.9994999e-01 -1.8645000e-01 -1.7295000e-01 -1.5944999e-01 + -1.4595000e-01 -1.3245000e-01 -1.1895000e-01 -1.0545000e-01 + -9.1949999e-02 -7.8450002e-02 -6.4949997e-02 -5.1449999e-02 + -3.7950002e-02 -2.4450000e-02 -1.0950000e-02 2.5500001e-03 + 1.6050000e-02 2.9549999e-02 4.3049999e-02 5.6550000e-02 + 7.0050001e-02 8.3549999e-02 9.7050004e-02 1.1055000e-01 + 1.2405000e-01 1.3755000e-01 1.5105000e-01 1.6455001e-01 + 1.7805000e-01 1.9155000e-01 2.0505001e-01 2.1855000e-01 + 2.3205000e-01 2.4555001e-01 2.5905001e-01 2.7254999e-01 + 2.8604999e-01 2.9955000e-01 3.1305000e-01 3.2655001e-01 + 3.4005001e-01 3.5354999e-01 3.6704999e-01 3.8055000e-01 + 3.9405000e-01 4.0755001e-01 4.2105001e-01 4.3454999e-01 + 4.4804999e-01 4.6155000e-01 4.7505000e-01 4.8855001e-01 + 5.0204998e-01 5.1555002e-01 5.2904999e-01 5.4255003e-01 + 5.5605000e-01 5.6954998e-01 5.8305001e-01 5.9654999e-01 + 6.1005002e-01 6.2355000e-01 6.3704997e-01 6.5055001e-01 + 6.6404998e-01 6.7755002e-01 6.9104999e-01 7.0455003e-01 + 7.1805000e-01 7.3154998e-01 7.4505001e-01 7.5854999e-01 + 7.7205002e-01 7.8555000e-01 7.9904997e-01 8.1255001e-01 + 8.2604998e-01 8.3955002e-01 8.5304999e-01 8.6655003e-01 + 8.8005000e-01 8.9354998e-01 9.0705001e-01 9.2054999e-01 + 9.3405002e-01 9.4755000e-01 9.6104997e-01 9.7455001e-01 + 9.8804998e-01 1.0015500e+00 1.0150501e+00 1.0285500e+00 + 1.0420500e+00 1.0555500e+00 1.0690500e+00 1.0825500e+00 + 1.0960500e+00 1.1095500e+00 1.1230500e+00 1.1365499e+00 + 1.1500500e+00 1.1635500e+00 1.1770500e+00 1.1905500e+00 + 1.2040499e+00 1.2175500e+00 1.2310500e+00 1.2445500e+00 + 1.2580500e+00 1.2715501e+00 1.2850500e+00 1.2985500e+00 + 1.3120500e+00 1.3255500e+00 1.3390501e+00 1.3525500e+00 + 1.3660500e+00 1.3795500e+00 1.3930500e+00 1.4065500e+00 + 1.4200500e+00 1.4335500e+00 1.4470500e+00 1.4605500e+00 + 1.4740500e+00 1.4875500e+00 1.5010500e+00 1.5145500e+00 + 1.5280499e+00 1.5415500e+00 1.5550500e+00 1.5685500e+00 + 1.5820500e+00 1.5955499e+00 1.6090500e+00 1.6225500e+00 + 1.6360500e+00 1.6495500e+00 1.6630501e+00 1.6765500e+00 + 1.6900500e+00 1.7035500e+00 1.7170500e+00 1.7305501e+00 + 1.7440500e+00 1.7575500e+00 1.7710500e+00 1.7845500e+00 + 1.7980500e+00 1.8115500e+00 1.8250500e+00 1.8385500e+00 + 1.8520499e+00 1.8655500e+00 1.8790500e+00 1.8925500e+00 + 1.9060500e+00 1.9195499e+00 1.9330500e+00 1.9465500e+00 + 1.9600500e+00 1.9735500e+00 1.9870501e+00 2.0005500e+00 + 2.0140500e+00 2.0275500e+00 2.0410500e+00 2.0545499e+00 + 2.0680499e+00 2.0815499e+00 2.0950501e+00 2.1085501e+00 + 2.1220500e+00 2.1355500e+00 2.1490500e+00 2.1625500e+00 + 2.1760499e+00 2.1895499e+00 2.2030499e+00 2.2165501e+00 + 2.2300501e+00 2.2435501e+00 2.2570500e+00 2.2705500e+00 + 2.2840500e+00 2.2975500e+00 2.3110499e+00 2.3245499e+00 + 2.3380499e+00 2.3515501e+00 2.3650501e+00 2.3785501e+00 + 2.3920500e+00 2.4055500e+00 2.4190500e+00 2.4325500e+00 + 2.4460499e+00 2.4595499e+00 2.4730501e+00 2.4865501e+00 + 2.5000501e+00 2.5135500e+00 2.5270500e+00 2.5405500e+00 + 2.5540500e+00 2.5675499e+00 2.5810499e+00 2.5945499e+00 + 2.6080501e+00 2.6215501e+00 2.6350501e+00 2.6485500e+00 + 2.6620500e+00 2.6755500e+00 2.6890500e+00 2.7025499e+00 + 2.7160499e+00 2.7295499e+00 2.7430501e+00 2.7565501e+00 + 2.7700500e+00 2.7835500e+00 2.7970500e+00 2.8105500e+00 + 2.8240499e+00 2.8375499e+00 2.8510499e+00 2.8645501e+00 + 2.8780501e+00 2.8915501e+00 2.9050500e+00 2.9185500e+00 + 2.9320500e+00 2.9455500e+00 2.9590499e+00 2.9725499e+00 + 2.9860499e+00 2.9995501e+00 3.0130501e+00 3.0265501e+00 + 3.0400500e+00 3.0535500e+00 3.0670500e+00 3.0805500e+00 + 3.0940499e+00 3.1075499e+00 3.1210499e+00 3.1345501e+00 + 3.1480501e+00 3.1615500e+00 3.1750500e+00 3.1885500e+00 + 3.2020500e+00 3.2155499e+00 3.2290499e+00 3.2425499e+00 + 3.2560501e+00 3.2695501e+00 3.2830501e+00 3.2965500e+00 + 3.3100500e+00 3.3235500e+00 3.3370500e+00 3.3505499e+00 + 3.3640499e+00 3.3775499e+00 3.3910501e+00 3.4045501e+00 + 3.4180501e+00 3.4315500e+00 3.4450500e+00 3.4585500e+00 + 3.4720500e+00 3.4855499e+00 3.4990499e+00 3.5125501e+00 + 3.5260501e+00 3.5395501e+00 3.5530500e+00 3.5665500e+00 + 3.5800500e+00 3.5935500e+00 3.6070499e+00 3.6205499e+00 + 3.6340499e+00 3.6475501e+00 3.6610501e+00 3.6745501e+00 + 3.6880500e+00 3.7015500e+00 3.7150500e+00 3.7285500e+00 + 3.7420499e+00 3.7555499e+00 3.7690499e+00 3.7825501e+00 + 3.7960501e+00 3.8095500e+00 3.8230500e+00 3.8365500e+00 + 3.8500500e+00 3.8635499e+00 3.8770499e+00 3.8905499e+00 + 3.9040501e+00 3.9175501e+00 3.9310501e+00 3.9445500e+00 + 3.9580500e+00 3.9715500e+00 3.9850500e+00 3.9985499e+00 + 4.0120502e+00 4.0255499e+00 4.0390501e+00 4.0525498e+00 + 4.0660501e+00 4.0795498e+00 4.0930500e+00 4.1065502e+00 + 4.1200500e+00 4.1335502e+00 4.1470499e+00 4.1605501e+00 + 4.1740499e+00 4.1875501e+00 4.2010498e+00 4.2145500e+00 + 4.2280502e+00 4.2415500e+00 4.2550502e+00 4.2685499e+00 + 4.2820501e+00 4.2955499e+00 4.3090501e+00 4.3225498e+00 + 4.3360500e+00 4.3495498e+00 4.3630500e+00 4.3765502e+00 + 4.3900499e+00 4.4035501e+00 4.4170499e+00 4.4305501e+00 + 4.4440498e+00 4.4575500e+00 4.4710498e+00 4.4845500e+00 + 4.4980502e+00 4.5115499e+00 4.5250502e+00 4.5385499e+00 + 4.5520501e+00 4.5655499e+00 4.5790501e+00 4.5925498e+00 + 4.6060500e+00 4.6195502e+00 4.6330500e+00 4.6465502e+00 + 4.6600499e+00 4.6735501e+00 4.6870499e+00 4.7005501e+00 + 4.7140498e+00 4.7275500e+00 4.7410498e+00 4.7545500e+00 + 4.7680502e+00 4.7815499e+00 4.7950501e+00 4.8085499e+00 + 4.8220501e+00 4.8355498e+00 4.8490500e+00 4.8625498e+00 + 4.8760500e+00 4.8895502e+00 4.9030499e+00 4.9165502e+00 + 4.9300499e+00 4.9435501e+00 4.9570498e+00 4.9705501e+00 + 4.9840498e+00 4.9975500e+00 5.0110502e+00 5.0245500e+00 + 5.0380502e+00 5.0515499e+00 5.0650501e+00 5.0785499e+00 + 5.0920501e+00 5.1055498e+00 5.1190500e+00 5.1325498e+00 + 5.1460500e+00 5.1595502e+00 5.1730499e+00 5.1865501e+00 + 5.2000499e+00 5.2135501e+00 5.2270498e+00 5.2405500e+00 + 5.2540498e+00 5.2675500e+00 5.2810502e+00 5.2945499e+00 + 5.3080502e+00 5.3215499e+00 5.3350501e+00 5.3485498e+00 + 5.3620501e+00 5.3755498e+00 5.3890500e+00 5.4025502e+00 + 5.4160500e+00 5.4295502e+00 5.4430499e+00 5.4565501e+00 + 5.4700499e+00 5.4835501e+00 5.4970498e+00 5.5105500e+00 + 5.5240502e+00 5.5375500e+00 5.5510502e+00 5.5645499e+00 + 5.5780501e+00 5.5915499e+00 5.6050501e+00 5.6185498e+00 + 5.6320500e+00 5.6455498e+00 5.6590500e+00 5.6725502e+00 + 5.6860499e+00 5.6995502e+00 5.7130499e+00 5.7265501e+00 + 5.7400498e+00 5.7535501e+00 5.7670498e+00 5.7805500e+00 + 5.7940502e+00 5.8075500e+00 5.8210502e+00 5.8345499e+00 + 5.8480501e+00 5.8615499e+00 5.8750501e+00 5.8885498e+00 + 5.9020500e+00 5.9155502e+00 5.9290500e+00 5.9425502e+00 + 5.9560499e+00 5.9695501e+00 5.9830499e+00 5.9965501e+00 + 6.0100498e+00 6.0235500e+00 6.0370498e+00 6.0505500e+00 + 6.0640502e+00 6.0775499e+00 6.0910501e+00 6.1045499e+00 + 6.1180501e+00 6.1315498e+00 6.1450500e+00 6.1585498e+00 + 6.1720500e+00 6.1855502e+00 6.1990499e+00 6.2125502e+00 + 6.2260499e+00 6.2395501e+00 6.2530499e+00 6.2665501e+00 + 6.2800498e+00 6.2935500e+00 6.3070502e+00 6.3205500e+00 + 6.3340502e+00 6.3475499e+00 6.3610501e+00 6.3745499e+00 + 6.3880501e+00 6.4015498e+00 6.4150500e+00 6.4285498e+00 + 6.4420500e+00 6.4555502e+00 6.4690499e+00 6.4825501e+00 + 6.4960499e+00 6.5095501e+00 6.5230498e+00 6.5365500e+00 + 6.5500498e+00 6.5635500e+00 6.5770502e+00 6.5905499e+00 + 6.6040502e+00 6.6175499e+00 6.6310501e+00 6.6445498e+00 + 6.6580501e+00 6.6715498e+00 6.6850500e+00 6.6985502e+00 + 6.7120500e+00 6.7255502e+00 6.7390499e+00 6.7525501e+00 + 6.7660499e+00 6.7795501e+00 6.7930498e+00 6.8065500e+00 + 6.8200498e+00 6.8335500e+00 6.8470502e+00 6.8605499e+00 + 6.8740501e+00 6.8875499e+00 6.9010501e+00 6.9145498e+00 + 6.9280500e+00 6.9415498e+00 6.9550500e+00 6.9685502e+00 + 6.9820499e+00 6.9955502e+00 7.0090499e+00 7.0225501e+00 + 7.0360498e+00 7.0495501e+00 7.0630498e+00 7.0765500e+00 + 7.0900502e+00 7.1035500e+00 7.1170502e+00 7.1305499e+00 + 7.1440501e+00 7.1578269e+00 7.1721697e+00 7.1871009e+00 + 7.2026453e+00 7.2188272e+00 7.2356739e+00 7.2532115e+00 + 7.2714696e+00 7.2904768e+00 7.3102641e+00 7.3308635e+00 + 7.3523088e+00 7.3746343e+00 7.3978763e+00 7.4220719e+00 + 7.4472609e+00 7.4734836e+00 7.5007830e+00 7.5292029e+00 + 7.5587893e+00 7.5895901e+00 7.6233001e+00 7.6592999e+00 + 7.6953001e+00 7.7312999e+00 7.7673001e+00 7.8032999e+00 + 7.8393002e+00 7.8752999e+00 7.9113002e+00 7.9473000e+00 + 7.9833002e+00 8.0193005e+00 8.0552998e+00 8.0913000e+00 + 8.1273003e+00 8.1632996e+00 8.1992998e+00 8.2353001e+00 + 8.2713003e+00 8.3072996e+00 8.3432999e+00 8.3793001e+00 + 8.4153004e+00 8.4512997e+00 8.4872999e+00 8.5233002e+00 + 8.5593004e+00 8.5952997e+00 8.6313000e+00 8.6673002e+00 + 8.7033005e+00 8.7392998e+00 8.7753000e+00 8.8113003e+00 + 8.8472996e+00 8.8832998e+00 8.9193001e+00 8.9553003e+00] + y_upper_bound: [-5.5752001e+00 -5.5391998e+00 -5.5032001e+00 -5.4671998e+00 + -5.4312000e+00 -5.3951998e+00 -5.3592000e+00 -5.3232002e+00 + -5.2872000e+00 -5.2512002e+00 -5.2151999e+00 -5.1792002e+00 + -5.1431999e+00 -5.1072001e+00 -5.0711999e+00 -5.0352001e+00 + -4.9991999e+00 -4.9632001e+00 -4.9271998e+00 -4.8912001e+00 + -4.8551998e+00 -4.8192000e+00 -4.7831998e+00 -4.7472000e+00 + -4.7112002e+00 -4.6752000e+00 -4.6392002e+00 -4.6032000e+00 + -4.5672002e+00 -4.5311999e+00 -4.4952002e+00 -4.4591999e+00 + -4.4232001e+00 -4.3871999e+00 -4.3512001e+00 -4.3151999e+00 + -4.2792001e+00 -4.2431998e+00 -4.2094898e+00 -4.1786890e+00 + -4.1491027e+00 -4.1206832e+00 -4.0933838e+00 -4.0671611e+00 + -4.0419717e+00 -4.0177760e+00 -3.9945343e+00 -3.9722090e+00 + -3.9507637e+00 -3.9301641e+00 -3.9103768e+00 -3.8913693e+00 + -3.8731117e+00 -3.8555737e+00 -3.8387272e+00 -3.8225451e+00 + -3.8070009e+00 -3.7920697e+00 -3.7777271e+00 -3.7639501e+00 + -3.7504499e+00 -3.7369499e+00 -3.7234499e+00 -3.7099500e+00 + -3.6964500e+00 -3.6829500e+00 -3.6694500e+00 -3.6559501e+00 + -3.6424501e+00 -3.6289501e+00 -3.6154499e+00 -3.6019499e+00 + -3.5884500e+00 -3.5749500e+00 -3.5614500e+00 -3.5479500e+00 + -3.5344501e+00 -3.5209501e+00 -3.5074501e+00 -3.4939499e+00 + -3.4804499e+00 -3.4669499e+00 -3.4534500e+00 -3.4399500e+00 + -3.4264500e+00 -3.4129500e+00 -3.3994501e+00 -3.3859501e+00 + -3.3724501e+00 -3.3589499e+00 -3.3454499e+00 -3.3319499e+00 + -3.3184500e+00 -3.3049500e+00 -3.2914500e+00 -3.2779500e+00 + -3.2644501e+00 -3.2509501e+00 -3.2374499e+00 -3.2239499e+00 + -3.2104499e+00 -3.1969500e+00 -3.1834500e+00 -3.1699500e+00 + -3.1564500e+00 -3.1429501e+00 -3.1294501e+00 -3.1159501e+00 + -3.1024499e+00 -3.0889499e+00 -3.0754499e+00 -3.0619500e+00 + -3.0484500e+00 -3.0349500e+00 -3.0214500e+00 -3.0079501e+00 + -2.9944501e+00 -2.9809501e+00 -2.9674499e+00 -2.9539499e+00 + -2.9404500e+00 -2.9269500e+00 -2.9134500e+00 -2.8999500e+00 + -2.8864501e+00 -2.8729501e+00 -2.8594501e+00 -2.8459499e+00 + -2.8324499e+00 -2.8189499e+00 -2.8054500e+00 -2.7919500e+00 + -2.7784500e+00 -2.7649500e+00 -2.7514501e+00 -2.7379501e+00 + -2.7244501e+00 -2.7109499e+00 -2.6974499e+00 -2.6839499e+00 + -2.6704500e+00 -2.6569500e+00 -2.6434500e+00 -2.6299500e+00 + -2.6164501e+00 -2.6029501e+00 -2.5894499e+00 -2.5759499e+00 + -2.5624499e+00 -2.5489500e+00 -2.5354500e+00 -2.5219500e+00 + -2.5084500e+00 -2.4949501e+00 -2.4814501e+00 -2.4679501e+00 + -2.4544499e+00 -2.4409499e+00 -2.4274499e+00 -2.4139500e+00 + -2.4004500e+00 -2.3869500e+00 -2.3734500e+00 -2.3599501e+00 + -2.3464501e+00 -2.3329501e+00 -2.3194499e+00 -2.3059499e+00 + -2.2924500e+00 -2.2789500e+00 -2.2654500e+00 -2.2519500e+00 + -2.2384501e+00 -2.2249501e+00 -2.2114501e+00 -2.1979499e+00 + -2.1844499e+00 -2.1709499e+00 -2.1574500e+00 -2.1439500e+00 + -2.1304500e+00 -2.1169500e+00 -2.1034501e+00 -2.0899501e+00 + -2.0764501e+00 -2.0629499e+00 -2.0494499e+00 -2.0359499e+00 + -2.0224500e+00 -2.0089500e+00 -1.9954500e+00 -1.9819500e+00 + -1.9684500e+00 -1.9549500e+00 -1.9414500e+00 -1.9279500e+00 + -1.9144500e+00 -1.9009500e+00 -1.8874500e+00 -1.8739500e+00 + -1.8604500e+00 -1.8469501e+00 -1.8334500e+00 -1.8199500e+00 + -1.8064500e+00 -1.7929500e+00 -1.7794501e+00 -1.7659500e+00 + -1.7524500e+00 -1.7389500e+00 -1.7254500e+00 -1.7119499e+00 + -1.6984500e+00 -1.6849500e+00 -1.6714500e+00 -1.6579500e+00 + -1.6444499e+00 -1.6309500e+00 -1.6174500e+00 -1.6039500e+00 + -1.5904500e+00 -1.5769500e+00 -1.5634500e+00 -1.5499500e+00 + -1.5364500e+00 -1.5229501e+00 -1.5094500e+00 -1.4959500e+00 + -1.4824500e+00 -1.4689500e+00 -1.4554501e+00 -1.4419500e+00 + -1.4284500e+00 -1.4149500e+00 -1.4014500e+00 -1.3879499e+00 + -1.3744500e+00 -1.3609500e+00 -1.3474500e+00 -1.3339500e+00 + -1.3204499e+00 -1.3069500e+00 -1.2934500e+00 -1.2799500e+00 + -1.2664500e+00 -1.2529500e+00 -1.2394500e+00 -1.2259500e+00 + -1.2124500e+00 -1.1989501e+00 -1.1854500e+00 -1.1719500e+00 + -1.1584500e+00 -1.1449500e+00 -1.1314501e+00 -1.1179500e+00 + -1.1044500e+00 -1.0909500e+00 -1.0774500e+00 -1.0639499e+00 + -1.0504500e+00 -1.0369500e+00 -1.0234500e+00 -1.0099500e+00 + -9.9645001e-01 -9.8294997e-01 -9.6945000e-01 -9.5595002e-01 + -9.4244999e-01 -9.2895001e-01 -9.1544998e-01 -9.0195000e-01 + -8.8845003e-01 -8.7494999e-01 -8.6145002e-01 -8.4794998e-01 + -8.3445001e-01 -8.2094997e-01 -8.0745000e-01 -7.9395002e-01 + -7.8044999e-01 -7.6695001e-01 -7.5344998e-01 -7.3995000e-01 + -7.2645003e-01 -7.1294999e-01 -6.9945002e-01 -6.8594998e-01 + -6.7245001e-01 -6.5894997e-01 -6.4545000e-01 -6.3195002e-01 + -6.1844999e-01 -6.0495001e-01 -5.9144998e-01 -5.7795000e-01 + -5.6445003e-01 -5.5094999e-01 -5.3745002e-01 -5.2394998e-01 + -5.1045001e-01 -4.9695000e-01 -4.8345000e-01 -4.6994999e-01 + -4.5644999e-01 -4.4295001e-01 -4.2945001e-01 -4.1595000e-01 + -4.0245000e-01 -3.8894999e-01 -3.7544999e-01 -3.6195001e-01 + -3.4845001e-01 -3.3495000e-01 -3.2145000e-01 -3.0794999e-01 + -2.9445001e-01 -2.8095001e-01 -2.6745000e-01 -2.5395000e-01 + -2.4044999e-01 -2.2695000e-01 -2.1345000e-01 -1.9994999e-01 + -1.8645000e-01 -1.7295000e-01 -1.5944999e-01 -1.4595000e-01 + -1.3245000e-01 -1.1895000e-01 -1.0545000e-01 -9.1949999e-02 + -7.8450002e-02 -6.4949997e-02 -5.1449999e-02 -3.7950002e-02 + -2.4450000e-02 -1.0950000e-02 2.5500001e-03 1.6050000e-02 + 2.9549999e-02 4.3049999e-02 5.6550000e-02 7.0050001e-02 + 8.3549999e-02 9.7050004e-02 1.1055000e-01 1.2405000e-01 + 1.3755000e-01 1.5105000e-01 1.6455001e-01 1.7805000e-01 + 1.9155000e-01 2.0505001e-01 2.1855000e-01 2.3205000e-01 + 2.4555001e-01 2.5905001e-01 2.7254999e-01 2.8604999e-01 + 2.9955000e-01 3.1305000e-01 3.2655001e-01 3.4005001e-01 + 3.5354999e-01 3.6704999e-01 3.8055000e-01 3.9405000e-01 + 4.0755001e-01 4.2105001e-01 4.3454999e-01 4.4804999e-01 + 4.6155000e-01 4.7505000e-01 4.8855001e-01 5.0204998e-01 + 5.1555002e-01 5.2904999e-01 5.4255003e-01 5.5605000e-01 + 5.6954998e-01 5.8305001e-01 5.9654999e-01 6.1005002e-01 + 6.2355000e-01 6.3704997e-01 6.5055001e-01 6.6404998e-01 + 6.7755002e-01 6.9104999e-01 7.0455003e-01 7.1805000e-01 + 7.3154998e-01 7.4505001e-01 7.5854999e-01 7.7205002e-01 + 7.8555000e-01 7.9904997e-01 8.1255001e-01 8.2604998e-01 + 8.3955002e-01 8.5304999e-01 8.6655003e-01 8.8005000e-01 + 8.9354998e-01 9.0705001e-01 9.2054999e-01 9.3405002e-01 + 9.4755000e-01 9.6104997e-01 9.7455001e-01 9.8804998e-01 + 1.0015500e+00 1.0150501e+00 1.0285500e+00 1.0420500e+00 + 1.0555500e+00 1.0690500e+00 1.0825500e+00 1.0960500e+00 + 1.1095500e+00 1.1230500e+00 1.1365499e+00 1.1500500e+00 + 1.1635500e+00 1.1770500e+00 1.1905500e+00 1.2040499e+00 + 1.2175500e+00 1.2310500e+00 1.2445500e+00 1.2580500e+00 + 1.2715501e+00 1.2850500e+00 1.2985500e+00 1.3120500e+00 + 1.3255500e+00 1.3390501e+00 1.3525500e+00 1.3660500e+00 + 1.3795500e+00 1.3930500e+00 1.4065500e+00 1.4200500e+00 + 1.4335500e+00 1.4470500e+00 1.4605500e+00 1.4740500e+00 + 1.4875500e+00 1.5010500e+00 1.5145500e+00 1.5280499e+00 + 1.5415500e+00 1.5550500e+00 1.5685500e+00 1.5820500e+00 + 1.5955499e+00 1.6090500e+00 1.6225500e+00 1.6360500e+00 + 1.6495500e+00 1.6630501e+00 1.6765500e+00 1.6900500e+00 + 1.7035500e+00 1.7170500e+00 1.7305501e+00 1.7440500e+00 + 1.7575500e+00 1.7710500e+00 1.7845500e+00 1.7980500e+00 + 1.8115500e+00 1.8250500e+00 1.8385500e+00 1.8520499e+00 + 1.8655500e+00 1.8790500e+00 1.8925500e+00 1.9060500e+00 + 1.9195499e+00 1.9330500e+00 1.9465500e+00 1.9600500e+00 + 1.9735500e+00 1.9870501e+00 2.0005500e+00 2.0140500e+00 + 2.0275500e+00 2.0410500e+00 2.0545499e+00 2.0680499e+00 + 2.0815499e+00 2.0950501e+00 2.1085501e+00 2.1220500e+00 + 2.1355500e+00 2.1490500e+00 2.1625500e+00 2.1760499e+00 + 2.1895499e+00 2.2030499e+00 2.2165501e+00 2.2300501e+00 + 2.2435501e+00 2.2570500e+00 2.2705500e+00 2.2840500e+00 + 2.2975500e+00 2.3110499e+00 2.3245499e+00 2.3380499e+00 + 2.3515501e+00 2.3650501e+00 2.3785501e+00 2.3920500e+00 + 2.4055500e+00 2.4190500e+00 2.4325500e+00 2.4460499e+00 + 2.4595499e+00 2.4730501e+00 2.4865501e+00 2.5000501e+00 + 2.5135500e+00 2.5270500e+00 2.5405500e+00 2.5540500e+00 + 2.5675499e+00 2.5810499e+00 2.5945499e+00 2.6080501e+00 + 2.6215501e+00 2.6350501e+00 2.6485500e+00 2.6620500e+00 + 2.6755500e+00 2.6890500e+00 2.7025499e+00 2.7160499e+00 + 2.7295499e+00 2.7430501e+00 2.7565501e+00 2.7700500e+00 + 2.7835500e+00 2.7970500e+00 2.8105500e+00 2.8240499e+00 + 2.8375499e+00 2.8510499e+00 2.8645501e+00 2.8780501e+00 + 2.8915501e+00 2.9050500e+00 2.9185500e+00 2.9320500e+00 + 2.9455500e+00 2.9590499e+00 2.9725499e+00 2.9860499e+00 + 2.9995501e+00 3.0130501e+00 3.0265501e+00 3.0400500e+00 + 3.0535500e+00 3.0670500e+00 3.0805500e+00 3.0940499e+00 + 3.1075499e+00 3.1210499e+00 3.1345501e+00 3.1480501e+00 + 3.1615500e+00 3.1750500e+00 3.1885500e+00 3.2020500e+00 + 3.2155499e+00 3.2290499e+00 3.2425499e+00 3.2560501e+00 + 3.2695501e+00 3.2830501e+00 3.2965500e+00 3.3100500e+00 + 3.3235500e+00 3.3370500e+00 3.3505499e+00 3.3640499e+00 + 3.3775499e+00 3.3910501e+00 3.4045501e+00 3.4180501e+00 + 3.4315500e+00 3.4450500e+00 3.4585500e+00 3.4720500e+00 + 3.4855499e+00 3.4990499e+00 3.5125501e+00 3.5260501e+00 + 3.5395501e+00 3.5530500e+00 3.5665500e+00 3.5800500e+00 + 3.5935500e+00 3.6070499e+00 3.6205499e+00 3.6340499e+00 + 3.6475501e+00 3.6610501e+00 3.6745501e+00 3.6880500e+00 + 3.7015500e+00 3.7150500e+00 3.7285500e+00 3.7420499e+00 + 3.7555499e+00 3.7690499e+00 3.7825501e+00 3.7960501e+00 + 3.8095500e+00 3.8230500e+00 3.8365500e+00 3.8500500e+00 + 3.8635499e+00 3.8770499e+00 3.8905499e+00 3.9040501e+00 + 3.9175501e+00 3.9310501e+00 3.9445500e+00 3.9580500e+00 + 3.9715500e+00 3.9850500e+00 3.9985499e+00 4.0120502e+00 + 4.0255499e+00 4.0390501e+00 4.0525498e+00 4.0660501e+00 + 4.0795498e+00 4.0930500e+00 4.1065502e+00 4.1200500e+00 + 4.1335502e+00 4.1470499e+00 4.1605501e+00 4.1740499e+00 + 4.1875501e+00 4.2010498e+00 4.2145500e+00 4.2280502e+00 + 4.2415500e+00 4.2550502e+00 4.2685499e+00 4.2820501e+00 + 4.2955499e+00 4.3090501e+00 4.3225498e+00 4.3360500e+00 + 4.3495498e+00 4.3630500e+00 4.3765502e+00 4.3900499e+00 + 4.4035501e+00 4.4170499e+00 4.4305501e+00 4.4440498e+00 + 4.4575500e+00 4.4710498e+00 4.4845500e+00 4.4980502e+00 + 4.5115499e+00 4.5250502e+00 4.5385499e+00 4.5520501e+00 + 4.5655499e+00 4.5790501e+00 4.5925498e+00 4.6060500e+00 + 4.6195502e+00 4.6330500e+00 4.6465502e+00 4.6600499e+00 + 4.6735501e+00 4.6870499e+00 4.7005501e+00 4.7140498e+00 + 4.7275500e+00 4.7410498e+00 4.7545500e+00 4.7680502e+00 + 4.7815499e+00 4.7950501e+00 4.8085499e+00 4.8220501e+00 + 4.8355498e+00 4.8490500e+00 4.8625498e+00 4.8760500e+00 + 4.8895502e+00 4.9030499e+00 4.9165502e+00 4.9300499e+00 + 4.9435501e+00 4.9570498e+00 4.9705501e+00 4.9840498e+00 + 4.9975500e+00 5.0110502e+00 5.0245500e+00 5.0380502e+00 + 5.0515499e+00 5.0650501e+00 5.0785499e+00 5.0920501e+00 + 5.1055498e+00 5.1190500e+00 5.1325498e+00 5.1460500e+00 + 5.1595502e+00 5.1730499e+00 5.1865501e+00 5.2000499e+00 + 5.2135501e+00 5.2270498e+00 5.2405500e+00 5.2540498e+00 + 5.2675500e+00 5.2810502e+00 5.2945499e+00 5.3080502e+00 + 5.3215499e+00 5.3350501e+00 5.3485498e+00 5.3620501e+00 + 5.3755498e+00 5.3890500e+00 5.4025502e+00 5.4160500e+00 + 5.4295502e+00 5.4430499e+00 5.4565501e+00 5.4700499e+00 + 5.4835501e+00 5.4970498e+00 5.5105500e+00 5.5240502e+00 + 5.5375500e+00 5.5510502e+00 5.5645499e+00 5.5780501e+00 + 5.5915499e+00 5.6050501e+00 5.6185498e+00 5.6320500e+00 + 5.6455498e+00 5.6590500e+00 5.6725502e+00 5.6860499e+00 + 5.6995502e+00 5.7130499e+00 5.7265501e+00 5.7400498e+00 + 5.7535501e+00 5.7670498e+00 5.7805500e+00 5.7940502e+00 + 5.8075500e+00 5.8210502e+00 5.8345499e+00 5.8480501e+00 + 5.8615499e+00 5.8750501e+00 5.8885498e+00 5.9020500e+00 + 5.9155502e+00 5.9290500e+00 5.9425502e+00 5.9560499e+00 + 5.9695501e+00 5.9830499e+00 5.9965501e+00 6.0100498e+00 + 6.0235500e+00 6.0370498e+00 6.0505500e+00 6.0640502e+00 + 6.0775499e+00 6.0910501e+00 6.1045499e+00 6.1180501e+00 + 6.1315498e+00 6.1450500e+00 6.1585498e+00 6.1720500e+00 + 6.1855502e+00 6.1990499e+00 6.2125502e+00 6.2260499e+00 + 6.2395501e+00 6.2530499e+00 6.2665501e+00 6.2800498e+00 + 6.2935500e+00 6.3070502e+00 6.3205500e+00 6.3340502e+00 + 6.3475499e+00 6.3610501e+00 6.3745499e+00 6.3880501e+00 + 6.4015498e+00 6.4150500e+00 6.4285498e+00 6.4420500e+00 + 6.4555502e+00 6.4690499e+00 6.4825501e+00 6.4960499e+00 + 6.5095501e+00 6.5230498e+00 6.5365500e+00 6.5500498e+00 + 6.5635500e+00 6.5770502e+00 6.5905499e+00 6.6040502e+00 + 6.6175499e+00 6.6310501e+00 6.6445498e+00 6.6580501e+00 + 6.6715498e+00 6.6850500e+00 6.6985502e+00 6.7120500e+00 + 6.7255502e+00 6.7390499e+00 6.7525501e+00 6.7660499e+00 + 6.7795501e+00 6.7930498e+00 6.8065500e+00 6.8200498e+00 + 6.8335500e+00 6.8470502e+00 6.8605499e+00 6.8740501e+00 + 6.8875499e+00 6.9010501e+00 6.9145498e+00 6.9280500e+00 + 6.9415498e+00 6.9550500e+00 6.9685502e+00 6.9820499e+00 + 6.9955502e+00 7.0090499e+00 7.0225501e+00 7.0360498e+00 + 7.0495501e+00 7.0630498e+00 7.0765500e+00 7.0900502e+00 + 7.1035500e+00 7.1170502e+00 7.1305499e+00 7.1440501e+00 + 7.1578269e+00 7.1721697e+00 7.1871009e+00 7.2026453e+00 + 7.2188272e+00 7.2356739e+00 7.2532115e+00 7.2714696e+00 + 7.2904768e+00 7.3102641e+00 7.3308635e+00 7.3523088e+00 + 7.3746343e+00 7.3978763e+00 7.4220719e+00 7.4472609e+00 + 7.4734836e+00 7.5007830e+00 7.5292029e+00 7.5587893e+00 + 7.5895901e+00 7.6233001e+00 7.6592999e+00 7.6953001e+00 + 7.7312999e+00 7.7673001e+00 7.8032999e+00 7.8393002e+00 + 7.8752999e+00 7.9113002e+00 7.9473000e+00 7.9833002e+00 + 8.0193005e+00 8.0552998e+00 8.0913000e+00 8.1273003e+00 + 8.1632996e+00 8.1992998e+00 8.2353001e+00 8.2713003e+00 + 8.3072996e+00 8.3432999e+00 8.3793001e+00 8.4153004e+00 + 8.4512997e+00 8.4872999e+00 8.5233002e+00 8.5593004e+00 + 8.5952997e+00 8.6313000e+00 8.6673002e+00 8.7033005e+00 + 8.7392998e+00 8.7753000e+00 8.8113003e+00 8.8472996e+00 + 8.8832998e+00 8.9193001e+00 8.9553003e+00 8.9912996e+00] ] \ No newline at end of file diff --git a/lib/iris/tests/results/PP/global_test.pp.txt b/lib/iris/tests/results/PP/global_test.pp.txt index df5c010021..51e626d558 100644 --- a/lib/iris/tests/results/PP/global_test.pp.txt +++ b/lib/iris/tests/results/PP/global_test.pp.txt @@ -45,23 +45,17 @@ bplat: 90.0 bplon: 0.0 bgor: 0.0 - bzy: 92.5 - bdy: -2.5 - bzx: -3.75 - bdx: 3.75 + bzy: 92.499985 + bdy: -2.499999 + bzx: -3.749999 + bdx: 3.749999 bmdi: -1e+30 bmks: 1.0 - data: [[ 254.64399719 254.64399719 254.64399719 ..., 254.64399719 - 254.64399719 254.64399719] - [ 254.97499084 254.96766663 254.9808197 ..., 254.98776245 - 255.03466797 254.99720764] - [ 255.99584961 256.30834961 256.55874634 ..., 256.11685181 - 255.95605469 255.83555603] - ..., - [ 254.57333374 253.86854553 252.90516663 ..., 255.29681396 - 255.38789368 255.14859009] - [ 252.33691406 252.08926392 251.85536194 ..., 252.59863281 - 252.67466736 252.58959961] - [ 248.74584961 248.74584961 248.74584961 ..., 248.74584961 - 248.74584961 248.74584961]] + data: [[254.644 254.644 254.644 ... 254.644 254.644 254.644 ] + [254.97499 254.96767 254.98082 ... 254.98776 255.03467 254.99721] + [255.99585 256.30835 256.55875 ... 256.11685 255.95605 255.83556] + ... + [254.57333 253.86855 252.90517 ... 255.29681 255.3879 255.14859] + [252.33691 252.08926 251.85536 ... 252.59863 252.67467 252.5896 ] + [248.74585 248.74585 248.74585 ... 248.74585 248.74585 248.74585]] ] \ No newline at end of file diff --git a/lib/iris/tests/results/PP/nae_unpacked.pp.txt b/lib/iris/tests/results/PP/nae_unpacked.pp.txt index 8511ff2a8b..a26dae0645 100644 --- a/lib/iris/tests/results/PP/nae_unpacked.pp.txt +++ b/lib/iris/tests/results/PP/nae_unpacked.pp.txt @@ -49,18 +49,15 @@ bdy: 0.11 bzx: 326.11 bdx: 0.11 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 388.78125 389.46875 384.0625 ..., 318.1875 310.84375 - 307.796875] - [ 388.09375 381.375 374.28125 ..., 310.28125 305.59375 - 300.53125 ] - [ 382.34375 373.671875 371.171875 ..., 297.046875 293.109375 - 288.484375] - ..., - [ 0. 0. 0. ..., 0. 0. 0. ] - [ 0. 0. 0. ..., 0. 0. 0. ] - [ 0. 0. 0. ..., 0. 0. 0. ]] + data: [[388.78125 389.46875 384.0625 ... 318.1875 310.84375 307.79688] + [388.09375 381.375 374.28125 ... 310.28125 305.59375 300.53125] + [382.34375 373.67188 371.17188 ... 297.04688 293.10938 288.48438] + ... + [ 0. 0. 0. ... 0. 0. 0. ] + [ 0. 0. 0. ... 0. 0. 0. ] + [ 0. 0. 0. ... 0. 0. 0. ]] , PP Field lbyr: 2010 lbmon: 1 @@ -112,18 +109,15 @@ bdy: 0.11 bzx: 326.11 bdx: 0.11 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 226.078125 226.515625 231.921875 ..., 244.796875 251.34375 - 254.578125] - [ 225.625 233.296875 241.171875 ..., 250.421875 254.65625 - 259.453125] - [ 230.046875 239.890625 242.84375 ..., 260.921875 264.59375 - 269.09375 ] - ..., - [ 0. 0. 0. ..., 0. 0. 0. ] - [ 0. 0. 0. ..., 0. 0. 0. ] - [ 0. 0. 0. ..., 0. 0. 0. ]] + data: [[226.07812 226.51562 231.92188 ... 244.79688 251.34375 254.57812] + [225.625 233.29688 241.17188 ... 250.42188 254.65625 259.45312] + [230.04688 239.89062 242.84375 ... 260.92188 264.59375 269.09375] + ... + [ 0. 0. 0. ... 0. 0. 0. ] + [ 0. 0. 0. ... 0. 0. 0. ] + [ 0. 0. 0. ... 0. 0. 0. ]] , PP Field lbyr: 2010 lbmon: 1 @@ -175,16 +169,15 @@ bdy: 0.11 bzx: 326.11 bdx: 0.11 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ 412.875 413.5625 407.875 ..., 522.953125 523.265625 - 524.453125] - [ 412.1875 405.078125 397.578125 ..., 521.953125 522.421875 523.25 ] - [ 406.1875 397.015625 394.359375 ..., 521.515625 522.046875 522.875 ] - ..., - [ 0. 0. 0. ..., 0. 0. 0. ] - [ 0. 0. 0. ..., 0. 0. 0. ] - [ 0. 0. 0. ..., 0. 0. 0. ]] + data: [[412.875 413.5625 407.875 ... 522.9531 523.2656 524.4531 ] + [412.1875 405.07812 397.57812 ... 521.9531 522.4219 523.25 ] + [406.1875 397.01562 394.35938 ... 521.5156 522.0469 522.875 ] + ... + [ 0. 0. 0. ... 0. 0. 0. ] + [ 0. 0. 0. ... 0. 0. 0. ] + [ 0. 0. 0. ... 0. 0. 0. ]] , PP Field lbyr: 2010 lbmon: 1 @@ -236,17 +229,19 @@ bdy: 0.11 bzx: 326.11 bdx: 0.11 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data: [[ -61.265625 -61.3125 -60.4375 ..., -198.171875 -193.734375 + data: [[ -61.265625 -61.3125 -60.4375 ... -198.17188 -193.73438 -189.3125 ] - [ -61.234375 -60.0625 -58.6875 ..., -197.515625 -193.703125 + [ -61.234375 -60.0625 -58.6875 ... -197.51562 -193.70312 -189.9375 ] - [ -60.390625 -59.03125 -58.640625 ..., -193.484375 -190.140625 + [ -60.390625 -59.03125 -58.640625 ... -193.48438 -190.14062 -186.78125 ] - ..., - [ -73.28125 -19.171875 -3.03125 ..., -19.03125 -16.65625 + ... + [ -73.28125 -19.171875 -3.03125 ... -19.03125 -16.65625 -48.828125] - [ -48.1875 1.265625 -17.765625 ..., -17.21875 -41.3125 -64.65625 ] - [ -72.578125 -46.671875 -68.734375 ..., -49.15625 -66.71875 -65.6875 ]] + [ -48.1875 1.265625 -17.765625 ... -17.21875 -41.3125 + -64.65625 ] + [ -72.578125 -46.671875 -68.734375 ... -49.15625 -66.71875 + -65.6875 ]] ] \ No newline at end of file diff --git a/lib/iris/tests/results/PP/rle_unpacked.pp.txt b/lib/iris/tests/results/PP/rle_unpacked.pp.txt index c3b0f6650f..419c7e4082 100644 --- a/lib/iris/tests/results/PP/rle_unpacked.pp.txt +++ b/lib/iris/tests/results/PP/rle_unpacked.pp.txt @@ -39,7 +39,7 @@ bdatum: 0.0 bacc: -99.0 blev: 5.0 - brlev: -1.07374e+09 + brlev: -1073741800.0 bhlev: 0.0 bhrlev: 0.0 bplat: 90.0 @@ -49,172 +49,161 @@ bdy: 0.0 bzx: -1.0 bdx: 1.0 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data.data: [[ 0. 0. 0. ..., 0. 0. 0. ] - [ 0. 0. 0. ..., 0. 0. 0. ] - [ 0. 0. 0. ..., 0. 0. 0. ] - ..., - [ 233.78448486 233.66023254 233.53538513 ..., 234.14790344 - 234.02868652 233.90744019] - [ 232.06645203 231.93363953 231.80679321 ..., 232.4972229 232.34857178 - 232.20487976] - [ 0. 0. 0. ..., 0. 0. 0. ]] - data.mask: [[ True True True ..., True True True] - [ True True True ..., True True True] - [ True True True ..., True True True] - ..., - [False False False ..., False False False] - [False False False ..., False False False] - [ True True True ..., True True True]] - y: [-90. -89. -88. -87. -86. -85. -84. - -83. -82. -81. -80. -79. -78. -77. - -76. -75. -74. -73. -72. -71. -70. - -69. -68. -67. -66. -65. -64. -63. - -62. -61. -60. -59. -58. -57. -56. - -55. -54. -53. -52. -51. -50. -49. - -48. -47. -46. -45. -44. -43. -42. - -41. -40. -39. -38. -37. -36. -35. - -34. -33. -32. -31.00038528 -30.00230789 - -29.00729752 -28.01687241 -27.03252792 -26.05572891 -25.08790588 - -24.1304493 -23.18470192 -22.2519474 -21.33341408 -20.4302597 - -19.54357338 -18.674366 -17.82356834 -16.99202156 -16.18048286 - -15.38961029 -14.61997032 -13.87202835 -13.14614677 -12.44258881 - -11.7615118 -11.10296726 -10.46690273 -9.85316086 -9.26148129 - -8.69149876 -8.14274788 -7.61466455 -7.10658741 -6.61776304 - -6.14734745 -5.6944108 -5.2579422 -4.83685303 -4.42998457 - -4.03610992 -3.65394306 -3.2821424 -2.91931939 -2.56404257 - -2.21484447 -1.87023103 -1.52868605 -1.1886785 -0.84905553 - -0.50943249 -0.16980951 0.1698135 0.50943649 0.84905952 - 1.18868256 1.52868998 1.87023497 2.21484852 2.56404638 - 2.91932344 3.28214645 3.65394711 4.03611422 4.42998838 - 4.83685684 5.25794601 5.69441509 6.14735126 6.61776686 - 7.1065917 7.61466837 8.14275169 8.69150257 9.2614851 - 9.85316467 10.46690655 11.10297108 11.76151562 12.44259262 - 13.14615059 13.87203217 14.61997414 15.38961411 16.18048668 - 16.99202538 17.82357216 18.67436981 19.54357719 20.43026352 - 21.33341789 22.25195122 23.18470573 24.13045311 25.0879097 - 26.05573273 27.03253174 28.01687622 29.00730133 30.00231171 - 31.0003891 32.00000381 33.00000381 34.00000381 35.00000381 - 36.00000381 37.00000381 38.00000381 39.00000381 40.00000381 - 41.00000381 42.00000381 43.00000381 44.00000381 45.00000381 - 46.00000381 47.00000381 48.00000381 49.00000381 50.00000381 - 51.00000381 52.00000381 53.00000381 54.00000381 55.00000381 - 56.00000381 57.00000381 58.00000381 59.00000381 60.00000381 - 61.00000381 62.00000381 63.00000381 64.00000763 65.00000763 - 66.00000763 67.00000763 68.00000763 69.00000763 70.00000763 - 71.00000763 72.00000763 73.00000763 74.00000763 75.00000763 - 76.00000763 77.00000763 78.00000763 79.00000763 80.00000763 - 81.00000763 82.00000763 83.00000763 84.00000763 85.00000763 - 86.00000763 87.00000763 88.00000763 89.00000763 90.00000763] - y_lower_bound: [ -9.05000000e+01 -8.95000000e+01 -8.85000000e+01 -8.75000000e+01 - -8.65000000e+01 -8.55000000e+01 -8.45000000e+01 -8.35000000e+01 - -8.25000000e+01 -8.15000000e+01 -8.05000000e+01 -7.95000000e+01 - -7.85000000e+01 -7.75000000e+01 -7.65000000e+01 -7.55000000e+01 - -7.45000000e+01 -7.35000000e+01 -7.25000000e+01 -7.15000000e+01 - -7.05000000e+01 -6.95000000e+01 -6.85000000e+01 -6.75000000e+01 - -6.65000000e+01 -6.55000000e+01 -6.45000000e+01 -6.35000000e+01 - -6.25000000e+01 -6.15000000e+01 -6.05000000e+01 -5.95000000e+01 - -5.85000000e+01 -5.75000000e+01 -5.65000000e+01 -5.55000000e+01 - -5.45000000e+01 -5.35000000e+01 -5.25000000e+01 -5.15000000e+01 - -5.05000000e+01 -4.95000000e+01 -4.85000000e+01 -4.75000000e+01 - -4.65000000e+01 -4.55000000e+01 -4.45000000e+01 -4.35000000e+01 - -4.25000000e+01 -4.15000000e+01 -4.05000000e+01 -3.95000000e+01 - -3.85000000e+01 -3.75000000e+01 -3.65000000e+01 -3.55000000e+01 - -3.45000000e+01 -3.35000000e+01 -3.25000000e+01 -3.15000000e+01 - -3.05007706e+01 -2.95038452e+01 -2.85107517e+01 -2.75229950e+01 - -2.65420609e+01 -2.55693951e+01 -2.46064148e+01 -2.36544838e+01 - -2.27149181e+01 -2.17889767e+01 -2.08778515e+01 -1.99826679e+01 - -1.91044788e+01 -1.82442532e+01 -1.74028816e+01 -1.65811615e+01 - -1.57798033e+01 -1.49994183e+01 -1.42405233e+01 -1.35035334e+01 - -1.27887611e+01 -1.20964174e+01 -1.14266062e+01 -1.07793283e+01 - -1.01544771e+01 -9.55184460e+00 -8.97111797e+00 -8.41187954e+00 - -7.87361622e+00 -7.35571289e+00 -6.85746193e+00 -6.37806416e+00 - -5.91663122e+00 -5.47219086e+00 -5.04369307e+00 -4.63001299e+00 - -4.22995615e+00 -3.84226394e+00 -3.46562195e+00 -3.09866309e+00 - -2.73997593e+00 -2.38810897e+00 -2.04157996e+00 -1.69888198e+00 - -1.35848999e+00 -1.01886702e+00 -6.79243982e-01 -3.39621007e-01 - 1.99999999e-06 3.39625001e-01 6.79247975e-01 1.01887095e+00 - 1.35849404e+00 1.69888604e+00 2.04158401e+00 2.38811302e+00 - 2.73997998e+00 3.09866691e+00 3.46562600e+00 3.84226799e+00 - 4.22995996e+00 4.63001680e+00 5.04369688e+00 5.47219515e+00 - 5.91663504e+00 6.37806797e+00 6.85746622e+00 7.35571718e+00 - 7.87362003e+00 8.41188431e+00 8.97112179e+00 9.55184937e+00 - 1.01544809e+01 1.07793322e+01 1.14266100e+01 1.20964212e+01 - 1.27887650e+01 1.35035372e+01 1.42405272e+01 1.49994221e+01 - 1.57798071e+01 1.65811653e+01 1.74028854e+01 1.82442589e+01 - 1.91044827e+01 1.99826717e+01 2.08778553e+01 2.17889805e+01 - 2.27149220e+01 2.36544876e+01 2.46064186e+01 2.55694008e+01 - 2.65420647e+01 2.75229988e+01 2.85107555e+01 2.95038490e+01 - 3.05007744e+01 3.15000038e+01 3.25000038e+01 3.35000038e+01 - 3.45000038e+01 3.55000038e+01 3.65000038e+01 3.75000038e+01 - 3.85000038e+01 3.95000038e+01 4.05000038e+01 4.15000038e+01 - 4.25000038e+01 4.35000038e+01 4.45000038e+01 4.55000038e+01 - 4.65000038e+01 4.75000038e+01 4.85000038e+01 4.95000038e+01 - 5.05000038e+01 5.15000038e+01 5.25000038e+01 5.35000038e+01 - 5.45000038e+01 5.55000038e+01 5.65000038e+01 5.75000038e+01 - 5.85000038e+01 5.95000038e+01 6.05000038e+01 6.15000038e+01 - 6.25000038e+01 6.35000038e+01 6.45000076e+01 6.55000076e+01 - 6.65000076e+01 6.75000076e+01 6.85000076e+01 6.95000076e+01 - 7.05000076e+01 7.15000076e+01 7.25000076e+01 7.35000076e+01 - 7.45000076e+01 7.55000076e+01 7.65000076e+01 7.75000076e+01 - 7.85000076e+01 7.95000076e+01 8.05000076e+01 8.15000076e+01 - 8.25000076e+01 8.35000076e+01 8.45000076e+01 8.55000076e+01 - 8.65000076e+01 8.75000076e+01 8.85000076e+01 8.95000076e+01] - y_upper_bound: [ -8.95000000e+01 -8.85000000e+01 -8.75000000e+01 -8.65000000e+01 - -8.55000000e+01 -8.45000000e+01 -8.35000000e+01 -8.25000000e+01 - -8.15000000e+01 -8.05000000e+01 -7.95000000e+01 -7.85000000e+01 - -7.75000000e+01 -7.65000000e+01 -7.55000000e+01 -7.45000000e+01 - -7.35000000e+01 -7.25000000e+01 -7.15000000e+01 -7.05000000e+01 - -6.95000000e+01 -6.85000000e+01 -6.75000000e+01 -6.65000000e+01 - -6.55000000e+01 -6.45000000e+01 -6.35000000e+01 -6.25000000e+01 - -6.15000000e+01 -6.05000000e+01 -5.95000000e+01 -5.85000000e+01 - -5.75000000e+01 -5.65000000e+01 -5.55000000e+01 -5.45000000e+01 - -5.35000000e+01 -5.25000000e+01 -5.15000000e+01 -5.05000000e+01 - -4.95000000e+01 -4.85000000e+01 -4.75000000e+01 -4.65000000e+01 - -4.55000000e+01 -4.45000000e+01 -4.35000000e+01 -4.25000000e+01 - -4.15000000e+01 -4.05000000e+01 -3.95000000e+01 -3.85000000e+01 - -3.75000000e+01 -3.65000000e+01 -3.55000000e+01 -3.45000000e+01 - -3.35000000e+01 -3.25000000e+01 -3.15000000e+01 -3.05007706e+01 - -2.95038452e+01 -2.85107517e+01 -2.75229950e+01 -2.65420609e+01 - -2.55693951e+01 -2.46064148e+01 -2.36544838e+01 -2.27149181e+01 - -2.17889767e+01 -2.08778515e+01 -1.99826679e+01 -1.91044788e+01 - -1.82442532e+01 -1.74028816e+01 -1.65811615e+01 -1.57798033e+01 - -1.49994183e+01 -1.42405233e+01 -1.35035334e+01 -1.27887611e+01 - -1.20964174e+01 -1.14266062e+01 -1.07793283e+01 -1.01544771e+01 - -9.55184460e+00 -8.97111797e+00 -8.41187954e+00 -7.87361622e+00 - -7.35571289e+00 -6.85746193e+00 -6.37806416e+00 -5.91663122e+00 - -5.47219086e+00 -5.04369307e+00 -4.63001299e+00 -4.22995615e+00 - -3.84226394e+00 -3.46562195e+00 -3.09866309e+00 -2.73997593e+00 - -2.38810897e+00 -2.04157996e+00 -1.69888198e+00 -1.35848999e+00 - -1.01886702e+00 -6.79243982e-01 -3.39621007e-01 1.99999999e-06 - 3.39625001e-01 6.79247975e-01 1.01887095e+00 1.35849404e+00 - 1.69888604e+00 2.04158401e+00 2.38811302e+00 2.73997998e+00 - 3.09866691e+00 3.46562600e+00 3.84226799e+00 4.22995996e+00 - 4.63001680e+00 5.04369688e+00 5.47219515e+00 5.91663504e+00 - 6.37806797e+00 6.85746622e+00 7.35571718e+00 7.87362003e+00 - 8.41188431e+00 8.97112179e+00 9.55184937e+00 1.01544809e+01 - 1.07793322e+01 1.14266100e+01 1.20964212e+01 1.27887650e+01 - 1.35035372e+01 1.42405272e+01 1.49994221e+01 1.57798071e+01 - 1.65811653e+01 1.74028854e+01 1.82442589e+01 1.91044827e+01 - 1.99826717e+01 2.08778553e+01 2.17889805e+01 2.27149220e+01 - 2.36544876e+01 2.46064186e+01 2.55694008e+01 2.65420647e+01 - 2.75229988e+01 2.85107555e+01 2.95038490e+01 3.05007744e+01 - 3.15000038e+01 3.25000038e+01 3.35000038e+01 3.45000038e+01 - 3.55000038e+01 3.65000038e+01 3.75000038e+01 3.85000038e+01 - 3.95000038e+01 4.05000038e+01 4.15000038e+01 4.25000038e+01 - 4.35000038e+01 4.45000038e+01 4.55000038e+01 4.65000038e+01 - 4.75000038e+01 4.85000038e+01 4.95000038e+01 5.05000038e+01 - 5.15000038e+01 5.25000038e+01 5.35000038e+01 5.45000038e+01 - 5.55000038e+01 5.65000038e+01 5.75000038e+01 5.85000038e+01 - 5.95000038e+01 6.05000038e+01 6.15000038e+01 6.25000038e+01 - 6.35000038e+01 6.45000076e+01 6.55000076e+01 6.65000076e+01 - 6.75000076e+01 6.85000076e+01 6.95000076e+01 7.05000076e+01 - 7.15000076e+01 7.25000076e+01 7.35000076e+01 7.45000076e+01 - 7.55000076e+01 7.65000076e+01 7.75000076e+01 7.85000076e+01 - 7.95000076e+01 8.05000076e+01 8.15000076e+01 8.25000076e+01 - 8.35000076e+01 8.45000076e+01 8.55000076e+01 8.65000076e+01 - 8.75000076e+01 8.85000076e+01 8.95000076e+01 9.05000076e+01] + data: [[-- -- -- ... -- -- --] + [-- -- -- ... -- -- --] + [-- -- -- ... -- -- --] + ... + [233.78448486328125 233.6602325439453 233.53538513183594 ... + 234.1479034423828 234.0286865234375 233.90744018554688] + [232.0664520263672 231.9336395263672 231.80679321289062 ... + 232.49722290039062 232.34857177734375 232.2048797607422] + [-- -- -- ... -- -- --]] + y: [-90. -89. -88. -87. -86. -85. + -84. -83. -82. -81. -80. -79. + -78. -77. -76. -75. -74. -73. + -72. -71. -70. -69. -68. -67. + -66. -65. -64. -63. -62. -61. + -60. -59. -58. -57. -56. -55. + -54. -53. -52. -51. -50. -49. + -48. -47. -46. -45. -44. -43. + -42. -41. -40. -39. -38. -37. + -36. -35. -34. -33. -32. -31.000385 + -30.002308 -29.007298 -28.016872 -27.032528 -26.055729 -25.087906 + -24.13045 -23.184702 -22.251947 -21.333414 -20.43026 -19.543573 + -18.674366 -17.823568 -16.992022 -16.180483 -15.38961 -14.61997 + -13.872028 -13.146147 -12.442589 -11.761512 -11.102967 -10.466903 + -9.853161 -9.261481 -8.691499 -8.142748 -7.6146646 -7.1065874 + -6.617763 -6.1473475 -5.694411 -5.257942 -4.836853 -4.4299846 + -4.03611 -3.653943 -3.2821424 -2.9193194 -2.5640426 -2.2148445 + -1.870231 -1.528686 -1.1886785 -0.8490555 -0.5094325 -0.1698095 + 0.1698135 0.5094365 0.8490595 1.1886826 1.52869 1.870235 + 2.2148485 2.5640464 2.9193234 3.2821465 3.653947 4.036114 + 4.4299884 4.836857 5.257946 5.694415 6.1473513 6.617767 + 7.1065917 7.6146684 8.142752 8.691503 9.261485 9.853165 + 10.466907 11.102971 11.761516 12.442593 13.146151 13.872032 + 14.619974 15.389614 16.180487 16.992025 17.823572 18.67437 + 19.543577 20.430264 21.333418 22.251951 23.184706 24.130453 + 25.08791 26.055733 27.032532 28.016876 29.007301 30.002312 + 31.00039 32.000004 33.000004 34.000004 35.000004 36.000004 + 37.000004 38.000004 39.000004 40.000004 41.000004 42.000004 + 43.000004 44.000004 45.000004 46.000004 47.000004 48.000004 + 49.000004 50.000004 51.000004 52.000004 53.000004 54.000004 + 55.000004 56.000004 57.000004 58.000004 59.000004 60.000004 + 61.000004 62.000004 63.000004 64.00001 65.00001 66.00001 + 67.00001 68.00001 69.00001 70.00001 71.00001 72.00001 + 73.00001 74.00001 75.00001 76.00001 77.00001 78.00001 + 79.00001 80.00001 81.00001 82.00001 83.00001 84.00001 + 85.00001 86.00001 87.00001 88.00001 89.00001 90.00001 ] + y_lower_bound: [-9.0500000e+01 -8.9500000e+01 -8.8500000e+01 -8.7500000e+01 + -8.6500000e+01 -8.5500000e+01 -8.4500000e+01 -8.3500000e+01 + -8.2500000e+01 -8.1500000e+01 -8.0500000e+01 -7.9500000e+01 + -7.8500000e+01 -7.7500000e+01 -7.6500000e+01 -7.5500000e+01 + -7.4500000e+01 -7.3500000e+01 -7.2500000e+01 -7.1500000e+01 + -7.0500000e+01 -6.9500000e+01 -6.8500000e+01 -6.7500000e+01 + -6.6500000e+01 -6.5500000e+01 -6.4500000e+01 -6.3500000e+01 + -6.2500000e+01 -6.1500000e+01 -6.0500000e+01 -5.9500000e+01 + -5.8500000e+01 -5.7500000e+01 -5.6500000e+01 -5.5500000e+01 + -5.4500000e+01 -5.3500000e+01 -5.2500000e+01 -5.1500000e+01 + -5.0500000e+01 -4.9500000e+01 -4.8500000e+01 -4.7500000e+01 + -4.6500000e+01 -4.5500000e+01 -4.4500000e+01 -4.3500000e+01 + -4.2500000e+01 -4.1500000e+01 -4.0500000e+01 -3.9500000e+01 + -3.8500000e+01 -3.7500000e+01 -3.6500000e+01 -3.5500000e+01 + -3.4500000e+01 -3.3500000e+01 -3.2500000e+01 -3.1500000e+01 + -3.0500771e+01 -2.9503845e+01 -2.8510752e+01 -2.7522995e+01 + -2.6542061e+01 -2.5569395e+01 -2.4606415e+01 -2.3654484e+01 + -2.2714918e+01 -2.1788977e+01 -2.0877851e+01 -1.9982668e+01 + -1.9104479e+01 -1.8244253e+01 -1.7402882e+01 -1.6581161e+01 + -1.5779803e+01 -1.4999418e+01 -1.4240523e+01 -1.3503533e+01 + -1.2788761e+01 -1.2096417e+01 -1.1426606e+01 -1.0779328e+01 + -1.0154477e+01 -9.5518446e+00 -8.9711180e+00 -8.4118795e+00 + -7.8736162e+00 -7.3557129e+00 -6.8574619e+00 -6.3780642e+00 + -5.9166312e+00 -5.4721909e+00 -5.0436931e+00 -4.6300130e+00 + -4.2299562e+00 -3.8422639e+00 -3.4656219e+00 -3.0986631e+00 + -2.7399759e+00 -2.3881090e+00 -2.0415800e+00 -1.6988820e+00 + -1.3584900e+00 -1.0188670e+00 -6.7924398e-01 -3.3962101e-01 + 2.0000000e-06 3.3962500e-01 6.7924798e-01 1.0188709e+00 + 1.3584940e+00 1.6988860e+00 2.0415840e+00 2.3881130e+00 + 2.7399800e+00 3.0986669e+00 3.4656260e+00 3.8422680e+00 + 4.2299600e+00 4.6300168e+00 5.0436969e+00 5.4721951e+00 + 5.9166350e+00 6.3780680e+00 6.8574662e+00 7.3557172e+00 + 7.8736200e+00 8.4118843e+00 8.9711218e+00 9.5518494e+00 + 1.0154481e+01 1.0779332e+01 1.1426610e+01 1.2096421e+01 + 1.2788765e+01 1.3503537e+01 1.4240527e+01 1.4999422e+01 + 1.5779807e+01 1.6581165e+01 1.7402885e+01 1.8244259e+01 + 1.9104483e+01 1.9982672e+01 2.0877855e+01 2.1788980e+01 + 2.2714922e+01 2.3654488e+01 2.4606419e+01 2.5569401e+01 + 2.6542065e+01 2.7522999e+01 2.8510756e+01 2.9503849e+01 + 3.0500774e+01 3.1500004e+01 3.2500004e+01 3.3500004e+01 + 3.4500004e+01 3.5500004e+01 3.6500004e+01 3.7500004e+01 + 3.8500004e+01 3.9500004e+01 4.0500004e+01 4.1500004e+01 + 4.2500004e+01 4.3500004e+01 4.4500004e+01 4.5500004e+01 + 4.6500004e+01 4.7500004e+01 4.8500004e+01 4.9500004e+01 + 5.0500004e+01 5.1500004e+01 5.2500004e+01 5.3500004e+01 + 5.4500004e+01 5.5500004e+01 5.6500004e+01 5.7500004e+01 + 5.8500004e+01 5.9500004e+01 6.0500004e+01 6.1500004e+01 + 6.2500004e+01 6.3500004e+01 6.4500008e+01 6.5500008e+01 + 6.6500008e+01 6.7500008e+01 6.8500008e+01 6.9500008e+01 + 7.0500008e+01 7.1500008e+01 7.2500008e+01 7.3500008e+01 + 7.4500008e+01 7.5500008e+01 7.6500008e+01 7.7500008e+01 + 7.8500008e+01 7.9500008e+01 8.0500008e+01 8.1500008e+01 + 8.2500008e+01 8.3500008e+01 8.4500008e+01 8.5500008e+01 + 8.6500008e+01 8.7500008e+01 8.8500008e+01 8.9500008e+01] + y_upper_bound: [-8.9500000e+01 -8.8500000e+01 -8.7500000e+01 -8.6500000e+01 + -8.5500000e+01 -8.4500000e+01 -8.3500000e+01 -8.2500000e+01 + -8.1500000e+01 -8.0500000e+01 -7.9500000e+01 -7.8500000e+01 + -7.7500000e+01 -7.6500000e+01 -7.5500000e+01 -7.4500000e+01 + -7.3500000e+01 -7.2500000e+01 -7.1500000e+01 -7.0500000e+01 + -6.9500000e+01 -6.8500000e+01 -6.7500000e+01 -6.6500000e+01 + -6.5500000e+01 -6.4500000e+01 -6.3500000e+01 -6.2500000e+01 + -6.1500000e+01 -6.0500000e+01 -5.9500000e+01 -5.8500000e+01 + -5.7500000e+01 -5.6500000e+01 -5.5500000e+01 -5.4500000e+01 + -5.3500000e+01 -5.2500000e+01 -5.1500000e+01 -5.0500000e+01 + -4.9500000e+01 -4.8500000e+01 -4.7500000e+01 -4.6500000e+01 + -4.5500000e+01 -4.4500000e+01 -4.3500000e+01 -4.2500000e+01 + -4.1500000e+01 -4.0500000e+01 -3.9500000e+01 -3.8500000e+01 + -3.7500000e+01 -3.6500000e+01 -3.5500000e+01 -3.4500000e+01 + -3.3500000e+01 -3.2500000e+01 -3.1500000e+01 -3.0500771e+01 + -2.9503845e+01 -2.8510752e+01 -2.7522995e+01 -2.6542061e+01 + -2.5569395e+01 -2.4606415e+01 -2.3654484e+01 -2.2714918e+01 + -2.1788977e+01 -2.0877851e+01 -1.9982668e+01 -1.9104479e+01 + -1.8244253e+01 -1.7402882e+01 -1.6581161e+01 -1.5779803e+01 + -1.4999418e+01 -1.4240523e+01 -1.3503533e+01 -1.2788761e+01 + -1.2096417e+01 -1.1426606e+01 -1.0779328e+01 -1.0154477e+01 + -9.5518446e+00 -8.9711180e+00 -8.4118795e+00 -7.8736162e+00 + -7.3557129e+00 -6.8574619e+00 -6.3780642e+00 -5.9166312e+00 + -5.4721909e+00 -5.0436931e+00 -4.6300130e+00 -4.2299562e+00 + -3.8422639e+00 -3.4656219e+00 -3.0986631e+00 -2.7399759e+00 + -2.3881090e+00 -2.0415800e+00 -1.6988820e+00 -1.3584900e+00 + -1.0188670e+00 -6.7924398e-01 -3.3962101e-01 2.0000000e-06 + 3.3962500e-01 6.7924798e-01 1.0188709e+00 1.3584940e+00 + 1.6988860e+00 2.0415840e+00 2.3881130e+00 2.7399800e+00 + 3.0986669e+00 3.4656260e+00 3.8422680e+00 4.2299600e+00 + 4.6300168e+00 5.0436969e+00 5.4721951e+00 5.9166350e+00 + 6.3780680e+00 6.8574662e+00 7.3557172e+00 7.8736200e+00 + 8.4118843e+00 8.9711218e+00 9.5518494e+00 1.0154481e+01 + 1.0779332e+01 1.1426610e+01 1.2096421e+01 1.2788765e+01 + 1.3503537e+01 1.4240527e+01 1.4999422e+01 1.5779807e+01 + 1.6581165e+01 1.7402885e+01 1.8244259e+01 1.9104483e+01 + 1.9982672e+01 2.0877855e+01 2.1788980e+01 2.2714922e+01 + 2.3654488e+01 2.4606419e+01 2.5569401e+01 2.6542065e+01 + 2.7522999e+01 2.8510756e+01 2.9503849e+01 3.0500774e+01 + 3.1500004e+01 3.2500004e+01 3.3500004e+01 3.4500004e+01 + 3.5500004e+01 3.6500004e+01 3.7500004e+01 3.8500004e+01 + 3.9500004e+01 4.0500004e+01 4.1500004e+01 4.2500004e+01 + 4.3500004e+01 4.4500004e+01 4.5500004e+01 4.6500004e+01 + 4.7500004e+01 4.8500004e+01 4.9500004e+01 5.0500004e+01 + 5.1500004e+01 5.2500004e+01 5.3500004e+01 5.4500004e+01 + 5.5500004e+01 5.6500004e+01 5.7500004e+01 5.8500004e+01 + 5.9500004e+01 6.0500004e+01 6.1500004e+01 6.2500004e+01 + 6.3500004e+01 6.4500008e+01 6.5500008e+01 6.6500008e+01 + 6.7500008e+01 6.8500008e+01 6.9500008e+01 7.0500008e+01 + 7.1500008e+01 7.2500008e+01 7.3500008e+01 7.4500008e+01 + 7.5500008e+01 7.6500008e+01 7.7500008e+01 7.8500008e+01 + 7.9500008e+01 8.0500008e+01 8.1500008e+01 8.2500008e+01 + 8.3500008e+01 8.4500008e+01 8.5500008e+01 8.6500008e+01 + 8.7500008e+01 8.8500008e+01 8.9500008e+01 9.0500008e+01] , PP Field lbyr: 2014 lbmon: 8 @@ -256,7 +245,7 @@ bdatum: 0.0 bacc: -99.0 blev: 5.0 - brlev: -1.07374e+09 + brlev: -1073741800.0 bhlev: 0.0 bhrlev: 0.0 bplat: 90.0 @@ -266,172 +255,161 @@ bdy: 0.0 bzx: -1.0 bdx: 1.0 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data.data: [[ 0. 0. 0. ..., 0. 0. 0. ] - [ 0. 0. 0. ..., 0. 0. 0. ] - [ 0. 0. 0. ..., 0. 0. 0. ] - ..., - [ 0.00864433 0.00852169 0.00838812 ..., 0.00917711 0.00897506 - 0.0088051 ] - [ 0.00563598 0.00565888 0.00567179 ..., 0.00559308 0.00561324 - 0.00562014] - [ 0. 0. 0. ..., 0. 0. 0. ]] - data.mask: [[ True True True ..., True True True] - [ True True True ..., True True True] - [ True True True ..., True True True] - ..., - [False False False ..., False False False] - [False False False ..., False False False] - [ True True True ..., True True True]] - y: [-90. -89. -88. -87. -86. -85. -84. - -83. -82. -81. -80. -79. -78. -77. - -76. -75. -74. -73. -72. -71. -70. - -69. -68. -67. -66. -65. -64. -63. - -62. -61. -60. -59. -58. -57. -56. - -55. -54. -53. -52. -51. -50. -49. - -48. -47. -46. -45. -44. -43. -42. - -41. -40. -39. -38. -37. -36. -35. - -34. -33. -32. -31.00038528 -30.00230789 - -29.00729752 -28.01687241 -27.03252792 -26.05572891 -25.08790588 - -24.1304493 -23.18470192 -22.2519474 -21.33341408 -20.4302597 - -19.54357338 -18.674366 -17.82356834 -16.99202156 -16.18048286 - -15.38961029 -14.61997032 -13.87202835 -13.14614677 -12.44258881 - -11.7615118 -11.10296726 -10.46690273 -9.85316086 -9.26148129 - -8.69149876 -8.14274788 -7.61466455 -7.10658741 -6.61776304 - -6.14734745 -5.6944108 -5.2579422 -4.83685303 -4.42998457 - -4.03610992 -3.65394306 -3.2821424 -2.91931939 -2.56404257 - -2.21484447 -1.87023103 -1.52868605 -1.1886785 -0.84905553 - -0.50943249 -0.16980951 0.1698135 0.50943649 0.84905952 - 1.18868256 1.52868998 1.87023497 2.21484852 2.56404638 - 2.91932344 3.28214645 3.65394711 4.03611422 4.42998838 - 4.83685684 5.25794601 5.69441509 6.14735126 6.61776686 - 7.1065917 7.61466837 8.14275169 8.69150257 9.2614851 - 9.85316467 10.46690655 11.10297108 11.76151562 12.44259262 - 13.14615059 13.87203217 14.61997414 15.38961411 16.18048668 - 16.99202538 17.82357216 18.67436981 19.54357719 20.43026352 - 21.33341789 22.25195122 23.18470573 24.13045311 25.0879097 - 26.05573273 27.03253174 28.01687622 29.00730133 30.00231171 - 31.0003891 32.00000381 33.00000381 34.00000381 35.00000381 - 36.00000381 37.00000381 38.00000381 39.00000381 40.00000381 - 41.00000381 42.00000381 43.00000381 44.00000381 45.00000381 - 46.00000381 47.00000381 48.00000381 49.00000381 50.00000381 - 51.00000381 52.00000381 53.00000381 54.00000381 55.00000381 - 56.00000381 57.00000381 58.00000381 59.00000381 60.00000381 - 61.00000381 62.00000381 63.00000381 64.00000763 65.00000763 - 66.00000763 67.00000763 68.00000763 69.00000763 70.00000763 - 71.00000763 72.00000763 73.00000763 74.00000763 75.00000763 - 76.00000763 77.00000763 78.00000763 79.00000763 80.00000763 - 81.00000763 82.00000763 83.00000763 84.00000763 85.00000763 - 86.00000763 87.00000763 88.00000763 89.00000763 90.00000763] - y_lower_bound: [ -9.05000000e+01 -8.95000000e+01 -8.85000000e+01 -8.75000000e+01 - -8.65000000e+01 -8.55000000e+01 -8.45000000e+01 -8.35000000e+01 - -8.25000000e+01 -8.15000000e+01 -8.05000000e+01 -7.95000000e+01 - -7.85000000e+01 -7.75000000e+01 -7.65000000e+01 -7.55000000e+01 - -7.45000000e+01 -7.35000000e+01 -7.25000000e+01 -7.15000000e+01 - -7.05000000e+01 -6.95000000e+01 -6.85000000e+01 -6.75000000e+01 - -6.65000000e+01 -6.55000000e+01 -6.45000000e+01 -6.35000000e+01 - -6.25000000e+01 -6.15000000e+01 -6.05000000e+01 -5.95000000e+01 - -5.85000000e+01 -5.75000000e+01 -5.65000000e+01 -5.55000000e+01 - -5.45000000e+01 -5.35000000e+01 -5.25000000e+01 -5.15000000e+01 - -5.05000000e+01 -4.95000000e+01 -4.85000000e+01 -4.75000000e+01 - -4.65000000e+01 -4.55000000e+01 -4.45000000e+01 -4.35000000e+01 - -4.25000000e+01 -4.15000000e+01 -4.05000000e+01 -3.95000000e+01 - -3.85000000e+01 -3.75000000e+01 -3.65000000e+01 -3.55000000e+01 - -3.45000000e+01 -3.35000000e+01 -3.25000000e+01 -3.15000000e+01 - -3.05007706e+01 -2.95038452e+01 -2.85107517e+01 -2.75229950e+01 - -2.65420609e+01 -2.55693951e+01 -2.46064148e+01 -2.36544838e+01 - -2.27149181e+01 -2.17889767e+01 -2.08778515e+01 -1.99826679e+01 - -1.91044788e+01 -1.82442532e+01 -1.74028816e+01 -1.65811615e+01 - -1.57798033e+01 -1.49994183e+01 -1.42405233e+01 -1.35035334e+01 - -1.27887611e+01 -1.20964174e+01 -1.14266062e+01 -1.07793283e+01 - -1.01544771e+01 -9.55184460e+00 -8.97111797e+00 -8.41187954e+00 - -7.87361622e+00 -7.35571289e+00 -6.85746193e+00 -6.37806416e+00 - -5.91663122e+00 -5.47219086e+00 -5.04369307e+00 -4.63001299e+00 - -4.22995615e+00 -3.84226394e+00 -3.46562195e+00 -3.09866309e+00 - -2.73997593e+00 -2.38810897e+00 -2.04157996e+00 -1.69888198e+00 - -1.35848999e+00 -1.01886702e+00 -6.79243982e-01 -3.39621007e-01 - 1.99999999e-06 3.39625001e-01 6.79247975e-01 1.01887095e+00 - 1.35849404e+00 1.69888604e+00 2.04158401e+00 2.38811302e+00 - 2.73997998e+00 3.09866691e+00 3.46562600e+00 3.84226799e+00 - 4.22995996e+00 4.63001680e+00 5.04369688e+00 5.47219515e+00 - 5.91663504e+00 6.37806797e+00 6.85746622e+00 7.35571718e+00 - 7.87362003e+00 8.41188431e+00 8.97112179e+00 9.55184937e+00 - 1.01544809e+01 1.07793322e+01 1.14266100e+01 1.20964212e+01 - 1.27887650e+01 1.35035372e+01 1.42405272e+01 1.49994221e+01 - 1.57798071e+01 1.65811653e+01 1.74028854e+01 1.82442589e+01 - 1.91044827e+01 1.99826717e+01 2.08778553e+01 2.17889805e+01 - 2.27149220e+01 2.36544876e+01 2.46064186e+01 2.55694008e+01 - 2.65420647e+01 2.75229988e+01 2.85107555e+01 2.95038490e+01 - 3.05007744e+01 3.15000038e+01 3.25000038e+01 3.35000038e+01 - 3.45000038e+01 3.55000038e+01 3.65000038e+01 3.75000038e+01 - 3.85000038e+01 3.95000038e+01 4.05000038e+01 4.15000038e+01 - 4.25000038e+01 4.35000038e+01 4.45000038e+01 4.55000038e+01 - 4.65000038e+01 4.75000038e+01 4.85000038e+01 4.95000038e+01 - 5.05000038e+01 5.15000038e+01 5.25000038e+01 5.35000038e+01 - 5.45000038e+01 5.55000038e+01 5.65000038e+01 5.75000038e+01 - 5.85000038e+01 5.95000038e+01 6.05000038e+01 6.15000038e+01 - 6.25000038e+01 6.35000038e+01 6.45000076e+01 6.55000076e+01 - 6.65000076e+01 6.75000076e+01 6.85000076e+01 6.95000076e+01 - 7.05000076e+01 7.15000076e+01 7.25000076e+01 7.35000076e+01 - 7.45000076e+01 7.55000076e+01 7.65000076e+01 7.75000076e+01 - 7.85000076e+01 7.95000076e+01 8.05000076e+01 8.15000076e+01 - 8.25000076e+01 8.35000076e+01 8.45000076e+01 8.55000076e+01 - 8.65000076e+01 8.75000076e+01 8.85000076e+01 8.95000076e+01] - y_upper_bound: [ -8.95000000e+01 -8.85000000e+01 -8.75000000e+01 -8.65000000e+01 - -8.55000000e+01 -8.45000000e+01 -8.35000000e+01 -8.25000000e+01 - -8.15000000e+01 -8.05000000e+01 -7.95000000e+01 -7.85000000e+01 - -7.75000000e+01 -7.65000000e+01 -7.55000000e+01 -7.45000000e+01 - -7.35000000e+01 -7.25000000e+01 -7.15000000e+01 -7.05000000e+01 - -6.95000000e+01 -6.85000000e+01 -6.75000000e+01 -6.65000000e+01 - -6.55000000e+01 -6.45000000e+01 -6.35000000e+01 -6.25000000e+01 - -6.15000000e+01 -6.05000000e+01 -5.95000000e+01 -5.85000000e+01 - -5.75000000e+01 -5.65000000e+01 -5.55000000e+01 -5.45000000e+01 - -5.35000000e+01 -5.25000000e+01 -5.15000000e+01 -5.05000000e+01 - -4.95000000e+01 -4.85000000e+01 -4.75000000e+01 -4.65000000e+01 - -4.55000000e+01 -4.45000000e+01 -4.35000000e+01 -4.25000000e+01 - -4.15000000e+01 -4.05000000e+01 -3.95000000e+01 -3.85000000e+01 - -3.75000000e+01 -3.65000000e+01 -3.55000000e+01 -3.45000000e+01 - -3.35000000e+01 -3.25000000e+01 -3.15000000e+01 -3.05007706e+01 - -2.95038452e+01 -2.85107517e+01 -2.75229950e+01 -2.65420609e+01 - -2.55693951e+01 -2.46064148e+01 -2.36544838e+01 -2.27149181e+01 - -2.17889767e+01 -2.08778515e+01 -1.99826679e+01 -1.91044788e+01 - -1.82442532e+01 -1.74028816e+01 -1.65811615e+01 -1.57798033e+01 - -1.49994183e+01 -1.42405233e+01 -1.35035334e+01 -1.27887611e+01 - -1.20964174e+01 -1.14266062e+01 -1.07793283e+01 -1.01544771e+01 - -9.55184460e+00 -8.97111797e+00 -8.41187954e+00 -7.87361622e+00 - -7.35571289e+00 -6.85746193e+00 -6.37806416e+00 -5.91663122e+00 - -5.47219086e+00 -5.04369307e+00 -4.63001299e+00 -4.22995615e+00 - -3.84226394e+00 -3.46562195e+00 -3.09866309e+00 -2.73997593e+00 - -2.38810897e+00 -2.04157996e+00 -1.69888198e+00 -1.35848999e+00 - -1.01886702e+00 -6.79243982e-01 -3.39621007e-01 1.99999999e-06 - 3.39625001e-01 6.79247975e-01 1.01887095e+00 1.35849404e+00 - 1.69888604e+00 2.04158401e+00 2.38811302e+00 2.73997998e+00 - 3.09866691e+00 3.46562600e+00 3.84226799e+00 4.22995996e+00 - 4.63001680e+00 5.04369688e+00 5.47219515e+00 5.91663504e+00 - 6.37806797e+00 6.85746622e+00 7.35571718e+00 7.87362003e+00 - 8.41188431e+00 8.97112179e+00 9.55184937e+00 1.01544809e+01 - 1.07793322e+01 1.14266100e+01 1.20964212e+01 1.27887650e+01 - 1.35035372e+01 1.42405272e+01 1.49994221e+01 1.57798071e+01 - 1.65811653e+01 1.74028854e+01 1.82442589e+01 1.91044827e+01 - 1.99826717e+01 2.08778553e+01 2.17889805e+01 2.27149220e+01 - 2.36544876e+01 2.46064186e+01 2.55694008e+01 2.65420647e+01 - 2.75229988e+01 2.85107555e+01 2.95038490e+01 3.05007744e+01 - 3.15000038e+01 3.25000038e+01 3.35000038e+01 3.45000038e+01 - 3.55000038e+01 3.65000038e+01 3.75000038e+01 3.85000038e+01 - 3.95000038e+01 4.05000038e+01 4.15000038e+01 4.25000038e+01 - 4.35000038e+01 4.45000038e+01 4.55000038e+01 4.65000038e+01 - 4.75000038e+01 4.85000038e+01 4.95000038e+01 5.05000038e+01 - 5.15000038e+01 5.25000038e+01 5.35000038e+01 5.45000038e+01 - 5.55000038e+01 5.65000038e+01 5.75000038e+01 5.85000038e+01 - 5.95000038e+01 6.05000038e+01 6.15000038e+01 6.25000038e+01 - 6.35000038e+01 6.45000076e+01 6.55000076e+01 6.65000076e+01 - 6.75000076e+01 6.85000076e+01 6.95000076e+01 7.05000076e+01 - 7.15000076e+01 7.25000076e+01 7.35000076e+01 7.45000076e+01 - 7.55000076e+01 7.65000076e+01 7.75000076e+01 7.85000076e+01 - 7.95000076e+01 8.05000076e+01 8.15000076e+01 8.25000076e+01 - 8.35000076e+01 8.45000076e+01 8.55000076e+01 8.65000076e+01 - 8.75000076e+01 8.85000076e+01 8.95000076e+01 9.05000076e+01] + data: [[-- -- -- ... -- -- --] + [-- -- -- ... -- -- --] + [-- -- -- ... -- -- --] + ... + [0.00864433217793703 0.008521686308085918 0.008388116024434566 ... + 0.009177112020552158 0.008975056000053883 0.008805099874734879] + [0.005635980516672134 0.005658876616507769 0.005671785678714514 ... + 0.00559308473020792 0.00561324181035161 0.005620136857032776] + [-- -- -- ... -- -- --]] + y: [-90. -89. -88. -87. -86. -85. + -84. -83. -82. -81. -80. -79. + -78. -77. -76. -75. -74. -73. + -72. -71. -70. -69. -68. -67. + -66. -65. -64. -63. -62. -61. + -60. -59. -58. -57. -56. -55. + -54. -53. -52. -51. -50. -49. + -48. -47. -46. -45. -44. -43. + -42. -41. -40. -39. -38. -37. + -36. -35. -34. -33. -32. -31.000385 + -30.002308 -29.007298 -28.016872 -27.032528 -26.055729 -25.087906 + -24.13045 -23.184702 -22.251947 -21.333414 -20.43026 -19.543573 + -18.674366 -17.823568 -16.992022 -16.180483 -15.38961 -14.61997 + -13.872028 -13.146147 -12.442589 -11.761512 -11.102967 -10.466903 + -9.853161 -9.261481 -8.691499 -8.142748 -7.6146646 -7.1065874 + -6.617763 -6.1473475 -5.694411 -5.257942 -4.836853 -4.4299846 + -4.03611 -3.653943 -3.2821424 -2.9193194 -2.5640426 -2.2148445 + -1.870231 -1.528686 -1.1886785 -0.8490555 -0.5094325 -0.1698095 + 0.1698135 0.5094365 0.8490595 1.1886826 1.52869 1.870235 + 2.2148485 2.5640464 2.9193234 3.2821465 3.653947 4.036114 + 4.4299884 4.836857 5.257946 5.694415 6.1473513 6.617767 + 7.1065917 7.6146684 8.142752 8.691503 9.261485 9.853165 + 10.466907 11.102971 11.761516 12.442593 13.146151 13.872032 + 14.619974 15.389614 16.180487 16.992025 17.823572 18.67437 + 19.543577 20.430264 21.333418 22.251951 23.184706 24.130453 + 25.08791 26.055733 27.032532 28.016876 29.007301 30.002312 + 31.00039 32.000004 33.000004 34.000004 35.000004 36.000004 + 37.000004 38.000004 39.000004 40.000004 41.000004 42.000004 + 43.000004 44.000004 45.000004 46.000004 47.000004 48.000004 + 49.000004 50.000004 51.000004 52.000004 53.000004 54.000004 + 55.000004 56.000004 57.000004 58.000004 59.000004 60.000004 + 61.000004 62.000004 63.000004 64.00001 65.00001 66.00001 + 67.00001 68.00001 69.00001 70.00001 71.00001 72.00001 + 73.00001 74.00001 75.00001 76.00001 77.00001 78.00001 + 79.00001 80.00001 81.00001 82.00001 83.00001 84.00001 + 85.00001 86.00001 87.00001 88.00001 89.00001 90.00001 ] + y_lower_bound: [-9.0500000e+01 -8.9500000e+01 -8.8500000e+01 -8.7500000e+01 + -8.6500000e+01 -8.5500000e+01 -8.4500000e+01 -8.3500000e+01 + -8.2500000e+01 -8.1500000e+01 -8.0500000e+01 -7.9500000e+01 + -7.8500000e+01 -7.7500000e+01 -7.6500000e+01 -7.5500000e+01 + -7.4500000e+01 -7.3500000e+01 -7.2500000e+01 -7.1500000e+01 + -7.0500000e+01 -6.9500000e+01 -6.8500000e+01 -6.7500000e+01 + -6.6500000e+01 -6.5500000e+01 -6.4500000e+01 -6.3500000e+01 + -6.2500000e+01 -6.1500000e+01 -6.0500000e+01 -5.9500000e+01 + -5.8500000e+01 -5.7500000e+01 -5.6500000e+01 -5.5500000e+01 + -5.4500000e+01 -5.3500000e+01 -5.2500000e+01 -5.1500000e+01 + -5.0500000e+01 -4.9500000e+01 -4.8500000e+01 -4.7500000e+01 + -4.6500000e+01 -4.5500000e+01 -4.4500000e+01 -4.3500000e+01 + -4.2500000e+01 -4.1500000e+01 -4.0500000e+01 -3.9500000e+01 + -3.8500000e+01 -3.7500000e+01 -3.6500000e+01 -3.5500000e+01 + -3.4500000e+01 -3.3500000e+01 -3.2500000e+01 -3.1500000e+01 + -3.0500771e+01 -2.9503845e+01 -2.8510752e+01 -2.7522995e+01 + -2.6542061e+01 -2.5569395e+01 -2.4606415e+01 -2.3654484e+01 + -2.2714918e+01 -2.1788977e+01 -2.0877851e+01 -1.9982668e+01 + -1.9104479e+01 -1.8244253e+01 -1.7402882e+01 -1.6581161e+01 + -1.5779803e+01 -1.4999418e+01 -1.4240523e+01 -1.3503533e+01 + -1.2788761e+01 -1.2096417e+01 -1.1426606e+01 -1.0779328e+01 + -1.0154477e+01 -9.5518446e+00 -8.9711180e+00 -8.4118795e+00 + -7.8736162e+00 -7.3557129e+00 -6.8574619e+00 -6.3780642e+00 + -5.9166312e+00 -5.4721909e+00 -5.0436931e+00 -4.6300130e+00 + -4.2299562e+00 -3.8422639e+00 -3.4656219e+00 -3.0986631e+00 + -2.7399759e+00 -2.3881090e+00 -2.0415800e+00 -1.6988820e+00 + -1.3584900e+00 -1.0188670e+00 -6.7924398e-01 -3.3962101e-01 + 2.0000000e-06 3.3962500e-01 6.7924798e-01 1.0188709e+00 + 1.3584940e+00 1.6988860e+00 2.0415840e+00 2.3881130e+00 + 2.7399800e+00 3.0986669e+00 3.4656260e+00 3.8422680e+00 + 4.2299600e+00 4.6300168e+00 5.0436969e+00 5.4721951e+00 + 5.9166350e+00 6.3780680e+00 6.8574662e+00 7.3557172e+00 + 7.8736200e+00 8.4118843e+00 8.9711218e+00 9.5518494e+00 + 1.0154481e+01 1.0779332e+01 1.1426610e+01 1.2096421e+01 + 1.2788765e+01 1.3503537e+01 1.4240527e+01 1.4999422e+01 + 1.5779807e+01 1.6581165e+01 1.7402885e+01 1.8244259e+01 + 1.9104483e+01 1.9982672e+01 2.0877855e+01 2.1788980e+01 + 2.2714922e+01 2.3654488e+01 2.4606419e+01 2.5569401e+01 + 2.6542065e+01 2.7522999e+01 2.8510756e+01 2.9503849e+01 + 3.0500774e+01 3.1500004e+01 3.2500004e+01 3.3500004e+01 + 3.4500004e+01 3.5500004e+01 3.6500004e+01 3.7500004e+01 + 3.8500004e+01 3.9500004e+01 4.0500004e+01 4.1500004e+01 + 4.2500004e+01 4.3500004e+01 4.4500004e+01 4.5500004e+01 + 4.6500004e+01 4.7500004e+01 4.8500004e+01 4.9500004e+01 + 5.0500004e+01 5.1500004e+01 5.2500004e+01 5.3500004e+01 + 5.4500004e+01 5.5500004e+01 5.6500004e+01 5.7500004e+01 + 5.8500004e+01 5.9500004e+01 6.0500004e+01 6.1500004e+01 + 6.2500004e+01 6.3500004e+01 6.4500008e+01 6.5500008e+01 + 6.6500008e+01 6.7500008e+01 6.8500008e+01 6.9500008e+01 + 7.0500008e+01 7.1500008e+01 7.2500008e+01 7.3500008e+01 + 7.4500008e+01 7.5500008e+01 7.6500008e+01 7.7500008e+01 + 7.8500008e+01 7.9500008e+01 8.0500008e+01 8.1500008e+01 + 8.2500008e+01 8.3500008e+01 8.4500008e+01 8.5500008e+01 + 8.6500008e+01 8.7500008e+01 8.8500008e+01 8.9500008e+01] + y_upper_bound: [-8.9500000e+01 -8.8500000e+01 -8.7500000e+01 -8.6500000e+01 + -8.5500000e+01 -8.4500000e+01 -8.3500000e+01 -8.2500000e+01 + -8.1500000e+01 -8.0500000e+01 -7.9500000e+01 -7.8500000e+01 + -7.7500000e+01 -7.6500000e+01 -7.5500000e+01 -7.4500000e+01 + -7.3500000e+01 -7.2500000e+01 -7.1500000e+01 -7.0500000e+01 + -6.9500000e+01 -6.8500000e+01 -6.7500000e+01 -6.6500000e+01 + -6.5500000e+01 -6.4500000e+01 -6.3500000e+01 -6.2500000e+01 + -6.1500000e+01 -6.0500000e+01 -5.9500000e+01 -5.8500000e+01 + -5.7500000e+01 -5.6500000e+01 -5.5500000e+01 -5.4500000e+01 + -5.3500000e+01 -5.2500000e+01 -5.1500000e+01 -5.0500000e+01 + -4.9500000e+01 -4.8500000e+01 -4.7500000e+01 -4.6500000e+01 + -4.5500000e+01 -4.4500000e+01 -4.3500000e+01 -4.2500000e+01 + -4.1500000e+01 -4.0500000e+01 -3.9500000e+01 -3.8500000e+01 + -3.7500000e+01 -3.6500000e+01 -3.5500000e+01 -3.4500000e+01 + -3.3500000e+01 -3.2500000e+01 -3.1500000e+01 -3.0500771e+01 + -2.9503845e+01 -2.8510752e+01 -2.7522995e+01 -2.6542061e+01 + -2.5569395e+01 -2.4606415e+01 -2.3654484e+01 -2.2714918e+01 + -2.1788977e+01 -2.0877851e+01 -1.9982668e+01 -1.9104479e+01 + -1.8244253e+01 -1.7402882e+01 -1.6581161e+01 -1.5779803e+01 + -1.4999418e+01 -1.4240523e+01 -1.3503533e+01 -1.2788761e+01 + -1.2096417e+01 -1.1426606e+01 -1.0779328e+01 -1.0154477e+01 + -9.5518446e+00 -8.9711180e+00 -8.4118795e+00 -7.8736162e+00 + -7.3557129e+00 -6.8574619e+00 -6.3780642e+00 -5.9166312e+00 + -5.4721909e+00 -5.0436931e+00 -4.6300130e+00 -4.2299562e+00 + -3.8422639e+00 -3.4656219e+00 -3.0986631e+00 -2.7399759e+00 + -2.3881090e+00 -2.0415800e+00 -1.6988820e+00 -1.3584900e+00 + -1.0188670e+00 -6.7924398e-01 -3.3962101e-01 2.0000000e-06 + 3.3962500e-01 6.7924798e-01 1.0188709e+00 1.3584940e+00 + 1.6988860e+00 2.0415840e+00 2.3881130e+00 2.7399800e+00 + 3.0986669e+00 3.4656260e+00 3.8422680e+00 4.2299600e+00 + 4.6300168e+00 5.0436969e+00 5.4721951e+00 5.9166350e+00 + 6.3780680e+00 6.8574662e+00 7.3557172e+00 7.8736200e+00 + 8.4118843e+00 8.9711218e+00 9.5518494e+00 1.0154481e+01 + 1.0779332e+01 1.1426610e+01 1.2096421e+01 1.2788765e+01 + 1.3503537e+01 1.4240527e+01 1.4999422e+01 1.5779807e+01 + 1.6581165e+01 1.7402885e+01 1.8244259e+01 1.9104483e+01 + 1.9982672e+01 2.0877855e+01 2.1788980e+01 2.2714922e+01 + 2.3654488e+01 2.4606419e+01 2.5569401e+01 2.6542065e+01 + 2.7522999e+01 2.8510756e+01 2.9503849e+01 3.0500774e+01 + 3.1500004e+01 3.2500004e+01 3.3500004e+01 3.4500004e+01 + 3.5500004e+01 3.6500004e+01 3.7500004e+01 3.8500004e+01 + 3.9500004e+01 4.0500004e+01 4.1500004e+01 4.2500004e+01 + 4.3500004e+01 4.4500004e+01 4.5500004e+01 4.6500004e+01 + 4.7500004e+01 4.8500004e+01 4.9500004e+01 5.0500004e+01 + 5.1500004e+01 5.2500004e+01 5.3500004e+01 5.4500004e+01 + 5.5500004e+01 5.6500004e+01 5.7500004e+01 5.8500004e+01 + 5.9500004e+01 6.0500004e+01 6.1500004e+01 6.2500004e+01 + 6.3500004e+01 6.4500008e+01 6.5500008e+01 6.6500008e+01 + 6.7500008e+01 6.8500008e+01 6.9500008e+01 7.0500008e+01 + 7.1500008e+01 7.2500008e+01 7.3500008e+01 7.4500008e+01 + 7.5500008e+01 7.6500008e+01 7.7500008e+01 7.8500008e+01 + 7.9500008e+01 8.0500008e+01 8.1500008e+01 8.2500008e+01 + 8.3500008e+01 8.4500008e+01 8.5500008e+01 8.6500008e+01 + 8.7500008e+01 8.8500008e+01 8.9500008e+01 9.0500008e+01] , PP Field lbyr: 2014 lbmon: 8 @@ -473,7 +451,7 @@ bdatum: 0.0 bacc: -99.0 blev: 5.0 - brlev: -1.07374e+09 + brlev: -1073741800.0 bhlev: 0.0 bhrlev: 0.0 bplat: 90.0 @@ -483,168 +461,157 @@ bdy: 0.0 bzx: -1.0 bdx: 1.0 - bmdi: -1.07374e+09 + bmdi: -1073741800.0 bmks: 1.0 - data.data: [[ 0. 0. 0. ..., 0. 0. 0.] - [ 0. 0. 0. ..., 0. 0. 0.] - [ 0. 0. 0. ..., 0. 0. 0.] - ..., - [ 0. 0. 0. ..., 0. 0. 0.] - [ 0. 0. 0. ..., 0. 0. 0.] - [ 0. 0. 0. ..., 0. 0. 0.]] - data.mask: [[ True True True ..., True True True] - [ True True True ..., True True True] - [ True True True ..., True True True] - ..., - [False False False ..., False False False] - [False False False ..., False False False] - [ True True True ..., True True True]] - y: [-90. -89. -88. -87. -86. -85. -84. - -83. -82. -81. -80. -79. -78. -77. - -76. -75. -74. -73. -72. -71. -70. - -69. -68. -67. -66. -65. -64. -63. - -62. -61. -60. -59. -58. -57. -56. - -55. -54. -53. -52. -51. -50. -49. - -48. -47. -46. -45. -44. -43. -42. - -41. -40. -39. -38. -37. -36. -35. - -34. -33. -32. -31.00038528 -30.00230789 - -29.00729752 -28.01687241 -27.03252792 -26.05572891 -25.08790588 - -24.1304493 -23.18470192 -22.2519474 -21.33341408 -20.4302597 - -19.54357338 -18.674366 -17.82356834 -16.99202156 -16.18048286 - -15.38961029 -14.61997032 -13.87202835 -13.14614677 -12.44258881 - -11.7615118 -11.10296726 -10.46690273 -9.85316086 -9.26148129 - -8.69149876 -8.14274788 -7.61466455 -7.10658741 -6.61776304 - -6.14734745 -5.6944108 -5.2579422 -4.83685303 -4.42998457 - -4.03610992 -3.65394306 -3.2821424 -2.91931939 -2.56404257 - -2.21484447 -1.87023103 -1.52868605 -1.1886785 -0.84905553 - -0.50943249 -0.16980951 0.1698135 0.50943649 0.84905952 - 1.18868256 1.52868998 1.87023497 2.21484852 2.56404638 - 2.91932344 3.28214645 3.65394711 4.03611422 4.42998838 - 4.83685684 5.25794601 5.69441509 6.14735126 6.61776686 - 7.1065917 7.61466837 8.14275169 8.69150257 9.2614851 - 9.85316467 10.46690655 11.10297108 11.76151562 12.44259262 - 13.14615059 13.87203217 14.61997414 15.38961411 16.18048668 - 16.99202538 17.82357216 18.67436981 19.54357719 20.43026352 - 21.33341789 22.25195122 23.18470573 24.13045311 25.0879097 - 26.05573273 27.03253174 28.01687622 29.00730133 30.00231171 - 31.0003891 32.00000381 33.00000381 34.00000381 35.00000381 - 36.00000381 37.00000381 38.00000381 39.00000381 40.00000381 - 41.00000381 42.00000381 43.00000381 44.00000381 45.00000381 - 46.00000381 47.00000381 48.00000381 49.00000381 50.00000381 - 51.00000381 52.00000381 53.00000381 54.00000381 55.00000381 - 56.00000381 57.00000381 58.00000381 59.00000381 60.00000381 - 61.00000381 62.00000381 63.00000381 64.00000763 65.00000763 - 66.00000763 67.00000763 68.00000763 69.00000763 70.00000763 - 71.00000763 72.00000763 73.00000763 74.00000763 75.00000763 - 76.00000763 77.00000763 78.00000763 79.00000763 80.00000763 - 81.00000763 82.00000763 83.00000763 84.00000763 85.00000763 - 86.00000763 87.00000763 88.00000763 89.00000763 90.00000763] - y_lower_bound: [ -9.05000000e+01 -8.95000000e+01 -8.85000000e+01 -8.75000000e+01 - -8.65000000e+01 -8.55000000e+01 -8.45000000e+01 -8.35000000e+01 - -8.25000000e+01 -8.15000000e+01 -8.05000000e+01 -7.95000000e+01 - -7.85000000e+01 -7.75000000e+01 -7.65000000e+01 -7.55000000e+01 - -7.45000000e+01 -7.35000000e+01 -7.25000000e+01 -7.15000000e+01 - -7.05000000e+01 -6.95000000e+01 -6.85000000e+01 -6.75000000e+01 - -6.65000000e+01 -6.55000000e+01 -6.45000000e+01 -6.35000000e+01 - -6.25000000e+01 -6.15000000e+01 -6.05000000e+01 -5.95000000e+01 - -5.85000000e+01 -5.75000000e+01 -5.65000000e+01 -5.55000000e+01 - -5.45000000e+01 -5.35000000e+01 -5.25000000e+01 -5.15000000e+01 - -5.05000000e+01 -4.95000000e+01 -4.85000000e+01 -4.75000000e+01 - -4.65000000e+01 -4.55000000e+01 -4.45000000e+01 -4.35000000e+01 - -4.25000000e+01 -4.15000000e+01 -4.05000000e+01 -3.95000000e+01 - -3.85000000e+01 -3.75000000e+01 -3.65000000e+01 -3.55000000e+01 - -3.45000000e+01 -3.35000000e+01 -3.25000000e+01 -3.15000000e+01 - -3.05007706e+01 -2.95038452e+01 -2.85107517e+01 -2.75229950e+01 - -2.65420609e+01 -2.55693951e+01 -2.46064148e+01 -2.36544838e+01 - -2.27149181e+01 -2.17889767e+01 -2.08778515e+01 -1.99826679e+01 - -1.91044788e+01 -1.82442532e+01 -1.74028816e+01 -1.65811615e+01 - -1.57798033e+01 -1.49994183e+01 -1.42405233e+01 -1.35035334e+01 - -1.27887611e+01 -1.20964174e+01 -1.14266062e+01 -1.07793283e+01 - -1.01544771e+01 -9.55184460e+00 -8.97111797e+00 -8.41187954e+00 - -7.87361622e+00 -7.35571289e+00 -6.85746193e+00 -6.37806416e+00 - -5.91663122e+00 -5.47219086e+00 -5.04369307e+00 -4.63001299e+00 - -4.22995615e+00 -3.84226394e+00 -3.46562195e+00 -3.09866309e+00 - -2.73997593e+00 -2.38810897e+00 -2.04157996e+00 -1.69888198e+00 - -1.35848999e+00 -1.01886702e+00 -6.79243982e-01 -3.39621007e-01 - 1.99999999e-06 3.39625001e-01 6.79247975e-01 1.01887095e+00 - 1.35849404e+00 1.69888604e+00 2.04158401e+00 2.38811302e+00 - 2.73997998e+00 3.09866691e+00 3.46562600e+00 3.84226799e+00 - 4.22995996e+00 4.63001680e+00 5.04369688e+00 5.47219515e+00 - 5.91663504e+00 6.37806797e+00 6.85746622e+00 7.35571718e+00 - 7.87362003e+00 8.41188431e+00 8.97112179e+00 9.55184937e+00 - 1.01544809e+01 1.07793322e+01 1.14266100e+01 1.20964212e+01 - 1.27887650e+01 1.35035372e+01 1.42405272e+01 1.49994221e+01 - 1.57798071e+01 1.65811653e+01 1.74028854e+01 1.82442589e+01 - 1.91044827e+01 1.99826717e+01 2.08778553e+01 2.17889805e+01 - 2.27149220e+01 2.36544876e+01 2.46064186e+01 2.55694008e+01 - 2.65420647e+01 2.75229988e+01 2.85107555e+01 2.95038490e+01 - 3.05007744e+01 3.15000038e+01 3.25000038e+01 3.35000038e+01 - 3.45000038e+01 3.55000038e+01 3.65000038e+01 3.75000038e+01 - 3.85000038e+01 3.95000038e+01 4.05000038e+01 4.15000038e+01 - 4.25000038e+01 4.35000038e+01 4.45000038e+01 4.55000038e+01 - 4.65000038e+01 4.75000038e+01 4.85000038e+01 4.95000038e+01 - 5.05000038e+01 5.15000038e+01 5.25000038e+01 5.35000038e+01 - 5.45000038e+01 5.55000038e+01 5.65000038e+01 5.75000038e+01 - 5.85000038e+01 5.95000038e+01 6.05000038e+01 6.15000038e+01 - 6.25000038e+01 6.35000038e+01 6.45000076e+01 6.55000076e+01 - 6.65000076e+01 6.75000076e+01 6.85000076e+01 6.95000076e+01 - 7.05000076e+01 7.15000076e+01 7.25000076e+01 7.35000076e+01 - 7.45000076e+01 7.55000076e+01 7.65000076e+01 7.75000076e+01 - 7.85000076e+01 7.95000076e+01 8.05000076e+01 8.15000076e+01 - 8.25000076e+01 8.35000076e+01 8.45000076e+01 8.55000076e+01 - 8.65000076e+01 8.75000076e+01 8.85000076e+01 8.95000076e+01] - y_upper_bound: [ -8.95000000e+01 -8.85000000e+01 -8.75000000e+01 -8.65000000e+01 - -8.55000000e+01 -8.45000000e+01 -8.35000000e+01 -8.25000000e+01 - -8.15000000e+01 -8.05000000e+01 -7.95000000e+01 -7.85000000e+01 - -7.75000000e+01 -7.65000000e+01 -7.55000000e+01 -7.45000000e+01 - -7.35000000e+01 -7.25000000e+01 -7.15000000e+01 -7.05000000e+01 - -6.95000000e+01 -6.85000000e+01 -6.75000000e+01 -6.65000000e+01 - -6.55000000e+01 -6.45000000e+01 -6.35000000e+01 -6.25000000e+01 - -6.15000000e+01 -6.05000000e+01 -5.95000000e+01 -5.85000000e+01 - -5.75000000e+01 -5.65000000e+01 -5.55000000e+01 -5.45000000e+01 - -5.35000000e+01 -5.25000000e+01 -5.15000000e+01 -5.05000000e+01 - -4.95000000e+01 -4.85000000e+01 -4.75000000e+01 -4.65000000e+01 - -4.55000000e+01 -4.45000000e+01 -4.35000000e+01 -4.25000000e+01 - -4.15000000e+01 -4.05000000e+01 -3.95000000e+01 -3.85000000e+01 - -3.75000000e+01 -3.65000000e+01 -3.55000000e+01 -3.45000000e+01 - -3.35000000e+01 -3.25000000e+01 -3.15000000e+01 -3.05007706e+01 - -2.95038452e+01 -2.85107517e+01 -2.75229950e+01 -2.65420609e+01 - -2.55693951e+01 -2.46064148e+01 -2.36544838e+01 -2.27149181e+01 - -2.17889767e+01 -2.08778515e+01 -1.99826679e+01 -1.91044788e+01 - -1.82442532e+01 -1.74028816e+01 -1.65811615e+01 -1.57798033e+01 - -1.49994183e+01 -1.42405233e+01 -1.35035334e+01 -1.27887611e+01 - -1.20964174e+01 -1.14266062e+01 -1.07793283e+01 -1.01544771e+01 - -9.55184460e+00 -8.97111797e+00 -8.41187954e+00 -7.87361622e+00 - -7.35571289e+00 -6.85746193e+00 -6.37806416e+00 -5.91663122e+00 - -5.47219086e+00 -5.04369307e+00 -4.63001299e+00 -4.22995615e+00 - -3.84226394e+00 -3.46562195e+00 -3.09866309e+00 -2.73997593e+00 - -2.38810897e+00 -2.04157996e+00 -1.69888198e+00 -1.35848999e+00 - -1.01886702e+00 -6.79243982e-01 -3.39621007e-01 1.99999999e-06 - 3.39625001e-01 6.79247975e-01 1.01887095e+00 1.35849404e+00 - 1.69888604e+00 2.04158401e+00 2.38811302e+00 2.73997998e+00 - 3.09866691e+00 3.46562600e+00 3.84226799e+00 4.22995996e+00 - 4.63001680e+00 5.04369688e+00 5.47219515e+00 5.91663504e+00 - 6.37806797e+00 6.85746622e+00 7.35571718e+00 7.87362003e+00 - 8.41188431e+00 8.97112179e+00 9.55184937e+00 1.01544809e+01 - 1.07793322e+01 1.14266100e+01 1.20964212e+01 1.27887650e+01 - 1.35035372e+01 1.42405272e+01 1.49994221e+01 1.57798071e+01 - 1.65811653e+01 1.74028854e+01 1.82442589e+01 1.91044827e+01 - 1.99826717e+01 2.08778553e+01 2.17889805e+01 2.27149220e+01 - 2.36544876e+01 2.46064186e+01 2.55694008e+01 2.65420647e+01 - 2.75229988e+01 2.85107555e+01 2.95038490e+01 3.05007744e+01 - 3.15000038e+01 3.25000038e+01 3.35000038e+01 3.45000038e+01 - 3.55000038e+01 3.65000038e+01 3.75000038e+01 3.85000038e+01 - 3.95000038e+01 4.05000038e+01 4.15000038e+01 4.25000038e+01 - 4.35000038e+01 4.45000038e+01 4.55000038e+01 4.65000038e+01 - 4.75000038e+01 4.85000038e+01 4.95000038e+01 5.05000038e+01 - 5.15000038e+01 5.25000038e+01 5.35000038e+01 5.45000038e+01 - 5.55000038e+01 5.65000038e+01 5.75000038e+01 5.85000038e+01 - 5.95000038e+01 6.05000038e+01 6.15000038e+01 6.25000038e+01 - 6.35000038e+01 6.45000076e+01 6.55000076e+01 6.65000076e+01 - 6.75000076e+01 6.85000076e+01 6.95000076e+01 7.05000076e+01 - 7.15000076e+01 7.25000076e+01 7.35000076e+01 7.45000076e+01 - 7.55000076e+01 7.65000076e+01 7.75000076e+01 7.85000076e+01 - 7.95000076e+01 8.05000076e+01 8.15000076e+01 8.25000076e+01 - 8.35000076e+01 8.45000076e+01 8.55000076e+01 8.65000076e+01 - 8.75000076e+01 8.85000076e+01 8.95000076e+01 9.05000076e+01] + data: [[-- -- -- ... -- -- --] + [-- -- -- ... -- -- --] + [-- -- -- ... -- -- --] + ... + [0.0 0.0 0.0 ... 0.0 0.0 0.0] + [0.0 0.0 0.0 ... 0.0 0.0 0.0] + [-- -- -- ... -- -- --]] + y: [-90. -89. -88. -87. -86. -85. + -84. -83. -82. -81. -80. -79. + -78. -77. -76. -75. -74. -73. + -72. -71. -70. -69. -68. -67. + -66. -65. -64. -63. -62. -61. + -60. -59. -58. -57. -56. -55. + -54. -53. -52. -51. -50. -49. + -48. -47. -46. -45. -44. -43. + -42. -41. -40. -39. -38. -37. + -36. -35. -34. -33. -32. -31.000385 + -30.002308 -29.007298 -28.016872 -27.032528 -26.055729 -25.087906 + -24.13045 -23.184702 -22.251947 -21.333414 -20.43026 -19.543573 + -18.674366 -17.823568 -16.992022 -16.180483 -15.38961 -14.61997 + -13.872028 -13.146147 -12.442589 -11.761512 -11.102967 -10.466903 + -9.853161 -9.261481 -8.691499 -8.142748 -7.6146646 -7.1065874 + -6.617763 -6.1473475 -5.694411 -5.257942 -4.836853 -4.4299846 + -4.03611 -3.653943 -3.2821424 -2.9193194 -2.5640426 -2.2148445 + -1.870231 -1.528686 -1.1886785 -0.8490555 -0.5094325 -0.1698095 + 0.1698135 0.5094365 0.8490595 1.1886826 1.52869 1.870235 + 2.2148485 2.5640464 2.9193234 3.2821465 3.653947 4.036114 + 4.4299884 4.836857 5.257946 5.694415 6.1473513 6.617767 + 7.1065917 7.6146684 8.142752 8.691503 9.261485 9.853165 + 10.466907 11.102971 11.761516 12.442593 13.146151 13.872032 + 14.619974 15.389614 16.180487 16.992025 17.823572 18.67437 + 19.543577 20.430264 21.333418 22.251951 23.184706 24.130453 + 25.08791 26.055733 27.032532 28.016876 29.007301 30.002312 + 31.00039 32.000004 33.000004 34.000004 35.000004 36.000004 + 37.000004 38.000004 39.000004 40.000004 41.000004 42.000004 + 43.000004 44.000004 45.000004 46.000004 47.000004 48.000004 + 49.000004 50.000004 51.000004 52.000004 53.000004 54.000004 + 55.000004 56.000004 57.000004 58.000004 59.000004 60.000004 + 61.000004 62.000004 63.000004 64.00001 65.00001 66.00001 + 67.00001 68.00001 69.00001 70.00001 71.00001 72.00001 + 73.00001 74.00001 75.00001 76.00001 77.00001 78.00001 + 79.00001 80.00001 81.00001 82.00001 83.00001 84.00001 + 85.00001 86.00001 87.00001 88.00001 89.00001 90.00001 ] + y_lower_bound: [-9.0500000e+01 -8.9500000e+01 -8.8500000e+01 -8.7500000e+01 + -8.6500000e+01 -8.5500000e+01 -8.4500000e+01 -8.3500000e+01 + -8.2500000e+01 -8.1500000e+01 -8.0500000e+01 -7.9500000e+01 + -7.8500000e+01 -7.7500000e+01 -7.6500000e+01 -7.5500000e+01 + -7.4500000e+01 -7.3500000e+01 -7.2500000e+01 -7.1500000e+01 + -7.0500000e+01 -6.9500000e+01 -6.8500000e+01 -6.7500000e+01 + -6.6500000e+01 -6.5500000e+01 -6.4500000e+01 -6.3500000e+01 + -6.2500000e+01 -6.1500000e+01 -6.0500000e+01 -5.9500000e+01 + -5.8500000e+01 -5.7500000e+01 -5.6500000e+01 -5.5500000e+01 + -5.4500000e+01 -5.3500000e+01 -5.2500000e+01 -5.1500000e+01 + -5.0500000e+01 -4.9500000e+01 -4.8500000e+01 -4.7500000e+01 + -4.6500000e+01 -4.5500000e+01 -4.4500000e+01 -4.3500000e+01 + -4.2500000e+01 -4.1500000e+01 -4.0500000e+01 -3.9500000e+01 + -3.8500000e+01 -3.7500000e+01 -3.6500000e+01 -3.5500000e+01 + -3.4500000e+01 -3.3500000e+01 -3.2500000e+01 -3.1500000e+01 + -3.0500771e+01 -2.9503845e+01 -2.8510752e+01 -2.7522995e+01 + -2.6542061e+01 -2.5569395e+01 -2.4606415e+01 -2.3654484e+01 + -2.2714918e+01 -2.1788977e+01 -2.0877851e+01 -1.9982668e+01 + -1.9104479e+01 -1.8244253e+01 -1.7402882e+01 -1.6581161e+01 + -1.5779803e+01 -1.4999418e+01 -1.4240523e+01 -1.3503533e+01 + -1.2788761e+01 -1.2096417e+01 -1.1426606e+01 -1.0779328e+01 + -1.0154477e+01 -9.5518446e+00 -8.9711180e+00 -8.4118795e+00 + -7.8736162e+00 -7.3557129e+00 -6.8574619e+00 -6.3780642e+00 + -5.9166312e+00 -5.4721909e+00 -5.0436931e+00 -4.6300130e+00 + -4.2299562e+00 -3.8422639e+00 -3.4656219e+00 -3.0986631e+00 + -2.7399759e+00 -2.3881090e+00 -2.0415800e+00 -1.6988820e+00 + -1.3584900e+00 -1.0188670e+00 -6.7924398e-01 -3.3962101e-01 + 2.0000000e-06 3.3962500e-01 6.7924798e-01 1.0188709e+00 + 1.3584940e+00 1.6988860e+00 2.0415840e+00 2.3881130e+00 + 2.7399800e+00 3.0986669e+00 3.4656260e+00 3.8422680e+00 + 4.2299600e+00 4.6300168e+00 5.0436969e+00 5.4721951e+00 + 5.9166350e+00 6.3780680e+00 6.8574662e+00 7.3557172e+00 + 7.8736200e+00 8.4118843e+00 8.9711218e+00 9.5518494e+00 + 1.0154481e+01 1.0779332e+01 1.1426610e+01 1.2096421e+01 + 1.2788765e+01 1.3503537e+01 1.4240527e+01 1.4999422e+01 + 1.5779807e+01 1.6581165e+01 1.7402885e+01 1.8244259e+01 + 1.9104483e+01 1.9982672e+01 2.0877855e+01 2.1788980e+01 + 2.2714922e+01 2.3654488e+01 2.4606419e+01 2.5569401e+01 + 2.6542065e+01 2.7522999e+01 2.8510756e+01 2.9503849e+01 + 3.0500774e+01 3.1500004e+01 3.2500004e+01 3.3500004e+01 + 3.4500004e+01 3.5500004e+01 3.6500004e+01 3.7500004e+01 + 3.8500004e+01 3.9500004e+01 4.0500004e+01 4.1500004e+01 + 4.2500004e+01 4.3500004e+01 4.4500004e+01 4.5500004e+01 + 4.6500004e+01 4.7500004e+01 4.8500004e+01 4.9500004e+01 + 5.0500004e+01 5.1500004e+01 5.2500004e+01 5.3500004e+01 + 5.4500004e+01 5.5500004e+01 5.6500004e+01 5.7500004e+01 + 5.8500004e+01 5.9500004e+01 6.0500004e+01 6.1500004e+01 + 6.2500004e+01 6.3500004e+01 6.4500008e+01 6.5500008e+01 + 6.6500008e+01 6.7500008e+01 6.8500008e+01 6.9500008e+01 + 7.0500008e+01 7.1500008e+01 7.2500008e+01 7.3500008e+01 + 7.4500008e+01 7.5500008e+01 7.6500008e+01 7.7500008e+01 + 7.8500008e+01 7.9500008e+01 8.0500008e+01 8.1500008e+01 + 8.2500008e+01 8.3500008e+01 8.4500008e+01 8.5500008e+01 + 8.6500008e+01 8.7500008e+01 8.8500008e+01 8.9500008e+01] + y_upper_bound: [-8.9500000e+01 -8.8500000e+01 -8.7500000e+01 -8.6500000e+01 + -8.5500000e+01 -8.4500000e+01 -8.3500000e+01 -8.2500000e+01 + -8.1500000e+01 -8.0500000e+01 -7.9500000e+01 -7.8500000e+01 + -7.7500000e+01 -7.6500000e+01 -7.5500000e+01 -7.4500000e+01 + -7.3500000e+01 -7.2500000e+01 -7.1500000e+01 -7.0500000e+01 + -6.9500000e+01 -6.8500000e+01 -6.7500000e+01 -6.6500000e+01 + -6.5500000e+01 -6.4500000e+01 -6.3500000e+01 -6.2500000e+01 + -6.1500000e+01 -6.0500000e+01 -5.9500000e+01 -5.8500000e+01 + -5.7500000e+01 -5.6500000e+01 -5.5500000e+01 -5.4500000e+01 + -5.3500000e+01 -5.2500000e+01 -5.1500000e+01 -5.0500000e+01 + -4.9500000e+01 -4.8500000e+01 -4.7500000e+01 -4.6500000e+01 + -4.5500000e+01 -4.4500000e+01 -4.3500000e+01 -4.2500000e+01 + -4.1500000e+01 -4.0500000e+01 -3.9500000e+01 -3.8500000e+01 + -3.7500000e+01 -3.6500000e+01 -3.5500000e+01 -3.4500000e+01 + -3.3500000e+01 -3.2500000e+01 -3.1500000e+01 -3.0500771e+01 + -2.9503845e+01 -2.8510752e+01 -2.7522995e+01 -2.6542061e+01 + -2.5569395e+01 -2.4606415e+01 -2.3654484e+01 -2.2714918e+01 + -2.1788977e+01 -2.0877851e+01 -1.9982668e+01 -1.9104479e+01 + -1.8244253e+01 -1.7402882e+01 -1.6581161e+01 -1.5779803e+01 + -1.4999418e+01 -1.4240523e+01 -1.3503533e+01 -1.2788761e+01 + -1.2096417e+01 -1.1426606e+01 -1.0779328e+01 -1.0154477e+01 + -9.5518446e+00 -8.9711180e+00 -8.4118795e+00 -7.8736162e+00 + -7.3557129e+00 -6.8574619e+00 -6.3780642e+00 -5.9166312e+00 + -5.4721909e+00 -5.0436931e+00 -4.6300130e+00 -4.2299562e+00 + -3.8422639e+00 -3.4656219e+00 -3.0986631e+00 -2.7399759e+00 + -2.3881090e+00 -2.0415800e+00 -1.6988820e+00 -1.3584900e+00 + -1.0188670e+00 -6.7924398e-01 -3.3962101e-01 2.0000000e-06 + 3.3962500e-01 6.7924798e-01 1.0188709e+00 1.3584940e+00 + 1.6988860e+00 2.0415840e+00 2.3881130e+00 2.7399800e+00 + 3.0986669e+00 3.4656260e+00 3.8422680e+00 4.2299600e+00 + 4.6300168e+00 5.0436969e+00 5.4721951e+00 5.9166350e+00 + 6.3780680e+00 6.8574662e+00 7.3557172e+00 7.8736200e+00 + 8.4118843e+00 8.9711218e+00 9.5518494e+00 1.0154481e+01 + 1.0779332e+01 1.1426610e+01 1.2096421e+01 1.2788765e+01 + 1.3503537e+01 1.4240527e+01 1.4999422e+01 1.5779807e+01 + 1.6581165e+01 1.7402885e+01 1.8244259e+01 1.9104483e+01 + 1.9982672e+01 2.0877855e+01 2.1788980e+01 2.2714922e+01 + 2.3654488e+01 2.4606419e+01 2.5569401e+01 2.6542065e+01 + 2.7522999e+01 2.8510756e+01 2.9503849e+01 3.0500774e+01 + 3.1500004e+01 3.2500004e+01 3.3500004e+01 3.4500004e+01 + 3.5500004e+01 3.6500004e+01 3.7500004e+01 3.8500004e+01 + 3.9500004e+01 4.0500004e+01 4.1500004e+01 4.2500004e+01 + 4.3500004e+01 4.4500004e+01 4.5500004e+01 4.6500004e+01 + 4.7500004e+01 4.8500004e+01 4.9500004e+01 5.0500004e+01 + 5.1500004e+01 5.2500004e+01 5.3500004e+01 5.4500004e+01 + 5.5500004e+01 5.6500004e+01 5.7500004e+01 5.8500004e+01 + 5.9500004e+01 6.0500004e+01 6.1500004e+01 6.2500004e+01 + 6.3500004e+01 6.4500008e+01 6.5500008e+01 6.6500008e+01 + 6.7500008e+01 6.8500008e+01 6.9500008e+01 7.0500008e+01 + 7.1500008e+01 7.2500008e+01 7.3500008e+01 7.4500008e+01 + 7.5500008e+01 7.6500008e+01 7.7500008e+01 7.8500008e+01 + 7.9500008e+01 8.0500008e+01 8.1500008e+01 8.2500008e+01 + 8.3500008e+01 8.4500008e+01 8.5500008e+01 8.6500008e+01 + 8.7500008e+01 8.8500008e+01 8.9500008e+01 9.0500008e+01] ] \ No newline at end of file diff --git a/lib/iris/tests/results/abf/load.cml b/lib/iris/tests/results/abf/load.cml index 58a05fe592..25be488650 100644 --- a/lib/iris/tests/results/abf/load.cml +++ b/lib/iris/tests/results/abf/load.cml @@ -1,6 +1,6 @@ - + @@ -12,7 +12,7 @@ ..., [89.75, 89.8333333333], [89.8333333333, 89.9166666667], - [89.9166666667, 90.0]]" id="f6259174" points="[-89.9583333333, -89.875, -89.7916666667, ..., + [89.9166666667, 90.0]]" id="9823ab62" points="[-89.9583333333, -89.875, -89.7916666667, ..., 89.7916666667, 89.875, 89.9583333333]" shape="(2160,)" standard_name="latitude" units="Unit('degrees')" value_type="float64"> @@ -24,16 +24,16 @@ ..., [179.75, 179.833333333], [179.833333333, 179.916666667], - [179.916666667, 180.0]]" id="c3f54a17" points="[-179.958333333, -179.875, -179.791666667, ..., + [179.916666667, 180.0]]" id="dfa7b3d0" points="[-179.958333333, -179.875, -179.791666667, ..., 179.791666667, 179.875, 179.958333333]" shape="(4320,)" standard_name="longitude" units="Unit('degrees')" value_type="float64"> - + - + diff --git a/lib/iris/tests/results/analysis/abs.cml b/lib/iris/tests/results/analysis/abs.cml index 8afe7aa4f5..e92f96e1cb 100644 --- a/lib/iris/tests/results/analysis/abs.cml +++ b/lib/iris/tests/results/analysis/abs.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/addition.cml b/lib/iris/tests/results/analysis/addition.cml index e7a09f03cd..d673e73bb3 100644 --- a/lib/iris/tests/results/analysis/addition.cml +++ b/lib/iris/tests/results/analysis/addition.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/addition_coord_x.cml b/lib/iris/tests/results/analysis/addition_coord_x.cml index 7d24a018f5..af0c5ecc91 100644 --- a/lib/iris/tests/results/analysis/addition_coord_x.cml +++ b/lib/iris/tests/results/analysis/addition_coord_x.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/addition_coord_y.cml b/lib/iris/tests/results/analysis/addition_coord_y.cml index cda61855aa..ba8547b617 100644 --- a/lib/iris/tests/results/analysis/addition_coord_y.cml +++ b/lib/iris/tests/results/analysis/addition_coord_y.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/addition_different_std_name.cml b/lib/iris/tests/results/analysis/addition_different_std_name.cml index eed5cb30b9..cb77adde99 100644 --- a/lib/iris/tests/results/analysis/addition_different_std_name.cml +++ b/lib/iris/tests/results/analysis/addition_different_std_name.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/addition_in_place.cml b/lib/iris/tests/results/analysis/addition_in_place.cml index e7a09f03cd..d673e73bb3 100644 --- a/lib/iris/tests/results/analysis/addition_in_place.cml +++ b/lib/iris/tests/results/analysis/addition_in_place.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/addition_in_place_coord.cml b/lib/iris/tests/results/analysis/addition_in_place_coord.cml index ee90ebff50..6ec39571c1 100644 --- a/lib/iris/tests/results/analysis/addition_in_place_coord.cml +++ b/lib/iris/tests/results/analysis/addition_in_place_coord.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/addition_scalar.cml b/lib/iris/tests/results/analysis/addition_scalar.cml index 6ff7f79a61..d65d7492fe 100644 --- a/lib/iris/tests/results/analysis/addition_scalar.cml +++ b/lib/iris/tests/results/analysis/addition_scalar.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/aggregated_by/easy.cml b/lib/iris/tests/results/analysis/aggregated_by/easy.cml index 117da52568..c4edb9484f 100644 --- a/lib/iris/tests/results/analysis/aggregated_by/easy.cml +++ b/lib/iris/tests/results/analysis/aggregated_by/easy.cml @@ -1,14 +1,14 @@ - + - + - + @@ -18,6 +18,6 @@ - + diff --git a/lib/iris/tests/results/analysis/aggregated_by/multi.cml b/lib/iris/tests/results/analysis/aggregated_by/multi.cml index f371d3c136..75cb67c054 100644 --- a/lib/iris/tests/results/analysis/aggregated_by/multi.cml +++ b/lib/iris/tests/results/analysis/aggregated_by/multi.cml @@ -1,20 +1,20 @@ - + - + - + - + - + @@ -27,7 +27,7 @@ [10, 11], [12, 14], [15, 15], - [16, 17]]" id="f2bf14cc" points="[1.0, 3.5, 12.0, 7.0, 9.0, 10.5, 13.0, 15.0, 16.5]" shape="(9,)" standard_name="model_level_number" units="Unit('1')" value_type="float64"/> + [16, 17]]" id="2e7cc9c8" points="[1.0, 3.5, 12.0, 7.0, 9.0, 10.5, 13.0, 15.0, 16.5]" shape="(9,)" standard_name="model_level_number" units="Unit('1')" value_type="float64"/> @@ -36,6 +36,6 @@ - + diff --git a/lib/iris/tests/results/analysis/aggregated_by/multi_missing.cml b/lib/iris/tests/results/analysis/aggregated_by/multi_missing.cml index cd7a990816..2f8f1e73d7 100644 --- a/lib/iris/tests/results/analysis/aggregated_by/multi_missing.cml +++ b/lib/iris/tests/results/analysis/aggregated_by/multi_missing.cml @@ -1,20 +1,20 @@ - + - + - + - + - + @@ -27,7 +27,7 @@ [10, 11], [12, 14], [15, 15], - [16, 17]]" id="f2bf14cc" points="[1.0, 3.5, 12.0, 7.0, 9.0, 10.5, 13.0, 15.0, 16.5]" shape="(9,)" standard_name="model_level_number" units="Unit('1')" value_type="float64"/> + [16, 17]]" id="2e7cc9c8" points="[1.0, 3.5, 12.0, 7.0, 9.0, 10.5, 13.0, 15.0, 16.5]" shape="(9,)" standard_name="model_level_number" units="Unit('1')" value_type="float64"/> @@ -36,6 +36,6 @@ - + diff --git a/lib/iris/tests/results/analysis/aggregated_by/multi_shared.cml b/lib/iris/tests/results/analysis/aggregated_by/multi_shared.cml index 14880c371d..81d775e741 100644 --- a/lib/iris/tests/results/analysis/aggregated_by/multi_shared.cml +++ b/lib/iris/tests/results/analysis/aggregated_by/multi_shared.cml @@ -1,6 +1,6 @@ - + + [3, 2]]" id="35dc92ed" long_name="gamma" points="[18.0, 15.5, 7.0, 12.0, 10.0, 8.5, 6.0, 4.0, 2.5]" shape="(9,)" units="Unit('1')" value_type="float64"/> - + - + - + - + @@ -38,7 +38,7 @@ [10, 11], [12, 14], [15, 15], - [16, 17]]" id="f2bf14cc" points="[1.0, 3.5, 12.0, 7.0, 9.0, 10.5, 13.0, 15.0, 16.5]" shape="(9,)" standard_name="model_level_number" units="Unit('1')" value_type="float64"/> + [16, 17]]" id="2e7cc9c8" points="[1.0, 3.5, 12.0, 7.0, 9.0, 10.5, 13.0, 15.0, 16.5]" shape="(9,)" standard_name="model_level_number" units="Unit('1')" value_type="float64"/> + [16, 17]]" id="a5c170db" long_name="sigma" points="[1.0, 3.5, 12.0, 7.0, 9.0, 10.5, 13.0, 15.0, 16.5]" shape="(9,)" units="Unit('1')" value_type="float64"/> @@ -58,6 +58,6 @@ - + diff --git a/lib/iris/tests/results/analysis/aggregated_by/single.cml b/lib/iris/tests/results/analysis/aggregated_by/single.cml index 80e23d6f02..3f2ea6fce2 100644 --- a/lib/iris/tests/results/analysis/aggregated_by/single.cml +++ b/lib/iris/tests/results/analysis/aggregated_by/single.cml @@ -1,17 +1,17 @@ - + - + - + - + @@ -23,7 +23,7 @@ [10, 14], [15, 20], [21, 27], - [28, 35]]" id="f2bf14cc" points="[0.0, 1.5, 4.0, 7.5, 12.0, 17.5, 24.0, 31.5]" shape="(8,)" standard_name="model_level_number" units="Unit('1')" value_type="float64"/> + [28, 35]]" id="2e7cc9c8" points="[0.0, 1.5, 4.0, 7.5, 12.0, 17.5, 24.0, 31.5]" shape="(8,)" standard_name="model_level_number" units="Unit('1')" value_type="float64"/> @@ -31,6 +31,6 @@ - + diff --git a/lib/iris/tests/results/analysis/aggregated_by/single_missing.cml b/lib/iris/tests/results/analysis/aggregated_by/single_missing.cml index 20a80bcff1..e6b95e3cbc 100644 --- a/lib/iris/tests/results/analysis/aggregated_by/single_missing.cml +++ b/lib/iris/tests/results/analysis/aggregated_by/single_missing.cml @@ -1,17 +1,17 @@ - + - + - + - + @@ -23,7 +23,7 @@ [10, 14], [15, 20], [21, 27], - [28, 35]]" id="f2bf14cc" points="[0.0, 1.5, 4.0, 7.5, 12.0, 17.5, 24.0, 31.5]" shape="(8,)" standard_name="model_level_number" units="Unit('1')" value_type="float64"/> + [28, 35]]" id="2e7cc9c8" points="[0.0, 1.5, 4.0, 7.5, 12.0, 17.5, 24.0, 31.5]" shape="(8,)" standard_name="model_level_number" units="Unit('1')" value_type="float64"/> @@ -31,6 +31,6 @@ - + diff --git a/lib/iris/tests/results/analysis/aggregated_by/single_rms.cml b/lib/iris/tests/results/analysis/aggregated_by/single_rms.cml index 12525b42cb..2961a6b48d 100644 --- a/lib/iris/tests/results/analysis/aggregated_by/single_rms.cml +++ b/lib/iris/tests/results/analysis/aggregated_by/single_rms.cml @@ -1,17 +1,17 @@ - + - + - + - + @@ -23,7 +23,7 @@ [10, 14], [15, 20], [21, 27], - [28, 35]]" id="f2bf14cc" points="[0.0, 1.5, 4.0, 7.5, 12.0, 17.5, 24.0, 31.5]" shape="(8,)" standard_name="model_level_number" units="Unit('1')" value_type="float64"/> + [28, 35]]" id="2e7cc9c8" points="[0.0, 1.5, 4.0, 7.5, 12.0, 17.5, 24.0, 31.5]" shape="(8,)" standard_name="model_level_number" units="Unit('1')" value_type="float64"/> @@ -31,6 +31,6 @@ - + diff --git a/lib/iris/tests/results/analysis/aggregated_by/single_shared.cml b/lib/iris/tests/results/analysis/aggregated_by/single_shared.cml index 6baf33ed4f..adbf893864 100644 --- a/lib/iris/tests/results/analysis/aggregated_by/single_shared.cml +++ b/lib/iris/tests/results/analysis/aggregated_by/single_shared.cml @@ -1,17 +1,17 @@ - + - + - + - + @@ -23,7 +23,7 @@ [10, 14], [15, 20], [21, 27], - [28, 35]]" id="f2bf14cc" points="[0.0, 1.5, 4.0, 7.5, 12.0, 17.5, 24.0, 31.5]" shape="(8,)" standard_name="model_level_number" units="Unit('1')" value_type="float64"/> + [28, 35]]" id="2e7cc9c8" points="[0.0, 1.5, 4.0, 7.5, 12.0, 17.5, 24.0, 31.5]" shape="(8,)" standard_name="model_level_number" units="Unit('1')" value_type="float64"/> + [28, 35]]" id="10b8e1fc" long_name="wibble" points="[0.0, 1.5, 4.0, 7.5, 12.0, 17.5, 24.0, 31.5]" shape="(8,)" units="Unit('1')" value_type="float64"/> @@ -41,6 +41,6 @@ - + diff --git a/lib/iris/tests/results/analysis/aggregated_by/single_shared_circular.cml b/lib/iris/tests/results/analysis/aggregated_by/single_shared_circular.cml index 1d7a77d7a8..eba017837d 100644 --- a/lib/iris/tests/results/analysis/aggregated_by/single_shared_circular.cml +++ b/lib/iris/tests/results/analysis/aggregated_by/single_shared_circular.cml @@ -1,6 +1,6 @@ - + - + - + - + @@ -34,7 +34,7 @@ [10, 14], [15, 20], [21, 27], - [28, 35]]" id="f2bf14cc" points="[0.0, 1.5, 4.0, 7.5, 12.0, 17.5, 24.0, 31.5]" shape="(8,)" standard_name="model_level_number" units="Unit('1')" value_type="float64"/> + [28, 35]]" id="2e7cc9c8" points="[0.0, 1.5, 4.0, 7.5, 12.0, 17.5, 24.0, 31.5]" shape="(8,)" standard_name="model_level_number" units="Unit('1')" value_type="float64"/> @@ -42,6 +42,6 @@ - + diff --git a/lib/iris/tests/results/analysis/apply_ifunc.cml b/lib/iris/tests/results/analysis/apply_ifunc.cml new file mode 100644 index 0000000000..f2bac40826 --- /dev/null +++ b/lib/iris/tests/results/analysis/apply_ifunc.cml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/apply_ifunc.data.0.json b/lib/iris/tests/results/analysis/apply_ifunc.data.0.json new file mode 100644 index 0000000000..3c3dde46b3 --- /dev/null +++ b/lib/iris/tests/results/analysis/apply_ifunc.data.0.json @@ -0,0 +1 @@ +{"std": 600.0958251953125, "min": 5.4993666708469391e-05, "max": 2069.03369140625, "shape": [73, 96], "masked": false, "mean": 664.99627685546875} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/apply_ifunc_frompyfunc.cml b/lib/iris/tests/results/analysis/apply_ifunc_frompyfunc.cml new file mode 100644 index 0000000000..2faa06f4a5 --- /dev/null +++ b/lib/iris/tests/results/analysis/apply_ifunc_frompyfunc.cml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/apply_ifunc_frompyfunc.data.0.json b/lib/iris/tests/results/analysis/apply_ifunc_frompyfunc.data.0.json new file mode 100644 index 0000000000..1b77395e01 --- /dev/null +++ b/lib/iris/tests/results/analysis/apply_ifunc_frompyfunc.data.0.json @@ -0,0 +1 @@ +{"std": 848.63707924732125, "min": 2.0000550754478277, "max": 2927.4700625478599, "shape": [73, 96], "masked": false, "mean": 941.88598170710736} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/apply_ifunc_original.cml b/lib/iris/tests/results/analysis/apply_ifunc_original.cml new file mode 100644 index 0000000000..62a569f7cc --- /dev/null +++ b/lib/iris/tests/results/analysis/apply_ifunc_original.cml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/apply_ifunc_original.data.0.json b/lib/iris/tests/results/analysis/apply_ifunc_original.data.0.json new file mode 100644 index 0000000000..a612f9728c --- /dev/null +++ b/lib/iris/tests/results/analysis/apply_ifunc_original.data.0.json @@ -0,0 +1 @@ +{"std": 16.345842361450195, "min": -15.285690307617188, "max": 45.48663330078125, "shape": [73, 96], "masked": false, "mean": 19.945165634155273} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/apply_ufunc.cml b/lib/iris/tests/results/analysis/apply_ufunc.cml new file mode 100644 index 0000000000..f2bac40826 --- /dev/null +++ b/lib/iris/tests/results/analysis/apply_ufunc.cml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/apply_ufunc.data.0.json b/lib/iris/tests/results/analysis/apply_ufunc.data.0.json new file mode 100644 index 0000000000..3c3dde46b3 --- /dev/null +++ b/lib/iris/tests/results/analysis/apply_ufunc.data.0.json @@ -0,0 +1 @@ +{"std": 600.0958251953125, "min": 5.4993666708469391e-05, "max": 2069.03369140625, "shape": [73, 96], "masked": false, "mean": 664.99627685546875} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/apply_ufunc_frompyfunc.cml b/lib/iris/tests/results/analysis/apply_ufunc_frompyfunc.cml new file mode 100644 index 0000000000..d4239acbad --- /dev/null +++ b/lib/iris/tests/results/analysis/apply_ufunc_frompyfunc.cml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/apply_ufunc_frompyfunc.data.0.json b/lib/iris/tests/results/analysis/apply_ufunc_frompyfunc.data.0.json new file mode 100644 index 0000000000..1b77395e01 --- /dev/null +++ b/lib/iris/tests/results/analysis/apply_ufunc_frompyfunc.data.0.json @@ -0,0 +1 @@ +{"std": 848.63707924732125, "min": 2.0000550754478277, "max": 2927.4700625478599, "shape": [73, 96], "masked": false, "mean": 941.88598170710736} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/apply_ufunc_original.cml b/lib/iris/tests/results/analysis/apply_ufunc_original.cml new file mode 100644 index 0000000000..62a569f7cc --- /dev/null +++ b/lib/iris/tests/results/analysis/apply_ufunc_original.cml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/apply_ufunc_original.data.0.json b/lib/iris/tests/results/analysis/apply_ufunc_original.data.0.json new file mode 100644 index 0000000000..a612f9728c --- /dev/null +++ b/lib/iris/tests/results/analysis/apply_ufunc_original.data.0.json @@ -0,0 +1 @@ +{"std": 16.345842361450195, "min": -15.285690307617188, "max": 45.48663330078125, "shape": [73, 96], "masked": false, "mean": 19.945165634155273} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/areaweights_original.cml b/lib/iris/tests/results/analysis/areaweights_original.cml index 28e19b7844..3c33ef500a 100644 --- a/lib/iris/tests/results/analysis/areaweights_original.cml +++ b/lib/iris/tests/results/analysis/areaweights_original.cml @@ -1,32 +1,32 @@ - + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/calculus/cos_simple.xml b/lib/iris/tests/results/analysis/calculus/cos_simple.xml index a09e231834..478902833f 100644 --- a/lib/iris/tests/results/analysis/calculus/cos_simple.xml +++ b/lib/iris/tests/results/analysis/calculus/cos_simple.xml @@ -1,2 +1,2 @@ - + diff --git a/lib/iris/tests/results/analysis/calculus/cos_simple_radians.xml b/lib/iris/tests/results/analysis/calculus/cos_simple_radians.xml index a09e231834..478902833f 100644 --- a/lib/iris/tests/results/analysis/calculus/cos_simple_radians.xml +++ b/lib/iris/tests/results/analysis/calculus/cos_simple_radians.xml @@ -1,2 +1,2 @@ - + diff --git a/lib/iris/tests/results/analysis/calculus/curl_contrived_cartesian2.cml b/lib/iris/tests/results/analysis/calculus/curl_contrived_cartesian2.cml index 37042c6a89..a744dfc782 100644 --- a/lib/iris/tests/results/analysis/calculus/curl_contrived_cartesian2.cml +++ b/lib/iris/tests/results/analysis/calculus/curl_contrived_cartesian2.cml @@ -1,9 +1,9 @@ - + - - - @@ -29,12 +29,12 @@ - + - + - - - @@ -60,12 +60,12 @@ - + - + - - - @@ -91,6 +91,6 @@ - + diff --git a/lib/iris/tests/results/analysis/calculus/delta_handmade_simple_wrt_x.cml b/lib/iris/tests/results/analysis/calculus/delta_handmade_simple_wrt_x.cml index e2f10ca52c..ee1301b11d 100644 --- a/lib/iris/tests/results/analysis/calculus/delta_handmade_simple_wrt_x.cml +++ b/lib/iris/tests/results/analysis/calculus/delta_handmade_simple_wrt_x.cml @@ -1,15 +1,15 @@ - + - + - + - + diff --git a/lib/iris/tests/results/analysis/calculus/delta_handmade_simple_wrt_x.data.0.json b/lib/iris/tests/results/analysis/calculus/delta_handmade_simple_wrt_x.data.0.json new file mode 100644 index 0000000000..dc7edcae22 --- /dev/null +++ b/lib/iris/tests/results/analysis/calculus/delta_handmade_simple_wrt_x.data.0.json @@ -0,0 +1 @@ +{"std": 0.21794494986534119, "min": 1.0, "max": 2.0, "shape": [4, 5], "masked": false, "mean": 1.0499999523162842} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/calculus/delta_handmade_simple_wrt_x.data.0.npy b/lib/iris/tests/results/analysis/calculus/delta_handmade_simple_wrt_x.data.0.npy deleted file mode 100644 index 8b6fec90ee..0000000000 Binary files a/lib/iris/tests/results/analysis/calculus/delta_handmade_simple_wrt_x.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lat.cml b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lat.cml index dc149f4b3a..0693498989 100644 --- a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lat.cml +++ b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lat.cml @@ -1,25 +1,25 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lat.data.0.json b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lat.data.0.json new file mode 100644 index 0000000000..32b3104232 --- /dev/null +++ b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lat.data.0.json @@ -0,0 +1 @@ +{"std": 0.24206146597862244, "min": 1.0, "max": 2.0, "shape": [4, 4], "masked": false, "mean": 1.0625} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lat.data.0.npy b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lat.data.0.npy deleted file mode 100644 index 5afca70510..0000000000 Binary files a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lat.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lon.cml b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lon.cml index a22a04de7b..376c624265 100644 --- a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lon.cml +++ b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lon.cml @@ -1,25 +1,25 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lon.data.0.json b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lon.data.0.json new file mode 100644 index 0000000000..9d98a55251 --- /dev/null +++ b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lon.data.0.json @@ -0,0 +1 @@ +{"std": 1.8708287477493286, "min": -4.0, "max": 2.0, "shape": [4, 5], "masked": false, "mean": 0.0} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lon.data.0.npy b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lon.data.0.npy deleted file mode 100644 index e400581400..0000000000 Binary files a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_lon.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_x.cml b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_x.cml index baa6c3f33c..d54dae3424 100644 --- a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_x.cml +++ b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_x.cml @@ -1,25 +1,25 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_x.data.0.json b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_x.data.0.json new file mode 100644 index 0000000000..9d98a55251 --- /dev/null +++ b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_x.data.0.json @@ -0,0 +1 @@ +{"std": 1.8708287477493286, "min": -4.0, "max": 2.0, "shape": [4, 5], "masked": false, "mean": 0.0} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_x.data.0.npy b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_x.data.0.npy deleted file mode 100644 index e400581400..0000000000 Binary files a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_x.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_y.cml b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_y.cml index 6ff9c884d3..7561c7b02f 100644 --- a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_y.cml +++ b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_y.cml @@ -1,25 +1,25 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_y.data.0.json b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_y.data.0.json new file mode 100644 index 0000000000..32b3104232 --- /dev/null +++ b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_y.data.0.json @@ -0,0 +1 @@ +{"std": 0.24206146597862244, "min": 1.0, "max": 2.0, "shape": [4, 4], "masked": false, "mean": 1.0625} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_y.data.0.npy b/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_y.data.0.npy deleted file mode 100644 index 5afca70510..0000000000 Binary files a/lib/iris/tests/results/analysis/calculus/delta_handmade_wrt_y.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/calculus/grad_contrived1.cml b/lib/iris/tests/results/analysis/calculus/grad_contrived1.cml index dd72a451ae..0696e1be75 100644 --- a/lib/iris/tests/results/analysis/calculus/grad_contrived1.cml +++ b/lib/iris/tests/results/analysis/calculus/grad_contrived1.cml @@ -1,9 +1,9 @@ - + - @@ -11,7 +11,7 @@ - + @@ -32,6 +32,6 @@ - + diff --git a/lib/iris/tests/results/analysis/calculus/grad_contrived2.cml b/lib/iris/tests/results/analysis/calculus/grad_contrived2.cml index 9a27065677..ffa976d4a4 100644 --- a/lib/iris/tests/results/analysis/calculus/grad_contrived2.cml +++ b/lib/iris/tests/results/analysis/calculus/grad_contrived2.cml @@ -1,9 +1,9 @@ - + - - - + @@ -36,6 +36,6 @@ - + diff --git a/lib/iris/tests/results/analysis/calculus/grad_contrived_non_spherical1.cml b/lib/iris/tests/results/analysis/calculus/grad_contrived_non_spherical1.cml index a819ff158b..077e3df4ab 100644 --- a/lib/iris/tests/results/analysis/calculus/grad_contrived_non_spherical1.cml +++ b/lib/iris/tests/results/analysis/calculus/grad_contrived_non_spherical1.cml @@ -1,9 +1,9 @@ - + - - - + @@ -28,6 +28,6 @@ - + diff --git a/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lat.cml b/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lat.cml index fb2375d5c8..7cc09660ab 100644 --- a/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lat.cml +++ b/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lat.cml @@ -1,9 +1,9 @@ - + - - + diff --git a/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lat.data.0.json b/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lat.data.0.json new file mode 100644 index 0000000000..f085c17bc3 --- /dev/null +++ b/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lat.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 0.2222222238779068, "max": 0.2222222238779068, "shape": [50, 49], "masked": false, "mean": 0.2222222238779068} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lat.data.0.npy b/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lat.data.0.npy deleted file mode 100644 index 33b1bb6b7e..0000000000 Binary files a/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lat.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lon.cml b/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lon.cml index 922451faa3..ced788b5c6 100644 --- a/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lon.cml +++ b/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lon.cml @@ -1,9 +1,9 @@ - + - - + diff --git a/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lon.data.0.json b/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lon.data.0.json new file mode 100644 index 0000000000..325c7d9d0c --- /dev/null +++ b/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lon.data.0.json @@ -0,0 +1 @@ +{"std": 9.5367431640625e-07, "min": 11.111110687255859, "max": 11.111110687255859, "shape": [49, 50], "masked": false, "mean": 11.111111640930176} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lon.data.0.npy b/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lon.data.0.npy deleted file mode 100644 index 6e8db0618c..0000000000 Binary files a/lib/iris/tests/results/analysis/calculus/handmade2_wrt_lon.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/calculus/handmade_simple_wrt_x.cml b/lib/iris/tests/results/analysis/calculus/handmade_simple_wrt_x.cml index 247f8268c3..c055a46e59 100644 --- a/lib/iris/tests/results/analysis/calculus/handmade_simple_wrt_x.cml +++ b/lib/iris/tests/results/analysis/calculus/handmade_simple_wrt_x.cml @@ -1,15 +1,15 @@ - + - + - + - + diff --git a/lib/iris/tests/results/analysis/calculus/handmade_simple_wrt_x.data.0.json b/lib/iris/tests/results/analysis/calculus/handmade_simple_wrt_x.data.0.json new file mode 100644 index 0000000000..dc7edcae22 --- /dev/null +++ b/lib/iris/tests/results/analysis/calculus/handmade_simple_wrt_x.data.0.json @@ -0,0 +1 @@ +{"std": 0.21794494986534119, "min": 1.0, "max": 2.0, "shape": [4, 5], "masked": false, "mean": 1.0499999523162842} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/calculus/handmade_simple_wrt_x.data.0.npy b/lib/iris/tests/results/analysis/calculus/handmade_simple_wrt_x.data.0.npy deleted file mode 100644 index 8b6fec90ee..0000000000 Binary files a/lib/iris/tests/results/analysis/calculus/handmade_simple_wrt_x.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/calculus/handmade_wrt_lat.cml b/lib/iris/tests/results/analysis/calculus/handmade_wrt_lat.cml index 841d02a2ed..98612df27b 100644 --- a/lib/iris/tests/results/analysis/calculus/handmade_wrt_lat.cml +++ b/lib/iris/tests/results/analysis/calculus/handmade_wrt_lat.cml @@ -1,25 +1,25 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/calculus/handmade_wrt_lat.data.0.json b/lib/iris/tests/results/analysis/calculus/handmade_wrt_lat.data.0.json new file mode 100644 index 0000000000..ec37eb3937 --- /dev/null +++ b/lib/iris/tests/results/analysis/calculus/handmade_wrt_lat.data.0.json @@ -0,0 +1 @@ +{"std": 0.0053791436366736889, "min": 0.02222222276031971, "max": 0.04444444552063942, "shape": [4, 4], "masked": false, "mean": 0.023611113429069519} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/calculus/handmade_wrt_lat.data.0.npy b/lib/iris/tests/results/analysis/calculus/handmade_wrt_lat.data.0.npy deleted file mode 100644 index acf3201df1..0000000000 Binary files a/lib/iris/tests/results/analysis/calculus/handmade_wrt_lat.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/calculus/handmade_wrt_lon.cml b/lib/iris/tests/results/analysis/calculus/handmade_wrt_lon.cml index 423051b4f7..ceeb537ac6 100644 --- a/lib/iris/tests/results/analysis/calculus/handmade_wrt_lon.cml +++ b/lib/iris/tests/results/analysis/calculus/handmade_wrt_lon.cml @@ -1,25 +1,25 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/calculus/handmade_wrt_lon.data.0.json b/lib/iris/tests/results/analysis/calculus/handmade_wrt_lon.data.0.json new file mode 100644 index 0000000000..baa77f637d --- /dev/null +++ b/lib/iris/tests/results/analysis/calculus/handmade_wrt_lon.data.0.json @@ -0,0 +1 @@ +{"std": 0.020786985754966736, "min": -0.04444444552063942, "max": 0.02222222276031971, "shape": [4, 5], "masked": false, "mean": 3.7252903539730653e-10} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/calculus/handmade_wrt_lon.data.0.npy b/lib/iris/tests/results/analysis/calculus/handmade_wrt_lon.data.0.npy deleted file mode 100644 index 78b21dacce..0000000000 Binary files a/lib/iris/tests/results/analysis/calculus/handmade_wrt_lon.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/calculus/handmade_wrt_x.cml b/lib/iris/tests/results/analysis/calculus/handmade_wrt_x.cml index d3ce6fcd6f..cbe823b2e0 100644 --- a/lib/iris/tests/results/analysis/calculus/handmade_wrt_x.cml +++ b/lib/iris/tests/results/analysis/calculus/handmade_wrt_x.cml @@ -1,25 +1,25 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/calculus/handmade_wrt_x.data.0.json b/lib/iris/tests/results/analysis/calculus/handmade_wrt_x.data.0.json new file mode 100644 index 0000000000..a1de71d548 --- /dev/null +++ b/lib/iris/tests/results/analysis/calculus/handmade_wrt_x.data.0.json @@ -0,0 +1 @@ +{"std": 0.22607769072055817, "min": 1.0, "max": 2.0, "shape": [4, 5], "masked": false, "mean": 1.0666667222976685} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/calculus/handmade_wrt_x.data.0.npy b/lib/iris/tests/results/analysis/calculus/handmade_wrt_x.data.0.npy deleted file mode 100644 index c498544b3f..0000000000 Binary files a/lib/iris/tests/results/analysis/calculus/handmade_wrt_x.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/calculus/handmade_wrt_y.cml b/lib/iris/tests/results/analysis/calculus/handmade_wrt_y.cml index 6c3a63a545..b0eaa31da8 100644 --- a/lib/iris/tests/results/analysis/calculus/handmade_wrt_y.cml +++ b/lib/iris/tests/results/analysis/calculus/handmade_wrt_y.cml @@ -1,25 +1,25 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/calculus/handmade_wrt_y.data.0.json b/lib/iris/tests/results/analysis/calculus/handmade_wrt_y.data.0.json new file mode 100644 index 0000000000..32b3104232 --- /dev/null +++ b/lib/iris/tests/results/analysis/calculus/handmade_wrt_y.data.0.json @@ -0,0 +1 @@ +{"std": 0.24206146597862244, "min": 1.0, "max": 2.0, "shape": [4, 4], "masked": false, "mean": 1.0625} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/calculus/handmade_wrt_y.data.0.npy b/lib/iris/tests/results/analysis/calculus/handmade_wrt_y.data.0.npy deleted file mode 100644 index 5afca70510..0000000000 Binary files a/lib/iris/tests/results/analysis/calculus/handmade_wrt_y.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/coord_comparison/cube1_cube1.txt b/lib/iris/tests/results/analysis/coord_comparison/cube1_cube1.txt index 5e6c9d273e..530829950c 100644 --- a/lib/iris/tests/results/analysis/coord_comparison/cube1_cube1.txt +++ b/lib/iris/tests/results/analysis/coord_comparison/cube1_cube1.txt @@ -1,14 +1,14 @@ - grouped_coords [['f', 'f'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] - not_equal [] dimensioned [['latitude', 'latitude'], ['longitude', 'longitude']] - non_equal_shape [] equal [['f', 'f'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] equal_data_dimension [['f', 'f'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] - resamplable [] + grouped_coords [['f', 'f'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] + ignorable [] no_data_dimension [['f', 'f'], ['z', 'z']] - ungroupable [] + non_equal_data_dimension [] + non_equal_shape [] + not_equal [] + resamplable [] scalar [['f', 'f'], ['z', 'z']] transposable [] - non_equal_data_dimension [] + ungroupable [] ungroupable_and_dimensioned [] - ignorable [] diff --git a/lib/iris/tests/results/analysis/coord_comparison/cube1_cube1_cube1.txt b/lib/iris/tests/results/analysis/coord_comparison/cube1_cube1_cube1.txt index 7c5e736046..a3edfc3c3f 100644 --- a/lib/iris/tests/results/analysis/coord_comparison/cube1_cube1_cube1.txt +++ b/lib/iris/tests/results/analysis/coord_comparison/cube1_cube1_cube1.txt @@ -1,14 +1,14 @@ - grouped_coords [['f', 'f', 'f'], ['latitude', 'latitude', 'latitude'], ['longitude', 'longitude', 'longitude'], ['z', 'z', 'z']] - not_equal [] dimensioned [['latitude', 'latitude', 'latitude'], ['longitude', 'longitude', 'longitude']] - non_equal_shape [] equal [['f', 'f', 'f'], ['latitude', 'latitude', 'latitude'], ['longitude', 'longitude', 'longitude'], ['z', 'z', 'z']] equal_data_dimension [['f', 'f', 'f'], ['latitude', 'latitude', 'latitude'], ['longitude', 'longitude', 'longitude'], ['z', 'z', 'z']] - resamplable [] + grouped_coords [['f', 'f', 'f'], ['latitude', 'latitude', 'latitude'], ['longitude', 'longitude', 'longitude'], ['z', 'z', 'z']] + ignorable [] no_data_dimension [['f', 'f', 'f'], ['z', 'z', 'z']] - ungroupable [] + non_equal_data_dimension [] + non_equal_shape [] + not_equal [] + resamplable [] scalar [['f', 'f', 'f'], ['z', 'z', 'z']] transposable [] - non_equal_data_dimension [] + ungroupable [] ungroupable_and_dimensioned [] - ignorable [] diff --git a/lib/iris/tests/results/analysis/coord_comparison/cube1_cube2.txt b/lib/iris/tests/results/analysis/coord_comparison/cube1_cube2.txt index 4be8a473c5..db766729f8 100644 --- a/lib/iris/tests/results/analysis/coord_comparison/cube1_cube2.txt +++ b/lib/iris/tests/results/analysis/coord_comparison/cube1_cube2.txt @@ -1,14 +1,14 @@ - grouped_coords [['f', 'None'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] - not_equal [['f', 'None'], ['longitude', 'longitude'], ['z', 'z']] dimensioned [['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] - non_equal_shape [['f', 'None'], ['z', 'z']] equal [['latitude', 'latitude']] equal_data_dimension [['latitude', 'latitude'], ['longitude', 'longitude']] - resamplable [['longitude', 'longitude']] + grouped_coords [['f', 'None'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] + ignorable [['f', 'None']] no_data_dimension [['f', 'None']] - ungroupable [['f', 'None']] + non_equal_data_dimension [['f', 'None'], ['z', 'z']] + non_equal_shape [['f', 'None'], ['z', 'z']] + not_equal [['f', 'None'], ['longitude', 'longitude'], ['z', 'z']] + resamplable [['longitude', 'longitude']] scalar [['f', 'None']] transposable [] - non_equal_data_dimension [['f', 'None'], ['z', 'z']] + ungroupable [['f', 'None']] ungroupable_and_dimensioned [] - ignorable [['f', 'None']] diff --git a/lib/iris/tests/results/analysis/coord_comparison/cube1_cube2_cube1.txt b/lib/iris/tests/results/analysis/coord_comparison/cube1_cube2_cube1.txt index 05857f9b90..c8048d815a 100644 --- a/lib/iris/tests/results/analysis/coord_comparison/cube1_cube2_cube1.txt +++ b/lib/iris/tests/results/analysis/coord_comparison/cube1_cube2_cube1.txt @@ -1,14 +1,14 @@ - grouped_coords [['f', 'None', 'f'], ['latitude', 'latitude', 'latitude'], ['longitude', 'longitude', 'longitude'], ['z', 'z', 'z']] - not_equal [['f', 'None', 'f'], ['longitude', 'longitude', 'longitude'], ['z', 'z', 'z']] dimensioned [['latitude', 'latitude', 'latitude'], ['longitude', 'longitude', 'longitude'], ['z', 'z', 'z']] - non_equal_shape [['f', 'None', 'f'], ['z', 'z', 'z']] equal [['latitude', 'latitude', 'latitude']] equal_data_dimension [['latitude', 'latitude', 'latitude'], ['longitude', 'longitude', 'longitude']] - resamplable [['longitude', 'longitude', 'longitude']] + grouped_coords [['f', 'None', 'f'], ['latitude', 'latitude', 'latitude'], ['longitude', 'longitude', 'longitude'], ['z', 'z', 'z']] + ignorable [['f', 'None', 'f']] no_data_dimension [['f', 'None', 'f']] - ungroupable [['f', 'None', 'f']] + non_equal_data_dimension [['f', 'None', 'f'], ['z', 'z', 'z']] + non_equal_shape [['f', 'None', 'f'], ['z', 'z', 'z']] + not_equal [['f', 'None', 'f'], ['longitude', 'longitude', 'longitude'], ['z', 'z', 'z']] + resamplable [['longitude', 'longitude', 'longitude']] scalar [['f', 'None', 'f']] transposable [] - non_equal_data_dimension [['f', 'None', 'f'], ['z', 'z', 'z']] + ungroupable [['f', 'None', 'f']] ungroupable_and_dimensioned [] - ignorable [['f', 'None', 'f']] diff --git a/lib/iris/tests/results/analysis/coord_comparison/cube1_cube3.txt b/lib/iris/tests/results/analysis/coord_comparison/cube1_cube3.txt index efe158bb97..585745d305 100644 --- a/lib/iris/tests/results/analysis/coord_comparison/cube1_cube3.txt +++ b/lib/iris/tests/results/analysis/coord_comparison/cube1_cube3.txt @@ -1,14 +1,14 @@ - grouped_coords [['f', 'f'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] - not_equal [['z', 'z']] dimensioned [['latitude', 'latitude'], ['longitude', 'longitude']] - non_equal_shape [] equal [['f', 'f'], ['latitude', 'latitude'], ['longitude', 'longitude']] equal_data_dimension [['f', 'f'], ['z', 'z']] - resamplable [] + grouped_coords [['f', 'f'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] + ignorable [['z', 'z']] no_data_dimension [['f', 'f'], ['z', 'z']] - ungroupable [] + non_equal_data_dimension [['latitude', 'latitude'], ['longitude', 'longitude']] + non_equal_shape [] + not_equal [['z', 'z']] + resamplable [] scalar [['f', 'f'], ['z', 'z']] transposable [['latitude', 'latitude'], ['longitude', 'longitude']] - non_equal_data_dimension [['latitude', 'latitude'], ['longitude', 'longitude']] + ungroupable [] ungroupable_and_dimensioned [] - ignorable [['z', 'z']] diff --git a/lib/iris/tests/results/analysis/coord_comparison/cube1_cube4.txt b/lib/iris/tests/results/analysis/coord_comparison/cube1_cube4.txt index 9ef3613f9b..0de1c647b9 100644 --- a/lib/iris/tests/results/analysis/coord_comparison/cube1_cube4.txt +++ b/lib/iris/tests/results/analysis/coord_comparison/cube1_cube4.txt @@ -1,14 +1,14 @@ - grouped_coords [['f', 'None'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] - not_equal [['f', 'None'], ['longitude', 'longitude'], ['z', 'z']] dimensioned [['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] - non_equal_shape [['f', 'None'], ['z', 'z']] equal [['latitude', 'latitude']] equal_data_dimension [] - resamplable [] + grouped_coords [['f', 'None'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] + ignorable [['f', 'None']] no_data_dimension [['f', 'None']] - ungroupable [['f', 'None']] + non_equal_data_dimension [['f', 'None'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] + non_equal_shape [['f', 'None'], ['z', 'z']] + not_equal [['f', 'None'], ['longitude', 'longitude'], ['z', 'z']] + resamplable [] scalar [['f', 'None']] transposable [['latitude', 'latitude']] - non_equal_data_dimension [['f', 'None'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] + ungroupable [['f', 'None']] ungroupable_and_dimensioned [] - ignorable [['f', 'None']] diff --git a/lib/iris/tests/results/analysis/coord_comparison/cube1_cube5.txt b/lib/iris/tests/results/analysis/coord_comparison/cube1_cube5.txt new file mode 100644 index 0000000000..d15d4c74d7 --- /dev/null +++ b/lib/iris/tests/results/analysis/coord_comparison/cube1_cube5.txt @@ -0,0 +1,14 @@ + dimensioned [['latitude', 'latitude'], ['longitude', 'longitude']] + equal [['latitude', 'latitude'], ['longitude', 'longitude']] + equal_data_dimension [['latitude', 'latitude'], ['longitude', 'longitude']] + grouped_coords [['f', 'None'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'None']] + ignorable [['f', 'None'], ['z', 'None']] + no_data_dimension [['f', 'None'], ['z', 'None']] + non_equal_data_dimension [['f', 'None'], ['z', 'None']] + non_equal_shape [['f', 'None'], ['z', 'None']] + not_equal [['f', 'None'], ['z', 'None']] + resamplable [] + scalar [['f', 'None'], ['z', 'None']] + transposable [] + ungroupable [['f', 'None'], ['z', 'None']] + ungroupable_and_dimensioned [] diff --git a/lib/iris/tests/results/analysis/coord_comparison/cube2_cube3.txt b/lib/iris/tests/results/analysis/coord_comparison/cube2_cube3.txt index 224951d9f3..096d0eccd7 100644 --- a/lib/iris/tests/results/analysis/coord_comparison/cube2_cube3.txt +++ b/lib/iris/tests/results/analysis/coord_comparison/cube2_cube3.txt @@ -1,14 +1,14 @@ - grouped_coords [['None', 'f'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] - not_equal [['None', 'f'], ['longitude', 'longitude'], ['z', 'z']] dimensioned [['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] - non_equal_shape [['None', 'f'], ['z', 'z']] equal [['latitude', 'latitude']] equal_data_dimension [] - resamplable [] + grouped_coords [['None', 'f'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] + ignorable [['None', 'f']] no_data_dimension [['None', 'f']] - ungroupable [['None', 'f']] + non_equal_data_dimension [['None', 'f'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] + non_equal_shape [['None', 'f'], ['z', 'z']] + not_equal [['None', 'f'], ['longitude', 'longitude'], ['z', 'z']] + resamplable [] scalar [['None', 'f']] transposable [['latitude', 'latitude']] - non_equal_data_dimension [['None', 'f'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] + ungroupable [['None', 'f']] ungroupable_and_dimensioned [] - ignorable [['None', 'f']] diff --git a/lib/iris/tests/results/analysis/coord_comparison/cube2_cube4.txt b/lib/iris/tests/results/analysis/coord_comparison/cube2_cube4.txt index 7d1db6fdbe..1bc956fa26 100644 --- a/lib/iris/tests/results/analysis/coord_comparison/cube2_cube4.txt +++ b/lib/iris/tests/results/analysis/coord_comparison/cube2_cube4.txt @@ -1,14 +1,14 @@ - grouped_coords [['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] - not_equal [] dimensioned [['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] - non_equal_shape [] equal [['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] equal_data_dimension [['z', 'z']] - resamplable [] + grouped_coords [['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] + ignorable [] no_data_dimension [] - ungroupable [] + non_equal_data_dimension [['latitude', 'latitude'], ['longitude', 'longitude']] + non_equal_shape [] + not_equal [] + resamplable [] scalar [] transposable [['latitude', 'latitude'], ['longitude', 'longitude']] - non_equal_data_dimension [['latitude', 'latitude'], ['longitude', 'longitude']] + ungroupable [] ungroupable_and_dimensioned [] - ignorable [] diff --git a/lib/iris/tests/results/analysis/coord_comparison/cube2_cube5.txt b/lib/iris/tests/results/analysis/coord_comparison/cube2_cube5.txt new file mode 100644 index 0000000000..b1d7e797ac --- /dev/null +++ b/lib/iris/tests/results/analysis/coord_comparison/cube2_cube5.txt @@ -0,0 +1,14 @@ + dimensioned [['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'None']] + equal [['latitude', 'latitude']] + equal_data_dimension [['latitude', 'latitude'], ['longitude', 'longitude']] + grouped_coords [['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'None']] + ignorable [] + no_data_dimension [] + non_equal_data_dimension [['z', 'None']] + non_equal_shape [['z', 'None']] + not_equal [['longitude', 'longitude'], ['z', 'None']] + resamplable [['longitude', 'longitude']] + scalar [] + transposable [] + ungroupable [['z', 'None']] + ungroupable_and_dimensioned [['z', 'None']] diff --git a/lib/iris/tests/results/analysis/coord_comparison/cube3_cube4.txt b/lib/iris/tests/results/analysis/coord_comparison/cube3_cube4.txt index 4be8a473c5..db766729f8 100644 --- a/lib/iris/tests/results/analysis/coord_comparison/cube3_cube4.txt +++ b/lib/iris/tests/results/analysis/coord_comparison/cube3_cube4.txt @@ -1,14 +1,14 @@ - grouped_coords [['f', 'None'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] - not_equal [['f', 'None'], ['longitude', 'longitude'], ['z', 'z']] dimensioned [['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] - non_equal_shape [['f', 'None'], ['z', 'z']] equal [['latitude', 'latitude']] equal_data_dimension [['latitude', 'latitude'], ['longitude', 'longitude']] - resamplable [['longitude', 'longitude']] + grouped_coords [['f', 'None'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'z']] + ignorable [['f', 'None']] no_data_dimension [['f', 'None']] - ungroupable [['f', 'None']] + non_equal_data_dimension [['f', 'None'], ['z', 'z']] + non_equal_shape [['f', 'None'], ['z', 'z']] + not_equal [['f', 'None'], ['longitude', 'longitude'], ['z', 'z']] + resamplable [['longitude', 'longitude']] scalar [['f', 'None']] transposable [] - non_equal_data_dimension [['f', 'None'], ['z', 'z']] + ungroupable [['f', 'None']] ungroupable_and_dimensioned [] - ignorable [['f', 'None']] diff --git a/lib/iris/tests/results/analysis/coord_comparison/cube3_cube5.txt b/lib/iris/tests/results/analysis/coord_comparison/cube3_cube5.txt new file mode 100644 index 0000000000..7859ef2d2c --- /dev/null +++ b/lib/iris/tests/results/analysis/coord_comparison/cube3_cube5.txt @@ -0,0 +1,14 @@ + dimensioned [['latitude', 'latitude'], ['longitude', 'longitude']] + equal [['latitude', 'latitude'], ['longitude', 'longitude']] + equal_data_dimension [] + grouped_coords [['f', 'None'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'None']] + ignorable [['f', 'None'], ['z', 'None']] + no_data_dimension [['f', 'None'], ['z', 'None']] + non_equal_data_dimension [['f', 'None'], ['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'None']] + non_equal_shape [['f', 'None'], ['z', 'None']] + not_equal [['f', 'None'], ['z', 'None']] + resamplable [] + scalar [['f', 'None'], ['z', 'None']] + transposable [['latitude', 'latitude'], ['longitude', 'longitude']] + ungroupable [['f', 'None'], ['z', 'None']] + ungroupable_and_dimensioned [] diff --git a/lib/iris/tests/results/analysis/coord_comparison/cube4_cube5.txt b/lib/iris/tests/results/analysis/coord_comparison/cube4_cube5.txt new file mode 100644 index 0000000000..25fd739bea --- /dev/null +++ b/lib/iris/tests/results/analysis/coord_comparison/cube4_cube5.txt @@ -0,0 +1,14 @@ + dimensioned [['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'None']] + equal [['latitude', 'latitude']] + equal_data_dimension [] + grouped_coords [['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'None']] + ignorable [] + no_data_dimension [] + non_equal_data_dimension [['latitude', 'latitude'], ['longitude', 'longitude'], ['z', 'None']] + non_equal_shape [['z', 'None']] + not_equal [['longitude', 'longitude'], ['z', 'None']] + resamplable [] + scalar [] + transposable [['latitude', 'latitude']] + ungroupable [['z', 'None']] + ungroupable_and_dimensioned [['z', 'None']] diff --git a/lib/iris/tests/results/analysis/count_bar_2d.cml b/lib/iris/tests/results/analysis/count_bar_2d.cml index 46cd76e32c..3457187d4e 100644 --- a/lib/iris/tests/results/analysis/count_bar_2d.cml +++ b/lib/iris/tests/results/analysis/count_bar_2d.cml @@ -1,15 +1,15 @@ - + - + + [30, 45]]" id="b0d35dcf" long_name="foo" points="[-7.5, 7.5, 22.5, 37.5]" shape="(4,)" units="Unit('1')" value_type="float64"/> @@ -17,6 +17,6 @@ - + diff --git a/lib/iris/tests/results/analysis/count_foo_1d.cml b/lib/iris/tests/results/analysis/count_foo_1d.cml index 6df467a98f..6a76951959 100644 --- a/lib/iris/tests/results/analysis/count_foo_1d.cml +++ b/lib/iris/tests/results/analysis/count_foo_1d.cml @@ -1,9 +1,9 @@ - + - + @@ -11,6 +11,6 @@ - + diff --git a/lib/iris/tests/results/analysis/count_foo_2d.cml b/lib/iris/tests/results/analysis/count_foo_2d.cml index aada5d8935..af4ee81c3f 100644 --- a/lib/iris/tests/results/analysis/count_foo_2d.cml +++ b/lib/iris/tests/results/analysis/count_foo_2d.cml @@ -1,14 +1,14 @@ - + + [10, 15]]" id="434cbbd8" long_name="bar" points="[2.5, 7.5, 12.5]" shape="(3,)" units="Unit('1')" value_type="float64"/> - + @@ -16,6 +16,6 @@ - + diff --git a/lib/iris/tests/results/analysis/count_foo_bar_2d.cml b/lib/iris/tests/results/analysis/count_foo_bar_2d.cml index 25370d16da..47a25bbd84 100644 --- a/lib/iris/tests/results/analysis/count_foo_bar_2d.cml +++ b/lib/iris/tests/results/analysis/count_foo_bar_2d.cml @@ -1,12 +1,12 @@ - + - + - + @@ -15,6 +15,6 @@ - + diff --git a/lib/iris/tests/results/analysis/delta_and_midpoint/delta_one_element_explicit.xml b/lib/iris/tests/results/analysis/delta_and_midpoint/delta_one_element_explicit.xml index 7e2328b8c4..494d198e64 100644 --- a/lib/iris/tests/results/analysis/delta_and_midpoint/delta_one_element_explicit.xml +++ b/lib/iris/tests/results/analysis/delta_and_midpoint/delta_one_element_explicit.xml @@ -1,2 +1,2 @@ - + diff --git a/lib/iris/tests/results/analysis/delta_and_midpoint/midpoint_one_element_explicit.xml b/lib/iris/tests/results/analysis/delta_and_midpoint/midpoint_one_element_explicit.xml index 28209f602d..8b68a16b47 100644 --- a/lib/iris/tests/results/analysis/delta_and_midpoint/midpoint_one_element_explicit.xml +++ b/lib/iris/tests/results/analysis/delta_and_midpoint/midpoint_one_element_explicit.xml @@ -1,2 +1,2 @@ - + diff --git a/lib/iris/tests/results/analysis/delta_and_midpoint/simple1.cml b/lib/iris/tests/results/analysis/delta_and_midpoint/simple1.cml index 2cda13a99a..b4c123e294 100644 --- a/lib/iris/tests/results/analysis/delta_and_midpoint/simple1.cml +++ b/lib/iris/tests/results/analysis/delta_and_midpoint/simple1.cml @@ -1,2 +1,2 @@ - + diff --git a/lib/iris/tests/results/analysis/delta_and_midpoint/simple1_delta.cml b/lib/iris/tests/results/analysis/delta_and_midpoint/simple1_delta.cml index d60415fada..c81ccfc9e8 100644 --- a/lib/iris/tests/results/analysis/delta_and_midpoint/simple1_delta.cml +++ b/lib/iris/tests/results/analysis/delta_and_midpoint/simple1_delta.cml @@ -1,2 +1,2 @@ - + diff --git a/lib/iris/tests/results/analysis/delta_and_midpoint/simple1_midpoint.cml b/lib/iris/tests/results/analysis/delta_and_midpoint/simple1_midpoint.cml index 4a03728569..f97d74bff8 100644 --- a/lib/iris/tests/results/analysis/delta_and_midpoint/simple1_midpoint.cml +++ b/lib/iris/tests/results/analysis/delta_and_midpoint/simple1_midpoint.cml @@ -1,2 +1,2 @@ - + diff --git a/lib/iris/tests/results/analysis/delta_and_midpoint/simple2.cml b/lib/iris/tests/results/analysis/delta_and_midpoint/simple2.cml index bd20537342..50bc4d77c1 100644 --- a/lib/iris/tests/results/analysis/delta_and_midpoint/simple2.cml +++ b/lib/iris/tests/results/analysis/delta_and_midpoint/simple2.cml @@ -1,2 +1,2 @@ - + diff --git a/lib/iris/tests/results/analysis/delta_and_midpoint/simple2_delta.cml b/lib/iris/tests/results/analysis/delta_and_midpoint/simple2_delta.cml index 5bf6db21d8..a4621734d3 100644 --- a/lib/iris/tests/results/analysis/delta_and_midpoint/simple2_delta.cml +++ b/lib/iris/tests/results/analysis/delta_and_midpoint/simple2_delta.cml @@ -1,2 +1,2 @@ - + diff --git a/lib/iris/tests/results/analysis/delta_and_midpoint/simple2_midpoint.cml b/lib/iris/tests/results/analysis/delta_and_midpoint/simple2_midpoint.cml index b9d26fbf29..a981e2b79c 100644 --- a/lib/iris/tests/results/analysis/delta_and_midpoint/simple2_midpoint.cml +++ b/lib/iris/tests/results/analysis/delta_and_midpoint/simple2_midpoint.cml @@ -1,2 +1,2 @@ - + diff --git a/lib/iris/tests/results/analysis/delta_and_midpoint/simple3.cml b/lib/iris/tests/results/analysis/delta_and_midpoint/simple3.cml index 1bb75a4ff0..f088c97634 100644 --- a/lib/iris/tests/results/analysis/delta_and_midpoint/simple3.cml +++ b/lib/iris/tests/results/analysis/delta_and_midpoint/simple3.cml @@ -2,4 +2,4 @@ + [45.0, 135.0]]" circular="True" id="6a05e671" long_name="foo" points="[-180.0, -90.0, 0.0, 90.0]" shape="(4,)" units="Unit('degrees')" value_type="float32"/> diff --git a/lib/iris/tests/results/analysis/delta_and_midpoint/simple3_delta.cml b/lib/iris/tests/results/analysis/delta_and_midpoint/simple3_delta.cml index 32c33559b9..74d7546592 100644 --- a/lib/iris/tests/results/analysis/delta_and_midpoint/simple3_delta.cml +++ b/lib/iris/tests/results/analysis/delta_and_midpoint/simple3_delta.cml @@ -2,4 +2,4 @@ + [90.0, 90.0]]" id="ebe2592f" long_name="change_in_foo" points="[90.0, 90.0, 90.0, 90.0]" shape="(4,)" units="Unit('degrees')" value_type="float32"/> diff --git a/lib/iris/tests/results/analysis/delta_and_midpoint/simple3_midpoint.cml b/lib/iris/tests/results/analysis/delta_and_midpoint/simple3_midpoint.cml index 9c7ac3d5ec..961a953ea5 100644 --- a/lib/iris/tests/results/analysis/delta_and_midpoint/simple3_midpoint.cml +++ b/lib/iris/tests/results/analysis/delta_and_midpoint/simple3_midpoint.cml @@ -2,4 +2,4 @@ + [90.0, 180.0]]" circular="True" id="6a05e671" long_name="foo" points="[-135.0, -45.0, 45.0, 135.0]" shape="(4,)" units="Unit('degrees')" value_type="float32"/> diff --git a/lib/iris/tests/results/analysis/delta_and_midpoint/simple4.cml b/lib/iris/tests/results/analysis/delta_and_midpoint/simple4.cml index cff45d2fa6..fd4e8ed6bf 100644 --- a/lib/iris/tests/results/analysis/delta_and_midpoint/simple4.cml +++ b/lib/iris/tests/results/analysis/delta_and_midpoint/simple4.cml @@ -2,4 +2,4 @@ + [45.0, 135.0]]" id="6a05e671" long_name="foo" points="[-180.0, -90.0, 0.0, 90.0]" shape="(4,)" units="Unit('degrees')" value_type="float32"/> diff --git a/lib/iris/tests/results/analysis/delta_and_midpoint/simple4_delta.cml b/lib/iris/tests/results/analysis/delta_and_midpoint/simple4_delta.cml index 64e6a33a5d..dc6b09a87a 100644 --- a/lib/iris/tests/results/analysis/delta_and_midpoint/simple4_delta.cml +++ b/lib/iris/tests/results/analysis/delta_and_midpoint/simple4_delta.cml @@ -1,4 +1,4 @@ + [90.0, 90.0]]" id="ebe2592f" long_name="change_in_foo" points="[90.0, 90.0, 90.0]" shape="(3,)" units="Unit('degrees')" value_type="float32"/> diff --git a/lib/iris/tests/results/analysis/delta_and_midpoint/simple4_midpoint.cml b/lib/iris/tests/results/analysis/delta_and_midpoint/simple4_midpoint.cml index 8d75d930c1..e413c214e9 100644 --- a/lib/iris/tests/results/analysis/delta_and_midpoint/simple4_midpoint.cml +++ b/lib/iris/tests/results/analysis/delta_and_midpoint/simple4_midpoint.cml @@ -1,4 +1,4 @@ + [0.0, 90.0]]" id="6a05e671" long_name="foo" points="[-135.0, -45.0, 45.0]" shape="(3,)" units="Unit('degrees')" value_type="float32"/> diff --git a/lib/iris/tests/results/analysis/delta_and_midpoint/simple5.cml b/lib/iris/tests/results/analysis/delta_and_midpoint/simple5.cml index 25f719bec9..0aad76ca07 100644 --- a/lib/iris/tests/results/analysis/delta_and_midpoint/simple5.cml +++ b/lib/iris/tests/results/analysis/delta_and_midpoint/simple5.cml @@ -1,2 +1,2 @@ - + diff --git a/lib/iris/tests/results/analysis/delta_and_midpoint/simple5_delta.cml b/lib/iris/tests/results/analysis/delta_and_midpoint/simple5_delta.cml index 547a86b293..73ee9c9070 100644 --- a/lib/iris/tests/results/analysis/delta_and_midpoint/simple5_delta.cml +++ b/lib/iris/tests/results/analysis/delta_and_midpoint/simple5_delta.cml @@ -1,2 +1,2 @@ - + diff --git a/lib/iris/tests/results/analysis/delta_and_midpoint/simple5_midpoint.cml b/lib/iris/tests/results/analysis/delta_and_midpoint/simple5_midpoint.cml index 6b4edaf0f2..3e93c682ba 100644 --- a/lib/iris/tests/results/analysis/delta_and_midpoint/simple5_midpoint.cml +++ b/lib/iris/tests/results/analysis/delta_and_midpoint/simple5_midpoint.cml @@ -1,2 +1,2 @@ - + diff --git a/lib/iris/tests/results/analysis/delta_and_midpoint/simple6.cml b/lib/iris/tests/results/analysis/delta_and_midpoint/simple6.cml index a35b25293a..6413204d03 100644 --- a/lib/iris/tests/results/analysis/delta_and_midpoint/simple6.cml +++ b/lib/iris/tests/results/analysis/delta_and_midpoint/simple6.cml @@ -1,2 +1,2 @@ - + diff --git a/lib/iris/tests/results/analysis/division.cml b/lib/iris/tests/results/analysis/division.cml index d78b9973f9..bbe6c1eb90 100644 --- a/lib/iris/tests/results/analysis/division.cml +++ b/lib/iris/tests/results/analysis/division.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/division_by_array.cml b/lib/iris/tests/results/analysis/division_by_array.cml index 48332243b8..cb77adde99 100644 --- a/lib/iris/tests/results/analysis/division_by_array.cml +++ b/lib/iris/tests/results/analysis/division_by_array.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/division_by_latitude.cml b/lib/iris/tests/results/analysis/division_by_latitude.cml index 1247b319c4..3e2abf69cd 100644 --- a/lib/iris/tests/results/analysis/division_by_latitude.cml +++ b/lib/iris/tests/results/analysis/division_by_latitude.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/division_by_longitude.cml b/lib/iris/tests/results/analysis/division_by_longitude.cml index 7eb2141216..b1a0228dc8 100644 --- a/lib/iris/tests/results/analysis/division_by_longitude.cml +++ b/lib/iris/tests/results/analysis/division_by_longitude.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/division_by_singular_coord.cml b/lib/iris/tests/results/analysis/division_by_singular_coord.cml index 992cdaddf1..7f7835a1be 100644 --- a/lib/iris/tests/results/analysis/division_by_singular_coord.cml +++ b/lib/iris/tests/results/analysis/division_by_singular_coord.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/division_scalar.cml b/lib/iris/tests/results/analysis/division_scalar.cml index 48332243b8..cb77adde99 100644 --- a/lib/iris/tests/results/analysis/division_scalar.cml +++ b/lib/iris/tests/results/analysis/division_scalar.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/exp.cml b/lib/iris/tests/results/analysis/exp.cml index 3b916df537..357a84363e 100644 --- a/lib/iris/tests/results/analysis/exp.cml +++ b/lib/iris/tests/results/analysis/exp.cml @@ -1,6 +1,6 @@ - + + [10, 11]]" id="b0d35dcf" long_name="foo" points="[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]" shape="(11,)" units="Unit('1')" value_type="int32"/> - + diff --git a/lib/iris/tests/results/analysis/exp.data.0.json b/lib/iris/tests/results/analysis/exp.data.0.json new file mode 100644 index 0000000000..1e52495f02 --- /dev/null +++ b/lib/iris/tests/results/analysis/exp.data.0.json @@ -0,0 +1 @@ +{"std": 6401.1652629017917, "min": 1.0, "max": 22026.465794806718, "shape": [11], "masked": false, "mean": 3167.7067132119382} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/exp.data.0.npy b/lib/iris/tests/results/analysis/exp.data.0.npy deleted file mode 100644 index d5887314c5..0000000000 Binary files a/lib/iris/tests/results/analysis/exp.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/exponentiate.cml b/lib/iris/tests/results/analysis/exponentiate.cml index 49bff7e56b..a13c6be151 100644 --- a/lib/iris/tests/results/analysis/exponentiate.cml +++ b/lib/iris/tests/results/analysis/exponentiate.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/exponentiate.data.0.json b/lib/iris/tests/results/analysis/exponentiate.data.0.json new file mode 100644 index 0000000000..e7425d0e4a --- /dev/null +++ b/lib/iris/tests/results/analysis/exponentiate.data.0.json @@ -0,0 +1 @@ +{"std": 978472.15716317657, "min": 3.0243033780422146e-09, "max": 4280900.9029495027, "shape": [73, 96], "masked": false, "mean": 802335.05663924129} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/exponentiate.data.0.npy b/lib/iris/tests/results/analysis/exponentiate.data.0.npy deleted file mode 100644 index bf1d6bd75a..0000000000 Binary files a/lib/iris/tests/results/analysis/exponentiate.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/first_quartile_foo_1d.cml b/lib/iris/tests/results/analysis/first_quartile_foo_1d.cml index 9cc35ce957..a9e69c291e 100644 --- a/lib/iris/tests/results/analysis/first_quartile_foo_1d.cml +++ b/lib/iris/tests/results/analysis/first_quartile_foo_1d.cml @@ -1,16 +1,15 @@ - + - + + + + - - - - - - + + diff --git a/lib/iris/tests/results/analysis/first_quartile_foo_1d_fast_percentile.cml b/lib/iris/tests/results/analysis/first_quartile_foo_1d_fast_percentile.cml new file mode 100644 index 0000000000..a9e69c291e --- /dev/null +++ b/lib/iris/tests/results/analysis/first_quartile_foo_1d_fast_percentile.cml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/first_quartile_foo_2d.cml b/lib/iris/tests/results/analysis/first_quartile_foo_2d.cml index f29a6605f2..34c9e746f6 100644 --- a/lib/iris/tests/results/analysis/first_quartile_foo_2d.cml +++ b/lib/iris/tests/results/analysis/first_quartile_foo_2d.cml @@ -1,21 +1,20 @@ - + + [10, 15]]" id="434cbbd8" long_name="bar" points="[2.5, 7.5, 12.5]" shape="(3,)" units="Unit('1')" value_type="float64"/> - + + + + - - - - - - + + diff --git a/lib/iris/tests/results/analysis/first_quartile_foo_2d_fast_percentile.cml b/lib/iris/tests/results/analysis/first_quartile_foo_2d_fast_percentile.cml new file mode 100644 index 0000000000..34c9e746f6 --- /dev/null +++ b/lib/iris/tests/results/analysis/first_quartile_foo_2d_fast_percentile.cml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/first_quartile_foo_bar_2d.cml b/lib/iris/tests/results/analysis/first_quartile_foo_bar_2d.cml index 64620aeda3..b3f135cede 100644 --- a/lib/iris/tests/results/analysis/first_quartile_foo_bar_2d.cml +++ b/lib/iris/tests/results/analysis/first_quartile_foo_bar_2d.cml @@ -1,20 +1,18 @@ - + - + - + + + + - - - - - - - + + diff --git a/lib/iris/tests/results/analysis/first_quartile_foo_bar_2d_fast_percentile.cml b/lib/iris/tests/results/analysis/first_quartile_foo_bar_2d_fast_percentile.cml new file mode 100644 index 0000000000..b3f135cede --- /dev/null +++ b/lib/iris/tests/results/analysis/first_quartile_foo_bar_2d_fast_percentile.cml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/gmean_latitude.cml b/lib/iris/tests/results/analysis/gmean_latitude.cml index e2a2d4aa82..ebe22c54f3 100644 --- a/lib/iris/tests/results/analysis/gmean_latitude.cml +++ b/lib/iris/tests/results/analysis/gmean_latitude.cml @@ -1,32 +1,31 @@ - + - + + - + - + - + - - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/gmean_latitude.data.0.json b/lib/iris/tests/results/analysis/gmean_latitude.data.0.json new file mode 100644 index 0000000000..81da27a8d4 --- /dev/null +++ b/lib/iris/tests/results/analysis/gmean_latitude.data.0.json @@ -0,0 +1 @@ +{"std": 306.9084856481536, "min": 100878.38609750666, "max": 101988.84048626159, "shape": [10, 720], "masked": false, "mean": 101441.5793318709} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/gmean_latitude.data.0.npy b/lib/iris/tests/results/analysis/gmean_latitude.data.0.npy deleted file mode 100644 index 7c235bc402..0000000000 Binary files a/lib/iris/tests/results/analysis/gmean_latitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/gmean_latitude_longitude.cml b/lib/iris/tests/results/analysis/gmean_latitude_longitude.cml index fa7277bd28..3cd6a93948 100644 --- a/lib/iris/tests/results/analysis/gmean_latitude_longitude.cml +++ b/lib/iris/tests/results/analysis/gmean_latitude_longitude.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -38,6 +37,6 @@ - + diff --git a/lib/iris/tests/results/analysis/gmean_latitude_longitude.data.0.json b/lib/iris/tests/results/analysis/gmean_latitude_longitude.data.0.json new file mode 100644 index 0000000000..55a6386cbc --- /dev/null +++ b/lib/iris/tests/results/analysis/gmean_latitude_longitude.data.0.json @@ -0,0 +1 @@ +{"std": 1.4551915228366852e-11, "min": 101441.11521734977, "max": 101441.11521734977, "shape": [10], "masked": false, "mean": 101441.11521734975} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/gmean_latitude_longitude.data.0.npy b/lib/iris/tests/results/analysis/gmean_latitude_longitude.data.0.npy deleted file mode 100644 index 3eb2c7d3aa..0000000000 Binary files a/lib/iris/tests/results/analysis/gmean_latitude_longitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/gmean_latitude_longitude_1call.cml b/lib/iris/tests/results/analysis/gmean_latitude_longitude_1call.cml index 5fe7dc4eb1..cc7b3133e0 100644 --- a/lib/iris/tests/results/analysis/gmean_latitude_longitude_1call.cml +++ b/lib/iris/tests/results/analysis/gmean_latitude_longitude_1call.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/gmean_latitude_longitude_1call.data.0.json b/lib/iris/tests/results/analysis/gmean_latitude_longitude_1call.data.0.json new file mode 100644 index 0000000000..c6c36b2a45 --- /dev/null +++ b/lib/iris/tests/results/analysis/gmean_latitude_longitude_1call.data.0.json @@ -0,0 +1 @@ +{"std": 1.4551915228366852e-11, "min": 101441.11521735013, "max": 101441.11521735013, "shape": [10], "masked": false, "mean": 101441.11521735015} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/gmean_latitude_longitude_1call.data.0.npy b/lib/iris/tests/results/analysis/gmean_latitude_longitude_1call.data.0.npy deleted file mode 100644 index ec3b18b06d..0000000000 Binary files a/lib/iris/tests/results/analysis/gmean_latitude_longitude_1call.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/hmean_latitude.cml b/lib/iris/tests/results/analysis/hmean_latitude.cml index 9d71ed8ea7..d953f0e4d9 100644 --- a/lib/iris/tests/results/analysis/hmean_latitude.cml +++ b/lib/iris/tests/results/analysis/hmean_latitude.cml @@ -1,32 +1,31 @@ - + - + + - + - + - + - - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/hmean_latitude.data.0.json b/lib/iris/tests/results/analysis/hmean_latitude.data.0.json new file mode 100644 index 0000000000..de3773040e --- /dev/null +++ b/lib/iris/tests/results/analysis/hmean_latitude.data.0.json @@ -0,0 +1 @@ +{"std": 62791732.052807324, "min": 10173628652.643913, "max": 10401222118.976389, "shape": [10, 720], "masked": false, "mean": 10289063259.465273} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/hmean_latitude.data.0.npy b/lib/iris/tests/results/analysis/hmean_latitude.data.0.npy deleted file mode 100644 index a5a6b5f729..0000000000 Binary files a/lib/iris/tests/results/analysis/hmean_latitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/hmean_latitude_longitude.cml b/lib/iris/tests/results/analysis/hmean_latitude_longitude.cml index e101f68451..43700b083c 100644 --- a/lib/iris/tests/results/analysis/hmean_latitude_longitude.cml +++ b/lib/iris/tests/results/analysis/hmean_latitude_longitude.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -38,6 +37,6 @@ - + diff --git a/lib/iris/tests/results/analysis/hmean_latitude_longitude.data.0.json b/lib/iris/tests/results/analysis/hmean_latitude_longitude.data.0.json new file mode 100644 index 0000000000..9007f1fdf7 --- /dev/null +++ b/lib/iris/tests/results/analysis/hmean_latitude_longitude.data.0.json @@ -0,0 +1 @@ +{"std": 1.9073486328125e-06, "min": 10288680426.032187, "max": 10288680426.032187, "shape": [10], "masked": false, "mean": 10288680426.032185} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/hmean_latitude_longitude.data.0.npy b/lib/iris/tests/results/analysis/hmean_latitude_longitude.data.0.npy deleted file mode 100644 index 70b32616cf..0000000000 Binary files a/lib/iris/tests/results/analysis/hmean_latitude_longitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/hmean_latitude_longitude_1call.cml b/lib/iris/tests/results/analysis/hmean_latitude_longitude_1call.cml index 67818b9dee..e17383ff64 100644 --- a/lib/iris/tests/results/analysis/hmean_latitude_longitude_1call.cml +++ b/lib/iris/tests/results/analysis/hmean_latitude_longitude_1call.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/hmean_latitude_longitude_1call.data.0.json b/lib/iris/tests/results/analysis/hmean_latitude_longitude_1call.data.0.json new file mode 100644 index 0000000000..10d9962912 --- /dev/null +++ b/lib/iris/tests/results/analysis/hmean_latitude_longitude_1call.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 10288680426.032185, "max": 10288680426.032185, "shape": [10], "masked": false, "mean": 10288680426.032185} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/hmean_latitude_longitude_1call.data.0.npy b/lib/iris/tests/results/analysis/hmean_latitude_longitude_1call.data.0.npy deleted file mode 100644 index 35e77acf32..0000000000 Binary files a/lib/iris/tests/results/analysis/hmean_latitude_longitude_1call.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/interpolation/linear/circular_vs_non_circular.cml b/lib/iris/tests/results/analysis/interpolation/linear/circular_vs_non_circular.cml index db10cb2ae3..594095f50b 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/circular_vs_non_circular.cml +++ b/lib/iris/tests/results/analysis/interpolation/linear/circular_vs_non_circular.cml @@ -1,18 +1,18 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/positive b/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/positive index 133e8ffc05..6654ef46a4 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/positive +++ b/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/positive @@ -1,15 +1,14 @@ - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/positive.data.0.json b/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/positive.data.0.json new file mode 100644 index 0000000000..9bb2969bbd --- /dev/null +++ b/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/positive.data.0.json @@ -0,0 +1 @@ +{"std": 0.33973028517732512, "min": 0.0, "max": 1.1000000000000001, "shape": [3, 24], "masked": false, "mean": 0.55000000000000004} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/positive.data.0.npy b/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/positive.data.0.npy deleted file mode 100644 index 24c285e4d5..0000000000 Binary files a/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/positive.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/symmetric b/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/symmetric index 133e8ffc05..6654ef46a4 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/symmetric +++ b/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/symmetric @@ -1,15 +1,14 @@ - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/symmetric.data.0.json b/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/symmetric.data.0.json new file mode 100644 index 0000000000..9bb2969bbd --- /dev/null +++ b/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/symmetric.data.0.json @@ -0,0 +1 @@ +{"std": 0.33973028517732512, "min": 0.0, "max": 1.1000000000000001, "shape": [3, 24], "masked": false, "mean": 0.55000000000000004} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/symmetric.data.0.npy b/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/symmetric.data.0.npy deleted file mode 100644 index 8b2771133f..0000000000 Binary files a/lib/iris/tests/results/analysis/interpolation/linear/circular_wrapping/symmetric.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/interpolation/linear/dim_to_aux.cml b/lib/iris/tests/results/analysis/interpolation/linear/dim_to_aux.cml index 7055bda7fb..5efc312a0f 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/dim_to_aux.cml +++ b/lib/iris/tests/results/analysis/interpolation/linear/dim_to_aux.cml @@ -1,21 +1,21 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/real_2dslice.cml b/lib/iris/tests/results/analysis/interpolation/linear/real_2dslice.cml index 90a76343ac..63703be654 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/real_2dslice.cml +++ b/lib/iris/tests/results/analysis/interpolation/linear/real_2dslice.cml @@ -1,19 +1,20 @@ - + - + + - + - + - + @@ -55,7 +56,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -68,12 +69,12 @@ - + - @@ -119,7 +120,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -129,7 +130,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -137,6 +138,6 @@ - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/real_2slices.cml b/lib/iris/tests/results/analysis/interpolation/linear/real_2slices.cml index eb78c5bac8..af035e9393 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/real_2slices.cml +++ b/lib/iris/tests/results/analysis/interpolation/linear/real_2slices.cml @@ -1,19 +1,20 @@ - + - + + - + - + - + @@ -55,7 +56,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -68,12 +69,12 @@ - + - @@ -119,7 +120,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -129,7 +130,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -137,6 +138,6 @@ - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/real_circular_2dslice.cml b/lib/iris/tests/results/analysis/interpolation/linear/real_circular_2dslice.cml index 528d9bc0e7..2a9faedb3d 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/real_circular_2dslice.cml +++ b/lib/iris/tests/results/analysis/interpolation/linear/real_circular_2dslice.cml @@ -1,19 +1,20 @@ - + - + + - + - + - + @@ -55,7 +56,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -68,12 +69,12 @@ - + - @@ -119,7 +120,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -129,7 +130,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -137,6 +138,6 @@ - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/simple_casting_datatype.cml b/lib/iris/tests/results/analysis/interpolation/linear/simple_casting_datatype.cml index b8009ad1ed..ccd109ca9a 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/simple_casting_datatype.cml +++ b/lib/iris/tests/results/analysis/interpolation/linear/simple_casting_datatype.cml @@ -1,21 +1,21 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/simple_coord_linear_extrapolation.cml b/lib/iris/tests/results/analysis/interpolation/linear/simple_coord_linear_extrapolation.cml index 819bda6485..fc5140841e 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/simple_coord_linear_extrapolation.cml +++ b/lib/iris/tests/results/analysis/interpolation/linear/simple_coord_linear_extrapolation.cml @@ -1,18 +1,18 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/simple_coord_linear_extrapolation_multipoint1.cml b/lib/iris/tests/results/analysis/interpolation/linear/simple_coord_linear_extrapolation_multipoint1.cml index 9e3433a183..255fe34d7f 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/simple_coord_linear_extrapolation_multipoint1.cml +++ b/lib/iris/tests/results/analysis/interpolation/linear/simple_coord_linear_extrapolation_multipoint1.cml @@ -1,18 +1,18 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/simple_coord_linear_extrapolation_multipoint2.cml b/lib/iris/tests/results/analysis/interpolation/linear/simple_coord_linear_extrapolation_multipoint2.cml index 27f6abf220..46dfe870b8 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/simple_coord_linear_extrapolation_multipoint2.cml +++ b/lib/iris/tests/results/analysis/interpolation/linear/simple_coord_linear_extrapolation_multipoint2.cml @@ -1,18 +1,18 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/simple_coord_nan_extrapolation.cml b/lib/iris/tests/results/analysis/interpolation/linear/simple_coord_nan_extrapolation.cml index cdc364de19..15ac105a91 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/simple_coord_nan_extrapolation.cml +++ b/lib/iris/tests/results/analysis/interpolation/linear/simple_coord_nan_extrapolation.cml @@ -1,18 +1,18 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/simple_multiple_coords.cml b/lib/iris/tests/results/analysis/interpolation/linear/simple_multiple_coords.cml index f440e29093..03657be64c 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/simple_multiple_coords.cml +++ b/lib/iris/tests/results/analysis/interpolation/linear/simple_multiple_coords.cml @@ -1,18 +1,18 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/simple_multiple_coords_extrapolation.cml b/lib/iris/tests/results/analysis/interpolation/linear/simple_multiple_coords_extrapolation.cml index 17a59fb0cd..2f453b1330 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/simple_multiple_coords_extrapolation.cml +++ b/lib/iris/tests/results/analysis/interpolation/linear/simple_multiple_coords_extrapolation.cml @@ -1,18 +1,18 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/simple_multiple_points.cml b/lib/iris/tests/results/analysis/interpolation/linear/simple_multiple_points.cml index ede7f802d7..248848e38b 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/simple_multiple_points.cml +++ b/lib/iris/tests/results/analysis/interpolation/linear/simple_multiple_points.cml @@ -1,18 +1,18 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/simple_multiple_points_circular.cml b/lib/iris/tests/results/analysis/interpolation/linear/simple_multiple_points_circular.cml index a05af5c976..298bdf0f98 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/simple_multiple_points_circular.cml +++ b/lib/iris/tests/results/analysis/interpolation/linear/simple_multiple_points_circular.cml @@ -1,15 +1,15 @@ - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/simple_shared_axis.cml b/lib/iris/tests/results/analysis/interpolation/linear/simple_shared_axis.cml index d33f473e4f..d4fd63d4dc 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/simple_shared_axis.cml +++ b/lib/iris/tests/results/analysis/interpolation/linear/simple_shared_axis.cml @@ -1,21 +1,21 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/simple_single_point.cml b/lib/iris/tests/results/analysis/interpolation/linear/simple_single_point.cml index dbdf0c3a52..bf9f37d8a2 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/simple_single_point.cml +++ b/lib/iris/tests/results/analysis/interpolation/linear/simple_single_point.cml @@ -1,18 +1,18 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_0 b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_0 index 80b072c604..ace42c84f8 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_0 +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_0 @@ -1,19 +1,19 @@ - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_0.data.0.json b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_0.data.0.json new file mode 100644 index 0000000000..526e4b6aab --- /dev/null +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_0.data.0.json @@ -0,0 +1 @@ +{"std": 3.2659863237109041, "min": 2.0, "max": 10.0, "shape": [3, 4], "masked": false, "mean": 6.0} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_0.data.0.npy b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_0.data.0.npy deleted file mode 100644 index 86d6e81709..0000000000 Binary files a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_0.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_1 b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_1 index 2550f82117..6e5a38c646 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_1 +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_1 @@ -1,19 +1,19 @@ - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_1.data.0.json b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_1.data.0.json new file mode 100644 index 0000000000..b22387080a --- /dev/null +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_1.data.0.json @@ -0,0 +1 @@ +{"std": 1.1180339887498949, "min": 4.0, "max": 7.0, "shape": [4, 4], "masked": false, "mean": 5.5} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_1.data.0.npy b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_1.data.0.npy deleted file mode 100644 index a47b258d82..0000000000 Binary files a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_1.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_nan b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_nan index 43e4300284..fc9dc99eef 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_nan +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_nan @@ -1,19 +1,19 @@ - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_nan.data.0.json b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_nan.data.0.json new file mode 100644 index 0000000000..c3bc9b5673 --- /dev/null +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_nan.data.0.json @@ -0,0 +1 @@ +{"std": NaN, "min": NaN, "max": NaN, "shape": [3, 3], "masked": false, "mean": NaN} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_nan.data.0.npy b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_nan.data.0.npy deleted file mode 100644 index 676e8f6ca7..0000000000 Binary files a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_nan.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_same b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_same index 8c37ec5d68..270ad5746b 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_same +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_same @@ -1,19 +1,19 @@ - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_same.data.0.json b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_same.data.0.json new file mode 100644 index 0000000000..e52d7576da --- /dev/null +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_same.data.0.json @@ -0,0 +1 @@ +{"std": 3.2659863237109041, "min": 2.0, "max": 10.0, "shape": [3, 3], "masked": false, "mean": 6.0} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_same.data.0.npy b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_same.data.0.npy deleted file mode 100644 index a489bfae8e..0000000000 Binary files a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_many_same.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_same_pt b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_same_pt index 48f2131d3f..a16308e53f 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_same_pt +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_same_pt @@ -1,19 +1,19 @@ - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_same_pt.data.0.json b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_same_pt.data.0.json new file mode 100644 index 0000000000..083821afc1 --- /dev/null +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_same_pt.data.0.json @@ -0,0 +1 @@ +{"std": 3.2659863237109041, "min": 2.0, "max": 10.0, "shape": [3, 1], "masked": false, "mean": 6.0} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_same_pt.data.0.npy b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_same_pt.data.0.npy deleted file mode 100644 index 71bec8fd98..0000000000 Binary files a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_same_pt.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_0 b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_0 index cef2bb9d37..fe1edd72e7 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_0 +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_0 @@ -1,19 +1,19 @@ - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_0.data.0.json b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_0.data.0.json new file mode 100644 index 0000000000..6b64ed5556 --- /dev/null +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_0.data.0.json @@ -0,0 +1 @@ +{"std": 3.2659863237109041, "min": 2.0, "max": 10.0, "shape": [3], "masked": false, "mean": 6.0} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_0.data.0.npy b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_0.data.0.npy deleted file mode 100644 index da195dd91d..0000000000 Binary files a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_0.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_1 b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_1 index ec1319458b..7e8e447cc1 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_1 +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_1 @@ -1,19 +1,19 @@ - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_1.data.0.json b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_1.data.0.json new file mode 100644 index 0000000000..7d9a7486b6 --- /dev/null +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_1.data.0.json @@ -0,0 +1 @@ +{"std": 1.1180339887498949, "min": 4.0, "max": 7.0, "shape": [4], "masked": false, "mean": 5.5} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_1.data.0.npy b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_1.data.0.npy deleted file mode 100644 index 7596c5e945..0000000000 Binary files a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_1.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_nan b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_nan index aba2401a53..48fdd173da 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_nan +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_nan @@ -1,19 +1,19 @@ - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_nan.data.0.json b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_nan.data.0.json new file mode 100644 index 0000000000..28e588dc39 --- /dev/null +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_nan.data.0.json @@ -0,0 +1 @@ +{"std": NaN, "min": NaN, "max": NaN, "shape": [3], "masked": false, "mean": NaN} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_nan.data.0.npy b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_nan.data.0.npy deleted file mode 100644 index 988998331b..0000000000 Binary files a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_scalar_nan.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_0 b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_0 index 48f2131d3f..21078b9bb8 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_0 +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_0 @@ -1,19 +1,19 @@ - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_0.data.0.json b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_0.data.0.json new file mode 100644 index 0000000000..083821afc1 --- /dev/null +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_0.data.0.json @@ -0,0 +1 @@ +{"std": 3.2659863237109041, "min": 2.0, "max": 10.0, "shape": [3, 1], "masked": false, "mean": 6.0} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_0.data.0.npy b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_0.data.0.npy deleted file mode 100644 index 71bec8fd98..0000000000 Binary files a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_0.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_1 b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_1 index a021ba60e9..c0a3808c71 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_1 +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_1 @@ -1,19 +1,19 @@ - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_1.data.0.json b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_1.data.0.json new file mode 100644 index 0000000000..6eb7f12a11 --- /dev/null +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_1.data.0.json @@ -0,0 +1 @@ +{"std": 1.1180339887498949, "min": 4.0, "max": 7.0, "shape": [1, 4], "masked": false, "mean": 5.5} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_1.data.0.npy b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_1.data.0.npy deleted file mode 100644 index 28f66974d8..0000000000 Binary files a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_1.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_nan b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_nan index e03875fd3f..54764eb0a2 100644 --- a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_nan +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_nan @@ -1,19 +1,19 @@ - + - + - + - + diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_nan.data.0.json b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_nan.data.0.json new file mode 100644 index 0000000000..ba31ec5d67 --- /dev/null +++ b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_nan.data.0.json @@ -0,0 +1 @@ +{"std": NaN, "min": NaN, "max": NaN, "shape": [3, 1], "masked": false, "mean": NaN} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_nan.data.0.npy b/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_nan.data.0.npy deleted file mode 100644 index 351715ceb0..0000000000 Binary files a/lib/iris/tests/results/analysis/interpolation/linear/single_pt_to_single_pt_nan.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/interpolation/nearest_neighbour_extract_bounded.cml b/lib/iris/tests/results/analysis/interpolation/nearest_neighbour_extract_bounded.cml index 7bc1a3ad25..2a354e7397 100644 --- a/lib/iris/tests/results/analysis/interpolation/nearest_neighbour_extract_bounded.cml +++ b/lib/iris/tests/results/analysis/interpolation/nearest_neighbour_extract_bounded.cml @@ -1,42 +1,45 @@ - + - + - + - + - + - + - + - + - + + + + - + diff --git a/lib/iris/tests/results/analysis/interpolation/nearest_neighbour_extract_bounded_mid_point.cml b/lib/iris/tests/results/analysis/interpolation/nearest_neighbour_extract_bounded_mid_point.cml index 7bc1a3ad25..2a354e7397 100644 --- a/lib/iris/tests/results/analysis/interpolation/nearest_neighbour_extract_bounded_mid_point.cml +++ b/lib/iris/tests/results/analysis/interpolation/nearest_neighbour_extract_bounded_mid_point.cml @@ -1,42 +1,45 @@ - + - + - + - + - + - + - + - + - + + + + - + diff --git a/lib/iris/tests/results/analysis/interpolation/nearest_neighbour_extract_latitude.cml b/lib/iris/tests/results/analysis/interpolation/nearest_neighbour_extract_latitude.cml index e9fecdf74d..96568028eb 100644 --- a/lib/iris/tests/results/analysis/interpolation/nearest_neighbour_extract_latitude.cml +++ b/lib/iris/tests/results/analysis/interpolation/nearest_neighbour_extract_latitude.cml @@ -1,42 +1,45 @@ - + - + - + - + - + - + - + - + - + + + + - + diff --git a/lib/iris/tests/results/analysis/interpolation/nearest_neighbour_extract_latitude_longitude.cml b/lib/iris/tests/results/analysis/interpolation/nearest_neighbour_extract_latitude_longitude.cml index 86080a0a8e..0bd5fd46d8 100644 --- a/lib/iris/tests/results/analysis/interpolation/nearest_neighbour_extract_latitude_longitude.cml +++ b/lib/iris/tests/results/analysis/interpolation/nearest_neighbour_extract_latitude_longitude.cml @@ -1,42 +1,45 @@ - + - + - + - + - + - + - + - + - + + + + - + diff --git a/lib/iris/tests/results/analysis/last_quartile_foo_3d_masked.cml b/lib/iris/tests/results/analysis/last_quartile_foo_3d_masked.cml index 0de2532891..80fab0e150 100644 --- a/lib/iris/tests/results/analysis/last_quartile_foo_3d_masked.cml +++ b/lib/iris/tests/results/analysis/last_quartile_foo_3d_masked.cml @@ -1,22 +1,21 @@ - + - + - + - + + + + - - - - - - + + diff --git a/lib/iris/tests/results/analysis/last_quartile_foo_3d_notmasked.cml b/lib/iris/tests/results/analysis/last_quartile_foo_3d_notmasked.cml index 0de2532891..80fab0e150 100644 --- a/lib/iris/tests/results/analysis/last_quartile_foo_3d_notmasked.cml +++ b/lib/iris/tests/results/analysis/last_quartile_foo_3d_notmasked.cml @@ -1,22 +1,21 @@ - + - + - + - + + + + - - - - - - + + diff --git a/lib/iris/tests/results/analysis/last_quartile_foo_3d_notmasked_fast_percentile.cml b/lib/iris/tests/results/analysis/last_quartile_foo_3d_notmasked_fast_percentile.cml new file mode 100644 index 0000000000..80fab0e150 --- /dev/null +++ b/lib/iris/tests/results/analysis/last_quartile_foo_3d_notmasked_fast_percentile.cml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/log.cml b/lib/iris/tests/results/analysis/log.cml index 2a2e5f7b99..33214d01f1 100644 --- a/lib/iris/tests/results/analysis/log.cml +++ b/lib/iris/tests/results/analysis/log.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/log.data.0.json b/lib/iris/tests/results/analysis/log.data.0.json new file mode 100644 index 0000000000..c17557292d --- /dev/null +++ b/lib/iris/tests/results/analysis/log.data.0.json @@ -0,0 +1 @@ +{"std": 0.059119906276464462, "min": 5.500091552734375, "max": 5.7219061851501465, "shape": [73, 96], "masked": false, "mean": 5.6328606605529785} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/log.data.0.npy b/lib/iris/tests/results/analysis/log.data.0.npy deleted file mode 100644 index 0d2533c3e8..0000000000 Binary files a/lib/iris/tests/results/analysis/log.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/log10.cml b/lib/iris/tests/results/analysis/log10.cml index 6e304036e7..fbee8f73f0 100644 --- a/lib/iris/tests/results/analysis/log10.cml +++ b/lib/iris/tests/results/analysis/log10.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/log10.data.0.json b/lib/iris/tests/results/analysis/log10.data.0.json new file mode 100644 index 0000000000..d5c0091b03 --- /dev/null +++ b/lib/iris/tests/results/analysis/log10.data.0.json @@ -0,0 +1 @@ +{"std": 0.025675451382994652, "min": 2.3886594772338867, "max": 2.4849922657012939, "shape": [73, 96], "masked": false, "mean": 2.4463202953338623} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/log10.data.0.npy b/lib/iris/tests/results/analysis/log10.data.0.npy deleted file mode 100644 index ab3c8084f4..0000000000 Binary files a/lib/iris/tests/results/analysis/log10.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/log2.cml b/lib/iris/tests/results/analysis/log2.cml index ef29a01c94..6371f3925b 100644 --- a/lib/iris/tests/results/analysis/log2.cml +++ b/lib/iris/tests/results/analysis/log2.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/log2.data.0.json b/lib/iris/tests/results/analysis/log2.data.0.json new file mode 100644 index 0000000000..08b3b3fac5 --- /dev/null +++ b/lib/iris/tests/results/analysis/log2.data.0.json @@ -0,0 +1 @@ +{"std": 0.085292011499404907, "min": 7.9349546432495117, "max": 8.2549657821655273, "shape": [73, 96], "masked": false, "mean": 8.126500129699707} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/log2.data.0.npy b/lib/iris/tests/results/analysis/log2.data.0.npy deleted file mode 100644 index 29dd4162a7..0000000000 Binary files a/lib/iris/tests/results/analysis/log2.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/maths_original.cml b/lib/iris/tests/results/analysis/maths_original.cml index 78d13fc283..15fbb5210f 100644 --- a/lib/iris/tests/results/analysis/maths_original.cml +++ b/lib/iris/tests/results/analysis/maths_original.cml @@ -1,19 +1,19 @@ - + - + - + - - + - + - + - + + + + - + diff --git a/lib/iris/tests/results/analysis/max_latitude.cml b/lib/iris/tests/results/analysis/max_latitude.cml index 0349d5dd29..faa54fff8a 100644 --- a/lib/iris/tests/results/analysis/max_latitude.cml +++ b/lib/iris/tests/results/analysis/max_latitude.cml @@ -1,32 +1,31 @@ - + - + + - + - + - + - - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/max_latitude.data.0.json b/lib/iris/tests/results/analysis/max_latitude.data.0.json new file mode 100644 index 0000000000..5774626548 --- /dev/null +++ b/lib/iris/tests/results/analysis/max_latitude.data.0.json @@ -0,0 +1 @@ +{"std": 331.70321238027685, "min": 101864.0, "max": 102977.0, "shape": [10, 720], "masked": false, "mean": 102466.40277777778} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/max_latitude.data.0.npy b/lib/iris/tests/results/analysis/max_latitude.data.0.npy deleted file mode 100644 index a95c8e6355..0000000000 Binary files a/lib/iris/tests/results/analysis/max_latitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/max_latitude_longitude.cml b/lib/iris/tests/results/analysis/max_latitude_longitude.cml index a5915c391b..8437e8f4a1 100644 --- a/lib/iris/tests/results/analysis/max_latitude_longitude.cml +++ b/lib/iris/tests/results/analysis/max_latitude_longitude.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -38,6 +37,6 @@ - + diff --git a/lib/iris/tests/results/analysis/max_latitude_longitude.data.0.json b/lib/iris/tests/results/analysis/max_latitude_longitude.data.0.json new file mode 100644 index 0000000000..c3ca8ecf59 --- /dev/null +++ b/lib/iris/tests/results/analysis/max_latitude_longitude.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 102977.0, "max": 102977.0, "shape": [10], "masked": false, "mean": 102977.0} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/max_latitude_longitude.data.0.npy b/lib/iris/tests/results/analysis/max_latitude_longitude.data.0.npy deleted file mode 100644 index 46d6c7e814..0000000000 Binary files a/lib/iris/tests/results/analysis/max_latitude_longitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/max_latitude_longitude_1call.cml b/lib/iris/tests/results/analysis/max_latitude_longitude_1call.cml index 9dc94dc8ce..5b6504dfb1 100644 --- a/lib/iris/tests/results/analysis/max_latitude_longitude_1call.cml +++ b/lib/iris/tests/results/analysis/max_latitude_longitude_1call.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/max_latitude_longitude_1call.data.0.json b/lib/iris/tests/results/analysis/max_latitude_longitude_1call.data.0.json new file mode 100644 index 0000000000..c3ca8ecf59 --- /dev/null +++ b/lib/iris/tests/results/analysis/max_latitude_longitude_1call.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 102977.0, "max": 102977.0, "shape": [10], "masked": false, "mean": 102977.0} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/max_latitude_longitude_1call.data.0.npy b/lib/iris/tests/results/analysis/max_latitude_longitude_1call.data.0.npy deleted file mode 100644 index 46d6c7e814..0000000000 Binary files a/lib/iris/tests/results/analysis/max_latitude_longitude_1call.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/mean_latitude.cml b/lib/iris/tests/results/analysis/mean_latitude.cml index 8f5f2d95eb..fcf2ef55be 100644 --- a/lib/iris/tests/results/analysis/mean_latitude.cml +++ b/lib/iris/tests/results/analysis/mean_latitude.cml @@ -1,32 +1,31 @@ - + - + + - + - + - + - - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/mean_latitude.data.0.json b/lib/iris/tests/results/analysis/mean_latitude.data.0.json new file mode 100644 index 0000000000..bffdff6979 --- /dev/null +++ b/lib/iris/tests/results/analysis/mean_latitude.data.0.json @@ -0,0 +1 @@ +{"std": 305.67198815976997, "min": 100885.3425925926, "max": 101990.07175925926, "shape": [10, 720], "masked": false, "mean": 101445.07356931583} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/mean_latitude.data.0.npy b/lib/iris/tests/results/analysis/mean_latitude.data.0.npy deleted file mode 100644 index 4691185210..0000000000 Binary files a/lib/iris/tests/results/analysis/mean_latitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/mean_latitude_longitude.cml b/lib/iris/tests/results/analysis/mean_latitude_longitude.cml index 8eb7483fd6..5cb139be1a 100644 --- a/lib/iris/tests/results/analysis/mean_latitude_longitude.cml +++ b/lib/iris/tests/results/analysis/mean_latitude_longitude.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -38,6 +37,6 @@ - + diff --git a/lib/iris/tests/results/analysis/mean_latitude_longitude.data.0.json b/lib/iris/tests/results/analysis/mean_latitude_longitude.data.0.json new file mode 100644 index 0000000000..987ed362c3 --- /dev/null +++ b/lib/iris/tests/results/analysis/mean_latitude_longitude.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 101445.07356931586, "max": 101445.07356931586, "shape": [10], "masked": false, "mean": 101445.07356931586} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/mean_latitude_longitude.data.0.npy b/lib/iris/tests/results/analysis/mean_latitude_longitude.data.0.npy deleted file mode 100644 index 522980b4fe..0000000000 Binary files a/lib/iris/tests/results/analysis/mean_latitude_longitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/mean_latitude_longitude_1call.cml b/lib/iris/tests/results/analysis/mean_latitude_longitude_1call.cml index ca78d0cdf4..573fa1c694 100644 --- a/lib/iris/tests/results/analysis/mean_latitude_longitude_1call.cml +++ b/lib/iris/tests/results/analysis/mean_latitude_longitude_1call.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/mean_latitude_longitude_1call.data.0.json b/lib/iris/tests/results/analysis/mean_latitude_longitude_1call.data.0.json new file mode 100644 index 0000000000..008d011f5c --- /dev/null +++ b/lib/iris/tests/results/analysis/mean_latitude_longitude_1call.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 101445.07356931585, "max": 101445.07356931585, "shape": [10], "masked": false, "mean": 101445.07356931585} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/mean_latitude_longitude_1call.data.0.npy b/lib/iris/tests/results/analysis/mean_latitude_longitude_1call.data.0.npy deleted file mode 100644 index 2e21c2a497..0000000000 Binary files a/lib/iris/tests/results/analysis/mean_latitude_longitude_1call.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/median_latitude.cml b/lib/iris/tests/results/analysis/median_latitude.cml index dbec19f0fd..49006c9592 100644 --- a/lib/iris/tests/results/analysis/median_latitude.cml +++ b/lib/iris/tests/results/analysis/median_latitude.cml @@ -1,32 +1,31 @@ - + - + + - + - + - + - - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/median_latitude.data.0.json b/lib/iris/tests/results/analysis/median_latitude.data.0.json new file mode 100644 index 0000000000..c0262df28d --- /dev/null +++ b/lib/iris/tests/results/analysis/median_latitude.data.0.json @@ -0,0 +1 @@ +{"std": 247.17003116388435, "min": 101023.5, "max": 102126.0, "shape": [10, 720], "masked": false, "mean": 101629.08333333333} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/median_latitude.data.0.npy b/lib/iris/tests/results/analysis/median_latitude.data.0.npy deleted file mode 100644 index 5ad4a357cf..0000000000 Binary files a/lib/iris/tests/results/analysis/median_latitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/median_latitude_longitude.cml b/lib/iris/tests/results/analysis/median_latitude_longitude.cml index 8c4b53d6b1..49ec42b391 100644 --- a/lib/iris/tests/results/analysis/median_latitude_longitude.cml +++ b/lib/iris/tests/results/analysis/median_latitude_longitude.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -38,6 +37,6 @@ - + diff --git a/lib/iris/tests/results/analysis/median_latitude_longitude.data.0.json b/lib/iris/tests/results/analysis/median_latitude_longitude.data.0.json new file mode 100644 index 0000000000..02a76b608d --- /dev/null +++ b/lib/iris/tests/results/analysis/median_latitude_longitude.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 101658.25, "max": 101658.25, "shape": [10], "masked": false, "mean": 101658.25} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/median_latitude_longitude.data.0.npy b/lib/iris/tests/results/analysis/median_latitude_longitude.data.0.npy deleted file mode 100644 index bd726f476e..0000000000 Binary files a/lib/iris/tests/results/analysis/median_latitude_longitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/median_latitude_longitude_1call.cml b/lib/iris/tests/results/analysis/median_latitude_longitude_1call.cml index f3d51ff999..036c6bb2f9 100644 --- a/lib/iris/tests/results/analysis/median_latitude_longitude_1call.cml +++ b/lib/iris/tests/results/analysis/median_latitude_longitude_1call.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/median_latitude_longitude_1call.data.0.json b/lib/iris/tests/results/analysis/median_latitude_longitude_1call.data.0.json new file mode 100644 index 0000000000..f217bff025 --- /dev/null +++ b/lib/iris/tests/results/analysis/median_latitude_longitude_1call.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 101604.0, "max": 101604.0, "shape": [10], "masked": false, "mean": 101604.0} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/median_latitude_longitude_1call.data.0.npy b/lib/iris/tests/results/analysis/median_latitude_longitude_1call.data.0.npy deleted file mode 100644 index 1a70039a62..0000000000 Binary files a/lib/iris/tests/results/analysis/median_latitude_longitude_1call.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/min_latitude.cml b/lib/iris/tests/results/analysis/min_latitude.cml index d01f1774a7..34a2dc5548 100644 --- a/lib/iris/tests/results/analysis/min_latitude.cml +++ b/lib/iris/tests/results/analysis/min_latitude.cml @@ -1,32 +1,31 @@ - + - + + - + - + - + - - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/min_latitude.data.0.json b/lib/iris/tests/results/analysis/min_latitude.data.0.json new file mode 100644 index 0000000000..b2f51e64b1 --- /dev/null +++ b/lib/iris/tests/results/analysis/min_latitude.data.0.json @@ -0,0 +1 @@ +{"std": 812.32687602393321, "min": 98385.0, "max": 101362.0, "shape": [10, 720], "masked": false, "mean": 99766.430555555562} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/min_latitude.data.0.npy b/lib/iris/tests/results/analysis/min_latitude.data.0.npy deleted file mode 100644 index 61d32da1b0..0000000000 Binary files a/lib/iris/tests/results/analysis/min_latitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/min_latitude_longitude.cml b/lib/iris/tests/results/analysis/min_latitude_longitude.cml index a2fe72ee36..76c7e96bce 100644 --- a/lib/iris/tests/results/analysis/min_latitude_longitude.cml +++ b/lib/iris/tests/results/analysis/min_latitude_longitude.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -38,6 +37,6 @@ - + diff --git a/lib/iris/tests/results/analysis/min_latitude_longitude.data.0.json b/lib/iris/tests/results/analysis/min_latitude_longitude.data.0.json new file mode 100644 index 0000000000..ae0619a07a --- /dev/null +++ b/lib/iris/tests/results/analysis/min_latitude_longitude.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 98385.0, "max": 98385.0, "shape": [10], "masked": false, "mean": 98385.0} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/min_latitude_longitude.data.0.npy b/lib/iris/tests/results/analysis/min_latitude_longitude.data.0.npy deleted file mode 100644 index 8ae56407a3..0000000000 Binary files a/lib/iris/tests/results/analysis/min_latitude_longitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/min_latitude_longitude_1call.cml b/lib/iris/tests/results/analysis/min_latitude_longitude_1call.cml index 4813a4cabb..6b484eb591 100644 --- a/lib/iris/tests/results/analysis/min_latitude_longitude_1call.cml +++ b/lib/iris/tests/results/analysis/min_latitude_longitude_1call.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/min_latitude_longitude_1call.data.0.json b/lib/iris/tests/results/analysis/min_latitude_longitude_1call.data.0.json new file mode 100644 index 0000000000..ae0619a07a --- /dev/null +++ b/lib/iris/tests/results/analysis/min_latitude_longitude_1call.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 98385.0, "max": 98385.0, "shape": [10], "masked": false, "mean": 98385.0} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/min_latitude_longitude_1call.data.0.npy b/lib/iris/tests/results/analysis/min_latitude_longitude_1call.data.0.npy deleted file mode 100644 index 8ae56407a3..0000000000 Binary files a/lib/iris/tests/results/analysis/min_latitude_longitude_1call.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/multiply.cml b/lib/iris/tests/results/analysis/multiply.cml index 2d928a0f4a..44996a9138 100644 --- a/lib/iris/tests/results/analysis/multiply.cml +++ b/lib/iris/tests/results/analysis/multiply.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/multiply_different_std_name.cml b/lib/iris/tests/results/analysis/multiply_different_std_name.cml index 63a850d2d1..49f1779b77 100644 --- a/lib/iris/tests/results/analysis/multiply_different_std_name.cml +++ b/lib/iris/tests/results/analysis/multiply_different_std_name.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/original.cml b/lib/iris/tests/results/analysis/original.cml index 250b58bc89..23129095b6 100644 --- a/lib/iris/tests/results/analysis/original.cml +++ b/lib/iris/tests/results/analysis/original.cml @@ -1,37 +1,36 @@ - + - + + - + - + - + - - - + diff --git a/lib/iris/tests/results/analysis/original_common.cml b/lib/iris/tests/results/analysis/original_common.cml index 9251722d17..c1759c12bd 100644 --- a/lib/iris/tests/results/analysis/original_common.cml +++ b/lib/iris/tests/results/analysis/original_common.cml @@ -1,37 +1,36 @@ - + - + + - + - + - + - - - + diff --git a/lib/iris/tests/results/analysis/original_hmean.cml b/lib/iris/tests/results/analysis/original_hmean.cml index 7d0ce09e5f..952cede1c2 100644 --- a/lib/iris/tests/results/analysis/original_hmean.cml +++ b/lib/iris/tests/results/analysis/original_hmean.cml @@ -1,37 +1,36 @@ - + - + + - + - + - + - - - + diff --git a/lib/iris/tests/results/analysis/project/default_source_cs.cml b/lib/iris/tests/results/analysis/project/default_source_cs.cml deleted file mode 100644 index a0b2fcecc0..0000000000 --- a/lib/iris/tests/results/analysis/project/default_source_cs.cml +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/analysis/proportion_bar_2d.cml b/lib/iris/tests/results/analysis/proportion_bar_2d.cml index 63f6523d5f..263fcaba9e 100644 --- a/lib/iris/tests/results/analysis/proportion_bar_2d.cml +++ b/lib/iris/tests/results/analysis/proportion_bar_2d.cml @@ -1,15 +1,15 @@ - + - + + [30, 45]]" id="b0d35dcf" long_name="foo" points="[-7.5, 7.5, 22.5, 37.5]" shape="(4,)" units="Unit('1')" value_type="float64"/> @@ -17,6 +17,6 @@ - + diff --git a/lib/iris/tests/results/analysis/proportion_foo_1d.cml b/lib/iris/tests/results/analysis/proportion_foo_1d.cml index 95edd42379..a0bd3c982f 100644 --- a/lib/iris/tests/results/analysis/proportion_foo_1d.cml +++ b/lib/iris/tests/results/analysis/proportion_foo_1d.cml @@ -1,9 +1,9 @@ - + - + @@ -11,6 +11,6 @@ - + diff --git a/lib/iris/tests/results/analysis/proportion_foo_2d.cml b/lib/iris/tests/results/analysis/proportion_foo_2d.cml index e2095dce12..d715499e58 100644 --- a/lib/iris/tests/results/analysis/proportion_foo_2d.cml +++ b/lib/iris/tests/results/analysis/proportion_foo_2d.cml @@ -1,14 +1,14 @@ - + + [10, 15]]" id="434cbbd8" long_name="bar" points="[2.5, 7.5, 12.5]" shape="(3,)" units="Unit('1')" value_type="float64"/> - + @@ -16,6 +16,6 @@ - + diff --git a/lib/iris/tests/results/analysis/proportion_foo_2d_masked.cml b/lib/iris/tests/results/analysis/proportion_foo_2d_masked.cml index 63f6523d5f..263fcaba9e 100644 --- a/lib/iris/tests/results/analysis/proportion_foo_2d_masked.cml +++ b/lib/iris/tests/results/analysis/proportion_foo_2d_masked.cml @@ -1,15 +1,15 @@ - + - + + [30, 45]]" id="b0d35dcf" long_name="foo" points="[-7.5, 7.5, 22.5, 37.5]" shape="(4,)" units="Unit('1')" value_type="float64"/> @@ -17,6 +17,6 @@ - + diff --git a/lib/iris/tests/results/analysis/proportion_foo_bar_2d.cml b/lib/iris/tests/results/analysis/proportion_foo_bar_2d.cml index 2025223be9..77123dd86e 100644 --- a/lib/iris/tests/results/analysis/proportion_foo_bar_2d.cml +++ b/lib/iris/tests/results/analysis/proportion_foo_bar_2d.cml @@ -1,12 +1,12 @@ - + - + - + @@ -15,6 +15,6 @@ - + diff --git a/lib/iris/tests/results/analysis/regrid/linear_both_circular.cml b/lib/iris/tests/results/analysis/regrid/linear_both_circular.cml new file mode 100644 index 0000000000..576ab4ace6 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_both_circular.cml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/linear_both_circular.data.0.json b/lib/iris/tests/results/analysis/regrid/linear_both_circular.data.0.json new file mode 100644 index 0000000000..9a7f53d9b4 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_both_circular.data.0.json @@ -0,0 +1 @@ +{"std": 2.5880997180938721, "min": 254.64399719238281, "max": 261.7274169921875, "shape": [4, 4], "masked": false, "mean": 258.11480712890625} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/linear_circular_grid.cml b/lib/iris/tests/results/analysis/regrid/linear_circular_grid.cml new file mode 100644 index 0000000000..d8fd78a749 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_circular_grid.cml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/linear_circular_grid.data.0.json b/lib/iris/tests/results/analysis/regrid/linear_circular_grid.data.0.json new file mode 100644 index 0000000000..1496975251 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_circular_grid.data.0.json @@ -0,0 +1 @@ +{"std": 2.5862049308282899, "min": 254.64399719238281, "max": 261.68328857421875, "shape": [4, 4], "masked": true, "mean": 258.11273193359375} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/linear_circular_src.cml b/lib/iris/tests/results/analysis/regrid/linear_circular_src.cml new file mode 100644 index 0000000000..1032b4fc6e --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_circular_src.cml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/linear_circular_src.data.0.json b/lib/iris/tests/results/analysis/regrid/linear_circular_src.data.0.json new file mode 100644 index 0000000000..9a7f53d9b4 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_circular_src.data.0.json @@ -0,0 +1 @@ +{"std": 2.5880997180938721, "min": 254.64399719238281, "max": 261.7274169921875, "shape": [4, 4], "masked": false, "mean": 258.11480712890625} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/linear_circular_srcmissingmask.cml b/lib/iris/tests/results/analysis/regrid/linear_circular_srcmissingmask.cml new file mode 100644 index 0000000000..1032b4fc6e --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_circular_srcmissingmask.cml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/linear_circular_srcmissingmask.data.0.json b/lib/iris/tests/results/analysis/regrid/linear_circular_srcmissingmask.data.0.json new file mode 100644 index 0000000000..ae92ce9d13 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_circular_srcmissingmask.data.0.json @@ -0,0 +1 @@ +{"std": 2.588099748331198, "min": 254.64399719238281, "max": 261.7274169921875, "shape": [4, 4], "masked": false, "mean": 258.11480712890625} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/linear_masked_altitude.cml b/lib/iris/tests/results/analysis/regrid/linear_masked_altitude.cml new file mode 100644 index 0000000000..dc1fee2f2b --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_masked_altitude.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/linear_masked_altitude.data.0.json b/lib/iris/tests/results/analysis/regrid/linear_masked_altitude.data.0.json new file mode 100644 index 0000000000..36714edf9c --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_masked_altitude.data.0.json @@ -0,0 +1 @@ +{"std": 0.33354389667510986, "min": 286.5152587890625, "max": 288.0738525390625, "shape": [5, 2, 4, 5], "masked": false, "mean": 287.3565673828125} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/linear_non_circular.cml b/lib/iris/tests/results/analysis/regrid/linear_non_circular.cml new file mode 100644 index 0000000000..064409dde5 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_non_circular.cml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/linear_non_circular.data.0.json b/lib/iris/tests/results/analysis/regrid/linear_non_circular.data.0.json new file mode 100644 index 0000000000..1496975251 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_non_circular.data.0.json @@ -0,0 +1 @@ +{"std": 2.5862049308282899, "min": 254.64399719238281, "max": 261.68328857421875, "shape": [4, 4], "masked": true, "mean": 258.11273193359375} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/linear_partial_overlap.cml b/lib/iris/tests/results/analysis/regrid/linear_partial_overlap.cml new file mode 100644 index 0000000000..6fdbe7df00 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_partial_overlap.cml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/linear_partial_overlap.data.0.json b/lib/iris/tests/results/analysis/regrid/linear_partial_overlap.data.0.json new file mode 100644 index 0000000000..19bcce33e2 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_partial_overlap.data.0.json @@ -0,0 +1 @@ +{"std": 0.33802566423192859, "min": 286.60049438476562, "max": 287.97402954101562, "shape": [5, 2, 4, 4], "masked": true, "mean": 287.31777343750002} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/linear_subset.cml b/lib/iris/tests/results/analysis/regrid/linear_subset.cml new file mode 100644 index 0000000000..d9b80dd86b --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_subset.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/linear_subset.data.0.json b/lib/iris/tests/results/analysis/regrid/linear_subset.data.0.json new file mode 100644 index 0000000000..36714edf9c --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_subset.data.0.json @@ -0,0 +1 @@ +{"std": 0.33354389667510986, "min": 286.5152587890625, "max": 288.0738525390625, "shape": [5, 2, 4, 5], "masked": false, "mean": 287.3565673828125} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/linear_subset_anon.cml b/lib/iris/tests/results/analysis/regrid/linear_subset_anon.cml new file mode 100644 index 0000000000..1945b03a1a --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_subset_anon.cml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/linear_subset_anon.data.0.json b/lib/iris/tests/results/analysis/regrid/linear_subset_anon.data.0.json new file mode 100644 index 0000000000..36714edf9c --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_subset_anon.data.0.json @@ -0,0 +1 @@ +{"std": 0.33354389667510986, "min": 286.5152587890625, "max": 288.0738525390625, "shape": [5, 2, 4, 5], "masked": false, "mean": 287.3565673828125} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/linear_subset_masked_1.cml b/lib/iris/tests/results/analysis/regrid/linear_subset_masked_1.cml new file mode 100644 index 0000000000..d9b80dd86b --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_subset_masked_1.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/linear_subset_masked_1.data.0.json b/lib/iris/tests/results/analysis/regrid/linear_subset_masked_1.data.0.json new file mode 100644 index 0000000000..f74b89b3ec --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_subset_masked_1.data.0.json @@ -0,0 +1 @@ +{"std": 0.32071127247937192, "min": 286.5152587890625, "max": 287.922607421875, "shape": [5, 2, 4, 5], "masked": true, "mean": 287.31103515625} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/linear_subset_masked_2.cml b/lib/iris/tests/results/analysis/regrid/linear_subset_masked_2.cml new file mode 100644 index 0000000000..d9b80dd86b --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_subset_masked_2.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/linear_subset_masked_2.data.0.json b/lib/iris/tests/results/analysis/regrid/linear_subset_masked_2.data.0.json new file mode 100644 index 0000000000..9202c611db --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/linear_subset_masked_2.data.0.json @@ -0,0 +1 @@ +{"std": 0.30926843652344405, "min": 286.81167602539062, "max": 288.0738525390625, "shape": [5, 2, 4, 5], "masked": true, "mean": 287.44599609375001} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/nearest_both_circular.cml b/lib/iris/tests/results/analysis/regrid/nearest_both_circular.cml new file mode 100644 index 0000000000..d8f1a9d0f6 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_both_circular.cml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/nearest_both_circular.data.0.json b/lib/iris/tests/results/analysis/regrid/nearest_both_circular.data.0.json new file mode 100644 index 0000000000..484b8b268c --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_both_circular.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 254.64399719238281, "max": 254.64399719238281, "shape": [4, 4], "masked": false, "mean": 254.64399719238281} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/nearest_circular_grid.cml b/lib/iris/tests/results/analysis/regrid/nearest_circular_grid.cml new file mode 100644 index 0000000000..16863839a1 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_circular_grid.cml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/nearest_circular_grid.data.0.json b/lib/iris/tests/results/analysis/regrid/nearest_circular_grid.data.0.json new file mode 100644 index 0000000000..dfccef151d --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_circular_grid.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 254.64399719238281, "max": 254.64399719238281, "shape": [4, 4], "masked": true, "mean": 254.64399719238281} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/nearest_circular_src.cml b/lib/iris/tests/results/analysis/regrid/nearest_circular_src.cml new file mode 100644 index 0000000000..5eb032cf2c --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_circular_src.cml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/nearest_circular_src.data.0.json b/lib/iris/tests/results/analysis/regrid/nearest_circular_src.data.0.json new file mode 100644 index 0000000000..484b8b268c --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_circular_src.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 254.64399719238281, "max": 254.64399719238281, "shape": [4, 4], "masked": false, "mean": 254.64399719238281} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/nearest_circular_srcmissingmask.cml b/lib/iris/tests/results/analysis/regrid/nearest_circular_srcmissingmask.cml new file mode 100644 index 0000000000..5eb032cf2c --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_circular_srcmissingmask.cml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/nearest_circular_srcmissingmask.data.0.json b/lib/iris/tests/results/analysis/regrid/nearest_circular_srcmissingmask.data.0.json new file mode 100644 index 0000000000..484b8b268c --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_circular_srcmissingmask.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 254.64399719238281, "max": 254.64399719238281, "shape": [4, 4], "masked": false, "mean": 254.64399719238281} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/nearest_masked_altitude.cml b/lib/iris/tests/results/analysis/regrid/nearest_masked_altitude.cml new file mode 100644 index 0000000000..b2aec5e891 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_masked_altitude.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/nearest_masked_altitude.data.0.json b/lib/iris/tests/results/analysis/regrid/nearest_masked_altitude.data.0.json new file mode 100644 index 0000000000..32fef225f0 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_masked_altitude.data.0.json @@ -0,0 +1 @@ +{"std": 0.33481752872467041, "min": 286.47329711914062, "max": 288.09292602539062, "shape": [5, 2, 4, 5], "masked": false, "mean": 287.353515625} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/nearest_non_circular.cml b/lib/iris/tests/results/analysis/regrid/nearest_non_circular.cml new file mode 100644 index 0000000000..da162648be --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_non_circular.cml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/nearest_non_circular.data.0.json b/lib/iris/tests/results/analysis/regrid/nearest_non_circular.data.0.json new file mode 100644 index 0000000000..dfccef151d --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_non_circular.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 254.64399719238281, "max": 254.64399719238281, "shape": [4, 4], "masked": true, "mean": 254.64399719238281} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/nearest_partial_overlap.cml b/lib/iris/tests/results/analysis/regrid/nearest_partial_overlap.cml new file mode 100644 index 0000000000..f6647aa426 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_partial_overlap.cml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/nearest_partial_overlap.data.0.json b/lib/iris/tests/results/analysis/regrid/nearest_partial_overlap.data.0.json new file mode 100644 index 0000000000..fd10f58692 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_partial_overlap.data.0.json @@ -0,0 +1 @@ +{"std": 0.34504886689951209, "min": 286.47329711914062, "max": 288.02426147460938, "shape": [5, 2, 4, 4], "masked": true, "mean": 287.30825195312502} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/nearest_subset.cml b/lib/iris/tests/results/analysis/regrid/nearest_subset.cml new file mode 100644 index 0000000000..7e12c9be60 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_subset.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/nearest_subset.data.0.json b/lib/iris/tests/results/analysis/regrid/nearest_subset.data.0.json new file mode 100644 index 0000000000..32fef225f0 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_subset.data.0.json @@ -0,0 +1 @@ +{"std": 0.33481752872467041, "min": 286.47329711914062, "max": 288.09292602539062, "shape": [5, 2, 4, 5], "masked": false, "mean": 287.353515625} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/nearest_subset_anon.cml b/lib/iris/tests/results/analysis/regrid/nearest_subset_anon.cml new file mode 100644 index 0000000000..40390f387c --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_subset_anon.cml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/nearest_subset_anon.data.0.json b/lib/iris/tests/results/analysis/regrid/nearest_subset_anon.data.0.json new file mode 100644 index 0000000000..32fef225f0 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_subset_anon.data.0.json @@ -0,0 +1 @@ +{"std": 0.33481752872467041, "min": 286.47329711914062, "max": 288.09292602539062, "shape": [5, 2, 4, 5], "masked": false, "mean": 287.353515625} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/nearest_subset_masked_1.cml b/lib/iris/tests/results/analysis/regrid/nearest_subset_masked_1.cml new file mode 100644 index 0000000000..7e12c9be60 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_subset_masked_1.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/nearest_subset_masked_1.data.0.json b/lib/iris/tests/results/analysis/regrid/nearest_subset_masked_1.data.0.json new file mode 100644 index 0000000000..c45dbec59e --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_subset_masked_1.data.0.json @@ -0,0 +1 @@ +{"std": 0.32882911282299754, "min": 286.47329711914062, "max": 288.02426147460938, "shape": [5, 2, 4, 5], "masked": true, "mean": 287.33749999999998} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/nearest_subset_masked_2.cml b/lib/iris/tests/results/analysis/regrid/nearest_subset_masked_2.cml new file mode 100644 index 0000000000..7e12c9be60 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_subset_masked_2.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/nearest_subset_masked_2.data.0.json b/lib/iris/tests/results/analysis/regrid/nearest_subset_masked_2.data.0.json new file mode 100644 index 0000000000..e9b376cdd4 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/nearest_subset_masked_2.data.0.json @@ -0,0 +1 @@ +{"std": 0.3384940347877971, "min": 286.47329711914062, "max": 288.09292602539062, "shape": [5, 2, 4, 5], "masked": true, "mean": 287.3533935546875} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/regrid/no_overlap.cml b/lib/iris/tests/results/analysis/regrid/no_overlap.cml new file mode 100644 index 0000000000..6aa4d218f8 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/no_overlap.cml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/regrid/no_overlap.data.0.json b/lib/iris/tests/results/analysis/regrid/no_overlap.data.0.json new file mode 100644 index 0000000000..addd0b83c8 --- /dev/null +++ b/lib/iris/tests/results/analysis/regrid/no_overlap.data.0.json @@ -0,0 +1 @@ +{"std": NaN, "min": NaN, "max": NaN, "shape": [5, 2, 4, 4], "masked": true, "mean": NaN} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/rms_latitude.cml b/lib/iris/tests/results/analysis/rms_latitude.cml index 293c305957..e409daed2d 100644 --- a/lib/iris/tests/results/analysis/rms_latitude.cml +++ b/lib/iris/tests/results/analysis/rms_latitude.cml @@ -1,32 +1,31 @@ - + - + + - + - + - + - - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/rms_latitude.data.0.json b/lib/iris/tests/results/analysis/rms_latitude.data.0.json new file mode 100644 index 0000000000..ccf6ad33f9 --- /dev/null +++ b/lib/iris/tests/results/analysis/rms_latitude.data.0.json @@ -0,0 +1 @@ +{"std": 304.4558865010406, "min": 100892.27635006171, "max": 101991.30432025448, "shape": [10, 720], "masked": false, "mean": 101448.55325547748} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/rms_latitude.data.0.npy b/lib/iris/tests/results/analysis/rms_latitude.data.0.npy deleted file mode 100644 index 3c9dc955d9..0000000000 Binary files a/lib/iris/tests/results/analysis/rms_latitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/rms_latitude_longitude.cml b/lib/iris/tests/results/analysis/rms_latitude_longitude.cml index d38777f26c..9bdc53fbad 100644 --- a/lib/iris/tests/results/analysis/rms_latitude_longitude.cml +++ b/lib/iris/tests/results/analysis/rms_latitude_longitude.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -38,6 +37,6 @@ - + diff --git a/lib/iris/tests/results/analysis/rms_latitude_longitude.data.0.json b/lib/iris/tests/results/analysis/rms_latitude_longitude.data.0.json new file mode 100644 index 0000000000..e52a5c046a --- /dev/null +++ b/lib/iris/tests/results/analysis/rms_latitude_longitude.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 101449.01010367858, "max": 101449.01010367858, "shape": [10], "masked": false, "mean": 101449.01010367858} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/rms_latitude_longitude.data.0.npy b/lib/iris/tests/results/analysis/rms_latitude_longitude.data.0.npy deleted file mode 100644 index 6ee521e928..0000000000 Binary files a/lib/iris/tests/results/analysis/rms_latitude_longitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/rms_latitude_longitude_1call.cml b/lib/iris/tests/results/analysis/rms_latitude_longitude_1call.cml index 9f1cc32d23..89a593d122 100644 --- a/lib/iris/tests/results/analysis/rms_latitude_longitude_1call.cml +++ b/lib/iris/tests/results/analysis/rms_latitude_longitude_1call.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/rms_latitude_longitude_1call.data.0.json b/lib/iris/tests/results/analysis/rms_latitude_longitude_1call.data.0.json new file mode 100644 index 0000000000..e52a5c046a --- /dev/null +++ b/lib/iris/tests/results/analysis/rms_latitude_longitude_1call.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 101449.01010367858, "max": 101449.01010367858, "shape": [10], "masked": false, "mean": 101449.01010367858} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/rms_latitude_longitude_1call.data.0.npy b/lib/iris/tests/results/analysis/rms_latitude_longitude_1call.data.0.npy deleted file mode 100644 index 3495d9d96b..0000000000 Binary files a/lib/iris/tests/results/analysis/rms_latitude_longitude_1call.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/rms_weighted_2d.cml b/lib/iris/tests/results/analysis/rms_weighted_2d.cml index 9109d40239..433e27d359 100644 --- a/lib/iris/tests/results/analysis/rms_weighted_2d.cml +++ b/lib/iris/tests/results/analysis/rms_weighted_2d.cml @@ -1,14 +1,14 @@ - + + [10, 15]]" id="434cbbd8" long_name="bar" points="[2.5, 7.5, 12.5]" shape="(3,)" units="Unit('1')" value_type="float64"/> - + @@ -16,6 +16,6 @@ - + diff --git a/lib/iris/tests/results/analysis/rolling_window/simple_latitude.cml b/lib/iris/tests/results/analysis/rolling_window/simple_latitude.cml index 652ca33787..ff64076f83 100644 --- a/lib/iris/tests/results/analysis/rolling_window/simple_latitude.cml +++ b/lib/iris/tests/results/analysis/rolling_window/simple_latitude.cml @@ -1,13 +1,13 @@ - + + [5.0, 10.0]]" id="4a0cb9d8" points="[2.5, 7.5]" shape="(2,)" standard_name="latitude" units="Unit('degrees')" value_type="float64"/> - + @@ -15,6 +15,6 @@ - + diff --git a/lib/iris/tests/results/analysis/rolling_window/simple_longitude.cml b/lib/iris/tests/results/analysis/rolling_window/simple_longitude.cml index a4decf62a2..b2c422057e 100644 --- a/lib/iris/tests/results/analysis/rolling_window/simple_longitude.cml +++ b/lib/iris/tests/results/analysis/rolling_window/simple_longitude.cml @@ -1,14 +1,14 @@ - + - + + [4.0, 6.0]]" id="62e940e0" points="[1.0, 3.0, 5.0]" shape="(3,)" standard_name="longitude" units="Unit('degrees')" value_type="float64"/> @@ -16,6 +16,6 @@ - + diff --git a/lib/iris/tests/results/analysis/rolling_window/size_4_longitude.cml b/lib/iris/tests/results/analysis/rolling_window/size_4_longitude.cml index dba3cd5297..0e4330ce82 100644 --- a/lib/iris/tests/results/analysis/rolling_window/size_4_longitude.cml +++ b/lib/iris/tests/results/analysis/rolling_window/size_4_longitude.cml @@ -1,12 +1,12 @@ - + - + - + @@ -14,6 +14,6 @@ - + diff --git a/lib/iris/tests/results/analysis/rotated_pole.0.rlat.json b/lib/iris/tests/results/analysis/rotated_pole.0.rlat.json new file mode 100644 index 0000000000..272cbd9c7a --- /dev/null +++ b/lib/iris/tests/results/analysis/rotated_pole.0.rlat.json @@ -0,0 +1 @@ +{"std": 3.7195863723754883, "min": -5.5932002067565918, "max": 8.7213001251220703, "shape": [93, 75], "masked": false, "mean": 1.6348202228546143} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/rotated_pole.0.rlon.json b/lib/iris/tests/results/analysis/rotated_pole.0.rlon.json new file mode 100644 index 0000000000..cd1fe2fd52 --- /dev/null +++ b/lib/iris/tests/results/analysis/rotated_pole.0.rlon.json @@ -0,0 +1 @@ +{"std": 3.05635954577972, "min": 353.052490234375, "max": 365.08099365234375, "shape": [93, 75], "masked": false, "mean": 359.0960595703125} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/rotated_pole.0.x.json b/lib/iris/tests/results/analysis/rotated_pole.0.x.json new file mode 100644 index 0000000000..7f09ca434f --- /dev/null +++ b/lib/iris/tests/results/analysis/rotated_pole.0.x.json @@ -0,0 +1 @@ +{"std": 5.256882991869942, "min": -16.571169372070806, "max": 7.855481068868564, "shape": [93, 75], "masked": false, "mean": -4.045853791096988} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/rotated_pole.0.y.json b/lib/iris/tests/results/analysis/rotated_pole.0.y.json new file mode 100644 index 0000000000..9f1fcef264 --- /dev/null +++ b/lib/iris/tests/results/analysis/rotated_pole.0.y.json @@ -0,0 +1 @@ +{"std": 3.711246685838892, "min": 46.42276494752364, "max": 61.22127069532664, "shape": [93, 75], "masked": false, "mean": 54.01432122690471} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/rotated_pole.1.rlat.json b/lib/iris/tests/results/analysis/rotated_pole.1.rlat.json new file mode 100644 index 0000000000..612cb85e9a --- /dev/null +++ b/lib/iris/tests/results/analysis/rotated_pole.1.rlat.json @@ -0,0 +1 @@ +{"std": 0.10904959181607428, "min": -1.732200026512146, "max": -1.3676999807357788, "shape": [28, 26], "masked": false, "mean": -1.5499499993664878} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/rotated_pole.1.rlon.json b/lib/iris/tests/results/analysis/rotated_pole.1.rlon.json new file mode 100644 index 0000000000..18923a67f6 --- /dev/null +++ b/lib/iris/tests/results/analysis/rotated_pole.1.rlon.json @@ -0,0 +1 @@ +{"std": 0.10125036032780034, "min": 359.8294982910156, "max": 360.1669921875, "shape": [28, 26], "masked": false, "mean": 359.99824993426984} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/rotated_pole.1.x.json b/lib/iris/tests/results/analysis/rotated_pole.1.x.json new file mode 100644 index 0000000000..c4fe081a1e --- /dev/null +++ b/lib/iris/tests/results/analysis/rotated_pole.1.x.json @@ -0,0 +1 @@ +{"std": 0.16065754648082262, "min": -2.7716267023533385, "max": -2.233964274513027, "shape": [28, 26], "masked": false, "mean": -2.5027768780735946} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/rotated_pole.1.y.json b/lib/iris/tests/results/analysis/rotated_pole.1.y.json new file mode 100644 index 0000000000..501fe5e3a5 --- /dev/null +++ b/lib/iris/tests/results/analysis/rotated_pole.1.y.json @@ -0,0 +1 @@ +{"std": 0.10904936809954589, "min": 50.767481894563936, "max": 51.13229974298538, "shape": [28, 26], "masked": false, "mean": 50.94993734826177} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/sqrt.cml b/lib/iris/tests/results/analysis/sqrt.cml index d7fa8b37fd..3a7bff138c 100644 --- a/lib/iris/tests/results/analysis/sqrt.cml +++ b/lib/iris/tests/results/analysis/sqrt.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/std_dev_latitude.cml b/lib/iris/tests/results/analysis/std_dev_latitude.cml index fad32178fd..154d5ef587 100644 --- a/lib/iris/tests/results/analysis/std_dev_latitude.cml +++ b/lib/iris/tests/results/analysis/std_dev_latitude.cml @@ -1,32 +1,31 @@ - + - + + - + - + - + - - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/std_dev_latitude.data.0.json b/lib/iris/tests/results/analysis/std_dev_latitude.data.0.json new file mode 100644 index 0000000000..429ea4dfea --- /dev/null +++ b/lib/iris/tests/results/analysis/std_dev_latitude.data.0.json @@ -0,0 +1 @@ +{"std": 275.39299405545052, "min": 376.13037125253311, "max": 1345.9708206598209, "shape": [10, 720], "masked": false, "mean": 794.39235307916192} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/std_dev_latitude.data.0.npy b/lib/iris/tests/results/analysis/std_dev_latitude.data.0.npy deleted file mode 100644 index 8246d19271..0000000000 Binary files a/lib/iris/tests/results/analysis/std_dev_latitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/std_dev_latitude_longitude.cml b/lib/iris/tests/results/analysis/std_dev_latitude_longitude.cml index 5a3d5a4e15..770ef9a35a 100644 --- a/lib/iris/tests/results/analysis/std_dev_latitude_longitude.cml +++ b/lib/iris/tests/results/analysis/std_dev_latitude_longitude.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -38,6 +37,6 @@ - + diff --git a/lib/iris/tests/results/analysis/std_dev_latitude_longitude.data.0.json b/lib/iris/tests/results/analysis/std_dev_latitude_longitude.data.0.json new file mode 100644 index 0000000000..cac908a787 --- /dev/null +++ b/lib/iris/tests/results/analysis/std_dev_latitude_longitude.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 275.5844386347452, "max": 275.5844386347452, "shape": [10], "masked": false, "mean": 275.5844386347452} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/std_dev_latitude_longitude.data.0.npy b/lib/iris/tests/results/analysis/std_dev_latitude_longitude.data.0.npy deleted file mode 100644 index 3b20329695..0000000000 Binary files a/lib/iris/tests/results/analysis/std_dev_latitude_longitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/std_dev_latitude_longitude_1call.cml b/lib/iris/tests/results/analysis/std_dev_latitude_longitude_1call.cml index 0e517a3c48..a5ce049ca5 100644 --- a/lib/iris/tests/results/analysis/std_dev_latitude_longitude_1call.cml +++ b/lib/iris/tests/results/analysis/std_dev_latitude_longitude_1call.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/std_dev_latitude_longitude_1call.data.0.json b/lib/iris/tests/results/analysis/std_dev_latitude_longitude_1call.data.0.json new file mode 100644 index 0000000000..20844c6e6d --- /dev/null +++ b/lib/iris/tests/results/analysis/std_dev_latitude_longitude_1call.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 893.70134844777931, "max": 893.70134844777931, "shape": [10], "masked": false, "mean": 893.70134844777931} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/std_dev_latitude_longitude_1call.data.0.npy b/lib/iris/tests/results/analysis/std_dev_latitude_longitude_1call.data.0.npy deleted file mode 100644 index 0fa3864bf7..0000000000 Binary files a/lib/iris/tests/results/analysis/std_dev_latitude_longitude_1call.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/subtract.cml b/lib/iris/tests/results/analysis/subtract.cml index 11289dc00b..7b0740888d 100644 --- a/lib/iris/tests/results/analysis/subtract.cml +++ b/lib/iris/tests/results/analysis/subtract.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/subtract_array.cml b/lib/iris/tests/results/analysis/subtract_array.cml index eed5cb30b9..cb77adde99 100644 --- a/lib/iris/tests/results/analysis/subtract_array.cml +++ b/lib/iris/tests/results/analysis/subtract_array.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/subtract_coord_x.cml b/lib/iris/tests/results/analysis/subtract_coord_x.cml index 046f7b650b..c7aee8395b 100644 --- a/lib/iris/tests/results/analysis/subtract_coord_x.cml +++ b/lib/iris/tests/results/analysis/subtract_coord_x.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/subtract_coord_y.cml b/lib/iris/tests/results/analysis/subtract_coord_y.cml index b35f0d28c1..355692b27b 100644 --- a/lib/iris/tests/results/analysis/subtract_coord_y.cml +++ b/lib/iris/tests/results/analysis/subtract_coord_y.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/subtract_scalar.cml b/lib/iris/tests/results/analysis/subtract_scalar.cml index b7e65e5edb..ab8e9d0d60 100644 --- a/lib/iris/tests/results/analysis/subtract_scalar.cml +++ b/lib/iris/tests/results/analysis/subtract_scalar.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/sum_latitude.cml b/lib/iris/tests/results/analysis/sum_latitude.cml index 28e2f7f9b2..943aa9312f 100644 --- a/lib/iris/tests/results/analysis/sum_latitude.cml +++ b/lib/iris/tests/results/analysis/sum_latitude.cml @@ -1,32 +1,31 @@ - + - + + - + - + - + - - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/sum_latitude.data.0.json b/lib/iris/tests/results/analysis/sum_latitude.data.0.json new file mode 100644 index 0000000000..e6dfa6bee7 --- /dev/null +++ b/lib/iris/tests/results/analysis/sum_latitude.data.0.json @@ -0,0 +1 @@ +{"std": 132050.29888502066, "min": 43582468.0, "max": 44059711.0, "shape": [10, 720], "masked": false, "mean": 43824271.781944446} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/sum_latitude.data.0.npy b/lib/iris/tests/results/analysis/sum_latitude.data.0.npy deleted file mode 100644 index 4b74a4f3ca..0000000000 Binary files a/lib/iris/tests/results/analysis/sum_latitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/sum_latitude_longitude.cml b/lib/iris/tests/results/analysis/sum_latitude_longitude.cml index 03f15ea780..2eff41339b 100644 --- a/lib/iris/tests/results/analysis/sum_latitude_longitude.cml +++ b/lib/iris/tests/results/analysis/sum_latitude_longitude.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -38,6 +37,6 @@ - + diff --git a/lib/iris/tests/results/analysis/sum_latitude_longitude.data.0.json b/lib/iris/tests/results/analysis/sum_latitude_longitude.data.0.json new file mode 100644 index 0000000000..7209db3059 --- /dev/null +++ b/lib/iris/tests/results/analysis/sum_latitude_longitude.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 31553475683.0, "max": 31553475683.0, "shape": [10], "masked": false, "mean": 31553475683.0} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/sum_latitude_longitude.data.0.npy b/lib/iris/tests/results/analysis/sum_latitude_longitude.data.0.npy deleted file mode 100644 index 9a08dab1f8..0000000000 Binary files a/lib/iris/tests/results/analysis/sum_latitude_longitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/sum_latitude_longitude_1call.cml b/lib/iris/tests/results/analysis/sum_latitude_longitude_1call.cml index 67c7fd39d3..a2a46d2ba8 100644 --- a/lib/iris/tests/results/analysis/sum_latitude_longitude_1call.cml +++ b/lib/iris/tests/results/analysis/sum_latitude_longitude_1call.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/sum_latitude_longitude_1call.data.0.json b/lib/iris/tests/results/analysis/sum_latitude_longitude_1call.data.0.json new file mode 100644 index 0000000000..7209db3059 --- /dev/null +++ b/lib/iris/tests/results/analysis/sum_latitude_longitude_1call.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 31553475683.0, "max": 31553475683.0, "shape": [10], "masked": false, "mean": 31553475683.0} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/sum_latitude_longitude_1call.data.0.npy b/lib/iris/tests/results/analysis/sum_latitude_longitude_1call.data.0.npy deleted file mode 100644 index 9a08dab1f8..0000000000 Binary files a/lib/iris/tests/results/analysis/sum_latitude_longitude_1call.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/sum_weighted_1d.cml b/lib/iris/tests/results/analysis/sum_weighted_1d.cml index a225d32655..09958e4eb0 100644 --- a/lib/iris/tests/results/analysis/sum_weighted_1d.cml +++ b/lib/iris/tests/results/analysis/sum_weighted_1d.cml @@ -1,9 +1,9 @@ - + - + @@ -11,6 +11,6 @@ - + diff --git a/lib/iris/tests/results/analysis/sum_weighted_2d.cml b/lib/iris/tests/results/analysis/sum_weighted_2d.cml index ff44b16e60..57cf7d3d1f 100644 --- a/lib/iris/tests/results/analysis/sum_weighted_2d.cml +++ b/lib/iris/tests/results/analysis/sum_weighted_2d.cml @@ -1,15 +1,15 @@ - + - + + [30, 45]]" id="b0d35dcf" long_name="foo" points="[-7.5, 7.5, 22.5, 37.5]" shape="(4,)" units="Unit('1')" value_type="float64"/> @@ -17,6 +17,6 @@ - + diff --git a/lib/iris/tests/results/analysis/third_quartile_foo_1d.cml b/lib/iris/tests/results/analysis/third_quartile_foo_1d.cml index 61ff839996..b14c51cfb3 100644 --- a/lib/iris/tests/results/analysis/third_quartile_foo_1d.cml +++ b/lib/iris/tests/results/analysis/third_quartile_foo_1d.cml @@ -1,16 +1,15 @@ - + - + + + + - - - - - - + + diff --git a/lib/iris/tests/results/analysis/third_quartile_foo_1d_fast_percentile.cml b/lib/iris/tests/results/analysis/third_quartile_foo_1d_fast_percentile.cml new file mode 100644 index 0000000000..b14c51cfb3 --- /dev/null +++ b/lib/iris/tests/results/analysis/third_quartile_foo_1d_fast_percentile.cml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/analysis/variance_latitude.cml b/lib/iris/tests/results/analysis/variance_latitude.cml index 70999d9f9c..437587b00d 100644 --- a/lib/iris/tests/results/analysis/variance_latitude.cml +++ b/lib/iris/tests/results/analysis/variance_latitude.cml @@ -1,32 +1,31 @@ - + - + + - + - + - + - - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/variance_latitude.data.0.json b/lib/iris/tests/results/analysis/variance_latitude.data.0.json new file mode 100644 index 0000000000..a2a3f796fc --- /dev/null +++ b/lib/iris/tests/results/analysis/variance_latitude.data.0.json @@ -0,0 +1 @@ +{"std": 463000.43254353397, "min": 141474.0561785684, "max": 1811637.4500676715, "shape": [10, 720], "masked": false, "mean": 706900.51180547348} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/variance_latitude.data.0.npy b/lib/iris/tests/results/analysis/variance_latitude.data.0.npy deleted file mode 100644 index 2d55210df0..0000000000 Binary files a/lib/iris/tests/results/analysis/variance_latitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/variance_latitude_longitude.cml b/lib/iris/tests/results/analysis/variance_latitude_longitude.cml index eb5a7ed144..391ab8834e 100644 --- a/lib/iris/tests/results/analysis/variance_latitude_longitude.cml +++ b/lib/iris/tests/results/analysis/variance_latitude_longitude.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -38,6 +37,6 @@ - + diff --git a/lib/iris/tests/results/analysis/variance_latitude_longitude.data.0.json b/lib/iris/tests/results/analysis/variance_latitude_longitude.data.0.json new file mode 100644 index 0000000000..176e8d427e --- /dev/null +++ b/lib/iris/tests/results/analysis/variance_latitude_longitude.data.0.json @@ -0,0 +1 @@ +{"std": 3.0517578125e-05, "min": 214667549910.37509, "max": 214667549910.37509, "shape": [10], "masked": false, "mean": 214667549910.37506} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/variance_latitude_longitude.data.0.npy b/lib/iris/tests/results/analysis/variance_latitude_longitude.data.0.npy deleted file mode 100644 index 4a9f2caff2..0000000000 Binary files a/lib/iris/tests/results/analysis/variance_latitude_longitude.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/variance_latitude_longitude_1call.cml b/lib/iris/tests/results/analysis/variance_latitude_longitude_1call.cml index 8d894589a5..535468acfc 100644 --- a/lib/iris/tests/results/analysis/variance_latitude_longitude_1call.cml +++ b/lib/iris/tests/results/analysis/variance_latitude_longitude_1call.cml @@ -1,31 +1,30 @@ - + - + + - + - + - + - + - @@ -36,6 +35,6 @@ - + diff --git a/lib/iris/tests/results/analysis/variance_latitude_longitude_1call.data.0.json b/lib/iris/tests/results/analysis/variance_latitude_longitude_1call.data.0.json new file mode 100644 index 0000000000..912e415819 --- /dev/null +++ b/lib/iris/tests/results/analysis/variance_latitude_longitude_1call.data.0.json @@ -0,0 +1 @@ +{"std": 1.1641532182693481e-10, "min": 798702.10021737905, "max": 798702.10021737905, "shape": [10], "masked": false, "mean": 798702.10021737893} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/variance_latitude_longitude_1call.data.0.npy b/lib/iris/tests/results/analysis/variance_latitude_longitude_1call.data.0.npy deleted file mode 100644 index b115cf6f1a..0000000000 Binary files a/lib/iris/tests/results/analysis/variance_latitude_longitude_1call.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/weighted_mean_lat.cml b/lib/iris/tests/results/analysis/weighted_mean_lat.cml index 868d54b886..d2bb6f0df4 100644 --- a/lib/iris/tests/results/analysis/weighted_mean_lat.cml +++ b/lib/iris/tests/results/analysis/weighted_mean_lat.cml @@ -1,17 +1,17 @@ - + - + - + - + @@ -21,6 +21,6 @@ - + diff --git a/lib/iris/tests/results/analysis/weighted_mean_lat.data.0.json b/lib/iris/tests/results/analysis/weighted_mean_lat.data.0.json new file mode 100644 index 0000000000..64501d6710 --- /dev/null +++ b/lib/iris/tests/results/analysis/weighted_mean_lat.data.0.json @@ -0,0 +1 @@ +{"std": 0.61282587616379602, "min": 3.0, "max": 4.5, "shape": [3], "masked": false, "mean": 3.7666667302449546} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/weighted_mean_lat.data.0.npy b/lib/iris/tests/results/analysis/weighted_mean_lat.data.0.npy deleted file mode 100644 index e756186220..0000000000 Binary files a/lib/iris/tests/results/analysis/weighted_mean_lat.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/weighted_mean_latlon.cml b/lib/iris/tests/results/analysis/weighted_mean_latlon.cml index 552d03a24b..e25e74c021 100644 --- a/lib/iris/tests/results/analysis/weighted_mean_latlon.cml +++ b/lib/iris/tests/results/analysis/weighted_mean_latlon.cml @@ -1,17 +1,17 @@ - + - + - + - + @@ -22,6 +22,6 @@ - + diff --git a/lib/iris/tests/results/analysis/weighted_mean_latlon.data.0.json b/lib/iris/tests/results/analysis/weighted_mean_latlon.data.0.json new file mode 100644 index 0000000000..5bbe261527 --- /dev/null +++ b/lib/iris/tests/results/analysis/weighted_mean_latlon.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 3.6666667461395264, "max": 3.6666667461395264, "shape": [], "masked": false, "mean": 3.6666667461395264} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/weighted_mean_latlon.data.0.npy b/lib/iris/tests/results/analysis/weighted_mean_latlon.data.0.npy deleted file mode 100644 index b9a095a7ec..0000000000 Binary files a/lib/iris/tests/results/analysis/weighted_mean_latlon.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/weighted_mean_lon.cml b/lib/iris/tests/results/analysis/weighted_mean_lon.cml index 4d36daa092..6ce89976b6 100644 --- a/lib/iris/tests/results/analysis/weighted_mean_lon.cml +++ b/lib/iris/tests/results/analysis/weighted_mean_lon.cml @@ -1,17 +1,17 @@ - + - + - + - + @@ -21,6 +21,6 @@ - + diff --git a/lib/iris/tests/results/analysis/weighted_mean_lon.data.0.json b/lib/iris/tests/results/analysis/weighted_mean_lon.data.0.json new file mode 100644 index 0000000000..8de8439349 --- /dev/null +++ b/lib/iris/tests/results/analysis/weighted_mean_lon.data.0.json @@ -0,0 +1 @@ +{"std": 2.347693920135498, "min": 1.9166666269302368, "max": 7.6666665077209473, "shape": [3], "masked": false, "mean": 4.8166666030883789} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/weighted_mean_lon.data.0.npy b/lib/iris/tests/results/analysis/weighted_mean_lon.data.0.npy deleted file mode 100644 index 13519b51fe..0000000000 Binary files a/lib/iris/tests/results/analysis/weighted_mean_lon.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/analysis/weighted_mean_original.cml b/lib/iris/tests/results/analysis/weighted_mean_original.cml index 848d989e83..2df84a8606 100644 --- a/lib/iris/tests/results/analysis/weighted_mean_original.cml +++ b/lib/iris/tests/results/analysis/weighted_mean_original.cml @@ -1,19 +1,19 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/analysis/weighted_mean_source.cml b/lib/iris/tests/results/analysis/weighted_mean_source.cml index b1cd04538b..eb72035a4f 100644 --- a/lib/iris/tests/results/analysis/weighted_mean_source.cml +++ b/lib/iris/tests/results/analysis/weighted_mean_source.cml @@ -1,22 +1,22 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/categorisation/customcheck.cml b/lib/iris/tests/results/categorisation/customcheck.cml index 345f5bfcc8..d6dcc7179d 100644 --- a/lib/iris/tests/results/categorisation/customcheck.cml +++ b/lib/iris/tests/results/categorisation/customcheck.cml @@ -1,28 +1,28 @@ - + - - - - - + diff --git a/lib/iris/tests/results/categorisation/quickcheck.cml b/lib/iris/tests/results/categorisation/quickcheck.cml index 68deb35447..f64c70350f 100644 --- a/lib/iris/tests/results/categorisation/quickcheck.cml +++ b/lib/iris/tests/results/categorisation/quickcheck.cml @@ -1,77 +1,77 @@ - + - - - - - - - - - - - - - - - + diff --git a/lib/iris/tests/results/cdm/str_repr/realistic_0d.repr.txt b/lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/0d_repr.txt similarity index 100% rename from lib/iris/tests/results/cdm/str_repr/realistic_0d.repr.txt rename to lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/0d_repr.txt diff --git a/lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/0d_str.txt b/lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/0d_str.txt new file mode 100644 index 0000000000..e79f060898 --- /dev/null +++ b/lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/0d_str.txt @@ -0,0 +1,13 @@ +air_potential_temperature / (K) (scalar cube) + Scalar coordinates: + altitude: 418.69836 m, bound=(413.93686, 426.63434) m + forecast_period: 0.0 hours + grid_latitude: -0.1278 degrees, bound=(-0.12825, -0.12735) degrees + grid_longitude: 359.5796 degrees, bound=(359.57916, 359.58005) degrees + level_height: 5.0 m, bound=(0.0, 13.333332) m + model_level_number: 1 + sigma: 0.9994238, bound=(1.0, 0.99846387) + surface_altitude: 413.93686 m + time: 2009-09-09 17:10:00 + Attributes: + source: Iris test case \ No newline at end of file diff --git a/lib/iris/tests/results/cdm/str_repr/realistic_1d.repr.txt b/lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/1d_repr.txt similarity index 100% rename from lib/iris/tests/results/cdm/str_repr/realistic_1d.repr.txt rename to lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/1d_repr.txt diff --git a/lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/1d_str.txt b/lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/1d_str.txt new file mode 100644 index 0000000000..204df1af1c --- /dev/null +++ b/lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/1d_str.txt @@ -0,0 +1,16 @@ +air_potential_temperature / (K) (grid_longitude: 100) + Dimension coordinates: + grid_longitude x + Auxiliary coordinates: + surface_altitude x + Derived coordinates: + altitude x + Scalar coordinates: + forecast_period: 0.0 hours + grid_latitude: -0.1278 degrees, bound=(-0.12825, -0.12735) degrees + level_height: 5.0 m, bound=(0.0, 13.333332) m + model_level_number: 1 + sigma: 0.9994238, bound=(1.0, 0.99846387) + time: 2009-09-09 17:10:00 + Attributes: + source: Iris test case \ No newline at end of file diff --git a/lib/iris/tests/results/cdm/str_repr/realistic_2d.repr.txt b/lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/2d_repr.txt similarity index 100% rename from lib/iris/tests/results/cdm/str_repr/realistic_2d.repr.txt rename to lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/2d_repr.txt diff --git a/lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/2d_str.txt b/lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/2d_str.txt new file mode 100644 index 0000000000..a440a28e04 --- /dev/null +++ b/lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/2d_str.txt @@ -0,0 +1,16 @@ +air_potential_temperature / (K) (grid_latitude: 100; grid_longitude: 100) + Dimension coordinates: + grid_latitude x - + grid_longitude - x + Auxiliary coordinates: + surface_altitude x x + Derived coordinates: + altitude x x + Scalar coordinates: + forecast_period: 0.0 hours + level_height: 5.0 m, bound=(0.0, 13.333332) m + model_level_number: 1 + sigma: 0.9994238, bound=(1.0, 0.99846387) + time: 2009-09-09 17:10:00 + Attributes: + source: Iris test case \ No newline at end of file diff --git a/lib/iris/tests/results/cdm/str_repr/realistic_3d.repr.txt b/lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/3d_repr.txt similarity index 100% rename from lib/iris/tests/results/cdm/str_repr/realistic_3d.repr.txt rename to lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/3d_repr.txt diff --git a/lib/iris/tests/results/cdm/str_repr/realistic_3d.str.txt b/lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/3d_str.txt similarity index 100% rename from lib/iris/tests/results/cdm/str_repr/realistic_3d.str.txt rename to lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/3d_str.txt diff --git a/lib/iris/tests/results/cdm/str_repr/realistic_4d.repr.txt b/lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/4d_repr.txt similarity index 100% rename from lib/iris/tests/results/cdm/str_repr/realistic_4d.repr.txt rename to lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/4d_repr.txt diff --git a/lib/iris/tests/results/cdm/str_repr/realistic_4d.str.txt b/lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/4d_str.txt similarity index 100% rename from lib/iris/tests/results/cdm/str_repr/realistic_4d.str.txt rename to lib/iris/tests/results/cdm/TestStockCubeStringRepresentations/4d_str.txt diff --git a/lib/iris/tests/results/cdm/extract/lat_eq_10.cml b/lib/iris/tests/results/cdm/extract/lat_eq_10.cml index 25a9032ced..f10c0be37c 100644 --- a/lib/iris/tests/results/cdm/extract/lat_eq_10.cml +++ b/lib/iris/tests/results/cdm/extract/lat_eq_10.cml @@ -1,19 +1,20 @@ - + - + + - + - + - + @@ -55,7 +56,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -68,12 +69,12 @@ - + - @@ -119,7 +120,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -129,7 +130,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -137,6 +138,6 @@ - + diff --git a/lib/iris/tests/results/cdm/extract/lat_gt_10.cml b/lib/iris/tests/results/cdm/extract/lat_gt_10.cml index ab00ae1116..e0d138f327 100644 --- a/lib/iris/tests/results/cdm/extract/lat_gt_10.cml +++ b/lib/iris/tests/results/cdm/extract/lat_gt_10.cml @@ -1,19 +1,20 @@ - + - + + - + - + - - + - @@ -128,7 +129,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -138,7 +139,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -146,6 +147,6 @@ - + diff --git a/lib/iris/tests/results/cdm/extract/lat_gt_10_and_lon_ge_10.cml b/lib/iris/tests/results/cdm/extract/lat_gt_10_and_lon_ge_10.cml index cee04b028b..3b435e9ceb 100644 --- a/lib/iris/tests/results/cdm/extract/lat_gt_10_and_lon_ge_10.cml +++ b/lib/iris/tests/results/cdm/extract/lat_gt_10_and_lon_ge_10.cml @@ -1,19 +1,20 @@ - + - + + - + - + - - - @@ -129,7 +130,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -139,7 +140,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -147,6 +148,6 @@ - + diff --git a/lib/iris/tests/results/cdm/masked_cube.cml b/lib/iris/tests/results/cdm/masked_cube.cml index e5d1975d7b..a38340913e 100644 --- a/lib/iris/tests/results/cdm/masked_cube.cml +++ b/lib/iris/tests/results/cdm/masked_cube.cml @@ -1,41 +1,41 @@ - + - + - + - - - - + - + diff --git a/lib/iris/tests/results/cdm/masked_save_pp.txt b/lib/iris/tests/results/cdm/masked_save_pp.txt index 20d1ada7cf..7c351667fc 100644 --- a/lib/iris/tests/results/cdm/masked_save_pp.txt +++ b/lib/iris/tests/results/cdm/masked_save_pp.txt @@ -49,126 +49,140 @@ bdy: 1.0 bzx: -1.0 bdx: 1.0 - bmdi: 123456.0 + bmdi: -1e+30 bmks: 1.0 - data.data: [[ 0. 0. 0. 0. 0. 0.64589411 - 0.4375872 0.89177299 0.96366274 0.38344151 0.79172504 0.5288949 - 0.56804454 0.92559665 0.07103606 0.0871293 0.0202184 0.83261985 - 0.77815676 0.87001216] - [ 0. 0. 0. 0. 0. 0.63992101 - 0.14335328 0.94466889 0.52184832 0.41466194 0.2645556 0.7742337 - 0.45615032 0.56843394 0.0187898 0.61763549 0.61209571 0.616934 - 0.94374806 0.68182027] - [ 0. 0. 0. 0. 0. 0.67063785 - 0.21038257 0.12892629 0.31542835 0.36371076 0.57019675 0.43860152 - 0.98837382 0.10204481 0.20887676 0.16130951 0.6531083 0.25329161 - 0.46631077 0.24442559] - [ 0. 0. 0. 0. 0. 0.36872518 - 0.82099324 0.09710128 0.83794492 0.09609841 0.97645944 0.46865121 - 0.9767611 0.60484552 0.73926359 0.03918779 0.28280696 0.12019656 - 0.29614019 0.11872772] - [ 0. 0. 0. 0. 0. 0.2653895 - 0.52324808 0.09394051 0.57594651 0.9292962 0.31856894 0.66741037 - 0.13179787 0.71632719 0.28940609 0.18319136 0.58651292 0.02010755 - 0.82894003 0.00469548] - [ 0.67781651 0.27000797 0.73519403 0.96218854 0.24875315 0.57615733 - 0.59204191 0.57225192 0.22308163 0.95274901 0.44712538 0.84640867 - 0.69947928 0.29743695 0.81379783 0.39650574 0.88110322 0.5812729 - 0.88173538 0.69253159] - [ 0.7252543 0.50132436 0.95608366 0.64399022 0.42385504 0.60639322 - 0.0191932 0.30157483 0.66017354 0.2900776 0.61801541 0.42876869 - 0.13547407 0.29828233 0.56996489 0.59087276 0.57432526 0.65320081 - 0.65210325 0.43141845] - [ 0.8965466 0.36756188 0.43586493 0.89192337 0.80619401 0.7038886 - 0.10022689 0.91948259 0.71424133 0.99884701 0.14944831 0.86812603 - 0.16249293 0.61555958 0.12381998 0.84800822 0.80731899 0.56910074 - 0.40718329 0.069167 ] - [ 0.69742876 0.45354268 0.72205561 0.8663823 0.9755215 0.85580337 - 0.01171408 0.35997805 0.72999054 0.17162968 0.52103662 0.05433799 - 0.19999653 0.0185218 0.79369771 0.22392468 0.34535167 0.92808127 - 0.70441443 0.03183893] - [ 0.16469416 0.62147838 0.57722861 0.23789282 0.934214 0.61396593 - 0.53563279 0.58990997 0.73012203 0.31194499 0.39822108 0.20984375 - 0.186193 0.94437242 0.73955077 0.49045882 0.22741462 0.25435647 - 0.05802916 0.43441662] - [ 0.31179589 0.69634348 0.37775183 0.17960368 0.02467873 0.06724963 - 0.67939276 0.45369685 0.53657919 0.8966713 0.99033892 0.21689698 - 0.66307819 0.26332238 0.020651 0.75837862 0.32001716 0.38346389 - 0.5883171 0.83104843] - [ 0.62898183 0.87265068 0.27354205 0.79804683 0.18563594 0.95279163 - 0.68748826 0.21550767 0.94737059 0.73085582 0.25394166 0.21331197 - 0.5182007 0.02566272 0.20747007 0.42468548 0.37416998 0.46357542 - 0.27762872 0.58678436] - [ 0.8638556 0.11753186 0.51737911 0.13206811 0.7168597 0.39605969 - 0.56542128 0.18327984 0.14484777 0.48805627 0.35561273 0.94043195 - 0.76532525 0.7486636 0.90371972 0.08342244 0.55219245 0.58447605 - 0.96193635 0.29214752] - [ 0.24082878 0.10029394 0.01642963 0.92952931 0.66991657 0.78515291 - 0.28173012 0.58641016 0.06395527 0.48562759 0.97749513 0.87650526 - 0.33815897 0.96157014 0.23170163 0.94931883 0.9413777 0.79920256 - 0.63044792 0.87428796] - [ 0.29302028 0.84894353 0.61787671 0.01323686 0.3472335 0.14814086 - 0.9818294 0.47837031 0.49739137 0.63947254 0.3685846 0.13690028 - 0.82211775 0.18984792 0.51131898 0.22431703 0.09784448 0.8621915 - 0.97291946 0.96083468] - [ 0.90655547 0.77404732 0.33314514 0.08110139 0.40724117 0.23223414 - 0.13248764 0.05342718 0.72559434 0.01142746 0.77058077 0.14694664 - 0.07952208 0.08960304 0.67204779 0.24536721 0.42053947 0.55736881 - 0.86055118 0.72704428] - [ 0.2703279 0.13148279 0.05537432 0.30159864 0.26211816 0.45614058 - 0.68328136 0.69562542 0.28351885 0.37992695 0.18115096 0.78854549 - 0.05684808 0.69699723 0.7786954 0.77740759 0.25942257 0.37381315 - 0.58759964 0.2728219 ] - [ 0.3708528 0.19705428 0.45985588 0.0446123 0.79979587 0.07695644 - 0.51883513 0.30681011 0.57754296 0.95943332 0.64557022 0.03536244 - 0.43040243 0.51001686 0.53617752 0.68139249 0.27759609 0.12886056 - 0.39267567 0.9564057 ] - [ 0.1871309 0.90398395 0.54380596 0.45691141 0.88204139 0.45860395 - 0.72416764 0.39902532 0.90404439 0.69002503 0.69962204 0.3277204 - 0.75677866 0.63606107 0.24002028 0.16053882 0.79639149 0.95916659 - 0.45813882 0.59098417] - [ 0.85772264 0.45722345 0.95187449 0.57575119 0.8207671 0.9088437 - 0.8155238 0.15941447 0.62889844 0.39843425 0.06271295 0.42403224 - 0.25868407 0.8490383 0.03330463 0.95898271 0.35536885 0.35670689 - 0.0163285 0.18523233]] - data.mask: [[ True True True True True False False False False False False False - False False False False False False False False] - [ True True True True True False False False False False False False - False False False False False False False False] - [ True True True True True False False False False False False False - False False False False False False False False] - [ True True True True True False False False False False False False - False False False False False False False False] - [ True True True True True False False False False False False False - False False False False False False False False] - [False False False False False False False False False False False False - False False False False False False False False] - [False False False False False False False False False False False False - False False False False False False False False] - [False False False False False False False False False False False False - False False False False False False False False] - [False False False False False False False False False False False False - False False False False False False False False] - [False False False False False False False False False False False False - False False False False False False False False] - [False False False False False False False False False False False False - False False False False False False False False] - [False False False False False False False False False False False False - False False False False False False False False] - [False False False False False False False False False False False False - False False False False False False False False] - [False False False False False False False False False False False False - False False False False False False False False] - [False False False False False False False False False False False False - False False False False False False False False] - [False False False False False False False False False False False False - False False False False False False False False] - [False False False False False False False False False False False False - False False False False False False False False] - [False False False False False False False False False False False False - False False False False False False False False] - [False False False False False False False False False False False False - False False False False False False False False] - [False False False False False False False False False False False False - False False False False False False False False]] + data: [[-- -- -- -- -- 0.6458941102027893 0.4375872015953064 0.891772985458374 + 0.9636627435684204 0.3834415078163147 0.7917250394821167 + 0.5288949012756348 0.5680445432662964 0.9255966544151306 + 0.07103605568408966 0.08712930232286453 0.020218396559357643 + 0.832619845867157 0.7781567573547363 0.8700121641159058] + [-- -- -- -- -- 0.6399210095405579 0.14335328340530396 + 0.9446688890457153 0.5218483209609985 0.4146619439125061 + 0.26455560326576233 0.7742336988449097 0.4561503231525421 + 0.568433940410614 0.018789799883961678 0.6176354885101318 + 0.6120957136154175 0.6169340014457703 0.9437480568885803 + 0.681820273399353] + [-- -- -- -- -- 0.670637845993042 0.21038256585597992 + 0.12892629206180573 0.31542834639549255 0.36371076107025146 + 0.5701967477798462 0.4386015236377716 0.9883738160133362 + 0.10204481333494186 0.20887675881385803 0.16130951046943665 + 0.6531082987785339 0.25329160690307617 0.4663107693195343 + 0.24442559480667114] + [-- -- -- -- -- 0.3687251806259155 0.8209932446479797 + 0.09710127860307693 0.8379449248313904 0.0960984081029892 + 0.9764594435691833 0.4686512053012848 0.9767611026763916 + 0.6048455238342285 0.7392635941505432 0.03918779268860817 + 0.28280696272850037 0.12019655853509903 0.296140193939209 + 0.11872772127389908] + [-- -- -- -- -- 0.26538950204849243 0.5232480764389038 + 0.09394051134586334 0.5759465098381042 0.9292961955070496 + 0.3185689449310303 0.6674103736877441 0.13179786503314972 + 0.7163271903991699 0.28940609097480774 0.18319135904312134 + 0.5865129232406616 0.02010754682123661 0.8289400339126587 + 0.004695476032793522] + [0.6778165102005005 0.2700079679489136 0.7351940274238586 + 0.9621885418891907 0.2487531453371048 0.5761573314666748 + 0.5920419096946716 0.5722519159317017 0.22308163344860077 + 0.9527490139007568 0.4471253752708435 0.8464086651802063 + 0.6994792819023132 0.2974369525909424 0.8137978315353394 + 0.396505743265152 0.8811032176017761 0.5812729001045227 + 0.8817353844642639 0.6925315856933594] + [0.7252542972564697 0.5013243556022644 0.9560836553573608 + 0.6439902186393738 0.4238550364971161 0.6063932180404663 + 0.019193198531866074 0.30157482624053955 0.6601735353469849 + 0.2900775969028473 0.6180154085159302 0.42876869440078735 + 0.1354740709066391 0.29828232526779175 0.5699648857116699 + 0.5908727645874023 0.5743252635002136 0.6532008051872253 + 0.6521032452583313 0.43141844868659973] + [0.8965466022491455 0.36756187677383423 0.4358649253845215 + 0.8919233679771423 0.806194007396698 0.7038885951042175 + 0.10022688657045364 0.9194825887680054 0.7142413258552551 + 0.9988470077514648 0.14944830536842346 0.8681260347366333 + 0.16249293088912964 0.6155595779418945 0.1238199844956398 + 0.8480082154273987 0.8073189854621887 0.5691007375717163 + 0.40718328952789307 0.06916699558496475] + [0.6974287629127502 0.45354267954826355 0.7220556139945984 + 0.8663823008537292 0.9755215048789978 0.855803370475769 + 0.011714084073901176 0.359978049993515 0.729990541934967 + 0.17162968218326569 0.5210366249084473 0.054337989538908005 + 0.19999653100967407 0.01852179504930973 0.793697714805603 + 0.2239246815443039 0.3453516662120819 0.9280812740325928 + 0.704414427280426 0.031838931143283844] + [0.1646941602230072 0.6214783787727356 0.5772286057472229 + 0.23789282143115997 0.9342139959335327 0.6139659285545349 + 0.5356327891349792 0.5899099707603455 0.7301220297813416 + 0.31194499135017395 0.39822107553482056 0.20984375476837158 + 0.18619300425052643 0.9443724155426025 0.739550769329071 + 0.49045881628990173 0.22741462290287018 0.2543564736843109 + 0.058029159903526306 0.43441662192344666] + [0.3117958903312683 0.6963434815406799 0.37775182723999023 + 0.1796036809682846 0.024678727611899376 0.06724963337182999 + 0.6793927550315857 0.4536968469619751 0.5365791916847229 + 0.8966712951660156 0.990338921546936 0.21689698100090027 + 0.6630781888961792 0.2633223831653595 0.02065099962055683 + 0.7583786249160767 0.32001715898513794 0.38346388936042786 + 0.5883170962333679 0.8310484290122986] + [0.6289818286895752 0.872650682926178 0.27354204654693604 + 0.7980468273162842 0.18563593924045563 0.9527916312217712 + 0.6874882578849792 0.21550767123699188 0.9473705887794495 + 0.7308558225631714 0.2539416551589966 0.21331197023391724 + 0.518200695514679 0.02566271834075451 0.20747007429599762 + 0.4246854782104492 0.3741699755191803 0.46357542276382446 + 0.27762871980667114 0.5867843627929688] + [0.8638556003570557 0.11753185838460922 0.517379105091095 + 0.13206811249256134 0.7168596982955933 0.39605969190597534 + 0.5654212832450867 0.1832798421382904 0.14484776556491852 + 0.4880562722682953 0.35561272501945496 0.9404319524765015 + 0.7653252482414246 0.748663604259491 0.9037197232246399 + 0.08342243731021881 0.5521924495697021 0.5844760537147522 + 0.961936354637146 0.29214751720428467] + [0.24082878232002258 0.10029394179582596 0.016429629176855087 + 0.9295293092727661 0.669916570186615 0.7851529121398926 + 0.28173011541366577 0.5864101648330688 0.06395526975393295 + 0.48562759160995483 0.9774951338768005 0.8765052556991577 + 0.3381589651107788 0.961570143699646 0.23170162737369537 + 0.9493188261985779 0.9413776993751526 0.799202561378479 + 0.6304479241371155 0.8742879629135132] + [0.2930202782154083 0.8489435315132141 0.6178767085075378 + 0.013236857950687408 0.34723350405693054 0.14814086258411407 + 0.9818294048309326 0.4783703088760376 0.49739137291908264 + 0.6394725441932678 0.36858460307121277 0.13690027594566345 + 0.8221177458763123 0.1898479163646698 0.5113189816474915 + 0.2243170291185379 0.09784448146820068 0.8621914982795715 + 0.9729194641113281 0.9608346819877625] + [0.9065554738044739 0.774047315120697 0.3331451416015625 + 0.08110138773918152 0.40724116563796997 0.2322341352701187 + 0.13248763978481293 0.053427182137966156 0.7255943417549133 + 0.011427458375692368 0.7705807685852051 0.14694663882255554 + 0.07952208071947098 0.08960303664207458 0.6720477938652039 + 0.24536721408367157 0.4205394685268402 0.557368814945221 + 0.8605511784553528 0.7270442843437195] + [0.2703278958797455 0.131482794880867 0.05537432059645653 + 0.3015986382961273 0.2621181607246399 0.45614057779312134 + 0.6832813620567322 0.6956254243850708 0.28351885080337524 + 0.3799269497394562 0.18115095794200897 0.7885454893112183 + 0.05684807524085045 0.6969972252845764 0.7786954045295715 + 0.7774075865745544 0.25942257046699524 0.3738131523132324 + 0.5875996351242065 0.27282190322875977] + [0.3708527982234955 0.19705428183078766 0.4598558843135834 + 0.044612299650907516 0.7997958660125732 0.07695644348859787 + 0.5188351273536682 0.3068101108074188 0.5775429606437683 + 0.9594333171844482 0.6455702185630798 0.03536243736743927 + 0.4304024279117584 0.5100168585777283 0.5361775159835815 + 0.6813924908638 0.2775960862636566 0.12886056303977966 + 0.3926756680011749 0.9564056992530823] + [0.1871308982372284 0.9039839506149292 0.5438059568405151 + 0.4569114148616791 0.8820413947105408 0.45860394835472107 + 0.7241676449775696 0.3990253210067749 0.9040443897247314 + 0.6900250315666199 0.6996220350265503 0.32772040367126465 + 0.7567786574363708 0.6360610723495483 0.2400202751159668 + 0.16053882241249084 0.796391487121582 0.9591665863990784 + 0.4581388235092163 0.5909841656684875] + [0.8577226400375366 0.45722344517707825 0.9518744945526123 + 0.5757511854171753 0.8207671046257019 0.9088436961174011 + 0.8155238032341003 0.15941447019577026 0.6288984417915344 + 0.39843425154685974 0.06271295249462128 0.4240322411060333 + 0.25868406891822815 0.849038302898407 0.03330462798476219 + 0.9589827060699463 0.35536885261535645 0.3567068874835968 + 0.01632850244641304 0.18523232638835907]] ] \ No newline at end of file diff --git a/lib/iris/tests/results/cdm/str_repr/0d_cube.__str__.txt b/lib/iris/tests/results/cdm/str_repr/0d_cube.__str__.txt index 966146deb7..afe329f38d 100644 --- a/lib/iris/tests/results/cdm/str_repr/0d_cube.__str__.txt +++ b/lib/iris/tests/results/cdm/str_repr/0d_cube.__str__.txt @@ -2,7 +2,7 @@ air_temperature / (K) (scalar cube) Scalar coordinates: forecast_period: 6477.0 hours forecast_reference_time: 1998-03-06 03:00:00 - latitude: 90.0 degrees + latitude: 89.999985 degrees longitude: 0.0 degrees pressure: 1000.0 hPa time: 1998-12-01 00:00:00 diff --git a/lib/iris/tests/results/cdm/str_repr/0d_cube.__unicode__.txt b/lib/iris/tests/results/cdm/str_repr/0d_cube.__unicode__.txt index 966146deb7..afe329f38d 100644 --- a/lib/iris/tests/results/cdm/str_repr/0d_cube.__unicode__.txt +++ b/lib/iris/tests/results/cdm/str_repr/0d_cube.__unicode__.txt @@ -2,7 +2,7 @@ air_temperature / (K) (scalar cube) Scalar coordinates: forecast_period: 6477.0 hours forecast_reference_time: 1998-03-06 03:00:00 - latitude: 90.0 degrees + latitude: 89.999985 degrees longitude: 0.0 degrees pressure: 1000.0 hPa time: 1998-12-01 00:00:00 diff --git a/lib/iris/tests/results/cdm/str_repr/realistic_0d.str.txt b/lib/iris/tests/results/cdm/str_repr/realistic_0d.str.txt deleted file mode 100644 index 0453a3b2df..0000000000 --- a/lib/iris/tests/results/cdm/str_repr/realistic_0d.str.txt +++ /dev/null @@ -1,13 +0,0 @@ -air_potential_temperature / (K) (scalar cube) - Scalar coordinates: - altitude: 418.698 m, bound=(413.937, 426.634) m - forecast_period: 0.0 hours - grid_latitude: -0.1278 degrees, bound=(-0.12825, -0.12735) degrees - grid_longitude: 359.58 degrees, bound=(359.579, 359.58) degrees - level_height: 5.0 m, bound=(0.0, 13.3333) m - model_level_number: 1 - sigma: 0.999424, bound=(1.0, 0.998464) - surface_altitude: 413.937 m - time: 2009-09-09 17:10:00 - Attributes: - source: Iris test case \ No newline at end of file diff --git a/lib/iris/tests/results/cdm/str_repr/realistic_1d.str.txt b/lib/iris/tests/results/cdm/str_repr/realistic_1d.str.txt deleted file mode 100644 index 123e5204b2..0000000000 --- a/lib/iris/tests/results/cdm/str_repr/realistic_1d.str.txt +++ /dev/null @@ -1,16 +0,0 @@ -air_potential_temperature / (K) (grid_longitude: 100) - Dimension coordinates: - grid_longitude x - Auxiliary coordinates: - surface_altitude x - Derived coordinates: - altitude x - Scalar coordinates: - forecast_period: 0.0 hours - grid_latitude: -0.1278 degrees, bound=(-0.12825, -0.12735) degrees - level_height: 5.0 m, bound=(0.0, 13.3333) m - model_level_number: 1 - sigma: 0.999424, bound=(1.0, 0.998464) - time: 2009-09-09 17:10:00 - Attributes: - source: Iris test case \ No newline at end of file diff --git a/lib/iris/tests/results/cdm/str_repr/realistic_2d.str.txt b/lib/iris/tests/results/cdm/str_repr/realistic_2d.str.txt deleted file mode 100644 index 21cf0ec445..0000000000 --- a/lib/iris/tests/results/cdm/str_repr/realistic_2d.str.txt +++ /dev/null @@ -1,16 +0,0 @@ -air_potential_temperature / (K) (grid_latitude: 100; grid_longitude: 100) - Dimension coordinates: - grid_latitude x - - grid_longitude - x - Auxiliary coordinates: - surface_altitude x x - Derived coordinates: - altitude x x - Scalar coordinates: - forecast_period: 0.0 hours - level_height: 5.0 m, bound=(0.0, 13.3333) m - model_level_number: 1 - sigma: 0.999424, bound=(1.0, 0.998464) - time: 2009-09-09 17:10:00 - Attributes: - source: Iris test case \ No newline at end of file diff --git a/lib/iris/tests/results/cdm/str_repr/simple.__str__.txt b/lib/iris/tests/results/cdm/str_repr/simple.__str__.txt index 442f0928ab..b174d346d2 100644 --- a/lib/iris/tests/results/cdm/str_repr/simple.__str__.txt +++ b/lib/iris/tests/results/cdm/str_repr/simple.__str__.txt @@ -1,6 +1,6 @@ -thingness (foo: 11) +thingness (foo: 11) Dimension coordinates: - foo x + foo x Auxiliary coordinates: - This is a really, really, really long long_name that requires to be clipped... x - This is a short long_name x \ No newline at end of file + This is a really, really, really, really long long_name that must be clipped... x + This is a short long_name x \ No newline at end of file diff --git a/lib/iris/tests/results/cdm/test_simple_cube_intersection.cml b/lib/iris/tests/results/cdm/test_simple_cube_intersection.cml index 9c0b1e7092..8d1b986397 100644 --- a/lib/iris/tests/results/cdm/test_simple_cube_intersection.cml +++ b/lib/iris/tests/results/cdm/test_simple_cube_intersection.cml @@ -1,41 +1,41 @@ - + - + - + - + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/concatenate/concat_2x2d.cml b/lib/iris/tests/results/concatenate/concat_2x2d.cml index 47303a0d7c..feeb553642 100644 --- a/lib/iris/tests/results/concatenate/concat_2x2d.cml +++ b/lib/iris/tests/results/concatenate/concat_2x2d.cml @@ -1,6 +1,6 @@ - + + [4.5, 5.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_2x2d_aux_x.cml b/lib/iris/tests/results/concatenate/concat_2x2d_aux_x.cml index 59dc9900af..9076ae2538 100644 --- a/lib/iris/tests/results/concatenate/concat_2x2d_aux_x.cml +++ b/lib/iris/tests/results/concatenate/concat_2x2d_aux_x.cml @@ -1,6 +1,6 @@ - + + [4.5, 5.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_2x2d_aux_x_bounds.cml b/lib/iris/tests/results/concatenate/concat_2x2d_aux_x_bounds.cml index e49ab697f7..5597a876b2 100644 --- a/lib/iris/tests/results/concatenate/concat_2x2d_aux_x_bounds.cml +++ b/lib/iris/tests/results/concatenate/concat_2x2d_aux_x_bounds.cml @@ -1,6 +1,6 @@ - + + [4.5, 5.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> + [45.0, 55.0]]" id="adc2bc82" long_name="x-aux" points="[0.0, 10.0, 20.0, 30.0, 40.0, 50.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_2x2d_aux_x_xy.cml b/lib/iris/tests/results/concatenate/concat_2x2d_aux_x_xy.cml index d59e9050dc..4c5c993b9e 100644 --- a/lib/iris/tests/results/concatenate/concat_2x2d_aux_x_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_2x2d_aux_x_xy.cml @@ -1,6 +1,6 @@ - + + [4.5, 5.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + - + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_2x2d_aux_x_y.cml b/lib/iris/tests/results/concatenate/concat_2x2d_aux_x_y.cml index 60d3d10f6c..2ace2a8024 100644 --- a/lib/iris/tests/results/concatenate/concat_2x2d_aux_x_y.cml +++ b/lib/iris/tests/results/concatenate/concat_2x2d_aux_x_y.cml @@ -1,6 +1,6 @@ - + + [4.5, 5.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + - + diff --git a/lib/iris/tests/results/concatenate/concat_2x2d_aux_x_y_xy.cml b/lib/iris/tests/results/concatenate/concat_2x2d_aux_x_y_xy.cml index 8ebb7ea808..e0f1fd2775 100644 --- a/lib/iris/tests/results/concatenate/concat_2x2d_aux_x_y_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_2x2d_aux_x_y_xy.cml @@ -1,6 +1,6 @@ - + + [4.5, 5.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + - + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + - + diff --git a/lib/iris/tests/results/concatenate/concat_2x2d_aux_xy.cml b/lib/iris/tests/results/concatenate/concat_2x2d_aux_xy.cml index 8564111527..5bc3c707f7 100644 --- a/lib/iris/tests/results/concatenate/concat_2x2d_aux_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_2x2d_aux_xy.cml @@ -1,6 +1,6 @@ - + + [4.5, 5.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_2x2d_aux_xy_bounds.cml b/lib/iris/tests/results/concatenate/concat_2x2d_aux_xy_bounds.cml index 31db069c6e..4f279cef01 100644 --- a/lib/iris/tests/results/concatenate/concat_2x2d_aux_xy_bounds.cml +++ b/lib/iris/tests/results/concatenate/concat_2x2d_aux_xy_bounds.cml @@ -1,31 +1,31 @@ - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_2x2d_aux_y.cml b/lib/iris/tests/results/concatenate/concat_2x2d_aux_y.cml index 930c258b03..95575d1b65 100644 --- a/lib/iris/tests/results/concatenate/concat_2x2d_aux_y.cml +++ b/lib/iris/tests/results/concatenate/concat_2x2d_aux_y.cml @@ -1,6 +1,6 @@ - + + [4.5, 5.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + - + diff --git a/lib/iris/tests/results/concatenate/concat_2x2d_aux_y_xy.cml b/lib/iris/tests/results/concatenate/concat_2x2d_aux_y_xy.cml index d305dfc6c7..dbe28f6a65 100644 --- a/lib/iris/tests/results/concatenate/concat_2x2d_aux_y_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_2x2d_aux_y_xy.cml @@ -1,6 +1,6 @@ - + + [4.5, 5.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + - + diff --git a/lib/iris/tests/results/concatenate/concat_2y2d.cml b/lib/iris/tests/results/concatenate/concat_2y2d.cml index 62b0f13687..55a896c12a 100644 --- a/lib/iris/tests/results/concatenate/concat_2y2d.cml +++ b/lib/iris/tests/results/concatenate/concat_2y2d.cml @@ -1,10 +1,10 @@ - + + [0.5, 1.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> + [4.5, 5.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_2y2d_aux_x.cml b/lib/iris/tests/results/concatenate/concat_2y2d_aux_x.cml index 8feee2afad..6e8e367501 100644 --- a/lib/iris/tests/results/concatenate/concat_2y2d_aux_x.cml +++ b/lib/iris/tests/results/concatenate/concat_2y2d_aux_x.cml @@ -1,13 +1,13 @@ - + + [0.5, 1.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + + [4.5, 5.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_2y2d_aux_x_xy.cml b/lib/iris/tests/results/concatenate/concat_2y2d_aux_x_xy.cml index acd9dbd185..20ce15e486 100644 --- a/lib/iris/tests/results/concatenate/concat_2y2d_aux_x_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_2y2d_aux_x_xy.cml @@ -1,16 +1,16 @@ - + + [0.5, 1.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + - + [4.5, 5.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_2y2d_aux_x_y.cml b/lib/iris/tests/results/concatenate/concat_2y2d_aux_x_y.cml index 0b86dde00a..f486652592 100644 --- a/lib/iris/tests/results/concatenate/concat_2y2d_aux_x_y.cml +++ b/lib/iris/tests/results/concatenate/concat_2y2d_aux_x_y.cml @@ -1,13 +1,13 @@ - + + [0.5, 1.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + + [4.5, 5.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + - + diff --git a/lib/iris/tests/results/concatenate/concat_2y2d_aux_x_y_xy.cml b/lib/iris/tests/results/concatenate/concat_2y2d_aux_x_y_xy.cml index 0f194f9869..cc1377cfd0 100644 --- a/lib/iris/tests/results/concatenate/concat_2y2d_aux_x_y_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_2y2d_aux_x_y_xy.cml @@ -1,16 +1,16 @@ - + + [0.5, 1.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + - + [4.5, 5.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + - + diff --git a/lib/iris/tests/results/concatenate/concat_2y2d_aux_xy.cml b/lib/iris/tests/results/concatenate/concat_2y2d_aux_xy.cml index 5c446dbb9b..4e4a8d8729 100644 --- a/lib/iris/tests/results/concatenate/concat_2y2d_aux_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_2y2d_aux_xy.cml @@ -1,13 +1,13 @@ - + + [0.5, 1.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + [4.5, 5.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_2y2d_aux_y.cml b/lib/iris/tests/results/concatenate/concat_2y2d_aux_y.cml index 94ff195fc4..73a11c74a8 100644 --- a/lib/iris/tests/results/concatenate/concat_2y2d_aux_y.cml +++ b/lib/iris/tests/results/concatenate/concat_2y2d_aux_y.cml @@ -1,10 +1,10 @@ - + + [0.5, 1.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> + [4.5, 5.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + - + diff --git a/lib/iris/tests/results/concatenate/concat_2y2d_aux_y_xy.cml b/lib/iris/tests/results/concatenate/concat_2y2d_aux_y_xy.cml index c43a236fbd..8add7084dc 100644 --- a/lib/iris/tests/results/concatenate/concat_2y2d_aux_y_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_2y2d_aux_y_xy.cml @@ -1,13 +1,13 @@ - + + [0.5, 1.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + [4.5, 5.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + - + diff --git a/lib/iris/tests/results/concatenate/concat_3d_simple.cml b/lib/iris/tests/results/concatenate/concat_3d_simple.cml index 813304a52f..67c7cc4376 100644 --- a/lib/iris/tests/results/concatenate/concat_3d_simple.cml +++ b/lib/iris/tests/results/concatenate/concat_3d_simple.cml @@ -1,45 +1,45 @@ - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - + - - + [6000.0, 7000.0, 6000.0, 7000.0], + [4000.0, 5000.0, 4000.0, 5000.0], + [6000.0, 7000.0, 6000.0, 7000.0]]]" shape="(4, 4, 4)" units="Unit('1')" value_type="float32"/> - @@ -48,13 +48,13 @@ + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - + - @@ -63,13 +63,13 @@ + [2.5, 3.5]]" id="5656f76e" long_name="z" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - + - + diff --git a/lib/iris/tests/results/concatenate/concat_4mix2d_aux_xy.cml b/lib/iris/tests/results/concatenate/concat_4mix2d_aux_xy.cml index 6871174b33..b706f7b3cb 100644 --- a/lib/iris/tests/results/concatenate/concat_4mix2d_aux_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_4mix2d_aux_xy.cml @@ -1,15 +1,15 @@ - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - @@ -18,10 +18,10 @@ + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_4x2d_aux_xy.cml b/lib/iris/tests/results/concatenate/concat_4x2d_aux_xy.cml index 4b341fea35..229281f88c 100644 --- a/lib/iris/tests/results/concatenate/concat_4x2d_aux_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_4x2d_aux_xy.cml @@ -1,15 +1,15 @@ - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - @@ -18,10 +18,10 @@ + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_4y2d_aux_xy.cml b/lib/iris/tests/results/concatenate/concat_4y2d_aux_xy.cml index 958ad1ebce..bf9ee0a610 100644 --- a/lib/iris/tests/results/concatenate/concat_4y2d_aux_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_4y2d_aux_xy.cml @@ -1,15 +1,15 @@ - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - @@ -18,10 +18,10 @@ + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_9mix2d_aux_xy.cml b/lib/iris/tests/results/concatenate/concat_9mix2d_aux_xy.cml index bad2da290c..636d7ad06d 100644 --- a/lib/iris/tests/results/concatenate/concat_9mix2d_aux_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_9mix2d_aux_xy.cml @@ -1,6 +1,6 @@ - + + [4.5, 5.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + [4.5, 5.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_9x2d_aux_xy.cml b/lib/iris/tests/results/concatenate/concat_9x2d_aux_xy.cml index 7dc4b4ef33..dea24c5518 100644 --- a/lib/iris/tests/results/concatenate/concat_9x2d_aux_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_9x2d_aux_xy.cml @@ -1,6 +1,6 @@ - + + [4.5, 5.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + [4.5, 5.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_9y2d_aux_xy.cml b/lib/iris/tests/results/concatenate/concat_9y2d_aux_xy.cml index 55d6ede744..ed4b23ce08 100644 --- a/lib/iris/tests/results/concatenate/concat_9y2d_aux_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_9y2d_aux_xy.cml @@ -1,6 +1,6 @@ - + + [4.5, 5.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + [4.5, 5.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]" shape="(6,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_anonymous.cml b/lib/iris/tests/results/concatenate/concat_anonymous.cml index 40db9e4e69..7eeccb2241 100644 --- a/lib/iris/tests/results/concatenate/concat_anonymous.cml +++ b/lib/iris/tests/results/concatenate/concat_anonymous.cml @@ -1,29 +1,29 @@ - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + - + + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_masked_2x2d.cml b/lib/iris/tests/results/concatenate/concat_masked_2x2d.cml index ea4954b477..f8b47f9627 100644 --- a/lib/iris/tests/results/concatenate/concat_masked_2x2d.cml +++ b/lib/iris/tests/results/concatenate/concat_masked_2x2d.cml @@ -1,19 +1,19 @@ - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_masked_2y2d.cml b/lib/iris/tests/results/concatenate/concat_masked_2y2d.cml index 0c75f7bb8e..d4f31c7e44 100644 --- a/lib/iris/tests/results/concatenate/concat_masked_2y2d.cml +++ b/lib/iris/tests/results/concatenate/concat_masked_2y2d.cml @@ -1,19 +1,19 @@ - + + [0.5, 1.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_merged_scalar_4mix2d_aux_xy.cml b/lib/iris/tests/results/concatenate/concat_merged_scalar_4mix2d_aux_xy.cml index 121524e80e..645d0aa95f 100644 --- a/lib/iris/tests/results/concatenate/concat_merged_scalar_4mix2d_aux_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_merged_scalar_4mix2d_aux_xy.cml @@ -1,18 +1,18 @@ - + - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - @@ -21,10 +21,10 @@ + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_merged_scalar_4x2d_aux_xy.cml b/lib/iris/tests/results/concatenate/concat_merged_scalar_4x2d_aux_xy.cml index 121524e80e..645d0aa95f 100644 --- a/lib/iris/tests/results/concatenate/concat_merged_scalar_4x2d_aux_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_merged_scalar_4x2d_aux_xy.cml @@ -1,18 +1,18 @@ - + - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - @@ -21,10 +21,10 @@ + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_merged_scalar_4y2d_aux_xy.cml b/lib/iris/tests/results/concatenate/concat_merged_scalar_4y2d_aux_xy.cml index d14e547396..94bcb31795 100644 --- a/lib/iris/tests/results/concatenate/concat_merged_scalar_4y2d_aux_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_merged_scalar_4y2d_aux_xy.cml @@ -1,18 +1,18 @@ - + - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - @@ -21,10 +21,10 @@ + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_pre_merged_scalar_4mix2d_aux_xy.cml b/lib/iris/tests/results/concatenate/concat_pre_merged_scalar_4mix2d_aux_xy.cml index de4f741254..1b60930a09 100644 --- a/lib/iris/tests/results/concatenate/concat_pre_merged_scalar_4mix2d_aux_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_pre_merged_scalar_4mix2d_aux_xy.cml @@ -1,87 +1,87 @@ - + - + + [0.5, 1.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + - + - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[2.0, 3.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[2.0, 3.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + - + - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[2.0, 3.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + - + - + + [0.5, 1.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[2.0, 3.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_pre_merged_scalar_4x2_aux_xy.cml b/lib/iris/tests/results/concatenate/concat_pre_merged_scalar_4x2_aux_xy.cml index c8c01a4013..1f87f5b3cf 100644 --- a/lib/iris/tests/results/concatenate/concat_pre_merged_scalar_4x2_aux_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_pre_merged_scalar_4x2_aux_xy.cml @@ -1,87 +1,87 @@ - + - + + [0.5, 1.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + - + - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[2.0, 3.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + - + - + + [0.5, 1.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[2.0, 3.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + - + - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[2.0, 3.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[2.0, 3.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_pre_merged_scalar_4y2d_aux_xy.cml b/lib/iris/tests/results/concatenate/concat_pre_merged_scalar_4y2d_aux_xy.cml index f075c4709c..cca6094d9c 100644 --- a/lib/iris/tests/results/concatenate/concat_pre_merged_scalar_4y2d_aux_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_pre_merged_scalar_4y2d_aux_xy.cml @@ -1,87 +1,87 @@ - + - + + [0.5, 1.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + - + - + + [0.5, 1.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[2.0, 3.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + - + - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[2.0, 3.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + [0.5, 1.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + - + - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[2.0, 3.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[2.0, 3.0]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_scalar_4mix2d_aux_xy.cml b/lib/iris/tests/results/concatenate/concat_scalar_4mix2d_aux_xy.cml index a0777aad53..8709ebd03d 100644 --- a/lib/iris/tests/results/concatenate/concat_scalar_4mix2d_aux_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_scalar_4mix2d_aux_xy.cml @@ -1,18 +1,18 @@ - + - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - @@ -21,25 +21,25 @@ + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - + - + - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - @@ -48,10 +48,10 @@ + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_scalar_4x2d_aux_xy.cml b/lib/iris/tests/results/concatenate/concat_scalar_4x2d_aux_xy.cml index a0777aad53..8709ebd03d 100644 --- a/lib/iris/tests/results/concatenate/concat_scalar_4x2d_aux_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_scalar_4x2d_aux_xy.cml @@ -1,18 +1,18 @@ - + - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - @@ -21,25 +21,25 @@ + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - + - + - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - @@ -48,10 +48,10 @@ + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/concatenate/concat_scalar_4y2d_aux_xy.cml b/lib/iris/tests/results/concatenate/concat_scalar_4y2d_aux_xy.cml index 9347f67585..864e476e97 100644 --- a/lib/iris/tests/results/concatenate/concat_scalar_4y2d_aux_xy.cml +++ b/lib/iris/tests/results/concatenate/concat_scalar_4y2d_aux_xy.cml @@ -1,18 +1,18 @@ - + - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - @@ -21,25 +21,25 @@ + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - + - + - + + [2.5, 3.5]]" id="78a0dfe8" long_name="x" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - @@ -48,10 +48,10 @@ + [2.5, 3.5]]" id="6fdbcbab" long_name="y" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/constrained_load/all_10_load_match.cml b/lib/iris/tests/results/constrained_load/all_10_load_match.cml index f06bfe208f..6a582f9d67 100644 --- a/lib/iris/tests/results/constrained_load/all_10_load_match.cml +++ b/lib/iris/tests/results/constrained_load/all_10_load_match.cml @@ -1,46 +1,47 @@ - + - + + - + - + - + - + - + - + - + - + @@ -48,49 +49,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -98,50 +100,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -149,50 +152,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -200,6 +204,6 @@ - + diff --git a/lib/iris/tests/results/constrained_load/all_ml_10_22_load_match.cml b/lib/iris/tests/results/constrained_load/all_ml_10_22_load_match.cml index 6b89a780f9..458474f98a 100644 --- a/lib/iris/tests/results/constrained_load/all_ml_10_22_load_match.cml +++ b/lib/iris/tests/results/constrained_load/all_ml_10_22_load_match.cml @@ -1,37 +1,38 @@ - + - + + - + - + - + + [9250.0, 10130.0]]" id="fb105c19" long_name="level_height" points="[2000.0, 9680.0]" shape="(2,)" units="Unit('m')" value_type="float32"> - + - + @@ -39,10 +40,10 @@ + [0.222443, 0.177555]]" id="a5c170db" long_name="sigma" points="[0.784571, 0.199878]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + @@ -50,40 +51,41 @@ - + - + - + + - + - + - + + [9250.0, 10130.0]]" id="fb105c19" long_name="level_height" points="[2000.0, 9680.0]" shape="(2,)" units="Unit('m')" value_type="float32"> - + - + @@ -91,10 +93,10 @@ + [0.222443, 0.177555]]" id="a5c170db" long_name="sigma" points="[0.784571, 0.199878]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + @@ -102,41 +104,42 @@ - + - + - + + - + - + - + + [8820.0, 9680.0]]" id="fb105c19" long_name="level_height" points="[1810.0, 9250.0]" shape="(2,)" units="Unit('m')" value_type="float32"> - - + @@ -144,10 +147,10 @@ + [0.246215, 0.199878]]" id="a5c170db" long_name="sigma" points="[0.803914, 0.222443]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + @@ -155,41 +158,42 @@ - + - + - + + - + - + - + [8820.0, 9680.0]]" id="fb105c19" long_name="level_height" points="[1810.0, 9250.0]" shape="(2,)" units="Unit('m')" value_type="float32"> - + - + @@ -197,10 +201,10 @@ + [0.246215, 0.199878]]" id="a5c170db" long_name="sigma" points="[0.803914, 0.222443]" shape="(2,)" units="Unit('1')" value_type="float32"/> - + @@ -208,6 +212,6 @@ - + diff --git a/lib/iris/tests/results/constrained_load/attribute_constraint.cml b/lib/iris/tests/results/constrained_load/attribute_constraint.cml index 977c728f1f..31714035fa 100644 --- a/lib/iris/tests/results/constrained_load/attribute_constraint.cml +++ b/lib/iris/tests/results/constrained_load/attribute_constraint.cml @@ -1,20 +1,21 @@ - + - + + - + - + - + @@ -56,7 +57,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -69,12 +70,12 @@ - + - @@ -120,7 +121,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -130,7 +131,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -138,6 +139,6 @@ - + diff --git a/lib/iris/tests/results/constrained_load/theta_10_and_theta_level_gt_30_le_3_load_match.cml b/lib/iris/tests/results/constrained_load/theta_10_and_theta_level_gt_30_le_3_load_match.cml index af9c026e17..bbafc31987 100644 --- a/lib/iris/tests/results/constrained_load/theta_10_and_theta_level_gt_30_le_3_load_match.cml +++ b/lib/iris/tests/results/constrained_load/theta_10_and_theta_level_gt_30_le_3_load_match.cml @@ -1,46 +1,47 @@ - + - + + - + - + - + - + - + - + - + - + @@ -48,22 +49,23 @@ - + - + - + + - + - + - + @@ -78,7 +80,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 19503.0, 20990.2, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 19503.0, 20990.2, 22626.1, 24458.3, 26583.6, 29219.1, 32908.7, 39254.8]" shape="(11,)" units="Unit('m')" value_type="float32"> @@ -87,12 +89,12 @@ - + - + @@ -109,11 +111,11 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.0, 0.0, 0.0, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(11,)" units="Unit('1')" value_type="float32"/> - + @@ -121,6 +123,6 @@ - + diff --git a/lib/iris/tests/results/constrained_load/theta_10_and_theta_level_gt_30_le_3_load_strict.cml b/lib/iris/tests/results/constrained_load/theta_10_and_theta_level_gt_30_le_3_load_strict.cml index af9c026e17..bbafc31987 100644 --- a/lib/iris/tests/results/constrained_load/theta_10_and_theta_level_gt_30_le_3_load_strict.cml +++ b/lib/iris/tests/results/constrained_load/theta_10_and_theta_level_gt_30_le_3_load_strict.cml @@ -1,46 +1,47 @@ - + - + + - + - + - + - + - + - + - + - + @@ -48,22 +49,23 @@ - + - + - + + - + - + - + @@ -78,7 +80,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 19503.0, 20990.2, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 19503.0, 20990.2, 22626.1, 24458.3, 26583.6, 29219.1, 32908.7, 39254.8]" shape="(11,)" units="Unit('m')" value_type="float32"> @@ -87,12 +89,12 @@ - + - + @@ -109,11 +111,11 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.0, 0.0, 0.0, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(11,)" units="Unit('1')" value_type="float32"/> - + @@ -121,6 +123,6 @@ - + diff --git a/lib/iris/tests/results/constrained_load/theta_10_load_match.cml b/lib/iris/tests/results/constrained_load/theta_10_load_match.cml index 537cf8a3e1..2e5005d042 100644 --- a/lib/iris/tests/results/constrained_load/theta_10_load_match.cml +++ b/lib/iris/tests/results/constrained_load/theta_10_load_match.cml @@ -1,46 +1,47 @@ - + - + + - + - + - + - + - + - + - + - + @@ -48,6 +49,6 @@ - + diff --git a/lib/iris/tests/results/constrained_load/theta_10_load_strict.cml b/lib/iris/tests/results/constrained_load/theta_10_load_strict.cml index 537cf8a3e1..2e5005d042 100644 --- a/lib/iris/tests/results/constrained_load/theta_10_load_strict.cml +++ b/lib/iris/tests/results/constrained_load/theta_10_load_strict.cml @@ -1,46 +1,47 @@ - + - + + - + - + - + - + - + - + - + - + @@ -48,6 +49,6 @@ - + diff --git a/lib/iris/tests/results/constrained_load/theta_and_all_10_load_match.cml b/lib/iris/tests/results/constrained_load/theta_and_all_10_load_match.cml index e64f92779b..40bb37f3ab 100644 --- a/lib/iris/tests/results/constrained_load/theta_and_all_10_load_match.cml +++ b/lib/iris/tests/results/constrained_load/theta_and_all_10_load_match.cml @@ -1,19 +1,20 @@ - + - + + - + - + - + @@ -55,7 +56,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -68,12 +69,12 @@ - + - @@ -119,7 +120,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -129,7 +130,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -137,49 +138,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -187,49 +189,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -237,50 +240,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -288,50 +292,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -339,6 +344,6 @@ - + diff --git a/lib/iris/tests/results/constrained_load/theta_and_theta_10_load_strict.cml b/lib/iris/tests/results/constrained_load/theta_and_theta_10_load_strict.cml index d492bc2b97..03fed4e61b 100644 --- a/lib/iris/tests/results/constrained_load/theta_and_theta_10_load_strict.cml +++ b/lib/iris/tests/results/constrained_load/theta_and_theta_10_load_strict.cml @@ -1,19 +1,20 @@ - + - + + - + - + - + @@ -55,7 +56,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -68,12 +69,12 @@ - + - @@ -119,7 +120,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -129,7 +130,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -137,49 +138,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -187,6 +189,6 @@ - + diff --git a/lib/iris/tests/results/constrained_load/theta_and_theta_load_match.cml b/lib/iris/tests/results/constrained_load/theta_and_theta_load_match.cml index f2c84c6999..eadbe8f365 100644 --- a/lib/iris/tests/results/constrained_load/theta_and_theta_load_match.cml +++ b/lib/iris/tests/results/constrained_load/theta_and_theta_load_match.cml @@ -1,19 +1,20 @@ - + - + + - + - + - + @@ -55,7 +56,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -68,12 +69,12 @@ - + - @@ -119,7 +120,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -129,7 +130,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -137,22 +138,23 @@ - + - + - + + - + - + - + @@ -194,7 +196,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -207,12 +209,12 @@ - + - @@ -258,7 +260,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -268,7 +270,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -276,6 +278,6 @@ - + diff --git a/lib/iris/tests/results/constrained_load/theta_and_theta_load_strict.cml b/lib/iris/tests/results/constrained_load/theta_and_theta_load_strict.cml index f2c84c6999..eadbe8f365 100644 --- a/lib/iris/tests/results/constrained_load/theta_and_theta_load_strict.cml +++ b/lib/iris/tests/results/constrained_load/theta_and_theta_load_strict.cml @@ -1,19 +1,20 @@ - + - + + - + - + - + @@ -55,7 +56,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -68,12 +69,12 @@ - + - @@ -119,7 +120,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -129,7 +130,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -137,22 +138,23 @@ - + - + - + + - + - + - + @@ -194,7 +196,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -207,12 +209,12 @@ - + - @@ -258,7 +260,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -268,7 +270,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -276,6 +278,6 @@ - + diff --git a/lib/iris/tests/results/constrained_load/theta_gt_30_le_3_load_match.cml b/lib/iris/tests/results/constrained_load/theta_gt_30_le_3_load_match.cml index d70cc1e42a..77534b9b55 100644 --- a/lib/iris/tests/results/constrained_load/theta_gt_30_le_3_load_match.cml +++ b/lib/iris/tests/results/constrained_load/theta_gt_30_le_3_load_match.cml @@ -1,19 +1,20 @@ - + - + + - + - + - + @@ -28,7 +29,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 19503.0, 20990.2, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 19503.0, 20990.2, 22626.1, 24458.3, 26583.6, 29219.1, 32908.7, 39254.8]" shape="(11,)" units="Unit('m')" value_type="float32"> @@ -37,12 +38,12 @@ - + - + @@ -59,11 +60,11 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.0, 0.0, 0.0, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(11,)" units="Unit('1')" value_type="float32"/> - + @@ -71,6 +72,6 @@ - + diff --git a/lib/iris/tests/results/constrained_load/theta_gt_30_le_3_load_strict.cml b/lib/iris/tests/results/constrained_load/theta_gt_30_le_3_load_strict.cml index d70cc1e42a..77534b9b55 100644 --- a/lib/iris/tests/results/constrained_load/theta_gt_30_le_3_load_strict.cml +++ b/lib/iris/tests/results/constrained_load/theta_gt_30_le_3_load_strict.cml @@ -1,19 +1,20 @@ - + - + + - + - + - + @@ -28,7 +29,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 19503.0, 20990.2, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 19503.0, 20990.2, 22626.1, 24458.3, 26583.6, 29219.1, 32908.7, 39254.8]" shape="(11,)" units="Unit('m')" value_type="float32"> @@ -37,12 +38,12 @@ - + - + @@ -59,11 +60,11 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.0, 0.0, 0.0, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(11,)" units="Unit('1')" value_type="float32"/> - + @@ -71,6 +72,6 @@ - + diff --git a/lib/iris/tests/results/constrained_load/theta_lat_30_load_match.cml b/lib/iris/tests/results/constrained_load/theta_lat_30_load_match.cml index 62d0f12b33..f6727427a1 100644 --- a/lib/iris/tests/results/constrained_load/theta_lat_30_load_match.cml +++ b/lib/iris/tests/results/constrained_load/theta_lat_30_load_match.cml @@ -1,19 +1,20 @@ - + - + + - + - + - + @@ -55,7 +56,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -68,12 +69,12 @@ - + - @@ -119,7 +120,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -129,7 +130,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -137,6 +138,6 @@ - + diff --git a/lib/iris/tests/results/constrained_load/theta_lat_30_load_strict.cml b/lib/iris/tests/results/constrained_load/theta_lat_30_load_strict.cml index 62d0f12b33..f6727427a1 100644 --- a/lib/iris/tests/results/constrained_load/theta_lat_30_load_strict.cml +++ b/lib/iris/tests/results/constrained_load/theta_lat_30_load_strict.cml @@ -1,19 +1,20 @@ - + - + + - + - + - + @@ -55,7 +56,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -68,12 +69,12 @@ - + - @@ -119,7 +120,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -129,7 +130,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -137,6 +138,6 @@ - + diff --git a/lib/iris/tests/results/constrained_load/theta_lat_gt_30_load_match.cml b/lib/iris/tests/results/constrained_load/theta_lat_gt_30_load_match.cml index 1371a0f290..daef7ba9dc 100644 --- a/lib/iris/tests/results/constrained_load/theta_lat_gt_30_load_match.cml +++ b/lib/iris/tests/results/constrained_load/theta_lat_gt_30_load_match.cml @@ -1,19 +1,20 @@ - + - + + - + - + - - + - @@ -124,7 +125,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -134,7 +135,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -142,6 +143,6 @@ - + diff --git a/lib/iris/tests/results/constrained_load/theta_lat_gt_30_load_strict.cml b/lib/iris/tests/results/constrained_load/theta_lat_gt_30_load_strict.cml index 1371a0f290..daef7ba9dc 100644 --- a/lib/iris/tests/results/constrained_load/theta_lat_gt_30_load_strict.cml +++ b/lib/iris/tests/results/constrained_load/theta_lat_gt_30_load_strict.cml @@ -1,19 +1,20 @@ - + - + + - + - + - - + - @@ -124,7 +125,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -134,7 +135,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -142,6 +143,6 @@ - + diff --git a/lib/iris/tests/results/constrained_load/theta_load_match.cml b/lib/iris/tests/results/constrained_load/theta_load_match.cml index 818c3d9846..293e40cc3a 100644 --- a/lib/iris/tests/results/constrained_load/theta_load_match.cml +++ b/lib/iris/tests/results/constrained_load/theta_load_match.cml @@ -1,19 +1,20 @@ - + - + + - + - + - + @@ -55,7 +56,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -68,12 +69,12 @@ - + - @@ -119,7 +120,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -129,7 +130,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -137,6 +138,6 @@ - + diff --git a/lib/iris/tests/results/constrained_load/theta_load_strict.cml b/lib/iris/tests/results/constrained_load/theta_load_strict.cml index 818c3d9846..293e40cc3a 100644 --- a/lib/iris/tests/results/constrained_load/theta_load_strict.cml +++ b/lib/iris/tests/results/constrained_load/theta_load_strict.cml @@ -1,19 +1,20 @@ - + - + + - + - + - + @@ -55,7 +56,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -68,12 +69,12 @@ - + - @@ -119,7 +120,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -129,7 +130,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -137,6 +138,6 @@ - + diff --git a/lib/iris/tests/results/coord_api/complex.xml b/lib/iris/tests/results/coord_api/complex.xml index e808387d9c..41adb2cb8d 100644 --- a/lib/iris/tests/results/coord_api/complex.xml +++ b/lib/iris/tests/results/coord_api/complex.xml @@ -2,7 +2,7 @@ + [2.5, 3.5]]" id="56772c5e" long_name="my_long_name" points="[0.0, 1.0, 2.0, 3.0]" shape="(4,)" standard_name="air_temperature" units="Unit('K')" value_type="float32"> diff --git a/lib/iris/tests/results/coord_api/coord_maths/add_float_expl.xml b/lib/iris/tests/results/coord_api/coord_maths/add_float_expl.xml index aac98b3b81..7eaf699f2d 100644 --- a/lib/iris/tests/results/coord_api/coord_maths/add_float_expl.xml +++ b/lib/iris/tests/results/coord_api/coord_maths/add_float_expl.xml @@ -18,7 +18,7 @@ [45.971, 48.271], [48.271, 50.571], [50.571, 52.871], - [52.871, 55.171]]" id="c7efdd09" points="[10.321, 12.621, 14.921, 17.221, 19.521, 21.821, + [52.871, 55.171]]" id="4a0cb9d8" points="[10.321, 12.621, 14.921, 17.221, 19.521, 21.821, 24.121, 26.421, 28.721, 31.021, 33.321, 35.621, 37.921, 40.221, 42.521, 44.821, 47.121, 49.421, 51.721, 54.021]" shape="(20,)" standard_name="latitude" units="Unit('degrees')" value_type="float32"/> diff --git a/lib/iris/tests/results/coord_api/coord_maths/add_simple_expl.xml b/lib/iris/tests/results/coord_api/coord_maths/add_simple_expl.xml index 280cb5132b..9bedff935b 100644 --- a/lib/iris/tests/results/coord_api/coord_maths/add_simple_expl.xml +++ b/lib/iris/tests/results/coord_api/coord_maths/add_simple_expl.xml @@ -18,6 +18,6 @@ [45.65, 47.95], [47.95, 50.25], [50.25, 52.55], - [52.55, 54.85]]" id="c7efdd09" points="[10.0, 12.3, 14.6, 16.9, 19.2, 21.5, 23.8, 26.1, + [52.55, 54.85]]" id="4a0cb9d8" points="[10.0, 12.3, 14.6, 16.9, 19.2, 21.5, 23.8, 26.1, 28.4, 30.7, 33.0, 35.3, 37.6, 39.9, 42.2, 44.5, 46.8, 49.1, 51.4, 53.7]" shape="(20,)" standard_name="latitude" units="Unit('degrees')" value_type="float32"/> diff --git a/lib/iris/tests/results/coord_api/coord_maths/divide_simple_expl.xml b/lib/iris/tests/results/coord_api/coord_maths/divide_simple_expl.xml index fab888e513..28c01a0f00 100644 --- a/lib/iris/tests/results/coord_api/coord_maths/divide_simple_expl.xml +++ b/lib/iris/tests/results/coord_api/coord_maths/divide_simple_expl.xml @@ -18,6 +18,6 @@ [3.565, 3.795], [3.795, 4.025], [4.025, 4.255], - [4.255, 4.485]]" id="c7efdd09" points="[0.0, 0.23, 0.46, 0.69, 0.92, 1.15, 1.38, 1.61, + [4.255, 4.485]]" id="4a0cb9d8" points="[0.0, 0.23, 0.46, 0.69, 0.92, 1.15, 1.38, 1.61, 1.84, 2.07, 2.3, 2.53, 2.76, 2.99, 3.22, 3.45, 3.68, 3.91, 4.14, 4.37]" shape="(20,)" standard_name="latitude" units="Unit('degrees')" value_type="float32"/> diff --git a/lib/iris/tests/results/coord_api/coord_maths/mult_float_expl.xml b/lib/iris/tests/results/coord_api/coord_maths/mult_float_expl.xml index 5d8159e6e4..77107b9906 100644 --- a/lib/iris/tests/results/coord_api/coord_maths/mult_float_expl.xml +++ b/lib/iris/tests/results/coord_api/coord_maths/mult_float_expl.xml @@ -18,7 +18,7 @@ [367.944, 391.682], [391.682, 415.42], [415.42, 439.159], - [439.159, 462.897]]" id="c7efdd09" points="[0.0, 23.7383, 47.4766, 71.2149, 94.9532, + [439.159, 462.897]]" id="4a0cb9d8" points="[0.0, 23.7383, 47.4766, 71.2149, 94.9532, 118.691, 142.43, 166.168, 189.906, 213.645, 237.383, 261.121, 284.86, 308.598, 332.336, 356.074, 379.813, 403.551, 427.289, 451.028]" shape="(20,)" standard_name="latitude" units="Unit('degrees')" value_type="float32"/> diff --git a/lib/iris/tests/results/coord_api/coord_maths/multiply_simple_expl.xml b/lib/iris/tests/results/coord_api/coord_maths/multiply_simple_expl.xml index 3cf5bbf29c..27f98a31ff 100644 --- a/lib/iris/tests/results/coord_api/coord_maths/multiply_simple_expl.xml +++ b/lib/iris/tests/results/coord_api/coord_maths/multiply_simple_expl.xml @@ -18,6 +18,6 @@ [356.5, 379.5], [379.5, 402.5], [402.5, 425.5], - [425.5, 448.5]]" id="c7efdd09" points="[0.0, 23.0, 46.0, 69.0, 92.0, 115.0, 138.0, + [425.5, 448.5]]" id="4a0cb9d8" points="[0.0, 23.0, 46.0, 69.0, 92.0, 115.0, 138.0, 161.0, 184.0, 207.0, 230.0, 253.0, 276.0, 299.0, 322.0, 345.0, 368.0, 391.0, 414.0, 437.0]" shape="(20,)" standard_name="latitude" units="Unit('degrees')" value_type="float32"/> diff --git a/lib/iris/tests/results/coord_api/coord_maths/negate_expl.xml b/lib/iris/tests/results/coord_api/coord_maths/negate_expl.xml index 324c6d4333..33a63e1f03 100644 --- a/lib/iris/tests/results/coord_api/coord_maths/negate_expl.xml +++ b/lib/iris/tests/results/coord_api/coord_maths/negate_expl.xml @@ -18,6 +18,6 @@ [-43.65, -45.95], [-45.95, -48.25], [-48.25, -50.55], - [-50.55, -52.85]]" id="c7efdd09" points="[-8.0, -10.3, -12.6, -14.9, -17.2, -19.5, -21.8, + [-50.55, -52.85]]" id="4a0cb9d8" points="[-8.0, -10.3, -12.6, -14.9, -17.2, -19.5, -21.8, -24.1, -26.4, -28.7, -31.0, -33.3, -35.6, -37.9, -40.2, -42.5, -44.8, -47.1, -49.4, -51.7]" shape="(20,)" standard_name="latitude" units="Unit('degrees')" value_type="float32"/> diff --git a/lib/iris/tests/results/coord_api/coord_maths/r_subtract_simple_exl.xml b/lib/iris/tests/results/coord_api/coord_maths/r_subtract_simple_exl.xml index 9267a4017f..95b9efef7a 100644 --- a/lib/iris/tests/results/coord_api/coord_maths/r_subtract_simple_exl.xml +++ b/lib/iris/tests/results/coord_api/coord_maths/r_subtract_simple_exl.xml @@ -18,6 +18,6 @@ [-25.65, -27.95], [-27.95, -30.25], [-30.25, -32.55], - [-32.55, -34.85]]" id="c7efdd09" points="[10.0, 7.7, 5.4, 3.1, 0.8, -1.5, -3.8, -6.1, + [-32.55, -34.85]]" id="4a0cb9d8" points="[10.0, 7.7, 5.4, 3.1, 0.8, -1.5, -3.8, -6.1, -8.4, -10.7, -13.0, -15.3, -17.6, -19.9, -22.2, -24.5, -26.8, -29.1, -31.4, -33.7]" shape="(20,)" standard_name="latitude" units="Unit('degrees')" value_type="float32"/> diff --git a/lib/iris/tests/results/coord_api/coord_maths/right_divide_simple_expl.xml b/lib/iris/tests/results/coord_api/coord_maths/right_divide_simple_expl.xml index 7be2e08742..00e932cf21 100644 --- a/lib/iris/tests/results/coord_api/coord_maths/right_divide_simple_expl.xml +++ b/lib/iris/tests/results/coord_api/coord_maths/right_divide_simple_expl.xml @@ -18,7 +18,7 @@ [0.0219058, 0.0208551], [0.0208551, 0.0199005], [0.0199005, 0.0190295], - [0.0190295, 0.0182315]]" id="c7efdd09" points="[0.1, 0.0813008, 0.0684932, 0.0591716, 0.0520833, + [0.0190295, 0.0182315]]" id="4a0cb9d8" points="[0.1, 0.0813008, 0.0684932, 0.0591716, 0.0520833, 0.0465116, 0.0420168, 0.0383142, 0.0352113, 0.0325733, 0.030303, 0.0283286, 0.0265957, 0.0250627, 0.0236967, 0.0224719, 0.0213675, diff --git a/lib/iris/tests/results/coord_api/coord_maths/subtract_simple_expl.xml b/lib/iris/tests/results/coord_api/coord_maths/subtract_simple_expl.xml index 32d49848aa..7f9ba5e097 100644 --- a/lib/iris/tests/results/coord_api/coord_maths/subtract_simple_expl.xml +++ b/lib/iris/tests/results/coord_api/coord_maths/subtract_simple_expl.xml @@ -18,6 +18,6 @@ [25.65, 27.95], [27.95, 30.25], [30.25, 32.55], - [32.55, 34.85]]" id="c7efdd09" points="[-10.0, -7.7, -5.4, -3.1, -0.8, 1.5, 3.8, 6.1, + [32.55, 34.85]]" id="4a0cb9d8" points="[-10.0, -7.7, -5.4, -3.1, -0.8, 1.5, 3.8, 6.1, 8.4, 10.7, 13.0, 15.3, 17.6, 19.9, 22.2, 24.5, 26.8, 29.1, 31.4, 33.7]" shape="(20,)" standard_name="latitude" units="Unit('degrees')" value_type="float32"/> diff --git a/lib/iris/tests/results/coord_api/intersection.xml b/lib/iris/tests/results/coord_api/intersection.xml index d042d1dad6..5c48c52872 100644 --- a/lib/iris/tests/results/coord_api/intersection.xml +++ b/lib/iris/tests/results/coord_api/intersection.xml @@ -6,4 +6,4 @@ [18.75, 21.75], [21.75, 24.75], [24.75, 27.75], - [27.75, 30.75]]" id="ce47d1d8" long_name="foo" points="[9.0, 12.0, 15.0, 18.0, 21.0, 24.0, 27.0, 30.0]" shape="(8,)" units="Unit('meter')" value_type="float32"/> + [27.75, 30.75]]" id="43cd7f4a" long_name="foo" points="[9.0, 12.0, 15.0, 18.0, 21.0, 24.0, 27.0, 30.0]" shape="(8,)" units="Unit('meter')" value_type="float32"/> diff --git a/lib/iris/tests/results/coord_api/intersection_missing.xml b/lib/iris/tests/results/coord_api/intersection_missing.xml index 82d73eb3d3..6336180833 100644 --- a/lib/iris/tests/results/coord_api/intersection_missing.xml +++ b/lib/iris/tests/results/coord_api/intersection_missing.xml @@ -5,4 +5,4 @@ [18.75, 21.75], [21.75, 24.75], [24.75, 27.75], - [27.75, 30.75]]" id="ce47d1d8" long_name="foo" points="[9.0, 12.0, 18.0, 21.0, 24.0, 27.0, 30.0]" shape="(7,)" units="Unit('meter')" value_type="float32"/> + [27.75, 30.75]]" id="43cd7f4a" long_name="foo" points="[9.0, 12.0, 18.0, 21.0, 24.0, 27.0, 30.0]" shape="(7,)" units="Unit('meter')" value_type="float32"/> diff --git a/lib/iris/tests/results/coord_api/intersection_reversed.xml b/lib/iris/tests/results/coord_api/intersection_reversed.xml index 7abc791f04..b966a09b54 100644 --- a/lib/iris/tests/results/coord_api/intersection_reversed.xml +++ b/lib/iris/tests/results/coord_api/intersection_reversed.xml @@ -6,4 +6,4 @@ [15.75, 18.75], [12.75, 15.75], [9.75, 12.75], - [6.75, 9.75]]" id="ce47d1d8" long_name="foo" points="[30.0, 27.0, 24.0, 21.0, 18.0, 15.0, 12.0, 9.0]" shape="(8,)" units="Unit('meter')" value_type="float32"/> + [6.75, 9.75]]" id="43cd7f4a" long_name="foo" points="[30.0, 27.0, 24.0, 21.0, 18.0, 15.0, 12.0, 9.0]" shape="(8,)" units="Unit('meter')" value_type="float32"/> diff --git a/lib/iris/tests/results/coord_api/minimal.xml b/lib/iris/tests/results/coord_api/minimal.xml index b9e416876f..a35c93dc68 100644 --- a/lib/iris/tests/results/coord_api/minimal.xml +++ b/lib/iris/tests/results/coord_api/minimal.xml @@ -1,2 +1,2 @@ - + diff --git a/lib/iris/tests/results/coord_api/nd_bounds.cml b/lib/iris/tests/results/coord_api/nd_bounds.cml index 6737a76efb..5c416af25b 100644 --- a/lib/iris/tests/results/coord_api/nd_bounds.cml +++ b/lib/iris/tests/results/coord_api/nd_bounds.cml @@ -1,12 +1,12 @@ - + - + - + @@ -15,6 +15,6 @@ - + diff --git a/lib/iris/tests/results/coord_api/str_repr/aux_time_repr.txt b/lib/iris/tests/results/coord_api/str_repr/aux_time_repr.txt index 59da7508e1..120546311f 100644 --- a/lib/iris/tests/results/coord_api/str_repr/aux_time_repr.txt +++ b/lib/iris/tests/results/coord_api/str_repr/aux_time_repr.txt @@ -1,2 +1,2 @@ -DimCoord(array([ 347921.16666667, 347921.33333333, 347921.5 , - 347921.66666666, 347921.83333333, 347922. ]), standard_name='time', units=Unit('hours since 1970-01-01 00:00:00', calendar='gregorian')) \ No newline at end of file +DimCoord(array([347921.16666667, 347921.33333333, 347921.5 , 347921.66666666, + 347921.83333333, 347922. ]), standard_name='time', units=Unit('hours since 1970-01-01 00:00:00', calendar='gregorian')) \ No newline at end of file diff --git a/lib/iris/tests/results/coord_api/str_repr/dim_time_repr.txt b/lib/iris/tests/results/coord_api/str_repr/dim_time_repr.txt index 59da7508e1..120546311f 100644 --- a/lib/iris/tests/results/coord_api/str_repr/dim_time_repr.txt +++ b/lib/iris/tests/results/coord_api/str_repr/dim_time_repr.txt @@ -1,2 +1,2 @@ -DimCoord(array([ 347921.16666667, 347921.33333333, 347921.5 , - 347921.66666666, 347921.83333333, 347922. ]), standard_name='time', units=Unit('hours since 1970-01-01 00:00:00', calendar='gregorian')) \ No newline at end of file +DimCoord(array([347921.16666667, 347921.33333333, 347921.5 , 347921.66666666, + 347921.83333333, 347922. ]), standard_name='time', units=Unit('hours since 1970-01-01 00:00:00', calendar='gregorian')) \ No newline at end of file diff --git a/lib/iris/tests/results/coord_systems/Mercator.xml b/lib/iris/tests/results/coord_systems/Mercator.xml new file mode 100644 index 0000000000..e8036ef824 --- /dev/null +++ b/lib/iris/tests/results/coord_systems/Mercator.xml @@ -0,0 +1,2 @@ + + diff --git a/lib/iris/tests/results/coord_systems/Stereographic.xml b/lib/iris/tests/results/coord_systems/Stereographic.xml new file mode 100644 index 0000000000..bb12cd94cc --- /dev/null +++ b/lib/iris/tests/results/coord_systems/Stereographic.xml @@ -0,0 +1,2 @@ + + diff --git a/lib/iris/tests/results/cube_collapsed/latitude_longitude_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/latitude_longitude_dual_stage.cml index 5f5f4bfd82..458b9bf908 100644 --- a/lib/iris/tests/results/cube_collapsed/latitude_longitude_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/latitude_longitude_dual_stage.cml @@ -1,20 +1,20 @@ - + - + - + - + @@ -25,7 +25,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -45,7 +45,7 @@ - - @@ -93,6 +93,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/latitude_longitude_dual_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/latitude_longitude_dual_stage.data.0.json new file mode 100644 index 0000000000..f11ebfcb0e --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/latitude_longitude_dual_stage.data.0.json @@ -0,0 +1 @@ +{"std": 183.20155135161352, "min": 286.57607421875002, "max": 1326.6421875000001, "shape": [6, 70], "masked": false, "mean": 368.57896210007442} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/latitude_longitude_dual_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/latitude_longitude_dual_stage.data.0.npy deleted file mode 100644 index aeb34aa664..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/latitude_longitude_dual_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/latitude_longitude_single_stage.cml b/lib/iris/tests/results/cube_collapsed/latitude_longitude_single_stage.cml index fcf2598221..a2f12b0b27 100644 --- a/lib/iris/tests/results/cube_collapsed/latitude_longitude_single_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/latitude_longitude_single_stage.cml @@ -1,20 +1,20 @@ - + - + - + - + @@ -25,7 +25,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -45,7 +45,7 @@ - - @@ -91,6 +91,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/latitude_longitude_single_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/latitude_longitude_single_stage.data.0.json new file mode 100644 index 0000000000..a445b7223a --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/latitude_longitude_single_stage.data.0.json @@ -0,0 +1 @@ +{"std": 183.20154787243786, "min": 286.5760498046875, "max": 1326.642333984375, "shape": [6, 70], "masked": false, "mean": 368.57894345238094} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/latitude_longitude_single_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/latitude_longitude_single_stage.data.0.npy deleted file mode 100644 index 0f99d6627c..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/latitude_longitude_single_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_dual_stage.cml index af3a0afb5a..60539d5960 100644 --- a/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_dual_stage.cml @@ -1,15 +1,15 @@ - + - + - + @@ -20,30 +20,30 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> - + - + - + - @@ -55,6 +55,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_dual_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_dual_stage.data.0.json new file mode 100644 index 0000000000..832fb203ca --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_dual_stage.data.0.json @@ -0,0 +1 @@ +{"std": 0.070972059805802012, "min": 368.37784598214284, "max": 368.75493861607146, "shape": [6, 100], "masked": false, "mean": 368.57896214657734} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_dual_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_dual_stage.data.0.npy deleted file mode 100644 index 4acb36e6d7..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_dual_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_single_stage.cml b/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_single_stage.cml index 6ecba790c7..466d0dd8cd 100644 --- a/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_single_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_single_stage.cml @@ -1,15 +1,15 @@ - + - + - + @@ -20,30 +20,30 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> - + - + - + - @@ -53,6 +53,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_single_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_single_stage.data.0.json new file mode 100644 index 0000000000..58a526eb58 --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_single_stage.data.0.json @@ -0,0 +1 @@ +{"std": 0.070973517507074896, "min": 368.3778076171875, "max": 368.7548828125, "shape": [6, 100], "masked": false, "mean": 368.57895833333333} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_single_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_single_stage.data.0.npy deleted file mode 100644 index a2a7c5ca10..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_single_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/latitude_time_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/latitude_time_dual_stage.cml index 7574983847..12bf9270d1 100644 --- a/lib/iris/tests/results/cube_collapsed/latitude_time_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/latitude_time_dual_stage.cml @@ -1,15 +1,15 @@ - + - + - + @@ -20,7 +20,7 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> @@ -32,7 +32,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -52,7 +52,7 @@ - - + @@ -99,6 +99,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/latitude_time_dual_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/latitude_time_dual_stage.data.0.json new file mode 100644 index 0000000000..5449d87a3a --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/latitude_time_dual_stage.data.0.json @@ -0,0 +1 @@ +{"std": 183.20140423648354, "min": 286.94415283203125, "max": 1326.8153483072917, "shape": [70, 100], "masked": false, "mean": 368.5789633527483} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/latitude_time_dual_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/latitude_time_dual_stage.data.0.npy deleted file mode 100644 index fb8204d385..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/latitude_time_dual_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/latitude_time_single_stage.cml b/lib/iris/tests/results/cube_collapsed/latitude_time_single_stage.cml index 4dbfcdfc24..9d1070140b 100644 --- a/lib/iris/tests/results/cube_collapsed/latitude_time_single_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/latitude_time_single_stage.cml @@ -1,15 +1,15 @@ - + - + - + @@ -20,7 +20,7 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> @@ -32,7 +32,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -52,7 +52,7 @@ - - + @@ -97,6 +97,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/latitude_time_single_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/latitude_time_single_stage.data.0.json new file mode 100644 index 0000000000..e1b7a903cd --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/latitude_time_single_stage.data.0.json @@ -0,0 +1 @@ +{"std": 183.20140361283885, "min": 286.94415283203125, "max": 1326.8154296875, "shape": [70, 100], "masked": false, "mean": 368.57896428571428} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/latitude_time_single_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/latitude_time_single_stage.data.0.npy deleted file mode 100644 index 6b8c8f3f49..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/latitude_time_single_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/longitude_latitude_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/longitude_latitude_dual_stage.cml index d77f0eeb92..4cd9da34f0 100644 --- a/lib/iris/tests/results/cube_collapsed/longitude_latitude_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/longitude_latitude_dual_stage.cml @@ -1,20 +1,20 @@ - + - + - + - + @@ -25,7 +25,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -45,7 +45,7 @@ - - @@ -93,6 +93,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/longitude_latitude_dual_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/longitude_latitude_dual_stage.data.0.json new file mode 100644 index 0000000000..6e4a2b64d8 --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/longitude_latitude_dual_stage.data.0.json @@ -0,0 +1 @@ +{"std": 183.20155278295425, "min": 286.5760546875, "max": 1326.6421875000001, "shape": [6, 70], "masked": false, "mean": 368.57896330915179} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/longitude_latitude_dual_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/longitude_latitude_dual_stage.data.0.npy deleted file mode 100644 index deade421fe..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/longitude_latitude_dual_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/longitude_latitude_single_stage.cml b/lib/iris/tests/results/cube_collapsed/longitude_latitude_single_stage.cml index a035898567..dd87dc175b 100644 --- a/lib/iris/tests/results/cube_collapsed/longitude_latitude_single_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/longitude_latitude_single_stage.cml @@ -1,20 +1,20 @@ - + - + - + - + @@ -25,7 +25,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -45,7 +45,7 @@ - - @@ -91,6 +91,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/longitude_latitude_single_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/longitude_latitude_single_stage.data.0.json new file mode 100644 index 0000000000..a445b7223a --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/longitude_latitude_single_stage.data.0.json @@ -0,0 +1 @@ +{"std": 183.20154787243786, "min": 286.5760498046875, "max": 1326.642333984375, "shape": [6, 70], "masked": false, "mean": 368.57894345238094} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/longitude_latitude_single_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/longitude_latitude_single_stage.data.0.npy deleted file mode 100644 index 8a7246504c..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/longitude_latitude_single_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_dual_stage.cml index c2ff73c8bc..16ea40c33e 100644 --- a/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_dual_stage.cml @@ -1,12 +1,12 @@ - + - + - + - + - + - + - @@ -55,6 +55,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_dual_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_dual_stage.data.0.json new file mode 100644 index 0000000000..bb97090248 --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_dual_stage.data.0.json @@ -0,0 +1 @@ +{"std": 0.076507800752643393, "min": 368.36489955357143, "max": 368.74302455357144, "shape": [6, 100], "masked": false, "mean": 368.57896340215774} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_dual_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_dual_stage.data.0.npy deleted file mode 100644 index c1df2dc58a..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_dual_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_single_stage.cml b/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_single_stage.cml index b0228c3e70..b01ede7936 100644 --- a/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_single_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_single_stage.cml @@ -1,12 +1,12 @@ - + - + - + - + - + - + - @@ -53,6 +53,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_single_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_single_stage.data.0.json new file mode 100644 index 0000000000..30735c3d89 --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_single_stage.data.0.json @@ -0,0 +1 @@ +{"std": 0.076507733018594218, "min": 368.36489868164062, "max": 368.7430419921875, "shape": [6, 100], "masked": false, "mean": 368.57895833333333} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_single_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_single_stage.data.0.npy deleted file mode 100644 index de4ab908f3..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_single_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/longitude_time_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/longitude_time_dual_stage.cml index cc467aa07d..8d38bb748c 100644 --- a/lib/iris/tests/results/cube_collapsed/longitude_time_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/longitude_time_dual_stage.cml @@ -1,12 +1,12 @@ - + - + - + @@ -32,7 +32,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -52,7 +52,7 @@ - - + @@ -99,6 +99,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/longitude_time_dual_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/longitude_time_dual_stage.data.0.json new file mode 100644 index 0000000000..93f878ca6d --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/longitude_time_dual_stage.data.0.json @@ -0,0 +1 @@ +{"std": 183.20142290782221, "min": 287.06424967447919, "max": 1327.0152180989583, "shape": [70, 100], "masked": false, "mean": 368.57896332077746} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/longitude_time_dual_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/longitude_time_dual_stage.data.0.npy deleted file mode 100644 index b95d08eab5..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/longitude_time_dual_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/longitude_time_single_stage.cml b/lib/iris/tests/results/cube_collapsed/longitude_time_single_stage.cml index d746e64778..f4589831a8 100644 --- a/lib/iris/tests/results/cube_collapsed/longitude_time_single_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/longitude_time_single_stage.cml @@ -1,12 +1,12 @@ - + - + - + @@ -32,7 +32,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -52,7 +52,7 @@ - - + @@ -97,6 +97,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/longitude_time_single_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/longitude_time_single_stage.data.0.json new file mode 100644 index 0000000000..18229f33f6 --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/longitude_time_single_stage.data.0.json @@ -0,0 +1 @@ +{"std": 183.20142856585872, "min": 287.06423950195312, "max": 1327.0152587890625, "shape": [70, 100], "masked": false, "mean": 368.57896428571428} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/longitude_time_single_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/longitude_time_single_stage.data.0.npy deleted file mode 100644 index afa26f763c..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/longitude_time_single_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_dual_stage.cml index f94b66c9d5..138e0207c7 100644 --- a/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_dual_stage.cml @@ -1,15 +1,15 @@ - + - + - + @@ -20,30 +20,30 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> - + - + - + - @@ -55,6 +55,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_dual_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_dual_stage.data.0.json new file mode 100644 index 0000000000..af4d75a782 --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_dual_stage.data.0.json @@ -0,0 +1 @@ +{"std": 0.070973870961262162, "min": 368.3778125, "max": 368.7548828125, "shape": [6, 100], "masked": false, "mean": 368.57896432291665} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_dual_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_dual_stage.data.0.npy deleted file mode 100644 index a55d42ea73..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_dual_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_single_stage.cml b/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_single_stage.cml index 6ebd8469c2..0e2cf8ef23 100644 --- a/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_single_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_single_stage.cml @@ -1,15 +1,15 @@ - + - + - + @@ -20,30 +20,30 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> - + - + - + - @@ -53,6 +53,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_single_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_single_stage.data.0.json new file mode 100644 index 0000000000..58a526eb58 --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_single_stage.data.0.json @@ -0,0 +1 @@ +{"std": 0.070973517507074896, "min": 368.3778076171875, "max": 368.7548828125, "shape": [6, 100], "masked": false, "mean": 368.57895833333333} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_single_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_single_stage.data.0.npy deleted file mode 100644 index 93a972e4a9..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_single_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_dual_stage.cml index 4d41779307..bbc8272c65 100644 --- a/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_dual_stage.cml @@ -1,12 +1,12 @@ - + - + - + - + - + - + - @@ -55,6 +55,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_dual_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_dual_stage.data.0.json new file mode 100644 index 0000000000..7f2966f46c --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_dual_stage.data.0.json @@ -0,0 +1 @@ +{"std": 0.076508496136123455, "min": 368.36492187499999, "max": 368.743046875, "shape": [6, 100], "masked": false, "mean": 368.57896223958329} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_dual_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_dual_stage.data.0.npy deleted file mode 100644 index e472a606f3..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_dual_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_single_stage.cml b/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_single_stage.cml index c1ef855d9d..ba5cd7a171 100644 --- a/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_single_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_single_stage.cml @@ -1,12 +1,12 @@ - + - + - + - + - + - + - @@ -53,6 +53,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_single_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_single_stage.data.0.json new file mode 100644 index 0000000000..30735c3d89 --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_single_stage.data.0.json @@ -0,0 +1 @@ +{"std": 0.076507733018594218, "min": 368.36489868164062, "max": 368.7430419921875, "shape": [6, 100], "masked": false, "mean": 368.57895833333333} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_single_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_single_stage.data.0.npy deleted file mode 100644 index b910549a56..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_single_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_time_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/model_level_number_time_dual_stage.cml index e476f70910..b835be4057 100644 --- a/lib/iris/tests/results/cube_collapsed/model_level_number_time_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/model_level_number_time_dual_stage.cml @@ -1,12 +1,12 @@ - + - + @@ -27,30 +27,30 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> - + - + - + - + @@ -61,6 +61,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_time_dual_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/model_level_number_time_dual_stage.data.0.json new file mode 100644 index 0000000000..f80cff4af1 --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/model_level_number_time_dual_stage.data.0.json @@ -0,0 +1 @@ +{"std": 0.1376022048268124, "min": 368.2593994140625, "max": 369.01175944010419, "shape": [100, 100], "masked": false, "mean": 368.57896353352874} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_time_dual_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/model_level_number_time_dual_stage.data.0.npy deleted file mode 100644 index 81ca71d092..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/model_level_number_time_dual_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_time_single_stage.cml b/lib/iris/tests/results/cube_collapsed/model_level_number_time_single_stage.cml index bb7ca7f96d..93196268e7 100644 --- a/lib/iris/tests/results/cube_collapsed/model_level_number_time_single_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/model_level_number_time_single_stage.cml @@ -1,12 +1,12 @@ - + - + @@ -27,30 +27,30 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> - + - + - + - + @@ -59,6 +59,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_time_single_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/model_level_number_time_single_stage.data.0.json new file mode 100644 index 0000000000..c3f9dbb06a --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/model_level_number_time_single_stage.data.0.json @@ -0,0 +1 @@ +{"std": 0.13760229016549494, "min": 368.2593994140625, "max": 369.01174926757812, "shape": [100, 100], "masked": false, "mean": 368.57897500000001} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_time_single_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/model_level_number_time_single_stage.data.0.npy deleted file mode 100644 index 9a5e8b1ede..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/model_level_number_time_single_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/original.cml b/lib/iris/tests/results/cube_collapsed/original.cml index 3069b08306..10a81f21d2 100644 --- a/lib/iris/tests/results/cube_collapsed/original.cml +++ b/lib/iris/tests/results/cube_collapsed/original.cml @@ -1,12 +1,12 @@ - + - + @@ -27,7 +27,7 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> @@ -39,7 +39,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -59,7 +59,7 @@ - - - + diff --git a/lib/iris/tests/results/cube_collapsed/time_latitude_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/time_latitude_dual_stage.cml index 29a719292a..a4f2cc6084 100644 --- a/lib/iris/tests/results/cube_collapsed/time_latitude_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/time_latitude_dual_stage.cml @@ -1,15 +1,15 @@ - + - + - + @@ -20,7 +20,7 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> @@ -32,7 +32,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -52,7 +52,7 @@ - - + @@ -99,6 +99,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/time_latitude_dual_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/time_latitude_dual_stage.data.0.json new file mode 100644 index 0000000000..0ed0e500a2 --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/time_latitude_dual_stage.data.0.json @@ -0,0 +1 @@ +{"std": 183.20140556610502, "min": 286.94416015625001, "max": 1326.81546875, "shape": [70, 100], "masked": false, "mean": 368.57896378906258} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/time_latitude_dual_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/time_latitude_dual_stage.data.0.npy deleted file mode 100644 index b102725174..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/time_latitude_dual_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/time_latitude_single_stage.cml b/lib/iris/tests/results/cube_collapsed/time_latitude_single_stage.cml index cf2e38e34e..885328a856 100644 --- a/lib/iris/tests/results/cube_collapsed/time_latitude_single_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/time_latitude_single_stage.cml @@ -1,15 +1,15 @@ - + - + - + @@ -20,7 +20,7 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> @@ -32,7 +32,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -52,7 +52,7 @@ - - + @@ -97,6 +97,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/time_latitude_single_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/time_latitude_single_stage.data.0.json new file mode 100644 index 0000000000..e1b7a903cd --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/time_latitude_single_stage.data.0.json @@ -0,0 +1 @@ +{"std": 183.20140361283885, "min": 286.94415283203125, "max": 1326.8154296875, "shape": [70, 100], "masked": false, "mean": 368.57896428571428} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/time_latitude_single_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/time_latitude_single_stage.data.0.npy deleted file mode 100644 index 01ab0da11a..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/time_latitude_single_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/time_longitude_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/time_longitude_dual_stage.cml index 08205073a0..273ad909d9 100644 --- a/lib/iris/tests/results/cube_collapsed/time_longitude_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/time_longitude_dual_stage.cml @@ -1,12 +1,12 @@ - + - + - + @@ -32,7 +32,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -52,7 +52,7 @@ - - + @@ -99,6 +99,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/time_longitude_dual_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/time_longitude_dual_stage.data.0.json new file mode 100644 index 0000000000..efbcabc89d --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/time_longitude_dual_stage.data.0.json @@ -0,0 +1 @@ +{"std": 183.20142267719854, "min": 287.06423828125003, "max": 1327.0153124999999, "shape": [70, 100], "masked": false, "mean": 368.57896318080356} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/time_longitude_dual_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/time_longitude_dual_stage.data.0.npy deleted file mode 100644 index 197a221272..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/time_longitude_dual_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/time_longitude_single_stage.cml b/lib/iris/tests/results/cube_collapsed/time_longitude_single_stage.cml index 2df2743bd2..c2e2993874 100644 --- a/lib/iris/tests/results/cube_collapsed/time_longitude_single_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/time_longitude_single_stage.cml @@ -1,12 +1,12 @@ - + - + - + @@ -32,7 +32,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -52,7 +52,7 @@ - - + @@ -97,6 +97,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/time_longitude_single_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/time_longitude_single_stage.data.0.json new file mode 100644 index 0000000000..18229f33f6 --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/time_longitude_single_stage.data.0.json @@ -0,0 +1 @@ +{"std": 183.20142856585872, "min": 287.06423950195312, "max": 1327.0152587890625, "shape": [70, 100], "masked": false, "mean": 368.57896428571428} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/time_longitude_single_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/time_longitude_single_stage.data.0.npy deleted file mode 100644 index f8da8ad229..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/time_longitude_single_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/time_model_level_number_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/time_model_level_number_dual_stage.cml index 14dc01ad6f..4d6e85f8a8 100644 --- a/lib/iris/tests/results/cube_collapsed/time_model_level_number_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/time_model_level_number_dual_stage.cml @@ -1,12 +1,12 @@ - + - + @@ -27,30 +27,30 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> - + - + - + - + @@ -61,6 +61,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/time_model_level_number_dual_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/time_model_level_number_dual_stage.data.0.json new file mode 100644 index 0000000000..6e807b0359 --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/time_model_level_number_dual_stage.data.0.json @@ -0,0 +1 @@ +{"std": 0.13760184846046464, "min": 368.25937499999998, "max": 369.01171875, "shape": [100, 100], "masked": false, "mean": 368.5789632645089} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/time_model_level_number_dual_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/time_model_level_number_dual_stage.data.0.npy deleted file mode 100644 index d87b1cb89f..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/time_model_level_number_dual_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/time_model_level_number_single_stage.cml b/lib/iris/tests/results/cube_collapsed/time_model_level_number_single_stage.cml index fa57c1a4e4..8f7ccf9b8a 100644 --- a/lib/iris/tests/results/cube_collapsed/time_model_level_number_single_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/time_model_level_number_single_stage.cml @@ -1,12 +1,12 @@ - + - + @@ -27,30 +27,30 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> - + - + - + - + @@ -59,6 +59,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/time_model_level_number_single_stage.data.0.json b/lib/iris/tests/results/cube_collapsed/time_model_level_number_single_stage.data.0.json new file mode 100644 index 0000000000..c3f9dbb06a --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/time_model_level_number_single_stage.data.0.json @@ -0,0 +1 @@ +{"std": 0.13760229016549494, "min": 368.2593994140625, "max": 369.01174926757812, "shape": [100, 100], "masked": false, "mean": 368.57897500000001} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/time_model_level_number_single_stage.data.0.npy b/lib/iris/tests/results/cube_collapsed/time_model_level_number_single_stage.data.0.npy deleted file mode 100644 index 05888551f9..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/time_model_level_number_single_stage.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/triple_collapse_lat_ml_pt.cml b/lib/iris/tests/results/cube_collapsed/triple_collapse_lat_ml_pt.cml index 13b8f22e88..33b35b7eaa 100644 --- a/lib/iris/tests/results/cube_collapsed/triple_collapse_lat_ml_pt.cml +++ b/lib/iris/tests/results/cube_collapsed/triple_collapse_lat_ml_pt.cml @@ -1,15 +1,15 @@ - + - + - + @@ -20,30 +20,30 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> - + - + - + - + @@ -53,6 +53,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/triple_collapse_lat_ml_pt.data.0.json b/lib/iris/tests/results/cube_collapsed/triple_collapse_lat_ml_pt.data.0.json new file mode 100644 index 0000000000..feae7837db --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/triple_collapse_lat_ml_pt.data.0.json @@ -0,0 +1 @@ +{"std": 0.048989868829430488, "min": 368.46124267578125, "max": 368.68606567382812, "shape": [100], "masked": false, "mean": 368.57249999999999} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/triple_collapse_lat_ml_pt.data.0.npy b/lib/iris/tests/results/cube_collapsed/triple_collapse_lat_ml_pt.data.0.npy deleted file mode 100644 index 0754ae5809..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/triple_collapse_lat_ml_pt.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_collapsed/triple_collapse_ml_pt_lon.cml b/lib/iris/tests/results/cube_collapsed/triple_collapse_ml_pt_lon.cml index aa64b29ab5..c3db78bd9e 100644 --- a/lib/iris/tests/results/cube_collapsed/triple_collapse_ml_pt_lon.cml +++ b/lib/iris/tests/results/cube_collapsed/triple_collapse_ml_pt_lon.cml @@ -1,12 +1,12 @@ - + - + - + - + - + - + - + @@ -53,6 +53,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/triple_collapse_ml_pt_lon.data.0.json b/lib/iris/tests/results/cube_collapsed/triple_collapse_ml_pt_lon.data.0.json new file mode 100644 index 0000000000..1ce4d3cfbd --- /dev/null +++ b/lib/iris/tests/results/cube_collapsed/triple_collapse_ml_pt_lon.data.0.json @@ -0,0 +1 @@ +{"std": 0.059104604901192966, "min": 368.43679809570312, "max": 368.67816162109375, "shape": [100], "masked": false, "mean": 368.57890624999999} \ No newline at end of file diff --git a/lib/iris/tests/results/cube_collapsed/triple_collapse_ml_pt_lon.data.0.npy b/lib/iris/tests/results/cube_collapsed/triple_collapse_ml_pt_lon.data.0.npy deleted file mode 100644 index 0a90ca50e0..0000000000 Binary files a/lib/iris/tests/results/cube_collapsed/triple_collapse_ml_pt_lon.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/cube_io/pickling/cubelist.cml b/lib/iris/tests/results/cube_io/pickling/cubelist.cml index ac7b7d222f..6cebe384aa 100644 --- a/lib/iris/tests/results/cube_io/pickling/cubelist.cml +++ b/lib/iris/tests/results/cube_io/pickling/cubelist.cml @@ -1,404 +1,405 @@ - + - + + + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + ..., + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0]]]" shape="(70, 100, 100)" standard_name="altitude" units="Unit('m')" value_type="float32"> - + - @@ -408,7 +409,7 @@ ..., [-0.04095, -0.04005], [-0.04005, -0.03915], - [-0.03915, -0.03825]]" id="3b3f362e" points="[-0.1278, -0.1269, -0.126, ..., -0.0405, -0.0396, + [-0.03915, -0.03825]]" id="f1ab3066" points="[-0.1278, -0.1269, -0.126, ..., -0.0405, -0.0396, -0.0387]" shape="(100,)" standard_name="grid_latitude" units="Unit('degrees')" value_type="float32"> @@ -420,7 +421,7 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> @@ -432,7 +433,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -452,7 +453,7 @@ - - + 300.34]]" shape="(100, 100)" standard_name="surface_altitude" units="Unit('m')" value_type="float32"> - + + - - + - + - + + - + - @@ -534,7 +537,7 @@ ..., [-0.04095, -0.04005], [-0.04005, -0.03915], - [-0.03915, -0.03825]]" id="3b3f362e" points="[-0.1278, -0.1269, -0.126, ..., -0.0405, -0.0396, + [-0.03915, -0.03825]]" id="f1ab3066" points="[-0.1278, -0.1269, -0.126, ..., -0.0405, -0.0396, -0.0387]" shape="(100,)" standard_name="grid_latitude" units="Unit('degrees')" value_type="float32"> @@ -546,17 +549,17 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> - - + diff --git a/lib/iris/tests/results/cube_io/pickling/single_cube.cml b/lib/iris/tests/results/cube_io/pickling/single_cube.cml index 3d00b4968c..2cd3dbb3cb 100644 --- a/lib/iris/tests/results/cube_io/pickling/single_cube.cml +++ b/lib/iris/tests/results/cube_io/pickling/single_cube.cml @@ -1,404 +1,405 @@ - + - + + + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + ..., + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0]]]" shape="(70, 100, 100)" standard_name="altitude" units="Unit('m')" value_type="float32"> - + - @@ -408,7 +409,7 @@ ..., [-0.04095, -0.04005], [-0.04005, -0.03915], - [-0.03915, -0.03825]]" id="3b3f362e" points="[-0.1278, -0.1269, -0.126, ..., -0.0405, -0.0396, + [-0.03915, -0.03825]]" id="f1ab3066" points="[-0.1278, -0.1269, -0.126, ..., -0.0405, -0.0396, -0.0387]" shape="(100,)" standard_name="grid_latitude" units="Unit('degrees')" value_type="float32"> @@ -420,7 +421,7 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> @@ -432,7 +433,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -452,7 +453,7 @@ - - + 300.34]]" shape="(100, 100)" standard_name="surface_altitude" units="Unit('m')" value_type="float32"> - + + - - + diff --git a/lib/iris/tests/results/cube_io/pickling/theta.cml b/lib/iris/tests/results/cube_io/pickling/theta.cml index 7e48be6db9..39ee6aecfd 100644 --- a/lib/iris/tests/results/cube_io/pickling/theta.cml +++ b/lib/iris/tests/results/cube_io/pickling/theta.cml @@ -1,19 +1,20 @@ - + - + + - + - + - + @@ -55,7 +56,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -68,12 +69,12 @@ - + - @@ -119,7 +120,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -129,7 +130,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + diff --git a/lib/iris/tests/results/cube_io/pp/load/global.cml b/lib/iris/tests/results/cube_io/pp/load/global.cml index 848d989e83..2df84a8606 100644 --- a/lib/iris/tests/results/cube_io/pp/load/global.cml +++ b/lib/iris/tests/results/cube_io/pp/load/global.cml @@ -1,19 +1,19 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/cube_io/pp/no_std_name.cml b/lib/iris/tests/results/cube_io/pp/no_std_name.cml deleted file mode 100644 index 536118339d..0000000000 --- a/lib/iris/tests/results/cube_io/pp/no_std_name.cml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/cube_merge/multidim_coord_merge.cml b/lib/iris/tests/results/cube_merge/multidim_coord_merge.cml index c27daf2069..0767f41844 100644 --- a/lib/iris/tests/results/cube_merge/multidim_coord_merge.cml +++ b/lib/iris/tests/results/cube_merge/multidim_coord_merge.cml @@ -1,48 +1,48 @@ - + - + - + diff --git a/lib/iris/tests/results/cube_merge/multidim_coord_merge_transpose.cml b/lib/iris/tests/results/cube_merge/multidim_coord_merge_transpose.cml index e8be4d1d97..c649dc8569 100644 --- a/lib/iris/tests/results/cube_merge/multidim_coord_merge_transpose.cml +++ b/lib/iris/tests/results/cube_merge/multidim_coord_merge_transpose.cml @@ -1,48 +1,48 @@ - + - + - + diff --git a/lib/iris/tests/results/cube_merge/test_orig_point_cube.cml b/lib/iris/tests/results/cube_merge/test_orig_point_cube.cml index 36e9291237..b49da17f26 100644 --- a/lib/iris/tests/results/cube_merge/test_orig_point_cube.cml +++ b/lib/iris/tests/results/cube_merge/test_orig_point_cube.cml @@ -1,18 +1,18 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/cube_merge/test_simple_attributes1.cml b/lib/iris/tests/results/cube_merge/test_simple_attributes1.cml index d3f4001e72..50bf6bea91 100644 --- a/lib/iris/tests/results/cube_merge/test_simple_attributes1.cml +++ b/lib/iris/tests/results/cube_merge/test_simple_attributes1.cml @@ -1,36 +1,36 @@ - + - + - + - + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/cube_merge/test_simple_attributes2.cml b/lib/iris/tests/results/cube_merge/test_simple_attributes2.cml index 3e875f0c15..27d3f573e1 100644 --- a/lib/iris/tests/results/cube_merge/test_simple_attributes2.cml +++ b/lib/iris/tests/results/cube_merge/test_simple_attributes2.cml @@ -1,39 +1,39 @@ - + - + - + - + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/cube_merge/test_simple_attributes3.cml b/lib/iris/tests/results/cube_merge/test_simple_attributes3.cml index 12dd21b4bd..096ceeee50 100644 --- a/lib/iris/tests/results/cube_merge/test_simple_attributes3.cml +++ b/lib/iris/tests/results/cube_merge/test_simple_attributes3.cml @@ -1,21 +1,21 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/cube_merge/test_simple_bound_merge.cml b/lib/iris/tests/results/cube_merge/test_simple_bound_merge.cml index e268994daa..d39cf419ae 100644 --- a/lib/iris/tests/results/cube_merge/test_simple_bound_merge.cml +++ b/lib/iris/tests/results/cube_merge/test_simple_bound_merge.cml @@ -1,23 +1,23 @@ - + + [10, 15]]" id="434cbbd8" long_name="bar" points="[2.5, 7.5, 12.5]" shape="(3,)" units="Unit('1')" value_type="float64"/> + [30, 45]]" id="b0d35dcf" long_name="foo" points="[-7.5, 7.5, 22.5, 37.5]" shape="(4,)" units="Unit('1')" value_type="float64"/> - + - + diff --git a/lib/iris/tests/results/cube_merge/test_simple_merge.cml b/lib/iris/tests/results/cube_merge/test_simple_merge.cml index 0aaba05a67..4a89d8044c 100644 --- a/lib/iris/tests/results/cube_merge/test_simple_merge.cml +++ b/lib/iris/tests/results/cube_merge/test_simple_merge.cml @@ -1,18 +1,18 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/cube_slice/2d_intersect_and_reverse.cml b/lib/iris/tests/results/cube_slice/2d_intersect_and_reverse.cml index 9b6513e35d..3f9e5fef9e 100644 --- a/lib/iris/tests/results/cube_slice/2d_intersect_and_reverse.cml +++ b/lib/iris/tests/results/cube_slice/2d_intersect_and_reverse.cml @@ -1,12 +1,12 @@ - + - + - + + [0, 1]]" id="e4dc1958" long_name="dim2" points="[9, 8, 7, 5, 4, 3, 2, 1, 0]" shape="(9,)" units="Unit('meters')" value_type="int32"/> + diff --git a/lib/iris/tests/results/cube_slice/2d_orig.cml b/lib/iris/tests/results/cube_slice/2d_orig.cml index 89c9e6a464..1956d9f324 100644 --- a/lib/iris/tests/results/cube_slice/2d_orig.cml +++ b/lib/iris/tests/results/cube_slice/2d_orig.cml @@ -1,12 +1,12 @@ - + - + - + + [18, 19]]" id="e4dc1958" long_name="dim2" points="[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]" shape="(10,)" units="Unit('meters')" value_type="int32"/> + diff --git a/lib/iris/tests/results/cube_slice/2d_to_0d_cube_slice.cml b/lib/iris/tests/results/cube_slice/2d_to_0d_cube_slice.cml index 53b8975bb5..2f1a4b80c1 100644 --- a/lib/iris/tests/results/cube_slice/2d_to_0d_cube_slice.cml +++ b/lib/iris/tests/results/cube_slice/2d_to_0d_cube_slice.cml @@ -1,21 +1,21 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/cube_slice/2d_to_1d_cube_multi_slice.cml b/lib/iris/tests/results/cube_slice/2d_to_1d_cube_multi_slice.cml index 260f2358be..5c08226ea8 100644 --- a/lib/iris/tests/results/cube_slice/2d_to_1d_cube_multi_slice.cml +++ b/lib/iris/tests/results/cube_slice/2d_to_1d_cube_multi_slice.cml @@ -1,23 +1,23 @@ - + - + - + + [2, 3]]" id="e4dc1958" long_name="dim2" points="[0, 1]" shape="(2,)" units="Unit('meters')" value_type="int32"/> + [4, 5, 6, 7]]" id="b5af630a" long_name="my_multi_dim_coord" points="[0, 1]" shape="(2,)" units="Unit('1')" value_type="int32"/> - + diff --git a/lib/iris/tests/results/cube_slice/2d_to_1d_cube_multi_slice2.cml b/lib/iris/tests/results/cube_slice/2d_to_1d_cube_multi_slice2.cml index d29c7470e4..b6e6bf10e8 100644 --- a/lib/iris/tests/results/cube_slice/2d_to_1d_cube_multi_slice2.cml +++ b/lib/iris/tests/results/cube_slice/2d_to_1d_cube_multi_slice2.cml @@ -1,30 +1,30 @@ - + - + - + + [6, 7]]" id="e4dc1958" long_name="dim2" points="[0, 1, 3]" shape="(3,)" units="Unit('meters')" value_type="int32"/> - + diff --git a/lib/iris/tests/results/cube_slice/2d_to_1d_cube_multi_slice3.cml b/lib/iris/tests/results/cube_slice/2d_to_1d_cube_multi_slice3.cml index 3737bf269c..ee69b13b5c 100644 --- a/lib/iris/tests/results/cube_slice/2d_to_1d_cube_multi_slice3.cml +++ b/lib/iris/tests/results/cube_slice/2d_to_1d_cube_multi_slice3.cml @@ -1,12 +1,12 @@ - + - + - + + [18, 19]]" id="e4dc1958" long_name="dim2" points="[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]" shape="(10,)" units="Unit('meters')" value_type="int32"/> - + diff --git a/lib/iris/tests/results/cube_slice/2d_to_1d_cube_slice.cml b/lib/iris/tests/results/cube_slice/2d_to_1d_cube_slice.cml index 820c7fd779..f3fcc747d7 100644 --- a/lib/iris/tests/results/cube_slice/2d_to_1d_cube_slice.cml +++ b/lib/iris/tests/results/cube_slice/2d_to_1d_cube_slice.cml @@ -1,12 +1,12 @@ - + - + - + + [18, 19]]" id="e4dc1958" long_name="dim2" points="[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]" shape="(10,)" units="Unit('meters')" value_type="int32"/> + [36, 37, 38, 39]]" id="b5af630a" long_name="my_multi_dim_coord" points="[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]" shape="(10,)" units="Unit('1')" value_type="int32"/> - + diff --git a/lib/iris/tests/results/cube_slice/2d_to_2d_revesed.cml b/lib/iris/tests/results/cube_slice/2d_to_2d_revesed.cml index b144567e38..6df2838935 100644 --- a/lib/iris/tests/results/cube_slice/2d_to_2d_revesed.cml +++ b/lib/iris/tests/results/cube_slice/2d_to_2d_revesed.cml @@ -1,12 +1,12 @@ - + - + - + + [0, 1]]" id="e4dc1958" long_name="dim2" points="[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]" shape="(10,)" units="Unit('meters')" value_type="int32"/> + diff --git a/lib/iris/tests/results/cube_slice/2d_transposed.cml b/lib/iris/tests/results/cube_slice/2d_transposed.cml index f8463e9ae9..542f2c0801 100644 --- a/lib/iris/tests/results/cube_slice/2d_transposed.cml +++ b/lib/iris/tests/results/cube_slice/2d_transposed.cml @@ -1,12 +1,12 @@ - + - + - + + [18, 19]]" id="e4dc1958" long_name="dim2" points="[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]" shape="(10,)" units="Unit('meters')" value_type="int32"/> + diff --git a/lib/iris/tests/results/cube_slice/real_data_dual_tuple_indexing1.cml b/lib/iris/tests/results/cube_slice/real_data_dual_tuple_indexing1.cml index 3ff4785dd5..fc387bb663 100644 --- a/lib/iris/tests/results/cube_slice/real_data_dual_tuple_indexing1.cml +++ b/lib/iris/tests/results/cube_slice/real_data_dual_tuple_indexing1.cml @@ -1,32 +1,33 @@ - + - + + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/cube_slice/real_data_dual_tuple_indexing2.cml b/lib/iris/tests/results/cube_slice/real_data_dual_tuple_indexing2.cml index d2c81cf28c..9e5b5a57db 100644 --- a/lib/iris/tests/results/cube_slice/real_data_dual_tuple_indexing2.cml +++ b/lib/iris/tests/results/cube_slice/real_data_dual_tuple_indexing2.cml @@ -1,32 +1,33 @@ - + - + + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/cube_slice/real_data_dual_tuple_indexing3.cml b/lib/iris/tests/results/cube_slice/real_data_dual_tuple_indexing3.cml index 428e83cae1..061255bbe4 100644 --- a/lib/iris/tests/results/cube_slice/real_data_dual_tuple_indexing3.cml +++ b/lib/iris/tests/results/cube_slice/real_data_dual_tuple_indexing3.cml @@ -1,32 +1,33 @@ - + - + + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/cube_slice/real_empty_data_indexing.cml b/lib/iris/tests/results/cube_slice/real_empty_data_indexing.cml index 5ef82d081e..2f899b333e 100644 --- a/lib/iris/tests/results/cube_slice/real_empty_data_indexing.cml +++ b/lib/iris/tests/results/cube_slice/real_empty_data_indexing.cml @@ -1,33 +1,34 @@ - + - + + - + - + - + - - + - + diff --git a/lib/iris/tests/results/cube_to_pp/append_multi.txt b/lib/iris/tests/results/cube_to_pp/append_multi.txt index d16a2851a0..d8fa276e1b 100644 --- a/lib/iris/tests/results/cube_to_pp/append_multi.txt +++ b/lib/iris/tests/results/cube_to_pp/append_multi.txt @@ -21,7 +21,7 @@ lbext: 101 lbpack: 0 lbrel: 3 - lbfc: 0 + lbfc: 19 lbcfc: 0 lbproc: 0 lbvc: 65 @@ -40,50 +40,37 @@ bacc: 0.0 blev: 5.0 brlev: 0.0 - bhlev: 0.999424 + bhlev: 0.9994238 bhrlev: 1.0 bplat: 37.5 bplon: 177.5 bgor: 0.0 bzy: -0.1287 - bdy: 0.0009 + bdy: 0.00090000004 bzx: 0.0 bdx: 0.0 bmdi: -1e+30 bmks: 1.0 - data: [[ 288.07168579 288.06069946 288.02706909 ..., 287.78564453 - 287.80233765 287.8374939 ] - [ 288.08636475 288.08166504 288.06390381 ..., 287.78015137 - 287.78012085 287.82788086] - [ 288.0831604 288.0977478 288.11920166 ..., 287.75787354 - 287.76098633 287.81887817] - ..., - [ 287.66946411 287.68670654 287.67776489 ..., 287.62060547 287.6237793 - 287.53704834] - [ 287.69033813 287.69802856 287.70999146 ..., 287.61547852 - 287.62786865 287.57424927] - [ 287.68191528 287.69769287 287.71490479 ..., 287.60797119 - 287.62600708 287.61743164]] - x: [ 359.57958984 359.58050537 359.58139038 359.58230591 359.58319092 - 359.58410645 359.58499146 359.58590698 359.58679199 359.58770752 - 359.58859253 359.58950806 359.59039307 359.59130859 359.5921936 - 359.59310913 359.59399414 359.59490967 359.59579468 359.59671021 - 359.59759521 359.59851074 359.59939575 359.60031128 359.60119629 - 359.60211182 359.60299683 359.60391235 359.60479736 359.60571289 - 359.6065979 359.60751343 359.60839844 359.60931396 359.61019897 - 359.6111145 359.61199951 359.61291504 359.61380005 359.61468506 - 359.61560059 359.6164856 359.61740112 359.61828613 359.61920166 - 359.62008667 359.6210022 359.62188721 359.62280273 359.62368774 - 359.62460327 359.62548828 359.62640381 359.62728882 359.62820435 - 359.62908936 359.63000488 359.63088989 359.63180542 359.63269043 - 359.63360596 359.63449097 359.63540649 359.6362915 359.63720703 - 359.63809204 359.63900757 359.63989258 359.64080811 359.64169312 - 359.64260864 359.64349365 359.64440918 359.64529419 359.64620972 - 359.64709473 359.64801025 359.64889526 359.64981079 359.6506958 - 359.65161133 359.65249634 359.65341187 359.65429688 359.6552124 - 359.65609741 359.65701294 359.65789795 359.65881348 359.65969849 - 359.66061401 359.66149902 359.66241455 359.66329956 359.66421509 - 359.6651001 359.66598511 359.66690063 359.66778564 359.66870117] + data: [[288.0717 288.0607 288.02707 ... 287.78564 287.80234 287.8375 ] + [288.08636 288.08167 288.0639 ... 287.78015 287.78012 287.82788] + [288.08316 288.09775 288.1192 ... 287.75787 287.761 287.81888] + ... + [287.66946 287.6867 287.67776 ... 287.6206 287.62378 287.53705] + [287.69034 287.69803 287.71 ... 287.61548 287.62787 287.57425] + [287.68192 287.6977 287.7149 ... 287.60797 287.626 287.61743]] + x: [359.5796 359.5805 359.5814 359.5823 359.5832 359.5841 359.585 359.5859 + 359.5868 359.5877 359.5886 359.5895 359.5904 359.5913 359.5922 359.5931 + 359.594 359.5949 359.5958 359.5967 359.5976 359.5985 359.5994 359.6003 + 359.6012 359.6021 359.603 359.6039 359.6048 359.6057 359.6066 359.6075 + 359.6084 359.6093 359.6102 359.6111 359.612 359.6129 359.6138 359.6147 + 359.6156 359.6165 359.6174 359.6183 359.6192 359.6201 359.621 359.6219 + 359.6228 359.6237 359.6246 359.6255 359.6264 359.6273 359.6282 359.6291 + 359.63 359.6309 359.6318 359.6327 359.6336 359.6345 359.6354 359.6363 + 359.6372 359.6381 359.639 359.6399 359.6408 359.6417 359.6426 359.6435 + 359.6444 359.6453 359.6462 359.6471 359.648 359.6489 359.6498 359.6507 + 359.6516 359.6525 359.6534 359.6543 359.6552 359.6561 359.657 359.6579 + 359.6588 359.6597 359.6606 359.6615 359.6624 359.6633 359.6642 359.6651 + 359.666 359.6669 359.6678 359.6687] , PP Field lbyr: 2009 lbmon: 9 @@ -107,7 +94,7 @@ lbext: 101 lbpack: 0 lbrel: 3 - lbfc: 0 + lbfc: 19 lbcfc: 0 lbproc: 0 lbvc: 65 @@ -121,55 +108,42 @@ lbrsvd: (0, 0, 0, 0) lbsrce: 0 lbuser: (1, -99, 0, 0, 0, 0, 0) - brsvd: (33.333332, 0.99616188, 0.0, 0.0) + brsvd: (33.333332, 0.9961619, 0.0, 0.0) bdatum: 0.0 bacc: 0.0 - blev: 21.6667 - brlev: 13.3333 - bhlev: 0.997504 - bhrlev: 0.998464 + blev: 21.666664 + brlev: 13.333332 + bhlev: 0.9975044 + bhrlev: 0.99846387 bplat: 37.5 bplon: 177.5 bgor: 0.0 bzy: -0.1287 - bdy: 0.0009 + bdy: 0.00090000004 bzx: 0.0 bdx: 0.0 bmdi: -1e+30 bmks: 1.0 - data: [[ 288.09292603 288.09207153 288.09320068 ..., 287.80407715 287.824646 - 287.84674072] - [ 288.09619141 288.09255981 288.08947754 ..., 287.79537964 - 287.81591797 287.84683228] - [ 288.10003662 288.09725952 288.09472656 ..., 287.7835083 287.81036377 - 287.84561157] - ..., - [ 287.73101807 287.73510742 287.72705078 ..., 287.61431885 - 287.61801147 287.53863525] - [ 287.71975708 287.73092651 287.73510742 ..., 287.6027832 287.62597656 - 287.56869507] - [ 287.70523071 287.71853638 287.72915649 ..., 287.59054565 - 287.62747192 287.60159302]] - x: [ 359.57958984 359.58050537 359.58139038 359.58230591 359.58319092 - 359.58410645 359.58499146 359.58590698 359.58679199 359.58770752 - 359.58859253 359.58950806 359.59039307 359.59130859 359.5921936 - 359.59310913 359.59399414 359.59490967 359.59579468 359.59671021 - 359.59759521 359.59851074 359.59939575 359.60031128 359.60119629 - 359.60211182 359.60299683 359.60391235 359.60479736 359.60571289 - 359.6065979 359.60751343 359.60839844 359.60931396 359.61019897 - 359.6111145 359.61199951 359.61291504 359.61380005 359.61468506 - 359.61560059 359.6164856 359.61740112 359.61828613 359.61920166 - 359.62008667 359.6210022 359.62188721 359.62280273 359.62368774 - 359.62460327 359.62548828 359.62640381 359.62728882 359.62820435 - 359.62908936 359.63000488 359.63088989 359.63180542 359.63269043 - 359.63360596 359.63449097 359.63540649 359.6362915 359.63720703 - 359.63809204 359.63900757 359.63989258 359.64080811 359.64169312 - 359.64260864 359.64349365 359.64440918 359.64529419 359.64620972 - 359.64709473 359.64801025 359.64889526 359.64981079 359.6506958 - 359.65161133 359.65249634 359.65341187 359.65429688 359.6552124 - 359.65609741 359.65701294 359.65789795 359.65881348 359.65969849 - 359.66061401 359.66149902 359.66241455 359.66329956 359.66421509 - 359.6651001 359.66598511 359.66690063 359.66778564 359.66870117] + data: [[288.09293 288.09207 288.0932 ... 287.80408 287.82465 287.84674] + [288.0962 288.09256 288.08948 ... 287.79538 287.81592 287.84683] + [288.10004 288.09726 288.09473 ... 287.7835 287.81036 287.8456 ] + ... + [287.73102 287.7351 287.72705 ... 287.61432 287.618 287.53864] + [287.71976 287.73093 287.7351 ... 287.60278 287.62598 287.5687 ] + [287.70523 287.71854 287.72916 ... 287.59055 287.62747 287.6016 ]] + x: [359.5796 359.5805 359.5814 359.5823 359.5832 359.5841 359.585 359.5859 + 359.5868 359.5877 359.5886 359.5895 359.5904 359.5913 359.5922 359.5931 + 359.594 359.5949 359.5958 359.5967 359.5976 359.5985 359.5994 359.6003 + 359.6012 359.6021 359.603 359.6039 359.6048 359.6057 359.6066 359.6075 + 359.6084 359.6093 359.6102 359.6111 359.612 359.6129 359.6138 359.6147 + 359.6156 359.6165 359.6174 359.6183 359.6192 359.6201 359.621 359.6219 + 359.6228 359.6237 359.6246 359.6255 359.6264 359.6273 359.6282 359.6291 + 359.63 359.6309 359.6318 359.6327 359.6336 359.6345 359.6354 359.6363 + 359.6372 359.6381 359.639 359.6399 359.6408 359.6417 359.6426 359.6435 + 359.6444 359.6453 359.6462 359.6471 359.648 359.6489 359.6498 359.6507 + 359.6516 359.6525 359.6534 359.6543 359.6552 359.6561 359.657 359.6579 + 359.6588 359.6597 359.6606 359.6615 359.6624 359.6633 359.6642 359.6651 + 359.666 359.6669 359.6678 359.6687] , PP Field lbyr: 2009 lbmon: 9 @@ -193,7 +167,7 @@ lbext: 101 lbpack: 0 lbrel: 3 - lbfc: 0 + lbfc: 19 lbcfc: 0 lbproc: 0 lbvc: 65 @@ -212,50 +186,37 @@ bacc: 0.0 blev: 5.0 brlev: 0.0 - bhlev: 0.999424 + bhlev: 0.9994238 bhrlev: 1.0 bplat: 37.5 bplon: 177.5 bgor: 0.0 bzy: -0.1287 - bdy: 0.0009 + bdy: 0.00090000004 bzx: 0.0 bdx: 0.0 bmdi: -1e+30 bmks: 1.0 - data: [[ 287.85189819 287.84213257 287.78909302 ..., 287.54266357 - 287.53170776 287.52819824] - [ 287.86260986 287.85971069 287.82723999 ..., 287.54309082 287.5138855 - 287.52264404] - [ 287.85455322 287.88586426 287.8878479 ..., 287.52322388 287.4979248 - 287.51049805] - ..., - [ 287.42971802 287.45941162 287.46008301 ..., 287.40472412 - 287.36236572 287.33816528] - [ 287.46743774 287.47412109 287.49343872 ..., 287.41680908 - 287.38430786 287.3664856 ] - [ 287.48812866 287.49301147 287.50875854 ..., 287.41833496 - 287.38116455 287.36645508]] - x: [ 359.57958984 359.58050537 359.58139038 359.58230591 359.58319092 - 359.58410645 359.58499146 359.58590698 359.58679199 359.58770752 - 359.58859253 359.58950806 359.59039307 359.59130859 359.5921936 - 359.59310913 359.59399414 359.59490967 359.59579468 359.59671021 - 359.59759521 359.59851074 359.59939575 359.60031128 359.60119629 - 359.60211182 359.60299683 359.60391235 359.60479736 359.60571289 - 359.6065979 359.60751343 359.60839844 359.60931396 359.61019897 - 359.6111145 359.61199951 359.61291504 359.61380005 359.61468506 - 359.61560059 359.6164856 359.61740112 359.61828613 359.61920166 - 359.62008667 359.6210022 359.62188721 359.62280273 359.62368774 - 359.62460327 359.62548828 359.62640381 359.62728882 359.62820435 - 359.62908936 359.63000488 359.63088989 359.63180542 359.63269043 - 359.63360596 359.63449097 359.63540649 359.6362915 359.63720703 - 359.63809204 359.63900757 359.63989258 359.64080811 359.64169312 - 359.64260864 359.64349365 359.64440918 359.64529419 359.64620972 - 359.64709473 359.64801025 359.64889526 359.64981079 359.6506958 - 359.65161133 359.65249634 359.65341187 359.65429688 359.6552124 - 359.65609741 359.65701294 359.65789795 359.65881348 359.65969849 - 359.66061401 359.66149902 359.66241455 359.66329956 359.66421509 - 359.6651001 359.66598511 359.66690063 359.66778564 359.66870117] + data: [[287.8519 287.84213 287.7891 ... 287.54266 287.5317 287.5282 ] + [287.8626 287.8597 287.82724 ... 287.5431 287.5139 287.52264] + [287.85455 287.88586 287.88785 ... 287.52322 287.49792 287.5105 ] + ... + [287.42972 287.4594 287.46008 ... 287.40472 287.36237 287.33817] + [287.46744 287.47412 287.49344 ... 287.4168 287.3843 287.3665 ] + [287.48813 287.493 287.50876 ... 287.41833 287.38116 287.36646]] + x: [359.5796 359.5805 359.5814 359.5823 359.5832 359.5841 359.585 359.5859 + 359.5868 359.5877 359.5886 359.5895 359.5904 359.5913 359.5922 359.5931 + 359.594 359.5949 359.5958 359.5967 359.5976 359.5985 359.5994 359.6003 + 359.6012 359.6021 359.603 359.6039 359.6048 359.6057 359.6066 359.6075 + 359.6084 359.6093 359.6102 359.6111 359.612 359.6129 359.6138 359.6147 + 359.6156 359.6165 359.6174 359.6183 359.6192 359.6201 359.621 359.6219 + 359.6228 359.6237 359.6246 359.6255 359.6264 359.6273 359.6282 359.6291 + 359.63 359.6309 359.6318 359.6327 359.6336 359.6345 359.6354 359.6363 + 359.6372 359.6381 359.639 359.6399 359.6408 359.6417 359.6426 359.6435 + 359.6444 359.6453 359.6462 359.6471 359.648 359.6489 359.6498 359.6507 + 359.6516 359.6525 359.6534 359.6543 359.6552 359.6561 359.657 359.6579 + 359.6588 359.6597 359.6606 359.6615 359.6624 359.6633 359.6642 359.6651 + 359.666 359.6669 359.6678 359.6687] , PP Field lbyr: 2009 lbmon: 9 @@ -279,7 +240,7 @@ lbext: 101 lbpack: 0 lbrel: 3 - lbfc: 0 + lbfc: 19 lbcfc: 0 lbproc: 0 lbvc: 65 @@ -293,55 +254,42 @@ lbrsvd: (0, 0, 0, 0) lbsrce: 0 lbuser: (1, -99, 0, 0, 0, 0, 0) - brsvd: (33.333332, 0.99616188, 0.0, 0.0) + brsvd: (33.333332, 0.9961619, 0.0, 0.0) bdatum: 0.0 bacc: 0.0 - blev: 21.6667 - brlev: 13.3333 - bhlev: 0.997504 - bhrlev: 0.998464 + blev: 21.666664 + brlev: 13.333332 + bhlev: 0.9975044 + bhrlev: 0.99846387 bplat: 37.5 bplon: 177.5 bgor: 0.0 bzy: -0.1287 - bdy: 0.0009 + bdy: 0.00090000004 bzx: 0.0 bdx: 0.0 bmdi: -1e+30 bmks: 1.0 - data: [[ 287.91665649 287.91522217 287.90628052 ..., 287.59512329 287.5892334 - 287.57333374] - [ 287.91455078 287.90072632 287.89422607 ..., 287.59274292 287.5949707 - 287.58169556] - [ 287.92056274 287.90350342 287.88308716 ..., 287.58111572 - 287.59597778 287.58496094] - ..., - [ 287.54907227 287.54638672 287.54373169 ..., 287.42886353 - 287.43325806 287.449646 ] - [ 287.55529785 287.55181885 287.55151367 ..., 287.42877197 - 287.43362427 287.44259644] - [ 287.57333374 287.5696106 287.56436157 ..., 287.42312622 - 287.42294312 287.42449951]] - x: [ 359.57958984 359.58050537 359.58139038 359.58230591 359.58319092 - 359.58410645 359.58499146 359.58590698 359.58679199 359.58770752 - 359.58859253 359.58950806 359.59039307 359.59130859 359.5921936 - 359.59310913 359.59399414 359.59490967 359.59579468 359.59671021 - 359.59759521 359.59851074 359.59939575 359.60031128 359.60119629 - 359.60211182 359.60299683 359.60391235 359.60479736 359.60571289 - 359.6065979 359.60751343 359.60839844 359.60931396 359.61019897 - 359.6111145 359.61199951 359.61291504 359.61380005 359.61468506 - 359.61560059 359.6164856 359.61740112 359.61828613 359.61920166 - 359.62008667 359.6210022 359.62188721 359.62280273 359.62368774 - 359.62460327 359.62548828 359.62640381 359.62728882 359.62820435 - 359.62908936 359.63000488 359.63088989 359.63180542 359.63269043 - 359.63360596 359.63449097 359.63540649 359.6362915 359.63720703 - 359.63809204 359.63900757 359.63989258 359.64080811 359.64169312 - 359.64260864 359.64349365 359.64440918 359.64529419 359.64620972 - 359.64709473 359.64801025 359.64889526 359.64981079 359.6506958 - 359.65161133 359.65249634 359.65341187 359.65429688 359.6552124 - 359.65609741 359.65701294 359.65789795 359.65881348 359.65969849 - 359.66061401 359.66149902 359.66241455 359.66329956 359.66421509 - 359.6651001 359.66598511 359.66690063 359.66778564 359.66870117] + data: [[287.91666 287.91522 287.90628 ... 287.59512 287.58923 287.57333] + [287.91455 287.90073 287.89423 ... 287.59274 287.59497 287.5817 ] + [287.92056 287.9035 287.8831 ... 287.58112 287.59598 287.58496] + ... + [287.54907 287.5464 287.54373 ... 287.42886 287.43326 287.44965] + [287.5553 287.55182 287.5515 ... 287.42877 287.43362 287.4426 ] + [287.57333 287.5696 287.56436 ... 287.42313 287.42294 287.4245 ]] + x: [359.5796 359.5805 359.5814 359.5823 359.5832 359.5841 359.585 359.5859 + 359.5868 359.5877 359.5886 359.5895 359.5904 359.5913 359.5922 359.5931 + 359.594 359.5949 359.5958 359.5967 359.5976 359.5985 359.5994 359.6003 + 359.6012 359.6021 359.603 359.6039 359.6048 359.6057 359.6066 359.6075 + 359.6084 359.6093 359.6102 359.6111 359.612 359.6129 359.6138 359.6147 + 359.6156 359.6165 359.6174 359.6183 359.6192 359.6201 359.621 359.6219 + 359.6228 359.6237 359.6246 359.6255 359.6264 359.6273 359.6282 359.6291 + 359.63 359.6309 359.6318 359.6327 359.6336 359.6345 359.6354 359.6363 + 359.6372 359.6381 359.639 359.6399 359.6408 359.6417 359.6426 359.6435 + 359.6444 359.6453 359.6462 359.6471 359.648 359.6489 359.6498 359.6507 + 359.6516 359.6525 359.6534 359.6543 359.6552 359.6561 359.657 359.6579 + 359.6588 359.6597 359.6606 359.6615 359.6624 359.6633 359.6642 359.6651 + 359.666 359.6669 359.6678 359.6687] , PP Field lbyr: 2009 lbmon: 9 @@ -365,7 +313,7 @@ lbext: 101 lbpack: 0 lbrel: 3 - lbfc: 0 + lbfc: 19 lbcfc: 0 lbproc: 0 lbvc: 65 @@ -384,50 +332,37 @@ bacc: 0.0 blev: 5.0 brlev: 0.0 - bhlev: 0.999424 + bhlev: 0.9994238 bhrlev: 1.0 bplat: 37.5 bplon: 177.5 bgor: 0.0 bzy: -0.1287 - bdy: 0.0009 + bdy: 0.00090000004 bzx: 0.0 bdx: 0.0 bmdi: -1e+30 bmks: 1.0 - data: [[ 287.53094482 287.59091187 287.59259033 ..., 287.2557373 287.24783325 - 287.24807739] - [ 287.5128479 287.55325317 287.60549927 ..., 287.25265503 - 287.22775269 287.24221802] - [ 287.52096558 287.54098511 287.60977173 ..., 287.2253418 287.20806885 - 287.22787476] - ..., - [ 287.25546265 287.28213501 287.28268433 ..., 287.05804443 - 287.04180908 287.03646851] - [ 287.31451416 287.31658936 287.33200073 ..., 287.06240845 - 287.05044556 287.05456543] - [ 287.34872437 287.35021973 287.36239624 ..., 287.0524292 287.02581787 - 287.03649902]] - x: [ 359.57958984 359.58050537 359.58139038 359.58230591 359.58319092 - 359.58410645 359.58499146 359.58590698 359.58679199 359.58770752 - 359.58859253 359.58950806 359.59039307 359.59130859 359.5921936 - 359.59310913 359.59399414 359.59490967 359.59579468 359.59671021 - 359.59759521 359.59851074 359.59939575 359.60031128 359.60119629 - 359.60211182 359.60299683 359.60391235 359.60479736 359.60571289 - 359.6065979 359.60751343 359.60839844 359.60931396 359.61019897 - 359.6111145 359.61199951 359.61291504 359.61380005 359.61468506 - 359.61560059 359.6164856 359.61740112 359.61828613 359.61920166 - 359.62008667 359.6210022 359.62188721 359.62280273 359.62368774 - 359.62460327 359.62548828 359.62640381 359.62728882 359.62820435 - 359.62908936 359.63000488 359.63088989 359.63180542 359.63269043 - 359.63360596 359.63449097 359.63540649 359.6362915 359.63720703 - 359.63809204 359.63900757 359.63989258 359.64080811 359.64169312 - 359.64260864 359.64349365 359.64440918 359.64529419 359.64620972 - 359.64709473 359.64801025 359.64889526 359.64981079 359.6506958 - 359.65161133 359.65249634 359.65341187 359.65429688 359.6552124 - 359.65609741 359.65701294 359.65789795 359.65881348 359.65969849 - 359.66061401 359.66149902 359.66241455 359.66329956 359.66421509 - 359.6651001 359.66598511 359.66690063 359.66778564 359.66870117] + data: [[287.53094 287.5909 287.5926 ... 287.25574 287.24783 287.24808] + [287.51285 287.55325 287.6055 ... 287.25266 287.22775 287.24222] + [287.52097 287.541 287.60977 ... 287.22534 287.20807 287.22787] + ... + [287.25546 287.28214 287.28268 ... 287.05804 287.0418 287.03647] + [287.3145 287.3166 287.332 ... 287.0624 287.05045 287.05457] + [287.34872 287.35022 287.3624 ... 287.05243 287.02582 287.0365 ]] + x: [359.5796 359.5805 359.5814 359.5823 359.5832 359.5841 359.585 359.5859 + 359.5868 359.5877 359.5886 359.5895 359.5904 359.5913 359.5922 359.5931 + 359.594 359.5949 359.5958 359.5967 359.5976 359.5985 359.5994 359.6003 + 359.6012 359.6021 359.603 359.6039 359.6048 359.6057 359.6066 359.6075 + 359.6084 359.6093 359.6102 359.6111 359.612 359.6129 359.6138 359.6147 + 359.6156 359.6165 359.6174 359.6183 359.6192 359.6201 359.621 359.6219 + 359.6228 359.6237 359.6246 359.6255 359.6264 359.6273 359.6282 359.6291 + 359.63 359.6309 359.6318 359.6327 359.6336 359.6345 359.6354 359.6363 + 359.6372 359.6381 359.639 359.6399 359.6408 359.6417 359.6426 359.6435 + 359.6444 359.6453 359.6462 359.6471 359.648 359.6489 359.6498 359.6507 + 359.6516 359.6525 359.6534 359.6543 359.6552 359.6561 359.657 359.6579 + 359.6588 359.6597 359.6606 359.6615 359.6624 359.6633 359.6642 359.6651 + 359.666 359.6669 359.6678 359.6687] , PP Field lbyr: 2009 lbmon: 9 @@ -451,7 +386,7 @@ lbext: 101 lbpack: 0 lbrel: 3 - lbfc: 0 + lbfc: 19 lbcfc: 0 lbproc: 0 lbvc: 65 @@ -465,55 +400,42 @@ lbrsvd: (0, 0, 0, 0) lbsrce: 0 lbuser: (1, -99, 0, 0, 0, 0, 0) - brsvd: (33.333332, 0.99616188, 0.0, 0.0) + brsvd: (33.333332, 0.9961619, 0.0, 0.0) bdatum: 0.0 bacc: 0.0 - blev: 21.6667 - brlev: 13.3333 - bhlev: 0.997504 - bhrlev: 0.998464 + blev: 21.666664 + brlev: 13.333332 + bhlev: 0.9975044 + bhrlev: 0.99846387 bplat: 37.5 bplon: 177.5 bgor: 0.0 bzy: -0.1287 - bdy: 0.0009 + bdy: 0.00090000004 bzx: 0.0 bdx: 0.0 bmdi: -1e+30 bmks: 1.0 - data: [[ 287.66656494 287.67156982 287.67788696 ..., 287.34863281 - 287.35137939 287.3520813 ] - [ 287.64865112 287.65151978 287.65512085 ..., 287.35079956 - 287.36505127 287.38079834] - [ 287.63696289 287.6340332 287.63772583 ..., 287.33383179 - 287.36331177 287.37634277] - ..., - [ 287.43460083 287.42514038 287.42144775 ..., 287.11776733 - 287.13406372 287.1607666 ] - [ 287.44631958 287.43557739 287.43032837 ..., 287.11791992 - 287.14456177 287.15402222] - [ 287.47320557 287.4644165 287.45251465 ..., 287.09741211 - 287.11654663 287.12765503]] - x: [ 359.57958984 359.58050537 359.58139038 359.58230591 359.58319092 - 359.58410645 359.58499146 359.58590698 359.58679199 359.58770752 - 359.58859253 359.58950806 359.59039307 359.59130859 359.5921936 - 359.59310913 359.59399414 359.59490967 359.59579468 359.59671021 - 359.59759521 359.59851074 359.59939575 359.60031128 359.60119629 - 359.60211182 359.60299683 359.60391235 359.60479736 359.60571289 - 359.6065979 359.60751343 359.60839844 359.60931396 359.61019897 - 359.6111145 359.61199951 359.61291504 359.61380005 359.61468506 - 359.61560059 359.6164856 359.61740112 359.61828613 359.61920166 - 359.62008667 359.6210022 359.62188721 359.62280273 359.62368774 - 359.62460327 359.62548828 359.62640381 359.62728882 359.62820435 - 359.62908936 359.63000488 359.63088989 359.63180542 359.63269043 - 359.63360596 359.63449097 359.63540649 359.6362915 359.63720703 - 359.63809204 359.63900757 359.63989258 359.64080811 359.64169312 - 359.64260864 359.64349365 359.64440918 359.64529419 359.64620972 - 359.64709473 359.64801025 359.64889526 359.64981079 359.6506958 - 359.65161133 359.65249634 359.65341187 359.65429688 359.6552124 - 359.65609741 359.65701294 359.65789795 359.65881348 359.65969849 - 359.66061401 359.66149902 359.66241455 359.66329956 359.66421509 - 359.6651001 359.66598511 359.66690063 359.66778564 359.66870117] + data: [[287.66656 287.67157 287.6779 ... 287.34863 287.35138 287.35208] + [287.64865 287.65152 287.65512 ... 287.3508 287.36505 287.3808 ] + [287.63696 287.63403 287.63773 ... 287.33383 287.3633 287.37634] + ... + [287.4346 287.42514 287.42145 ... 287.11777 287.13406 287.16077] + [287.44632 287.43558 287.43033 ... 287.11792 287.14456 287.15402] + [287.4732 287.46442 287.4525 ... 287.0974 287.11655 287.12766]] + x: [359.5796 359.5805 359.5814 359.5823 359.5832 359.5841 359.585 359.5859 + 359.5868 359.5877 359.5886 359.5895 359.5904 359.5913 359.5922 359.5931 + 359.594 359.5949 359.5958 359.5967 359.5976 359.5985 359.5994 359.6003 + 359.6012 359.6021 359.603 359.6039 359.6048 359.6057 359.6066 359.6075 + 359.6084 359.6093 359.6102 359.6111 359.612 359.6129 359.6138 359.6147 + 359.6156 359.6165 359.6174 359.6183 359.6192 359.6201 359.621 359.6219 + 359.6228 359.6237 359.6246 359.6255 359.6264 359.6273 359.6282 359.6291 + 359.63 359.6309 359.6318 359.6327 359.6336 359.6345 359.6354 359.6363 + 359.6372 359.6381 359.639 359.6399 359.6408 359.6417 359.6426 359.6435 + 359.6444 359.6453 359.6462 359.6471 359.648 359.6489 359.6498 359.6507 + 359.6516 359.6525 359.6534 359.6543 359.6552 359.6561 359.657 359.6579 + 359.6588 359.6597 359.6606 359.6615 359.6624 359.6633 359.6642 359.6651 + 359.666 359.6669 359.6678 359.6687] , PP Field lbyr: 2009 lbmon: 9 @@ -537,7 +459,7 @@ lbext: 101 lbpack: 0 lbrel: 3 - lbfc: 0 + lbfc: 19 lbcfc: 0 lbproc: 0 lbvc: 65 @@ -556,50 +478,37 @@ bacc: 0.0 blev: 5.0 brlev: 0.0 - bhlev: 0.999424 + bhlev: 0.9994238 bhrlev: 1.0 bplat: 37.5 bplon: 177.5 bgor: 0.0 bzy: -0.1287 - bdy: 0.0009 + bdy: 0.00090000004 bzx: 0.0 bdx: 0.0 bmdi: -1e+30 bmks: 1.0 - data: [[ 287.34893799 287.42550659 287.40127563 ..., 286.95541382 - 286.96194458 286.96682739] - [ 287.30154419 287.37628174 287.42120361 ..., 286.93814087 - 286.93344116 286.96240234] - [ 287.2989502 287.34576416 287.42221069 ..., 286.89581299 - 286.89935303 286.94052124] - ..., - [ 287.08889771 287.11340332 287.12139893 ..., 286.87512207 - 286.84820557 286.84524536] - [ 287.16998291 287.16873169 287.18426514 ..., 286.87496948 - 286.87020874 286.87353516] - [ 287.21185303 287.21325684 287.22512817 ..., 286.83877563 - 286.82666016 286.83929443]] - x: [ 359.57958984 359.58050537 359.58139038 359.58230591 359.58319092 - 359.58410645 359.58499146 359.58590698 359.58679199 359.58770752 - 359.58859253 359.58950806 359.59039307 359.59130859 359.5921936 - 359.59310913 359.59399414 359.59490967 359.59579468 359.59671021 - 359.59759521 359.59851074 359.59939575 359.60031128 359.60119629 - 359.60211182 359.60299683 359.60391235 359.60479736 359.60571289 - 359.6065979 359.60751343 359.60839844 359.60931396 359.61019897 - 359.6111145 359.61199951 359.61291504 359.61380005 359.61468506 - 359.61560059 359.6164856 359.61740112 359.61828613 359.61920166 - 359.62008667 359.6210022 359.62188721 359.62280273 359.62368774 - 359.62460327 359.62548828 359.62640381 359.62728882 359.62820435 - 359.62908936 359.63000488 359.63088989 359.63180542 359.63269043 - 359.63360596 359.63449097 359.63540649 359.6362915 359.63720703 - 359.63809204 359.63900757 359.63989258 359.64080811 359.64169312 - 359.64260864 359.64349365 359.64440918 359.64529419 359.64620972 - 359.64709473 359.64801025 359.64889526 359.64981079 359.6506958 - 359.65161133 359.65249634 359.65341187 359.65429688 359.6552124 - 359.65609741 359.65701294 359.65789795 359.65881348 359.65969849 - 359.66061401 359.66149902 359.66241455 359.66329956 359.66421509 - 359.6651001 359.66598511 359.66690063 359.66778564 359.66870117] + data: [[287.34894 287.4255 287.40128 ... 286.9554 286.96194 286.96683] + [287.30154 287.37628 287.4212 ... 286.93814 286.93344 286.9624 ] + [287.29895 287.34576 287.4222 ... 286.8958 286.89935 286.94052] + ... + [287.0889 287.1134 287.1214 ... 286.87512 286.8482 286.84525] + [287.16998 287.16873 287.18427 ... 286.87497 286.8702 286.87354] + [287.21185 287.21326 287.22513 ... 286.83878 286.82666 286.8393 ]] + x: [359.5796 359.5805 359.5814 359.5823 359.5832 359.5841 359.585 359.5859 + 359.5868 359.5877 359.5886 359.5895 359.5904 359.5913 359.5922 359.5931 + 359.594 359.5949 359.5958 359.5967 359.5976 359.5985 359.5994 359.6003 + 359.6012 359.6021 359.603 359.6039 359.6048 359.6057 359.6066 359.6075 + 359.6084 359.6093 359.6102 359.6111 359.612 359.6129 359.6138 359.6147 + 359.6156 359.6165 359.6174 359.6183 359.6192 359.6201 359.621 359.6219 + 359.6228 359.6237 359.6246 359.6255 359.6264 359.6273 359.6282 359.6291 + 359.63 359.6309 359.6318 359.6327 359.6336 359.6345 359.6354 359.6363 + 359.6372 359.6381 359.639 359.6399 359.6408 359.6417 359.6426 359.6435 + 359.6444 359.6453 359.6462 359.6471 359.648 359.6489 359.6498 359.6507 + 359.6516 359.6525 359.6534 359.6543 359.6552 359.6561 359.657 359.6579 + 359.6588 359.6597 359.6606 359.6615 359.6624 359.6633 359.6642 359.6651 + 359.666 359.6669 359.6678 359.6687] , PP Field lbyr: 2009 lbmon: 9 @@ -623,7 +532,7 @@ lbext: 101 lbpack: 0 lbrel: 3 - lbfc: 0 + lbfc: 19 lbcfc: 0 lbproc: 0 lbvc: 65 @@ -637,53 +546,40 @@ lbrsvd: (0, 0, 0, 0) lbsrce: 0 lbuser: (1, -99, 0, 0, 0, 0, 0) - brsvd: (33.333332, 0.99616188, 0.0, 0.0) + brsvd: (33.333332, 0.9961619, 0.0, 0.0) bdatum: 0.0 bacc: 0.0 - blev: 21.6667 - brlev: 13.3333 - bhlev: 0.997504 - bhrlev: 0.998464 + blev: 21.666664 + brlev: 13.333332 + bhlev: 0.9975044 + bhrlev: 0.99846387 bplat: 37.5 bplon: 177.5 bgor: 0.0 bzy: -0.1287 - bdy: 0.0009 + bdy: 0.00090000004 bzx: 0.0 bdx: 0.0 bmdi: -1e+30 bmks: 1.0 - data: [[ 287.53091431 287.53164673 287.5319519 ..., 287.08203125 - 287.09094238 287.09213257] - [ 287.51821899 287.52059937 287.52099609 ..., 287.07635498 - 287.10369873 287.12637329] - [ 287.50125122 287.50241089 287.50982666 ..., 287.04663086 - 287.09860229 287.12164307] - ..., - [ 287.32684326 287.31106567 287.30667114 ..., 286.9911499 287.01681519 - 287.04400635] - [ 287.33877563 287.3223877 287.3117981 ..., 287.00402832 287.0345459 - 287.03637695] - [ 287.36621094 287.35803223 287.33911133 ..., 286.95663452 - 286.98605347 286.99371338]] - x: [ 359.57958984 359.58050537 359.58139038 359.58230591 359.58319092 - 359.58410645 359.58499146 359.58590698 359.58679199 359.58770752 - 359.58859253 359.58950806 359.59039307 359.59130859 359.5921936 - 359.59310913 359.59399414 359.59490967 359.59579468 359.59671021 - 359.59759521 359.59851074 359.59939575 359.60031128 359.60119629 - 359.60211182 359.60299683 359.60391235 359.60479736 359.60571289 - 359.6065979 359.60751343 359.60839844 359.60931396 359.61019897 - 359.6111145 359.61199951 359.61291504 359.61380005 359.61468506 - 359.61560059 359.6164856 359.61740112 359.61828613 359.61920166 - 359.62008667 359.6210022 359.62188721 359.62280273 359.62368774 - 359.62460327 359.62548828 359.62640381 359.62728882 359.62820435 - 359.62908936 359.63000488 359.63088989 359.63180542 359.63269043 - 359.63360596 359.63449097 359.63540649 359.6362915 359.63720703 - 359.63809204 359.63900757 359.63989258 359.64080811 359.64169312 - 359.64260864 359.64349365 359.64440918 359.64529419 359.64620972 - 359.64709473 359.64801025 359.64889526 359.64981079 359.6506958 - 359.65161133 359.65249634 359.65341187 359.65429688 359.6552124 - 359.65609741 359.65701294 359.65789795 359.65881348 359.65969849 - 359.66061401 359.66149902 359.66241455 359.66329956 359.66421509 - 359.6651001 359.66598511 359.66690063 359.66778564 359.66870117] + data: [[287.5309 287.53165 287.53195 ... 287.08203 287.09094 287.09213] + [287.51822 287.5206 287.521 ... 287.07635 287.1037 287.12637] + [287.50125 287.5024 287.50983 ... 287.04663 287.0986 287.12164] + ... + [287.32684 287.31107 287.30667 ... 286.99115 287.0168 287.044 ] + [287.33878 287.3224 287.3118 ... 287.00403 287.03455 287.03638] + [287.3662 287.35803 287.3391 ... 286.95663 286.98605 286.9937 ]] + x: [359.5796 359.5805 359.5814 359.5823 359.5832 359.5841 359.585 359.5859 + 359.5868 359.5877 359.5886 359.5895 359.5904 359.5913 359.5922 359.5931 + 359.594 359.5949 359.5958 359.5967 359.5976 359.5985 359.5994 359.6003 + 359.6012 359.6021 359.603 359.6039 359.6048 359.6057 359.6066 359.6075 + 359.6084 359.6093 359.6102 359.6111 359.612 359.6129 359.6138 359.6147 + 359.6156 359.6165 359.6174 359.6183 359.6192 359.6201 359.621 359.6219 + 359.6228 359.6237 359.6246 359.6255 359.6264 359.6273 359.6282 359.6291 + 359.63 359.6309 359.6318 359.6327 359.6336 359.6345 359.6354 359.6363 + 359.6372 359.6381 359.639 359.6399 359.6408 359.6417 359.6426 359.6435 + 359.6444 359.6453 359.6462 359.6471 359.648 359.6489 359.6498 359.6507 + 359.6516 359.6525 359.6534 359.6543 359.6552 359.6561 359.657 359.6579 + 359.6588 359.6597 359.6606 359.6615 359.6624 359.6633 359.6642 359.6651 + 359.666 359.6669 359.6678 359.6687] ] \ No newline at end of file diff --git a/lib/iris/tests/results/cube_to_pp/append_single.txt b/lib/iris/tests/results/cube_to_pp/append_single.txt index 642d40cb2a..2235e9f37f 100644 --- a/lib/iris/tests/results/cube_to_pp/append_single.txt +++ b/lib/iris/tests/results/cube_to_pp/append_single.txt @@ -45,25 +45,19 @@ bplat: 90.0 bplon: 0.0 bgor: 0.0 - bzy: 92.5 - bdy: -2.5 - bzx: -3.75 - bdx: 3.75 + bzy: 92.499985 + bdy: -2.4999988 + bzx: -3.749999 + bdx: 3.749999 bmdi: -1e+30 bmks: 1.0 - data: [[ 254.64399719 254.64399719 254.64399719 ..., 254.64399719 - 254.64399719 254.64399719] - [ 254.97499084 254.96766663 254.9808197 ..., 254.98776245 - 255.03466797 254.99720764] - [ 255.99584961 256.30834961 256.55874634 ..., 256.11685181 - 255.95605469 255.83555603] - ..., - [ 254.57333374 253.86854553 252.90516663 ..., 255.29681396 - 255.38789368 255.14859009] - [ 252.33691406 252.08926392 251.85536194 ..., 252.59863281 - 252.67466736 252.58959961] - [ 248.74584961 248.74584961 248.74584961 ..., 248.74584961 - 248.74584961 248.74584961]] + data: [[254.644 254.644 254.644 ... 254.644 254.644 254.644 ] + [254.97499 254.96767 254.98082 ... 254.98776 255.03467 254.99721] + [255.99585 256.30835 256.55875 ... 256.11685 255.95605 255.83556] + ... + [254.57333 253.86855 252.90517 ... 255.29681 255.3879 255.14859] + [252.33691 252.08926 251.85536 ... 252.59863 252.67467 252.5896 ] + [248.74585 248.74585 248.74585 ... 248.74585 248.74585 248.74585]] , PP Field lbyr: 1998 lbmon: 12 @@ -111,23 +105,17 @@ bplat: 90.0 bplon: 0.0 bgor: 0.0 - bzy: 92.5 - bdy: -2.5 - bzx: -3.75 - bdx: 3.75 + bzy: 92.499985 + bdy: -2.4999988 + bzx: -3.749999 + bdx: 3.749999 bmdi: -1e+30 bmks: 1.0 - data: [[ 254.64399719 254.64399719 254.64399719 ..., 254.64399719 - 254.64399719 254.64399719] - [ 254.97499084 254.96766663 254.9808197 ..., 254.98776245 - 255.03466797 254.99720764] - [ 255.99584961 256.30834961 256.55874634 ..., 256.11685181 - 255.95605469 255.83555603] - ..., - [ 254.57333374 253.86854553 252.90516663 ..., 255.29681396 - 255.38789368 255.14859009] - [ 252.33691406 252.08926392 251.85536194 ..., 252.59863281 - 252.67466736 252.58959961] - [ 248.74584961 248.74584961 248.74584961 ..., 248.74584961 - 248.74584961 248.74584961]] + data: [[254.644 254.644 254.644 ... 254.644 254.644 254.644 ] + [254.97499 254.96767 254.98082 ... 254.98776 255.03467 254.99721] + [255.99585 256.30835 256.55875 ... 256.11685 255.95605 255.83556] + ... + [254.57333 253.86855 252.90517 ... 255.29681 255.3879 255.14859] + [252.33691 252.08926 251.85536 ... 252.59863 252.67467 252.5896 ] + [248.74585 248.74585 248.74585 ... 248.74585 248.74585 248.74585]] ] \ No newline at end of file diff --git a/lib/iris/tests/results/cube_to_pp/depth.latitude.pp.txt b/lib/iris/tests/results/cube_to_pp/depth.latitude.pp.txt index a26d2cd8c5..df58efd034 100644 --- a/lib/iris/tests/results/cube_to_pp/depth.latitude.pp.txt +++ b/lib/iris/tests/results/cube_to_pp/depth.latitude.pp.txt @@ -51,14 +51,14 @@ bdx: 0.0 bmdi: -1e+30 bmks: 1.0 - data: [[ 0. 1. 2. 3.] - [ 4. 5. 6. 7.] - [ 8. 9. 10. 11.] - [ 12. 13. 14. 15.]] - x: [ 1. 2. 3. 4.] - x_lower_bound: [ 0.89999998 1.89999998 2.9000001 3.9000001 ] - x_upper_bound: [ 1.10000002 2.0999999 3.0999999 4.0999999 ] - y: [ 111. 222. 333. 444.] - y_lower_bound: [ 110.90000153 221.8999939 332.8999939 443.8999939 ] - y_upper_bound: [ 111.09999847 222.1000061 333.1000061 444.1000061 ] + data: [[ 0. 1. 2. 3.] + [ 4. 5. 6. 7.] + [ 8. 9. 10. 11.] + [12. 13. 14. 15.]] + x: [1. 2. 3. 4.] + x_lower_bound: [0.9 1.9 2.9 3.9] + x_upper_bound: [1.1 2.1 3.1 4.1] + y: [111. 222. 333. 444.] + y_lower_bound: [110.9 221.9 332.9 443.9] + y_upper_bound: [111.1 222.1 333.1 444.1] ] \ No newline at end of file diff --git a/lib/iris/tests/results/cube_to_pp/depth.time.pp.txt b/lib/iris/tests/results/cube_to_pp/depth.time.pp.txt index b57fe74572..c9a2f54b4e 100644 --- a/lib/iris/tests/results/cube_to_pp/depth.time.pp.txt +++ b/lib/iris/tests/results/cube_to_pp/depth.time.pp.txt @@ -51,14 +51,14 @@ bdx: 0.0 bmdi: -1e+30 bmks: 1.0 - data: [[ 0. 1. 2. 3.] - [ 4. 5. 6. 7.] - [ 8. 9. 10. 11.] - [ 12. 13. 14. 15.]] - x: [ 1. 2. 3. 4.] - x_lower_bound: [ 0.89999998 1.89999998 2.9000001 3.9000001 ] - x_upper_bound: [ 1.10000002 2.0999999 3.0999999 4.0999999 ] - y: [ 111. 222. 333. 444.] - y_lower_bound: [ 110.90000153 221.8999939 332.8999939 443.8999939 ] - y_upper_bound: [ 111.09999847 222.1000061 333.1000061 444.1000061 ] + data: [[ 0. 1. 2. 3.] + [ 4. 5. 6. 7.] + [ 8. 9. 10. 11.] + [12. 13. 14. 15.]] + x: [1. 2. 3. 4.] + x_lower_bound: [0.9 1.9 2.9 3.9] + x_upper_bound: [1.1 2.1 3.1 4.1] + y: [111. 222. 333. 444.] + y_lower_bound: [110.9 221.9 332.9 443.9] + y_upper_bound: [111.1 222.1 333.1 444.1] ] \ No newline at end of file diff --git a/lib/iris/tests/results/cube_to_pp/eta.latitude.pp.txt b/lib/iris/tests/results/cube_to_pp/eta.latitude.pp.txt index 9f46563fdd..a226bc7375 100644 --- a/lib/iris/tests/results/cube_to_pp/eta.latitude.pp.txt +++ b/lib/iris/tests/results/cube_to_pp/eta.latitude.pp.txt @@ -51,14 +51,14 @@ bdx: 0.0 bmdi: -1e+30 bmks: 1.0 - data: [[ 0. 1. 2. 3.] - [ 4. 5. 6. 7.] - [ 8. 9. 10. 11.] - [ 12. 13. 14. 15.]] - x: [ 1. 2. 3. 4.] - x_lower_bound: [ 0.89999998 1.89999998 2.9000001 3.9000001 ] - x_upper_bound: [ 1.10000002 2.0999999 3.0999999 4.0999999 ] - y: [ 111. 222. 333. 444.] - y_lower_bound: [ 110.90000153 221.8999939 332.8999939 443.8999939 ] - y_upper_bound: [ 111.09999847 222.1000061 333.1000061 444.1000061 ] + data: [[ 0. 1. 2. 3.] + [ 4. 5. 6. 7.] + [ 8. 9. 10. 11.] + [12. 13. 14. 15.]] + x: [1. 2. 3. 4.] + x_lower_bound: [0.9 1.9 2.9 3.9] + x_upper_bound: [1.1 2.1 3.1 4.1] + y: [111. 222. 333. 444.] + y_lower_bound: [110.9 221.9 332.9 443.9] + y_upper_bound: [111.1 222.1 333.1 444.1] ] \ No newline at end of file diff --git a/lib/iris/tests/results/cube_to_pp/no_forecast_period.cml b/lib/iris/tests/results/cube_to_pp/no_forecast_period.cml index 35048f1784..1c1e58c02b 100644 --- a/lib/iris/tests/results/cube_to_pp/no_forecast_period.cml +++ b/lib/iris/tests/results/cube_to_pp/no_forecast_period.cml @@ -1,25 +1,25 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/cube_to_pp/no_forecast_time.cml b/lib/iris/tests/results/cube_to_pp/no_forecast_time.cml index 5073bfd968..02d380a097 100644 --- a/lib/iris/tests/results/cube_to_pp/no_forecast_time.cml +++ b/lib/iris/tests/results/cube_to_pp/no_forecast_time.cml @@ -1,22 +1,22 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/cube_to_pp/pressure.latitude.pp.txt b/lib/iris/tests/results/cube_to_pp/pressure.latitude.pp.txt index 9f45c36583..115d660cd8 100644 --- a/lib/iris/tests/results/cube_to_pp/pressure.latitude.pp.txt +++ b/lib/iris/tests/results/cube_to_pp/pressure.latitude.pp.txt @@ -51,14 +51,14 @@ bdx: 0.0 bmdi: -1e+30 bmks: 1.0 - data: [[ 0. 1. 2. 3.] - [ 4. 5. 6. 7.] - [ 8. 9. 10. 11.] - [ 12. 13. 14. 15.]] - x: [ 1. 2. 3. 4.] - x_lower_bound: [ 0.89999998 1.89999998 2.9000001 3.9000001 ] - x_upper_bound: [ 1.10000002 2.0999999 3.0999999 4.0999999 ] - y: [ 111. 222. 333. 444.] - y_lower_bound: [ 110.90000153 221.8999939 332.8999939 443.8999939 ] - y_upper_bound: [ 111.09999847 222.1000061 333.1000061 444.1000061 ] + data: [[ 0. 1. 2. 3.] + [ 4. 5. 6. 7.] + [ 8. 9. 10. 11.] + [12. 13. 14. 15.]] + x: [1. 2. 3. 4.] + x_lower_bound: [0.9 1.9 2.9 3.9] + x_upper_bound: [1.1 2.1 3.1 4.1] + y: [111. 222. 333. 444.] + y_lower_bound: [110.9 221.9 332.9 443.9] + y_upper_bound: [111.1 222.1 333.1 444.1] ] \ No newline at end of file diff --git a/lib/iris/tests/results/cube_to_pp/pressure.time.pp.txt b/lib/iris/tests/results/cube_to_pp/pressure.time.pp.txt index 5e70ebb9ea..39184506fe 100644 --- a/lib/iris/tests/results/cube_to_pp/pressure.time.pp.txt +++ b/lib/iris/tests/results/cube_to_pp/pressure.time.pp.txt @@ -51,14 +51,14 @@ bdx: 0.0 bmdi: -1e+30 bmks: 1.0 - data: [[ 0. 1. 2. 3.] - [ 4. 5. 6. 7.] - [ 8. 9. 10. 11.] - [ 12. 13. 14. 15.]] - x: [ 1. 2. 3. 4.] - x_lower_bound: [ 0.89999998 1.89999998 2.9000001 3.9000001 ] - x_upper_bound: [ 1.10000002 2.0999999 3.0999999 4.0999999 ] - y: [ 111. 222. 333. 444.] - y_lower_bound: [ 110.90000153 221.8999939 332.8999939 443.8999939 ] - y_upper_bound: [ 111.09999847 222.1000061 333.1000061 444.1000061 ] + data: [[ 0. 1. 2. 3.] + [ 4. 5. 6. 7.] + [ 8. 9. 10. 11.] + [12. 13. 14. 15.]] + x: [1. 2. 3. 4.] + x_lower_bound: [0.9 1.9 2.9 3.9] + x_upper_bound: [1.1 2.1 3.1 4.1] + y: [111. 222. 333. 444.] + y_lower_bound: [110.9 221.9 332.9 443.9] + y_upper_bound: [111.1 222.1 333.1 444.1] ] \ No newline at end of file diff --git a/lib/iris/tests/results/cube_to_pp/replace_multi.txt b/lib/iris/tests/results/cube_to_pp/replace_multi.txt index 922c8906a9..41de1f0380 100644 --- a/lib/iris/tests/results/cube_to_pp/replace_multi.txt +++ b/lib/iris/tests/results/cube_to_pp/replace_multi.txt @@ -21,7 +21,7 @@ lbext: 101 lbpack: 0 lbrel: 3 - lbfc: 0 + lbfc: 19 lbcfc: 0 lbproc: 0 lbvc: 65 @@ -40,50 +40,37 @@ bacc: 0.0 blev: 5.0 brlev: 0.0 - bhlev: 0.999424 + bhlev: 0.9994238 bhrlev: 1.0 bplat: 37.5 bplon: 177.5 bgor: 0.0 bzy: -0.1287 - bdy: 0.0009 + bdy: 0.00090000004 bzx: 0.0 bdx: 0.0 bmdi: -1e+30 bmks: 1.0 - data: [[ 287.53094482 287.59091187 287.59259033 ..., 287.2557373 287.24783325 - 287.24807739] - [ 287.5128479 287.55325317 287.60549927 ..., 287.25265503 - 287.22775269 287.24221802] - [ 287.52096558 287.54098511 287.60977173 ..., 287.2253418 287.20806885 - 287.22787476] - ..., - [ 287.25546265 287.28213501 287.28268433 ..., 287.05804443 - 287.04180908 287.03646851] - [ 287.31451416 287.31658936 287.33200073 ..., 287.06240845 - 287.05044556 287.05456543] - [ 287.34872437 287.35021973 287.36239624 ..., 287.0524292 287.02581787 - 287.03649902]] - x: [ 359.57958984 359.58050537 359.58139038 359.58230591 359.58319092 - 359.58410645 359.58499146 359.58590698 359.58679199 359.58770752 - 359.58859253 359.58950806 359.59039307 359.59130859 359.5921936 - 359.59310913 359.59399414 359.59490967 359.59579468 359.59671021 - 359.59759521 359.59851074 359.59939575 359.60031128 359.60119629 - 359.60211182 359.60299683 359.60391235 359.60479736 359.60571289 - 359.6065979 359.60751343 359.60839844 359.60931396 359.61019897 - 359.6111145 359.61199951 359.61291504 359.61380005 359.61468506 - 359.61560059 359.6164856 359.61740112 359.61828613 359.61920166 - 359.62008667 359.6210022 359.62188721 359.62280273 359.62368774 - 359.62460327 359.62548828 359.62640381 359.62728882 359.62820435 - 359.62908936 359.63000488 359.63088989 359.63180542 359.63269043 - 359.63360596 359.63449097 359.63540649 359.6362915 359.63720703 - 359.63809204 359.63900757 359.63989258 359.64080811 359.64169312 - 359.64260864 359.64349365 359.64440918 359.64529419 359.64620972 - 359.64709473 359.64801025 359.64889526 359.64981079 359.6506958 - 359.65161133 359.65249634 359.65341187 359.65429688 359.6552124 - 359.65609741 359.65701294 359.65789795 359.65881348 359.65969849 - 359.66061401 359.66149902 359.66241455 359.66329956 359.66421509 - 359.6651001 359.66598511 359.66690063 359.66778564 359.66870117] + data: [[287.53094 287.5909 287.5926 ... 287.25574 287.24783 287.24808] + [287.51285 287.55325 287.6055 ... 287.25266 287.22775 287.24222] + [287.52097 287.541 287.60977 ... 287.22534 287.20807 287.22787] + ... + [287.25546 287.28214 287.28268 ... 287.05804 287.0418 287.03647] + [287.3145 287.3166 287.332 ... 287.0624 287.05045 287.05457] + [287.34872 287.35022 287.3624 ... 287.05243 287.02582 287.0365 ]] + x: [359.5796 359.5805 359.5814 359.5823 359.5832 359.5841 359.585 359.5859 + 359.5868 359.5877 359.5886 359.5895 359.5904 359.5913 359.5922 359.5931 + 359.594 359.5949 359.5958 359.5967 359.5976 359.5985 359.5994 359.6003 + 359.6012 359.6021 359.603 359.6039 359.6048 359.6057 359.6066 359.6075 + 359.6084 359.6093 359.6102 359.6111 359.612 359.6129 359.6138 359.6147 + 359.6156 359.6165 359.6174 359.6183 359.6192 359.6201 359.621 359.6219 + 359.6228 359.6237 359.6246 359.6255 359.6264 359.6273 359.6282 359.6291 + 359.63 359.6309 359.6318 359.6327 359.6336 359.6345 359.6354 359.6363 + 359.6372 359.6381 359.639 359.6399 359.6408 359.6417 359.6426 359.6435 + 359.6444 359.6453 359.6462 359.6471 359.648 359.6489 359.6498 359.6507 + 359.6516 359.6525 359.6534 359.6543 359.6552 359.6561 359.657 359.6579 + 359.6588 359.6597 359.6606 359.6615 359.6624 359.6633 359.6642 359.6651 + 359.666 359.6669 359.6678 359.6687] , PP Field lbyr: 2009 lbmon: 9 @@ -107,7 +94,7 @@ lbext: 101 lbpack: 0 lbrel: 3 - lbfc: 0 + lbfc: 19 lbcfc: 0 lbproc: 0 lbvc: 65 @@ -121,55 +108,42 @@ lbrsvd: (0, 0, 0, 0) lbsrce: 0 lbuser: (1, -99, 0, 0, 0, 0, 0) - brsvd: (33.333332, 0.99616188, 0.0, 0.0) + brsvd: (33.333332, 0.9961619, 0.0, 0.0) bdatum: 0.0 bacc: 0.0 - blev: 21.6667 - brlev: 13.3333 - bhlev: 0.997504 - bhrlev: 0.998464 + blev: 21.666664 + brlev: 13.333332 + bhlev: 0.9975044 + bhrlev: 0.99846387 bplat: 37.5 bplon: 177.5 bgor: 0.0 bzy: -0.1287 - bdy: 0.0009 + bdy: 0.00090000004 bzx: 0.0 bdx: 0.0 bmdi: -1e+30 bmks: 1.0 - data: [[ 287.66656494 287.67156982 287.67788696 ..., 287.34863281 - 287.35137939 287.3520813 ] - [ 287.64865112 287.65151978 287.65512085 ..., 287.35079956 - 287.36505127 287.38079834] - [ 287.63696289 287.6340332 287.63772583 ..., 287.33383179 - 287.36331177 287.37634277] - ..., - [ 287.43460083 287.42514038 287.42144775 ..., 287.11776733 - 287.13406372 287.1607666 ] - [ 287.44631958 287.43557739 287.43032837 ..., 287.11791992 - 287.14456177 287.15402222] - [ 287.47320557 287.4644165 287.45251465 ..., 287.09741211 - 287.11654663 287.12765503]] - x: [ 359.57958984 359.58050537 359.58139038 359.58230591 359.58319092 - 359.58410645 359.58499146 359.58590698 359.58679199 359.58770752 - 359.58859253 359.58950806 359.59039307 359.59130859 359.5921936 - 359.59310913 359.59399414 359.59490967 359.59579468 359.59671021 - 359.59759521 359.59851074 359.59939575 359.60031128 359.60119629 - 359.60211182 359.60299683 359.60391235 359.60479736 359.60571289 - 359.6065979 359.60751343 359.60839844 359.60931396 359.61019897 - 359.6111145 359.61199951 359.61291504 359.61380005 359.61468506 - 359.61560059 359.6164856 359.61740112 359.61828613 359.61920166 - 359.62008667 359.6210022 359.62188721 359.62280273 359.62368774 - 359.62460327 359.62548828 359.62640381 359.62728882 359.62820435 - 359.62908936 359.63000488 359.63088989 359.63180542 359.63269043 - 359.63360596 359.63449097 359.63540649 359.6362915 359.63720703 - 359.63809204 359.63900757 359.63989258 359.64080811 359.64169312 - 359.64260864 359.64349365 359.64440918 359.64529419 359.64620972 - 359.64709473 359.64801025 359.64889526 359.64981079 359.6506958 - 359.65161133 359.65249634 359.65341187 359.65429688 359.6552124 - 359.65609741 359.65701294 359.65789795 359.65881348 359.65969849 - 359.66061401 359.66149902 359.66241455 359.66329956 359.66421509 - 359.6651001 359.66598511 359.66690063 359.66778564 359.66870117] + data: [[287.66656 287.67157 287.6779 ... 287.34863 287.35138 287.35208] + [287.64865 287.65152 287.65512 ... 287.3508 287.36505 287.3808 ] + [287.63696 287.63403 287.63773 ... 287.33383 287.3633 287.37634] + ... + [287.4346 287.42514 287.42145 ... 287.11777 287.13406 287.16077] + [287.44632 287.43558 287.43033 ... 287.11792 287.14456 287.15402] + [287.4732 287.46442 287.4525 ... 287.0974 287.11655 287.12766]] + x: [359.5796 359.5805 359.5814 359.5823 359.5832 359.5841 359.585 359.5859 + 359.5868 359.5877 359.5886 359.5895 359.5904 359.5913 359.5922 359.5931 + 359.594 359.5949 359.5958 359.5967 359.5976 359.5985 359.5994 359.6003 + 359.6012 359.6021 359.603 359.6039 359.6048 359.6057 359.6066 359.6075 + 359.6084 359.6093 359.6102 359.6111 359.612 359.6129 359.6138 359.6147 + 359.6156 359.6165 359.6174 359.6183 359.6192 359.6201 359.621 359.6219 + 359.6228 359.6237 359.6246 359.6255 359.6264 359.6273 359.6282 359.6291 + 359.63 359.6309 359.6318 359.6327 359.6336 359.6345 359.6354 359.6363 + 359.6372 359.6381 359.639 359.6399 359.6408 359.6417 359.6426 359.6435 + 359.6444 359.6453 359.6462 359.6471 359.648 359.6489 359.6498 359.6507 + 359.6516 359.6525 359.6534 359.6543 359.6552 359.6561 359.657 359.6579 + 359.6588 359.6597 359.6606 359.6615 359.6624 359.6633 359.6642 359.6651 + 359.666 359.6669 359.6678 359.6687] , PP Field lbyr: 2009 lbmon: 9 @@ -193,7 +167,7 @@ lbext: 101 lbpack: 0 lbrel: 3 - lbfc: 0 + lbfc: 19 lbcfc: 0 lbproc: 0 lbvc: 65 @@ -212,50 +186,37 @@ bacc: 0.0 blev: 5.0 brlev: 0.0 - bhlev: 0.999424 + bhlev: 0.9994238 bhrlev: 1.0 bplat: 37.5 bplon: 177.5 bgor: 0.0 bzy: -0.1287 - bdy: 0.0009 + bdy: 0.00090000004 bzx: 0.0 bdx: 0.0 bmdi: -1e+30 bmks: 1.0 - data: [[ 287.34893799 287.42550659 287.40127563 ..., 286.95541382 - 286.96194458 286.96682739] - [ 287.30154419 287.37628174 287.42120361 ..., 286.93814087 - 286.93344116 286.96240234] - [ 287.2989502 287.34576416 287.42221069 ..., 286.89581299 - 286.89935303 286.94052124] - ..., - [ 287.08889771 287.11340332 287.12139893 ..., 286.87512207 - 286.84820557 286.84524536] - [ 287.16998291 287.16873169 287.18426514 ..., 286.87496948 - 286.87020874 286.87353516] - [ 287.21185303 287.21325684 287.22512817 ..., 286.83877563 - 286.82666016 286.83929443]] - x: [ 359.57958984 359.58050537 359.58139038 359.58230591 359.58319092 - 359.58410645 359.58499146 359.58590698 359.58679199 359.58770752 - 359.58859253 359.58950806 359.59039307 359.59130859 359.5921936 - 359.59310913 359.59399414 359.59490967 359.59579468 359.59671021 - 359.59759521 359.59851074 359.59939575 359.60031128 359.60119629 - 359.60211182 359.60299683 359.60391235 359.60479736 359.60571289 - 359.6065979 359.60751343 359.60839844 359.60931396 359.61019897 - 359.6111145 359.61199951 359.61291504 359.61380005 359.61468506 - 359.61560059 359.6164856 359.61740112 359.61828613 359.61920166 - 359.62008667 359.6210022 359.62188721 359.62280273 359.62368774 - 359.62460327 359.62548828 359.62640381 359.62728882 359.62820435 - 359.62908936 359.63000488 359.63088989 359.63180542 359.63269043 - 359.63360596 359.63449097 359.63540649 359.6362915 359.63720703 - 359.63809204 359.63900757 359.63989258 359.64080811 359.64169312 - 359.64260864 359.64349365 359.64440918 359.64529419 359.64620972 - 359.64709473 359.64801025 359.64889526 359.64981079 359.6506958 - 359.65161133 359.65249634 359.65341187 359.65429688 359.6552124 - 359.65609741 359.65701294 359.65789795 359.65881348 359.65969849 - 359.66061401 359.66149902 359.66241455 359.66329956 359.66421509 - 359.6651001 359.66598511 359.66690063 359.66778564 359.66870117] + data: [[287.34894 287.4255 287.40128 ... 286.9554 286.96194 286.96683] + [287.30154 287.37628 287.4212 ... 286.93814 286.93344 286.9624 ] + [287.29895 287.34576 287.4222 ... 286.8958 286.89935 286.94052] + ... + [287.0889 287.1134 287.1214 ... 286.87512 286.8482 286.84525] + [287.16998 287.16873 287.18427 ... 286.87497 286.8702 286.87354] + [287.21185 287.21326 287.22513 ... 286.83878 286.82666 286.8393 ]] + x: [359.5796 359.5805 359.5814 359.5823 359.5832 359.5841 359.585 359.5859 + 359.5868 359.5877 359.5886 359.5895 359.5904 359.5913 359.5922 359.5931 + 359.594 359.5949 359.5958 359.5967 359.5976 359.5985 359.5994 359.6003 + 359.6012 359.6021 359.603 359.6039 359.6048 359.6057 359.6066 359.6075 + 359.6084 359.6093 359.6102 359.6111 359.612 359.6129 359.6138 359.6147 + 359.6156 359.6165 359.6174 359.6183 359.6192 359.6201 359.621 359.6219 + 359.6228 359.6237 359.6246 359.6255 359.6264 359.6273 359.6282 359.6291 + 359.63 359.6309 359.6318 359.6327 359.6336 359.6345 359.6354 359.6363 + 359.6372 359.6381 359.639 359.6399 359.6408 359.6417 359.6426 359.6435 + 359.6444 359.6453 359.6462 359.6471 359.648 359.6489 359.6498 359.6507 + 359.6516 359.6525 359.6534 359.6543 359.6552 359.6561 359.657 359.6579 + 359.6588 359.6597 359.6606 359.6615 359.6624 359.6633 359.6642 359.6651 + 359.666 359.6669 359.6678 359.6687] , PP Field lbyr: 2009 lbmon: 9 @@ -279,7 +240,7 @@ lbext: 101 lbpack: 0 lbrel: 3 - lbfc: 0 + lbfc: 19 lbcfc: 0 lbproc: 0 lbvc: 65 @@ -293,53 +254,40 @@ lbrsvd: (0, 0, 0, 0) lbsrce: 0 lbuser: (1, -99, 0, 0, 0, 0, 0) - brsvd: (33.333332, 0.99616188, 0.0, 0.0) + brsvd: (33.333332, 0.9961619, 0.0, 0.0) bdatum: 0.0 bacc: 0.0 - blev: 21.6667 - brlev: 13.3333 - bhlev: 0.997504 - bhrlev: 0.998464 + blev: 21.666664 + brlev: 13.333332 + bhlev: 0.9975044 + bhrlev: 0.99846387 bplat: 37.5 bplon: 177.5 bgor: 0.0 bzy: -0.1287 - bdy: 0.0009 + bdy: 0.00090000004 bzx: 0.0 bdx: 0.0 bmdi: -1e+30 bmks: 1.0 - data: [[ 287.53091431 287.53164673 287.5319519 ..., 287.08203125 - 287.09094238 287.09213257] - [ 287.51821899 287.52059937 287.52099609 ..., 287.07635498 - 287.10369873 287.12637329] - [ 287.50125122 287.50241089 287.50982666 ..., 287.04663086 - 287.09860229 287.12164307] - ..., - [ 287.32684326 287.31106567 287.30667114 ..., 286.9911499 287.01681519 - 287.04400635] - [ 287.33877563 287.3223877 287.3117981 ..., 287.00402832 287.0345459 - 287.03637695] - [ 287.36621094 287.35803223 287.33911133 ..., 286.95663452 - 286.98605347 286.99371338]] - x: [ 359.57958984 359.58050537 359.58139038 359.58230591 359.58319092 - 359.58410645 359.58499146 359.58590698 359.58679199 359.58770752 - 359.58859253 359.58950806 359.59039307 359.59130859 359.5921936 - 359.59310913 359.59399414 359.59490967 359.59579468 359.59671021 - 359.59759521 359.59851074 359.59939575 359.60031128 359.60119629 - 359.60211182 359.60299683 359.60391235 359.60479736 359.60571289 - 359.6065979 359.60751343 359.60839844 359.60931396 359.61019897 - 359.6111145 359.61199951 359.61291504 359.61380005 359.61468506 - 359.61560059 359.6164856 359.61740112 359.61828613 359.61920166 - 359.62008667 359.6210022 359.62188721 359.62280273 359.62368774 - 359.62460327 359.62548828 359.62640381 359.62728882 359.62820435 - 359.62908936 359.63000488 359.63088989 359.63180542 359.63269043 - 359.63360596 359.63449097 359.63540649 359.6362915 359.63720703 - 359.63809204 359.63900757 359.63989258 359.64080811 359.64169312 - 359.64260864 359.64349365 359.64440918 359.64529419 359.64620972 - 359.64709473 359.64801025 359.64889526 359.64981079 359.6506958 - 359.65161133 359.65249634 359.65341187 359.65429688 359.6552124 - 359.65609741 359.65701294 359.65789795 359.65881348 359.65969849 - 359.66061401 359.66149902 359.66241455 359.66329956 359.66421509 - 359.6651001 359.66598511 359.66690063 359.66778564 359.66870117] + data: [[287.5309 287.53165 287.53195 ... 287.08203 287.09094 287.09213] + [287.51822 287.5206 287.521 ... 287.07635 287.1037 287.12637] + [287.50125 287.5024 287.50983 ... 287.04663 287.0986 287.12164] + ... + [287.32684 287.31107 287.30667 ... 286.99115 287.0168 287.044 ] + [287.33878 287.3224 287.3118 ... 287.00403 287.03455 287.03638] + [287.3662 287.35803 287.3391 ... 286.95663 286.98605 286.9937 ]] + x: [359.5796 359.5805 359.5814 359.5823 359.5832 359.5841 359.585 359.5859 + 359.5868 359.5877 359.5886 359.5895 359.5904 359.5913 359.5922 359.5931 + 359.594 359.5949 359.5958 359.5967 359.5976 359.5985 359.5994 359.6003 + 359.6012 359.6021 359.603 359.6039 359.6048 359.6057 359.6066 359.6075 + 359.6084 359.6093 359.6102 359.6111 359.612 359.6129 359.6138 359.6147 + 359.6156 359.6165 359.6174 359.6183 359.6192 359.6201 359.621 359.6219 + 359.6228 359.6237 359.6246 359.6255 359.6264 359.6273 359.6282 359.6291 + 359.63 359.6309 359.6318 359.6327 359.6336 359.6345 359.6354 359.6363 + 359.6372 359.6381 359.639 359.6399 359.6408 359.6417 359.6426 359.6435 + 359.6444 359.6453 359.6462 359.6471 359.648 359.6489 359.6498 359.6507 + 359.6516 359.6525 359.6534 359.6543 359.6552 359.6561 359.657 359.6579 + 359.6588 359.6597 359.6606 359.6615 359.6624 359.6633 359.6642 359.6651 + 359.666 359.6669 359.6678 359.6687] ] \ No newline at end of file diff --git a/lib/iris/tests/results/cube_to_pp/replace_single.txt b/lib/iris/tests/results/cube_to_pp/replace_single.txt index c5fdb48515..15e47d2f91 100644 --- a/lib/iris/tests/results/cube_to_pp/replace_single.txt +++ b/lib/iris/tests/results/cube_to_pp/replace_single.txt @@ -45,23 +45,17 @@ bplat: 90.0 bplon: 0.0 bgor: 0.0 - bzy: 92.5 - bdy: -2.5 - bzx: -3.75 - bdx: 3.75 + bzy: 92.499985 + bdy: -2.4999988 + bzx: -3.749999 + bdx: 3.749999 bmdi: -1e+30 bmks: 1.0 - data: [[ 254.64399719 254.64399719 254.64399719 ..., 254.64399719 - 254.64399719 254.64399719] - [ 254.97499084 254.96766663 254.9808197 ..., 254.98776245 - 255.03466797 254.99720764] - [ 255.99584961 256.30834961 256.55874634 ..., 256.11685181 - 255.95605469 255.83555603] - ..., - [ 254.57333374 253.86854553 252.90516663 ..., 255.29681396 - 255.38789368 255.14859009] - [ 252.33691406 252.08926392 251.85536194 ..., 252.59863281 - 252.67466736 252.58959961] - [ 248.74584961 248.74584961 248.74584961 ..., 248.74584961 - 248.74584961 248.74584961]] + data: [[254.644 254.644 254.644 ... 254.644 254.644 254.644 ] + [254.97499 254.96767 254.98082 ... 254.98776 255.03467 254.99721] + [255.99585 256.30835 256.55875 ... 256.11685 255.95605 255.83556] + ... + [254.57333 253.86855 252.90517 ... 255.29681 255.3879 255.14859] + [252.33691 252.08926 251.85536 ... 252.59863 252.67467 252.5896 ] + [248.74585 248.74585 248.74585 ... 248.74585 248.74585 248.74585]] ] \ No newline at end of file diff --git a/lib/iris/tests/results/cube_to_pp/simple.txt b/lib/iris/tests/results/cube_to_pp/simple.txt index c5fdb48515..15e47d2f91 100644 --- a/lib/iris/tests/results/cube_to_pp/simple.txt +++ b/lib/iris/tests/results/cube_to_pp/simple.txt @@ -45,23 +45,17 @@ bplat: 90.0 bplon: 0.0 bgor: 0.0 - bzy: 92.5 - bdy: -2.5 - bzx: -3.75 - bdx: 3.75 + bzy: 92.499985 + bdy: -2.4999988 + bzx: -3.749999 + bdx: 3.749999 bmdi: -1e+30 bmks: 1.0 - data: [[ 254.64399719 254.64399719 254.64399719 ..., 254.64399719 - 254.64399719 254.64399719] - [ 254.97499084 254.96766663 254.9808197 ..., 254.98776245 - 255.03466797 254.99720764] - [ 255.99584961 256.30834961 256.55874634 ..., 256.11685181 - 255.95605469 255.83555603] - ..., - [ 254.57333374 253.86854553 252.90516663 ..., 255.29681396 - 255.38789368 255.14859009] - [ 252.33691406 252.08926392 251.85536194 ..., 252.59863281 - 252.67466736 252.58959961] - [ 248.74584961 248.74584961 248.74584961 ..., 248.74584961 - 248.74584961 248.74584961]] + data: [[254.644 254.644 254.644 ... 254.644 254.644 254.644 ] + [254.97499 254.96767 254.98082 ... 254.98776 255.03467 254.99721] + [255.99585 256.30835 256.55875 ... 256.11685 255.95605 255.83556] + ... + [254.57333 253.86855 252.90517 ... 255.29681 255.3879 255.14859] + [252.33691 252.08926 251.85536 ... 252.59863 252.67467 252.5896 ] + [248.74585 248.74585 248.74585 ... 248.74585 248.74585 248.74585]] ] \ No newline at end of file diff --git a/lib/iris/tests/results/derived/column.cml b/lib/iris/tests/results/derived/column.cml index 76e02b136f..e4402b4e4d 100644 --- a/lib/iris/tests/results/derived/column.cml +++ b/lib/iris/tests/results/derived/column.cml @@ -1,6 +1,6 @@ - + @@ -12,7 +12,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="c56f646c" points="[418.698, 434.57, 456.793, 485.366, 520.293, + [37922.5, 42077.5]]" id="9041e969" points="[418.698, 434.57, 456.793, 485.366, 520.293, 561.575, 609.214, 663.214, 723.577, 790.307, 863.407, 942.882, 1028.74, 1120.98, 1219.61, 1324.63, 1436.06, 1553.89, 1678.14, 1808.81, @@ -32,15 +32,15 @@ - + - + - + @@ -51,7 +51,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -71,7 +71,7 @@ - - + - - + diff --git a/lib/iris/tests/results/derived/no_orog.cml b/lib/iris/tests/results/derived/no_orog.cml index b529e80f14..ec0ffdd5ff 100644 --- a/lib/iris/tests/results/derived/no_orog.cml +++ b/lib/iris/tests/results/derived/no_orog.cml @@ -1,6 +1,6 @@ - + @@ -12,7 +12,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="c56f646c" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="9041e969" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -32,7 +32,7 @@ - + @@ -53,7 +53,7 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> @@ -65,7 +65,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -85,7 +85,7 @@ - - + 300.34]]" shape="(100, 100)" standard_name="surface_altitude" units="Unit('m')" value_type="float32"/> - - + diff --git a/lib/iris/tests/results/derived/removed_orog.cml b/lib/iris/tests/results/derived/removed_orog.cml index bdc2ba630d..4c30ec69bc 100644 --- a/lib/iris/tests/results/derived/removed_orog.cml +++ b/lib/iris/tests/results/derived/removed_orog.cml @@ -1,6 +1,6 @@ - + @@ -12,7 +12,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="c56f646c" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="9041e969" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -32,7 +32,7 @@ - + @@ -53,7 +53,7 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> @@ -65,7 +65,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -85,7 +85,7 @@ - - - + diff --git a/lib/iris/tests/results/derived/removed_sigma.cml b/lib/iris/tests/results/derived/removed_sigma.cml index 78168f9138..ea34680b7d 100644 --- a/lib/iris/tests/results/derived/removed_sigma.cml +++ b/lib/iris/tests/results/derived/removed_sigma.cml @@ -1,388 +1,388 @@ - + + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + ..., + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0]]]" shape="(70, 100, 100)" standard_name="altitude" units="Unit('m')" value_type="float32"> - + @@ -403,7 +403,7 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> @@ -415,7 +415,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -435,7 +435,7 @@ - - + 300.34]]" shape="(100, 100)" standard_name="surface_altitude" units="Unit('m')" value_type="float32"/> - - + diff --git a/lib/iris/tests/results/derived/transposed.cml b/lib/iris/tests/results/derived/transposed.cml index a4ab06efd9..eef077d774 100644 --- a/lib/iris/tests/results/derived/transposed.cml +++ b/lib/iris/tests/results/derived/transposed.cml @@ -1,400 +1,400 @@ - + + 35845.0, 40000.0], + [334.817, 350.85, 373.297, ..., 32192.7, + 35845.0, 40000.0], + [333.031, 349.068, 371.52, ..., 32192.7, + 35845.0, 40000.0], + ..., + [314.701, 330.773, 353.275, ..., 32192.7, + 35845.0, 40000.0], + [315.121, 331.192, 353.693, ..., 32192.7, + 35845.0, 40000.0], + [305.167, 321.257, 343.784, ..., 32192.7, + 35845.0, 40000.0]]]" shape="(100, 100, 70)" standard_name="altitude" units="Unit('m')" value_type="float32"> - + @@ -415,7 +415,7 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> @@ -427,7 +427,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -447,7 +447,7 @@ - - + 300.34]]" shape="(100, 100)" standard_name="surface_altitude" units="Unit('m')" value_type="float32"/> - - + diff --git a/lib/iris/tests/results/experimental/analysis/interpolate/LinearInterpolator/basic_orthogonal_cube.cml b/lib/iris/tests/results/experimental/analysis/interpolate/LinearInterpolator/basic_orthogonal_cube.cml new file mode 100644 index 0000000000..f06d8d7970 --- /dev/null +++ b/lib/iris/tests/results/experimental/analysis/interpolate/LinearInterpolator/basic_orthogonal_cube.cml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/experimental/analysis/interpolate/LinearInterpolator/basic_orthogonal_cube.data.0.json b/lib/iris/tests/results/experimental/analysis/interpolate/LinearInterpolator/basic_orthogonal_cube.data.0.json new file mode 100644 index 0000000000..e9e8754bee --- /dev/null +++ b/lib/iris/tests/results/experimental/analysis/interpolate/LinearInterpolator/basic_orthogonal_cube.data.0.json @@ -0,0 +1 @@ +{"std": 6.551081657409668, "min": 0.0, "max": 21.0, "shape": [3, 3, 2], "masked": false, "mean": 12.5} \ No newline at end of file diff --git a/lib/iris/tests/results/experimental/analysis/interpolate/LinearInterpolator/orthogonal_cube_1d_squashed.cml b/lib/iris/tests/results/experimental/analysis/interpolate/LinearInterpolator/orthogonal_cube_1d_squashed.cml new file mode 100644 index 0000000000..b2b33c4276 --- /dev/null +++ b/lib/iris/tests/results/experimental/analysis/interpolate/LinearInterpolator/orthogonal_cube_1d_squashed.cml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/experimental/analysis/interpolate/LinearInterpolator/orthogonal_cube_1d_squashed.data.0.json b/lib/iris/tests/results/experimental/analysis/interpolate/LinearInterpolator/orthogonal_cube_1d_squashed.data.0.json new file mode 100644 index 0000000000..5b8ba329e1 --- /dev/null +++ b/lib/iris/tests/results/experimental/analysis/interpolate/LinearInterpolator/orthogonal_cube_1d_squashed.data.0.json @@ -0,0 +1 @@ +{"std": 3.3040380477905273, "min": 0.0, "max": 9.0, "shape": [3, 2], "masked": false, "mean": 4.5} \ No newline at end of file diff --git a/lib/iris/tests/results/experimental/analysis/interpolate/LinearInterpolator/orthogonal_cube_1d_squashed_2.cml b/lib/iris/tests/results/experimental/analysis/interpolate/LinearInterpolator/orthogonal_cube_1d_squashed_2.cml new file mode 100644 index 0000000000..422826f7fd --- /dev/null +++ b/lib/iris/tests/results/experimental/analysis/interpolate/LinearInterpolator/orthogonal_cube_1d_squashed_2.cml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/experimental/analysis/interpolate/LinearInterpolator/orthogonal_cube_with_factory.cml b/lib/iris/tests/results/experimental/analysis/interpolate/LinearInterpolator/orthogonal_cube_with_factory.cml new file mode 100644 index 0000000000..1bb899c558 --- /dev/null +++ b/lib/iris/tests/results/experimental/analysis/interpolate/LinearInterpolator/orthogonal_cube_with_factory.cml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/experimental/analysis/interpolate/linear_nd.cml b/lib/iris/tests/results/experimental/analysis/interpolate/linear_nd.cml new file mode 100644 index 0000000000..05a31d7eda --- /dev/null +++ b/lib/iris/tests/results/experimental/analysis/interpolate/linear_nd.cml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/experimental/analysis/interpolate/linear_nd.data.0.json b/lib/iris/tests/results/experimental/analysis/interpolate/linear_nd.data.0.json new file mode 100644 index 0000000000..6778a301c3 --- /dev/null +++ b/lib/iris/tests/results/experimental/analysis/interpolate/linear_nd.data.0.json @@ -0,0 +1 @@ +{"std": 3.4520525932312012, "min": 6.0, "max": 17.0, "shape": [3, 4], "masked": false, "mean": 11.5} \ No newline at end of file diff --git a/lib/iris/tests/results/experimental/analysis/interpolate/linear_nd_2_coords.cml b/lib/iris/tests/results/experimental/analysis/interpolate/linear_nd_2_coords.cml new file mode 100644 index 0000000000..d35209f137 --- /dev/null +++ b/lib/iris/tests/results/experimental/analysis/interpolate/linear_nd_2_coords.cml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/experimental/analysis/interpolate/linear_nd_2_coords.data.0.json b/lib/iris/tests/results/experimental/analysis/interpolate/linear_nd_2_coords.data.0.json new file mode 100644 index 0000000000..b85c1c8353 --- /dev/null +++ b/lib/iris/tests/results/experimental/analysis/interpolate/linear_nd_2_coords.data.0.json @@ -0,0 +1 @@ +{"std": 6.0, "min": 7.5, "max": 19.5, "shape": [2], "masked": false, "mean": 13.5} \ No newline at end of file diff --git a/lib/iris/tests/results/experimental/analysis/interpolate/linear_nd_with_extrapolation.cml b/lib/iris/tests/results/experimental/analysis/interpolate/linear_nd_with_extrapolation.cml new file mode 100644 index 0000000000..41bf5bfa0b --- /dev/null +++ b/lib/iris/tests/results/experimental/analysis/interpolate/linear_nd_with_extrapolation.cml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/experimental/analysis/interpolate/linear_nd_with_extrapolation.data.0.json b/lib/iris/tests/results/experimental/analysis/interpolate/linear_nd_with_extrapolation.data.0.json new file mode 100644 index 0000000000..1c18659523 --- /dev/null +++ b/lib/iris/tests/results/experimental/analysis/interpolate/linear_nd_with_extrapolation.data.0.json @@ -0,0 +1 @@ +{"std": 3.4520523548126221, "min": -5.1000003814697266, "max": 5.899998664855957, "shape": [3, 4], "masked": false, "mean": 0.39999952912330627} \ No newline at end of file diff --git a/lib/iris/tests/results/experimental/raster/SMALL_total_column_co2.nc.ma.tif_header.txt b/lib/iris/tests/results/experimental/raster/SMALL_total_column_co2.nc.ma.tif_header.txt deleted file mode 100644 index bd26365867..0000000000 --- a/lib/iris/tests/results/experimental/raster/SMALL_total_column_co2.nc.ma.tif_header.txt +++ /dev/null @@ -1,14 +0,0 @@ -(256, (160,)) -(257, (159,)) -(258, (32,)) -(259, (1,)) -(262, (1,)) -(273, (354, 8034, 15714, 23394, 31074, 38754, 46434, 54114, 61794, 69474, 77154, 84834, 92514, 100194)) -(277, (1,)) -(278, (12,)) -(279, (7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 1920)) -(284, (1,)) -(339, (3,)) -(33550, (1.125, 1.125, 0.0)) -(33922, (0.0, 0.0, 0.0, -0.5625, 89.4375, 0.0)) -(42113, '1e+20') \ No newline at end of file diff --git a/lib/iris/tests/results/experimental/raster/SMALL_total_column_co2.nc.tif_header.txt b/lib/iris/tests/results/experimental/raster/SMALL_total_column_co2.nc.tif_header.txt deleted file mode 100644 index bb41244e6c..0000000000 --- a/lib/iris/tests/results/experimental/raster/SMALL_total_column_co2.nc.tif_header.txt +++ /dev/null @@ -1,13 +0,0 @@ -(256, (160,)) -(257, (159,)) -(258, (32,)) -(259, (1,)) -(262, (1,)) -(273, (354, 8034, 15714, 23394, 31074, 38754, 46434, 54114, 61794, 69474, 77154, 84834, 92514, 100194)) -(277, (1,)) -(278, (12,)) -(279, (7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 1920)) -(284, (1,)) -(339, (3,)) -(33550, (1.125, 1.125, 0.0)) -(33922, (0.0, 0.0, 0.0, -0.5625, 89.4375, 0.0)) \ No newline at end of file diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lat_cross_section.cml b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lat_cross_section.cml index 5eac18f9cc..585657b642 100644 --- a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lat_cross_section.cml +++ b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lat_cross_section.cml @@ -1,15 +1,15 @@ - + - + - + @@ -31,7 +31,7 @@ [359.600145123, 359.601643874], [359.601643874, 359.603142625], [359.603142625, 359.604641377], - [359.604641377, 359.606140128]]" id="5036c64b" points="[359.579911982, 359.581410733, 359.582909484, + [359.604641377, 359.606140128]]" id="d3676747" points="[359.579911982, 359.581410733, 359.582909484, 359.584408236, 359.585906987, 359.587405738, 359.588904489, 359.59040324, 359.591901992, 359.593400743, 359.594899494, 359.596398245, @@ -45,14 +45,14 @@ [13.3333, 33.3333], [33.3333, 60.0], [60.0, 93.3333], - [93.3333, 133.333]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667]" shape="(5,)" units="Unit('m')" value_type="float32"> + [93.3333, 133.333]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667]" shape="(5,)" units="Unit('m')" value_type="float32"> - + @@ -63,13 +63,13 @@ [0.998464, 0.996162], [0.996162, 0.993097], [0.993097, 0.989272], - [0.989272, 0.984692]]" id="5f88ebd6" long_name="sigma" points="[0.999424, 0.997504, 0.99482, 0.991375, 0.987171]" shape="(5,)" units="Unit('1')" value_type="float32"/> + [0.989272, 0.984692]]" id="a5c170db" long_name="sigma" points="[0.999424, 0.997504, 0.99482, 0.991375, 0.987171]" shape="(5,)" units="Unit('1')" value_type="float32"/> - + - + diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lat_cross_section.data.0.json b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lat_cross_section.data.0.json new file mode 100644 index 0000000000..0c2b277ef0 --- /dev/null +++ b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lat_cross_section.data.0.json @@ -0,0 +1 @@ +{"std": 0.04919414967298508, "min": 287.8340148925781, "max": 288.0903625488281, "shape": [5, 18], "masked": false, "mean": 288.0065002441406} \ No newline at end of file diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lat_cross_section.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lat_cross_section.data.0.npy deleted file mode 100644 index 07af002dea..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lat_cross_section.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lon_cross_section.cml b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lon_cross_section.cml index 93fbbf680b..4e928851fe 100644 --- a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lon_cross_section.cml +++ b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lon_cross_section.cml @@ -1,12 +1,12 @@ - + - + + @@ -39,14 +39,14 @@ [13.3333, 33.3333], [33.3333, 60.0], [60.0, 93.3333], - [93.3333, 133.333]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667]" shape="(5,)" units="Unit('m')" value_type="float32"> + [93.3333, 133.333]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667]" shape="(5,)" units="Unit('m')" value_type="float32"> - + @@ -57,13 +57,13 @@ [0.998464, 0.996162], [0.996162, 0.993097], [0.993097, 0.989272], - [0.989272, 0.984692]]" id="5f88ebd6" long_name="sigma" points="[0.999424, 0.997504, 0.99482, 0.991375, 0.987171]" shape="(5,)" units="Unit('1')" value_type="float32"/> + [0.989272, 0.984692]]" id="a5c170db" long_name="sigma" points="[0.999424, 0.997504, 0.99482, 0.991375, 0.987171]" shape="(5,)" units="Unit('1')" value_type="float32"/> - + - + diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lon_cross_section.data.0.json b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lon_cross_section.data.0.json new file mode 100644 index 0000000000..02772d9262 --- /dev/null +++ b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lon_cross_section.data.0.json @@ -0,0 +1 @@ +{"std": 0.05311942473053932, "min": 287.9081115722656, "max": 288.14678955078125, "shape": [5, 12], "masked": false, "mean": 288.02642822265625} \ No newline at end of file diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lon_cross_section.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lon_cross_section.data.0.npy deleted file mode 100644 index e512bd9332..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/const_lon_cross_section.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/higher.cml b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/higher.cml index ac096896b1..6c7779ff9f 100644 --- a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/higher.cml +++ b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/higher.cml @@ -1,6 +1,6 @@ - + @@ -32,7 +32,7 @@ [1.85713857143, 2.14285142857], [2.14285142857, 2.42856428571], [2.42856428571, 2.71427714286], - [2.71427714286, 2.99999]]" id="63128986" points="[-0.857133571429, -0.571420714286, + [2.71427714286, 2.99999]]" id="f913a8b3" points="[-0.857133571429, -0.571420714286, -0.285707857143, 5.00000000006e-06, 0.285717857143, 0.571430714286, 0.857143571429, 1.14285642857, 1.42856928571, 1.71428214286, @@ -43,6 +43,6 @@ - + diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/higher.data.0.json b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/higher.data.0.json new file mode 100644 index 0000000000..ca78693c58 --- /dev/null +++ b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/higher.data.0.json @@ -0,0 +1 @@ +{"std": 3.3421254401075182, "min": 0.0, "max": 11.0, "shape": [10, 14], "masked": false, "mean": 5.4999959381734458} \ No newline at end of file diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/higher.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/higher.data.0.npy deleted file mode 100644 index 28ac6fc5d3..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/higher.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/hybridheight.cml b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/hybridheight.cml index 383c309a41..31a753c059 100644 --- a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/hybridheight.cml +++ b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/hybridheight.cml @@ -1,334 +1,334 @@ - + - + - + + [93.3333, 133.333]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667]" shape="(5,)" units="Unit('m')" value_type="float32"> - + @@ -411,28 +411,28 @@ [0.998464, 0.996162], [0.996162, 0.993097], [0.993097, 0.989272], - [0.989272, 0.984692]]" id="5f88ebd6" long_name="sigma" points="[0.999424, 0.997504, 0.99482, 0.991375, 0.987171]" shape="(5,)" units="Unit('1')" value_type="float32"/> + [0.989272, 0.984692]]" id="a5c170db" long_name="sigma" points="[0.999424, 0.997504, 0.99482, 0.991375, 0.987171]" shape="(5,)" units="Unit('1')" value_type="float32"/> - + [495.303, 484.127, 468.996, ..., 242.443, + 239.918, 228.994], + [478.725, 468.312, 457.374, ..., 226.355, + 224.345, 220.717], + [457.115, 446.227, 439.824, ..., 220.517, + 218.732, 216.367]]" shape="(16, 21)" standard_name="surface_altitude" units="Unit('m')" value_type="float32"/> - + - + diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/hybridheight.data.0.json b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/hybridheight.data.0.json new file mode 100644 index 0000000000..bdc0cad306 --- /dev/null +++ b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/hybridheight.data.0.json @@ -0,0 +1 @@ +{"std": 0.10611984878778458, "min": 287.595703125, "max": 288.1650695800781, "shape": [2, 5, 16, 21], "masked": false, "mean": 287.91802978515625} \ No newline at end of file diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/hybridheight.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/hybridheight.data.0.npy deleted file mode 100644 index 2a7043b2a8..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/hybridheight.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/latlonreduced.cml b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/latlonreduced.cml index 5a22cbb4c8..803a54ce67 100644 --- a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/latlonreduced.cml +++ b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/latlonreduced.cml @@ -1,21 +1,21 @@ - + + [1.0, 2.0]]" id="77a50eb5" points="[-1, 1]" shape="(2,)" standard_name="latitude" units="Unit('degrees')" value_type="int32"> + [1.0, 3.0]]" id="f913a8b3" points="[-1, 1]" shape="(2,)" standard_name="longitude" units="Unit('degrees')" value_type="int32"> - + diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/latlonreduced.data.0.json b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/latlonreduced.data.0.json new file mode 100644 index 0000000000..afc254dc97 --- /dev/null +++ b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/latlonreduced.data.0.json @@ -0,0 +1 @@ +{"std": 3.1622776601683786, "min": 2.5, "max": 10.499999999999998, "shape": [2, 2], "masked": false, "mean": 6.5} \ No newline at end of file diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/latlonreduced.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/latlonreduced.data.0.npy deleted file mode 100644 index c70ff258cf..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/latlonreduced.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lonhalved.cml b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lonhalved.cml index 56f1541a8d..fb937c1729 100644 --- a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lonhalved.cml +++ b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lonhalved.cml @@ -1,22 +1,22 @@ - + + [0.999996666667, 1.99999]]" id="77a50eb5" points="[-0.499993333333, 0.5, 1.49999333333]" shape="(3,)" standard_name="latitude" units="Unit('degrees')" value_type="float64"> + [1.0, 2.99999]]" id="f913a8b3" points="[4.99999999992e-06, 1.999995]" shape="(2,)" standard_name="longitude" units="Unit('degrees')" value_type="float64"> - + diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lonhalved.data.0.json b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lonhalved.data.0.json new file mode 100644 index 0000000000..902c6b1ccc --- /dev/null +++ b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lonhalved.data.0.json @@ -0,0 +1 @@ +{"std": 3.4156391123995582, "min": 0.50001583411168193, "max": 10.499984163856872, "shape": [3, 2], "masked": false, "mean": 5.4999999993228519} \ No newline at end of file diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lonhalved.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lonhalved.data.0.npy deleted file mode 100644 index f37374a16e..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lonhalved.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lower.cml b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lower.cml index 814e368d0f..c324683476 100644 --- a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lower.cml +++ b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lower.cml @@ -1,22 +1,22 @@ - + + [0.5, 1.99999]]" id="77a50eb5" points="[-0.249995, 1.249995]" shape="(2,)" standard_name="latitude" units="Unit('degrees')" value_type="float64"> + [1.66666333333, 2.99999]]" id="f913a8b3" points="[-0.333326666667, 1.0, 2.33332666667]" shape="(3,)" standard_name="longitude" units="Unit('degrees')" value_type="float64"> - + diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lower.data.0.json b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lower.data.0.json new file mode 100644 index 0000000000..223c1fa48b --- /dev/null +++ b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lower.data.0.json @@ -0,0 +1 @@ +{"std": 2.8551710936291563, "min": 1.5833798185348189, "max": 9.4164170613250846, "shape": [2, 3], "masked": false, "mean": 5.4998984399299529} \ No newline at end of file diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lower.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lower.data.0.npy deleted file mode 100644 index 6d5ad92beb..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/lower.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/simple.cml b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/simple.cml index d288abe593..fe54eb19cf 100644 --- a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/simple.cml +++ b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/simple.cml @@ -1,11 +1,11 @@ - + + [1.0, 2.0]]" id="77a50eb5" points="[-1, 0, 1]" shape="(3,)" standard_name="latitude" units="Unit('degrees')" value_type="int32"> @@ -13,12 +13,12 @@ + [2.0, 3.0]]" id="f913a8b3" points="[-1, 0, 1, 2]" shape="(4,)" standard_name="longitude" units="Unit('degrees')" value_type="int32"> - + diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/simple.data.0.json b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/simple.data.0.json new file mode 100644 index 0000000000..59542e9e83 --- /dev/null +++ b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/simple.data.0.json @@ -0,0 +1 @@ +{"std": 3.4520525295346629, "min": 0.0, "max": 11.0, "shape": [3, 4], "masked": false, "mean": 5.5} \ No newline at end of file diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/simple.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/simple.data.0.npy deleted file mode 100644 index ea8827ec09..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/simple.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/trasposed.cml b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/trasposed.cml index 01349c2ba0..9aecbfc388 100644 --- a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/trasposed.cml +++ b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/trasposed.cml @@ -1,20 +1,20 @@ - + - + + [1.0, 3.0]]" id="f913a8b3" points="[-1, 1]" shape="(2,)" standard_name="longitude" units="Unit('degrees')" value_type="int32"> - + diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/trasposed.data.0.json b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/trasposed.data.0.json new file mode 100644 index 0000000000..0525283f0a --- /dev/null +++ b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/trasposed.data.0.json @@ -0,0 +1 @@ +{"std": 1.0, "min": 4.499593812507495, "max": 6.499593812507495, "shape": [2], "masked": false, "mean": 5.499593812507495} \ No newline at end of file diff --git a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/trasposed.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/trasposed.data.0.npy deleted file mode 100644 index 1be15f3f01..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_area_weighted_rectilinear_src_and_grid/trasposed.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/both_circular.cml b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/both_circular.cml deleted file mode 100644 index db2e2394f8..0000000000 --- a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/both_circular.cml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/both_circular.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/both_circular.data.0.npy deleted file mode 100644 index 4076eaa086..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/both_circular.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/circular_grid.cml b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/circular_grid.cml deleted file mode 100644 index 8ed961ac15..0000000000 --- a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/circular_grid.cml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/circular_grid.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/circular_grid.data.0.npy deleted file mode 100644 index 18f7f54f66..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/circular_grid.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/circular_src.cml b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/circular_src.cml deleted file mode 100644 index c04519cdf2..0000000000 --- a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/circular_src.cml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/circular_src.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/circular_src.data.0.npy deleted file mode 100644 index 4076eaa086..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/circular_src.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/no_overlap.cml b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/no_overlap.cml deleted file mode 100644 index 1ecc93250b..0000000000 --- a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/no_overlap.cml +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/no_overlap.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/no_overlap.data.0.npy deleted file mode 100644 index 953d122ae0..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/no_overlap.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/non_circular.cml b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/non_circular.cml deleted file mode 100644 index ee80d8f7d3..0000000000 --- a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/non_circular.cml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/non_circular.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/non_circular.data.0.npy deleted file mode 100644 index 18f7f54f66..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/non_circular.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/partial_overlap.cml b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/partial_overlap.cml deleted file mode 100644 index 4172caad4c..0000000000 --- a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/partial_overlap.cml +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/partial_overlap.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/partial_overlap.data.0.npy deleted file mode 100644 index a7fd46f801..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/partial_overlap.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset.cml b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset.cml deleted file mode 100644 index a9de60db0e..0000000000 --- a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset.cml +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset.data.0.npy deleted file mode 100644 index b6dd9abbd2..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_anon.cml b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_anon.cml deleted file mode 100644 index ef81e0e482..0000000000 --- a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_anon.cml +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_anon.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_anon.data.0.npy deleted file mode 100644 index b6dd9abbd2..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_anon.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_masked_1.cml b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_masked_1.cml deleted file mode 100644 index a9de60db0e..0000000000 --- a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_masked_1.cml +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_masked_1.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_masked_1.data.0.npy deleted file mode 100644 index b6dd9abbd2..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_masked_1.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_masked_2.cml b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_masked_2.cml deleted file mode 100644 index a9de60db0e..0000000000 --- a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_masked_2.cml +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_masked_2.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_masked_2.data.0.npy deleted file mode 100644 index b6dd9abbd2..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_masked_2.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_trans.data.0.npy b/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_trans.data.0.npy deleted file mode 100644 index cd5204f0e1..0000000000 Binary files a/lib/iris/tests/results/experimental/regrid/regrid_bilinear_rectilinear_src_and_grid/subset_trans.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/file_load/known_loaders.txt b/lib/iris/tests/results/file_load/known_loaders.txt index 28edcdf8b7..9b0a074574 100644 --- a/lib/iris/tests/results/file_load/known_loaders.txt +++ b/lib/iris/tests/results/file_load/known_loaders.txt @@ -1,16 +1,16 @@ * NetCDF OPeNDAP (priority 6) * NAME III (priority 5) - * NetCDF_v4 (priority 5) - * UM Post Processing file (PP) (priority 5) * NetCDF (priority 5) * NetCDF 64 bit offset format (priority 5) + * NetCDF_v4 (priority 5) + * UM Post Processing file (PP) (priority 5) * UM Fieldsfile (FF) post v5.2 (priority 4) - * UM Fieldsfile (FF) pre v3.1 (priority 3) - * UM Fieldsfile (FF) ancillary (priority 3) - * UM Post Processing file (PP) little-endian (priority 3) - * UM Fieldsfile (FF) converted with ieee to 32 bit (priority 3) - * UM Fieldsfile (FF) ancillary converted with ieee to 32 bit (priority 3) - * NIMROD (priority 3) * ABF (priority 3) * ABL (priority 3) + * NIMROD (priority 3) + * UM Fieldsfile (FF) ancillary (priority 3) + * UM Fieldsfile (FF) ancillary converted with ieee to 32 bit (priority 3) + * UM Fieldsfile (FF) converted with ieee to 32 bit (priority 3) + * UM Fieldsfile (FF) pre v3.1 (priority 3) + * UM Post Processing file (PP) little-endian (priority 3) * GRIB (priority 1) \ No newline at end of file diff --git a/lib/iris/tests/results/file_load/theta_levels.cml b/lib/iris/tests/results/file_load/theta_levels.cml index 22f17478b4..b4ae2a4b35 100644 --- a/lib/iris/tests/results/file_load/theta_levels.cml +++ b/lib/iris/tests/results/file_load/theta_levels.cml @@ -1,46 +1,47 @@ - + - + + - + - + - + - + - + - + - + - + @@ -48,49 +49,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -98,49 +100,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -148,49 +151,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -198,49 +202,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -248,49 +253,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -298,49 +304,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -348,49 +355,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -398,49 +406,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -448,49 +457,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -498,49 +508,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -548,49 +559,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -598,49 +610,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -648,49 +661,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -698,49 +712,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -748,49 +763,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -798,49 +814,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -848,49 +865,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -898,49 +916,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -948,49 +967,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -998,49 +1018,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -1048,49 +1069,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -1098,49 +1120,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -1148,49 +1171,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -1198,49 +1222,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -1248,49 +1273,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -1298,49 +1324,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -1348,49 +1375,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -1398,49 +1426,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -1448,49 +1477,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -1498,49 +1528,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -1548,49 +1579,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -1598,49 +1630,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -1648,49 +1681,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -1698,49 +1732,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -1748,49 +1783,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -1798,49 +1834,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -1848,49 +1885,50 @@ - + - + - + + - + - + - + - + - + - + - + - + @@ -1898,6 +1936,6 @@ - + diff --git a/lib/iris/tests/results/file_load/u_wind_levels.cml b/lib/iris/tests/results/file_load/u_wind_levels.cml index 3afc4a458e..68a3b45f07 100644 --- a/lib/iris/tests/results/file_load/u_wind_levels.cml +++ b/lib/iris/tests/results/file_load/u_wind_levels.cml @@ -1,47 +1,48 @@ - + - + + - + - + - + - + - - + - + - + @@ -49,50 +50,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -100,50 +102,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -151,50 +154,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -202,50 +206,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -253,50 +258,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -304,50 +310,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -355,50 +362,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -406,50 +414,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -457,50 +466,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -508,50 +518,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -559,50 +570,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -610,50 +622,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -661,50 +674,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -712,50 +726,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -763,50 +778,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -814,50 +830,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -865,50 +882,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -916,50 +934,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -967,50 +986,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1018,50 +1038,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1069,50 +1090,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1120,50 +1142,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1171,50 +1194,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1222,50 +1246,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1273,50 +1298,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1324,50 +1350,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1375,50 +1402,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1426,50 +1454,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1477,50 +1506,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1528,50 +1558,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1579,50 +1610,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1630,50 +1662,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1681,50 +1714,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1732,50 +1766,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1783,50 +1818,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1834,50 +1870,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1885,50 +1922,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1936,6 +1974,6 @@ - + diff --git a/lib/iris/tests/results/file_load/v_wind_levels.cml b/lib/iris/tests/results/file_load/v_wind_levels.cml index 727c896213..9ccdade1bd 100644 --- a/lib/iris/tests/results/file_load/v_wind_levels.cml +++ b/lib/iris/tests/results/file_load/v_wind_levels.cml @@ -1,47 +1,48 @@ - + - + + - + - + - - + - + - + - + - + @@ -49,50 +50,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -100,50 +102,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -151,50 +154,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -202,50 +206,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -253,50 +258,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -304,50 +310,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -355,50 +362,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -406,50 +414,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -457,50 +466,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -508,50 +518,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -559,50 +570,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -610,50 +622,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -661,50 +674,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -712,50 +726,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -763,50 +778,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -814,50 +830,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -865,50 +882,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -916,50 +934,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -967,50 +986,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1018,50 +1038,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1069,50 +1090,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1120,50 +1142,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1171,50 +1194,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1222,50 +1246,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1273,50 +1298,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1324,50 +1350,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1375,50 +1402,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1426,50 +1454,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1477,50 +1506,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1528,50 +1558,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1579,50 +1610,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1630,50 +1662,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1681,50 +1714,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1732,50 +1766,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1783,50 +1818,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1834,50 +1870,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1885,50 +1922,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1936,6 +1974,6 @@ - + diff --git a/lib/iris/tests/results/file_load/wind_levels.cml b/lib/iris/tests/results/file_load/wind_levels.cml index 8825428da1..96d821fc1c 100644 --- a/lib/iris/tests/results/file_load/wind_levels.cml +++ b/lib/iris/tests/results/file_load/wind_levels.cml @@ -1,47 +1,48 @@ - + - + + - + - + - + - + - - + - + - + @@ -49,50 +50,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -100,50 +102,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -151,50 +154,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -202,50 +206,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -253,50 +258,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -304,50 +310,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -355,50 +362,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -406,50 +414,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -457,50 +466,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -508,50 +518,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -559,50 +570,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -610,50 +622,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -661,50 +674,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -712,50 +726,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -763,50 +778,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -814,50 +830,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -865,50 +882,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -916,50 +934,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -967,50 +986,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1018,50 +1038,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1069,50 +1090,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1120,50 +1142,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1171,50 +1194,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1222,50 +1246,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1273,50 +1298,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1324,50 +1350,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1375,50 +1402,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1426,50 +1454,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1477,50 +1506,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1528,50 +1558,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1579,50 +1610,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1630,50 +1662,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1681,50 +1714,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1732,50 +1766,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1783,50 +1818,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1834,50 +1870,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1885,50 +1922,51 @@ - + - + - + + - + - + - + - + - - + - + - + @@ -1936,50 +1974,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -1987,50 +2026,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2038,50 +2078,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2089,50 +2130,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2140,50 +2182,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2191,50 +2234,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2242,50 +2286,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2293,50 +2338,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2344,50 +2390,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2395,50 +2442,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2446,50 +2494,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2497,50 +2546,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2548,50 +2598,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2599,50 +2650,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2650,50 +2702,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2701,50 +2754,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2752,50 +2806,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2803,50 +2858,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2854,50 +2910,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2905,50 +2962,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -2956,50 +3014,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -3007,50 +3066,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -3058,50 +3118,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -3109,50 +3170,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -3160,50 +3222,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -3211,50 +3274,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -3262,50 +3326,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -3313,50 +3378,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -3364,50 +3430,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -3415,50 +3482,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -3466,50 +3534,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -3517,50 +3586,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -3568,50 +3638,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -3619,50 +3690,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -3670,50 +3742,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -3721,50 +3794,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -3772,50 +3846,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -3823,50 +3898,51 @@ - + - + - + + - + - + - - + - + - + - + - + @@ -3874,6 +3950,6 @@ - + diff --git a/lib/iris/tests/results/grib_load/3_layer.cml b/lib/iris/tests/results/grib_load/3_layer.cml index cf36f132f3..24f24ed777 100644 --- a/lib/iris/tests/results/grib_load/3_layer.cml +++ b/lib/iris/tests/results/grib_load/3_layer.cml @@ -1,42 +1,45 @@ - + - + + + + - - - - - - + - + - + - + - + + + + - - - + - - - - + @@ -79,33 +79,33 @@ - + - + - + + + + - - - - - - + - + @@ -113,6 +113,6 @@ - + diff --git a/lib/iris/tests/results/grib_load/earth_shape_0.cml b/lib/iris/tests/results/grib_load/earth_shape_0.cml index f5a881c6e0..1e1e491d58 100644 --- a/lib/iris/tests/results/grib_load/earth_shape_0.cml +++ b/lib/iris/tests/results/grib_load/earth_shape_0.cml @@ -1,12 +1,15 @@ - + - + + + + - - - - - - + - + @@ -49,6 +49,6 @@ - + diff --git a/lib/iris/tests/results/grib_load/earth_shape_1.cml b/lib/iris/tests/results/grib_load/earth_shape_1.cml index d019550ea4..dd409ebb20 100644 --- a/lib/iris/tests/results/grib_load/earth_shape_1.cml +++ b/lib/iris/tests/results/grib_load/earth_shape_1.cml @@ -1,12 +1,15 @@ - + - + + + + - - - - - - + - + @@ -49,6 +49,6 @@ - + diff --git a/lib/iris/tests/results/grib_load/earth_shape_2.cml b/lib/iris/tests/results/grib_load/earth_shape_2.cml index 42f41fac97..0e3a4a14ea 100644 --- a/lib/iris/tests/results/grib_load/earth_shape_2.cml +++ b/lib/iris/tests/results/grib_load/earth_shape_2.cml @@ -1,12 +1,15 @@ - + - + + + + - - + - - + - - - - + - + @@ -49,6 +49,6 @@ - + diff --git a/lib/iris/tests/results/grib_load/earth_shape_3.cml b/lib/iris/tests/results/grib_load/earth_shape_3.cml index 512f582677..0213c4a4a0 100644 --- a/lib/iris/tests/results/grib_load/earth_shape_3.cml +++ b/lib/iris/tests/results/grib_load/earth_shape_3.cml @@ -1,12 +1,15 @@ - + - + + + + - - - - - - + - + @@ -49,6 +49,6 @@ - + diff --git a/lib/iris/tests/results/grib_load/earth_shape_4.cml b/lib/iris/tests/results/grib_load/earth_shape_4.cml index 0f656ff415..2573e867d1 100644 --- a/lib/iris/tests/results/grib_load/earth_shape_4.cml +++ b/lib/iris/tests/results/grib_load/earth_shape_4.cml @@ -1,12 +1,15 @@ - + - + + + + - - + - - + - - - - + - + @@ -49,6 +49,6 @@ - + diff --git a/lib/iris/tests/results/grib_load/earth_shape_5.cml b/lib/iris/tests/results/grib_load/earth_shape_5.cml index cd983c0f7e..56462c684b 100644 --- a/lib/iris/tests/results/grib_load/earth_shape_5.cml +++ b/lib/iris/tests/results/grib_load/earth_shape_5.cml @@ -1,12 +1,15 @@ - + - + + + + - - + - - + - - - - + - + @@ -49,6 +49,6 @@ - + diff --git a/lib/iris/tests/results/grib_load/earth_shape_6.cml b/lib/iris/tests/results/grib_load/earth_shape_6.cml index 9e3afb14f7..1ad54d1f77 100644 --- a/lib/iris/tests/results/grib_load/earth_shape_6.cml +++ b/lib/iris/tests/results/grib_load/earth_shape_6.cml @@ -1,12 +1,15 @@ - + - + + + + - - - - - - + - + @@ -49,6 +49,6 @@ - + diff --git a/lib/iris/tests/results/grib_load/earth_shape_7.cml b/lib/iris/tests/results/grib_load/earth_shape_7.cml index 624f13885a..cea76b2739 100644 --- a/lib/iris/tests/results/grib_load/earth_shape_7.cml +++ b/lib/iris/tests/results/grib_load/earth_shape_7.cml @@ -1,12 +1,15 @@ - + - + + + + - - - - - - + - + @@ -49,6 +49,6 @@ - + diff --git a/lib/iris/tests/results/grib_load/earth_shape_grib1.cml b/lib/iris/tests/results/grib_load/earth_shape_grib1.cml index edb42a3d22..7ee99f8d74 100644 --- a/lib/iris/tests/results/grib_load/earth_shape_grib1.cml +++ b/lib/iris/tests/results/grib_load/earth_shape_grib1.cml @@ -1,32 +1,32 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/grib_load/ineg_jneg.cml b/lib/iris/tests/results/grib_load/ineg_jneg.cml index 9b783c00d0..344fbbacf2 100644 --- a/lib/iris/tests/results/grib_load/ineg_jneg.cml +++ b/lib/iris/tests/results/grib_load/ineg_jneg.cml @@ -1,12 +1,15 @@ - + - + + + + - - + - - - - + - + @@ -49,6 +49,6 @@ - + diff --git a/lib/iris/tests/results/grib_load/ineg_jpos.cml b/lib/iris/tests/results/grib_load/ineg_jpos.cml index 2ea612ddfe..14967e6a88 100644 --- a/lib/iris/tests/results/grib_load/ineg_jpos.cml +++ b/lib/iris/tests/results/grib_load/ineg_jpos.cml @@ -1,12 +1,15 @@ - + - + + + + - - + - - - - + - + @@ -49,6 +49,6 @@ - + diff --git a/lib/iris/tests/results/grib_load/ipos_jneg.cml b/lib/iris/tests/results/grib_load/ipos_jneg.cml index f5a881c6e0..1e1e491d58 100644 --- a/lib/iris/tests/results/grib_load/ipos_jneg.cml +++ b/lib/iris/tests/results/grib_load/ipos_jneg.cml @@ -1,12 +1,15 @@ - + - + + + + - - - - - - + - + @@ -49,6 +49,6 @@ - + diff --git a/lib/iris/tests/results/grib_load/ipos_jpos.cml b/lib/iris/tests/results/grib_load/ipos_jpos.cml index 065d84eb0d..373d8fc475 100644 --- a/lib/iris/tests/results/grib_load/ipos_jpos.cml +++ b/lib/iris/tests/results/grib_load/ipos_jpos.cml @@ -1,12 +1,15 @@ - + - + + + + - - - - - - + - + @@ -49,6 +49,6 @@ - + diff --git a/lib/iris/tests/results/grib_load/lambert_grib1.cml b/lib/iris/tests/results/grib_load/lambert_grib1.cml index a9ac9b1c06..74fe0a27fb 100644 --- a/lib/iris/tests/results/grib_load/lambert_grib1.cml +++ b/lib/iris/tests/results/grib_load/lambert_grib1.cml @@ -1,31 +1,38 @@ - + - + - + + + + + + + + - - - + - + diff --git a/lib/iris/tests/results/grib_load/lambert_grib2.cml b/lib/iris/tests/results/grib_load/lambert_grib2.cml index 17d7466318..e8b3f1c4c6 100644 --- a/lib/iris/tests/results/grib_load/lambert_grib2.cml +++ b/lib/iris/tests/results/grib_load/lambert_grib2.cml @@ -1,34 +1,34 @@ - + - + - + - + - - - + - + diff --git a/lib/iris/tests/results/grib_load/missing_values_grib2.cml b/lib/iris/tests/results/grib_load/missing_values_grib2.cml index 5f836cf6a6..b090d56a92 100644 --- a/lib/iris/tests/results/grib_load/missing_values_grib2.cml +++ b/lib/iris/tests/results/grib_load/missing_values_grib2.cml @@ -1,12 +1,15 @@ - + - + + + + - - + - - - - + - + diff --git a/lib/iris/tests/results/grib_load/polar_stereo_grib1.cml b/lib/iris/tests/results/grib_load/polar_stereo_grib1.cml index d89eae149e..2ba2e8205b 100644 --- a/lib/iris/tests/results/grib_load/polar_stereo_grib1.cml +++ b/lib/iris/tests/results/grib_load/polar_stereo_grib1.cml @@ -1,27 +1,27 @@ - + - + - + - - - + @@ -29,6 +29,6 @@ - + diff --git a/lib/iris/tests/results/grib_load/polar_stereo_grib2.cml b/lib/iris/tests/results/grib_load/polar_stereo_grib2.cml deleted file mode 100644 index fe8bf1b8e1..0000000000 --- a/lib/iris/tests/results/grib_load/polar_stereo_grib2.cml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/grib_load/reduced_gg_grib2.cml b/lib/iris/tests/results/grib_load/reduced_gg_grib2.cml index 4b04ce6830..f34938ce3f 100644 --- a/lib/iris/tests/results/grib_load/reduced_gg_grib2.cml +++ b/lib/iris/tests/results/grib_load/reduced_gg_grib2.cml @@ -1,42 +1,45 @@ - + + + + - + + + + - + - + - + - - + + - + - + - - - - + - + - + diff --git a/lib/iris/tests/results/grib_load/reduced_ll_grib1.cml b/lib/iris/tests/results/grib_load/reduced_ll_grib1.cml index 47cd7130ab..b1d68014fd 100644 --- a/lib/iris/tests/results/grib_load/reduced_ll_grib1.cml +++ b/lib/iris/tests/results/grib_load/reduced_ll_grib1.cml @@ -1,52 +1,21 @@ - + - - - - - - - - - - - + - + - + - + - + diff --git a/lib/iris/tests/results/grib_load/reduced_ll_missing_grib1.cml b/lib/iris/tests/results/grib_load/reduced_ll_missing_grib1.cml deleted file mode 100644 index 0f9093de39..0000000000 --- a/lib/iris/tests/results/grib_load/reduced_ll_missing_grib1.cml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/grib_load/regular_gg_grib1.cml b/lib/iris/tests/results/grib_load/regular_gg_grib1.cml index daa7135682..b1dc1f6c81 100644 --- a/lib/iris/tests/results/grib_load/regular_gg_grib1.cml +++ b/lib/iris/tests/results/grib_load/regular_gg_grib1.cml @@ -1,32 +1,32 @@ - + - + - - + - + - + - + - + diff --git a/lib/iris/tests/results/grib_load/regular_gg_grib2.cml b/lib/iris/tests/results/grib_load/regular_gg_grib2.cml index 7ac1eae2a3..20230aee0f 100644 --- a/lib/iris/tests/results/grib_load/regular_gg_grib2.cml +++ b/lib/iris/tests/results/grib_load/regular_gg_grib2.cml @@ -1,32 +1,32 @@ - + - + + + + - - + - - - - + - + - + diff --git a/lib/iris/tests/results/grib_load/rotated.cml b/lib/iris/tests/results/grib_load/rotated.cml index cf39fd7dec..06e2b517e1 100644 --- a/lib/iris/tests/results/grib_load/rotated.cml +++ b/lib/iris/tests/results/grib_load/rotated.cml @@ -1,31 +1,31 @@ - + - + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/grib_load/time_bound_grib1.cml b/lib/iris/tests/results/grib_load/time_bound_grib1.cml index 809878faf5..89902729b5 100644 --- a/lib/iris/tests/results/grib_load/time_bound_grib1.cml +++ b/lib/iris/tests/results/grib_load/time_bound_grib1.cml @@ -1,26 +1,26 @@ - + - + - + - - + - + @@ -28,6 +28,6 @@ - + diff --git a/lib/iris/tests/results/grib_load/time_bound_grib2.cml b/lib/iris/tests/results/grib_load/time_bound_grib2.cml index f5a881c6e0..1e1e491d58 100644 --- a/lib/iris/tests/results/grib_load/time_bound_grib2.cml +++ b/lib/iris/tests/results/grib_load/time_bound_grib2.cml @@ -1,12 +1,15 @@ - + - + + + + - - - - - - + - + @@ -49,6 +49,6 @@ - + diff --git a/lib/iris/tests/results/grib_load/y_fastest.cml b/lib/iris/tests/results/grib_load/y_fastest.cml index 53a911edf6..c111999c06 100644 --- a/lib/iris/tests/results/grib_load/y_fastest.cml +++ b/lib/iris/tests/results/grib_load/y_fastest.cml @@ -3,10 +3,10 @@ - + - - - + - + - + @@ -49,6 +49,6 @@ - + diff --git a/lib/iris/tests/results/grib_save/latlon_forecast_plev.grib_compare.txt b/lib/iris/tests/results/grib_save/latlon_forecast_plev.grib_compare.txt deleted file mode 100644 index dddfa8da98..0000000000 --- a/lib/iris/tests/results/grib_save/latlon_forecast_plev.grib_compare.txt +++ /dev/null @@ -1,8 +0,0 @@ - --- GRIB #1 -- shortName=t paramId=130 stepRange=48 levelType=pl level=0 packingType=grid_simple gridType=regular_ll -- -long [productionStatusOfProcessedData]: [0] != [255] -long [shapeOfTheEarth]: [0] != [1] -scaleFactorOfRadiusOfSphericalEarth is set to missing in 1st field is not missing in 2nd field -scaledValueOfRadiusOfSphericalEarth is set to missing in 1st field is not missing in 2nd field -long [typeOfGeneratingProcess]: [0] != [255] -long [generatingProcessIdentifier]: [128] != [255] diff --git a/lib/iris/tests/results/grib_save/rotated_latlon.grib_compare.txt b/lib/iris/tests/results/grib_save/rotated_latlon.grib_compare.txt deleted file mode 100644 index 559cc2281d..0000000000 --- a/lib/iris/tests/results/grib_save/rotated_latlon.grib_compare.txt +++ /dev/null @@ -1,12 +0,0 @@ - --- GRIB #1 -- shortName=t paramId=130 stepRange=0 levelType=pl level=1000 packingType=grid_simple gridType=rotated_ll -- -long [productionStatusOfProcessedData]: [0] != [255] -long [shapeOfTheEarth]: [0] != [1] -scaleFactorOfRadiusOfSphericalEarth is set to missing in 1st field is not missing in 2nd field -scaledValueOfRadiusOfSphericalEarth is set to missing in 1st field is not missing in 2nd field -long [latitudeOfLastGridPoint]: [19419996] != [19419285] -long [longitudeOfLastGridPoint]: [392109982] != [32106370] -long [iDirectionIncrement]: [109994] != [109993] -long [longitudeOfSouthernPole]: [332466980] != [332466979] -long [typeOfGeneratingProcess]: [0] != [255] -long [generatingProcessIdentifier]: [128] != [255] diff --git a/lib/iris/tests/results/grib_save/time_mean.grib_compare.FT_PATCH.txt b/lib/iris/tests/results/grib_save/time_mean.grib_compare.FT_PATCH.txt deleted file mode 100644 index 55fb972fa9..0000000000 --- a/lib/iris/tests/results/grib_save/time_mean.grib_compare.FT_PATCH.txt +++ /dev/null @@ -1,11 +0,0 @@ - --- GRIB #1 -- shortName=t paramId=130 stepRange=-28587-6477 levelType=pl level=1000 packingType=grid_simple gridType=regular_ll -- -long [productionStatusOfProcessedData]: [0] != [255] -long [shapeOfTheEarth]: [0] != [1] -scaleFactorOfRadiusOfSphericalEarth is set to missing in 1st field is not missing in 2nd field -scaledValueOfRadiusOfSphericalEarth is set to missing in 1st field is not missing in 2nd field -long [latitudeOfLastGridPoint]: [-89999938] != [-89999944] -long [longitudeOfLastGridPoint]: [356249908] != [356249810] -long [typeOfGeneratingProcess]: [0] != [255] -long [generatingProcessIdentifier]: [128] != [255] -long [typeOfTimeIncrement]: [2] != [255] diff --git a/lib/iris/tests/results/grib_save/time_mean.grib_compare.txt b/lib/iris/tests/results/grib_save/time_mean.grib_compare.txt deleted file mode 100644 index d088a1c67f..0000000000 --- a/lib/iris/tests/results/grib_save/time_mean.grib_compare.txt +++ /dev/null @@ -1,11 +0,0 @@ - --- GRIB #1 -- shortName=t paramId=130 stepRange=2147512235-2147547299 levelType=pl level=1000 packingType=grid_simple gridType=regular_ll -- -long [productionStatusOfProcessedData]: [0] != [255] -long [shapeOfTheEarth]: [0] != [1] -scaleFactorOfRadiusOfSphericalEarth is set to missing in 1st field is not missing in 2nd field -scaledValueOfRadiusOfSphericalEarth is set to missing in 1st field is not missing in 2nd field -long [latitudeOfLastGridPoint]: [-89999938] != [-89999944] -long [longitudeOfLastGridPoint]: [356249908] != [356249810] -long [typeOfGeneratingProcess]: [0] != [255] -long [generatingProcessIdentifier]: [128] != [255] -long [typeOfTimeIncrement]: [2] != [255] diff --git a/lib/iris/tests/results/imagerepo.json b/lib/iris/tests/results/imagerepo.json new file mode 100644 index 0000000000..40dd593655 --- /dev/null +++ b/lib/iris/tests/results/imagerepo.json @@ -0,0 +1,970 @@ +{ + "example_tests.test_COP_1d_plot.TestCOP1DPlot.test_COP_1d_plot.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/baff589936602d8ec977334ae4dac9b61a6dc4d99532c86cc2913e36c4cc0f61.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/aefec91c3601249cc9b3336dc4c8cdb31a64c6d997b3c0eccb5932d285e42f33.png" + ], + "example_tests.test_COP_maps.TestCOPMaps.test_cop_maps.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea9138db95668524913e6ac168997e85957e917e876396b96a81b5ce3c496935.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea9130db95668524913c6ac178995b0d956e917ec76396b96a853dcf94696935.png" + ], + "example_tests.test_SOI_filtering.TestSOIFiltering.test_soi_filtering.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fac460b9c17b78723e05a5a9954edaf062332799954e9ca5c63b9a52d24e5a95.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa8460b9c17b78723e05a5a9954edaf062333799954e9ca5c63b9a52d24e4a9d.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa167295c5e0696a3c17a58c9568da536233da19994cdab487739b4b9b444eb5.png" + ], + "example_tests.test_TEC.TestTEC.test_TEC.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e1a561b69b1a9a42846e9a49c7596e3cce6c907b3a83c17e1b8239b3e4f33bc4.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e1a561b69b1a9e43846e9a49c7596e2cce6c907b3a83c16e1b9231b3e4f33b8c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e5a761b69a589a4bc46f9e48c65c6631ce61d1ce3982c13739b33193c0ee3f8c.png" + ], + "example_tests.test_anomaly_log_colouring.TestAnomalyLogColouring.test_anomaly_log_colouring.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ec4464e185a39f93931e9b1e91696d2949dde6e63e26a47a5ad391938d9a5a0c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ecc164e78e979b19b3789b0885a564a56cc2c65e3ec69469db1bdb9a853c1e24.png" + ], + "example_tests.test_atlantic_profiles.TestAtlanticProfiles.test_atlantic_profiles.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/9f8260536bd28e1320739437b5f437b0a51d66f4cc5d08fcd00fdb1c93fcb21c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/9f8260536bd28e1320739437b5f437b0a51d66f4cc7c09f4d00fdb1c93fcb21c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/9f8a60536bd28e1320739437b5f437b0a53d66f4cc5c08f4d00fdb1c93fcb21c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/9fc060f462a08f07203ebc77a1f36707e61f4e38d8f7d08a910197fc877cec58.png" + ], + "example_tests.test_atlantic_profiles.TestAtlanticProfiles.test_atlantic_profiles.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/a6eaa57e6e81ddf999311ba3b3775e20845d5889c199673b4e22a4675e8ca11c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/eeea64dd6ea8cd99991f1322b3761e06845718d89995b3131f32a4765ec2a1cd.png" + ], + "example_tests.test_coriolis_plot.TestCoriolisPlot.test_coriolis_plot.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e78665de9a699659e55e9965886979966986c5e63e98c19e3a256679e1981a24.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e68665de9a699659c1fe99a5896965966996c46e3e19c1da3a652669c51e1a26.png" + ], + "example_tests.test_cross_section.TestCrossSection.test_cross_section.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea95317b9562e4d1649f5a05856e4ca4da52947e4ea5f13f1b499d42f13b1b41.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea91b17b9562e4d1609f5a05856e4ca45a52957e5ea5f13b1bca9dc0b17b1ac1.png" + ], + "example_tests.test_cross_section.TestCrossSection.test_cross_section.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea9521fb956a394069921e93f07f4aad856cc47e4e95857a1ea5da3591ba1b81.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea9521fb956a394068931e9be07e4aa5856cc47e4a91957a1ba55bb5b17a3b81.png" + ], + "example_tests.test_custom_aggregation.TestCustomAggregation.test_custom_aggregation.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fe816e81917e907eb43e873f85677ac190f0703c6a95811f1ac33ce1a57a6f18.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fe816e81817e907eb43e873f85637ac198d8703c6a94811f1ac73ee1a57a6f90.png" + ], + "example_tests.test_custom_file_loading.TestCustomFileLoading.test_custom_file_loading.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/faa0cbf1845e34be913787416edcc8bc3bc81f9b63332662a4ed30cdc1b2cd21.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fba0cbf1845e34be912787416edcc8bc3b881f9b62332762a5ad32cdc1b2cd21.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/faa1cb47845e34bc912797436cccc8343f11359b73523746c48c72d9d9b34da5.png" + ], + "example_tests.test_deriving_phenomena.TestDerivingPhenomena.test_deriving_phenomena.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/b9993986866952e6c9464639c4766bd9c669916e7b99c1663f99768990763e81.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/b99139de866952e6c946c639c47e6bd18769d16e7a9981662e813699d0763e89.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ec97681793689768943c97e8926669d186e8c33f6c99c32e6b936c83d33e2c98.png" + ], + "example_tests.test_global_map.TestGlobalMap.test_global_map.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa9979468566857ef07e3e8978566b91cb0179883c89946686a96b9d83766f81.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa997b958466846ed13e87467a997a898d66d17e2cc9906684696f99d3162f81.png" + ], + "example_tests.test_hovmoller.TestGlobalMap.test_hovmoller.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/bab430b4ce4bce43c5becf89c54b1a63c543c56e1e64907e3bb469b490de1ac1.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/eeb46cb4934b934bc07e974bc14b38949943c0fe3e94c17f6ea46cb4c07b3f00.png" + ], + "example_tests.test_inset_plot.TestInsetPlot.test_inset_plot.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ebff6992f50096a5b245dac4f6559496b49248dbc95dcb699529912dcf244a54.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e9ff6992b50096a5b245dac4f64594b6b49248dbc95dcb699529952dcf244a56.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ebff6992b50096ad9267dac4d64094b294924cdbc95d4b699d29952dcda46e94.png" + ], + "example_tests.test_lagged_ensemble.TestLaggedEnsemble.test_lagged_ensemble.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/bbbb31e1c44e64e4b0459b5bb1716ecac464f496ce34618eb1079b39b193ce25.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/bbbb31b1c44e64e4b1579b5b917133cecc61f146c414668eb1119b1bb197ce34.png" + ], + "example_tests.test_lagged_ensemble.TestLaggedEnsemble.test_lagged_ensemble.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/abfef958fd462c993a07d87960464b81d1009687c139d3b594e9cf87c6b89687.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/aafec5e9e5e03e099a07e0f86542db879438261ec3b13ce78d8dc65a92d83d89.png" + ], + "example_tests.test_lineplot_with_legend.TestLineplotWithLegend.test_lineplot_with_legend.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/eae942526540b869961f8da694589da69543cc9af1014afbc3fd596b84fe19a7.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/eae942146540b869961f8de694589da69543cc9af1014afbc3fd596b84fe19a7.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/eafd9e12a5a061e9925ec716de489e9685078ec981b229e70ddb79219cc3768d.png" + ], + "example_tests.test_orca_projection.TestOrcaProjection.test_orca_projection.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fb11731a94cea4ee64b35e91d1d2304e9e5ac7397b20e1fe12852487e666ce46.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/bb11721a87cce5e4cce79e81d19b3b5e1e1cd3783168e07835853485e65e2e1e.png" + ], + "example_tests.test_orca_projection.TestOrcaProjection.test_orca_projection.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e5a665a69a599659e5db1865c2653b869996cce63e99e19a1a912639e7181e65.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e58661969e799659c1f719a6c867359a1996c0773649c09c3e612679c07b3f66.png" + ], + "example_tests.test_orca_projection.TestOrcaProjection.test_orca_projection.2": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/f2c464ce9e399332e1b74ce1cc79338c6586e5b33b31b37a66c9664cc06e1a64.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a58660ce9e739b31c93d1cc9c8df33863383e33b3f11c03f2664366cc8ee3cc1.png" + ], + "example_tests.test_orca_projection.TestOrcaProjection.test_orca_projection.3": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa817a83846ea46ce539c93391de32cc86cf87a33fa168721cdb3e896e374b04.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/be817a87845ea56cec79817a919e338436a5c1e73fa16c736c4a3e816a1e6b1c.png" + ], + "example_tests.test_polar_stereo.TestPolarStereo.test_polar_stereo.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e168317a92d36d89c5bb9e94c55e6f0c9a93c15a6ec584763b21716791de3a81.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/b9e16079971e9e93c8ce0f84c31e3b929f92c0ff3ca1c17e39e03961c07e3f80.png" + ], + "example_tests.test_polynomial_fit.TestPolynomialFit.test_polynomial_fit.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/abff4a9df26435886520c97f12414695c4b69d23934bc86adc969237d68ccc6f.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/aaff4a9df26435886520c97f12414695c4b69d23934bc86adc969a17d69ccc6f.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/aeffcb34d244348be5a2c96c3a4fc6d0c4b69f2d87294ccb9f1a125684cd7c11.png" + ], + "example_tests.test_projections_and_annotations.TestProjectionsAndAnnotations.test_projections_and_annotations.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa854f19851a30e4cc76cd0bb179325ca7c665b0c938cb4b4e719e9cb727b5c0.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fac54f19851a30e4cc76cd0bb179325cb78665b0c938cb4b4e719e9c9727b5c0.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa854e19851a30e4cc76cd0bb179325cb7c664b0c938cb4bce739e9c37a3b5c0.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa854e19851a30e4cc76cd0bb179325cb78665b1c938c94bce739e9c3727b5c0.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa854f19851a30e4cc76cd0bb0f932dca7c665b1c92ccb4b4ed19e9c3721b5c8.png" + ], + "example_tests.test_projections_and_annotations.TestProjectionsAndAnnotations.test_projections_and_annotations.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e385699d9c3896627243318fcdad5a7dc6dba492e9b69964936dc21974b18592.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e385699d9c3896727243318f8dad5a7dc65ba492b93699649b6dc25b64938592.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e385699d9c3896627243318fcdad5a7dc6dba492b93699649b6dc25964938592.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e3856b999c3896727243318f8dad5a75965ba492f9b69964db4cc65b64918592.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e3856b999c3896727243318f8dad5a75865ba492e9b69964db6cc65b74918592.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e3856d999c389662734731afcdad5a7384daa592b1b69b64d26dc29974b18590.png" + ], + "example_tests.test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa15615e97a193adc15e1e81c4fa3eb49d30817e3e05c17e7ba59927817e1e01.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ee46607e97a19781c0df1f81d0bb3e241f20c16f3fc0c1fe39263d33d06f3e80.png" + ], + "example_tests.test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ba056717c3e099e9b90f8e81c4da589499b696763e45e56b3b893929c17b7e01.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea57685f95a886a1c0de9da090be3e2697e1c0ff3f00c17e6b266c17c07f3f00.png" + ], + "example_tests.test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.2": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ba1e605ec7a191a1b85e9e81c4da58909996b37e3a65e16f7b817939e57a1e01.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ba1e605ec7a193a1b85e9e81c4da58909996b3763a65e16f7b816939ed7a1e01.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e85a697e97a18681c6da9f8190bf3e263624c1ef3b48c17a2b223c47c0ff3f81.png" + ], + "example_tests.test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.3": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa8172d0847ecd2bc913939c36846c714933799cc3cc8727e67639f939996a58.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa8172c6857ecd38cb3392ce36c564311931d85ec64e9787719a39993c316e66.png" + ], + "example_tests.test_wind_speed.TestWindSpeed.test_wind_speed.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/bcf924fb9306930ce12ccf97c73236b28ecec4cd3e29847b18e639e6c14f1a09.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e9e960e996169306c1ee9e96c29e36739e13c07d3d61c07f39a139a1c07f3f01.png" + ], + "example_tests.test_wind_speed.TestWindSpeed.test_wind_speed.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/bcf924fb9306930ce12ccf97c73236b28ecec4cc3e29847b38e639e6c14f1a09.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e9e960e996169306c1ee9e86c29e36739e13c07d3d61c07f39a139a1c17f3f01.png" + ], + "iris.tests.experimental.test_animate.IntegrationTest.test_cube_animation.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fe81957ac17e6a85817e6a85857e942a3e81957a7e81917a7a81d95ec17e2ca1.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fe81c17e817e3e81817e7e81857e7e817e81c07e7e81c17e7a81817e817e8c2a.png" + ], + "iris.tests.experimental.test_animate.IntegrationTest.test_cube_animation.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/be81c17ec17e7e81c17e3e81c57ea55a3e80c17e3e81c1fe7a81c285c95f2c03.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fe81857e817e6a85817e7a81857e7e817e81957a7e81817e7a81817e817e843e.png" + ], + "iris.tests.experimental.test_animate.IntegrationTest.test_cube_animation.2": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea857a81957a857e957ec17e817e6a816a853e817a853e816e818d3a862ad3fe.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/be81857ec17e7a81c17e7e81857e3e803e81817a3e81c17e7a81c17ec97e2c2b.png" + ], + "iris.tests.integration.plot.test_plot_2d_coords.Test.test_2d_coord_bounds_northpolarstereo.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e59661969e699659c0f719a6c967339a1992c07f3649c09c3f612669c07b3f66.png" + ], + "iris.tests.integration.plot.test_plot_2d_coords.Test.test_2d_coord_bounds_platecarree.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ee816299954a1da699b6915ec25b6e419729c42c3f84bd9fe6d262d1d1dac076.png" + ], + "iris.tests.integration.plot.test_plot_2d_coords.Test2dContour.test_2d_coords_contour.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/b4b0643ecb05cb43b0f23d90c53c4e1d3c5990eb1f83c1be2fb43cb4c47f3e41.png" + ], + "iris.tests.integration.plot.test_vector_plots.TestQuiver.test_2d_plain_latlon.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fb8d4f21c472b27e919d2e216f216b3178e69c7e961ab39a84696c616d245b94.png" + ], + "iris.tests.integration.plot.test_vector_plots.TestQuiver.test_2d_plain_latlon_on_polar_map.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e66c6619999933666666c6d99999336663646d9999c1332667b60cf964d8672c.png" + ], + "iris.tests.integration.plot.test_vector_plots.TestQuiver.test_2d_rotated_latlon.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/eba925a5c476d25a95a56b876f3826246a449c6b96a3731ab13f6c656a5cb48a.png" + ], + "iris.tests.integration.plot.test_vector_plots.TestQuiver.test_non_latlon_1d_coords.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/a7ac24947259f3493697632df45926b6e126c4f392593b4937266f26ccf032d8.png" + ], + "iris.tests.integration.plot.test_vector_plots.TestQuiver.test_non_latlon_2d_coords.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/afac26367251d3493617632df45c26a6e126c6f392593b4937266f26ccf232d0.png" + ], + "iris.tests.test_analysis.TestProject.test_cartopy_projection.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/9e1952c9c165b4fc668a9d47c1461d7a60fb2e853eb426bd62fd229c9f04c16d.png" + ], + "iris.tests.test_mapping.TestBasic.test_contourf.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e85a69cc96ad92e193c9963385929e1cc3819acde6d965ce6e666b30386e65b1.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e97a346c9685cb899685c9c39695c79396ec634969ce2c74697a3864697b3c8c.png" + ], + "iris.tests.test_mapping.TestBasic.test_pcolor.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e95a69c896a592e59bc99e3384929636c32d98cde6d964ce7e666332386465b1.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e97a347c96858b8d9685c9c39696c393966c634969ce3c64697a3864697b3c9c.png" + ], + "iris.tests.test_mapping.TestBasic.test_unmappable.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/eaa5684eb54a947ad09eb731c521978dc2fb1cc0e4966ce26e2c6b2d3a6e691a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea853e48957ac1df957ac8be852bc1b1944e7a9878e03f4c6a253e6c7a912dc2.png" + ], + "iris.tests.test_mapping.TestBoundedCube.test_grid.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81917e857e6e81857e7a857a81917a7a81857e857e7e81857e7a817a81852e.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7a81857e7a817a81817e7a81857e857e7a81857e7a817a81857e.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7a81857e7a817a81857a7a81857e857e7a85857e7a817a81857a.png" + ], + "iris.tests.test_mapping.TestBoundedCube.test_pcolormesh.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81e535857e92ca8ec23d21b13ce15e7a811ea5c47e1a5ac17b652d3b05e4f2.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81c17a857e1ea5857e634a7a81cd257e8584da857e3b29817e68f47a81c791.png" + ], + "iris.tests.test_mapping.TestLimitedAreaCube.test_grid.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/bf80e2b1c17f1d0ac4f7c8d739a637202749699b6bb3ce3666e4b048944d9d89.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/bf80e2f1c17f1d0ac457c8d619a637213749699b6bb34e3666e4b04e944d9d89.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea05392995bac6d691ce3f21666569d86a96c6360ee195cb91e8ce54953b313b.png" + ], + "iris.tests.test_mapping.TestLimitedAreaCube.test_outline.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e3e80857e7a817a817a817a81817f7a81857e857e857e857e7a81.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7e21857e7a817a817a857a81857a7a81857a857e857a857e7a84.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa1585e885e87a1785fa7a177a177e807a1585e85fa0857a85e86817857f6a16.png" + ], + "iris.tests.test_mapping.TestLimitedAreaCube.test_pcolormesh.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/bf81e6b1c17e1d4884bfc8df39a43720374969db69b34e26c4e4b0ca904f9d89.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea57396995a8c6d691ea3f25664569d86b16c63686ed958991ea4a549531393b.png" + ], + "iris.tests.test_mapping.TestLimitedAreaCube.test_scatter.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea053d2e916ac2d9c4d894346b24f3477acf68ad39329ed8c696e136c1ab9a71.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea053d2e916ac2d9c4d895346b2473477acf68ad39329ed8c69ee126c1ab9a71.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea05bd2e916ac2d984983d346b2473477acf69ad3d3296d8c696e126c1ab1e71.png" + ], + "iris.tests.test_mapping.TestLowLevel.test_keywords.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/be21a71bc1de58e43a31871f7e856470c1fa9b8c7b81647384665b9ed1b998c1.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/be21a71bc1de58e43a63a71b3e016061c1fe9b8c3e01a473847e5b94d1fb9ac3.png" + ], + "iris.tests.test_mapping.TestLowLevel.test_keywords.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea811831957fe3cea68c6ce0d9f29b9b6a816463953e61cc917f1ae36ac09d38.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa819097857e6560957e7bcc7a819c316e81951e857e62c281fe79a17aa19637.png" + ], + "iris.tests.test_mapping.TestLowLevel.test_params.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ee819cb7913b63c8846e64737bb1999c6ec52633953a69c8916f6c636e92911c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa8190be857e6739917a7bc47a8594337bb1911c857e6ec3913279007e819637.png" + ], + "iris.tests.test_mapping.TestLowLevel.test_params.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/be21a71bc1de58e43a31871f7e856470c1fa9b8c7b81647384665b9ed1b998c1.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/be21a71bc1de58e43a63a71b3e016061c1fe9b8c3e01a473847e5b94d1fb9ac3.png" + ], + "iris.tests.test_mapping.TestLowLevel.test_params.2": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea811831957ae3cea68c6ce0c9f39b9b6a816473953e63cc917f1ae36ac09d38.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81909f857e6520957e5bcc7a8194716e31851e857e6ac281fe3f817a81963f.png" + ], + "iris.tests.test_mapping.TestLowLevel.test_simple.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/eae0943295154bcc844e6c314fb093ce7bc7c4b3a4307bc4916f3f316ed2b4ce.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/faa0e55c855fdce7857a1ab16a85a50c3ea1e55e856658a5c11837096e8fe17a.png" + ], + "iris.tests.test_mapping.TestMappingSubRegion.test_simple.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/bd913e01d07ee07e926e87876f8196c1e0d36967393c1f181e2c3cb8b0f960d7.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/b9913d90c66eca6ec66ec2f3689195b6cf5b2f00392cb3496695621d34db6c92.png" + ], + "iris.tests.test_mapping.TestUnmappable.test_simple.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fe818d6ac17e5a958d7ab12b9d677615986e666dc4f20dea7281d98833889b22.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81b54a817eca35817ec701857e3e64943e7bb41b846f996e817e006ee1b19b.png" + ], + "iris.tests.test_plot.Test1dPlotMultiArgs.test_coord.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/83fec2ff7c00a56de9023b52e4143da5d16d7ecad1b76f2094c963929c6471c8.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8bfec2d77e01a5a5ed013b4ac4521c94817d4e6d91ff63349c6d61991e3278cc.png" + ], + "iris.tests.test_plot.Test1dPlotMultiArgs.test_coord_coord.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/87ff95776a01e1f67801cc36f4075b81c5437668c1167c88d2676d39d6867b68.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8fff941e7e01e1c2f801c878a41e5b0d85cf36e1837e2d9992c62f21769e6a4d.png" + ], + "iris.tests.test_plot.Test1dPlotMultiArgs.test_coord_coord_map.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fbe0623dc9879d91b41e4b449b6579e78798a49b7872d2644b8c919b39306e6c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/bbe0c21ccd179dc3b05e4b689b0771b48698961b7962da446e8ca5bb36716c6e.png" + ], + "iris.tests.test_plot.Test1dPlotMultiArgs.test_coord_cube.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/8ff897066b41f076f81dce1fb007da79c50633e9c40626b8d1066df9d6067969.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8ff897066a01f0f2f818ee1eb007ca41853e3b81c57e36a991fe2ca9725e29ed.png" + ], + "iris.tests.test_plot.Test1dPlotMultiArgs.test_cube.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/8ffac1547a0792546c179db7f1254f6d945b7392841678e895017e3e91c17a0f.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8ff8c1fa7a05b4ea6c059d2ff1494e4b90f26304846d78d1872a6cfc938b2e3e.png" + ], + "iris.tests.test_plot.Test1dPlotMultiArgs.test_cube_coord.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/83fec1ff7e0098757103a71ce4506dc3d11e7b20d2477ec094857db895217f6a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8fffc1dc7e019c70f001b70ee4386de1814e7938837b6a7f84d07c9f15b02f21.png" + ], + "iris.tests.test_plot.Test1dPlotMultiArgs.test_cube_cube.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/8ff8c2d73a09b4a76c099d26f14b0e5ad0d643b0d42763e9d51378f895867c39.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8fe8c0173a19b4066d599946f35f0ed5d0b74729d40369d8953678e897877879.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8ff8c0567a01b096e4019daff10b464bd4da6391943678e5879f7e3103e67f1c.png" + ], + "iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_coord.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/83fec2777e04256f68023352f6d61da5c109dec8d19bcf089cc9d99a9c85d999.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/83fec2777e06256f68023352f6d61da5c009decad19bcf089cc9d99a9c85d989.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/83fec2777e002427e801bb4ae65a1c94813dcec999db4bbc9ccd79991f3238cc.png" + ], + "iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_coord_coord.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/83fe9dd77f00e1d73000cc1df707db8184427ef8d1367c88d2667d39d0866b68.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/83fe9d977f41e1d73000cc1df707d98184427ef8d1367c88d2667d39d0866b68.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/83ff9d9f7e01e1c2b001c8f8f63e1b1d81cf36e1837e259982ce2f215c9a626c.png" + ], + "iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_coord_coord_map.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fbe0623dc9879d91b41e4b449b6579e78798a49b7872d2644b8c919b39306e6c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/bbe0c21ccd179dc3b05e4b689b0771b48698961b7962da446e8ca5bb36716c6e.png" + ], + "iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_coord_cube.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/87ffb5867f0060d4301f6d9fb007d899c50699e9c8668e78d8678d69de069969.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/87ffb79e7f0060d8303fcd1eb007d801c52699e18d769e2199e60ce1da5629ed.png" + ], + "iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_cube.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/83ffc1dc7e00b0dc66179d95f127cfc9d44959ba846658e891075a3e99415a2f.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a3ffc1d87e00b49964179d28f16bce4b98724b268c6d58e1972e4874998b2e7e.png" + ], + "iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_cube_coord.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/83fec1ff7f90987720029f1ef458cd43811cdb60d647de609485ddb899215f62.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/83fec1ff7f94987720009f1ef458cd43810cdb60d647de609485ddb89921df62.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a3ffc1de7e009c7030019786f438cde3810fd97c93734a778ce07c9f99b02731.png" + ], + "iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_cube_cube.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/83ffc8967e0098a6241f9d26e34b8e42f4d20bb4942759e9941f78f8d7867a39.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/83f9c8967e009da6245f9946e25f9ed6f0940f29f40749d8853678e8d7857879.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/83ffc9d67e00909624079daef160cf4bd45a439184367ae5979f7e3119e6261c.png" + ], + "iris.tests.test_plot.Test1dQuickplotScatter.test_coord_coord.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/a3fac1947c99184e62669ca7f65bc96ab81d97b7e248199cc7913662d94ac5a1.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a3fac1947c99184e62669ca7f65bc96ab81d97b7c248399cc7917662d84ac5a1.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a3fac1b47c99184e62669ca7f65bc96ab81d97b7e248199cc7913662d84acda0.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/b2ecc1a8b9994a16e666b5e3ce151969a5fb4ed49909653990d46b9bfc097684.png" + ], + "iris.tests.test_plot.Test1dQuickplotScatter.test_coord_coord_map.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/bea07c99c15eb16e9891ce50c742394a3ced6cb13390f1cc73c29f1b2d0ecd66.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/bea06899c14eb16e9895ce46c74a396a74ed64b13390b3c61b439f1b4d2ccde6.png" + ], + "iris.tests.test_plot.Test1dQuickplotScatter.test_coord_cube.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ae7f1f07f3e0e0f0211b9e066e074d83926ed8f8cd3792dad1964db0d80e9b09.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ae7f1f07f3e0e0f0311b9e066e074d839266d8e8cd379adad1964db0d80e9b09.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/be852fc1e078c83eb30e3607672149c098d95c5b9e4636f2c1fc299d999f7e03.png" + ], + "iris.tests.test_plot.Test1dQuickplotScatter.test_cube_coord.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/a5f896d99a67b94c621deda3f69392cccd246db39018989ec4836de9ed249292.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a5f896d99a66b94c621deda3f69392cccd646db3901898dec4836de9cd249292.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a5f896d99a67b94c621ceda3f6d392cccd246db3901898dec4836de9cd249292.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/edfa96cb9a256b4f65466d9892d9c865693a1a9c94b39ed8484b35ad9a864c32.png" + ], + "iris.tests.test_plot.Test1dQuickplotScatter.test_cube_cube.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/a4fb19b3db04c6cd6307b98678601c738c39d71cf3866186d8616e69bd191b9e.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e8b33c129649c78de3a773e578650c728e92279be12de1edc4f246b2939c3b01.png" + ], + "iris.tests.test_plot.Test1dScatter.test_coord_coord.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/bbfac39d9899384a6f6694a7b613cb489c95b7b7c24a399cc5913262d84acda0.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/b2ecc12999994e16e666b5e3ce171969a5fb4ed49909e53990c44b9b7c09f684.png" + ], + "iris.tests.test_plot.Test1dScatter.test_coord_coord_map.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/bea07c99c15eb16e9891ce50c742394a3ced6cb13390f1cc73c29f1b2d0ecd66.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/bea06899c14eb16e9895ce46c74a396a74ed64b13390b3c61b439f1b4d2ccde6.png" + ], + "iris.tests.test_plot.Test1dScatter.test_coord_cube.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/af7e1f0ff1e1e0f0d918960e6c076d8bd266d868c537365a90966db0de0e1b09.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ae7e1f0ff1e1e0f0d918960e6c076d83d266d868c537365ad0966db0de4e1b09.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/be812fc1c078c03e930e3627672369c1d8d85c5b96463662e1fc699d9b9f7e03.png" + ], + "iris.tests.test_plot.Test1dScatter.test_cube_coord.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/edf896d79a67b94c651ced23d29392cccd646d33901912fcc4836d69ed249292.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/edda96cb9a256b4765c26d9892dbc665693a1a9494b796c86c4b37ad92864c32.png" + ], + "iris.tests.test_plot.Test1dScatter.test_cube_cube.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/acf939339a16c64de306318638673c738c19d71cf3866186d8636e69bd191b9e.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/edb23c529649c78de38773e538650c729e92279be12de1edc4f246b2139c3b01.png" + ], + "iris.tests.test_plot.TestAttributePositive.test_1d_positive_down.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/87fef8117980c7c160078f1ffc049e7e90159a7a95419a7e910dcf1ece19ce3a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a7fe781b708487c360079e3bb4789869816bdb64c76b4a3cce7b4e749a6130c5.png" + ], + "iris.tests.test_plot.TestAttributePositive.test_1d_positive_up.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/87ff85d47800bd9f660779d0863f49c9947f4e1e9141de38d700da28ce1d9a2b.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/87ff85d47a00bc9f660779d8863f49c9907f4e1e9141de38d708da28ce1d9a0b.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a7ff958b7a00b09c661761c9907fcb0d9163ce7895289a618f381bffccf97200.png" + ], + "iris.tests.test_plot.TestAttributePositive.test_2d_positive_down.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fb946ba684e194fb901b3a0587641ad03b1ae7674e64c15a5b99c767c47e3a98.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fb946ba484e194dbc01f3665c0e4399a3f0fc2653f90c99e3f613e64c81e3f81.png" + ], + "iris.tests.test_plot.TestAttributePositive.test_2d_positive_up.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ee176c7f93e093a0c50f9383815e6e156859e17e6e15e17a9be08e2d851a9b83.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ebc06be1941e941ec07f941f907f6fa0950fc07e6f80c07f6b806be1c07f3f80.png" + ], + "iris.tests.test_plot.TestContour.test_tx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/cff8a55f7a15b55a7817854ad007a5e8c04f3ce8c04f3e2ac4706ab295b37a96.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/eaece0173d17951fbd03974a914964e8c04a72e8c1531ee1cc746bb293973ecd.png" + ], + "iris.tests.test_plot.TestContour.test_ty.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/8bfc815e78018597fc019b65b425d121955e7eda854b7d6a80db7eb481b72b61.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ebfa8553fc01b15ab4044a269546caa5956b7e9bc0b97f2cc2d62d360b363b49.png" + ], + "iris.tests.test_plot.TestContour.test_tz.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/8bfe81ff780185fff800955ad4027e00d517d400855f7e0085ff7e8085ff6aed.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8bfe81ff780085fff800855fd4027e00d517d400855f7e0085ff7e8085ff6aed.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8bfe817ffc00855ef0007e81d4027e80815fd56a03ff7a8085ff3aa883ff6aa5.png" + ], + "iris.tests.test_plot.TestContour.test_yx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa56c3cc34e891b1c9a91c36c5a170e3c71b3e5993a784e492c49b4ecec76393.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e85e36cb95b199999765cd3694b06478c7396329958434c2cecb6c6d69ce1b92.png" + ], + "iris.tests.test_plot.TestContour.test_zx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/8bfe857f7a01a56afa05854ad015bd00d015d50a90577e80857f7ea0857f7abf.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/affe815ffc008554f8007e01d0027e808557d5ea815f7ea0817f2fea817d2aff.png" + ], + "iris.tests.test_plot.TestContour.test_zy.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/8bff81ff7a0195fcf8019578d4027e00d550d402857c7e0185fe7a8385fe6aaf.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/abff857ff8018578f8017a80d4027e00855ec42a81fe7a8185fe6a8f85fe6ab7.png" + ], + "iris.tests.test_plot.TestContourf.test_tx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/faa562ed68569d52857abd12953a8f12951f64e0d30f3ac96a4d6a696ee06a32.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea857a81957ac57e957a857a957a958ac5723b0d6ac56b833e856e606a923e90.png" + ], + "iris.tests.test_plot.TestContourf.test_ty.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/eaa5e03f957a4f80954a9e41e16e9c60970fb5b24ada634e6e93692d4ba562d8.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea851f00957ac0f7957ac07f957a628d815e7b126ab13e816a953ae46a859ed3.png" + ], + "iris.tests.test_plot.TestContourf.test_tz.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e954a7a81857e957e857efc00857e7e007a85c02a7e859f287a85c1fe.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7a81857e7a81857e7a81857e7a806a85857a7a85857e7a85817e.png" + ], + "iris.tests.test_plot.TestContourf.test_yx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e95a6938b6b5969193901a4fc1e594a7c69999cbce33639879526e72330e65e4.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e97a3c7e968597b19685c9c696a7c79491c16e59691a387f6978396e68683184.png" + ], + "iris.tests.test_plot.TestContourf.test_zx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa85857ec45a7a81857e854a857ee56a917ec56a3a85c56a3a85c4ea7a8112fe.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81817e857e7a81857a7a81957a6e81917a6caa3a85c57a3a8585fa6a8591fe.png" + ], + "iris.tests.test_plot.TestContourf.test_zy.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81817ec40a7a81857e957e857ef40a857ef60b7a81c40a7b81e60f7a814aff.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81817e857e7a81857e7a81817a7e81817a668f7a91857e7a81857e7a85817e.png" + ], + "iris.tests.test_plot.TestHybridHeight.test_bounds.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/eab5313f954a7b9260f39789c5ec4cd084d0c4e45aa1c5fe3a04797bb13b3b06.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ee856aa5957a955ac0bf954bc17e3b819548c07f3e81c07e2ec46ea4c07f3e84.png" + ], + "iris.tests.test_plot.TestHybridHeight.test_bounds.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/be853f80854ac17ec0bdc2f5c17a0d09cc1fc07f5ab5e1fe3f409d7a38743e00.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/bf813e85c07ec57ec17e9073c07e3f81856ec17a3f80c0fe3e813f84c2733e80.png" + ], + "iris.tests.test_plot.TestHybridHeight.test_bounds.2": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/eab5313f954a7b9260f39789c5ec4cd084d0c4e45aa1c5fe3a04797bb13b3b06.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ee856aa5957a955ac0bf954bc17e3b819548c07f3e81c07e2ec46ea4c07f3e84.png" + ], + "iris.tests.test_plot.TestHybridHeight.test_orography.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa17291f95e895e8645e7a95c17a6eece4b4e1333b01c07e1bb13909914b9ec1.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa17291f95e895e8645e7a91c17a6ee464f4e1333b01c17e1bb1390d914b9ec1.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa817a91957a857ac4fe268cc07f6e846e05d9373b81d17b1b6a1b41c4fa2cc4.png" + ], + "iris.tests.test_plot.TestHybridHeight.test_orography.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/bb07314fc4e0c6b4c31e9ee1847939a1c116c15e7b94e57e1ea9391de16e1ac3.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/bb07314fc6e1c6b4c31e9ee1846939a1c116c15e7b14e17e1ea9393de16e1ac3.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/af0b690f96f0d2d4c25e94a194ad3da19a52c25e3f02c07f3fa52d03c16a3fcb.png" + ], + "iris.tests.test_plot.TestHybridHeight.test_points.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea953bfb956ac4f4649f1a05c56e6ca45a53945e6ea5c13f1b498542c13f1b41.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fe857b91917a847ec0bd3f01c47e6ca43b11915a3ea4db3b1b4a84c4c03f3fc1.png" + ], + "iris.tests.test_plot.TestHybridHeight.test_points.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/be813fc0c15ac13dc1bfc27dc17e1d93c51fc43f1ea1c17a3ec138e4b1721a81.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/be813a81c17ec57ec17e952ac07f3f808556c17e3f80c07f3e813f80c27e3f81.png" + ], + "iris.tests.test_plot.TestHybridHeight.test_points.2": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea9561ef956a7b92609b922dc16e6ec6845ac47e5aa5c57e5ec04861957b1b81.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fe856a85957a955ac03f956ac17f3f809552c07f3e81c07e3e806e85c07e3f84.png" + ], + "iris.tests.test_plot.TestHybridHeight.test_points.3": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea953bfb956ac4f4649f1a05c56e6ca45a53945e6ea5c13f1b498542c13f1b41.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fe857b91917a847ec0bd3f01c47e6ca43b11915a3ea4db3b1b4a84c4c03f3fc1.png" + ], + "iris.tests.test_plot.TestHybridHeight.test_points.4": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/baf5347ecf0ac3f1c1f68f83850b1f83cc11c0fc7ad0c17a1be138e4b07e1a0d.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/b878387e978ec2f0c0f09f83878f3f81c070c0fe78d0c1763fa13856d03e3f0f.png" + ], + "iris.tests.test_plot.TestMissingCS.test_missing_cs.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fac16ee0953b911bc15e9648e56ec4e691be7bcc7a8184733ea16a90c17e930d.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa816ac1857e853cc17f957ac15f3e849486c8f43e81c13b3f813e91c07e3f46.png" + ], + "iris.tests.test_plot.TestMissingCoord.test_no_u.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fe816a95c17fb51e953e9485857a1f409552856a1f81c17e5ab94e15c0ff5a85.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a95955a954ac17f954ac07e3f48951ec07e3e81c0ff7ea16a81c0bf3e81.png" + ], + "iris.tests.test_plot.TestMissingCoord.test_no_u.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/be0e695ac3f096b5943fd2a185fc1e8590e594ee1e05c17a4f403d0fe1fe4b42.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea956ab5954a954ac17f954a817e3f40950ac07f3e81c0ff7a856aa1c0ff3f80.png" + ], + "iris.tests.test_plot.TestMissingCoord.test_no_v.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b6c0773d09956a955a857a1d88845ec57e3f81c07e4ae56b21d0ff5a85.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa816a85957a857ac17e954ac17e1fa2950bc07e3e81c07f3e807a85c17f3f81.png" + ], + "iris.tests.test_plot.TestMissingCoord.test_no_v.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa9562d4c7c43d0bb57b97e0857a3f1995d284763a05c17a7b856a2dc0f45a84.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa856a85957a857ac17e954ac17e9d02954ac07e3e81c07f3e857a85c2fd3f80.png" + ], + "iris.tests.test_plot.TestMissingCoord.test_none.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b6c0763d09b54a955a857a3f88845ec57a3e85c07e6a616b25d0ff7a81.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa816a85957a857ac17e954ac17e3fa29506c07e3e81c07f3e807a84c1ff3f81.png" + ], + "iris.tests.test_plot.TestMissingCoord.test_none.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562f6c0773d09b54a955a857a3f81955ac47e3e85c17e7aa16a25c0765aa1.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa856a85957a957ac17e954ac17a1f06954ac07e3e81c07f3e817a85c0ff3f80.png" + ], + "iris.tests.test_plot.TestPcolor.test_tx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e85e67c9c7e1391e97a596b03a3696a13c4f63066318695ec5c9695e6c49c6a5.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea817a81957e857e957e953e957e857e857e6aa06a816ac16a017a816a9585fa.png" + ], + "iris.tests.test_plot.TestPcolor.test_ty.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b3878958b38f8c7236a557a542c7868d54b877875978abc789722.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b387895ab38f8c7236a557a542c7868d54b05787197eab478972a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea953f83954ac2bc956ac07e956a3509c0de61796ab57a816a856ad16ab590fb.png" + ], + "iris.tests.test_plot.TestPcolor.test_tz.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e874978b978b6875978b6875978b7854950b78506855787468747ea2687597aa.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857a7a84857a7a85857e7a813a2f7a817a85857a7a85857a7a85857a.png" + ], + "iris.tests.test_plot.TestPcolor.test_yx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e95e696994b196b793b19a1ec3c191c5c6e596191e4e693269336c36391a6e3a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e97a387e968596319697c3c19284a62c93a560c36933393a6c7e793b6c6b31cd.png" + ], + "iris.tests.test_plot.TestPcolor.test_zx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e85e87a197a1695a97a1695a97a17d5a97a17906785a7816685a7e86685ad687.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857a7e01857e7a81857e7a81e8177a816a8585fa7a85857e7a81857e.png" + ], + "iris.tests.test_plot.TestPcolor.test_zy.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/af42c0bdd0ad2f52d0bd3f42d0bd7f02d0bd7f003d527f002f427ea82f42d6a8.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/af42c0bdd0ad2f52d0ad2b52d0bd7f02d0bd7f002d527f002f527e0d2f52d4ad.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7e80857e7a81857e7a812d557a817a85857e7a81857e7a80857e.png" + ], + "iris.tests.test_plot.TestPcolorNoBounds.test_tx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa1594f3858a670c94e37b1cccb13e736a1d8cf17a1f94e2c119938e9463678c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea858782957a703f957a3878957a7a65957a6bc06ae76f806ad50fd06a859c50.png" + ], + "iris.tests.test_plot.TestPcolorNoBounds.test_ty.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ad5e94a5c3b0c3f096a5695a96a53c0f711b3c0f7d1b97b46943c3e0cc416b5a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea85857a857e7e81957a7a81957a6a85857acac6c1fb6aa67a81956e6a81b506.png" + ], + "iris.tests.test_plot.TestPcolorNoBounds.test_tz.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/a95e3c1f96a096a5d6a5eb40c3f0ebe0c1c0c3f07c0b3e3e96a13c1e6d5b694a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a95e381f96a096a5d6a5eb40c3f0ebf0c1e0c3f07c0a3e3e96a13c1e6d5b694a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa817e81857e857a857e7a81857e6a85817b81e63a913e857e81c17e7a81956e.png" + ], + "iris.tests.test_plot.TestPcolorNoBounds.test_yx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/bc7a1c32d3c366cdc585c39986cdc79ec792e3a6960d584939793c3438743873.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e96ac78796953c4c9685383996c538e69692637263696b49693ac796693ac71b.png" + ], + "iris.tests.test_plot.TestPcolorNoBounds.test_zx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea1f781f95e085e885e0954295e195ea95a085e87a153e7f95e06a1778557a1f.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa817a81857e857e857e7a81857e6a81c17f95786aa77a807e81c17c7e819558.png" + ], + "iris.tests.test_plot.TestPcolorNoBounds.test_zy.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ba173a1795e895e8c5e8f400c1f8c1f895a8c5e87a077a5ec5e83e173e177e02.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa817a80857e857e857e7a81817e3e81817e857f6aa07a857e80c17f7e80c15f.png" + ], + "iris.tests.test_plot.TestPcolormesh.test_tx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e85e67c9c7e1391e97a596b03a3696a13c4fe3026318695ec5c9695e6c49c6a5.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea817a81957e857e957e953e957e857e857e6aa06a816ac16a017a816a9585fa.png" + ], + "iris.tests.test_plot.TestPcolormesh.test_ty.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b3878958b38f8c7236a557a542c7868d54b877875978abc789722.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b387895ab38f8c7236a557a542c7868d54b05787197eabc789722.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea953f83954ac2fc956ac07e956a3509c0de61796ab57a816a854ad16ab590fb.png" + ], + "iris.tests.test_plot.TestPcolormesh.test_tz.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e874978b978b6875978b6875978b7854950b78506855787468747ea2687597aa.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857a7a84857a7a85857e7a813a2f7a817a85857a7a85857a7a85857a.png" + ], + "iris.tests.test_plot.TestPcolormesh.test_yx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e95e696994b196b593b19a1ec3c591c5c6e596191e4e693269336c36391a6e3a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e9693878969696139296c38f9bcc3474692169cb6c7339393c6cc387c78796cc.png" + ], + "iris.tests.test_plot.TestPcolormesh.test_zx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e85e87a197a1695a97a16d5a97a17d5a97a17806785a7816685a7e86685ad687.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e6e05857e7a81857e7a81a0577a816a8585fa7a85857e7a81857e.png" + ], + "iris.tests.test_plot.TestPcolormesh.test_zy.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/af42c0bdd0ad2f52d0bd3f42d0bd7f02d0bd7f002d527f002f427fa82f42d6a8.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/af4280bdd0ad2f52d0ad2b52d0bd7f02d0bd7f002d527f002f527f0d2f52d4ad.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7e80857e7a81857e7a8129577a817a85857e7a81857e7a80857e.png" + ], + "iris.tests.test_plot.TestPcolormeshNoBounds.test_tx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa1594f3858a670c94e37b1cccb13e736a1d84f17a1d94e2c11d938e9463678e.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa1594f3858a670c94e37b1cccb13e736a1d8cf17a1d94e2c11993ae9463678c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea858782957a703f957a3878957a7a65957e6bc06ae56f806ad50fd06a859c50.png" + ], + "iris.tests.test_plot.TestPcolormeshNoBounds.test_ty.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ad5e94a5c3b0c3f096a1695a96a53c1f711b3c0f791b97b46943c3e06c436b5a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea85857a857e7e81957a7a81957a6a85857acae6c1fb6aa47a81956e6a81b506.png" + ], + "iris.tests.test_plot.TestPcolormeshNoBounds.test_tz.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/a95e3c1f96a096a5d6a56b40c3f06be2c1c0c3f07c0b3ebe96a13c1e6d5b694a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa813e81857e857a857e7a81857e6a85817b00e63eb93e857e81c17e7a81956e.png" + ], + "iris.tests.test_plot.TestPcolormeshNoBounds.test_yx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/bc7a1c32d3c366cdc785c39986cdc78ec792e7a6960d584939793c3438703873.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e129c7169ed638ec9ed6387196c761c665396724612dcf0d693896929ed698c9.png" + ], + "iris.tests.test_plot.TestPcolormeshNoBounds.test_zx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea1f781f95e085e895e0fd4295e095ea95a085e87a153e7e95e06a1778157a17.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa817a85857a857e857e7a81857e7a81817f95506aaf7a807e81c17c7a81957a.png" + ], + "iris.tests.test_plot.TestPcolormeshNoBounds.test_zy.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ba176a1795e895e8c5e87c00c1f8c1f894a8c5e87a077adec5e83e173e177a06.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa817a80857a857e857e7a81857e3e81817e2fc56aa07a857e80c17f7e80c17f.png" + ], + "iris.tests.test_plot.TestPlot.test_t.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/83fe955f6a05e5137305d9c4f443127195187e9cd5467fa3d4917b68fc007a1a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8ffe95027e05e7007305d9c4a447127f853f069f814f2fa7d4d12b6cfc007e5a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8ffe9c1a7e05e718f305d9d2e46312718138049e824e2fa783db2bed76b4fe00.png" + ], + "iris.tests.test_plot.TestPlot.test_t_dates.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/abffd5ae2a15cdb6b10178d7d4082e57d7290906f685814277b1dc88724cfd26.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/abffd5ae2a15c9b6a10178d7d4082c57d7290906f6c58942f7b1dc88724cfd26.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/abffd4a02a01cc84f10078d7d4082c77d73909ded6ef816273bd9c98725cdd26.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/87fc9d8a7e054d83f5067bc1c1423471927ba73c8d9f864e09a1a7b358c8276f.png" + ], + "iris.tests.test_plot.TestPlot.test_x.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/8ffe95297e87c74a6a059158f89c3d6ed0536597c0387836d0f87866d0697097.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8bfe956b7c01c2f26300929dfc1e3c6690736f91817e3b0c84be6be5d1603ed1.png" + ], + "iris.tests.test_plot.TestPlot.test_y.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/8fe896266f068d873b83cb71e435725cd07c607ad07e70fcd0007a7881fe7ab8.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8fe896066f068d873b83cb71e435725cd07c607ad07c70fcd0007af881fe7bb8.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8fe896366f0f8d93398bcb71e435f24ed074646ed07670acf010726d81f2798c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/aff8946c7a14c99fb193d263e42432d8d00c2d27944a3f8dc5223ef703ff6b90.png" + ], + "iris.tests.test_plot.TestPlot.test_z.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/8ffac1547a0792546c179db7f1254f6d945b7392841678e895017e3e91c17a0f.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8ff8c1fa7a05b4ea6c059d2ff1494e4b90f26304846d78d1872a6cfc938b2e3e.png" + ], + "iris.tests.test_plot.TestPlotCitation.test.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/abf895067a1d9506f811783585437abd85426ab995067af9f00687f96afe87c8.png" + ], + "iris.tests.test_plot.TestPlotCitation.test_axes.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/abf895067a1d9506f811783585437abd85426ab995067af9f00687f96afe87c8.png" + ], + "iris.tests.test_plot.TestPlotCitation.test_figure.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/abf895067a1d9506f811783585437abd85426ab995067af9f00687f96afe87c8.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_non_cube_coordinate.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7e81857e7a81857e7a81857e7a818576c02a7e95856a7e81c17a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e3e85857e7a81857e7a81857e7a817e81780b7a81c56a7a81857e.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fe8142f5c17ebd2cc16eb548954a9542916a347a915e60bd4afd68793f916296.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea853f10956ac5e1957a854e957a203e955e6aa76ae17aa16a856aaf6ab19e12.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa8542b7b503b548857abd08857abd09945eed6b91d968c161b972d76aa462b5.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa8542b7b503b548857abd08857abd09945eed6a91d96ac163b972d36aa462b5.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea853a85857a857a957a857a957ad05a857b3e946a606b917a816f647a853af4.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.2": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/8bf88f457a03b5307e16b561f007b53ed067217ac1786afec0f570bf8178681a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8bf98f057a03b5307e16b561f007b53ad067217ac1786afec0f570bf8178685a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/eafdcec9bc219530b696a56694c2852a95656b7b81986acdc0e516adad186eda.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.3": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/8ffe8f367e05952afe05a50b980ded4bd05d69c2c1fb71c1c06272f4d0a06af4.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/aff24ab7bd05952fbd0f950f914fcd48c47860f3e1b9329094266e345a850f6c.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.4": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/aa953d0f85fab50fd0f2956a7a1785fafa176877d00f68f1d02c60f2f008d0f0.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ebeaa5419e94b5019e97950d685395bee05361fad05560fad01570fef001dabe.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ebeaa5419e95b5419e97950d6853953ee053617ad05560fad01570fef001dabe.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ebfaa56f96a1856cd681a56ee8162d52e8467e12c50c7e8095ad7e0095ad03ff.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.5": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ebfaaf439e87b5019687b5019687b56ac05561fae07103fe6079687a607178f8.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ebfa2d4b968795059e87970f6854697ae055697ac08561fad041d7aef001d6ae.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/eb7a3e0c978187a4950190bc6856687a607e687bc0fcc1e394acfc0197fc2bfb.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_x.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/aeb8b5095a87cd60386592d9ec97ad6dd23ca4f6d0797827f0096216c1f878e6.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/affa950ddb13c03634359ad8a4c80f26911f26f3c06e0ff3f4007b4285fd6e72.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_y.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/8fea97194f07c9c830d79169ce16269f91097af6c47861f6d0796076d0797a16.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8fee970b4f07c9c930d79129ce16269f91097af6c4f861f4d0786076d0797a16.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/afea97094f07c9c870d79129ce16269f91096af6c4f861f6c07960f6d0797a16.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/afee9632de05c9d9f180d168c454a53e931b3e84956a3b8c85d94ce703ff7284.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_yx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea85603f956a9741951e9d83c1fa8d2fd0a55af0d25f345ae5f062c72d68612d.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea853f00957ac07c957ac0be951a69f3c47c7a5f3a6127816b953e646b813761.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_yx.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e85a69cc96ad92e193c9963385929e1cc3819acde6d965ce6e666b30386e65b1.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e97a346c9685cb899685c9c39695c79396ec634969ce2c74697a3864697b3c8c.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_yx.2": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/8ffcc65767039740bc069d9ad00b8dadd03f52f181dd347a847a62ff81e8626c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8ffcc65777039740bc069d9ad00b8dadd03d52f181dd707a847a62ff81e8626c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ebffca44f502b36498309c9b940999add1bb62bba784374acc5a6a246acc6b65.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_yx.3": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea5649c434ac92e5d9c9361b95b39c38c3835a5ec6d966ced34c633099ace5a5.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e85a6b6c96a597a591c9949b94b61b69c7926b5bccce66646b3869b831a52c26.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_yx.4": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2dd2d09295c3c0c7d13c1bc6d23d2c696de0e53c3ac393daf6d205c2c4.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2fd2d09295c3c0c7d13c1bc6d23d2c696ce0e53c3ac393dbf6d205c2c0.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2f92d09295c3d0c7d13c1bc6d23d2c696cf0e53c3ac2b3d9f6d201c2c4.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e85e3e2f97a1c19996a1c8f26c1e360f684a3c2c6913dca497b9d38097a903ff.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e85e3e3f96a1c3e197a169f1785e3b0e68523e1c398bc58687b1d86096e1039f.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_yx.5": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e9686d8c9696924797879e3b86929e58696d69cc6869659379626133398d9ccd.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e961658f961e92469e1e1c7966f36cd86165618c70e166b39b9698719e1e9ec8.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e1a530e29e5ecf199a5acd8f64f1326161a530e265999cd29e52cf199a5e6669.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_zx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/bf803f00c05fc4bfc07ec15dc05fd8bbc07cc96c333a32113bd02dd27ced3ec0.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/be813ea0c17ec55ac17ed23dc07e295ac57e3b653f803f813e816e853e81b542.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_zx.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea95956a95626993941a6a2d956e6ed6845a6e65c4bec7b64a9594686ea19578.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea85856e857e4893957a7aa1956a7b81954b3b817a856fd46a85846e6e85857e.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_zx.2": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/8fe82f047c018c83bc01bc5af01fd1bcd15a327c847860fdc57a69beb0be68bd.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8fe82f047c018c83bc01bc5af01fd1bcd15a32fd847860fdc57269beb0be689d.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8bedcf25bc03a4929c103a5bf03fdbbc81cb364d86e46da70f86899b3a0f6cc0.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_zx.3": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/cee8953a7a15856978579696d03d672cc49a6e5a842d3d2cc0b66bd1c2ea39f1.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/aee1f93a63168569b852d697913d632485ca2e43952d3bbcc2b66bd1426b3c71.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_zx.4": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ee953f0591ea3f07914a95fa7e07d1fa68156a15d07c6a3dd038c0fef000d0fa.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ae953f0591ea3f07914a95fa7e07d1fa68156a15d07c6a7dd068c0fef000d0fa.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/bec11ab5c1be857ac13e7ae53c422d423e017a85b542fc00c1fefe0091fe03ff.png" + ], + "iris.tests.test_plot.TestPlotCoordinatesGiven.test_zx.5": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e87a973d96a56953968769439685a54ae05117eae0511fba60513bba69717aba.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e87a952d96a56953968769439685a54ae85197eae0511fba60513bba69717aba.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e85a96ac97a16c5897a1791e95a53b0b913c6953687c4ec3685cc6c36e7c87c3.png" + ], + "iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_coord_names.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/f9789b388786678686966c9093879ce592c79bc94d19929b6939cf66316c672c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/b87830b0c786cf269ec766c99399cce998d3b3166f2530d3658c692d30ec6735.png" + ], + "iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_coord_names.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e9a53a59961ec5a62c691a587b9662e1c0e1e53e9e0e9b873ec15a7161bc642f.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/b8a53b59c71ac5a6b8791c1867876b63d9e0e65c96199d871cc23339633664ce.png" + ], + "iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_coords.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/f9789b388786678686966c9093879ce592c79bc94d19929b6939cf66316c672c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/b87830b0c786cf269ec766c99399cce998d3b3166f2530d3658c692d30ec6735.png" + ], + "iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_coords.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e9a53a59961ec5a62c691a587b9662e1c0e1e53e9e0e9b873ec15a7161bc642f.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/b8a53b59c71ac5a6b8791c1867876b63d9e0e65c96199d871cc23339633664ce.png" + ], + "iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_default.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/f9789b388786678686966c9093879ce592c79bc94d19929b6939cf66316c672c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/b87830b0c786cf269ec766c99399cce998d3b3166f2530d3658c692d30ec6735.png" + ], + "iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_yx_order.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa81948e857e4971907ea72e95fa66b2952e4ead6d429b527ac7a5286e981836.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa85978e837e68f094d3673089626ad792073985659a9b1a7a15b52869f19f56.png" + ], + "iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_yx_order.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea159694856a6b5096afa53a36941da1e4f5c369cd1ae6d69b6a1c80625af2f6.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea95969c874a63d39ca3ad2a231cdbc9c4973631cd6336c633182cbc61c3d3f2.png" + ], + "iris.tests.test_plot.TestPlotOtherCoordSystems.test_plot_tmerc.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e63399cd99cd64b29999335965369b262649c98c9b3966c6998d3319ccd69333.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e665326d999ecc9b3319b3246666cce69b496cccccc9669923193336666699a6.png" + ], + "iris.tests.test_plot.TestQuickplotPlot.test_t.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/83ffb5d67fd4e5962211d9c6a443da77d5389c8ed346d923d011d968dc00da48.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/82ffb5d67fdde5962211d9c6a441da77d5389c8cd346d927d011d968dc00da48.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/82fabd867fd5e5822201d9c6a4539a77953d8cbf834f99e7d051996cdc00da48.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/83ffb59a7f00e59a2205d9d6e4619a74d9388c8e884e8da799d30b6dddb47e00.png" + ], + "iris.tests.test_plot.TestQuickplotPlot.test_t_dates.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/a3ffd5ae7f51efb6200378d7d4082c17d7280906d6e58962db31d800da6cdd26.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a3ffd4ae7f55efbe200178d7d4082c17d7280906d6e58962df319800da6cdd26.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a3ffd4827f51ef94200078d7c4082c57d739095ed6ed8962db759808da6cdd26.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/82fd958a7e006f9ba0077bc5c9462c759873dd3c8d8f826699a187b358c82f67.png" + ], + "iris.tests.test_plot.TestQuickplotPlot.test_x.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/83ffb5097e84c54a621799d8601d9966d213cd67c039d876d078d866d869d8f7.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/83ffbd097e84c54a621799d8601d9966d253cc27c039d876d078d866d869d8f7.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/82ff950b7f81c0d6620199bcfc5e986695734da1816e1b2c85be2b65d96276d1.png" + ], + "iris.tests.test_plot.TestQuickplotPlot.test_y.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/a7ffb6067f008d87339bc973e435d86ef034c87ad07c586cd001da69897e5838.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a7ffb6067f008d87339bc973e435d86ef034c87ad07cd86cd001da68897e58a8.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a7efb6367f008d97338fc973e435d86ef030c86ed070d86cd030d86d89f0d82c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a2fbb46e7f10c99f2013d863e46498dcd06c0d2798421fa5dd221e7789ff6f10.png" + ], + "iris.tests.test_plot.TestQuickplotPlot.test_z.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/83ffc1dc7e00b0dc66179d95f127cfc9d44959ba846658e891075a3e99415a2f.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a3ffc1d87e00b49964179d28f16bce4b98724b268c6d58e1972e4874998b2e7e.png" + ], + "iris.tests.test_plot.TestSimple.test_bounds.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa9562fcc7c0b50bb53b9f8085727a157a95c0f67a85e07e0be08069e07d9fa0.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a85954a957ac17e954ac17a9c3e956ac07e3e81c07f3e857aa5c2753f80.png" + ], + "iris.tests.test_plot.TestSimple.test_points.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b7c2763d09956a955a855a1d88d45ec57a3f81c07e6ae16b21c0ff7a81.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a85957a957ac17e954ac17e1ca2954ac07e3e81c07f3e807a85c1ff3f81.png" + ], + "iris.tests.test_plot.TestSymbols.test_cloud_cover.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e95a330c96a5ccf2695a330c96a5ccf2695a330c96b5ccf3694a330c96b5ccf3.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/eb52916494ad6e1b6b5291e494ad6e1b6b5291e494ad6e1b6b5291e494ad6e1b.png" + ], + "iris.tests.test_quickplot.TestLabels.test_alignment.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa95350f952ad2f0c1f66ac1c55a4af4e550a52b3e05905e1e419e6f937e3b21.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa95350f952ad3f0c1f66a81e55a4af4e550a52b3e05905e1e419e6f937e1b21.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/be8137f4954ac03fc0ff3e81d03f496a6d00b4af3ea0c07f6fa232c0db7f2d00.png" + ], + "iris.tests.test_quickplot.TestLabels.test_contour.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/a3fd956a7a01a5ee321fc96666919b6ec15fdca593600d2586785a259dfa5a01.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a3fd956a7a01a5ee3217c9e66691996ec15fdca593680d2586785a259dfa5a01.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a7fd95da7a01654a3217c962e4819a56c96f3c8593624da584da3b658db662db.png" + ], + "iris.tests.test_quickplot.TestLabels.test_contour.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/faa12bc1954ef43fc0bf9f02854a4ee48548c17a5ab5c17e7a0d7875a17e3a81.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/bf802f85c17fc17fc07eb42ac07f3f929130c07e3f80c07f7aa02e85c07f3e81.png" + ], + "iris.tests.test_quickplot.TestLabels.test_contourf.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fe812f88957a955a857a9257c17f7aa5c03dc0bf5a85c07e7f402d40a57a3f01.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/be816a95957a957ac0fe1e8bc07f7f806e01c07f3f80c07f3fa23f00c07f3d00.png" + ], + "iris.tests.test_quickplot.TestLabels.test_contourf.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/faa12bc1954ef43fc0bf9f02854a4ee48548c17a5ab5c17e7a0d7875a17e3a81.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/bf802f85c17fc17fc07eb42ac07f3f929130c07e3f80c07f7aa02e85c07f3e81.png" + ], + "iris.tests.test_quickplot.TestLabels.test_contourf.2": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa852f81955ac532c0bf9e89c57edae69357e13f4ea0c05a3f8561a4935a3e01.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/be816a95907ae508c17e955ac07f3fa0945bc07f3f80c07f3aa36f01c0ff3f80.png" + ], + "iris.tests.test_quickplot.TestLabels.test_contourf_nameless.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/faa52ec1955ac536c0bf9e09c57edae69357e13f4e80c0da2f81618493da3f01.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/be816af5907ee508c17e955ac03f3f809419c07f3f80c07f3a8b6f81c0ff3f80.png" + ], + "iris.tests.test_quickplot.TestLabels.test_map.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea5e618434ac36e5c1c9369b95b39c38c3a39a4fcee19a6e9b64cb609925cd25.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e85a636c86a597a593c9b49b94b79969c396c95bccc69a64db30d9b039a52c26.png" + ], + "iris.tests.test_quickplot.TestLabels.test_map.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea5e618434ac36e5c1c9369b95b39c38c3a39a4ecef19a6e9b64cb609925cd25.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e85a636c86a597a593c9b49b94b79969c396c95bccc69a64db30d9b039a52c26.png" + ], + "iris.tests.test_quickplot.TestLabels.test_pcolor.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/bb423d4e94a5c6b9c15adaadc1fb6a469c8de43a3e07904e5f016b57984e1ea1.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/eea16affc05ab500956e974ac53f3d80925ac03f2f81c07e3fa12da1c2fe3f80.png" + ], + "iris.tests.test_quickplot.TestLabels.test_pcolormesh.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/bb433d4e94a4c6b9c15adaadc1fb6a469c8de43a3e07904e5f016b57984e1ea1.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/eea16affc05ab500956e974ac53f3d80925ac03f3f81c07e3fa12da1c27e3f80.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_non_cube_coordinate.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa816a85857a955ae17e957ec57e7a81855fc17e3a81c57e1a813a85c57a1a05.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fe816a85857a957ac07f957ac07f3e80956ac07f3e80c07f3e813e85c07e3f80.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa856a95e15ab51a953e9485857a1f409552857e1fc1c07e5abd4a35e07f4aa5.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a95955a956ac17f950ac07e3f48951ac07f3f81c0ff3ea16aa1c0be3e81.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b7c2763d09956a955a855a1d88d45ec57a3f81c07e6ae16b21c0ff7a81.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a85957a957ac17e954ac17e1ca2954ac07e3e81c07f3e807a85c1ff3f81.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.2": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/8aff878b7f00953062179561f087953ad167997a80784a7fc1e5d86d9978485f.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/8aff878b7f80953860179561f087953ad167997a80784a7fc1e5d86d9978485b.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/eafdc6c9f720953030968d6795d28d6a95674b7b81304aedc9e51cad8d186c9a.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.3": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/82ff8db67f94952e76159d6bb01dcd629059c962c1fbd9c1c062da74d820ca74.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/82be8db67f95952e761d9d6bb01dcd628059c962c1fbd9e1c072da64d060ca74.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/82fe8db67f95952e76159d6bb01dcd629059c962c1fbd9e1c072da64d020ca74.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a2ff6a967f00952eb40d9d0f900fcd62c47069f3d1f93a909c266e34d8a56f68.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.4": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/aa97b70ff5f0970f20b2956a6a17957af805da71d06f5a75d02cd870d800d8f2.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e1faa549de9497090697971d60539f3ef171c87ac075487ad025d87ed801da3e.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/eadab54fd7a1856d90819d6df8169962e946d862802ed8809ded7e809d2d03ff.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.5": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e8faad47f784bd0596859d03969f9962c05dc96ee07189fe6870c862687178f8.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a8fa2d4797859585b6959d07605f896ee051697ad061d9fad0619aaed801deae.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/aa5b3c0c978187a4b60199bc605f6976687e6873d07c99e390acdc0391fc2f7b.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_x.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/a6ffb5097e84cde2224598d1649f8d6cd2388c76d0799867d009da76c9f8d866.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a6bfb5097f84cde2224599d1649f8d6cd2388c76d0799867d009da76c1f8d866.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a6fbb50cfbd0c036203598dce4c88d26d32f8cf3886e1df3dc047b4289ec6e72.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_y.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/a7ff978b7f00c9c830d7992166179e969509d866c478d964d079c876d869da26.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a7ff97837f00c9c830d79921661f9e9695099876c478d964c079c876d879da26.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a2ffb6127f0dc9993085d960c6748d3e9b121ca49d6a1b048df34ce789ff7205.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_yx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a9ff16eb740954a9e05855a19a3c0fbc13e1ea5c07d5ad0cb58e45e3c35.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a95957a957ac07e954ac17e3e87950bc07f3ea4c27d3e833ac1c1e03f80.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_yx.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e5a565b69e1a9a42917e1a19c17b3a619e59c47b3a25c53e3b8430e5c57a3e85.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e5a761a79a589e58c07d1e48c07c3f819e41c07f3d84c17e3fa62585c0fe3f83.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_yx.2": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/afffe6d67700958636179d92e019992dd039daf5817d987a807a48e499684a6d.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/aeffe6d67780958636179d92e019892dd139daf5815d987a807a48e699684a6d.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/eaff6ad4f74ab16490109c9b942999add1b74bb785a41d4acd526a254acc6365.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_yx.3": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea5e618434ac36e5c1c9369b95b39c38c3a39a4fcee19a6e9b64cb609925cd25.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e85a636c86a597a593c9b49b94b79969c396c95bccc69a64db30d9b039a52c26.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_yx.4": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2fd2d09295c2d1c3d33c1bc2d67d2c696ce0653c3ac2b1d976da05c2c4.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2fd2d09295c2d1c3d33c1bc2d27d2c696ce0e53c3ad2b1d976da01c2c4.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e85e3e2f97a1c19996a1c8f26d1e3a0f684a3c2c6913dc2497b9db8095e502ff.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e85e3c1f97a1c3e197a1c9f37c5e390668521e0c390bdd8685b1d86096e5279f.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_yx.5": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e968658e969692c797879e3b86929e58696d49cd6869c9a37962c923990d9c6d.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e9e1658e961e92569e9e3c7966d36c586165698c70e1ce739b3698619e1e984c.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e1a530e29e5ecf199a5acd8f64f1326161a538e665a198d29e52cb1d9a5e6669.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_zx.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/bf813f80c156c05dc0fec29dc17f1a6dd05fc0ff1aa1c57e3b243b20375a1e81.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/be816a81d17ec57ac07e952ac07f3aa0955ec17e3f80c07f3f803f80c0bf3f81.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_zx.1": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ea95629d956a996069939e9bc07f7aad856cc47e5e81857a1e254a35c1be1b81.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/fa816a85957a957ac03f957ac07f3ba1954ac07e3e81c07f3ea47a85c07e3e80.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_zx.2": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/87ed2f867f008d8220179852f01fd9bed1789a6c847cc877c46ac972987ec8fd.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/87ed2f067f008d8220179852f01fd9bed1789a6c847cc877c468c9f6987ec8fd.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/87ed2f067f008d8220179c52f01fd9bed1789a6c847cc877c560c976987ec8fd.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a3eded05fe11a492b000985af07fdbb4d1e3366d8c644da79fa68993180f6ec1.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_zx.3": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/a2f9b5ba7600a56962df9e96f01dc926c498cc46847f9d6cd0244bf19a6b19f1.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/a2f9b5ba7600856962df9e96f01dcd26c498cc46847f9d6cd0244bf19a6b1975.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/aef9f93a770085e9205fd696d13c4b2485ca1a43952f1934daa66bd1ca6b3c71.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_zx.4": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/ae953f87d5e82d86801f91ee6e1591fe7e117876c07d6877d068d878d800d07a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/ae953f87d5e82d87801b91ee6e1599fe7e117874c07d6877d068d878d800d07a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/bec1329dc5be85dac01d58d73e419d423e41daa59822dc00c5fefe0091fe03ff.png" + ], + "iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_zx.5": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/e87a952d96856943969f694696858d4ee0519d6ee07f9b6a78619b2a79711a2a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e87a952d96856943969f694696858d4ae0519d6ee07f996a78719b2a79711a3a.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/e85e96ac97a168d897a5791695a19927913c3953687ecce3687c86e3487cc6c3.png" + ], + "iris.tests.test_quickplot.TestTimeReferenceUnitsLabels.test_not_reference_time_units.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/82faa1977fdf89976200ddf6e000d9e7f75f9866d560dae4dc00d966dc005e20.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/82b8a1977fdf89876200dde6e000d9e7f77f9866d560dfe4dc00d966fc005e20.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/82f8a1977fdf89876200ddf6e000d9e7f77f9866d560dee4dc00d966dc005e20.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/82f8a1977fdf89876200dde6e000d9e7f77f9866d560dfe4dc00dd64dc005e20.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/82faa19e7f51898c6001dd86845fd9a2dd7f996281ee19f389ef03ffdc007e00.png" + ], + "iris.tests.test_quickplot.TestTimeReferenceUnitsLabels.test_reference_time_units.0": [ + "https://scitools.github.io/test-iris-imagehash/images/v4/82fe81987fd777ffe0002addd4002805dda8de65dde9d4625bfddc209841de20.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/82fe81987fdf77ffe0002a9dd4002805ddaade65d9a9d5625bfddc209841de20.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/82fe81987fdf77ffe0002addd4002805dd28df67d9a9d4625bfddc209841de20.png", + "https://scitools.github.io/test-iris-imagehash/images/v4/82fa80997f547799a0037a00d52f0956ddaf9f7e98a1816e09f5d8260bfffe00.png" + ] +} \ No newline at end of file diff --git a/lib/iris/tests/results/integration/grib2/TestDRT3/grid_complex_spatial_differencing.cml b/lib/iris/tests/results/integration/grib2/TestDRT3/grid_complex_spatial_differencing.cml new file mode 100644 index 0000000000..b15c6a4308 --- /dev/null +++ b/lib/iris/tests/results/integration/grib2/TestDRT3/grid_complex_spatial_differencing.cml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/integration/grib2/TestDRT3/grid_complex_spatial_differencing.data.0.json b/lib/iris/tests/results/integration/grib2/TestDRT3/grid_complex_spatial_differencing.data.0.json new file mode 100644 index 0000000000..f42d355d31 --- /dev/null +++ b/lib/iris/tests/results/integration/grib2/TestDRT3/grid_complex_spatial_differencing.data.0.json @@ -0,0 +1 @@ +{"std": 7.798695691713748, "min": -34.43, "max": 33.009999999999998, "shape": [73, 144], "masked": true, "mean": 2.3147813807531383} \ No newline at end of file diff --git a/lib/iris/tests/results/integration/grib2/TestGDT30/lambert.cml b/lib/iris/tests/results/integration/grib2/TestGDT30/lambert.cml new file mode 100644 index 0000000000..a33d0b04ba --- /dev/null +++ b/lib/iris/tests/results/integration/grib2/TestGDT30/lambert.cml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/integration/grib2/TestGDT30/lambert.data.0.json b/lib/iris/tests/results/integration/grib2/TestGDT30/lambert.data.0.json new file mode 100644 index 0000000000..99d58c5e34 --- /dev/null +++ b/lib/iris/tests/results/integration/grib2/TestGDT30/lambert.data.0.json @@ -0,0 +1 @@ +{"std": 5.3916288115779398, "min": 265.550048828125, "max": 300.862548828125, "shape": [799, 1199], "masked": false, "mean": 287.6306666328037} \ No newline at end of file diff --git a/lib/iris/tests/results/integration/grib2/TestGDT40/reduced.cml b/lib/iris/tests/results/integration/grib2/TestGDT40/reduced.cml new file mode 100644 index 0000000000..f2ca666998 --- /dev/null +++ b/lib/iris/tests/results/integration/grib2/TestGDT40/reduced.cml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/integration/grib2/TestGDT40/reduced.data.0.json b/lib/iris/tests/results/integration/grib2/TestGDT40/reduced.data.0.json new file mode 100644 index 0000000000..4cd44b531e --- /dev/null +++ b/lib/iris/tests/results/integration/grib2/TestGDT40/reduced.data.0.json @@ -0,0 +1 @@ +{"std": 6295.5250434859099, "min": -6419.0146484375, "max": 55403.9853515625, "shape": [13280], "masked": false, "mean": 2446.3044780685241} \ No newline at end of file diff --git a/lib/iris/tests/results/integration/grib2/TestGDT40/regular.cml b/lib/iris/tests/results/integration/grib2/TestGDT40/regular.cml new file mode 100644 index 0000000000..fb6445b8b1 --- /dev/null +++ b/lib/iris/tests/results/integration/grib2/TestGDT40/regular.cml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/integration/grib2/TestGDT40/regular.data.0.json b/lib/iris/tests/results/integration/grib2/TestGDT40/regular.data.0.json new file mode 100644 index 0000000000..9595f90e89 --- /dev/null +++ b/lib/iris/tests/results/integration/grib2/TestGDT40/regular.data.0.json @@ -0,0 +1 @@ +{"std": 290.49181302067751, "min": 4388.16162109375, "max": 5576.53662109375, "shape": [96, 192], "masked": false, "mean": 5210.564598931207} \ No newline at end of file diff --git a/lib/iris/tests/results/integration/grib2/TestImport/gdt1.cml b/lib/iris/tests/results/integration/grib2/TestImport/gdt1.cml new file mode 100644 index 0000000000..d3cc6b4732 --- /dev/null +++ b/lib/iris/tests/results/integration/grib2/TestImport/gdt1.cml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/integration/grib2/TestImport/gdt1.data.0.json b/lib/iris/tests/results/integration/grib2/TestImport/gdt1.data.0.json new file mode 100644 index 0000000000..2b416f6a93 --- /dev/null +++ b/lib/iris/tests/results/integration/grib2/TestImport/gdt1.data.0.json @@ -0,0 +1 @@ +{"std": 6.1629553729365423, "min": 266.625, "max": 302.25, "shape": [360, 600], "masked": false, "mean": 284.43164236111113} \ No newline at end of file diff --git a/lib/iris/tests/results/integration/grib2/TestImport/gdt90_with_bitmap.cml b/lib/iris/tests/results/integration/grib2/TestImport/gdt90_with_bitmap.cml new file mode 100644 index 0000000000..deb9774b3f --- /dev/null +++ b/lib/iris/tests/results/integration/grib2/TestImport/gdt90_with_bitmap.cml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/integration/grib2/TestImport/gdt90_with_bitmap.data.0.json b/lib/iris/tests/results/integration/grib2/TestImport/gdt90_with_bitmap.data.0.json new file mode 100644 index 0000000000..08c3cb82cb --- /dev/null +++ b/lib/iris/tests/results/integration/grib2/TestImport/gdt90_with_bitmap.data.0.json @@ -0,0 +1 @@ +{"std": 13.780125280995835, "min": 208.90541992187502, "max": 287.25541992187499, "shape": [227, 390], "masked": true, "mean": 266.3984425053925} \ No newline at end of file diff --git a/lib/iris/tests/results/integration/name_grib/NAMEII/0_TRACER_AIR_CONCENTRATION.cml b/lib/iris/tests/results/integration/name_grib/NAMEII/0_TRACER_AIR_CONCENTRATION.cml index d22849c848..4d0fddbba5 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEII/0_TRACER_AIR_CONCENTRATION.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEII/0_TRACER_AIR_CONCENTRATION.cml @@ -1,30 +1,27 @@ - + - + - + - + - - - - - + @@ -32,6 +29,6 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEII/1_TRACER_DOSAGE.cml b/lib/iris/tests/results/integration/name_grib/NAMEII/1_TRACER_DOSAGE.cml index 2d8e82d851..fd61a67eb6 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEII/1_TRACER_DOSAGE.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEII/1_TRACER_DOSAGE.cml @@ -1,30 +1,27 @@ - + - + - + - + - - - - - + @@ -32,6 +29,6 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEII/2_TRACER_WET_DEPOSITION.cml b/lib/iris/tests/results/integration/name_grib/NAMEII/2_TRACER_WET_DEPOSITION.cml index 423187cb99..029aa022ea 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEII/2_TRACER_WET_DEPOSITION.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEII/2_TRACER_WET_DEPOSITION.cml @@ -3,25 +3,22 @@ - + - - - - - - + @@ -29,6 +26,6 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEII/3_TRACER_DRY_DEPOSITION.cml b/lib/iris/tests/results/integration/name_grib/NAMEII/3_TRACER_DRY_DEPOSITION.cml index cee8abe600..429d9db2ff 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEII/3_TRACER_DRY_DEPOSITION.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEII/3_TRACER_DRY_DEPOSITION.cml @@ -1,27 +1,24 @@ - + - + - + - - - - - + @@ -29,6 +26,6 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEII/4_TRACER_TOTAL_DEPOSITION.cml b/lib/iris/tests/results/integration/name_grib/NAMEII/4_TRACER_TOTAL_DEPOSITION.cml index cee8abe600..429d9db2ff 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEII/4_TRACER_TOTAL_DEPOSITION.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEII/4_TRACER_TOTAL_DEPOSITION.cml @@ -1,27 +1,24 @@ - + - + - + - - - - - + @@ -29,6 +26,6 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEIII/0_TRACER_AIR_CONCENTRATION.cml b/lib/iris/tests/results/integration/name_grib/NAMEIII/0_TRACER_AIR_CONCENTRATION.cml index 2c3d172fc5..8412a4f814 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEIII/0_TRACER_AIR_CONCENTRATION.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEIII/0_TRACER_AIR_CONCENTRATION.cml @@ -1,27 +1,24 @@ - + - + - + - - - - - + @@ -29,6 +26,6 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEIII/1_TRACER_AIR_CONCENTRATION.cml b/lib/iris/tests/results/integration/name_grib/NAMEIII/1_TRACER_AIR_CONCENTRATION.cml index 4bf5fe0082..590e8ef463 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEIII/1_TRACER_AIR_CONCENTRATION.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEIII/1_TRACER_AIR_CONCENTRATION.cml @@ -1,27 +1,24 @@ - + - + - + - - - - - + @@ -29,6 +26,6 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEIII/2_TRACER_DRY_DEPOSITION.cml b/lib/iris/tests/results/integration/name_grib/NAMEIII/2_TRACER_DRY_DEPOSITION.cml index 506afe52b3..d3edb03a56 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEIII/2_TRACER_DRY_DEPOSITION.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEIII/2_TRACER_DRY_DEPOSITION.cml @@ -1,27 +1,24 @@ - + - + - + - - - - - + @@ -29,6 +26,6 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEIII/3_TRACER_WET_DEPOSITION.cml b/lib/iris/tests/results/integration/name_grib/NAMEIII/3_TRACER_WET_DEPOSITION.cml index 78e1166be2..3e8d62ef3d 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEIII/3_TRACER_WET_DEPOSITION.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEIII/3_TRACER_WET_DEPOSITION.cml @@ -1,27 +1,24 @@ - + - + - + - - - - - + @@ -29,6 +26,6 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEIII/4_TRACER_DEPOSITION.cml b/lib/iris/tests/results/integration/name_grib/NAMEIII/4_TRACER_DEPOSITION.cml index 5d71c6929f..586aaa6b56 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEIII/4_TRACER_DEPOSITION.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEIII/4_TRACER_DEPOSITION.cml @@ -1,27 +1,24 @@ - + - + - + - - - - - + @@ -29,6 +26,6 @@ - + diff --git a/lib/iris/tests/results/integration/netcdf/TestHybridPressure/save.cdl b/lib/iris/tests/results/integration/netcdf/TestHybridPressure/save.cdl new file mode 100644 index 0000000000..7cf343549d --- /dev/null +++ b/lib/iris/tests/results/integration/netcdf/TestHybridPressure/save.cdl @@ -0,0 +1,66 @@ +dimensions: + bnds = 2 ; + grid_latitude = 100 ; + grid_longitude = 100 ; + model_level_number = 70 ; + time = 6 ; +variables: + float air_potential_temperature(time, model_level_number, grid_latitude, grid_longitude) ; + air_potential_temperature:standard_name = "air_potential_temperature" ; + air_potential_temperature:units = "K" ; + air_potential_temperature:grid_mapping = "rotated_latitude_longitude" ; + air_potential_temperature:coordinates = "forecast_period level_pressure sigma surface_air_pressure" ; + int rotated_latitude_longitude ; + rotated_latitude_longitude:grid_mapping_name = "rotated_latitude_longitude" ; + rotated_latitude_longitude:longitude_of_prime_meridian = 0. ; + rotated_latitude_longitude:earth_radius = 6371229. ; + rotated_latitude_longitude:grid_north_pole_latitude = 37.5 ; + rotated_latitude_longitude:grid_north_pole_longitude = 177.5 ; + rotated_latitude_longitude:north_pole_grid_longitude = 0. ; + double time(time) ; + time:axis = "T" ; + time:units = "hours since 1970-01-01 00:00:00" ; + time:standard_name = "time" ; + time:calendar = "gregorian" ; + int model_level_number(model_level_number) ; + model_level_number:axis = "Z" ; + model_level_number:units = "1" ; + model_level_number:standard_name = "model_level_number" ; + model_level_number:positive = "up" ; + float grid_latitude(grid_latitude) ; + grid_latitude:axis = "Y" ; + grid_latitude:bounds = "grid_latitude_bnds" ; + grid_latitude:units = "degrees" ; + grid_latitude:standard_name = "grid_latitude" ; + float grid_latitude_bnds(grid_latitude, bnds) ; + float grid_longitude(grid_longitude) ; + grid_longitude:axis = "X" ; + grid_longitude:bounds = "grid_longitude_bnds" ; + grid_longitude:units = "degrees" ; + grid_longitude:standard_name = "grid_longitude" ; + float grid_longitude_bnds(grid_longitude, bnds) ; + double forecast_period ; + forecast_period:units = "hours" ; + forecast_period:standard_name = "forecast_period" ; + float level_pressure(model_level_number) ; + level_pressure:bounds = "level_pressure_bnds" ; + level_pressure:units = "Pa" ; + level_pressure:long_name = "level_pressure" ; + level_pressure:positive = "up" ; + level_pressure:standard_name = "atmosphere_hybrid_sigma_pressure_coordinate" ; + level_pressure:axis = "Z" ; + level_pressure:formula_terms = "ap: level_pressure b: sigma ps: surface_air_pressure" ; + float level_pressure_bnds(model_level_number, bnds) ; + float sigma(model_level_number) ; + sigma:bounds = "sigma_bnds" ; + sigma:units = "1" ; + sigma:long_name = "sigma" ; + float sigma_bnds(model_level_number, bnds) ; + float surface_air_pressure(grid_latitude, grid_longitude) ; + surface_air_pressure:units = "Pa" ; + surface_air_pressure:standard_name = "surface_air_pressure" ; + +// global attributes: + :source = "Iris test case" ; + :Conventions = "CF-1.5" ; +} diff --git a/lib/iris/tests/results/integration/netcdf/TestPackedData/multi_packed_multi_dtype.cdl b/lib/iris/tests/results/integration/netcdf/TestPackedData/multi_packed_multi_dtype.cdl new file mode 100644 index 0000000000..287cbe5358 --- /dev/null +++ b/lib/iris/tests/results/integration/netcdf/TestPackedData/multi_packed_multi_dtype.cdl @@ -0,0 +1,68 @@ +dimensions: + bnds = 2 ; + latitude = 73 ; + longitude = 96 ; + time = 360 ; +variables: + short air_temperature(time, latitude, longitude) ; + air_temperature:scale_factor = 0.0024257504786326 ; + air_temperature:add_offset = 261.648002426021 ; + air_temperature:standard_name = "air_temperature" ; + air_temperature:units = "K" ; + air_temperature:um_stash_source = "m01s03i236" ; + air_temperature:cell_methods = "time: maximum (interval: 1 hour)" ; + air_temperature:grid_mapping = "latitude_longitude" ; + air_temperature:coordinates = "forecast_period forecast_reference_time height" ; + int latitude_longitude ; + latitude_longitude:grid_mapping_name = "latitude_longitude" ; + latitude_longitude:longitude_of_prime_meridian = 0. ; + latitude_longitude:earth_radius = 6371229. ; + double time(time) ; + time:axis = "T" ; + time:bounds = "time_bnds" ; + time:units = "hours since 1970-01-01 00:00:00" ; + time:standard_name = "time" ; + time:calendar = "360_day" ; + double time_bnds(time, bnds) ; + float latitude(latitude) ; + latitude:axis = "Y" ; + latitude:units = "degrees_north" ; + latitude:standard_name = "latitude" ; + float longitude(longitude) ; + longitude:axis = "X" ; + longitude:units = "degrees_east" ; + longitude:standard_name = "longitude" ; + double forecast_period(time) ; + forecast_period:bounds = "forecast_period_bnds" ; + forecast_period:units = "hours" ; + forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(time, bnds) ; + double forecast_reference_time ; + forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; + forecast_reference_time:standard_name = "forecast_reference_time" ; + forecast_reference_time:calendar = "360_day" ; + double height ; + height:units = "m" ; + height:standard_name = "height" ; + height:positive = "up" ; + float precipitation_flux(time, latitude, longitude) ; + precipitation_flux:standard_name = "precipitation_flux" ; + precipitation_flux:units = "kg m-2 s-1" ; + precipitation_flux:um_stash_source = "m01s05i216" ; + precipitation_flux:cell_methods = "time: mean (interval: 1 hour)" ; + precipitation_flux:grid_mapping = "latitude_longitude" ; + precipitation_flux:coordinates = "forecast_period forecast_reference_time" ; + ushort air_temperature_0(time, latitude, longitude) ; + air_temperature_0:scale_factor = 0.0020141666756075 ; + air_temperature_0:add_offset = 176.7872f ; + air_temperature_0:standard_name = "air_temperature" ; + air_temperature_0:units = "K" ; + air_temperature_0:um_stash_source = "m01s03i236" ; + air_temperature_0:cell_methods = "time: minimum (interval: 1 hour)" ; + air_temperature_0:grid_mapping = "latitude_longitude" ; + air_temperature_0:coordinates = "forecast_period forecast_reference_time height" ; + +// global attributes: + :source = "Data from Met Office Unified Model" ; + :Conventions = "CF-1.5" ; +} diff --git a/lib/iris/tests/results/integration/netcdf/TestPackedData/multi_packed_single_dtype.cdl b/lib/iris/tests/results/integration/netcdf/TestPackedData/multi_packed_single_dtype.cdl new file mode 100644 index 0000000000..d498520f70 --- /dev/null +++ b/lib/iris/tests/results/integration/netcdf/TestPackedData/multi_packed_single_dtype.cdl @@ -0,0 +1,70 @@ +dimensions: + bnds = 2 ; + latitude = 73 ; + longitude = 96 ; + time = 360 ; +variables: + short air_temperature(time, latitude, longitude) ; + air_temperature:scale_factor = 0.0024257504786326 ; + air_temperature:add_offset = 261.648002426021 ; + air_temperature:standard_name = "air_temperature" ; + air_temperature:units = "K" ; + air_temperature:um_stash_source = "m01s03i236" ; + air_temperature:cell_methods = "time: maximum (interval: 1 hour)" ; + air_temperature:grid_mapping = "latitude_longitude" ; + air_temperature:coordinates = "forecast_period forecast_reference_time height" ; + int latitude_longitude ; + latitude_longitude:grid_mapping_name = "latitude_longitude" ; + latitude_longitude:longitude_of_prime_meridian = 0. ; + latitude_longitude:earth_radius = 6371229. ; + double time(time) ; + time:axis = "T" ; + time:bounds = "time_bnds" ; + time:units = "hours since 1970-01-01 00:00:00" ; + time:standard_name = "time" ; + time:calendar = "360_day" ; + double time_bnds(time, bnds) ; + float latitude(latitude) ; + latitude:axis = "Y" ; + latitude:units = "degrees_north" ; + latitude:standard_name = "latitude" ; + float longitude(longitude) ; + longitude:axis = "X" ; + longitude:units = "degrees_east" ; + longitude:standard_name = "longitude" ; + double forecast_period(time) ; + forecast_period:bounds = "forecast_period_bnds" ; + forecast_period:units = "hours" ; + forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(time, bnds) ; + double forecast_reference_time ; + forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; + forecast_reference_time:standard_name = "forecast_reference_time" ; + forecast_reference_time:calendar = "360_day" ; + double height ; + height:units = "m" ; + height:standard_name = "height" ; + height:positive = "up" ; + short precipitation_flux(time, latitude, longitude) ; + precipitation_flux:scale_factor = 2.9897383798121e-08 ; + precipitation_flux:add_offset = 0.000979677472296829 ; + precipitation_flux:standard_name = "precipitation_flux" ; + precipitation_flux:units = "kg m-2 s-1" ; + precipitation_flux:um_stash_source = "m01s05i216" ; + precipitation_flux:cell_methods = "time: mean (interval: 1 hour)" ; + precipitation_flux:grid_mapping = "latitude_longitude" ; + precipitation_flux:coordinates = "forecast_period forecast_reference_time" ; + short air_temperature_0(time, latitude, longitude) ; + air_temperature_0:scale_factor = 0.0020141666756075 ; + air_temperature_0:add_offset = 242.787445071619 ; + air_temperature_0:standard_name = "air_temperature" ; + air_temperature_0:units = "K" ; + air_temperature_0:um_stash_source = "m01s03i236" ; + air_temperature_0:cell_methods = "time: minimum (interval: 1 hour)" ; + air_temperature_0:grid_mapping = "latitude_longitude" ; + air_temperature_0:coordinates = "forecast_period forecast_reference_time height" ; + +// global attributes: + :source = "Data from Met Office Unified Model" ; + :Conventions = "CF-1.5" ; +} diff --git a/lib/iris/tests/results/integration/netcdf/TestPackedData/single_packed_manual.cdl b/lib/iris/tests/results/integration/netcdf/TestPackedData/single_packed_manual.cdl new file mode 100644 index 0000000000..34446083e2 --- /dev/null +++ b/lib/iris/tests/results/integration/netcdf/TestPackedData/single_packed_manual.cdl @@ -0,0 +1,50 @@ +dimensions: + bnds = 2 ; + latitude = 73 ; + longitude = 96 ; +variables: + short air_temperature(latitude, longitude) ; + air_temperature:scale_factor = 0.00119806791576066 ; + air_temperature:add_offset = 267.40062344802 ; + air_temperature:standard_name = "air_temperature" ; + air_temperature:units = "K" ; + air_temperature:um_stash_source = "m01s03i236" ; + air_temperature:cell_methods = "time: mean (interval: 6 hour)" ; + air_temperature:grid_mapping = "latitude_longitude" ; + air_temperature:coordinates = "forecast_period forecast_reference_time height time" ; + int latitude_longitude ; + latitude_longitude:grid_mapping_name = "latitude_longitude" ; + latitude_longitude:longitude_of_prime_meridian = 0. ; + latitude_longitude:earth_radius = 6371229. ; + float latitude(latitude) ; + latitude:axis = "Y" ; + latitude:units = "degrees_north" ; + latitude:standard_name = "latitude" ; + float longitude(longitude) ; + longitude:axis = "X" ; + longitude:units = "degrees_east" ; + longitude:standard_name = "longitude" ; + double forecast_period ; + forecast_period:bounds = "forecast_period_bnds" ; + forecast_period:units = "hours" ; + forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(bnds) ; + double forecast_reference_time ; + forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; + forecast_reference_time:standard_name = "forecast_reference_time" ; + forecast_reference_time:calendar = "gregorian" ; + double height ; + height:units = "m" ; + height:standard_name = "height" ; + height:positive = "up" ; + double time ; + time:bounds = "time_bnds" ; + time:units = "hours since 1970-01-01 00:00:00" ; + time:standard_name = "time" ; + time:calendar = "gregorian" ; + double time_bnds(bnds) ; + +// global attributes: + :source = "Data from Met Office Unified Model" ; + :Conventions = "CF-1.5" ; +} diff --git a/lib/iris/tests/results/integration/netcdf/TestPackedData/single_packed_signed.cdl b/lib/iris/tests/results/integration/netcdf/TestPackedData/single_packed_signed.cdl new file mode 100644 index 0000000000..34446083e2 --- /dev/null +++ b/lib/iris/tests/results/integration/netcdf/TestPackedData/single_packed_signed.cdl @@ -0,0 +1,50 @@ +dimensions: + bnds = 2 ; + latitude = 73 ; + longitude = 96 ; +variables: + short air_temperature(latitude, longitude) ; + air_temperature:scale_factor = 0.00119806791576066 ; + air_temperature:add_offset = 267.40062344802 ; + air_temperature:standard_name = "air_temperature" ; + air_temperature:units = "K" ; + air_temperature:um_stash_source = "m01s03i236" ; + air_temperature:cell_methods = "time: mean (interval: 6 hour)" ; + air_temperature:grid_mapping = "latitude_longitude" ; + air_temperature:coordinates = "forecast_period forecast_reference_time height time" ; + int latitude_longitude ; + latitude_longitude:grid_mapping_name = "latitude_longitude" ; + latitude_longitude:longitude_of_prime_meridian = 0. ; + latitude_longitude:earth_radius = 6371229. ; + float latitude(latitude) ; + latitude:axis = "Y" ; + latitude:units = "degrees_north" ; + latitude:standard_name = "latitude" ; + float longitude(longitude) ; + longitude:axis = "X" ; + longitude:units = "degrees_east" ; + longitude:standard_name = "longitude" ; + double forecast_period ; + forecast_period:bounds = "forecast_period_bnds" ; + forecast_period:units = "hours" ; + forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(bnds) ; + double forecast_reference_time ; + forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; + forecast_reference_time:standard_name = "forecast_reference_time" ; + forecast_reference_time:calendar = "gregorian" ; + double height ; + height:units = "m" ; + height:standard_name = "height" ; + height:positive = "up" ; + double time ; + time:bounds = "time_bnds" ; + time:units = "hours since 1970-01-01 00:00:00" ; + time:standard_name = "time" ; + time:calendar = "gregorian" ; + double time_bnds(bnds) ; + +// global attributes: + :source = "Data from Met Office Unified Model" ; + :Conventions = "CF-1.5" ; +} diff --git a/lib/iris/tests/results/integration/netcdf/TestPackedData/single_packed_unsigned.cdl b/lib/iris/tests/results/integration/netcdf/TestPackedData/single_packed_unsigned.cdl new file mode 100644 index 0000000000..43037a36c5 --- /dev/null +++ b/lib/iris/tests/results/integration/netcdf/TestPackedData/single_packed_unsigned.cdl @@ -0,0 +1,50 @@ +dimensions: + bnds = 2 ; + latitude = 73 ; + longitude = 96 ; +variables: + ubyte air_temperature(latitude, longitude) ; + air_temperature:scale_factor = 0.30790345435049 ; + air_temperature:add_offset = 228.1423f ; + air_temperature:standard_name = "air_temperature" ; + air_temperature:units = "K" ; + air_temperature:um_stash_source = "m01s03i236" ; + air_temperature:cell_methods = "time: mean (interval: 6 hour)" ; + air_temperature:grid_mapping = "latitude_longitude" ; + air_temperature:coordinates = "forecast_period forecast_reference_time height time" ; + int latitude_longitude ; + latitude_longitude:grid_mapping_name = "latitude_longitude" ; + latitude_longitude:longitude_of_prime_meridian = 0. ; + latitude_longitude:earth_radius = 6371229. ; + float latitude(latitude) ; + latitude:axis = "Y" ; + latitude:units = "degrees_north" ; + latitude:standard_name = "latitude" ; + float longitude(longitude) ; + longitude:axis = "X" ; + longitude:units = "degrees_east" ; + longitude:standard_name = "longitude" ; + double forecast_period ; + forecast_period:bounds = "forecast_period_bnds" ; + forecast_period:units = "hours" ; + forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(bnds) ; + double forecast_reference_time ; + forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; + forecast_reference_time:standard_name = "forecast_reference_time" ; + forecast_reference_time:calendar = "gregorian" ; + double height ; + height:units = "m" ; + height:standard_name = "height" ; + height:positive = "up" ; + double time ; + time:bounds = "time_bnds" ; + time:units = "hours since 1970-01-01 00:00:00" ; + time:standard_name = "time" ; + time:calendar = "gregorian" ; + double time_bnds(bnds) ; + +// global attributes: + :source = "Data from Met Office Unified Model" ; + :Conventions = "CF-1.5" ; +} diff --git a/lib/iris/tests/results/integration/netcdf/TestSaveMultipleAuxFactories/hybrid_height_and_pressure.cdl b/lib/iris/tests/results/integration/netcdf/TestSaveMultipleAuxFactories/hybrid_height_and_pressure.cdl new file mode 100644 index 0000000000..1d680136d2 --- /dev/null +++ b/lib/iris/tests/results/integration/netcdf/TestSaveMultipleAuxFactories/hybrid_height_and_pressure.cdl @@ -0,0 +1,78 @@ +dimensions: + bnds = 2 ; + grid_latitude = 100 ; + grid_longitude = 100 ; + model_level_number = 70 ; + time = 6 ; +variables: + float air_potential_temperature(time, model_level_number, grid_latitude, grid_longitude) ; + air_potential_temperature:standard_name = "air_potential_temperature" ; + air_potential_temperature:units = "K" ; + air_potential_temperature:grid_mapping = "rotated_latitude_longitude" ; + air_potential_temperature:coordinates = "forecast_period level_height level_pressure sigma surface_air_pressure surface_altitude unknown_scalar" ; + int rotated_latitude_longitude ; + rotated_latitude_longitude:grid_mapping_name = "rotated_latitude_longitude" ; + rotated_latitude_longitude:longitude_of_prime_meridian = 0. ; + rotated_latitude_longitude:earth_radius = 6371229. ; + rotated_latitude_longitude:grid_north_pole_latitude = 37.5 ; + rotated_latitude_longitude:grid_north_pole_longitude = 177.5 ; + rotated_latitude_longitude:north_pole_grid_longitude = 0. ; + double time(time) ; + time:axis = "T" ; + time:units = "hours since 1970-01-01 00:00:00" ; + time:standard_name = "time" ; + time:calendar = "gregorian" ; + int model_level_number(model_level_number) ; + model_level_number:axis = "Z" ; + model_level_number:units = "1" ; + model_level_number:standard_name = "model_level_number" ; + model_level_number:positive = "up" ; + float grid_latitude(grid_latitude) ; + grid_latitude:axis = "Y" ; + grid_latitude:bounds = "grid_latitude_bnds" ; + grid_latitude:units = "degrees" ; + grid_latitude:standard_name = "grid_latitude" ; + float grid_latitude_bnds(grid_latitude, bnds) ; + float grid_longitude(grid_longitude) ; + grid_longitude:axis = "X" ; + grid_longitude:bounds = "grid_longitude_bnds" ; + grid_longitude:units = "degrees" ; + grid_longitude:standard_name = "grid_longitude" ; + float grid_longitude_bnds(grid_longitude, bnds) ; + double forecast_period ; + forecast_period:units = "hours" ; + forecast_period:standard_name = "forecast_period" ; + float level_height(model_level_number) ; + level_height:bounds = "level_height_bnds" ; + level_height:units = "m" ; + level_height:long_name = "level_height" ; + level_height:positive = "up" ; + level_height:standard_name = "atmosphere_hybrid_height_coordinate" ; + level_height:axis = "Z" ; + level_height:formula_terms = "a: level_height b: sigma orog: surface_altitude" ; + float level_height_bnds(model_level_number, bnds) ; + double level_pressure ; + level_pressure:units = "hPa" ; + level_pressure:long_name = "level_pressure" ; + level_pressure:standard_name = "atmosphere_hybrid_sigma_pressure_coordinate" ; + level_pressure:axis = "Z" ; + level_pressure:formula_terms = "ap: level_pressure b: unknown_scalar ps: surface_air_pressure" ; + double unknown_scalar ; + unknown_scalar:units = "1" ; + unknown_scalar:long_name = "other sigma" ; + float sigma(model_level_number) ; + sigma:bounds = "sigma_bnds" ; + sigma:units = "1" ; + sigma:long_name = "sigma" ; + float sigma_bnds(model_level_number, bnds) ; + double surface_air_pressure ; + surface_air_pressure:units = "hPa" ; + surface_air_pressure:long_name = "surface_air_pressure" ; + float surface_altitude(grid_latitude, grid_longitude) ; + surface_altitude:units = "m" ; + surface_altitude:standard_name = "surface_altitude" ; + +// global attributes: + :source = "Iris test case" ; + :Conventions = "CF-1.5" ; +} diff --git a/lib/iris/tests/results/integration/netcdf/TestSaveMultipleAuxFactories/hybrid_height_cubes.cml b/lib/iris/tests/results/integration/netcdf/TestSaveMultipleAuxFactories/hybrid_height_cubes.cml new file mode 100644 index 0000000000..a6bf903419 --- /dev/null +++ b/lib/iris/tests/results/integration/netcdf/TestSaveMultipleAuxFactories/hybrid_height_cubes.cml @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/integration/netcdf/TestUmVersionAttribute/multiple_different_saves_on_variables.cdl b/lib/iris/tests/results/integration/netcdf/TestUmVersionAttribute/multiple_different_saves_on_variables.cdl new file mode 100644 index 0000000000..a7a9538dfd --- /dev/null +++ b/lib/iris/tests/results/integration/netcdf/TestUmVersionAttribute/multiple_different_saves_on_variables.cdl @@ -0,0 +1,15 @@ +dimensions: + dim0 = 1 ; +variables: + double air_temperature(dim0) ; + air_temperature:standard_name = "air_temperature" ; + air_temperature:units = "K" ; + air_temperature:um_version = "4.3" ; + double air_pressure(dim0) ; + air_pressure:standard_name = "air_pressure" ; + air_pressure:units = "hPa" ; + air_pressure:um_version = "4.4" ; + +// global attributes: + :Conventions = "CF-1.5" ; +} diff --git a/lib/iris/tests/results/integration/netcdf/TestUmVersionAttribute/multiple_same_saves_as_global.cdl b/lib/iris/tests/results/integration/netcdf/TestUmVersionAttribute/multiple_same_saves_as_global.cdl new file mode 100644 index 0000000000..59c94491bd --- /dev/null +++ b/lib/iris/tests/results/integration/netcdf/TestUmVersionAttribute/multiple_same_saves_as_global.cdl @@ -0,0 +1,14 @@ +dimensions: + dim0 = 1 ; +variables: + double air_temperature(dim0) ; + air_temperature:standard_name = "air_temperature" ; + air_temperature:units = "K" ; + double air_pressure(dim0) ; + air_pressure:standard_name = "air_pressure" ; + air_pressure:units = "hPa" ; + +// global attributes: + :um_version = "4.3" ; + :Conventions = "CF-1.5" ; +} diff --git a/lib/iris/tests/results/integration/netcdf/TestUmVersionAttribute/single_saves_as_global.cdl b/lib/iris/tests/results/integration/netcdf/TestUmVersionAttribute/single_saves_as_global.cdl new file mode 100644 index 0000000000..671c9d03e3 --- /dev/null +++ b/lib/iris/tests/results/integration/netcdf/TestUmVersionAttribute/single_saves_as_global.cdl @@ -0,0 +1,11 @@ +dimensions: + dim0 = 1 ; +variables: + double air_temperature(dim0) ; + air_temperature:standard_name = "air_temperature" ; + air_temperature:units = "K" ; + +// global attributes: + :um_version = "4.3" ; + :Conventions = "CF-1.5" ; +} diff --git a/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadFF/simple.cml b/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadFF/simple.cml new file mode 100644 index 0000000000..bac3f9b503 --- /dev/null +++ b/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadFF/simple.cml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadFF/simple_callback.cml b/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadFF/simple_callback.cml new file mode 100644 index 0000000000..971f76d618 --- /dev/null +++ b/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadFF/simple_callback.cml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadPP/simple.cml b/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadPP/simple.cml new file mode 100644 index 0000000000..4da5286d78 --- /dev/null +++ b/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadPP/simple.cml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadPP/simple_callback.cml b/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadPP/simple_callback.cml new file mode 100644 index 0000000000..1614dad71a --- /dev/null +++ b/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadPP/simple_callback.cml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/iterate/izip_nd_ortho.cml b/lib/iris/tests/results/iterate/izip_nd_ortho.cml index b5154ea47e..1b8fded247 100644 --- a/lib/iris/tests/results/iterate/izip_nd_ortho.cml +++ b/lib/iris/tests/results/iterate/izip_nd_ortho.cml @@ -1,233 +1,233 @@ - + - - - + - + - + - - - + - + - + - - - + - + - + - - - + - + - + - - - + - + - + - - - + - + - + - - - + - + - + - - - + - + - + - - - + - + - + - - - + - + diff --git a/lib/iris/tests/results/merge/a_aux_b_aux.cml b/lib/iris/tests/results/merge/a_aux_b_aux.cml index 06a2a9b2e0..88af58cbe7 100644 --- a/lib/iris/tests/results/merge/a_aux_b_aux.cml +++ b/lib/iris/tests/results/merge/a_aux_b_aux.cml @@ -1,21 +1,21 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/merge/a_aux_b_dim.cml b/lib/iris/tests/results/merge/a_aux_b_dim.cml index 06a2a9b2e0..88af58cbe7 100644 --- a/lib/iris/tests/results/merge/a_aux_b_dim.cml +++ b/lib/iris/tests/results/merge/a_aux_b_dim.cml @@ -1,21 +1,21 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/merge/a_dim_b_aux.cml b/lib/iris/tests/results/merge/a_dim_b_aux.cml index 06a2a9b2e0..88af58cbe7 100644 --- a/lib/iris/tests/results/merge/a_dim_b_aux.cml +++ b/lib/iris/tests/results/merge/a_dim_b_aux.cml @@ -1,21 +1,21 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/merge/a_dim_b_dim.cml b/lib/iris/tests/results/merge/a_dim_b_dim.cml index 06a2a9b2e0..88af58cbe7 100644 --- a/lib/iris/tests/results/merge/a_dim_b_dim.cml +++ b/lib/iris/tests/results/merge/a_dim_b_dim.cml @@ -1,21 +1,21 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/merge/dec.cml b/lib/iris/tests/results/merge/dec.cml index 915805c885..ea72b506f0 100644 --- a/lib/iris/tests/results/merge/dec.cml +++ b/lib/iris/tests/results/merge/dec.cml @@ -1,19 +1,20 @@ - + - + + - + - + - + @@ -55,7 +56,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -68,12 +69,12 @@ - + - @@ -119,7 +120,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -129,7 +130,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -137,22 +138,23 @@ - + - + - + + - + - + - + @@ -194,7 +196,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -207,12 +209,12 @@ - + - @@ -258,7 +260,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -268,7 +270,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -276,22 +278,23 @@ - + - + - + + - + - + - + @@ -333,7 +336,7 @@ [24458.3, 26583.6], [26583.6, 29219.1], [29219.1, 32908.7], - [32908.7, 39254.8]]" id="218bea13" long_name="level_height" points="[9.99821, 49.9989, 130.0, 249.998, 410.001, + [32908.7, 39254.8]]" id="fb105c19" long_name="level_height" points="[9.99821, 49.9989, 130.0, 249.998, 410.001, 610.0, 850.001, 1130.0, 1450.0, 1810.0, 2210.0, 2650.0, 3130.0, 3650.0, 4210.0, 4810.0, 5450.0, 6130.0, 6850.0, 7610.0, 8410.0, 9250.0, 10130.0, @@ -346,13 +349,13 @@ - - @@ -398,7 +401,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.998858, 0.994296, 0.985204, 0.971644, 0.95371, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.998858, 0.994296, 0.985204, 0.971644, 0.95371, 0.931527, 0.905253, 0.875075, 0.841212, 0.803914, 0.763465, 0.720176, 0.674393, 0.626491, 0.576877, 0.525991, 0.474301, 0.42231, @@ -408,7 +411,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -416,22 +419,23 @@ - + - + - + + - + - + - @@ -474,7 +478,7 @@ [24458.3, 26583.6], [26583.6, 29219.1], [29219.1, 32908.7], - [32908.7, 39254.8]]" id="218bea13" long_name="level_height" points="[9.99821, 49.9989, 130.0, 249.998, 410.001, + [32908.7, 39254.8]]" id="fb105c19" long_name="level_height" points="[9.99821, 49.9989, 130.0, 249.998, 410.001, 610.0, 850.001, 1130.0, 1450.0, 1810.0, 2210.0, 2650.0, 3130.0, 3650.0, 4210.0, 4810.0, 5450.0, 6130.0, 6850.0, 7610.0, 8410.0, 9250.0, 10130.0, @@ -487,12 +491,12 @@ - + - @@ -538,7 +542,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.998858, 0.994296, 0.985204, 0.971644, 0.95371, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.998858, 0.994296, 0.985204, 0.971644, 0.95371, 0.931527, 0.905253, 0.875075, 0.841212, 0.803914, 0.763465, 0.720176, 0.674393, 0.626491, 0.576877, 0.525991, 0.474301, 0.42231, @@ -548,7 +552,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -556,6 +560,6 @@ - + diff --git a/lib/iris/tests/results/merge/multi_split.cml b/lib/iris/tests/results/merge/multi_split.cml index 80c81da9f3..1ee69d6723 100644 --- a/lib/iris/tests/results/merge/multi_split.cml +++ b/lib/iris/tests/results/merge/multi_split.cml @@ -1,24 +1,24 @@ - + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/merge/separable_combination.cml b/lib/iris/tests/results/merge/separable_combination.cml index 078040eff5..25802c8228 100644 --- a/lib/iris/tests/results/merge/separable_combination.cml +++ b/lib/iris/tests/results/merge/separable_combination.cml @@ -1,14 +1,14 @@ - + - - - - - + - + - + diff --git a/lib/iris/tests/results/merge/single_split.cml b/lib/iris/tests/results/merge/single_split.cml index 6de9bdd499..fffe59fe02 100644 --- a/lib/iris/tests/results/merge/single_split.cml +++ b/lib/iris/tests/results/merge/single_split.cml @@ -1,26 +1,26 @@ - + - + - + - - + - + - + diff --git a/lib/iris/tests/results/merge/string_a_b.cml b/lib/iris/tests/results/merge/string_a_b.cml index 3ecdcea428..48b46979c1 100644 --- a/lib/iris/tests/results/merge/string_a_b.cml +++ b/lib/iris/tests/results/merge/string_a_b.cml @@ -1,21 +1,21 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/merge/string_a_with_aux.cml b/lib/iris/tests/results/merge/string_a_with_aux.cml index 22b0668ba5..1f41f23aad 100644 --- a/lib/iris/tests/results/merge/string_a_with_aux.cml +++ b/lib/iris/tests/results/merge/string_a_with_aux.cml @@ -1,21 +1,21 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/merge/string_a_with_dim.cml b/lib/iris/tests/results/merge/string_a_with_dim.cml index 22b0668ba5..1f41f23aad 100644 --- a/lib/iris/tests/results/merge/string_a_with_dim.cml +++ b/lib/iris/tests/results/merge/string_a_with_dim.cml @@ -1,21 +1,21 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/merge/string_b_with_dim.cml b/lib/iris/tests/results/merge/string_b_with_dim.cml index 5c3ba09002..8710767c41 100644 --- a/lib/iris/tests/results/merge/string_b_with_dim.cml +++ b/lib/iris/tests/results/merge/string_b_with_dim.cml @@ -1,21 +1,21 @@ - + - + - + - + - + - + diff --git a/lib/iris/tests/results/merge/theta.cml b/lib/iris/tests/results/merge/theta.cml index 818c3d9846..293e40cc3a 100644 --- a/lib/iris/tests/results/merge/theta.cml +++ b/lib/iris/tests/results/merge/theta.cml @@ -1,19 +1,20 @@ - + - + + - + - + - + @@ -55,7 +56,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -68,12 +69,12 @@ - + - @@ -119,7 +120,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -129,7 +130,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -137,6 +138,6 @@ - + diff --git a/lib/iris/tests/results/merge/theta_two_times.cml b/lib/iris/tests/results/merge/theta_two_times.cml index 57a81afc05..0dd396e337 100644 --- a/lib/iris/tests/results/merge/theta_two_times.cml +++ b/lib/iris/tests/results/merge/theta_two_times.cml @@ -1,404 +1,405 @@ - + - + + + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + ..., + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0]]]" shape="(70, 100, 100)" standard_name="altitude" units="Unit('m')" value_type="float32"> - + - + @@ -419,7 +420,7 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> @@ -431,7 +432,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -451,7 +452,7 @@ - - + 300.34]]" shape="(100, 100)" standard_name="surface_altitude" units="Unit('m')" value_type="float32"> - + + - + - + diff --git a/lib/iris/tests/results/merge/time_triple_duplicate_data.cml b/lib/iris/tests/results/merge/time_triple_duplicate_data.cml index f480490df1..67f091ccc6 100644 --- a/lib/iris/tests/results/merge/time_triple_duplicate_data.cml +++ b/lib/iris/tests/results/merge/time_triple_duplicate_data.cml @@ -1,45 +1,45 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/merge/time_triple_independent.cml b/lib/iris/tests/results/merge/time_triple_independent.cml index 484b92b921..1e7d9ef400 100644 --- a/lib/iris/tests/results/merge/time_triple_independent.cml +++ b/lib/iris/tests/results/merge/time_triple_independent.cml @@ -1,24 +1,24 @@ - + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/merge/time_triple_merging1.cml b/lib/iris/tests/results/merge/time_triple_merging1.cml index f23c31d602..6082384c73 100644 --- a/lib/iris/tests/results/merge/time_triple_merging1.cml +++ b/lib/iris/tests/results/merge/time_triple_merging1.cml @@ -1,24 +1,24 @@ - + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/merge/time_triple_merging2.cml b/lib/iris/tests/results/merge/time_triple_merging2.cml index 20cba30128..b838ad569a 100644 --- a/lib/iris/tests/results/merge/time_triple_merging2.cml +++ b/lib/iris/tests/results/merge/time_triple_merging2.cml @@ -1,25 +1,25 @@ - + - + - + - - + - + - + diff --git a/lib/iris/tests/results/merge/time_triple_merging3.cml b/lib/iris/tests/results/merge/time_triple_merging3.cml index df635a7242..0fb7a25299 100644 --- a/lib/iris/tests/results/merge/time_triple_merging3.cml +++ b/lib/iris/tests/results/merge/time_triple_merging3.cml @@ -1,24 +1,24 @@ - + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/merge/time_triple_merging4.cml b/lib/iris/tests/results/merge/time_triple_merging4.cml index 5667e8d36b..147bf1adf8 100644 --- a/lib/iris/tests/results/merge/time_triple_merging4.cml +++ b/lib/iris/tests/results/merge/time_triple_merging4.cml @@ -1,26 +1,26 @@ - + - + - + - - + - + - + diff --git a/lib/iris/tests/results/merge/time_triple_merging5.cml b/lib/iris/tests/results/merge/time_triple_merging5.cml index 44fd4ef6ee..fa7073e829 100644 --- a/lib/iris/tests/results/merge/time_triple_merging5.cml +++ b/lib/iris/tests/results/merge/time_triple_merging5.cml @@ -1,24 +1,24 @@ - + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/merge/time_triple_non_expanding.cml b/lib/iris/tests/results/merge/time_triple_non_expanding.cml index 4f43ffbb87..c558c8a327 100644 --- a/lib/iris/tests/results/merge/time_triple_non_expanding.cml +++ b/lib/iris/tests/results/merge/time_triple_non_expanding.cml @@ -1,24 +1,24 @@ - + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/merge/time_triple_series.cml b/lib/iris/tests/results/merge/time_triple_series.cml index ca689aad44..02470fa557 100644 --- a/lib/iris/tests/results/merge/time_triple_series.cml +++ b/lib/iris/tests/results/merge/time_triple_series.cml @@ -1,24 +1,24 @@ - + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/merge/time_triple_single_forecast.cml b/lib/iris/tests/results/merge/time_triple_single_forecast.cml index fe1d9910c2..eea9e538a6 100644 --- a/lib/iris/tests/results/merge/time_triple_single_forecast.cml +++ b/lib/iris/tests/results/merge/time_triple_single_forecast.cml @@ -1,24 +1,24 @@ - + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/merge/time_triple_successive_forecasts.cml b/lib/iris/tests/results/merge/time_triple_successive_forecasts.cml index c14c9e2834..ff0d9cdad2 100644 --- a/lib/iris/tests/results/merge/time_triple_successive_forecasts.cml +++ b/lib/iris/tests/results/merge/time_triple_successive_forecasts.cml @@ -1,26 +1,26 @@ - + - + - + - - + - + - + diff --git a/lib/iris/tests/results/merge/time_triple_time_non_dim_coord.cml b/lib/iris/tests/results/merge/time_triple_time_non_dim_coord.cml index cf6a85b88e..b3c2c26d96 100644 --- a/lib/iris/tests/results/merge/time_triple_time_non_dim_coord.cml +++ b/lib/iris/tests/results/merge/time_triple_time_non_dim_coord.cml @@ -1,25 +1,25 @@ - + - + - + + [0, 10]]" id="bc1dc451" points="[2, 5]" shape="(2,)" standard_name="time" units="Unit('1')" value_type="int32"/> - + - + - + diff --git a/lib/iris/tests/results/merge/time_triple_time_vs_forecast.cml b/lib/iris/tests/results/merge/time_triple_time_vs_forecast.cml index d6ba4d96bc..f0d625671f 100644 --- a/lib/iris/tests/results/merge/time_triple_time_vs_forecast.cml +++ b/lib/iris/tests/results/merge/time_triple_time_vs_forecast.cml @@ -1,27 +1,27 @@ - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/merge/time_triple_time_vs_ref_time.cml b/lib/iris/tests/results/merge/time_triple_time_vs_ref_time.cml index a863f7a27f..cef8a71d1f 100644 --- a/lib/iris/tests/results/merge/time_triple_time_vs_ref_time.cml +++ b/lib/iris/tests/results/merge/time_triple_time_vs_ref_time.cml @@ -1,27 +1,27 @@ - + - - + - + - + - + - + diff --git a/lib/iris/tests/results/name/NAMEIII_field.cml b/lib/iris/tests/results/name/NAMEIII_field.cml index 1ce74c1b05..674190f642 100644 --- a/lib/iris/tests/results/name/NAMEIII_field.cml +++ b/lib/iris/tests/results/name/NAMEIII_field.cml @@ -1,6 +1,6 @@ - + @@ -8,8 +8,6 @@ - - @@ -32,7 +30,7 @@ ..., [50.808, 50.809], [50.809, 50.81], - [50.81, 50.811]]" id="a42bcac2" points="[50.6115, 50.6125, 50.6135, ..., 50.8085, + [50.81, 50.811]]" id="77a50eb5" points="[50.6115, 50.6125, 50.6135, ..., 50.8085, 50.8095, 50.8105]" shape="(200,)" standard_name="latitude" units="Unit('degrees')" value_type="float64"> @@ -44,16 +42,16 @@ ..., [-3.3245, -3.3227], [-3.3227, -3.3209], - [-3.3209, -3.3191]]" id="63128986" points="[-3.6782, -3.6764, -3.6746, ..., -3.3236, + [-3.3209, -3.3191]]" id="f913a8b3" points="[-3.6782, -3.6764, -3.6746, ..., -3.3236, -3.3218, -3.32]" shape="(200,)" standard_name="longitude" units="Unit('degrees')" value_type="float64"> - + - + @@ -61,9 +59,9 @@ - + - + @@ -71,8 +69,6 @@ - - @@ -95,7 +91,7 @@ ..., [50.808, 50.809], [50.809, 50.81], - [50.81, 50.811]]" id="a42bcac2" points="[50.6115, 50.6125, 50.6135, ..., 50.8085, + [50.81, 50.811]]" id="77a50eb5" points="[50.6115, 50.6125, 50.6135, ..., 50.8085, 50.8095, 50.8105]" shape="(200,)" standard_name="latitude" units="Unit('degrees')" value_type="float64"> @@ -107,16 +103,16 @@ ..., [-3.3245, -3.3227], [-3.3227, -3.3209], - [-3.3209, -3.3191]]" id="63128986" points="[-3.6782, -3.6764, -3.6746, ..., -3.3236, + [-3.3209, -3.3191]]" id="f913a8b3" points="[-3.6782, -3.6764, -3.6746, ..., -3.3236, -3.3218, -3.32]" shape="(200,)" standard_name="longitude" units="Unit('degrees')" value_type="float64"> - + - + @@ -124,9 +120,9 @@ - + - + @@ -134,8 +130,6 @@ - - @@ -157,7 +151,7 @@ ..., [50.808, 50.809], [50.809, 50.81], - [50.81, 50.811]]" id="a42bcac2" points="[50.6115, 50.6125, 50.6135, ..., 50.8085, + [50.81, 50.811]]" id="77a50eb5" points="[50.6115, 50.6125, 50.6135, ..., 50.8085, 50.8095, 50.8105]" shape="(200,)" standard_name="latitude" units="Unit('degrees')" value_type="float64"> @@ -169,16 +163,16 @@ ..., [-3.3245, -3.3227], [-3.3227, -3.3209], - [-3.3209, -3.3191]]" id="63128986" points="[-3.6782, -3.6764, -3.6746, ..., -3.3236, + [-3.3209, -3.3191]]" id="f913a8b3" points="[-3.6782, -3.6764, -3.6746, ..., -3.3236, -3.3218, -3.32]" shape="(200,)" standard_name="longitude" units="Unit('degrees')" value_type="float64"> - + - + @@ -186,9 +180,9 @@ - + - + @@ -196,8 +190,6 @@ - - @@ -219,7 +211,7 @@ ..., [50.808, 50.809], [50.809, 50.81], - [50.81, 50.811]]" id="a42bcac2" points="[50.6115, 50.6125, 50.6135, ..., 50.8085, + [50.81, 50.811]]" id="77a50eb5" points="[50.6115, 50.6125, 50.6135, ..., 50.8085, 50.8095, 50.8105]" shape="(200,)" standard_name="latitude" units="Unit('degrees')" value_type="float64"> @@ -231,16 +223,16 @@ ..., [-3.3245, -3.3227], [-3.3227, -3.3209], - [-3.3209, -3.3191]]" id="63128986" points="[-3.6782, -3.6764, -3.6746, ..., -3.3236, + [-3.3209, -3.3191]]" id="f913a8b3" points="[-3.6782, -3.6764, -3.6746, ..., -3.3236, -3.3218, -3.32]" shape="(200,)" standard_name="longitude" units="Unit('degrees')" value_type="float64"> - + - + @@ -248,9 +240,9 @@ - + - + @@ -258,8 +250,6 @@ - - @@ -281,7 +271,7 @@ ..., [50.808, 50.809], [50.809, 50.81], - [50.81, 50.811]]" id="a42bcac2" points="[50.6115, 50.6125, 50.6135, ..., 50.8085, + [50.81, 50.811]]" id="77a50eb5" points="[50.6115, 50.6125, 50.6135, ..., 50.8085, 50.8095, 50.8105]" shape="(200,)" standard_name="latitude" units="Unit('degrees')" value_type="float64"> @@ -293,16 +283,16 @@ ..., [-3.3245, -3.3227], [-3.3227, -3.3209], - [-3.3209, -3.3191]]" id="63128986" points="[-3.6782, -3.6764, -3.6746, ..., -3.3236, + [-3.3209, -3.3191]]" id="f913a8b3" points="[-3.6782, -3.6764, -3.6746, ..., -3.3236, -3.3218, -3.32]" shape="(200,)" standard_name="longitude" units="Unit('degrees')" value_type="float64"> - + - + @@ -310,6 +300,6 @@ - + diff --git a/lib/iris/tests/results/name/NAMEIII_field.data.0.json b/lib/iris/tests/results/name/NAMEIII_field.data.0.json new file mode 100644 index 0000000000..883332a4d5 --- /dev/null +++ b/lib/iris/tests/results/name/NAMEIII_field.data.0.json @@ -0,0 +1 @@ +{"std": 9.2157414144367067e-08, "min": 0.0, "max": 4.62122034150525e-06, "shape": [200, 200], "masked": false, "mean": 4.639838735442936e-09} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEIII_field.data.0.npy b/lib/iris/tests/results/name/NAMEIII_field.data.0.npy deleted file mode 100644 index c950864dec..0000000000 Binary files a/lib/iris/tests/results/name/NAMEIII_field.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/name/NAMEIII_field.data.1.json b/lib/iris/tests/results/name/NAMEIII_field.data.1.json new file mode 100644 index 0000000000..f08f477bde --- /dev/null +++ b/lib/iris/tests/results/name/NAMEIII_field.data.1.json @@ -0,0 +1 @@ +{"std": 2.5599286579414127e-11, "min": 0.0, "max": 1.283672279583925e-09, "shape": [200, 200], "masked": false, "mean": 1.2888440314995364e-12} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEIII_field.data.1.npy b/lib/iris/tests/results/name/NAMEIII_field.data.1.npy deleted file mode 100644 index be1510693f..0000000000 Binary files a/lib/iris/tests/results/name/NAMEIII_field.data.1.npy and /dev/null differ diff --git a/lib/iris/tests/results/name/NAMEIII_field.data.2.json b/lib/iris/tests/results/name/NAMEIII_field.data.2.json new file mode 100644 index 0000000000..62bb264316 --- /dev/null +++ b/lib/iris/tests/results/name/NAMEIII_field.data.2.json @@ -0,0 +1 @@ +{"std": 2.9475852314497786e-10, "min": 0.0, "max": 1.5096331296149401e-08, "shape": [200, 200], "masked": false, "mean": 1.4808954409972763e-11} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEIII_field.data.2.npy b/lib/iris/tests/results/name/NAMEIII_field.data.2.npy deleted file mode 100644 index 71d9f06400..0000000000 Binary files a/lib/iris/tests/results/name/NAMEIII_field.data.2.npy and /dev/null differ diff --git a/lib/iris/tests/results/name/NAMEIII_field.data.3.json b/lib/iris/tests/results/name/NAMEIII_field.data.3.json new file mode 100644 index 0000000000..aec65f4682 --- /dev/null +++ b/lib/iris/tests/results/name/NAMEIII_field.data.3.json @@ -0,0 +1 @@ +{"std": 1.8573325100135207e-09, "min": 0.0, "max": 1.231626072240033e-07, "shape": [200, 200], "masked": false, "mean": 8.4571800951227516e-11} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEIII_field.data.3.npy b/lib/iris/tests/results/name/NAMEIII_field.data.3.npy deleted file mode 100644 index 212e34c3cc..0000000000 Binary files a/lib/iris/tests/results/name/NAMEIII_field.data.3.npy and /dev/null differ diff --git a/lib/iris/tests/results/name/NAMEIII_field.data.4.json b/lib/iris/tests/results/name/NAMEIII_field.data.4.json new file mode 100644 index 0000000000..01816dee83 --- /dev/null +++ b/lib/iris/tests/results/name/NAMEIII_field.data.4.json @@ -0,0 +1 @@ +{"std": 2.1372636993532979e-09, "min": 0.0, "max": 1.3791643027616374e-07, "shape": [200, 200], "masked": false, "mean": 9.9380746687582899e-11} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEIII_field.data.4.npy b/lib/iris/tests/results/name/NAMEIII_field.data.4.npy deleted file mode 100644 index 895525b1ca..0000000000 Binary files a/lib/iris/tests/results/name/NAMEIII_field.data.4.npy and /dev/null differ diff --git a/lib/iris/tests/results/name/NAMEIII_timeseries.cml b/lib/iris/tests/results/name/NAMEIII_timeseries.cml index d1f78f51e7..976a6b2804 100644 --- a/lib/iris/tests/results/name/NAMEIII_timeseries.cml +++ b/lib/iris/tests/results/name/NAMEIII_timeseries.cml @@ -1,6 +1,6 @@ - + @@ -9,8 +9,6 @@ - - @@ -27,12 +25,12 @@ - + - + @@ -43,7 +41,7 @@ ..., [358354.0, 358355.0], [358355.0, 358356.0], - [358356.0, 358357.0]]" id="6a1b3c16" points="[358286.0, 358287.0, 358288.0, 358289.0, + [358356.0, 358357.0]]" id="cb784457" points="[358286.0, 358287.0, 358288.0, 358289.0, 358290.0, 358291.0, 358292.0, 358293.0, 358294.0, 358295.0, 358296.0, 358297.0, 358298.0, 358299.0, 358300.0, 358301.0, @@ -63,13 +61,13 @@ 358354.0, 358355.0, 358356.0, 358357.0]" shape="(72,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='gregorian')" value_type="float64"/> - + - + - + @@ -78,8 +76,6 @@ - - @@ -96,12 +92,12 @@ - + - + @@ -112,7 +108,7 @@ ..., [358354.0, 358355.0], [358355.0, 358356.0], - [358356.0, 358357.0]]" id="6a1b3c16" points="[358286.0, 358287.0, 358288.0, 358289.0, + [358356.0, 358357.0]]" id="cb784457" points="[358286.0, 358287.0, 358288.0, 358289.0, 358290.0, 358291.0, 358292.0, 358293.0, 358294.0, 358295.0, 358296.0, 358297.0, 358298.0, 358299.0, 358300.0, 358301.0, @@ -132,13 +128,13 @@ 358354.0, 358355.0, 358356.0, 358357.0]" shape="(72,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='gregorian')" value_type="float64"/> - + - + - + @@ -147,8 +143,6 @@ - - @@ -164,12 +158,12 @@ - + - + @@ -180,7 +174,7 @@ ..., [358354.0, 358355.0], [358355.0, 358356.0], - [358356.0, 358357.0]]" id="6a1b3c16" points="[358286.0, 358287.0, 358288.0, 358289.0, + [358356.0, 358357.0]]" id="cb784457" points="[358286.0, 358287.0, 358288.0, 358289.0, 358290.0, 358291.0, 358292.0, 358293.0, 358294.0, 358295.0, 358296.0, 358297.0, 358298.0, 358299.0, 358300.0, 358301.0, @@ -200,13 +194,13 @@ 358354.0, 358355.0, 358356.0, 358357.0]" shape="(72,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='gregorian')" value_type="float64"/> - + - + - + @@ -215,8 +209,6 @@ - - @@ -232,12 +224,12 @@ - + - + @@ -248,7 +240,7 @@ ..., [358354.0, 358355.0], [358355.0, 358356.0], - [358356.0, 358357.0]]" id="6a1b3c16" points="[358286.0, 358287.0, 358288.0, 358289.0, + [358356.0, 358357.0]]" id="cb784457" points="[358286.0, 358287.0, 358288.0, 358289.0, 358290.0, 358291.0, 358292.0, 358293.0, 358294.0, 358295.0, 358296.0, 358297.0, 358298.0, 358299.0, 358300.0, 358301.0, @@ -268,13 +260,13 @@ 358354.0, 358355.0, 358356.0, 358357.0]" shape="(72,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='gregorian')" value_type="float64"/> - + - + - + @@ -283,8 +275,6 @@ - - @@ -300,12 +290,12 @@ - + - + @@ -316,7 +306,7 @@ ..., [358354.0, 358355.0], [358355.0, 358356.0], - [358356.0, 358357.0]]" id="6a1b3c16" points="[358286.0, 358287.0, 358288.0, 358289.0, + [358356.0, 358357.0]]" id="cb784457" points="[358286.0, 358287.0, 358288.0, 358289.0, 358290.0, 358291.0, 358292.0, 358293.0, 358294.0, 358295.0, 358296.0, 358297.0, 358298.0, 358299.0, 358300.0, 358301.0, @@ -336,10 +326,10 @@ 358354.0, 358355.0, 358356.0, 358357.0]" shape="(72,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='gregorian')" value_type="float64"/> - + - + diff --git a/lib/iris/tests/results/name/NAMEIII_timeseries.data.0.json b/lib/iris/tests/results/name/NAMEIII_timeseries.data.0.json new file mode 100644 index 0000000000..c27b4d01e2 --- /dev/null +++ b/lib/iris/tests/results/name/NAMEIII_timeseries.data.0.json @@ -0,0 +1 @@ +{"std": 1.0903463650057284e-13, "min": 0.0, "max": 4.0756873000000001e-13, "shape": [72], "masked": false, "mean": 1.0429130496540107e-13} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEIII_timeseries.data.0.npy b/lib/iris/tests/results/name/NAMEIII_timeseries.data.0.npy deleted file mode 100644 index 02158cad2b..0000000000 Binary files a/lib/iris/tests/results/name/NAMEIII_timeseries.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/name/NAMEIII_timeseries.data.1.json b/lib/iris/tests/results/name/NAMEIII_timeseries.data.1.json new file mode 100644 index 0000000000..a716c1476f --- /dev/null +++ b/lib/iris/tests/results/name/NAMEIII_timeseries.data.1.json @@ -0,0 +1 @@ +{"std": 3.9252465982468551e-10, "min": 0.0, "max": 1.4672473e-09, "shape": [72], "masked": false, "mean": 3.7544867036405361e-10} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEIII_timeseries.data.1.npy b/lib/iris/tests/results/name/NAMEIII_timeseries.data.1.npy deleted file mode 100644 index b50bd0acb2..0000000000 Binary files a/lib/iris/tests/results/name/NAMEIII_timeseries.data.1.npy and /dev/null differ diff --git a/lib/iris/tests/results/name/NAMEIII_timeseries.data.2.json b/lib/iris/tests/results/name/NAMEIII_timeseries.data.2.json new file mode 100644 index 0000000000..5063a2bbbe --- /dev/null +++ b/lib/iris/tests/results/name/NAMEIII_timeseries.data.2.json @@ -0,0 +1 @@ +{"std": 5.2873227247937624e-17, "min": 0.0, "max": 1.948949e-16, "shape": [72], "masked": false, "mean": 5.7200061676526515e-17} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEIII_timeseries.data.2.npy b/lib/iris/tests/results/name/NAMEIII_timeseries.data.2.npy deleted file mode 100644 index 73260ef02c..0000000000 Binary files a/lib/iris/tests/results/name/NAMEIII_timeseries.data.2.npy and /dev/null differ diff --git a/lib/iris/tests/results/name/NAMEIII_timeseries.data.3.json b/lib/iris/tests/results/name/NAMEIII_timeseries.data.3.json new file mode 100644 index 0000000000..4de7113959 --- /dev/null +++ b/lib/iris/tests/results/name/NAMEIII_timeseries.data.3.json @@ -0,0 +1 @@ +{"std": 3.2318527050866585e-15, "min": 0.0, "max": 1.7424067e-14, "shape": [72], "masked": false, "mean": 1.2610151829633925e-15} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEIII_timeseries.data.3.npy b/lib/iris/tests/results/name/NAMEIII_timeseries.data.3.npy deleted file mode 100644 index cb840faccc..0000000000 Binary files a/lib/iris/tests/results/name/NAMEIII_timeseries.data.3.npy and /dev/null differ diff --git a/lib/iris/tests/results/name/NAMEIII_timeseries.data.4.json b/lib/iris/tests/results/name/NAMEIII_timeseries.data.4.json new file mode 100644 index 0000000000..9e1f769617 --- /dev/null +++ b/lib/iris/tests/results/name/NAMEIII_timeseries.data.4.json @@ -0,0 +1 @@ +{"std": 3.2470735674477217e-15, "min": 0.0, "max": 1.7555705e-14, "shape": [72], "masked": false, "mean": 1.3182152734315856e-15} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEIII_timeseries.data.4.npy b/lib/iris/tests/results/name/NAMEIII_timeseries.data.4.npy deleted file mode 100644 index f06e1e768f..0000000000 Binary files a/lib/iris/tests/results/name/NAMEIII_timeseries.data.4.npy and /dev/null differ diff --git a/lib/iris/tests/results/name/NAMEIII_trajectory.cml b/lib/iris/tests/results/name/NAMEIII_trajectory.cml index a684649d65..c514d589ca 100644 --- a/lib/iris/tests/results/name/NAMEIII_trajectory.cml +++ b/lib/iris/tests/results/name/NAMEIII_trajectory.cml @@ -1,649 +1,768 @@ - + + + + + + + + - + - + - + - + - - + - - - - + - + + + + + + + + - + - + - + - + - - + - - - - + - + + + + + + + + - + - + - + - + - - + - - - - + - + + + + + + + + - + - + - + - + - - + - - - - + - + + + + + + + + - + - + - + - + - - + - - - - + - + + + + + + + + - + - + - + - + - - + - - - - + - + + + + + + + + - + - + - + - + - - + - - - - + - + + + + + + + + - + - + - + - + - - + - - - - + - + + + + + + + + - + - + - + - + - - + - - - - + - + + + + + + + + - + - + - + - + - - + - - - - + - + + + + + + + + - + - + - + - + - - + - - - - + - + + + + + + + + - + - + - + - + - - + - - - - + - + + + + + + + + - + - + - + - + - - + - - - - + - + + + + + + + + - + - + - + - + - - + - - - - + - + + + + + + + + - + - + - + - + - - + - - - - + - + + + + + + + + - + - + - + - + - - + - - - - + - + + + + + + + + - + - + - + - + - - + - - - - + diff --git a/lib/iris/tests/results/name/NAMEIII_trajectory0.cml b/lib/iris/tests/results/name/NAMEIII_trajectory0.cml index 3f59dde9d0..5f10016f39 100644 --- a/lib/iris/tests/results/name/NAMEIII_trajectory0.cml +++ b/lib/iris/tests/results/name/NAMEIII_trajectory0.cml @@ -1,41 +1,48 @@ - + + + + + + + + - + - + - + - + - - + - - - - + diff --git a/lib/iris/tests/results/name/NAMEIII_version2.cml b/lib/iris/tests/results/name/NAMEIII_version2.cml new file mode 100644 index 0000000000..95b9db7d5b --- /dev/null +++ b/lib/iris/tests/results/name/NAMEIII_version2.cml @@ -0,0 +1,331 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/name/NAMEIII_version2.data.0.json b/lib/iris/tests/results/name/NAMEIII_version2.data.0.json new file mode 100644 index 0000000000..ef507ff2db --- /dev/null +++ b/lib/iris/tests/results/name/NAMEIII_version2.data.0.json @@ -0,0 +1 @@ +{"std": 1.7932158868916304e-08, "min": 0.0, "max": 1.0494331803556634e-07, "shape": [24, 10], "masked": false, "mean": 4.7153978499636651e-09} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEIII_version2.data.1.json b/lib/iris/tests/results/name/NAMEIII_version2.data.1.json new file mode 100644 index 0000000000..9d042e090d --- /dev/null +++ b/lib/iris/tests/results/name/NAMEIII_version2.data.1.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 0.0, "max": 0.0, "shape": [24, 10], "masked": false, "mean": 0.0} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEIII_version2.data.2.json b/lib/iris/tests/results/name/NAMEIII_version2.data.2.json new file mode 100644 index 0000000000..f2be43debd --- /dev/null +++ b/lib/iris/tests/results/name/NAMEIII_version2.data.2.json @@ -0,0 +1 @@ +{"std": 3.3590910608616298e-10, "min": 0.0, "max": 1.910191560483554e-09, "shape": [24, 10], "masked": false, "mean": 1.5448627099790002e-10} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEIII_version2.data.3.json b/lib/iris/tests/results/name/NAMEIII_version2.data.3.json new file mode 100644 index 0000000000..9d042e090d --- /dev/null +++ b/lib/iris/tests/results/name/NAMEIII_version2.data.3.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 0.0, "max": 0.0, "shape": [24, 10], "masked": false, "mean": 0.0} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEII_field.cml b/lib/iris/tests/results/name/NAMEII_field.cml index 7024c46e3b..db9ac94198 100644 --- a/lib/iris/tests/results/name/NAMEII_field.cml +++ b/lib/iris/tests/results/name/NAMEII_field.cml @@ -1,12 +1,11 @@ - + - @@ -20,7 +19,7 @@ - + @@ -41,14 +40,14 @@ ..., [-1.7301220759, -1.7283130306], [-1.7283130306, -1.7265039853], - [-1.7265039853, -1.72469494]]" id="63128986" points="[-2.08559947735, -2.08379043205, -2.08198138675, + [-1.7265039853, -1.72469494]]" id="f913a8b3" points="[-2.08559947735, -2.08379043205, -2.08198138675, ..., -1.72921755325, -1.72740850795, -1.72559946265]" shape="(200,)" standard_name="longitude" units="Unit('degrees')" value_type="float64"> - + @@ -56,15 +55,14 @@ - + - + - @@ -78,7 +76,7 @@ - + @@ -99,14 +97,14 @@ ..., [-1.7301220759, -1.7283130306], [-1.7283130306, -1.7265039853], - [-1.7265039853, -1.72469494]]" id="63128986" points="[-2.08559947735, -2.08379043205, -2.08198138675, + [-1.7265039853, -1.72469494]]" id="f913a8b3" points="[-2.08559947735, -2.08379043205, -2.08198138675, ..., -1.72921755325, -1.72740850795, -1.72559946265]" shape="(200,)" standard_name="longitude" units="Unit('degrees')" value_type="float64"> - + @@ -114,15 +112,14 @@ - + - + - @@ -142,7 +139,7 @@ ..., [52.5843389372, 52.5854444648], [52.5854444648, 52.5865499924], - [52.5865499924, 52.58765552]]" id="a42bcac2" points="[52.3671027638, 52.3682082914, 52.369313819, ..., + [52.5865499924, 52.58765552]]" id="77a50eb5" points="[52.3671027638, 52.3682082914, 52.369313819, ..., 52.584891701, 52.5859972286, 52.5871027562]" shape="(200,)" standard_name="latitude" units="Unit('degrees')" value_type="float64"> @@ -154,17 +151,17 @@ ..., [-1.7301220759, -1.7283130306], [-1.7283130306, -1.7265039853], - [-1.7265039853, -1.72469494]]" id="63128986" points="[-2.08559947735, -2.08379043205, -2.08198138675, + [-1.7265039853, -1.72469494]]" id="f913a8b3" points="[-2.08559947735, -2.08379043205, -2.08198138675, ..., -1.72921755325, -1.72740850795, -1.72559946265]" shape="(200,)" standard_name="longitude" units="Unit('degrees')" value_type="float64"> - + - + @@ -172,15 +169,14 @@ - + - + - @@ -200,7 +196,7 @@ ..., [52.5843389372, 52.5854444648], [52.5854444648, 52.5865499924], - [52.5865499924, 52.58765552]]" id="a42bcac2" points="[52.3671027638, 52.3682082914, 52.369313819, ..., + [52.5865499924, 52.58765552]]" id="77a50eb5" points="[52.3671027638, 52.3682082914, 52.369313819, ..., 52.584891701, 52.5859972286, 52.5871027562]" shape="(200,)" standard_name="latitude" units="Unit('degrees')" value_type="float64"> @@ -212,17 +208,17 @@ ..., [-1.7301220759, -1.7283130306], [-1.7283130306, -1.7265039853], - [-1.7265039853, -1.72469494]]" id="63128986" points="[-2.08559947735, -2.08379043205, -2.08198138675, + [-1.7265039853, -1.72469494]]" id="f913a8b3" points="[-2.08559947735, -2.08379043205, -2.08198138675, ..., -1.72921755325, -1.72740850795, -1.72559946265]" shape="(200,)" standard_name="longitude" units="Unit('degrees')" value_type="float64"> - + - + @@ -230,15 +226,14 @@ - + - + - @@ -258,7 +253,7 @@ ..., [52.5843389372, 52.5854444648], [52.5854444648, 52.5865499924], - [52.5865499924, 52.58765552]]" id="a42bcac2" points="[52.3671027638, 52.3682082914, 52.369313819, ..., + [52.5865499924, 52.58765552]]" id="77a50eb5" points="[52.3671027638, 52.3682082914, 52.369313819, ..., 52.584891701, 52.5859972286, 52.5871027562]" shape="(200,)" standard_name="latitude" units="Unit('degrees')" value_type="float64"> @@ -270,17 +265,17 @@ ..., [-1.7301220759, -1.7283130306], [-1.7283130306, -1.7265039853], - [-1.7265039853, -1.72469494]]" id="63128986" points="[-2.08559947735, -2.08379043205, -2.08198138675, + [-1.7265039853, -1.72469494]]" id="f913a8b3" points="[-2.08559947735, -2.08379043205, -2.08198138675, ..., -1.72921755325, -1.72740850795, -1.72559946265]" shape="(200,)" standard_name="longitude" units="Unit('degrees')" value_type="float64"> - + - + @@ -288,6 +283,6 @@ - + diff --git a/lib/iris/tests/results/name/NAMEII_field.data.0.json b/lib/iris/tests/results/name/NAMEII_field.data.0.json new file mode 100644 index 0000000000..04dfa72151 --- /dev/null +++ b/lib/iris/tests/results/name/NAMEII_field.data.0.json @@ -0,0 +1 @@ +{"std": 2.1295469831983382e-09, "min": 0.0, "max": 4.8132168473102865e-08, "shape": [200, 200], "masked": false, "mean": 2.1555640605797066e-10} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEII_field.data.0.npy b/lib/iris/tests/results/name/NAMEII_field.data.0.npy deleted file mode 100644 index 7082115bdf..0000000000 Binary files a/lib/iris/tests/results/name/NAMEII_field.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/name/NAMEII_field.data.1.json b/lib/iris/tests/results/name/NAMEII_field.data.1.json new file mode 100644 index 0000000000..5aa4b4ccc5 --- /dev/null +++ b/lib/iris/tests/results/name/NAMEII_field.data.1.json @@ -0,0 +1 @@ +{"std": 2.2493359210784547e-05, "min": 0.0, "max": 0.00048885477008298039, "shape": [200, 200], "masked": false, "mean": 2.3138848064263584e-06} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEII_field.data.1.npy b/lib/iris/tests/results/name/NAMEII_field.data.1.npy deleted file mode 100644 index 2fba787a8a..0000000000 Binary files a/lib/iris/tests/results/name/NAMEII_field.data.1.npy and /dev/null differ diff --git a/lib/iris/tests/results/name/NAMEII_field.data.2.json b/lib/iris/tests/results/name/NAMEII_field.data.2.json new file mode 100644 index 0000000000..d04d414178 --- /dev/null +++ b/lib/iris/tests/results/name/NAMEII_field.data.2.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 0.0, "max": 0.0, "shape": [200, 200], "masked": false, "mean": 0.0} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEII_field.data.2.npy b/lib/iris/tests/results/name/NAMEII_field.data.2.npy deleted file mode 100644 index 8d96945912..0000000000 Binary files a/lib/iris/tests/results/name/NAMEII_field.data.2.npy and /dev/null differ diff --git a/lib/iris/tests/results/name/NAMEII_field.data.3.json b/lib/iris/tests/results/name/NAMEII_field.data.3.json new file mode 100644 index 0000000000..03a03764d6 --- /dev/null +++ b/lib/iris/tests/results/name/NAMEII_field.data.3.json @@ -0,0 +1 @@ +{"std": 1.1607482264253122e-07, "min": 0.0, "max": 2.5288968572567683e-06, "shape": [200, 200], "masked": false, "mean": 1.1793673593274434e-08} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEII_field.data.3.npy b/lib/iris/tests/results/name/NAMEII_field.data.3.npy deleted file mode 100644 index 16373092db..0000000000 Binary files a/lib/iris/tests/results/name/NAMEII_field.data.3.npy and /dev/null differ diff --git a/lib/iris/tests/results/name/NAMEII_field.data.4.json b/lib/iris/tests/results/name/NAMEII_field.data.4.json new file mode 100644 index 0000000000..03a03764d6 --- /dev/null +++ b/lib/iris/tests/results/name/NAMEII_field.data.4.json @@ -0,0 +1 @@ +{"std": 1.1607482264253122e-07, "min": 0.0, "max": 2.5288968572567683e-06, "shape": [200, 200], "masked": false, "mean": 1.1793673593274434e-08} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEII_field.data.4.npy b/lib/iris/tests/results/name/NAMEII_field.data.4.npy deleted file mode 100644 index 16373092db..0000000000 Binary files a/lib/iris/tests/results/name/NAMEII_field.data.4.npy and /dev/null differ diff --git a/lib/iris/tests/results/name/NAMEII_timeseries.cml b/lib/iris/tests/results/name/NAMEII_timeseries.cml index 5bf19c85a8..61d0b2fed0 100644 --- a/lib/iris/tests/results/name/NAMEII_timeseries.cml +++ b/lib/iris/tests/results/name/NAMEII_timeseries.cml @@ -1,13 +1,12 @@ - + - @@ -20,12 +19,12 @@ - + - + @@ -36,24 +35,23 @@ ..., [370473.5, 370474.5], [370474.5, 370475.5], - [370475.5, 370476.5]]" id="6a1b3c16" points="[370345.0, 370346.0, 370347.0, ..., 370474.0, + [370475.5, 370476.5]]" id="cb784457" points="[370345.0, 370346.0, 370347.0, ..., 370474.0, 370475.0, 370476.0]" shape="(132,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='gregorian')" value_type="float64"/> - + - + - + - @@ -66,12 +64,12 @@ - + - + @@ -82,14 +80,14 @@ ..., [370473.5, 370474.5], [370474.5, 370475.5], - [370475.5, 370476.5]]" id="6a1b3c16" points="[370345.0, 370346.0, 370347.0, ..., 370474.0, + [370475.5, 370476.5]]" id="cb784457" points="[370345.0, 370346.0, 370347.0, ..., 370474.0, 370475.0, 370476.0]" shape="(132,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='gregorian')" value_type="float64"/> - + - + diff --git a/lib/iris/tests/results/name/NAMEII_timeseries.data.0.json b/lib/iris/tests/results/name/NAMEII_timeseries.data.0.json new file mode 100644 index 0000000000..5c23310a7b --- /dev/null +++ b/lib/iris/tests/results/name/NAMEII_timeseries.data.0.json @@ -0,0 +1 @@ +{"std": 0.00033021471021460599, "min": 0.0, "max": 0.0015961617, "shape": [132], "masked": false, "mean": 0.00019860586272835146} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEII_timeseries.data.0.npy b/lib/iris/tests/results/name/NAMEII_timeseries.data.0.npy deleted file mode 100644 index 20972b6393..0000000000 Binary files a/lib/iris/tests/results/name/NAMEII_timeseries.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/name/NAMEII_timeseries.data.1.json b/lib/iris/tests/results/name/NAMEII_timeseries.data.1.json new file mode 100644 index 0000000000..936e74deb3 --- /dev/null +++ b/lib/iris/tests/results/name/NAMEII_timeseries.data.1.json @@ -0,0 +1 @@ +{"std": 0.00017462574781585265, "min": 0.0, "max": 0.00099772017000000009, "shape": [132], "masked": false, "mean": 9.5217456948642194e-05} \ No newline at end of file diff --git a/lib/iris/tests/results/name/NAMEII_timeseries.data.1.npy b/lib/iris/tests/results/name/NAMEII_timeseries.data.1.npy deleted file mode 100644 index 54ef0eee77..0000000000 Binary files a/lib/iris/tests/results/name/NAMEII_timeseries.data.1.npy and /dev/null differ diff --git a/lib/iris/tests/results/netcdf/int64_auxiliary_coord_netcdf3.cml b/lib/iris/tests/results/netcdf/int64_auxiliary_coord_netcdf3.cml index b72412f660..0a28f4fb7e 100644 --- a/lib/iris/tests/results/netcdf/int64_auxiliary_coord_netcdf3.cml +++ b/lib/iris/tests/results/netcdf/int64_auxiliary_coord_netcdf3.cml @@ -1,12 +1,12 @@ - + - + diff --git a/lib/iris/tests/results/netcdf/int64_data_netcdf3.cml b/lib/iris/tests/results/netcdf/int64_data_netcdf3.cml index cafafcf39c..608769f4c3 100644 --- a/lib/iris/tests/results/netcdf/int64_data_netcdf3.cml +++ b/lib/iris/tests/results/netcdf/int64_data_netcdf3.cml @@ -1,11 +1,11 @@ - + - + diff --git a/lib/iris/tests/results/netcdf/int64_dimension_coord_netcdf3.cml b/lib/iris/tests/results/netcdf/int64_dimension_coord_netcdf3.cml index 401be5df65..5c523ac16b 100644 --- a/lib/iris/tests/results/netcdf/int64_dimension_coord_netcdf3.cml +++ b/lib/iris/tests/results/netcdf/int64_dimension_coord_netcdf3.cml @@ -1,12 +1,12 @@ - + - + diff --git a/lib/iris/tests/results/netcdf/multi_dim_coord_slightly_different.cdl b/lib/iris/tests/results/netcdf/multi_dim_coord_slightly_different.cdl index 4476be93ec..42592d9c3e 100644 --- a/lib/iris/tests/results/netcdf/multi_dim_coord_slightly_different.cdl +++ b/lib/iris/tests/results/netcdf/multi_dim_coord_slightly_different.cdl @@ -1,7 +1,7 @@ dimensions: - latitude_0 = UNLIMITED ; // (10 currently) - time = UNLIMITED ; // (2 currently) latitude = 2 ; + latitude_0 = 10 ; + time = 2 ; variables: double temp(time, latitude) ; temp:standard_name = "surface_temperature" ; diff --git a/lib/iris/tests/results/netcdf/netcdf_cell_methods.cml b/lib/iris/tests/results/netcdf/netcdf_cell_methods.cml index a627164194..8dd0e43b71 100644 --- a/lib/iris/tests/results/netcdf/netcdf_cell_methods.cml +++ b/lib/iris/tests/results/netcdf/netcdf_cell_methods.cml @@ -1,56 +1,56 @@ - + - + - + - + - - + + - + - + - + - + - + - - + + - + - + - + - + - + @@ -58,24 +58,24 @@ - + - + - + - + - + - + - + @@ -83,45 +83,45 @@ - - + + - + - + - + - + - + - - + + - + - + - + - + - + @@ -129,18 +129,18 @@ - + - + - + - + - + @@ -148,58 +148,58 @@ - + - + - + - + - + - - + + - + - + - + - + - + - - + + - + - + - + - + - + @@ -207,22 +207,22 @@ - - + + - + - + - + - + - + @@ -230,58 +230,58 @@ - + - + - + - + - + - - + + - + - + - + - + - + - - + + - + - + - + - + - + @@ -289,22 +289,22 @@ - - + + - + - + - + - + - + @@ -312,18 +312,18 @@ - + - + - + - + - + @@ -331,12 +331,12 @@ - + - + - + @@ -344,12 +344,12 @@ - + - + - + @@ -357,12 +357,12 @@ - + - + - + @@ -370,12 +370,12 @@ - + - + - + @@ -383,18 +383,18 @@ - + - + - + - + - + @@ -402,55 +402,55 @@ - + - + - + - + - + - - + + - + - + - + - + - + - - + + - + - + - + @@ -458,12 +458,12 @@ - + - + - + @@ -471,12 +471,12 @@ - + - + - + @@ -484,12 +484,12 @@ - + - + - + @@ -497,12 +497,12 @@ - + - + - + @@ -510,6 +510,6 @@ - + diff --git a/lib/iris/tests/results/netcdf/netcdf_deferred_index_0.cml b/lib/iris/tests/results/netcdf/netcdf_deferred_index_0.cml index 7206650640..a11d593684 100644 --- a/lib/iris/tests/results/netcdf/netcdf_deferred_index_0.cml +++ b/lib/iris/tests/results/netcdf/netcdf_deferred_index_0.cml @@ -1,6 +1,6 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/netcdf/netcdf_deferred_index_1.cml b/lib/iris/tests/results/netcdf/netcdf_deferred_index_1.cml index d1629ab558..30e6844591 100644 --- a/lib/iris/tests/results/netcdf/netcdf_deferred_index_1.cml +++ b/lib/iris/tests/results/netcdf/netcdf_deferred_index_1.cml @@ -1,6 +1,6 @@ - + + - + - + - + diff --git a/lib/iris/tests/results/netcdf/netcdf_deferred_index_2.cml b/lib/iris/tests/results/netcdf/netcdf_deferred_index_2.cml index e02ebaa306..6f9446582a 100644 --- a/lib/iris/tests/results/netcdf/netcdf_deferred_index_2.cml +++ b/lib/iris/tests/results/netcdf/netcdf_deferred_index_2.cml @@ -1,6 +1,6 @@ - + + - + - + - + diff --git a/lib/iris/tests/results/netcdf/netcdf_deferred_mix_0.cml b/lib/iris/tests/results/netcdf/netcdf_deferred_mix_0.cml index 573f35325c..12def7cea4 100644 --- a/lib/iris/tests/results/netcdf/netcdf_deferred_mix_0.cml +++ b/lib/iris/tests/results/netcdf/netcdf_deferred_mix_0.cml @@ -1,6 +1,6 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/netcdf/netcdf_deferred_mix_1.cml b/lib/iris/tests/results/netcdf/netcdf_deferred_mix_1.cml index 2b32d89bf8..b20281c53e 100644 --- a/lib/iris/tests/results/netcdf/netcdf_deferred_mix_1.cml +++ b/lib/iris/tests/results/netcdf/netcdf_deferred_mix_1.cml @@ -1,6 +1,6 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/netcdf/netcdf_deferred_slice_0.cml b/lib/iris/tests/results/netcdf/netcdf_deferred_slice_0.cml index 57350ed4a9..0d126109cf 100644 --- a/lib/iris/tests/results/netcdf/netcdf_deferred_slice_0.cml +++ b/lib/iris/tests/results/netcdf/netcdf_deferred_slice_0.cml @@ -1,6 +1,6 @@ - + - + - + - - + diff --git a/lib/iris/tests/results/netcdf/netcdf_deferred_slice_1.cml b/lib/iris/tests/results/netcdf/netcdf_deferred_slice_1.cml index 10cd67a210..8cfb4a0b5f 100644 --- a/lib/iris/tests/results/netcdf/netcdf_deferred_slice_1.cml +++ b/lib/iris/tests/results/netcdf/netcdf_deferred_slice_1.cml @@ -1,6 +1,6 @@ - + - + - + - - + diff --git a/lib/iris/tests/results/netcdf/netcdf_deferred_slice_2.cml b/lib/iris/tests/results/netcdf/netcdf_deferred_slice_2.cml index f61b3fd9c9..9259a07563 100644 --- a/lib/iris/tests/results/netcdf/netcdf_deferred_slice_2.cml +++ b/lib/iris/tests/results/netcdf/netcdf_deferred_slice_2.cml @@ -1,6 +1,6 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/netcdf/netcdf_deferred_tuple_0.cml b/lib/iris/tests/results/netcdf/netcdf_deferred_tuple_0.cml index 76e51365fa..6bc1a094e3 100644 --- a/lib/iris/tests/results/netcdf/netcdf_deferred_tuple_0.cml +++ b/lib/iris/tests/results/netcdf/netcdf_deferred_tuple_0.cml @@ -1,6 +1,6 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/netcdf/netcdf_deferred_tuple_1.cml b/lib/iris/tests/results/netcdf/netcdf_deferred_tuple_1.cml index 69f1c90fc1..0535339c7e 100644 --- a/lib/iris/tests/results/netcdf/netcdf_deferred_tuple_1.cml +++ b/lib/iris/tests/results/netcdf/netcdf_deferred_tuple_1.cml @@ -1,6 +1,6 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/netcdf/netcdf_deferred_tuple_2.cml b/lib/iris/tests/results/netcdf/netcdf_deferred_tuple_2.cml index 135f39bd86..6a0f9a90bf 100644 --- a/lib/iris/tests/results/netcdf/netcdf_deferred_tuple_2.cml +++ b/lib/iris/tests/results/netcdf/netcdf_deferred_tuple_2.cml @@ -1,6 +1,6 @@ - + - + - + - + - + diff --git a/lib/iris/tests/results/netcdf/netcdf_global_xyt_hires.cml b/lib/iris/tests/results/netcdf/netcdf_global_xyt_hires.cml index b89ae13524..bda7f9ed9f 100644 --- a/lib/iris/tests/results/netcdf/netcdf_global_xyt_hires.cml +++ b/lib/iris/tests/results/netcdf/netcdf_global_xyt_hires.cml @@ -1,6 +1,6 @@ - + @@ -20,7 +20,7 @@ - + @@ -33,7 +33,7 @@ ..., [86.3651715331, 87.4911905887], [87.4911905887, 88.6247285576], - [88.6247285576, 90.0]]" id="5ffde89e" long_name="latitude" points="[-89.1415194265, -88.029428868, -86.9107708141, + [88.6247285576, 90.0]]" id="dab47bb1" long_name="latitude" points="[-89.1415194265, -88.029428868, -86.9107708141, ..., 86.9107708141, 88.029428868, 89.1415194265]" shape="(160,)" standard_name="latitude" units="Unit('degrees')" value_type="float64" var_name="lat"/> @@ -43,7 +43,7 @@ ..., [356.0625, 357.1875], [357.1875, 358.3125], - [358.3125, 359.4375]]" circular="True" id="410c27bf" long_name="longitude" points="[0.0, 1.125, 2.25, ..., 356.625, 357.75, 358.875]" shape="(320,)" standard_name="longitude" units="Unit('degrees')" value_type="float64" var_name="lon"/> + [358.3125, 359.4375]]" circular="True" id="c15a8e5b" long_name="longitude" points="[0.0, 1.125, 2.25, ..., 356.625, 357.75, 358.875]" shape="(320,)" standard_name="longitude" units="Unit('degrees')" value_type="float64" var_name="lon"/> - + diff --git a/lib/iris/tests/results/netcdf/netcdf_global_xyt_total.cml b/lib/iris/tests/results/netcdf/netcdf_global_xyt_total.cml index 30b66b8ab0..1204fd0d39 100644 --- a/lib/iris/tests/results/netcdf/netcdf_global_xyt_total.cml +++ b/lib/iris/tests/results/netcdf/netcdf_global_xyt_total.cml @@ -1,6 +1,6 @@ - + - + - + - + diff --git a/lib/iris/tests/results/netcdf/netcdf_global_xyzt_gems.cml b/lib/iris/tests/results/netcdf/netcdf_global_xyzt_gems.cml index 34b54796ae..27d4569236 100644 --- a/lib/iris/tests/results/netcdf/netcdf_global_xyzt_gems.cml +++ b/lib/iris/tests/results/netcdf/netcdf_global_xyzt_gems.cml @@ -1,55 +1,55 @@ - + - + - + - + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]" shape="(60,)" units="Unit('1')" value_type="int32" var_name="levelist"/> - + - + - + - + - + - + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]" shape="(60,)" units="Unit('1')" value_type="int32" var_name="levelist"/> - + - + diff --git a/lib/iris/tests/results/netcdf/netcdf_global_xyzt_gems_iter_0.cml b/lib/iris/tests/results/netcdf/netcdf_global_xyzt_gems_iter_0.cml index 0feb2b5864..d677191beb 100644 --- a/lib/iris/tests/results/netcdf/netcdf_global_xyzt_gems_iter_0.cml +++ b/lib/iris/tests/results/netcdf/netcdf_global_xyzt_gems_iter_0.cml @@ -1,29 +1,29 @@ - + - + - + - + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]" shape="(60,)" units="Unit('1')" value_type="int32" var_name="levelist"/> - + - + diff --git a/lib/iris/tests/results/netcdf/netcdf_global_xyzt_gems_iter_1.cml b/lib/iris/tests/results/netcdf/netcdf_global_xyzt_gems_iter_1.cml index 2e52cf8ed1..775f480c66 100644 --- a/lib/iris/tests/results/netcdf/netcdf_global_xyzt_gems_iter_1.cml +++ b/lib/iris/tests/results/netcdf/netcdf_global_xyzt_gems_iter_1.cml @@ -1,29 +1,29 @@ - + - + - + - + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]" shape="(60,)" units="Unit('1')" value_type="int32" var_name="levelist"/> - + - + diff --git a/lib/iris/tests/results/netcdf/netcdf_laea.cml b/lib/iris/tests/results/netcdf/netcdf_laea.cml new file mode 100644 index 0000000000..03fdb529a4 --- /dev/null +++ b/lib/iris/tests/results/netcdf/netcdf_laea.cml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/netcdf/netcdf_lcc.cml b/lib/iris/tests/results/netcdf/netcdf_lcc.cml new file mode 100644 index 0000000000..ace6c632d9 --- /dev/null +++ b/lib/iris/tests/results/netcdf/netcdf_lcc.cml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/netcdf/netcdf_merc.cml b/lib/iris/tests/results/netcdf/netcdf_merc.cml new file mode 100644 index 0000000000..02fc4e7c34 --- /dev/null +++ b/lib/iris/tests/results/netcdf/netcdf_merc.cml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/netcdf/netcdf_monotonic.cml b/lib/iris/tests/results/netcdf/netcdf_monotonic.cml index 0e989633b0..578b2b6d96 100644 --- a/lib/iris/tests/results/netcdf/netcdf_monotonic.cml +++ b/lib/iris/tests/results/netcdf/netcdf_monotonic.cml @@ -1,57 +1,57 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/netcdf/netcdf_rotated_xy_land.cml b/lib/iris/tests/results/netcdf/netcdf_rotated_xy_land.cml index 4b432e591a..d975768a15 100644 --- a/lib/iris/tests/results/netcdf/netcdf_rotated_xy_land.cml +++ b/lib/iris/tests/results/netcdf/netcdf_rotated_xy_land.cml @@ -1,6 +1,6 @@ - + @@ -13,12 +13,12 @@ - + - - + 67.5437, 67.3271]]" shape="(95, 85)" standard_name="latitude" units="Unit('degrees')" value_type="float32" var_name="lat"/> - + 57.0309, 57.9421]]" shape="(95, 85)" standard_name="longitude" units="Unit('degrees')" value_type="float32" var_name="lon"/> - + diff --git a/lib/iris/tests/results/netcdf/netcdf_rotated_xyt_precipitation.cml b/lib/iris/tests/results/netcdf/netcdf_rotated_xyt_precipitation.cml index 679d2d1cef..b236a3677d 100644 --- a/lib/iris/tests/results/netcdf/netcdf_rotated_xyt_precipitation.cml +++ b/lib/iris/tests/results/netcdf/netcdf_rotated_xyt_precipitation.cml @@ -1,6 +1,6 @@ - + @@ -11,50 +11,50 @@ - + - + - + 67.2542, 67.1424]]" shape="(190, 174)" standard_name="latitude" units="Unit('degrees')" value_type="float32" var_name="lat"/> - + 58.7689, 59.214]]" shape="(190, 174)" standard_name="longitude" units="Unit('degrees')" value_type="float32" var_name="lon"/> + [2925.5, 2926.5]]" id="2306ff47" long_name="Julian Day" points="[2922.5, 2923.5, 2924.5, 2925.5]" shape="(4,)" standard_name="time" units="Unit('days since 1950-01-01 00:00:00.0', calendar='gregorian')" value_type="float32" var_name="time"/> @@ -62,6 +62,6 @@ - + diff --git a/lib/iris/tests/results/netcdf/netcdf_save_attr.cdl b/lib/iris/tests/results/netcdf/netcdf_save_attr.cdl deleted file mode 100644 index 3fd2570422..0000000000 --- a/lib/iris/tests/results/netcdf/netcdf_save_attr.cdl +++ /dev/null @@ -1,19 +0,0 @@ -dimensions: - dim0 = UNLIMITED ; // (2 currently) - dim1 = 2 ; -variables: - double temp(dim0, dim1) ; - temp:standard_name = "surface_temperature" ; - temp:units = "K" ; - temp:ukmo__um_stash_source = "m01s02i003" ; - temp:flag_masks = "a" ; - temp:flag_meanings = "b" ; - temp:flag_values = "c" ; - temp:standard_error_multiplier = 23L ; - -// global attributes: - :foo = "bar" ; - :history = "A long time ago..." ; - :title = "Attribute test" ; - :Conventions = "CF-1.5" ; -} diff --git a/lib/iris/tests/results/netcdf/netcdf_save_conf_aux.cdl b/lib/iris/tests/results/netcdf/netcdf_save_conf_aux.cdl index 26f746ee10..c331ce9b84 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_conf_aux.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_conf_aux.cdl @@ -1,5 +1,5 @@ dimensions: - dim0 = UNLIMITED ; // (10 currently) + dim0 = 10 ; variables: double temp(dim0) ; temp:standard_name = "air_temperature" ; diff --git a/lib/iris/tests/results/netcdf/netcdf_save_conf_name.cdl b/lib/iris/tests/results/netcdf/netcdf_save_conf_name.cdl index ea01a055a5..2104322bea 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_conf_name.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_conf_name.cdl @@ -1,6 +1,6 @@ dimensions: - dim0 = UNLIMITED ; // (10 currently) - time = UNLIMITED ; // (10 currently) + dim0 = 10 ; + time = 10 ; variables: double temp(time) ; temp:standard_name = "air_temperature" ; diff --git a/lib/iris/tests/results/netcdf/netcdf_save_confl_attr.cdl b/lib/iris/tests/results/netcdf/netcdf_save_confl_attr.cdl index 0295655210..deba7f5ef7 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_confl_attr.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_confl_attr.cdl @@ -1,6 +1,6 @@ dimensions: - dim0 = UNLIMITED ; // (2 currently) - dim0_0 = UNLIMITED ; // (1 currently) + dim0 = 2 ; + dim0_0 = 1 ; dim1 = 2 ; dim2 = 2 ; variables: diff --git a/lib/iris/tests/results/netcdf/netcdf_save_confl_global_attr.cdl b/lib/iris/tests/results/netcdf/netcdf_save_confl_global_attr.cdl index bd957fac4e..e2d41987d9 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_confl_global_attr.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_confl_global_attr.cdl @@ -1,6 +1,6 @@ dimensions: - dim0 = UNLIMITED ; // (2 currently) - dim0_0 = UNLIMITED ; // (1 currently) + dim0 = 2 ; + dim0_0 = 1 ; dim1 = 2 ; dim2 = 2 ; variables: diff --git a/lib/iris/tests/results/netcdf/netcdf_save_gridmapmulti.cdl b/lib/iris/tests/results/netcdf/netcdf_save_gridmapmulti.cdl index b5da925144..ff74fcdd2c 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_gridmapmulti.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_gridmapmulti.cdl @@ -1,10 +1,10 @@ dimensions: - grid_longitude = UNLIMITED ; // (2 currently) - longitude = UNLIMITED ; // (2 currently) - longitude_0 = UNLIMITED ; // (2 currently) grid_latitude = 2 ; + grid_longitude = 2 ; latitude = 2 ; latitude_0 = 2 ; + longitude = 2 ; + longitude_0 = 2 ; variables: int64 air_temperature(longitude, latitude) ; air_temperature:standard_name = "air_temperature" ; @@ -12,8 +12,7 @@ variables: int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; int64 longitude(longitude) ; longitude:axis = "X" ; longitude:units = "degrees_east" ; @@ -30,8 +29,7 @@ variables: int latitude_longitude_0 ; latitude_longitude_0:grid_mapping_name = "latitude_longitude_0" ; latitude_longitude_0:longitude_of_prime_meridian = 0. ; - latitude_longitude_0:semi_major_axis = 6371228. ; - latitude_longitude_0:semi_minor_axis = 6371228. ; + latitude_longitude_0:earth_radius = 6371228. ; int64 longitude_0(longitude_0) ; longitude_0:axis = "X" ; longitude_0:units = "degrees_east" ; diff --git a/lib/iris/tests/results/netcdf/netcdf_save_hybrid_height.cdl b/lib/iris/tests/results/netcdf/netcdf_save_hybrid_height.cdl index dcb506d391..f6dcee0e22 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_hybrid_height.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_hybrid_height.cdl @@ -1,21 +1,20 @@ dimensions: - time = UNLIMITED ; // (6 currently) bnds = 2 ; grid_latitude = 83 ; grid_longitude = 83 ; model_level_number = 10 ; + time = 6 ; variables: float air_potential_temperature(time, model_level_number, grid_latitude, grid_longitude) ; air_potential_temperature:standard_name = "air_potential_temperature" ; air_potential_temperature:units = "K" ; - air_potential_temperature:ukmo__um_stash_source = "m01s00i004" ; + air_potential_temperature:um_stash_source = "m01s00i004" ; air_potential_temperature:grid_mapping = "rotated_latitude_longitude" ; air_potential_temperature:coordinates = "forecast_period forecast_reference_time level_height sigma surface_altitude" ; int rotated_latitude_longitude ; rotated_latitude_longitude:grid_mapping_name = "rotated_latitude_longitude" ; rotated_latitude_longitude:longitude_of_prime_meridian = 0. ; - rotated_latitude_longitude:semi_major_axis = 6371229. ; - rotated_latitude_longitude:semi_minor_axis = 6371229. ; + rotated_latitude_longitude:earth_radius = 6371229. ; rotated_latitude_longitude:grid_north_pole_latitude = 37.5 ; rotated_latitude_longitude:grid_north_pole_longitude = 177.5 ; rotated_latitude_longitude:north_pole_grid_longitude = 0. ; @@ -50,12 +49,12 @@ variables: forecast_reference_time:calendar = "gregorian" ; float level_height(model_level_number) ; level_height:bounds = "level_height_bnds" ; - level_height:axis = "Z" ; - level_height:formula_terms = "a: level_height b: sigma orog: surface_altitude" ; level_height:units = "m" ; - level_height:standard_name = "atmosphere_hybrid_height_coordinate" ; level_height:long_name = "level_height" ; level_height:positive = "up" ; + level_height:standard_name = "atmosphere_hybrid_height_coordinate" ; + level_height:axis = "Z" ; + level_height:formula_terms = "a: level_height b: sigma orog: surface_altitude" ; float level_height_bnds(model_level_number, bnds) ; float sigma(model_level_number) ; sigma:bounds = "sigma_bnds" ; @@ -65,10 +64,12 @@ variables: float surface_altitude(grid_latitude, grid_longitude) ; surface_altitude:units = "m" ; surface_altitude:standard_name = "surface_altitude" ; - surface_altitude:ukmo__um_stash_source = "m01s00i033" ; - surface_altitude:source = "Data from Met Office Unified Model 7.04" ; + surface_altitude:um_stash_source = "m01s00i033" ; + surface_altitude:source = "Data from Met Office Unified Model" ; + surface_altitude:um_version = "7.4" ; // global attributes: - :source = "Data from Met Office Unified Model 7.04" ; + :source = "Data from Met Office Unified Model" ; + :um_version = "7.4" ; :Conventions = "CF-1.5" ; } diff --git a/lib/iris/tests/results/netcdf/netcdf_save_load_hybrid_height.cml b/lib/iris/tests/results/netcdf/netcdf_save_load_hybrid_height.cml index 60497e0457..070e7597d3 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_load_hybrid_height.cml +++ b/lib/iris/tests/results/netcdf/netcdf_save_load_hybrid_height.cml @@ -1,395 +1,396 @@ - + - + + + 476.751, 445.735], + [534.494, 574.562, 720.976, ..., 507.224, + 470.836, 518.705], + [727.317, 800.517, 595.591, ..., 465.849, + 476.977, 486.773], + ..., + [687.474, 753.275, 707.277, ..., 446.561, + 452.217, 488.646], + [567.94, 686.381, 848.409, ..., 461.055, + 455.619, 468.224], + [698.235, 812.745, 675.237, ..., 517.086, + 475.494, 508.362]]]" shape="(10, 83, 83)" standard_name="altitude" units="Unit('m')" value_type="float32"> @@ -405,7 +406,7 @@ [180.0, 233.333], [233.333, 293.333], [293.333, 360.0], - [360.0, 433.333]]" id="1c9102f3" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [360.0, 433.333]]" id="6556fe1e" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0]" shape="(10,)" standard_name="atmosphere_hybrid_height_coordinate" units="Unit('m')" value_type="float32" var_name="level_height"> @@ -413,11 +414,11 @@ - + - + - + @@ -491,35 +492,36 @@ [0.979362, 0.973288], [0.973288, 0.966478], [0.966478, 0.958939], - [0.958939, 0.95068]]" id="273ab6c5" long_name="sigma" points="[0.999424, 0.997504, 0.99482, 0.991375, 0.987171, + [0.958939, 0.95068]]" id="a5c170db" long_name="sigma" points="[0.999424, 0.997504, 0.99482, 0.991375, 0.987171, 0.982215, 0.976512, 0.970069, 0.962893, 0.954993]" shape="(10,)" units="Unit('1')" value_type="float32" var_name="sigma"/> - + 84.2878, 118.704]]" shape="(83, 83)" standard_name="surface_altitude" units="Unit('m')" value_type="float32" var_name="surface_altitude"> - - + + + - - + diff --git a/lib/iris/tests/results/netcdf/netcdf_save_load_ndim_auxiliary.cml b/lib/iris/tests/results/netcdf/netcdf_save_load_ndim_auxiliary.cml index eca2fa8d23..e4f880f4c8 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_load_ndim_auxiliary.cml +++ b/lib/iris/tests/results/netcdf/netcdf_save_load_ndim_auxiliary.cml @@ -1,6 +1,6 @@ - + @@ -11,50 +11,50 @@ - + - + - + 67.2542, 67.1424]]" shape="(190, 174)" standard_name="latitude" units="Unit('degrees')" value_type="float32" var_name="lat"/> - + 58.7689, 59.214]]" shape="(190, 174)" standard_name="longitude" units="Unit('degrees')" value_type="float32" var_name="lon"/> + [2925.5, 2926.5]]" id="2306ff47" long_name="Julian Day" points="[2922.5, 2923.5, 2924.5, 2925.5]" shape="(4,)" standard_name="time" units="Unit('days since 1950-01-01 00:00:00.0', calendar='gregorian')" value_type="float32" var_name="time"/> @@ -62,6 +62,6 @@ - + diff --git a/lib/iris/tests/results/netcdf/netcdf_save_multi_0.cdl b/lib/iris/tests/results/netcdf/netcdf_save_multi_0.cdl index 28761c7096..27cf62a962 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_multi_0.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_multi_0.cdl @@ -1,21 +1,20 @@ dimensions: - time = UNLIMITED ; // (360 currently) bnds = 2 ; latitude = 73 ; longitude = 96 ; + time = 360 ; variables: float air_temperature(time, latitude, longitude) ; air_temperature:standard_name = "air_temperature" ; air_temperature:units = "K" ; - air_temperature:ukmo__um_stash_source = "m01s03i236" ; + air_temperature:um_stash_source = "m01s03i236" ; air_temperature:cell_methods = "time: maximum (interval: 1 hour)" ; air_temperature:grid_mapping = "latitude_longitude" ; air_temperature:coordinates = "forecast_period forecast_reference_time height" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; double time(time) ; time:axis = "T" ; time:bounds = "time_bnds" ; @@ -31,9 +30,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period(time) ; + double forecast_period(time) ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(time, bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/netcdf/netcdf_save_multi_1.cdl b/lib/iris/tests/results/netcdf/netcdf_save_multi_1.cdl index aa77f8c552..7377f94592 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_multi_1.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_multi_1.cdl @@ -1,21 +1,20 @@ dimensions: - time = UNLIMITED ; // (360 currently) bnds = 2 ; latitude = 73 ; longitude = 96 ; + time = 360 ; variables: float air_temperature(time, latitude, longitude) ; air_temperature:standard_name = "air_temperature" ; air_temperature:units = "K" ; - air_temperature:ukmo__um_stash_source = "m01s03i236" ; + air_temperature:um_stash_source = "m01s03i236" ; air_temperature:cell_methods = "time: minimum (interval: 1 hour)" ; air_temperature:grid_mapping = "latitude_longitude" ; air_temperature:coordinates = "forecast_period forecast_reference_time height" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; double time(time) ; time:axis = "T" ; time:bounds = "time_bnds" ; @@ -31,9 +30,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period(time) ; + double forecast_period(time) ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(time, bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/netcdf/netcdf_save_multi_2.cdl b/lib/iris/tests/results/netcdf/netcdf_save_multi_2.cdl index e083b79734..553566355c 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_multi_2.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_multi_2.cdl @@ -1,21 +1,20 @@ dimensions: - time = UNLIMITED ; // (360 currently) bnds = 2 ; latitude = 73 ; longitude = 96 ; + time = 360 ; variables: float precipitation_flux(time, latitude, longitude) ; precipitation_flux:standard_name = "precipitation_flux" ; precipitation_flux:units = "kg m-2 s-1" ; - precipitation_flux:ukmo__um_stash_source = "m01s05i216" ; + precipitation_flux:um_stash_source = "m01s05i216" ; precipitation_flux:cell_methods = "time: mean (interval: 1 hour)" ; precipitation_flux:grid_mapping = "latitude_longitude" ; precipitation_flux:coordinates = "forecast_period forecast_reference_time" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; double time(time) ; time:axis = "T" ; time:bounds = "time_bnds" ; @@ -31,9 +30,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period(time) ; + double forecast_period(time) ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(time, bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/netcdf/netcdf_save_multiple.cdl b/lib/iris/tests/results/netcdf/netcdf_save_multiple.cdl index 9d404c372c..141c1ba5db 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_multiple.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_multiple.cdl @@ -1,21 +1,20 @@ dimensions: - time = UNLIMITED ; // (360 currently) bnds = 2 ; latitude = 73 ; longitude = 96 ; + time = 360 ; variables: float air_temperature(time, latitude, longitude) ; air_temperature:standard_name = "air_temperature" ; air_temperature:units = "K" ; - air_temperature:ukmo__um_stash_source = "m01s03i236" ; + air_temperature:um_stash_source = "m01s03i236" ; air_temperature:cell_methods = "time: maximum (interval: 1 hour)" ; air_temperature:grid_mapping = "latitude_longitude" ; air_temperature:coordinates = "forecast_period forecast_reference_time height" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; double time(time) ; time:axis = "T" ; time:bounds = "time_bnds" ; @@ -31,9 +30,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period(time) ; + double forecast_period(time) ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(time, bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; @@ -45,14 +46,14 @@ variables: float air_temperature_0(time, latitude, longitude) ; air_temperature_0:standard_name = "air_temperature" ; air_temperature_0:units = "K" ; - air_temperature_0:ukmo__um_stash_source = "m01s03i236" ; + air_temperature_0:um_stash_source = "m01s03i236" ; air_temperature_0:cell_methods = "time: minimum (interval: 1 hour)" ; air_temperature_0:grid_mapping = "latitude_longitude" ; air_temperature_0:coordinates = "forecast_period forecast_reference_time height" ; float precipitation_flux(time, latitude, longitude) ; precipitation_flux:standard_name = "precipitation_flux" ; precipitation_flux:units = "kg m-2 s-1" ; - precipitation_flux:ukmo__um_stash_source = "m01s05i216" ; + precipitation_flux:um_stash_source = "m01s05i216" ; precipitation_flux:cell_methods = "time: mean (interval: 1 hour)" ; precipitation_flux:grid_mapping = "latitude_longitude" ; precipitation_flux:coordinates = "forecast_period forecast_reference_time" ; diff --git a/lib/iris/tests/results/netcdf/netcdf_save_ndim_auxiliary.cdl b/lib/iris/tests/results/netcdf/netcdf_save_ndim_auxiliary.cdl index 28350ae4e9..27e4b13e00 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_ndim_auxiliary.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_ndim_auxiliary.cdl @@ -1,8 +1,8 @@ dimensions: - time = UNLIMITED ; // (4 currently) bnds = 2 ; rlat = 190 ; rlon = 174 ; + time = 4 ; variables: float pr(time, rlat, rlon) ; pr:standard_name = "precipitation_flux" ; @@ -35,11 +35,11 @@ variables: rlon:standard_name = "grid_longitude" ; rlon:long_name = "rotated longitude" ; float lat(rlat, rlon) ; - lat:units = "degrees" ; + lat:units = "degrees_north" ; lat:standard_name = "latitude" ; lat:long_name = "latitude" ; float lon(rlat, rlon) ; - lon:units = "degrees" ; + lon:units = "degrees_east" ; lon:standard_name = "longitude" ; lon:long_name = "longitude" ; diff --git a/lib/iris/tests/results/netcdf/netcdf_save_no_global_attr.cdl b/lib/iris/tests/results/netcdf/netcdf_save_no_global_attr.cdl index ca5be25b02..b10abf5a4a 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_no_global_attr.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_no_global_attr.cdl @@ -1,8 +1,8 @@ dimensions: - dim0 = UNLIMITED ; // (2 currently) - dim0_0 = UNLIMITED ; // (1 currently) - dim0_1 = UNLIMITED ; // (10 currently) - dim0_2 = UNLIMITED ; // (20 currently) + dim0 = 2 ; + dim0_0 = 1 ; + dim0_1 = 10 ; + dim0_2 = 20 ; dim1 = 2 ; dim2 = 2 ; variables: diff --git a/lib/iris/tests/results/netcdf/netcdf_save_no_name.cdl b/lib/iris/tests/results/netcdf/netcdf_save_no_name.cdl index 667dc3190b..dd8ee12e6a 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_no_name.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_no_name.cdl @@ -1,5 +1,5 @@ dimensions: - dim0 = UNLIMITED ; // (4 currently) + dim0 = 4 ; dim1 = 5 ; string6 = 6 ; variables: diff --git a/lib/iris/tests/results/netcdf/netcdf_save_nocoord.cdl b/lib/iris/tests/results/netcdf/netcdf_save_nocoord.cdl index 800ec26335..05ad948c52 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_nocoord.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_nocoord.cdl @@ -1,6 +1,6 @@ dimensions: - dim0 = UNLIMITED ; // (2 currently) - dim0_0 = UNLIMITED ; // (1 currently) + dim0 = 2 ; + dim0_0 = 1 ; dim1 = 2 ; dim2 = 2 ; variables: diff --git a/lib/iris/tests/results/netcdf/netcdf_save_realistic_0d.cdl b/lib/iris/tests/results/netcdf/netcdf_save_realistic_0d.cdl index cd85792efa..a5be3b454c 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_realistic_0d.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_realistic_0d.cdl @@ -9,8 +9,7 @@ variables: int rotated_latitude_longitude ; rotated_latitude_longitude:grid_mapping_name = "rotated_latitude_longitude" ; rotated_latitude_longitude:longitude_of_prime_meridian = 0. ; - rotated_latitude_longitude:semi_major_axis = 6371229. ; - rotated_latitude_longitude:semi_minor_axis = 6371229. ; + rotated_latitude_longitude:earth_radius = 6371229. ; rotated_latitude_longitude:grid_north_pole_latitude = 37.5 ; rotated_latitude_longitude:grid_north_pole_longitude = 177.5 ; rotated_latitude_longitude:north_pole_grid_longitude = 0. ; @@ -29,12 +28,12 @@ variables: float grid_longitude_bnds(bnds) ; float level_height ; level_height:bounds = "level_height_bnds" ; - level_height:axis = "Z" ; - level_height:formula_terms = "a: level_height b: sigma orog: surface_altitude" ; level_height:units = "m" ; - level_height:standard_name = "atmosphere_hybrid_height_coordinate" ; level_height:long_name = "level_height" ; level_height:positive = "up" ; + level_height:standard_name = "atmosphere_hybrid_height_coordinate" ; + level_height:axis = "Z" ; + level_height:formula_terms = "a: level_height b: sigma orog: surface_altitude" ; float level_height_bnds(bnds) ; int model_level_number ; model_level_number:units = "1" ; diff --git a/lib/iris/tests/results/netcdf/netcdf_save_realistic_4d.cdl b/lib/iris/tests/results/netcdf/netcdf_save_realistic_4d.cdl index a52ea73465..f30eb67952 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_realistic_4d.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_realistic_4d.cdl @@ -1,9 +1,9 @@ dimensions: - time = UNLIMITED ; // (6 currently) bnds = 2 ; grid_latitude = 100 ; grid_longitude = 100 ; model_level_number = 70 ; + time = 6 ; variables: float air_potential_temperature(time, model_level_number, grid_latitude, grid_longitude) ; air_potential_temperature:standard_name = "air_potential_temperature" ; @@ -13,8 +13,7 @@ variables: int rotated_latitude_longitude ; rotated_latitude_longitude:grid_mapping_name = "rotated_latitude_longitude" ; rotated_latitude_longitude:longitude_of_prime_meridian = 0. ; - rotated_latitude_longitude:semi_major_axis = 6371229. ; - rotated_latitude_longitude:semi_minor_axis = 6371229. ; + rotated_latitude_longitude:earth_radius = 6371229. ; rotated_latitude_longitude:grid_north_pole_latitude = 37.5 ; rotated_latitude_longitude:grid_north_pole_longitude = 177.5 ; rotated_latitude_longitude:north_pole_grid_longitude = 0. ; @@ -45,12 +44,12 @@ variables: forecast_period:standard_name = "forecast_period" ; float level_height(model_level_number) ; level_height:bounds = "level_height_bnds" ; - level_height:axis = "Z" ; - level_height:formula_terms = "a: level_height b: sigma orog: surface_altitude" ; level_height:units = "m" ; - level_height:standard_name = "atmosphere_hybrid_height_coordinate" ; level_height:long_name = "level_height" ; level_height:positive = "up" ; + level_height:standard_name = "atmosphere_hybrid_height_coordinate" ; + level_height:axis = "Z" ; + level_height:formula_terms = "a: level_height b: sigma orog: surface_altitude" ; float level_height_bnds(model_level_number, bnds) ; float sigma(model_level_number) ; sigma:bounds = "sigma_bnds" ; diff --git a/lib/iris/tests/results/netcdf/netcdf_save_realistic_4d_no_hybrid.cdl b/lib/iris/tests/results/netcdf/netcdf_save_realistic_4d_no_hybrid.cdl index c66784db31..a061484318 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_realistic_4d_no_hybrid.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_realistic_4d_no_hybrid.cdl @@ -1,9 +1,9 @@ dimensions: - time = UNLIMITED ; // (6 currently) bnds = 2 ; grid_latitude = 100 ; grid_longitude = 100 ; model_level_number = 70 ; + time = 6 ; variables: float air_potential_temperature(time, model_level_number, grid_latitude, grid_longitude) ; air_potential_temperature:standard_name = "air_potential_temperature" ; @@ -13,8 +13,7 @@ variables: int rotated_latitude_longitude ; rotated_latitude_longitude:grid_mapping_name = "rotated_latitude_longitude" ; rotated_latitude_longitude:longitude_of_prime_meridian = 0. ; - rotated_latitude_longitude:semi_major_axis = 6371229. ; - rotated_latitude_longitude:semi_minor_axis = 6371229. ; + rotated_latitude_longitude:earth_radius = 6371229. ; rotated_latitude_longitude:grid_north_pole_latitude = 37.5 ; rotated_latitude_longitude:grid_north_pole_longitude = 177.5 ; rotated_latitude_longitude:north_pole_grid_longitude = 0. ; diff --git a/lib/iris/tests/results/netcdf/netcdf_save_samedimcoord.cdl b/lib/iris/tests/results/netcdf/netcdf_save_samedimcoord.cdl index 2090ccd732..2b40c45b3a 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_samedimcoord.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_samedimcoord.cdl @@ -1,6 +1,6 @@ dimensions: - time = UNLIMITED ; // (10 currently) - time_0 = UNLIMITED ; // (20 currently) + time = 10 ; + time_0 = 20 ; variables: double temp(time) ; temp:standard_name = "air_temperature" ; diff --git a/lib/iris/tests/results/netcdf/netcdf_save_samevar.cdl b/lib/iris/tests/results/netcdf/netcdf_save_samevar.cdl index 73815db12b..e7b2115ca8 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_samevar.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_samevar.cdl @@ -1,6 +1,6 @@ dimensions: - dim0 = UNLIMITED ; // (2 currently) - dim0_0 = UNLIMITED ; // (1 currently) + dim0 = 2 ; + dim0_0 = 1 ; dim1 = 2 ; dim2 = 2 ; variables: diff --git a/lib/iris/tests/results/netcdf/netcdf_save_single.cdl b/lib/iris/tests/results/netcdf/netcdf_save_single.cdl index 15c37e5094..5edaf8bfde 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_single.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_single.cdl @@ -1,20 +1,19 @@ dimensions: - latitude = UNLIMITED ; // (73 currently) bnds = 2 ; + latitude = 73 ; longitude = 96 ; variables: float air_temperature(latitude, longitude) ; air_temperature:standard_name = "air_temperature" ; air_temperature:units = "K" ; - air_temperature:ukmo__um_stash_source = "m01s03i236" ; + air_temperature:um_stash_source = "m01s03i236" ; air_temperature:cell_methods = "time: mean (interval: 6 hour)" ; air_temperature:grid_mapping = "latitude_longitude" ; air_temperature:coordinates = "forecast_period forecast_reference_time height time" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; float latitude(latitude) ; latitude:axis = "Y" ; latitude:units = "degrees_north" ; @@ -23,9 +22,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period ; + double forecast_period ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/netcdf/netcdf_save_wcoord.cdl b/lib/iris/tests/results/netcdf/netcdf_save_wcoord.cdl index 611ad26bbf..d0f8844199 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_wcoord.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_wcoord.cdl @@ -1,14 +1,14 @@ dimensions: - dim0 = UNLIMITED ; // (1 currently) - lon = UNLIMITED ; // (2 currently) + dim0 = 1 ; lat = 2 ; + lon = 2 ; variables: double temp(lon, lat) ; temp:standard_name = "surface_temperature" ; temp:units = "K" ; int64 lon(lon) ; lon:axis = "X" ; - lon:units = "degree_east" ; + lon:units = "degrees_east" ; lon:standard_name = "longitude" ; int64 lat(lat) ; lat:units = "degree_north" ; diff --git a/lib/iris/tests/results/netcdf/netcdf_stereo.cml b/lib/iris/tests/results/netcdf/netcdf_stereo.cml new file mode 100644 index 0000000000..b07304cd62 --- /dev/null +++ b/lib/iris/tests/results/netcdf/netcdf_stereo.cml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/netcdf/netcdf_tmerc_and_climatology.cml b/lib/iris/tests/results/netcdf/netcdf_tmerc_and_climatology.cml index baebec01d9..2776b2018c 100644 --- a/lib/iris/tests/results/netcdf/netcdf_tmerc_and_climatology.cml +++ b/lib/iris/tests/results/netcdf/netcdf_tmerc_and_climatology.cml @@ -1,6 +1,6 @@ - + @@ -11,68 +11,68 @@ - + ..., 48.0579386958, 48.055666981, 48.0533563384]]" shape="(290, 180)" standard_name="latitude" units="Unit('degrees')" value_type="float64" var_name="lat"/> - + ..., 1.85911871182, 1.92607194716, + 1.99301683617]]" shape="(290, 180)" standard_name="longitude" units="Unit('degrees')" value_type="float64" var_name="lon"/> - - - + - + - + - + diff --git a/lib/iris/tests/results/netcdf/netcdf_units_0.cml b/lib/iris/tests/results/netcdf/netcdf_units_0.cml index b6e5d5c911..b153daba76 100644 --- a/lib/iris/tests/results/netcdf/netcdf_units_0.cml +++ b/lib/iris/tests/results/netcdf/netcdf_units_0.cml @@ -1,12 +1,12 @@ - + - + - + @@ -14,6 +14,6 @@ - + diff --git a/lib/iris/tests/results/netcdf/netcdf_units_1.cml b/lib/iris/tests/results/netcdf/netcdf_units_1.cml index 1a1b5cbcd5..b3d742262c 100644 --- a/lib/iris/tests/results/netcdf/netcdf_units_1.cml +++ b/lib/iris/tests/results/netcdf/netcdf_units_1.cml @@ -1,15 +1,15 @@ - + - + - + @@ -17,6 +17,6 @@ - + diff --git a/lib/iris/tests/results/netcdf/save_load_traj.cml b/lib/iris/tests/results/netcdf/save_load_traj.cml index 60a0179cc5..44cbc28513 100644 --- a/lib/iris/tests/results/netcdf/save_load_traj.cml +++ b/lib/iris/tests/results/netcdf/save_load_traj.cml @@ -1,6 +1,6 @@ - + @@ -8,31 +8,34 @@ - + - + - - - + - + - + + + + - + diff --git a/lib/iris/tests/results/netcdf/uint32_auxiliary_coord_netcdf3.cml b/lib/iris/tests/results/netcdf/uint32_auxiliary_coord_netcdf3.cml index b72412f660..0a28f4fb7e 100644 --- a/lib/iris/tests/results/netcdf/uint32_auxiliary_coord_netcdf3.cml +++ b/lib/iris/tests/results/netcdf/uint32_auxiliary_coord_netcdf3.cml @@ -1,12 +1,12 @@ - + - + diff --git a/lib/iris/tests/results/netcdf/uint32_data_netcdf3.cml b/lib/iris/tests/results/netcdf/uint32_data_netcdf3.cml index cafafcf39c..608769f4c3 100644 --- a/lib/iris/tests/results/netcdf/uint32_data_netcdf3.cml +++ b/lib/iris/tests/results/netcdf/uint32_data_netcdf3.cml @@ -1,11 +1,11 @@ - + - + diff --git a/lib/iris/tests/results/netcdf/uint32_dimension_coord_netcdf3.cml b/lib/iris/tests/results/netcdf/uint32_dimension_coord_netcdf3.cml index 401be5df65..5c523ac16b 100644 --- a/lib/iris/tests/results/netcdf/uint32_dimension_coord_netcdf3.cml +++ b/lib/iris/tests/results/netcdf/uint32_dimension_coord_netcdf3.cml @@ -1,12 +1,12 @@ - + - + diff --git a/lib/iris/tests/results/nimrod/levels_below_ground.cml b/lib/iris/tests/results/nimrod/levels_below_ground.cml index 655cc49589..22d2168578 100644 --- a/lib/iris/tests/results/nimrod/levels_below_ground.cml +++ b/lib/iris/tests/results/nimrod/levels_below_ground.cml @@ -1,9 +1,9 @@ - + - + @@ -11,6 +11,6 @@ - + diff --git a/lib/iris/tests/results/nimrod/load_2flds.cml b/lib/iris/tests/results/nimrod/load_2flds.cml index 427f66d785..d57761e235 100644 --- a/lib/iris/tests/results/nimrod/load_2flds.cml +++ b/lib/iris/tests/results/nimrod/load_2flds.cml @@ -1,6 +1,6 @@ - + @@ -10,32 +10,32 @@ - + - + - - - + - + diff --git a/lib/iris/tests/results/nimrod/mockography.cml b/lib/iris/tests/results/nimrod/mockography.cml index 726793f2eb..6e63d9fa87 100644 --- a/lib/iris/tests/results/nimrod/mockography.cml +++ b/lib/iris/tests/results/nimrod/mockography.cml @@ -1,12 +1,12 @@ - + - + diff --git a/lib/iris/tests/results/nimrod/period_of_interest.cml b/lib/iris/tests/results/nimrod/period_of_interest.cml index ef75398ff3..ef0f33649e 100644 --- a/lib/iris/tests/results/nimrod/period_of_interest.cml +++ b/lib/iris/tests/results/nimrod/period_of_interest.cml @@ -1,12 +1,12 @@ - + - + - + diff --git a/lib/iris/tests/results/pandas/as_cube/data_frame_datetime_gregorian.cml b/lib/iris/tests/results/pandas/as_cube/data_frame_datetime_gregorian.cml index aacf551a66..12124cc308 100644 --- a/lib/iris/tests/results/pandas/as_cube/data_frame_datetime_gregorian.cml +++ b/lib/iris/tests/results/pandas/as_cube/data_frame_datetime_gregorian.cml @@ -1,15 +1,15 @@ - + - + - + - + diff --git a/lib/iris/tests/results/pandas/as_cube/data_frame_masked.cml b/lib/iris/tests/results/pandas/as_cube/data_frame_masked.cml index 19f1db4d54..7100506c3d 100644 --- a/lib/iris/tests/results/pandas/as_cube/data_frame_masked.cml +++ b/lib/iris/tests/results/pandas/as_cube/data_frame_masked.cml @@ -1,15 +1,15 @@ - + - + - + - + diff --git a/lib/iris/tests/results/pandas/as_cube/data_frame_multidim.cml b/lib/iris/tests/results/pandas/as_cube/data_frame_multidim.cml new file mode 100644 index 0000000000..d377fa72d8 --- /dev/null +++ b/lib/iris/tests/results/pandas/as_cube/data_frame_multidim.cml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/pandas/as_cube/data_frame_netcdftime_360.cml b/lib/iris/tests/results/pandas/as_cube/data_frame_netcdftime_360.cml index be0f966f5f..39bc96f8e3 100644 --- a/lib/iris/tests/results/pandas/as_cube/data_frame_netcdftime_360.cml +++ b/lib/iris/tests/results/pandas/as_cube/data_frame_netcdftime_360.cml @@ -1,15 +1,15 @@ - + - + - + - + diff --git a/lib/iris/tests/results/pandas/as_cube/data_frame_nonotonic.cml b/lib/iris/tests/results/pandas/as_cube/data_frame_nonotonic.cml index 64764ec99e..7eb4e4ed3d 100644 --- a/lib/iris/tests/results/pandas/as_cube/data_frame_nonotonic.cml +++ b/lib/iris/tests/results/pandas/as_cube/data_frame_nonotonic.cml @@ -1,15 +1,15 @@ - + - + - + - + diff --git a/lib/iris/tests/results/pandas/as_cube/data_frame_simple.cml b/lib/iris/tests/results/pandas/as_cube/data_frame_simple.cml index 958a1791b3..066edd7c58 100644 --- a/lib/iris/tests/results/pandas/as_cube/data_frame_simple.cml +++ b/lib/iris/tests/results/pandas/as_cube/data_frame_simple.cml @@ -1,15 +1,15 @@ - + - + - + - + diff --git a/lib/iris/tests/results/pandas/as_cube/series_datetime_gregorian.cml b/lib/iris/tests/results/pandas/as_cube/series_datetime_gregorian.cml index afbc7a79e0..7e2e6f4166 100644 --- a/lib/iris/tests/results/pandas/as_cube/series_datetime_gregorian.cml +++ b/lib/iris/tests/results/pandas/as_cube/series_datetime_gregorian.cml @@ -1,13 +1,13 @@ - + - - + diff --git a/lib/iris/tests/results/pandas/as_cube/series_masked.cml b/lib/iris/tests/results/pandas/as_cube/series_masked.cml index c79b8b7325..99b94c32b6 100644 --- a/lib/iris/tests/results/pandas/as_cube/series_masked.cml +++ b/lib/iris/tests/results/pandas/as_cube/series_masked.cml @@ -1,12 +1,12 @@ - + - + - + diff --git a/lib/iris/tests/results/pandas/as_cube/series_netcdfimte_360.cml b/lib/iris/tests/results/pandas/as_cube/series_netcdfimte_360.cml index 2a4923f8f3..0d9c4e149e 100644 --- a/lib/iris/tests/results/pandas/as_cube/series_netcdfimte_360.cml +++ b/lib/iris/tests/results/pandas/as_cube/series_netcdfimte_360.cml @@ -1,13 +1,13 @@ - + - - + diff --git a/lib/iris/tests/results/pandas/as_cube/series_object.cml b/lib/iris/tests/results/pandas/as_cube/series_object.cml index 8bbf64e424..1e230bbcfe 100644 --- a/lib/iris/tests/results/pandas/as_cube/series_object.cml +++ b/lib/iris/tests/results/pandas/as_cube/series_object.cml @@ -1,12 +1,12 @@ - + - + - + diff --git a/lib/iris/tests/results/pandas/as_cube/series_simple.cml b/lib/iris/tests/results/pandas/as_cube/series_simple.cml index 1956c84aba..f71fd2d6c7 100644 --- a/lib/iris/tests/results/pandas/as_cube/series_simple.cml +++ b/lib/iris/tests/results/pandas/as_cube/series_simple.cml @@ -1,12 +1,12 @@ - + - + - + diff --git a/lib/iris/tests/results/pandas/as_dataframe/masked.txt b/lib/iris/tests/results/pandas/as_dataframe/masked.txt deleted file mode 100644 index eef6a59bba..0000000000 --- a/lib/iris/tests/results/pandas/as_dataframe/masked.txt +++ /dev/null @@ -1,3 +0,0 @@ - 0 1 2 3 4 -0 0 NaN 2 NaN 4.4 -1 NaN 6 NaN 8 NaN \ No newline at end of file diff --git a/lib/iris/tests/results/pandas/as_dataframe/no_dim_coords.txt b/lib/iris/tests/results/pandas/as_dataframe/no_dim_coords.txt deleted file mode 100644 index 9df2d6bef6..0000000000 --- a/lib/iris/tests/results/pandas/as_dataframe/no_dim_coords.txt +++ /dev/null @@ -1,3 +0,0 @@ - 0 1 2 3 4 -0 0 1 2 3 4 -1 5 6 7 8 9 \ No newline at end of file diff --git a/lib/iris/tests/results/pandas/as_dataframe/no_x_coord.txt b/lib/iris/tests/results/pandas/as_dataframe/no_x_coord.txt deleted file mode 100644 index 8ae4d22c74..0000000000 --- a/lib/iris/tests/results/pandas/as_dataframe/no_x_coord.txt +++ /dev/null @@ -1,3 +0,0 @@ - 0 1 2 3 4 -10 0 1 2 3 4 -11 5 6 7 8 9 \ No newline at end of file diff --git a/lib/iris/tests/results/pandas/as_dataframe/no_y_coord.txt b/lib/iris/tests/results/pandas/as_dataframe/no_y_coord.txt deleted file mode 100644 index 5ec6a46d88..0000000000 --- a/lib/iris/tests/results/pandas/as_dataframe/no_y_coord.txt +++ /dev/null @@ -1,3 +0,0 @@ - 10 11 12 13 14 -0 0 1 2 3 4 -1 5 6 7 8 9 \ No newline at end of file diff --git a/lib/iris/tests/results/pandas/as_dataframe/simple.txt b/lib/iris/tests/results/pandas/as_dataframe/simple.txt deleted file mode 100644 index 0d7e236b90..0000000000 --- a/lib/iris/tests/results/pandas/as_dataframe/simple.txt +++ /dev/null @@ -1,3 +0,0 @@ - 10 11 12 13 14 -15 0 1 2 3 4 -16 5 6 7 8 9 \ No newline at end of file diff --git a/lib/iris/tests/results/pandas/as_dataframe/time_360.txt b/lib/iris/tests/results/pandas/as_dataframe/time_360.txt deleted file mode 100644 index c512d2b197..0000000000 --- a/lib/iris/tests/results/pandas/as_dataframe/time_360.txt +++ /dev/null @@ -1,3 +0,0 @@ - 0 1 2 3 4 -2000-04-11 02:24:00 0 1 2 3 4 -2000-07-21 04:48:00 5 6 7 8 9 \ No newline at end of file diff --git a/lib/iris/tests/results/pandas/as_series/masked.txt b/lib/iris/tests/results/pandas/as_series/masked.txt deleted file mode 100644 index a532cd7a96..0000000000 --- a/lib/iris/tests/results/pandas/as_series/masked.txt +++ /dev/null @@ -1,6 +0,0 @@ -0 0.0 -1 NaN -2 2.0 -3 NaN -4 4.4 -dtype: float32 \ No newline at end of file diff --git a/lib/iris/tests/results/pandas/as_series/no_dim_coord.txt b/lib/iris/tests/results/pandas/as_series/no_dim_coord.txt deleted file mode 100644 index 6c47690704..0000000000 --- a/lib/iris/tests/results/pandas/as_series/no_dim_coord.txt +++ /dev/null @@ -1,6 +0,0 @@ -0 0 -1 1 -2 2 -3 3 -4 4 -dtype: int64 \ No newline at end of file diff --git a/lib/iris/tests/results/pandas/as_series/simple.txt b/lib/iris/tests/results/pandas/as_series/simple.txt deleted file mode 100644 index 9d9415cdb0..0000000000 --- a/lib/iris/tests/results/pandas/as_series/simple.txt +++ /dev/null @@ -1,6 +0,0 @@ -5 0.0 -6 1.0 -7 2.0 -8 3.0 -9 4.4 -dtype: float64 \ No newline at end of file diff --git a/lib/iris/tests/results/pandas/as_series/time_360.txt b/lib/iris/tests/results/pandas/as_series/time_360.txt deleted file mode 100644 index fd90458506..0000000000 --- a/lib/iris/tests/results/pandas/as_series/time_360.txt +++ /dev/null @@ -1,6 +0,0 @@ -2000-01-01 00:00:00 0 -2000-04-11 02:24:00 1 -2000-07-21 04:48:00 2 -2000-11-01 07:12:00 3 -2001-02-11 09:36:00 4 -dtype: int64 \ No newline at end of file diff --git a/lib/iris/tests/results/pandas/as_series/time_gregorian.txt b/lib/iris/tests/results/pandas/as_series/time_gregorian.txt deleted file mode 100644 index 6dcd4ea105..0000000000 --- a/lib/iris/tests/results/pandas/as_series/time_gregorian.txt +++ /dev/null @@ -1,6 +0,0 @@ -2000-01-01 00:00:00 0 -2000-04-10 02:24:00 1 -2000-07-19 04:48:00 2 -2000-10-27 07:12:00 3 -2001-02-04 09:36:00 4 -dtype: int64 \ No newline at end of file diff --git a/lib/iris/tests/results/pp_rules/global.cml b/lib/iris/tests/results/pp_load_rules/global.cml similarity index 77% rename from lib/iris/tests/results/pp_rules/global.cml rename to lib/iris/tests/results/pp_load_rules/global.cml index 848d989e83..2df84a8606 100644 --- a/lib/iris/tests/results/pp_rules/global.cml +++ b/lib/iris/tests/results/pp_load_rules/global.cml @@ -1,19 +1,19 @@ - + - + - + - - + - + - + - + diff --git a/lib/iris/tests/results/pp_load_rules/lbproc_mean_max_min.cml b/lib/iris/tests/results/pp_load_rules/lbproc_mean_max_min.cml new file mode 100644 index 0000000000..9e4b6d31f5 --- /dev/null +++ b/lib/iris/tests/results/pp_load_rules/lbproc_mean_max_min.cml @@ -0,0 +1,199 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/pp_rules/lbtim_2.cml b/lib/iris/tests/results/pp_load_rules/lbtim_2.cml similarity index 80% rename from lib/iris/tests/results/pp_rules/lbtim_2.cml rename to lib/iris/tests/results/pp_load_rules/lbtim_2.cml index 2318a5f3bc..8ce7dd472c 100644 --- a/lib/iris/tests/results/pp_rules/lbtim_2.cml +++ b/lib/iris/tests/results/pp_load_rules/lbtim_2.cml @@ -1,13 +1,13 @@ - + - - + - + - @@ -40,6 +40,6 @@ - + diff --git a/lib/iris/tests/results/pp_load_rules/ocean_depth.cml b/lib/iris/tests/results/pp_load_rules/ocean_depth.cml new file mode 100644 index 0000000000..9c33acdac4 --- /dev/null +++ b/lib/iris/tests/results/pp_load_rules/ocean_depth.cml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/pp_load_rules/ocean_depth_bounded.cml b/lib/iris/tests/results/pp_load_rules/ocean_depth_bounded.cml new file mode 100644 index 0000000000..5a959ad027 --- /dev/null +++ b/lib/iris/tests/results/pp_load_rules/ocean_depth_bounded.cml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/pp_load_rules/rotated_uk.cml b/lib/iris/tests/results/pp_load_rules/rotated_uk.cml new file mode 100644 index 0000000000..51b4682ebf --- /dev/null +++ b/lib/iris/tests/results/pp_load_rules/rotated_uk.cml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/pp_rules/invalid_units.cml b/lib/iris/tests/results/pp_rules/invalid_units.cml deleted file mode 100644 index f1f041c78a..0000000000 --- a/lib/iris/tests/results/pp_rules/invalid_units.cml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/pp_rules/lbproc_mean_max_min.cml b/lib/iris/tests/results/pp_rules/lbproc_mean_max_min.cml deleted file mode 100644 index 79d5ddcf70..0000000000 --- a/lib/iris/tests/results/pp_rules/lbproc_mean_max_min.cml +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/pp_rules/ocean_depth.cml b/lib/iris/tests/results/pp_rules/ocean_depth.cml deleted file mode 100644 index 84e5c64d75..0000000000 --- a/lib/iris/tests/results/pp_rules/ocean_depth.cml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/pp_rules/ocean_depth_bounded.cml b/lib/iris/tests/results/pp_rules/ocean_depth_bounded.cml deleted file mode 100644 index e8fe93bf65..0000000000 --- a/lib/iris/tests/results/pp_rules/ocean_depth_bounded.cml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/pp_rules/rotated_uk.cml b/lib/iris/tests/results/pp_rules/rotated_uk.cml deleted file mode 100644 index 31985d1f4e..0000000000 --- a/lib/iris/tests/results/pp_rules/rotated_uk.cml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/regrid/airpress_on_theta_0d.cml b/lib/iris/tests/results/regrid/airpress_on_theta_0d.cml deleted file mode 100644 index 6e1b80d9fe..0000000000 --- a/lib/iris/tests/results/regrid/airpress_on_theta_0d.cml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/regrid/airpress_on_theta_0d.data.0.json b/lib/iris/tests/results/regrid/airpress_on_theta_0d.data.0.json new file mode 100644 index 0000000000..bb55e1e464 --- /dev/null +++ b/lib/iris/tests/results/regrid/airpress_on_theta_0d.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 102192.140625, "max": 102192.140625, "shape": [], "masked": false, "mean": 102192.140625} \ No newline at end of file diff --git a/lib/iris/tests/results/regrid/airpress_on_theta_0d.data.0.npy b/lib/iris/tests/results/regrid/airpress_on_theta_0d.data.0.npy deleted file mode 100644 index 65c50e6291..0000000000 Binary files a/lib/iris/tests/results/regrid/airpress_on_theta_0d.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/regrid/airpress_on_theta_1d.cml b/lib/iris/tests/results/regrid/airpress_on_theta_1d.cml deleted file mode 100644 index 88b821fceb..0000000000 --- a/lib/iris/tests/results/regrid/airpress_on_theta_1d.cml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/regrid/airpress_on_theta_1d.data.0.json b/lib/iris/tests/results/regrid/airpress_on_theta_1d.data.0.json new file mode 100644 index 0000000000..40af5a5f32 --- /dev/null +++ b/lib/iris/tests/results/regrid/airpress_on_theta_1d.data.0.json @@ -0,0 +1 @@ +{"std": 185.38343811035156, "min": 99609.65625, "max": 100038.796875, "shape": [3], "masked": false, "mean": 99781.375} \ No newline at end of file diff --git a/lib/iris/tests/results/regrid/airpress_on_theta_1d.data.0.npy b/lib/iris/tests/results/regrid/airpress_on_theta_1d.data.0.npy deleted file mode 100644 index 6a43c17532..0000000000 Binary files a/lib/iris/tests/results/regrid/airpress_on_theta_1d.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/regrid/airpress_on_theta_2d.cml b/lib/iris/tests/results/regrid/airpress_on_theta_2d.cml deleted file mode 100644 index b0ceaac0d1..0000000000 --- a/lib/iris/tests/results/regrid/airpress_on_theta_2d.cml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/regrid/airpress_on_theta_2d.data.0.json b/lib/iris/tests/results/regrid/airpress_on_theta_2d.data.0.json new file mode 100644 index 0000000000..5b4f8a1724 --- /dev/null +++ b/lib/iris/tests/results/regrid/airpress_on_theta_2d.data.0.json @@ -0,0 +1 @@ +{"std": 1048.704345703125, "min": 98272.953125, "max": 101113.84375, "shape": [2, 3], "masked": false, "mean": 99580.7421875} \ No newline at end of file diff --git a/lib/iris/tests/results/regrid/airpress_on_theta_2d.data.0.npy b/lib/iris/tests/results/regrid/airpress_on_theta_2d.data.0.npy deleted file mode 100644 index 4e97ddb5fd..0000000000 Binary files a/lib/iris/tests/results/regrid/airpress_on_theta_2d.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/regrid/airpress_on_theta_3d.cml b/lib/iris/tests/results/regrid/airpress_on_theta_3d.cml deleted file mode 100644 index c0626e755f..0000000000 --- a/lib/iris/tests/results/regrid/airpress_on_theta_3d.cml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/regrid/airpress_on_theta_3d.data.0.json b/lib/iris/tests/results/regrid/airpress_on_theta_3d.data.0.json new file mode 100644 index 0000000000..59f6885bf3 --- /dev/null +++ b/lib/iris/tests/results/regrid/airpress_on_theta_3d.data.0.json @@ -0,0 +1 @@ +{"std": 1126.344970703125, "min": 97080.71875, "max": 101113.84375, "shape": [5, 2, 3], "masked": false, "mean": 99043.671875} \ No newline at end of file diff --git a/lib/iris/tests/results/regrid/airpress_on_theta_3d.data.0.npy b/lib/iris/tests/results/regrid/airpress_on_theta_3d.data.0.npy deleted file mode 100644 index 4458cf2bf4..0000000000 Binary files a/lib/iris/tests/results/regrid/airpress_on_theta_3d.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/regrid/bilinear_larger.cml b/lib/iris/tests/results/regrid/bilinear_larger.cml deleted file mode 100644 index 2c45207b48..0000000000 --- a/lib/iris/tests/results/regrid/bilinear_larger.cml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/regrid/bilinear_larger.data.0.json b/lib/iris/tests/results/regrid/bilinear_larger.data.0.json new file mode 100644 index 0000000000..ed0557ad4f --- /dev/null +++ b/lib/iris/tests/results/regrid/bilinear_larger.data.0.json @@ -0,0 +1 @@ +{"std": 4.6904158592224121, "min": -2.5, "max": 13.5, "shape": [4, 5], "masked": false, "mean": 5.5} \ No newline at end of file diff --git a/lib/iris/tests/results/regrid/bilinear_larger.data.0.npy b/lib/iris/tests/results/regrid/bilinear_larger.data.0.npy deleted file mode 100644 index fc2e56a782..0000000000 Binary files a/lib/iris/tests/results/regrid/bilinear_larger.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/regrid/bilinear_larger_lon_extrapolate_left.cml b/lib/iris/tests/results/regrid/bilinear_larger_lon_extrapolate_left.cml deleted file mode 100644 index 7623c342f2..0000000000 --- a/lib/iris/tests/results/regrid/bilinear_larger_lon_extrapolate_left.cml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/regrid/bilinear_larger_lon_extrapolate_left.data.0.json b/lib/iris/tests/results/regrid/bilinear_larger_lon_extrapolate_left.data.0.json new file mode 100644 index 0000000000..ec738b52bd --- /dev/null +++ b/lib/iris/tests/results/regrid/bilinear_larger_lon_extrapolate_left.data.0.json @@ -0,0 +1 @@ +{"std": 4.6518816947937012, "min": -2.5, "max": 13.0, "shape": [4, 5], "masked": false, "mean": 5.0999999046325684} \ No newline at end of file diff --git a/lib/iris/tests/results/regrid/bilinear_larger_lon_extrapolate_left.data.0.npy b/lib/iris/tests/results/regrid/bilinear_larger_lon_extrapolate_left.data.0.npy deleted file mode 100644 index 9b43cb98e8..0000000000 Binary files a/lib/iris/tests/results/regrid/bilinear_larger_lon_extrapolate_left.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/regrid/bilinear_larger_lon_extrapolate_right.cml b/lib/iris/tests/results/regrid/bilinear_larger_lon_extrapolate_right.cml deleted file mode 100644 index 3e1b3638c8..0000000000 --- a/lib/iris/tests/results/regrid/bilinear_larger_lon_extrapolate_right.cml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/regrid/bilinear_larger_lon_extrapolate_right.data.0.json b/lib/iris/tests/results/regrid/bilinear_larger_lon_extrapolate_right.data.0.json new file mode 100644 index 0000000000..ca948c42df --- /dev/null +++ b/lib/iris/tests/results/regrid/bilinear_larger_lon_extrapolate_right.data.0.json @@ -0,0 +1 @@ +{"std": 4.6518816947937012, "min": -2.0, "max": 13.5, "shape": [4, 5], "masked": false, "mean": 5.9000000953674316} \ No newline at end of file diff --git a/lib/iris/tests/results/regrid/bilinear_larger_lon_extrapolate_right.data.0.npy b/lib/iris/tests/results/regrid/bilinear_larger_lon_extrapolate_right.data.0.npy deleted file mode 100644 index 65e3a181d4..0000000000 Binary files a/lib/iris/tests/results/regrid/bilinear_larger_lon_extrapolate_right.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/regrid/bilinear_smaller.cml b/lib/iris/tests/results/regrid/bilinear_smaller.cml deleted file mode 100644 index 1723b606b0..0000000000 --- a/lib/iris/tests/results/regrid/bilinear_smaller.cml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/regrid/bilinear_smaller.data.0.json b/lib/iris/tests/results/regrid/bilinear_smaller.data.0.json new file mode 100644 index 0000000000..e3adacb147 --- /dev/null +++ b/lib/iris/tests/results/regrid/bilinear_smaller.data.0.json @@ -0,0 +1 @@ +{"std": 2.1602468490600586, "min": 2.5, "max": 8.5, "shape": [2, 3], "masked": false, "mean": 5.5} \ No newline at end of file diff --git a/lib/iris/tests/results/regrid/bilinear_smaller.data.0.npy b/lib/iris/tests/results/regrid/bilinear_smaller.data.0.npy deleted file mode 100644 index 8d2eea8c73..0000000000 Binary files a/lib/iris/tests/results/regrid/bilinear_smaller.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/regrid/bilinear_smaller_lon_align_left.cml b/lib/iris/tests/results/regrid/bilinear_smaller_lon_align_left.cml deleted file mode 100644 index e666318cc5..0000000000 --- a/lib/iris/tests/results/regrid/bilinear_smaller_lon_align_left.cml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/regrid/bilinear_smaller_lon_align_left.data.0.json b/lib/iris/tests/results/regrid/bilinear_smaller_lon_align_left.data.0.json new file mode 100644 index 0000000000..b60594f0a5 --- /dev/null +++ b/lib/iris/tests/results/regrid/bilinear_smaller_lon_align_left.data.0.json @@ -0,0 +1 @@ +{"std": 2.1602468490600586, "min": 2.0, "max": 8.0, "shape": [2, 3], "masked": false, "mean": 5.0} \ No newline at end of file diff --git a/lib/iris/tests/results/regrid/bilinear_smaller_lon_align_left.data.0.npy b/lib/iris/tests/results/regrid/bilinear_smaller_lon_align_left.data.0.npy deleted file mode 100644 index a105d6bcb0..0000000000 Binary files a/lib/iris/tests/results/regrid/bilinear_smaller_lon_align_left.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/regrid/bilinear_smaller_lon_align_right.cml b/lib/iris/tests/results/regrid/bilinear_smaller_lon_align_right.cml deleted file mode 100644 index 9b9820a951..0000000000 --- a/lib/iris/tests/results/regrid/bilinear_smaller_lon_align_right.cml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/regrid/bilinear_smaller_lon_align_right.data.0.json b/lib/iris/tests/results/regrid/bilinear_smaller_lon_align_right.data.0.json new file mode 100644 index 0000000000..74786e568a --- /dev/null +++ b/lib/iris/tests/results/regrid/bilinear_smaller_lon_align_right.data.0.json @@ -0,0 +1 @@ +{"std": 2.1602468490600586, "min": 3.0, "max": 9.0, "shape": [2, 3], "masked": false, "mean": 6.0} \ No newline at end of file diff --git a/lib/iris/tests/results/regrid/bilinear_smaller_lon_align_right.data.0.npy b/lib/iris/tests/results/regrid/bilinear_smaller_lon_align_right.data.0.npy deleted file mode 100644 index fe9a91636b..0000000000 Binary files a/lib/iris/tests/results/regrid/bilinear_smaller_lon_align_right.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/regrid/low_med_high.cml b/lib/iris/tests/results/regrid/low_med_high.cml index bbdf3c4f94..fb2c5bd3cf 100644 --- a/lib/iris/tests/results/regrid/low_med_high.cml +++ b/lib/iris/tests/results/regrid/low_med_high.cml @@ -1,51 +1,51 @@ - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/regrid/low_med_high.data.0.json b/lib/iris/tests/results/regrid/low_med_high.data.0.json new file mode 100644 index 0000000000..d64741ce40 --- /dev/null +++ b/lib/iris/tests/results/regrid/low_med_high.data.0.json @@ -0,0 +1 @@ +{"std": 3.7925365302569376, "min": 0.0, "max": 11.0, "shape": [5, 6], "masked": false, "mean": 5.5} \ No newline at end of file diff --git a/lib/iris/tests/results/regrid/low_med_high.data.0.npy b/lib/iris/tests/results/regrid/low_med_high.data.0.npy deleted file mode 100644 index aec9817eeb..0000000000 Binary files a/lib/iris/tests/results/regrid/low_med_high.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/regrid/low_med_high.data.1.json b/lib/iris/tests/results/regrid/low_med_high.data.1.json new file mode 100644 index 0000000000..fb58052aab --- /dev/null +++ b/lib/iris/tests/results/regrid/low_med_high.data.1.json @@ -0,0 +1 @@ +{"std": 6.0184900284225957, "min": 0.0, "max": 19.0, "shape": [5, 6], "masked": false, "mean": 8.3333333333333339} \ No newline at end of file diff --git a/lib/iris/tests/results/regrid/low_med_high.data.1.npy b/lib/iris/tests/results/regrid/low_med_high.data.1.npy deleted file mode 100644 index e427fbff36..0000000000 Binary files a/lib/iris/tests/results/regrid/low_med_high.data.1.npy and /dev/null differ diff --git a/lib/iris/tests/results/regrid/low_med_high.data.2.json b/lib/iris/tests/results/regrid/low_med_high.data.2.json new file mode 100644 index 0000000000..ac1c1a2b8c --- /dev/null +++ b/lib/iris/tests/results/regrid/low_med_high.data.2.json @@ -0,0 +1 @@ +{"std": 8.6554414483991895, "min": 0.0, "max": 29.0, "shape": [5, 6], "masked": false, "mean": 14.5} \ No newline at end of file diff --git a/lib/iris/tests/results/regrid/low_med_high.data.2.npy b/lib/iris/tests/results/regrid/low_med_high.data.2.npy deleted file mode 100644 index e14d51a630..0000000000 Binary files a/lib/iris/tests/results/regrid/low_med_high.data.2.npy and /dev/null differ diff --git a/lib/iris/tests/results/regrid/theta_on_airpress_0d.cml b/lib/iris/tests/results/regrid/theta_on_airpress_0d.cml deleted file mode 100644 index 71d6eed94a..0000000000 --- a/lib/iris/tests/results/regrid/theta_on_airpress_0d.cml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/regrid/theta_on_airpress_0d.data.0.json b/lib/iris/tests/results/regrid/theta_on_airpress_0d.data.0.json new file mode 100644 index 0000000000..292ae75826 --- /dev/null +++ b/lib/iris/tests/results/regrid/theta_on_airpress_0d.data.0.json @@ -0,0 +1 @@ +{"std": 0.0, "min": 282.12796020507812, "max": 282.12796020507812, "shape": [], "masked": false, "mean": 282.12796020507812} \ No newline at end of file diff --git a/lib/iris/tests/results/regrid/theta_on_airpress_0d.data.0.npy b/lib/iris/tests/results/regrid/theta_on_airpress_0d.data.0.npy deleted file mode 100644 index f03d94aa6c..0000000000 Binary files a/lib/iris/tests/results/regrid/theta_on_airpress_0d.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/regrid/theta_on_airpress_1d.cml b/lib/iris/tests/results/regrid/theta_on_airpress_1d.cml deleted file mode 100644 index d0a78e5694..0000000000 --- a/lib/iris/tests/results/regrid/theta_on_airpress_1d.cml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/regrid/theta_on_airpress_1d.data.0.json b/lib/iris/tests/results/regrid/theta_on_airpress_1d.data.0.json new file mode 100644 index 0000000000..0ad78fb933 --- /dev/null +++ b/lib/iris/tests/results/regrid/theta_on_airpress_1d.data.0.json @@ -0,0 +1 @@ +{"std": 0.20830129086971283, "min": 282.77932739257812, "max": 283.23013305664062, "shape": [4], "masked": false, "mean": 283.0235595703125} \ No newline at end of file diff --git a/lib/iris/tests/results/regrid/theta_on_airpress_1d.data.0.npy b/lib/iris/tests/results/regrid/theta_on_airpress_1d.data.0.npy deleted file mode 100644 index d38bec2bb4..0000000000 Binary files a/lib/iris/tests/results/regrid/theta_on_airpress_1d.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/regrid/theta_on_airpress_2d.cml b/lib/iris/tests/results/regrid/theta_on_airpress_2d.cml deleted file mode 100644 index 7f0251d176..0000000000 --- a/lib/iris/tests/results/regrid/theta_on_airpress_2d.cml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/regrid/theta_on_airpress_2d.data.0.json b/lib/iris/tests/results/regrid/theta_on_airpress_2d.data.0.json new file mode 100644 index 0000000000..1e19a7c045 --- /dev/null +++ b/lib/iris/tests/results/regrid/theta_on_airpress_2d.data.0.json @@ -0,0 +1 @@ +{"std": 0.89102786779403687, "min": 281.37478637695312, "max": 284.1317138671875, "shape": [4, 4], "masked": false, "mean": 282.7205810546875} \ No newline at end of file diff --git a/lib/iris/tests/results/regrid/theta_on_airpress_2d.data.0.npy b/lib/iris/tests/results/regrid/theta_on_airpress_2d.data.0.npy deleted file mode 100644 index c8d6757e78..0000000000 Binary files a/lib/iris/tests/results/regrid/theta_on_airpress_2d.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/regrid/theta_on_airpress_3d.cml b/lib/iris/tests/results/regrid/theta_on_airpress_3d.cml deleted file mode 100644 index 3de47e5d27..0000000000 --- a/lib/iris/tests/results/regrid/theta_on_airpress_3d.cml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/iris/tests/results/regrid/theta_on_airpress_3d.data.0.json b/lib/iris/tests/results/regrid/theta_on_airpress_3d.data.0.json new file mode 100644 index 0000000000..62fbe8491a --- /dev/null +++ b/lib/iris/tests/results/regrid/theta_on_airpress_3d.data.0.json @@ -0,0 +1 @@ +{"std": 1.0716584920883179, "min": 281.37478637695312, "max": 285.50057983398438, "shape": [5, 4, 4], "masked": false, "mean": 283.49774169921875} \ No newline at end of file diff --git a/lib/iris/tests/results/regrid/theta_on_airpress_3d.data.0.npy b/lib/iris/tests/results/regrid/theta_on_airpress_3d.data.0.npy deleted file mode 100644 index 958f90b662..0000000000 Binary files a/lib/iris/tests/results/regrid/theta_on_airpress_3d.data.0.npy and /dev/null differ diff --git a/lib/iris/tests/results/stock/realistic_4d.cml b/lib/iris/tests/results/stock/realistic_4d.cml index 69ae947f2c..88adbc43de 100644 --- a/lib/iris/tests/results/stock/realistic_4d.cml +++ b/lib/iris/tests/results/stock/realistic_4d.cml @@ -1,400 +1,400 @@ - + + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + ..., + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0], + [40000.0, 40000.0, 40000.0, ..., 40000.0, + 40000.0, 40000.0]]]" shape="(70, 100, 100)" standard_name="altitude" units="Unit('m')" value_type="float32"> - + @@ -415,7 +415,7 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> @@ -427,7 +427,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -447,7 +447,7 @@ - - + 300.34]]" shape="(100, 100)" standard_name="surface_altitude" units="Unit('m')" value_type="float32"/> - - + diff --git a/lib/iris/tests/results/system/supported_filetype_.grib2.cml b/lib/iris/tests/results/system/supported_filetype_.grib2.cml index ec90ebcd58..c230684fbd 100644 --- a/lib/iris/tests/results/system/supported_filetype_.grib2.cml +++ b/lib/iris/tests/results/system/supported_filetype_.grib2.cml @@ -1,12 +1,15 @@ - + - + + + + - - - - - + - + - + diff --git a/lib/iris/tests/results/system/supported_filetype_.nc.cml b/lib/iris/tests/results/system/supported_filetype_.nc.cml index 1d19cf5e0c..c752ff3464 100644 --- a/lib/iris/tests/results/system/supported_filetype_.nc.cml +++ b/lib/iris/tests/results/system/supported_filetype_.nc.cml @@ -1,15 +1,15 @@ - + - + - - + - + - + diff --git a/lib/iris/tests/results/system/supported_filetype_.pp.cml b/lib/iris/tests/results/system/supported_filetype_.pp.cml index 05a3f548ae..838b9fad50 100644 --- a/lib/iris/tests/results/system/supported_filetype_.pp.cml +++ b/lib/iris/tests/results/system/supported_filetype_.pp.cml @@ -1,15 +1,15 @@ - + - + - + - - + - + - + diff --git a/lib/iris/tests/results/trajectory/big_cube.cml b/lib/iris/tests/results/trajectory/big_cube.cml index 5ffb7c1c90..e8db4005ec 100644 --- a/lib/iris/tests/results/trajectory/big_cube.cml +++ b/lib/iris/tests/results/trajectory/big_cube.cml @@ -3,24 +3,25 @@ - + + - + - - - @@ -32,7 +33,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -52,7 +53,7 @@ - - - + diff --git a/lib/iris/tests/results/trajectory/constant_latitude.cml b/lib/iris/tests/results/trajectory/constant_latitude.cml index 69d8f1e86a..7990edada5 100644 --- a/lib/iris/tests/results/trajectory/constant_latitude.cml +++ b/lib/iris/tests/results/trajectory/constant_latitude.cml @@ -1,26 +1,27 @@ - + - + + - + - - - @@ -32,7 +33,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -52,7 +53,7 @@ - - - + diff --git a/lib/iris/tests/results/trajectory/hybrid_height.cml b/lib/iris/tests/results/trajectory/hybrid_height.cml index 96cb910d2c..63de9366dc 100644 --- a/lib/iris/tests/results/trajectory/hybrid_height.cml +++ b/lib/iris/tests/results/trajectory/hybrid_height.cml @@ -1,69 +1,69 @@ - + - + [5661, 5714, 5767, 5820, 5873, 5926], + [5979, 6032, 6085, 6138, 6191, 6244], + [6297, 6350, 6403, 6456, 6509, 6562], + [6615, 6668, 6721, 6774, 6827, 6880]]]" shape="(4, 5, 6)" standard_name="altitude" units="Unit('m')" value_type="int64"> - + - + - + - + - + - - + - + - + - @@ -73,28 +73,28 @@ - + - + - + - + - + - + - + - + diff --git a/lib/iris/tests/results/trajectory/single_point.cml b/lib/iris/tests/results/trajectory/single_point.cml index cc2d79b6ea..393ad5e335 100644 --- a/lib/iris/tests/results/trajectory/single_point.cml +++ b/lib/iris/tests/results/trajectory/single_point.cml @@ -1,25 +1,26 @@ - + - + + - + - - + - + @@ -30,7 +31,7 @@ ..., [30589.1, 34018.9], [34018.9, 37922.5], - [37922.5, 42077.5]]" id="218bea13" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, + [37922.5, 42077.5]]" id="fb105c19" long_name="level_height" points="[5.0, 21.6667, 45.0, 75.0, 111.667, 155.0, 205.0, 261.667, 325.0, 395.0, 471.667, 555.0, 645.0, 741.667, 845.0, 955.0, 1071.67, 1195.0, 1325.0, 1461.67, 1605.0, 1755.0, 1911.67, 2075.0, @@ -50,7 +51,7 @@ - - - + diff --git a/lib/iris/tests/results/trajectory/tri_polar_latitude_slice.cml b/lib/iris/tests/results/trajectory/tri_polar_latitude_slice.cml index 891ac8aca2..2224d12028 100644 --- a/lib/iris/tests/results/trajectory/tri_polar_latitude_slice.cml +++ b/lib/iris/tests/results/trajectory/tri_polar_latitude_slice.cml @@ -1,6 +1,6 @@ - + @@ -60,7 +60,7 @@ [3504.46, 4001.16], [4001.16, 4500.02], [4500.02, 5000.0], - [5000.0, 5500.55]]" id="b099957f" long_name="Vertical T levels" points="[4.99994, 15.0003, 25.0018, 35.0054, 45.0133, + [5000.0, 5500.55]]" id="3402b299" long_name="Vertical T levels" points="[4.99994, 15.0003, 25.0018, 35.0054, 45.0133, 55.0295, 65.0618, 75.1255, 85.2504, 95.4943, 105.97, 116.896, 128.698, 142.195, 158.961, 181.963, 216.648, 272.477, 364.303, 511.535, @@ -70,27 +70,33 @@ + + - + + - + + - + @@ -100,9 +106,9 @@ - + - + diff --git a/lib/iris/tests/results/trajectory/zigzag.cml b/lib/iris/tests/results/trajectory/zigzag.cml index 2c6790effd..250500786c 100644 --- a/lib/iris/tests/results/trajectory/zigzag.cml +++ b/lib/iris/tests/results/trajectory/zigzag.cml @@ -1,98 +1,57 @@ - + - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + diff --git a/lib/iris/tests/results/unit/analysis/cartography/project/TestAll/cube.cml b/lib/iris/tests/results/unit/analysis/cartography/project/TestAll/cube.cml new file mode 100644 index 0000000000..6c192a1006 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/cartography/project/TestAll/cube.cml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/cartography/project/TestAll/cube.data.0.json b/lib/iris/tests/results/unit/analysis/cartography/project/TestAll/cube.data.0.json new file mode 100644 index 0000000000..d340b7856c --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/cartography/project/TestAll/cube.data.0.json @@ -0,0 +1 @@ +{"std": 0.22496461010978716, "min": 287.27520751953125, "max": 288.09292602539062, "shape": [2, 3, 10, 10], "masked": true, "mean": 287.67258522727275} \ No newline at end of file diff --git a/lib/iris/tests/results/unit/analysis/maths/add/TestBroadcasting/collapse_all_dims.cml b/lib/iris/tests/results/unit/analysis/maths/add/TestBroadcasting/collapse_all_dims.cml new file mode 100644 index 0000000000..c6e6271a63 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/add/TestBroadcasting/collapse_all_dims.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/add/TestBroadcasting/collapse_last_dims.cml b/lib/iris/tests/results/unit/analysis/maths/add/TestBroadcasting/collapse_last_dims.cml new file mode 100644 index 0000000000..c6e6271a63 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/add/TestBroadcasting/collapse_last_dims.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/add/TestBroadcasting/collapse_middle_dim.cml b/lib/iris/tests/results/unit/analysis/maths/add/TestBroadcasting/collapse_middle_dim.cml new file mode 100644 index 0000000000..c6e6271a63 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/add/TestBroadcasting/collapse_middle_dim.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/add/TestBroadcasting/collapse_zeroth_dim.cml b/lib/iris/tests/results/unit/analysis/maths/add/TestBroadcasting/collapse_zeroth_dim.cml new file mode 100644 index 0000000000..c6e6271a63 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/add/TestBroadcasting/collapse_zeroth_dim.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/add/TestBroadcasting/slice.cml b/lib/iris/tests/results/unit/analysis/maths/add/TestBroadcasting/slice.cml new file mode 100644 index 0000000000..c6e6271a63 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/add/TestBroadcasting/slice.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/add/TestBroadcasting/transposed.cml b/lib/iris/tests/results/unit/analysis/maths/add/TestBroadcasting/transposed.cml new file mode 100644 index 0000000000..c6e6271a63 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/add/TestBroadcasting/transposed.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/divide/TestBroadcasting/collapse_all_dims.cml b/lib/iris/tests/results/unit/analysis/maths/divide/TestBroadcasting/collapse_all_dims.cml new file mode 100644 index 0000000000..940661c230 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/divide/TestBroadcasting/collapse_all_dims.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/divide/TestBroadcasting/collapse_last_dims.cml b/lib/iris/tests/results/unit/analysis/maths/divide/TestBroadcasting/collapse_last_dims.cml new file mode 100644 index 0000000000..940661c230 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/divide/TestBroadcasting/collapse_last_dims.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/divide/TestBroadcasting/collapse_middle_dim.cml b/lib/iris/tests/results/unit/analysis/maths/divide/TestBroadcasting/collapse_middle_dim.cml new file mode 100644 index 0000000000..940661c230 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/divide/TestBroadcasting/collapse_middle_dim.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/divide/TestBroadcasting/collapse_zeroth_dim.cml b/lib/iris/tests/results/unit/analysis/maths/divide/TestBroadcasting/collapse_zeroth_dim.cml new file mode 100644 index 0000000000..940661c230 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/divide/TestBroadcasting/collapse_zeroth_dim.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/divide/TestBroadcasting/slice.cml b/lib/iris/tests/results/unit/analysis/maths/divide/TestBroadcasting/slice.cml new file mode 100644 index 0000000000..940661c230 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/divide/TestBroadcasting/slice.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/divide/TestBroadcasting/transposed.cml b/lib/iris/tests/results/unit/analysis/maths/divide/TestBroadcasting/transposed.cml new file mode 100644 index 0000000000..940661c230 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/divide/TestBroadcasting/transposed.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/multiply/TestBroadcasting/collapse_all_dims.cml b/lib/iris/tests/results/unit/analysis/maths/multiply/TestBroadcasting/collapse_all_dims.cml new file mode 100644 index 0000000000..b646e8b550 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/multiply/TestBroadcasting/collapse_all_dims.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/multiply/TestBroadcasting/collapse_last_dims.cml b/lib/iris/tests/results/unit/analysis/maths/multiply/TestBroadcasting/collapse_last_dims.cml new file mode 100644 index 0000000000..b646e8b550 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/multiply/TestBroadcasting/collapse_last_dims.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/multiply/TestBroadcasting/collapse_middle_dim.cml b/lib/iris/tests/results/unit/analysis/maths/multiply/TestBroadcasting/collapse_middle_dim.cml new file mode 100644 index 0000000000..b646e8b550 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/multiply/TestBroadcasting/collapse_middle_dim.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/multiply/TestBroadcasting/collapse_zeroth_dim.cml b/lib/iris/tests/results/unit/analysis/maths/multiply/TestBroadcasting/collapse_zeroth_dim.cml new file mode 100644 index 0000000000..b646e8b550 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/multiply/TestBroadcasting/collapse_zeroth_dim.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/multiply/TestBroadcasting/slice.cml b/lib/iris/tests/results/unit/analysis/maths/multiply/TestBroadcasting/slice.cml new file mode 100644 index 0000000000..b646e8b550 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/multiply/TestBroadcasting/slice.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/multiply/TestBroadcasting/transposed.cml b/lib/iris/tests/results/unit/analysis/maths/multiply/TestBroadcasting/transposed.cml new file mode 100644 index 0000000000..b646e8b550 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/multiply/TestBroadcasting/transposed.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/subtract/TestBroadcasting/collapse_all_dims.cml b/lib/iris/tests/results/unit/analysis/maths/subtract/TestBroadcasting/collapse_all_dims.cml new file mode 100644 index 0000000000..c6e6271a63 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/subtract/TestBroadcasting/collapse_all_dims.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/subtract/TestBroadcasting/collapse_last_dims.cml b/lib/iris/tests/results/unit/analysis/maths/subtract/TestBroadcasting/collapse_last_dims.cml new file mode 100644 index 0000000000..c6e6271a63 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/subtract/TestBroadcasting/collapse_last_dims.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/subtract/TestBroadcasting/collapse_middle_dim.cml b/lib/iris/tests/results/unit/analysis/maths/subtract/TestBroadcasting/collapse_middle_dim.cml new file mode 100644 index 0000000000..c6e6271a63 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/subtract/TestBroadcasting/collapse_middle_dim.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/subtract/TestBroadcasting/collapse_zeroth_dim.cml b/lib/iris/tests/results/unit/analysis/maths/subtract/TestBroadcasting/collapse_zeroth_dim.cml new file mode 100644 index 0000000000..c6e6271a63 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/subtract/TestBroadcasting/collapse_zeroth_dim.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/subtract/TestBroadcasting/slice.cml b/lib/iris/tests/results/unit/analysis/maths/subtract/TestBroadcasting/slice.cml new file mode 100644 index 0000000000..c6e6271a63 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/subtract/TestBroadcasting/slice.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/analysis/maths/subtract/TestBroadcasting/transposed.cml b/lib/iris/tests/results/unit/analysis/maths/subtract/TestBroadcasting/transposed.cml new file mode 100644 index 0000000000..c6e6271a63 --- /dev/null +++ b/lib/iris/tests/results/unit/analysis/maths/subtract/TestBroadcasting/transposed.cml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/cube/Cube/intersection__Metadata/metadata.cml b/lib/iris/tests/results/unit/cube/Cube/intersection__Metadata/metadata.cml new file mode 100644 index 0000000000..4ae37abf0b --- /dev/null +++ b/lib/iris/tests/results/unit/cube/Cube/intersection__Metadata/metadata.cml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/cube/Cube/intersection__Metadata/metadata.data.0.json b/lib/iris/tests/results/unit/cube/Cube/intersection__Metadata/metadata.data.0.json new file mode 100644 index 0000000000..124c32d225 --- /dev/null +++ b/lib/iris/tests/results/unit/cube/Cube/intersection__Metadata/metadata.data.0.json @@ -0,0 +1 @@ +{"std": 1242.753662109375, "min": 170.0, "max": 4150.0, "shape": [4, 3, 21], "masked": false, "mean": 2160.0} \ No newline at end of file diff --git a/lib/iris/tests/results/unit/cube/Cube/intersection__Metadata/metadata_wrapped.cml b/lib/iris/tests/results/unit/cube/Cube/intersection__Metadata/metadata_wrapped.cml new file mode 100644 index 0000000000..17eebb6ea4 --- /dev/null +++ b/lib/iris/tests/results/unit/cube/Cube/intersection__Metadata/metadata_wrapped.cml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/cube/Cube/intersection__Metadata/metadata_wrapped.data.0.json b/lib/iris/tests/results/unit/cube/Cube/intersection__Metadata/metadata_wrapped.data.0.json new file mode 100644 index 0000000000..2f4603efd2 --- /dev/null +++ b/lib/iris/tests/results/unit/cube/Cube/intersection__Metadata/metadata_wrapped.data.0.json @@ -0,0 +1 @@ +{"std": 1254.9412841796875, "min": 0.0, "max": 4319.0, "shape": [4, 3, 21], "masked": false, "mean": 2151.428466796875} \ No newline at end of file diff --git a/lib/iris/tests/results/unit/cube/Cube/xml/checksum_ignores_masked_values.cml b/lib/iris/tests/results/unit/cube/Cube/xml/checksum_ignores_masked_values.cml index e15ac3a977..0d487d676c 100644 --- a/lib/iris/tests/results/unit/cube/Cube/xml/checksum_ignores_masked_values.cml +++ b/lib/iris/tests/results/unit/cube/Cube/xml/checksum_ignores_masked_values.cml @@ -1,8 +1,8 @@ - + - + diff --git a/lib/iris/tests/results/unit/cube/CubeList/merge__time_triple/combination_with_extra_realization.cml b/lib/iris/tests/results/unit/cube/CubeList/merge__time_triple/combination_with_extra_realization.cml new file mode 100644 index 0000000000..0a8b19cc2b --- /dev/null +++ b/lib/iris/tests/results/unit/cube/CubeList/merge__time_triple/combination_with_extra_realization.cml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/cube/CubeList/merge__time_triple/combination_with_extra_triple.cml b/lib/iris/tests/results/unit/cube/CubeList/merge__time_triple/combination_with_extra_triple.cml new file mode 100644 index 0000000000..edd4e8c9f7 --- /dev/null +++ b/lib/iris/tests/results/unit/cube/CubeList/merge__time_triple/combination_with_extra_triple.cml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/cube/CubeList/merge__time_triple/combination_with_realization.cml b/lib/iris/tests/results/unit/cube/CubeList/merge__time_triple/combination_with_realization.cml new file mode 100644 index 0000000000..3293bfa8c0 --- /dev/null +++ b/lib/iris/tests/results/unit/cube/CubeList/merge__time_triple/combination_with_realization.cml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/cube/CubeList/merge__time_triple/orthogonal_with_realization.cml b/lib/iris/tests/results/unit/cube/CubeList/merge__time_triple/orthogonal_with_realization.cml new file mode 100644 index 0000000000..2dcdc21c8f --- /dev/null +++ b/lib/iris/tests/results/unit/cube/CubeList/merge__time_triple/orthogonal_with_realization.cml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/experimental/stratify/relevel/Test/multi_dim_target_levels.cml b/lib/iris/tests/results/unit/experimental/stratify/relevel/Test/multi_dim_target_levels.cml new file mode 100644 index 0000000000..132ac9887e --- /dev/null +++ b/lib/iris/tests/results/unit/experimental/stratify/relevel/Test/multi_dim_target_levels.cml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/fileformats/grib/load_cubes/load_cubes/reduced_raw.cml b/lib/iris/tests/results/unit/fileformats/grib/load_cubes/load_cubes/reduced_raw.cml new file mode 100644 index 0000000000..b4f279914c --- /dev/null +++ b/lib/iris/tests/results/unit/fileformats/grib/load_cubes/load_cubes/reduced_raw.cml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/endian.cdl b/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/endian.cdl index 04bbd50aff..daa072c385 100644 --- a/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/endian.cdl +++ b/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/endian.cdl @@ -1,6 +1,6 @@ dimensions: - dim0 = UNLIMITED ; // (3 currently) bnds = 2 ; + dim0 = 3 ; dim1 = 4 ; variables: float air_pressure_anomaly(dim0, dim1) ; diff --git a/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/mercator.cdl b/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/mercator.cdl new file mode 100644 index 0000000000..1559cd2bff --- /dev/null +++ b/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/mercator.cdl @@ -0,0 +1,25 @@ +dimensions: + projection_x_coordinate = 4 ; + projection_y_coordinate = 3 ; +variables: + int64 air_pressure_anomaly(projection_y_coordinate, projection_x_coordinate) ; + air_pressure_anomaly:standard_name = "air_pressure_anomaly" ; + air_pressure_anomaly:grid_mapping = "mercator" ; + int mercator ; + mercator:grid_mapping_name = "mercator" ; + mercator:longitude_of_prime_meridian = 0. ; + mercator:semi_major_axis = 6377563.396 ; + mercator:semi_minor_axis = 6356256.909 ; + mercator:longitude_of_projection_origin = 49. ; + mercator:false_easting = 0. ; + mercator:false_northing = 0. ; + mercator:scale_factor_at_projection_origin = 1. ; + int64 projection_y_coordinate(projection_y_coordinate) ; + projection_y_coordinate:axis = "Y" ; + projection_y_coordinate:units = "m" ; + projection_y_coordinate:standard_name = "projection_y_coordinate" ; + int64 projection_x_coordinate(projection_x_coordinate) ; + projection_x_coordinate:axis = "X" ; + projection_x_coordinate:units = "m" ; + projection_x_coordinate:standard_name = "projection_x_coordinate" ; +} diff --git a/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/mercator_no_ellipsoid.cdl b/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/mercator_no_ellipsoid.cdl new file mode 100644 index 0000000000..8db60ca952 --- /dev/null +++ b/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/mercator_no_ellipsoid.cdl @@ -0,0 +1,22 @@ +dimensions: + projection_x_coordinate = 4 ; + projection_y_coordinate = 3 ; +variables: + int64 air_pressure_anomaly(projection_y_coordinate, projection_x_coordinate) ; + air_pressure_anomaly:standard_name = "air_pressure_anomaly" ; + air_pressure_anomaly:grid_mapping = "mercator" ; + int mercator ; + mercator:grid_mapping_name = "mercator" ; + mercator:longitude_of_projection_origin = 49. ; + mercator:false_easting = 0. ; + mercator:false_northing = 0. ; + mercator:scale_factor_at_projection_origin = 1. ; + int64 projection_y_coordinate(projection_y_coordinate) ; + projection_y_coordinate:axis = "Y" ; + projection_y_coordinate:units = "m" ; + projection_y_coordinate:standard_name = "projection_y_coordinate" ; + int64 projection_x_coordinate(projection_x_coordinate) ; + projection_x_coordinate:axis = "X" ; + projection_x_coordinate:units = "m" ; + projection_x_coordinate:standard_name = "projection_x_coordinate" ; +} diff --git a/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/stereographic.cdl b/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/stereographic.cdl new file mode 100644 index 0000000000..c021859121 --- /dev/null +++ b/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/stereographic.cdl @@ -0,0 +1,26 @@ +dimensions: + projection_x_coordinate = 4 ; + projection_y_coordinate = 3 ; +variables: + int64 air_pressure_anomaly(projection_y_coordinate, projection_x_coordinate) ; + air_pressure_anomaly:standard_name = "air_pressure_anomaly" ; + air_pressure_anomaly:grid_mapping = "stereographic" ; + int stereographic ; + stereographic:grid_mapping_name = "stereographic" ; + stereographic:longitude_of_prime_meridian = 0. ; + stereographic:semi_major_axis = 6377563.396 ; + stereographic:semi_minor_axis = 6356256.909 ; + stereographic:longitude_of_projection_origin = 20. ; + stereographic:latitude_of_projection_origin = -10. ; + stereographic:false_easting = 500000. ; + stereographic:false_northing = -200000. ; + stereographic:scale_factor_at_projection_origin = 1. ; + int64 projection_y_coordinate(projection_y_coordinate) ; + projection_y_coordinate:axis = "Y" ; + projection_y_coordinate:units = "m" ; + projection_y_coordinate:standard_name = "projection_y_coordinate" ; + int64 projection_x_coordinate(projection_x_coordinate) ; + projection_x_coordinate:axis = "X" ; + projection_x_coordinate:units = "m" ; + projection_x_coordinate:standard_name = "projection_x_coordinate" ; +} diff --git a/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/stereographic_no_ellipsoid.cdl b/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/stereographic_no_ellipsoid.cdl new file mode 100644 index 0000000000..7b21325fbb --- /dev/null +++ b/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/stereographic_no_ellipsoid.cdl @@ -0,0 +1,23 @@ +dimensions: + projection_x_coordinate = 4 ; + projection_y_coordinate = 3 ; +variables: + int64 air_pressure_anomaly(projection_y_coordinate, projection_x_coordinate) ; + air_pressure_anomaly:standard_name = "air_pressure_anomaly" ; + air_pressure_anomaly:grid_mapping = "stereographic" ; + int stereographic ; + stereographic:grid_mapping_name = "stereographic" ; + stereographic:longitude_of_projection_origin = 20. ; + stereographic:latitude_of_projection_origin = -10. ; + stereographic:false_easting = 500000. ; + stereographic:false_northing = -200000. ; + stereographic:scale_factor_at_projection_origin = 1. ; + int64 projection_y_coordinate(projection_y_coordinate) ; + projection_y_coordinate:axis = "Y" ; + projection_y_coordinate:units = "m" ; + projection_y_coordinate:standard_name = "projection_y_coordinate" ; + int64 projection_x_coordinate(projection_x_coordinate) ; + projection_x_coordinate:axis = "X" ; + projection_x_coordinate:units = "m" ; + projection_x_coordinate:standard_name = "projection_x_coordinate" ; +} diff --git a/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/transverse_mercator.cdl b/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/transverse_mercator.cdl index a1d47d5ab1..9a1d8e0431 100644 --- a/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/transverse_mercator.cdl +++ b/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/transverse_mercator.cdl @@ -1,6 +1,6 @@ dimensions: - projection_y_coordinate = UNLIMITED ; // (3 currently) projection_x_coordinate = 4 ; + projection_y_coordinate = 3 ; variables: int64 air_pressure_anomaly(projection_y_coordinate, projection_x_coordinate) ; air_pressure_anomaly:standard_name = "air_pressure_anomaly" ; diff --git a/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/transverse_mercator_no_ellipsoid.cdl b/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/transverse_mercator_no_ellipsoid.cdl index d89888ec95..a7aee0a177 100644 --- a/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/transverse_mercator_no_ellipsoid.cdl +++ b/lib/iris/tests/results/unit/fileformats/netcdf/Saver/write/transverse_mercator_no_ellipsoid.cdl @@ -1,6 +1,6 @@ dimensions: - projection_y_coordinate = UNLIMITED ; // (3 currently) projection_x_coordinate = 4 ; + projection_y_coordinate = 3 ; variables: int64 air_pressure_anomaly(projection_y_coordinate, projection_x_coordinate) ; air_pressure_anomaly:standard_name = "air_pressure_anomaly" ; diff --git a/lib/iris/tests/results/unit/merge/ProtoCube/register__CoordSig_general/noise.txt b/lib/iris/tests/results/unit/merge/ProtoCube/register__CoordSig_general/noise.txt index 901ae631c5..38c9f39984 100644 --- a/lib/iris/tests/results/unit/merge/ProtoCube/register__CoordSig_general/noise.txt +++ b/lib/iris/tests/results/unit/merge/ProtoCube/register__CoordSig_general/noise.txt @@ -1,6 +1,6 @@ failed to merge into a single cube. - Coordinates in cube.aux_coords (scalar) differ: liff, life, like, moog, mong, ming. - Coordinates in cube.dim_coords differ: altitude, equinomity, longitude, equinumity, latitude, equinimity. - Coordinates in cube.aux_coords (non-scalar) differ: cee, three, bee, two, ay, one. + Coordinates in cube.aux_coords (scalar) differ: life, liff, like, ming, mong, moog. + Coordinates in cube.dim_coords differ: altitude, equinimity, equinomity, equinumity, latitude, longitude. + Coordinates in cube.aux_coords (non-scalar) differ: ay, bee, cee, one, three, two. Coordinate-to-dimension mapping differs for cube.aux_coords (non-scalar). cube.aux_factories() differ \ No newline at end of file diff --git a/lib/iris/tests/results/unit/merge/ProtoCube/register__CubeSig/noise.txt b/lib/iris/tests/results/unit/merge/ProtoCube/register__CubeSig/noise.txt index efce0b7c9d..c330646e72 100644 --- a/lib/iris/tests/results/unit/merge/ProtoCube/register__CubeSig/noise.txt +++ b/lib/iris/tests/results/unit/merge/ProtoCube/register__CubeSig/noise.txt @@ -4,5 +4,4 @@ failed to merge into a single cube. cube.attributes keys differ: 'stuffed' cube.cell_methods differ cube.shape differs: (3,) != (2,) - cube data dtype differs: int64 != int8 - cube data fill_value differs: 999999 != 57 \ No newline at end of file + cube data dtype differs: int64 != int8 \ No newline at end of file diff --git a/lib/iris/tests/results/uri_callback/grib_global.cml b/lib/iris/tests/results/uri_callback/grib_global.cml index 0e6d0b6e4e..a7a23e7235 100644 --- a/lib/iris/tests/results/uri_callback/grib_global.cml +++ b/lib/iris/tests/results/uri_callback/grib_global.cml @@ -1,12 +1,18 @@ - + - + + + + + + + - - - - - - - - - + - + @@ -52,6 +52,6 @@ - + diff --git a/lib/iris/tests/results/uri_callback/pp_global.cml b/lib/iris/tests/results/uri_callback/pp_global.cml index b88cb90194..4e493f486d 100644 --- a/lib/iris/tests/results/uri_callback/pp_global.cml +++ b/lib/iris/tests/results/uri_callback/pp_global.cml @@ -1,6 +1,6 @@ - + @@ -9,13 +9,13 @@ - + - + - - + - + - + - + + + + - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/000003000000.03.236.000128.1990.12.01.00.00.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/000003000000.03.236.000128.1990.12.01.00.00.b_0.cml index d9b58d7c94..e251bc4e5b 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/000003000000.03.236.000128.1990.12.01.00.00.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/000003000000.03.236.000128.1990.12.01.00.00.b_0.cml @@ -1,6 +1,6 @@ - + @@ -8,20 +8,20 @@ - + - + - + - - + - + @@ -48,6 +48,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/000003000000.03.236.004224.1990.12.01.00.00.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/000003000000.03.236.004224.1990.12.01.00.00.b_0.cml index e060ee3849..86a3f9b50d 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/000003000000.03.236.004224.1990.12.01.00.00.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/000003000000.03.236.004224.1990.12.01.00.00.b_0.cml @@ -1,6 +1,6 @@ - + @@ -8,20 +8,20 @@ - + - + - + - - + - + @@ -48,6 +48,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/000003000000.03.236.008320.1990.12.01.00.00.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/000003000000.03.236.008320.1990.12.01.00.00.b_0.cml index 407a3b3908..8b77cb62a1 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/000003000000.03.236.008320.1990.12.01.00.00.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/000003000000.03.236.008320.1990.12.01.00.00.b_0.cml @@ -1,28 +1,28 @@ - + - + - + - + - + - - + - + - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/000003000000.16.202.000128.1860.09.01.00.00.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/000003000000.16.202.000128.1860.09.01.00.00.b_0.cml index c5984f7b85..fe90919bb0 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/000003000000.16.202.000128.1860.09.01.00.00.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/000003000000.16.202.000128.1860.09.01.00.00.b_0.cml @@ -1,6 +1,6 @@ - + @@ -8,13 +8,13 @@ - + - + - - + - + - + @@ -45,6 +45,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/001000000000.00.000.000000.1860.01.01.00.00.f.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/001000000000.00.000.000000.1860.01.01.00.00.f.b_0.cml index 9b0ff3cdce..d3f6e1cf4a 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/001000000000.00.000.000000.1860.01.01.00.00.f.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/001000000000.00.000.000000.1860.01.01.00.00.f.b_0.cml @@ -1,33 +1,33 @@ - + - + - + - - - + - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/002000000000.44.101.131200.1920.09.01.00.00.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/002000000000.44.101.131200.1920.09.01.00.00.b_0.cml index 10c0daa9dd..390d94cbc8 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/002000000000.44.101.131200.1920.09.01.00.00.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/002000000000.44.101.131200.1920.09.01.00.00.b_0.cml @@ -1,15 +1,15 @@ - + - + - @@ -19,13 +19,13 @@ - + - + - + - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/008000000000.44.101.000128.1890.09.01.00.00.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/008000000000.44.101.000128.1890.09.01.00.00.b_0.cml index a38ef538b8..d5e55c4516 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/008000000000.44.101.000128.1890.09.01.00.00.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/008000000000.44.101.000128.1890.09.01.00.00.b_0.cml @@ -1,6 +1,6 @@ - + @@ -8,7 +8,7 @@ - @@ -18,7 +18,7 @@ - @@ -29,6 +29,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/12187.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/12187.b_0.cml index fbed001996..9948c8e433 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/12187.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/12187.b_0.cml @@ -1,20 +1,21 @@ - + - + + - + - + - + @@ -56,7 +57,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="fb52c1a6" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -69,12 +70,12 @@ - + - @@ -120,7 +121,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="273ab6c5" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -130,7 +131,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32" var_name="sigma"/> - + @@ -138,6 +139,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/HadCM2_ts_SAT_ann_18602100.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/HadCM2_ts_SAT_ann_18602100.b_0.cml index 9887c76999..885944c4f0 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/HadCM2_ts_SAT_ann_18602100.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/HadCM2_ts_SAT_ann_18602100.b_0.cml @@ -1,6 +1,6 @@ - + @@ -8,23 +8,23 @@ - + + [-89.9, 1.24998]]" id="4a0cb9d8" points="[0.0, 45.575, -44.325]" shape="(3,)" standard_name="latitude" units="Unit('degrees')" value_type="float32" var_name="latitude"/> + [-1.875, 358.125]]" id="62e940e0" points="[178.125, 178.125, 178.125]" shape="(3,)" standard_name="longitude" units="Unit('degrees')" value_type="float32" var_name="longitude"/> - + - @@ -33,6 +33,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_level_lat_orig.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_level_lat_orig.b_0.cml index 889f96c385..e956bfcb70 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_level_lat_orig.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_level_lat_orig.b_0.cml @@ -1,6 +1,6 @@ - + @@ -8,13 +8,14 @@ - + - + - - + [1226160.0, 1398960.0]]" id="cb784457" points="[1139760.0, 1312560.0]" shape="(2,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64" var_name="time"/> @@ -42,6 +43,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_lon_lat_press_orig.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_lon_lat_press_orig.b_0.cml index dbdee53018..5fa7a949b2 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_lon_lat_press_orig.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_lon_lat_press_orig.b_0.cml @@ -1,6 +1,6 @@ - + @@ -8,13 +8,14 @@ - + - + - - + - + [1226160.0, 1398960.0]]" id="cb784457" points="[1139760.0, 1312560.0]" shape="(2,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64" var_name="time"/> @@ -47,6 +48,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_lon_lat_several.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_lon_lat_several.b_0.cml index ebc77ed6ca..ddb11831fc 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_lon_lat_several.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_lon_lat_several.b_0.cml @@ -1,6 +1,6 @@ - + @@ -8,22 +8,36 @@ - + - + - + - - + @@ -55,10 +69,10 @@ [1060560.0, 1061280.0], [1061280.0, 1062000.0], [1062000.0, 1062720.0], - [1062720.0, 1063440.0]]" id="2789ad5b" points="[1054080.0, 1054800.0, 1055520.0, 1056240.0, - 1056960.0, 1057680.0, 1058400.0, 1059120.0, - 1059840.0, 1060560.0, 1061280.0, 1062000.0, - 1062720.0, 1063440.0]" shape="(14,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64" var_name="time"/> + [1062720.0, 1063440.0]]" id="cb784457" points="[1053720.0, 1054440.0, 1055160.0, 1055880.0, + 1056600.0, 1057320.0, 1058040.0, 1058760.0, + 1059480.0, 1060200.0, 1060920.0, 1061640.0, + 1062360.0, 1063080.0]" shape="(14,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64" var_name="time"/> @@ -66,6 +80,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_n10r13xy.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_n10r13xy.b_0.cml index 4a12478b42..9c341b4898 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_n10r13xy.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_n10r13xy.b_0.cml @@ -1,28 +1,31 @@ - + - + - + - + - - @@ -31,7 +34,7 @@ + [1079280.0, 1081440.0]]" id="cb784457" points="[1054440.0, 1063080.0, 1071720.0, 1080360.0]" shape="(4,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64" var_name="time"/> @@ -39,6 +42,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_time_press.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_time_press.b_0.cml index 78e268f744..98bbd4e2f2 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_time_press.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_time_press.b_0.cml @@ -1,6 +1,6 @@ - + @@ -8,12 +8,12 @@ - - + @@ -21,6 +21,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_tseries.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_tseries.b_0.cml index 602a8cdeb0..958a241fd4 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_tseries.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/aaxzc_tseries.b_0.cml @@ -1,6 +1,6 @@ - + @@ -8,17 +8,17 @@ - + - + - + @@ -26,6 +26,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/abcza_pa19591997_daily_29.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/abcza_pa19591997_daily_29.b_0.cml index 9234c20899..1c9c58d6d0 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/abcza_pa19591997_daily_29.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/abcza_pa19591997_daily_29.b_0.cml @@ -1,6 +1,6 @@ - + @@ -8,21 +8,27 @@ - + - + - + - - + @@ -47,8 +53,8 @@ ..., [163368.0, 163392.0], [163392.0, 163416.0], - [163416.0, 163440.0]]" id="2789ad5b" points="[154824.0, 154848.0, 154872.0, ..., 163392.0, - 163416.0, 163440.0]" shape="(360,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64" var_name="time"/> + [163416.0, 163440.0]]" id="cb784457" points="[154812.0, 154836.0, 154860.0, ..., 163380.0, + 163404.0, 163428.0]" shape="(360,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64" var_name="time"/> @@ -56,6 +62,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/abcza_pa19591997_daily_29.b_1.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/abcza_pa19591997_daily_29.b_1.cml index 8bab783337..7228163b23 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/abcza_pa19591997_daily_29.b_1.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/abcza_pa19591997_daily_29.b_1.cml @@ -1,6 +1,6 @@ - + @@ -8,21 +8,27 @@ - + - + - + - - + @@ -47,8 +53,8 @@ ..., [163368.0, 163392.0], [163392.0, 163416.0], - [163416.0, 163440.0]]" id="2789ad5b" points="[154824.0, 154848.0, 154872.0, ..., 163392.0, - 163416.0, 163440.0]" shape="(360,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64" var_name="time"/> + [163416.0, 163440.0]]" id="cb784457" points="[154812.0, 154836.0, 154860.0, ..., 163380.0, + 163404.0, 163428.0]" shape="(360,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64" var_name="time"/> @@ -56,6 +62,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/abcza_pa19591997_daily_29.b_2.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/abcza_pa19591997_daily_29.b_2.cml index 159e8b58e0..cb5c754080 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/abcza_pa19591997_daily_29.b_2.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/abcza_pa19591997_daily_29.b_2.cml @@ -1,6 +1,6 @@ - + @@ -8,14 +8,20 @@ - + - + - - + @@ -40,8 +46,8 @@ ..., [163368.0, 163392.0], [163392.0, 163416.0], - [163416.0, 163440.0]]" id="2789ad5b" points="[154824.0, 154848.0, 154872.0, ..., 163392.0, - 163416.0, 163440.0]" shape="(360,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64" var_name="time"/> + [163416.0, 163440.0]]" id="cb784457" points="[154812.0, 154836.0, 154860.0, ..., 163380.0, + 163404.0, 163428.0]" shape="(360,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64" var_name="time"/> @@ -49,6 +55,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/abxpa_press_lat.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/abxpa_press_lat.b_0.cml index 7e6e379601..bd4411c1b3 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/abxpa_press_lat.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/abxpa_press_lat.b_0.cml @@ -1,6 +1,6 @@ - + @@ -8,13 +8,13 @@ - + - + - - - + @@ -41,6 +41,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/integer.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/integer.b_0.cml index 0588b2b9a0..53bcfc067d 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/integer.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/integer.b_0.cml @@ -1,19 +1,19 @@ - + - + - + - - + - + @@ -41,6 +41,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/model.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/model.b_0.cml index e4616b3317..186c1f6f48 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/model.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/model.b_0.cml @@ -1,6 +1,6 @@ - + @@ -8,16 +8,38 @@ - + - + - - + - @@ -62,11 +84,11 @@ [195840.0, 204480.0], [204480.0, 213120.0], [213120.0, 221760.0], - [221760.0, 230400.0]]" id="2789ad5b" points="[48960.0, 57600.0, 66240.0, 74880.0, 83520.0, - 92160.0, 100800.0, 109440.0, 118080.0, 126720.0, - 135360.0, 144000.0, 152640.0, 161280.0, - 169920.0, 178560.0, 187200.0, 195840.0, - 204480.0, 213120.0, 221760.0, 230400.0]" shape="(22,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64" var_name="time"/> + [221760.0, 230400.0]]" id="cb784457" points="[44640.0, 53280.0, 61920.0, 70560.0, 79200.0, + 87840.0, 96480.0, 105120.0, 113760.0, 122400.0, + 131040.0, 139680.0, 148320.0, 156960.0, + 165600.0, 174240.0, 182880.0, 191520.0, + 200160.0, 208800.0, 217440.0, 226080.0]" shape="(22,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64" var_name="time"/> @@ -74,6 +96,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/ocean_xsect.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/ocean_xsect.b_0.cml index 0e1cf99e1d..8f01a6c707 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/ocean_xsect.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/ocean_xsect.b_0.cml @@ -1,6 +1,6 @@ - + @@ -27,7 +27,7 @@ [3039.0, 3654.3], [3654.3, 4269.5], [4269.5, 4884.8], - [4884.8, 5500.1]]" id="e2b6e055" points="[5.0, 15.0, 25.0, 35.1, 47.85, 67.0, 95.75, + [4884.8, 5500.1]]" id="c88482b3" points="[5.0, 15.0, 25.0, 35.1, 47.85, 67.0, 95.75, 138.9, 203.7, 301.0, 447.05, 666.3, 995.55, 1500.85, 2116.15, 2731.4, 3346.65, 3961.9, 4577.15, 5192.45]" shape="(20,)" standard_name="depth" units="Unit('m')" value_type="float32" var_name="depth"> @@ -37,19 +37,19 @@ - + - + - - + @@ -57,6 +57,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/st0fc699.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/st0fc699.b_0.cml index 81fb0bc2b9..c67d6f4ce3 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/st0fc699.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/st0fc699.b_0.cml @@ -1,6 +1,6 @@ - + @@ -8,24 +8,24 @@ - + - + - - + - + @@ -33,6 +33,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/st0fc942.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/st0fc942.b_0.cml index 85b60eaf95..5dc6fb5c9c 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/st0fc942.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/st0fc942.b_0.cml @@ -1,6 +1,6 @@ - + @@ -8,7 +8,7 @@ - @@ -18,24 +18,27 @@ - + - + - + - + + [-432720.0, -259920.0]]" id="cb784457" points="[-864720.0, -691920.0, -519120.0, -346320.0]" shape="(4,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64" var_name="time"/> @@ -43,6 +46,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/st30211.b_0.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/st30211.b_0.cml index b85aba915f..1c803423b3 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/st30211.b_0.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_netcdf/st30211.b_0.cml @@ -1,6 +1,6 @@ - + @@ -8,29 +8,32 @@ - + - + - + - + - + + [-432720.0, -259920.0]]" id="cb784457" points="[-864720.0, -691920.0, -519120.0, -346320.0]" shape="(4,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64" var_name="time"/> @@ -38,6 +41,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/000003000000.03.236.000128.1990.12.01.00.00.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/000003000000.03.236.000128.1990.12.01.00.00.b.cml index a221506a29..d5d05f15fd 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/000003000000.03.236.000128.1990.12.01.00.00.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/000003000000.03.236.000128.1990.12.01.00.00.b.cml @@ -1,26 +1,26 @@ - + - + - + - + - - + - + @@ -47,6 +47,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/000003000000.03.236.004224.1990.12.01.00.00.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/000003000000.03.236.004224.1990.12.01.00.00.b.cml index c643d3c150..1f4d8a4b2c 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/000003000000.03.236.004224.1990.12.01.00.00.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/000003000000.03.236.004224.1990.12.01.00.00.b.cml @@ -1,26 +1,26 @@ - + - + - + - + - - + - + @@ -47,6 +47,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/000003000000.03.236.008320.1990.12.01.00.00.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/000003000000.03.236.008320.1990.12.01.00.00.b.cml index f4840c8b4d..359cba997f 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/000003000000.03.236.008320.1990.12.01.00.00.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/000003000000.03.236.008320.1990.12.01.00.00.b.cml @@ -1,6 +1,6 @@ - + @@ -8,20 +8,20 @@ - + - + - + - - + - + - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/000003000000.16.202.000128.1860.09.01.00.00.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/000003000000.16.202.000128.1860.09.01.00.00.b.cml index 301a5c906c..54e3824d6d 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/000003000000.16.202.000128.1860.09.01.00.00.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/000003000000.16.202.000128.1860.09.01.00.00.b.cml @@ -1,19 +1,19 @@ - + - + - + - - + - + - + @@ -44,6 +44,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/001000000000.00.000.000000.1860.01.01.00.00.f.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/001000000000.00.000.000000.1860.01.01.00.00.f.b.cml index 2286230ac9..7fef4515a2 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/001000000000.00.000.000000.1860.01.01.00.00.f.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/001000000000.00.000.000000.1860.01.01.00.00.f.b.cml @@ -1,30 +1,30 @@ - + - + - + - - - + - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/002000000000.44.101.131200.1920.09.01.00.00.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/002000000000.44.101.131200.1920.09.01.00.00.b.cml index 5f0d248ee9..f41f4a284a 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/002000000000.44.101.131200.1920.09.01.00.00.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/002000000000.44.101.131200.1920.09.01.00.00.b.cml @@ -1,6 +1,6 @@ - + @@ -8,7 +8,7 @@ - @@ -18,13 +18,13 @@ - + - + - + - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/008000000000.44.101.000128.1890.09.01.00.00.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/008000000000.44.101.000128.1890.09.01.00.00.b.cml index 07213e7a42..e8d2cb7735 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/008000000000.44.101.000128.1890.09.01.00.00.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/008000000000.44.101.000128.1890.09.01.00.00.b.cml @@ -1,13 +1,13 @@ - + - @@ -17,7 +17,7 @@ - @@ -28,6 +28,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/12187.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/12187.b.cml index 71ea26da6a..7e35faceda 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/12187.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/12187.b.cml @@ -1,19 +1,20 @@ - + - + + - + - + - + @@ -55,7 +56,7 @@ [25521.0, 27901.4], [27901.4, 31063.9], [31063.9, 36081.8], - [36081.8, 42427.9]]" id="218bea13" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, + [36081.8, 42427.9]]" id="fb105c19" long_name="level_height" points="[20.0003, 80.0014, 179.999, 320.001, 500.001, 720.0, 980.001, 1280.0, 1620.0, 2000.0, 2420.0, 2880.0, 3380.0, 3920.0, 4500.0, 5120.0, 5780.0, 6480.0, 7220.0, 8000.0, 8820.0, 9680.0, 10580.0, @@ -68,12 +69,12 @@ - + - @@ -119,7 +120,7 @@ [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], - [0.0, 0.0]]" id="5f88ebd6" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, + [0.0, 0.0]]" id="a5c170db" long_name="sigma" points="[0.997716, 0.990882, 0.979543, 0.963777, 0.943695, 0.919438, 0.891178, 0.859118, 0.823493, 0.784571, 0.742646, 0.69805, 0.651143, 0.602314, 0.551989, 0.50062, 0.448693, 0.396726, @@ -129,7 +130,7 @@ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]" shape="(38,)" units="Unit('1')" value_type="float32"/> - + @@ -137,6 +138,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/HadCM2_ts_SAT_ann_18602100.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/HadCM2_ts_SAT_ann_18602100.b.cml index bbf723e677..69f597d697 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/HadCM2_ts_SAT_ann_18602100.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/HadCM2_ts_SAT_ann_18602100.b.cml @@ -1,33 +1,33 @@ - + - + + [-89.9, 1.24998]]" id="77a50eb5" points="[0.0, 45.575, -44.325]" shape="(3,)" standard_name="latitude" units="Unit('degrees')" value_type="float32"> + [-1.875, 358.125]]" id="f913a8b3" points="[178.125, 178.125, 178.125]" shape="(3,)" standard_name="longitude" units="Unit('degrees')" value_type="float32"> - + - @@ -36,6 +36,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_level_lat_orig.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_level_lat_orig.b.cml index 28b6916a8b..d24575ca39 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_level_lat_orig.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_level_lat_orig.b.cml @@ -1,19 +1,20 @@ - + - + - + - - + [1226160.0, 1398960.0]]" id="cb784457" points="[1139760.0, 1312560.0]" shape="(2,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64"/> @@ -41,6 +42,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_lon_lat_press_orig.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_lon_lat_press_orig.b.cml index 4995242a11..358208d7b3 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_lon_lat_press_orig.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_lon_lat_press_orig.b.cml @@ -1,19 +1,20 @@ - + - + - + - - + - + [1226160.0, 1398960.0]]" id="cb784457" points="[1139760.0, 1312560.0]" shape="(2,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64"/> @@ -46,6 +47,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_lon_lat_several.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_lon_lat_several.b.cml index 425d2bc9da..93f156d33d 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_lon_lat_several.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_lon_lat_several.b.cml @@ -1,28 +1,42 @@ - + - + - + - + - - + @@ -54,10 +68,10 @@ [1060560.0, 1061280.0], [1061280.0, 1062000.0], [1062000.0, 1062720.0], - [1062720.0, 1063440.0]]" id="4c12dc80" points="[1054080.0, 1054800.0, 1055520.0, 1056240.0, - 1056960.0, 1057680.0, 1058400.0, 1059120.0, - 1059840.0, 1060560.0, 1061280.0, 1062000.0, - 1062720.0, 1063440.0]" shape="(14,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64"/> + [1062720.0, 1063440.0]]" id="cb784457" points="[1053720.0, 1054440.0, 1055160.0, 1055880.0, + 1056600.0, 1057320.0, 1058040.0, 1058760.0, + 1059480.0, 1060200.0, 1060920.0, 1061640.0, + 1062360.0, 1063080.0]" shape="(14,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64"/> @@ -65,6 +79,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_n10r13xy.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_n10r13xy.b.cml index 7192afdcfa..33ec73acee 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_n10r13xy.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_n10r13xy.b.cml @@ -1,27 +1,30 @@ - + - + - + - + - - @@ -30,7 +33,7 @@ + [1079280.0, 1081440.0]]" id="cb784457" points="[1054440.0, 1063080.0, 1071720.0, 1080360.0]" shape="(4,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64"/> @@ -38,6 +41,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_time_press.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_time_press.b.cml index 43ea1717ab..ad54273ae2 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_time_press.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_time_press.b.cml @@ -1,18 +1,18 @@ - + - - + @@ -20,6 +20,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_tseries.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_tseries.b.cml index 2a83c5ad93..6f3a5af440 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_tseries.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/aaxzc_tseries.b.cml @@ -1,23 +1,23 @@ - + - + - + - + @@ -25,6 +25,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/abcza_pa19591997_daily_29.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/abcza_pa19591997_daily_29.b.cml index 32a492a0a7..f3a4d8dd0d 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/abcza_pa19591997_daily_29.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/abcza_pa19591997_daily_29.b.cml @@ -1,27 +1,33 @@ - + - + - + - + - - + @@ -46,8 +52,8 @@ ..., [163368.0, 163392.0], [163392.0, 163416.0], - [163416.0, 163440.0]]" id="4c12dc80" points="[154824.0, 154848.0, 154872.0, ..., 163392.0, - 163416.0, 163440.0]" shape="(360,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64"/> + [163416.0, 163440.0]]" id="cb784457" points="[154812.0, 154836.0, 154860.0, ..., 163380.0, + 163404.0, 163428.0]" shape="(360,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64"/> @@ -55,30 +61,36 @@ - + - + - + - + - + - - + @@ -103,8 +115,8 @@ ..., [163368.0, 163392.0], [163392.0, 163416.0], - [163416.0, 163440.0]]" id="4c12dc80" points="[154824.0, 154848.0, 154872.0, ..., 163392.0, - 163416.0, 163440.0]" shape="(360,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64"/> + [163416.0, 163440.0]]" id="cb784457" points="[154812.0, 154836.0, 154860.0, ..., 163380.0, + 163404.0, 163428.0]" shape="(360,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64"/> @@ -112,23 +124,29 @@ - + - + - + - + - - + @@ -153,8 +171,8 @@ ..., [163368.0, 163392.0], [163392.0, 163416.0], - [163416.0, 163440.0]]" id="4c12dc80" points="[154824.0, 154848.0, 154872.0, ..., 163392.0, - 163416.0, 163440.0]" shape="(360,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64"/> + [163416.0, 163440.0]]" id="cb784457" points="[154812.0, 154836.0, 154860.0, ..., 163380.0, + 163404.0, 163428.0]" shape="(360,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64"/> @@ -162,6 +180,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/abxpa_press_lat.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/abxpa_press_lat.b.cml index 193b4b003e..0fbbd81c74 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/abxpa_press_lat.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/abxpa_press_lat.b.cml @@ -1,19 +1,19 @@ - + - + - + - - - + @@ -40,6 +40,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/integer.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/integer.b.cml index 064f80d44d..9cad8ea176 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/integer.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/integer.b.cml @@ -1,18 +1,18 @@ - + - + - + - - + - + @@ -40,6 +40,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/model.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/model.b.cml index 71df873839..2f8db655cc 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/model.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/model.b.cml @@ -1,22 +1,44 @@ - + - + - + - - + - @@ -61,11 +83,11 @@ [195840.0, 204480.0], [204480.0, 213120.0], [213120.0, 221760.0], - [221760.0, 230400.0]]" id="4c12dc80" points="[48960.0, 57600.0, 66240.0, 74880.0, 83520.0, - 92160.0, 100800.0, 109440.0, 118080.0, 126720.0, - 135360.0, 144000.0, 152640.0, 161280.0, - 169920.0, 178560.0, 187200.0, 195840.0, - 204480.0, 213120.0, 221760.0, 230400.0]" shape="(22,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64"/> + [221760.0, 230400.0]]" id="cb784457" points="[44640.0, 53280.0, 61920.0, 70560.0, 79200.0, + 87840.0, 96480.0, 105120.0, 113760.0, 122400.0, + 131040.0, 139680.0, 148320.0, 156960.0, + 165600.0, 174240.0, 182880.0, 191520.0, + 200160.0, 208800.0, 217440.0, 226080.0]" shape="(22,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64"/> @@ -73,6 +95,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/ocean_xsect.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/ocean_xsect.b.cml index 0b70208aac..cd4e742da9 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/ocean_xsect.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/ocean_xsect.b.cml @@ -1,6 +1,6 @@ - + @@ -26,7 +26,7 @@ [3039.0, 3654.3], [3654.3, 4269.5], [4269.5, 4884.8], - [4884.8, 5500.1]]" id="5e355df2" points="[5.0, 15.0, 25.0, 35.1, 47.85, 67.0, 95.75, + [4884.8, 5500.1]]" id="c88482b3" points="[5.0, 15.0, 25.0, 35.1, 47.85, 67.0, 95.75, 138.9, 203.7, 301.0, 447.05, 666.3, 995.55, 1500.85, 2116.15, 2731.4, 3346.65, 3961.9, 4577.15, 5192.45]" shape="(20,)" standard_name="depth" units="Unit('m')" value_type="float32"> @@ -36,19 +36,19 @@ - + - + - - + @@ -56,6 +56,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/st0fc699.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/st0fc699.b.cml index aacf233825..0a9e0a7bcb 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/st0fc699.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/st0fc699.b.cml @@ -1,30 +1,30 @@ - + - + - + - - + - + @@ -32,6 +32,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/st0fc942.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/st0fc942.b.cml index 767689a465..fd775483e9 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/st0fc942.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/st0fc942.b.cml @@ -1,13 +1,13 @@ - + - @@ -17,24 +17,27 @@ - + - + - + - + + [-432720.0, -259920.0]]" id="cb784457" points="[-864720.0, -691920.0, -519120.0, -346320.0]" shape="(4,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64"/> @@ -42,6 +45,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/st30211.b.cml b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/st30211.b.cml index 74f599ab6f..2a49cf6c71 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/st30211.b.cml +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/from_pp/st30211.b.cml @@ -1,35 +1,38 @@ - + - + - + - + - + - + + [-432720.0, -259920.0]]" id="cb784457" points="[-864720.0, -691920.0, -519120.0, -346320.0]" shape="(4,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='360_day')" value_type="float64"/> @@ -37,6 +40,6 @@ - + diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/000003000000.03.236.000128.1990.12.01.00.00.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/000003000000.03.236.000128.1990.12.01.00.00.b_0.cdl index 15c37e5094..a523f32b78 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/000003000000.03.236.000128.1990.12.01.00.00.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/000003000000.03.236.000128.1990.12.01.00.00.b_0.cdl @@ -1,20 +1,20 @@ dimensions: - latitude = UNLIMITED ; // (73 currently) bnds = 2 ; + latitude = 73 ; longitude = 96 ; variables: float air_temperature(latitude, longitude) ; + air_temperature:_FillValue = 9.96921e+36f ; air_temperature:standard_name = "air_temperature" ; air_temperature:units = "K" ; - air_temperature:ukmo__um_stash_source = "m01s03i236" ; + air_temperature:um_stash_source = "m01s03i236" ; air_temperature:cell_methods = "time: mean (interval: 6 hour)" ; air_temperature:grid_mapping = "latitude_longitude" ; air_temperature:coordinates = "forecast_period forecast_reference_time height time" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; float latitude(latitude) ; latitude:axis = "Y" ; latitude:units = "degrees_north" ; @@ -23,9 +23,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period ; + double forecast_period ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/000003000000.03.236.004224.1990.12.01.00.00.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/000003000000.03.236.004224.1990.12.01.00.00.b_0.cdl index 15c37e5094..a523f32b78 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/000003000000.03.236.004224.1990.12.01.00.00.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/000003000000.03.236.004224.1990.12.01.00.00.b_0.cdl @@ -1,20 +1,20 @@ dimensions: - latitude = UNLIMITED ; // (73 currently) bnds = 2 ; + latitude = 73 ; longitude = 96 ; variables: float air_temperature(latitude, longitude) ; + air_temperature:_FillValue = 9.96921e+36f ; air_temperature:standard_name = "air_temperature" ; air_temperature:units = "K" ; - air_temperature:ukmo__um_stash_source = "m01s03i236" ; + air_temperature:um_stash_source = "m01s03i236" ; air_temperature:cell_methods = "time: mean (interval: 6 hour)" ; air_temperature:grid_mapping = "latitude_longitude" ; air_temperature:coordinates = "forecast_period forecast_reference_time height time" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; float latitude(latitude) ; latitude:axis = "Y" ; latitude:units = "degrees_north" ; @@ -23,9 +23,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period ; + double forecast_period ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/000003000000.03.236.008320.1990.12.01.00.00.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/000003000000.03.236.008320.1990.12.01.00.00.b_0.cdl index 46d8712849..ab34087917 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/000003000000.03.236.008320.1990.12.01.00.00.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/000003000000.03.236.008320.1990.12.01.00.00.b_0.cdl @@ -1,20 +1,20 @@ dimensions: - latitude = UNLIMITED ; // (73 currently) bnds = 2 ; + latitude = 73 ; longitude = 96 ; variables: float air_temperature(latitude, longitude) ; + air_temperature:_FillValue = 9.96921e+36f ; air_temperature:standard_name = "air_temperature" ; air_temperature:units = "K" ; - air_temperature:ukmo__um_stash_source = "m01s03i236" ; + air_temperature:um_stash_source = "m01s03i236" ; air_temperature:ukmo__process_flags = "Maximum_value_of_field_during_time_period Time_mean_field" ; air_temperature:grid_mapping = "latitude_longitude" ; air_temperature:coordinates = "forecast_period forecast_reference_time height time" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; float latitude(latitude) ; latitude:axis = "Y" ; latitude:units = "degrees_north" ; @@ -23,9 +23,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period ; + double forecast_period ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/000003000000.16.202.000128.1860.09.01.00.00.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/000003000000.16.202.000128.1860.09.01.00.00.b_0.cdl index ef7af2e658..531f8f2e7d 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/000003000000.16.202.000128.1860.09.01.00.00.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/000003000000.16.202.000128.1860.09.01.00.00.b_0.cdl @@ -1,21 +1,21 @@ dimensions: - pressure = UNLIMITED ; // (3 currently) bnds = 2 ; latitude = 73 ; longitude = 96 ; + pressure = 3 ; variables: float geopotential_height(pressure, latitude, longitude) ; + geopotential_height:_FillValue = 9.96921e+36f ; geopotential_height:standard_name = "geopotential_height" ; geopotential_height:units = "m" ; - geopotential_height:ukmo__um_stash_source = "m01s16i202" ; + geopotential_height:um_stash_source = "m01s16i202" ; geopotential_height:cell_methods = "time: mean (interval: 4 hour)" ; geopotential_height:grid_mapping = "latitude_longitude" ; geopotential_height:coordinates = "forecast_period forecast_reference_time time" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; float pressure(pressure) ; pressure:axis = "Z" ; pressure:units = "hPa" ; @@ -28,9 +28,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period ; + double forecast_period ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/001000000000.00.000.000000.1860.01.01.00.00.f.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/001000000000.00.000.000000.1860.01.01.00.00.f.b_0.cdl index 96026f66f3..862a8c66ae 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/001000000000.00.000.000000.1860.01.01.00.00.f.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/001000000000.00.000.000000.1860.01.01.00.00.f.b_0.cdl @@ -1,10 +1,10 @@ dimensions: - latitude = UNLIMITED ; // (94 currently) bnds = 2 ; + latitude = 94 ; longitude = 128 ; variables: float sea_surface_height_above_geoid(latitude, longitude) ; - sea_surface_height_above_geoid:_FillValue = -1.e+30f ; + sea_surface_height_above_geoid:_FillValue = 9.96921e+36f ; sea_surface_height_above_geoid:standard_name = "sea_surface_height_above_geoid" ; sea_surface_height_above_geoid:units = "m" ; sea_surface_height_above_geoid:grid_mapping = "latitude_longitude" ; @@ -12,8 +12,7 @@ variables: int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; float latitude(latitude) ; latitude:axis = "Y" ; latitude:units = "degrees_north" ; @@ -22,9 +21,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period ; + double forecast_period ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/002000000000.44.101.131200.1920.09.01.00.00.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/002000000000.44.101.131200.1920.09.01.00.00.b_0.cdl index fa61ca1021..9a1d5b8d8a 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/002000000000.44.101.131200.1920.09.01.00.00.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/002000000000.44.101.131200.1920.09.01.00.00.b_0.cdl @@ -1,19 +1,18 @@ dimensions: - depth = UNLIMITED ; // (20 currently) bnds = 2 ; + depth = 20 ; latitude = 73 ; variables: - float unknown(depth, latitude) ; - unknown:_FillValue = -1.e+30f ; - unknown:ukmo__um_stash_source = "m??s44i101" ; - unknown:ukmo__process_flags = "Mean_over_an_ensemble_of_parallel_runs Time_mean_field" ; - unknown:grid_mapping = "latitude_longitude" ; - unknown:coordinates = "forecast_period forecast_reference_time time" ; + float m__s44i101(depth, latitude) ; + m__s44i101:_FillValue = 9.96921e+36f ; + m__s44i101:um_stash_source = "m??s44i101" ; + m__s44i101:ukmo__process_flags = "Mean_over_an_ensemble_of_parallel_runs Time_mean_field" ; + m__s44i101:grid_mapping = "latitude_longitude" ; + m__s44i101:coordinates = "forecast_period forecast_reference_time time" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; float depth(depth) ; depth:axis = "Z" ; depth:units = "m" ; @@ -23,9 +22,11 @@ variables: latitude:axis = "Y" ; latitude:units = "degrees_north" ; latitude:standard_name = "latitude" ; - int forecast_period ; + double forecast_period ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/008000000000.44.101.000128.1890.09.01.00.00.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/008000000000.44.101.000128.1890.09.01.00.00.b_0.cdl index 9217de49fa..299adc662e 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/008000000000.44.101.000128.1890.09.01.00.00.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/008000000000.44.101.000128.1890.09.01.00.00.b_0.cdl @@ -1,10 +1,11 @@ dimensions: - depth = UNLIMITED ; // (20 currently) + depth = 20 ; time = 16 ; variables: - float unknown(depth, time) ; - unknown:ukmo__um_stash_source = "m??s44i101" ; - unknown:cell_methods = "time: mean (interval: 24 hour)" ; + float m__s44i101(depth, time) ; + m__s44i101:_FillValue = 9.96921e+36f ; + m__s44i101:um_stash_source = "m??s44i101" ; + m__s44i101:cell_methods = "time: mean (interval: 24 hour)" ; float depth(depth) ; depth:axis = "Z" ; depth:units = "m" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/12187.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/12187.b_0.cdl index 039273f406..2044e2bc06 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/12187.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/12187.b_0.cdl @@ -1,21 +1,21 @@ dimensions: - model_level_number = UNLIMITED ; // (38 currently) bnds = 2 ; latitude = 145 ; longitude = 192 ; + model_level_number = 38 ; variables: - float tendency_of_upward_air_velocity_due_to_advection(model_level_number, latitude, longitude) ; - tendency_of_upward_air_velocity_due_to_advection:standard_name = "tendency_of_upward_air_velocity_due_to_advection" ; - tendency_of_upward_air_velocity_due_to_advection:units = "m s-1" ; - tendency_of_upward_air_velocity_due_to_advection:ukmo__um_stash_source = "m01s12i187" ; - tendency_of_upward_air_velocity_due_to_advection:cell_methods = "time: mean (interval: 1 hour)" ; - tendency_of_upward_air_velocity_due_to_advection:grid_mapping = "latitude_longitude" ; - tendency_of_upward_air_velocity_due_to_advection:coordinates = "forecast_period forecast_reference_time level_height sigma time" ; + float change_over_time_in_upward_air_velocity_due_to_advection(model_level_number, latitude, longitude) ; + change_over_time_in_upward_air_velocity_due_to_advection:_FillValue = 9.96921e+36f ; + change_over_time_in_upward_air_velocity_due_to_advection:long_name = "change_over_time_in_upward_air_velocity_due_to_advection" ; + change_over_time_in_upward_air_velocity_due_to_advection:units = "m s-1" ; + change_over_time_in_upward_air_velocity_due_to_advection:um_stash_source = "m01s12i187" ; + change_over_time_in_upward_air_velocity_due_to_advection:cell_methods = "time: mean (interval: 1 hour)" ; + change_over_time_in_upward_air_velocity_due_to_advection:grid_mapping = "latitude_longitude" ; + change_over_time_in_upward_air_velocity_due_to_advection:coordinates = "forecast_period forecast_reference_time level_height sigma time" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; int model_level_number(model_level_number) ; model_level_number:axis = "Z" ; model_level_number:units = "1" ; @@ -29,9 +29,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period ; + double forecast_period ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; @@ -55,6 +57,7 @@ variables: double time_bnds(bnds) ; // global attributes: - :source = "Data from Met Office Unified Model 6.01" ; + :source = "Data from Met Office Unified Model" ; + :um_version = "6.1" ; :Conventions = "CF-1.5" ; } diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/HadCM2_ts_SAT_ann_18602100.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/HadCM2_ts_SAT_ann_18602100.b_0.cdl index 582ab8caa9..43530865bd 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/HadCM2_ts_SAT_ann_18602100.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/HadCM2_ts_SAT_ann_18602100.b_0.cdl @@ -1,20 +1,20 @@ dimensions: - time = UNLIMITED ; // (240 currently) bnds = 2 ; site_number = 3 ; + time = 240 ; variables: float air_temperature(time, site_number) ; + air_temperature:_FillValue = 9.96921e+36f ; air_temperature:standard_name = "air_temperature" ; air_temperature:units = "Celsius" ; - air_temperature:ukmo__um_stash_source = "m01s03i236" ; + air_temperature:um_stash_source = "m01s03i236" ; air_temperature:cell_methods = "time: mean" ; air_temperature:grid_mapping = "latitude_longitude" ; air_temperature:coordinates = "height latitude longitude" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; float time(time) ; time:axis = "T" ; time:units = "days since 0000-01-01 00:00:00" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_level_lat_orig.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_level_lat_orig.b_0.cdl index 61385b78cb..dfbf6839b0 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_level_lat_orig.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_level_lat_orig.b_0.cdl @@ -1,21 +1,21 @@ dimensions: - time = UNLIMITED ; // (2 currently) bnds = 2 ; latitude = 73 ; pressure = 15 ; + time = 2 ; variables: float geopotential_height(time, pressure, latitude) ; + geopotential_height:_FillValue = 9.96921e+36f ; geopotential_height:standard_name = "geopotential_height" ; geopotential_height:units = "m" ; - geopotential_height:ukmo__um_stash_source = "m01s16i202" ; + geopotential_height:um_stash_source = "m01s16i202" ; geopotential_height:cell_methods = "time: mean" ; geopotential_height:grid_mapping = "latitude_longitude" ; geopotential_height:coordinates = "forecast_period forecast_reference_time" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; double time(time) ; time:axis = "T" ; time:bounds = "time_bnds" ; @@ -31,9 +31,11 @@ variables: latitude:axis = "Y" ; latitude:units = "degrees_north" ; latitude:standard_name = "latitude" ; - int forecast_period(time) ; + double forecast_period(time) ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(time, bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_lon_lat_press_orig.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_lon_lat_press_orig.b_0.cdl index 7c8a638744..ffff50f425 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_lon_lat_press_orig.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_lon_lat_press_orig.b_0.cdl @@ -1,22 +1,22 @@ dimensions: - time = UNLIMITED ; // (2 currently) bnds = 2 ; latitude = 73 ; longitude = 96 ; pressure = 15 ; + time = 2 ; variables: float geopotential_height(time, pressure, latitude, longitude) ; + geopotential_height:_FillValue = 9.96921e+36f ; geopotential_height:standard_name = "geopotential_height" ; geopotential_height:units = "m" ; - geopotential_height:ukmo__um_stash_source = "m01s16i202" ; + geopotential_height:um_stash_source = "m01s16i202" ; geopotential_height:cell_methods = "time: mean" ; geopotential_height:grid_mapping = "latitude_longitude" ; geopotential_height:coordinates = "forecast_period forecast_reference_time" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; double time(time) ; time:axis = "T" ; time:bounds = "time_bnds" ; @@ -36,9 +36,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period(time) ; + double forecast_period(time) ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(time, bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_lon_lat_several.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_lon_lat_several.b_0.cdl index bfc188c8e4..18ab8d865e 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_lon_lat_several.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_lon_lat_several.b_0.cdl @@ -1,21 +1,21 @@ dimensions: - time = UNLIMITED ; // (14 currently) bnds = 2 ; latitude = 73 ; longitude = 96 ; + time = 14 ; variables: float air_temperature(time, latitude, longitude) ; + air_temperature:_FillValue = 9.96921e+36f ; air_temperature:standard_name = "air_temperature" ; air_temperature:units = "K" ; - air_temperature:ukmo__um_stash_source = "m01s03i236" ; + air_temperature:um_stash_source = "m01s03i236" ; air_temperature:cell_methods = "time: mean (interval: 1 hour)" ; air_temperature:grid_mapping = "latitude_longitude" ; air_temperature:coordinates = "forecast_period forecast_reference_time height" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; double time(time) ; time:axis = "T" ; time:bounds = "time_bnds" ; @@ -31,9 +31,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period(time) ; + double forecast_period(time) ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(time, bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_n10r13xy.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_n10r13xy.b_0.cdl index 8eafeb9941..4ca612826d 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_n10r13xy.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_n10r13xy.b_0.cdl @@ -1,18 +1,20 @@ dimensions: - time = UNLIMITED ; // (4 currently) bnds = 2 ; latitude = 13 ; longitude = 10 ; + time = 4 ; variables: - float unknown(time, latitude, longitude) ; - unknown:cell_methods = "time: mean (interval: 1 hour)" ; - unknown:grid_mapping = "latitude_longitude" ; - unknown:coordinates = "forecast_period forecast_reference_time height" ; + float air_temperature(time, latitude, longitude) ; + air_temperature:_FillValue = 9.96921e+36f ; + air_temperature:standard_name = "air_temperature" ; + air_temperature:units = "K" ; + air_temperature:cell_methods = "time: mean (interval: 1 hour)" ; + air_temperature:grid_mapping = "latitude_longitude" ; + air_temperature:coordinates = "forecast_period forecast_reference_time height" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; double time(time) ; time:axis = "T" ; time:bounds = "time_bnds" ; @@ -28,9 +30,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period(time) ; + double forecast_period(time) ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(time, bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_time_press.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_time_press.b_0.cdl index da51832c5e..0a19ff646a 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_time_press.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_time_press.b_0.cdl @@ -1,11 +1,12 @@ dimensions: - pressure = UNLIMITED ; // (15 currently) + pressure = 15 ; time = 4 ; variables: float geopotential_height(pressure, time) ; + geopotential_height:_FillValue = 9.96921e+36f ; geopotential_height:standard_name = "geopotential_height" ; geopotential_height:units = "m" ; - geopotential_height:ukmo__um_stash_source = "m01s16i202" ; + geopotential_height:um_stash_source = "m01s16i202" ; geopotential_height:cell_methods = "time: mean" ; float pressure(pressure) ; pressure:axis = "Z" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_tseries.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_tseries.b_0.cdl index 516a8dd652..1e72aac281 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_tseries.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/aaxzc_tseries.b_0.cdl @@ -1,11 +1,12 @@ dimensions: - time = UNLIMITED ; // (4 currently) site_number = 1 ; + time = 4 ; variables: float air_temperature(time, site_number) ; + air_temperature:_FillValue = 9.96921e+36f ; air_temperature:standard_name = "air_temperature" ; air_temperature:units = "K" ; - air_temperature:ukmo__um_stash_source = "m01s03i236" ; + air_temperature:um_stash_source = "m01s03i236" ; air_temperature:cell_methods = "time: mean" ; air_temperature:coordinates = "height" ; float time(time) ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/abcza_pa19591997_daily_29.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/abcza_pa19591997_daily_29.b_0.cdl index 28761c7096..00659bb8ad 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/abcza_pa19591997_daily_29.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/abcza_pa19591997_daily_29.b_0.cdl @@ -1,21 +1,21 @@ dimensions: - time = UNLIMITED ; // (360 currently) bnds = 2 ; latitude = 73 ; longitude = 96 ; + time = 360 ; variables: float air_temperature(time, latitude, longitude) ; + air_temperature:_FillValue = 9.96921e+36f ; air_temperature:standard_name = "air_temperature" ; air_temperature:units = "K" ; - air_temperature:ukmo__um_stash_source = "m01s03i236" ; + air_temperature:um_stash_source = "m01s03i236" ; air_temperature:cell_methods = "time: maximum (interval: 1 hour)" ; air_temperature:grid_mapping = "latitude_longitude" ; air_temperature:coordinates = "forecast_period forecast_reference_time height" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; double time(time) ; time:axis = "T" ; time:bounds = "time_bnds" ; @@ -31,9 +31,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period(time) ; + double forecast_period(time) ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(time, bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/abcza_pa19591997_daily_29.b_1.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/abcza_pa19591997_daily_29.b_1.cdl index aa77f8c552..8fdedb8d3c 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/abcza_pa19591997_daily_29.b_1.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/abcza_pa19591997_daily_29.b_1.cdl @@ -1,21 +1,21 @@ dimensions: - time = UNLIMITED ; // (360 currently) bnds = 2 ; latitude = 73 ; longitude = 96 ; + time = 360 ; variables: float air_temperature(time, latitude, longitude) ; + air_temperature:_FillValue = 9.96921e+36f ; air_temperature:standard_name = "air_temperature" ; air_temperature:units = "K" ; - air_temperature:ukmo__um_stash_source = "m01s03i236" ; + air_temperature:um_stash_source = "m01s03i236" ; air_temperature:cell_methods = "time: minimum (interval: 1 hour)" ; air_temperature:grid_mapping = "latitude_longitude" ; air_temperature:coordinates = "forecast_period forecast_reference_time height" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; double time(time) ; time:axis = "T" ; time:bounds = "time_bnds" ; @@ -31,9 +31,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period(time) ; + double forecast_period(time) ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(time, bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/abcza_pa19591997_daily_29.b_2.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/abcza_pa19591997_daily_29.b_2.cdl index e083b79734..85c9b348cf 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/abcza_pa19591997_daily_29.b_2.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/abcza_pa19591997_daily_29.b_2.cdl @@ -1,21 +1,21 @@ dimensions: - time = UNLIMITED ; // (360 currently) bnds = 2 ; latitude = 73 ; longitude = 96 ; + time = 360 ; variables: float precipitation_flux(time, latitude, longitude) ; + precipitation_flux:_FillValue = 9.96921e+36f ; precipitation_flux:standard_name = "precipitation_flux" ; precipitation_flux:units = "kg m-2 s-1" ; - precipitation_flux:ukmo__um_stash_source = "m01s05i216" ; + precipitation_flux:um_stash_source = "m01s05i216" ; precipitation_flux:cell_methods = "time: mean (interval: 1 hour)" ; precipitation_flux:grid_mapping = "latitude_longitude" ; precipitation_flux:coordinates = "forecast_period forecast_reference_time" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; double time(time) ; time:axis = "T" ; time:bounds = "time_bnds" ; @@ -31,9 +31,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period(time) ; + double forecast_period(time) ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(time, bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/abxpa_press_lat.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/abxpa_press_lat.b_0.cdl index 7b24c1a3c4..fea73514b1 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/abxpa_press_lat.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/abxpa_press_lat.b_0.cdl @@ -1,20 +1,20 @@ dimensions: - pressure = UNLIMITED ; // (15 currently) bnds = 2 ; latitude = 73 ; + pressure = 15 ; variables: float geopotential_height(pressure, latitude) ; + geopotential_height:_FillValue = 9.96921e+36f ; geopotential_height:standard_name = "geopotential_height" ; geopotential_height:units = "m" ; - geopotential_height:ukmo__um_stash_source = "m01s16i202" ; + geopotential_height:um_stash_source = "m01s16i202" ; geopotential_height:cell_methods = "time: mean (interval: 4 hour)" ; geopotential_height:grid_mapping = "latitude_longitude" ; geopotential_height:coordinates = "forecast_period forecast_reference_time time" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; float pressure(pressure) ; pressure:axis = "Z" ; pressure:units = "hPa" ; @@ -23,9 +23,11 @@ variables: latitude:axis = "Y" ; latitude:units = "degrees_north" ; latitude:standard_name = "latitude" ; - int forecast_period ; + double forecast_period ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/000003000000.03.236.000128.1990.12.01.00.00.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/000003000000.03.236.000128.1990.12.01.00.00.b_0.txt deleted file mode 100644 index 4e6f4cdd11..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/000003000000.03.236.000128.1990.12.01.00.00.b_0.txt +++ /dev/null @@ -1,44 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/000003000000.03.236.000128.1990.12.01.00.00.b_0.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: longitude ------------------- - ------------------- -Checking variable: height ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: air_temperature ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: latitude ------------------- - -ERRORS detected: 0 -WARNINGS given: 0 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/000003000000.03.236.004224.1990.12.01.00.00.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/000003000000.03.236.004224.1990.12.01.00.00.b_0.txt deleted file mode 100644 index 923a440f77..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/000003000000.03.236.004224.1990.12.01.00.00.b_0.txt +++ /dev/null @@ -1,44 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/000003000000.03.236.004224.1990.12.01.00.00.b_0.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: longitude ------------------- - ------------------- -Checking variable: height ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: air_temperature ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: latitude ------------------- - -ERRORS detected: 0 -WARNINGS given: 0 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/000003000000.03.236.008320.1990.12.01.00.00.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/000003000000.03.236.008320.1990.12.01.00.00.b_0.txt deleted file mode 100644 index d6d3632a34..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/000003000000.03.236.008320.1990.12.01.00.00.b_0.txt +++ /dev/null @@ -1,44 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/000003000000.03.236.008320.1990.12.01.00.00.b_0.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: longitude ------------------- - ------------------- -Checking variable: height ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: air_temperature ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: latitude ------------------- - -ERRORS detected: 0 -WARNINGS given: 0 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/000003000000.16.202.000128.1860.09.01.00.00.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/000003000000.16.202.000128.1860.09.01.00.00.b_0.txt deleted file mode 100644 index a6655a17b5..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/000003000000.16.202.000128.1860.09.01.00.00.b_0.txt +++ /dev/null @@ -1,44 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/000003000000.16.202.000128.1860.09.01.00.00.b_0.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: longitude ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: pressure ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: latitude ------------------- - ------------------- -Checking variable: geopotential_height ------------------- - -ERRORS detected: 0 -WARNINGS given: 0 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/001000000000.00.000.000000.1860.01.01.00.00.f.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/001000000000.00.000.000000.1860.01.01.00.00.f.b_0.txt deleted file mode 100644 index 1035f20158..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/001000000000.00.000.000000.1860.01.01.00.00.f.b_0.txt +++ /dev/null @@ -1,40 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/001000000000.00.000.000000.1860.01.01.00.00.f.b_0.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: longitude ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: sea_surface_height_above_geoid ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: latitude ------------------- - -ERRORS detected: 0 -WARNINGS given: 0 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/002000000000.44.101.131200.1920.09.01.00.00.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/002000000000.44.101.131200.1920.09.01.00.00.b_0.txt deleted file mode 100644 index bdabff18f8..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/002000000000.44.101.131200.1920.09.01.00.00.b_0.txt +++ /dev/null @@ -1,42 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/002000000000.44.101.131200.1920.09.01.00.00.b_0.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: unknown ------------------- -WARNING (3): No standard_name or long_name attribute specified -INFO (3.1): No units attribute set. Please consider adding a units attribute for completeness. - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: latitude ------------------- - ------------------- -Checking variable: depth ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - -ERRORS detected: 0 -WARNINGS given: 1 -INFORMATION messages: 1 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/008000000000.44.101.000128.1890.09.01.00.00.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/008000000000.44.101.000128.1890.09.01.00.00.b_0.txt deleted file mode 100644 index 566c8a626b..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/008000000000.44.101.000128.1890.09.01.00.00.b_0.txt +++ /dev/null @@ -1,24 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/008000000000.44.101.000128.1890.09.01.00.00.b_0.nc -===================== - - ------------------- -Checking variable: unknown ------------------- -WARNING (2.4): space/time dimensions appear in incorrect order -WARNING (3): No standard_name or long_name attribute specified -INFO (3.1): No units attribute set. Please consider adding a units attribute for completeness. -WARNING (7.3): Coordinate variable time should have bounds or climatology attribute - ------------------- -Checking variable: depth ------------------- - ------------------- -Checking variable: time ------------------- - -ERRORS detected: 0 -WARNINGS given: 3 -INFORMATION messages: 1 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/12187.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/12187.b_0.txt deleted file mode 100644 index 7c5a272253..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/12187.b_0.txt +++ /dev/null @@ -1,61 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/12187.b_0.nc -===================== - - ------------------- -Checking variable: level_height ------------------- - ------------------- -Checking variable: level_height_bnds ------------------- - ------------------- -Checking variable: model_level_number ------------------- - ------------------- -Checking variable: sigma_bnds ------------------- - ------------------- -Checking variable: longitude ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: latitude ------------------- - ------------------- -Checking variable: sigma ------------------- - ------------------- -Checking variable: tendency_of_upward_air_velocity_due_to_advection ------------------- -ERROR (3.1): Units are not consistent with those given in the standard_name table. - -ERRORS detected: 1 -WARNINGS given: 0 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/HadCM2_ts_SAT_ann_18602100.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/HadCM2_ts_SAT_ann_18602100.b_0.txt deleted file mode 100644 index f660b7517a..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/HadCM2_ts_SAT_ann_18602100.b_0.txt +++ /dev/null @@ -1,45 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/HadCM2_ts_SAT_ann_18602100.b_0.nc -===================== - - ------------------- -Checking variable: longitude_bnds ------------------- - ------------------- -Checking variable: site_number ------------------- - ------------------- -Checking variable: longitude ------------------- - ------------------- -Checking variable: height ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: air_temperature ------------------- -WARNING (7.3): Coordinate variable time should have bounds or climatology attribute - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: latitude ------------------- - ------------------- -Checking variable: latitude_bnds ------------------- - -ERRORS detected: 0 -WARNINGS given: 1 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/aaxzc_level_lat_orig.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/aaxzc_level_lat_orig.b_0.txt deleted file mode 100644 index c21a2a9b9f..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/aaxzc_level_lat_orig.b_0.txt +++ /dev/null @@ -1,40 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/aaxzc_level_lat_orig.b_0.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: pressure ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: latitude ------------------- - ------------------- -Checking variable: geopotential_height ------------------- - -ERRORS detected: 0 -WARNINGS given: 0 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/aaxzc_lon_lat_press_orig.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/aaxzc_lon_lat_press_orig.b_0.txt deleted file mode 100644 index c31a268997..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/aaxzc_lon_lat_press_orig.b_0.txt +++ /dev/null @@ -1,44 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/aaxzc_lon_lat_press_orig.b_0.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: longitude ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: pressure ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: latitude ------------------- - ------------------- -Checking variable: geopotential_height ------------------- - -ERRORS detected: 0 -WARNINGS given: 0 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/aaxzc_lon_lat_several.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/aaxzc_lon_lat_several.b_0.txt deleted file mode 100644 index 64cae15d27..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/aaxzc_lon_lat_several.b_0.txt +++ /dev/null @@ -1,44 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/aaxzc_lon_lat_several.b_0.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: longitude ------------------- - ------------------- -Checking variable: height ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: air_temperature ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: latitude ------------------- - -ERRORS detected: 0 -WARNINGS given: 0 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/aaxzc_n10r13xy.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/aaxzc_n10r13xy.b_0.txt deleted file mode 100644 index 9a54470214..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/aaxzc_n10r13xy.b_0.txt +++ /dev/null @@ -1,46 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/aaxzc_n10r13xy.b_0.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: unknown ------------------- -WARNING (3): No standard_name or long_name attribute specified -INFO (3.1): No units attribute set. Please consider adding a units attribute for completeness. - ------------------- -Checking variable: longitude ------------------- - ------------------- -Checking variable: height ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: latitude ------------------- - -ERRORS detected: 0 -WARNINGS given: 1 -INFORMATION messages: 1 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/aaxzc_time_press.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/aaxzc_time_press.b_0.txt deleted file mode 100644 index 284f1eacf9..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/aaxzc_time_press.b_0.txt +++ /dev/null @@ -1,22 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/aaxzc_time_press.b_0.nc -===================== - - ------------------- -Checking variable: pressure ------------------- - ------------------- -Checking variable: geopotential_height ------------------- -WARNING (2.4): space/time dimensions appear in incorrect order -WARNING (7.3): Coordinate variable time should have bounds or climatology attribute - ------------------- -Checking variable: time ------------------- - -ERRORS detected: 0 -WARNINGS given: 2 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/aaxzc_tseries.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/aaxzc_tseries.b_0.txt deleted file mode 100644 index 286825c4ad..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/aaxzc_tseries.b_0.txt +++ /dev/null @@ -1,25 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/aaxzc_tseries.b_0.nc -===================== - - ------------------- -Checking variable: site_number ------------------- - ------------------- -Checking variable: height ------------------- - ------------------- -Checking variable: air_temperature ------------------- -WARNING (7.3): Coordinate variable time should have bounds or climatology attribute - ------------------- -Checking variable: time ------------------- - -ERRORS detected: 0 -WARNINGS given: 1 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/abcza_pa19591997_daily_29.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/abcza_pa19591997_daily_29.b_0.txt deleted file mode 100644 index c26de7d9f1..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/abcza_pa19591997_daily_29.b_0.txt +++ /dev/null @@ -1,44 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/abcza_pa19591997_daily_29.b_0.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: longitude ------------------- - ------------------- -Checking variable: height ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: air_temperature ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: latitude ------------------- - -ERRORS detected: 0 -WARNINGS given: 0 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/abcza_pa19591997_daily_29.b_1.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/abcza_pa19591997_daily_29.b_1.txt deleted file mode 100644 index 191c191733..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/abcza_pa19591997_daily_29.b_1.txt +++ /dev/null @@ -1,44 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/abcza_pa19591997_daily_29.b_1.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: longitude ------------------- - ------------------- -Checking variable: height ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: air_temperature ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: latitude ------------------- - -ERRORS detected: 0 -WARNINGS given: 0 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/abcza_pa19591997_daily_29.b_2.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/abcza_pa19591997_daily_29.b_2.txt deleted file mode 100644 index 5a35470467..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/abcza_pa19591997_daily_29.b_2.txt +++ /dev/null @@ -1,40 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/abcza_pa19591997_daily_29.b_2.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: precipitation_flux ------------------- - ------------------- -Checking variable: longitude ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: latitude ------------------- - -ERRORS detected: 0 -WARNINGS given: 0 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/abxpa_press_lat.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/abxpa_press_lat.b_0.txt deleted file mode 100644 index 619172a02d..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/abxpa_press_lat.b_0.txt +++ /dev/null @@ -1,40 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/abxpa_press_lat.b_0.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: latitude ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: pressure ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - ------------------- -Checking variable: geopotential_height ------------------- - -ERRORS detected: 0 -WARNINGS given: 0 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/integer.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/integer.b_0.txt deleted file mode 100644 index 270ed49117..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/integer.b_0.txt +++ /dev/null @@ -1,40 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/integer.b_0.nc -===================== - - ------------------- -Checking variable: land_binary_mask ------------------- - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: longitude ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: latitude ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - -ERRORS detected: 0 -WARNINGS given: 0 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/model.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/model.b_0.txt deleted file mode 100644 index dc8e9beb5c..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/model.b_0.txt +++ /dev/null @@ -1,44 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/model.b_0.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: longitude ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: pressure ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: air_temperature ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: latitude ------------------- - -ERRORS detected: 0 -WARNINGS given: 0 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/ocean_xsect.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/ocean_xsect.b_0.txt deleted file mode 100644 index 45915ff153..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/ocean_xsect.b_0.txt +++ /dev/null @@ -1,44 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/ocean_xsect.b_0.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: sea_water_potential_temperature ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - ------------------- -Checking variable: depth ------------------- - ------------------- -Checking variable: depth_bnds ------------------- - ------------------- -Checking variable: latitude ------------------- - -ERRORS detected: 0 -WARNINGS given: 0 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/st0fc699.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/st0fc699.b_0.txt deleted file mode 100644 index b44e154e28..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/st0fc699.b_0.txt +++ /dev/null @@ -1,42 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/st0fc699.b_0.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: unknown ------------------- -WARNING (3): No standard_name or long_name attribute specified -INFO (3.1): No units attribute set. Please consider adding a units attribute for completeness. - ------------------- -Checking variable: longitude ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: latitude ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - -ERRORS detected: 0 -WARNINGS given: 1 -INFORMATION messages: 1 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/st0fc942.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/st0fc942.b_0.txt deleted file mode 100644 index 8cd2c6c666..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/st0fc942.b_0.txt +++ /dev/null @@ -1,46 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/st0fc942.b_0.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: rotated_latitude_longitude ------------------- - ------------------- -Checking variable: unknown ------------------- -WARNING (3): No standard_name or long_name attribute specified -INFO (3.1): No units attribute set. Please consider adding a units attribute for completeness. - ------------------- -Checking variable: pseudo_level ------------------- - ------------------- -Checking variable: depth ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - ------------------- -Checking variable: grid_latitude ------------------- - ------------------- -Checking variable: forecast_period ------------------- - -ERRORS detected: 0 -WARNINGS given: 1 -INFORMATION messages: 1 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/st30211.b_0.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/st30211.b_0.txt deleted file mode 100644 index c495fdd76a..0000000000 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/cf_checker/st30211.b_0.txt +++ /dev/null @@ -1,44 +0,0 @@ - -CHECKING NetCDF FILE: /var/tmp/st30211.b_0.nc -===================== - - ------------------- -Checking variable: time_bnds ------------------- - ------------------- -Checking variable: northward_ocean_heat_transport ------------------- - ------------------- -Checking variable: pseudo_level ------------------- - ------------------- -Checking variable: longitude ------------------- - ------------------- -Checking variable: latitude_longitude ------------------- - ------------------- -Checking variable: forecast_reference_time ------------------- - ------------------- -Checking variable: forecast_period ------------------- - ------------------- -Checking variable: time ------------------- - ------------------- -Checking variable: latitude ------------------- - -ERRORS detected: 0 -WARNINGS given: 0 -INFORMATION messages: 0 diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/integer.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/integer.b_0.cdl index 700e345ece..f5fdbbd0e2 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/integer.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/integer.b_0.cdl @@ -1,9 +1,10 @@ dimensions: - latitude = UNLIMITED ; // (73 currently) bnds = 2 ; + latitude = 73 ; longitude = 96 ; variables: int land_binary_mask(latitude, longitude) ; + land_binary_mask:_FillValue = -2147483647 ; land_binary_mask:standard_name = "land_binary_mask" ; land_binary_mask:units = "1" ; land_binary_mask:cell_methods = "time: mean" ; @@ -12,8 +13,7 @@ variables: int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; float latitude(latitude) ; latitude:axis = "Y" ; latitude:units = "degrees_north" ; @@ -22,9 +22,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period ; + double forecast_period ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/model.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/model.b_0.cdl index 07277b0e03..9beb597e69 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/model.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/model.b_0.cdl @@ -1,22 +1,22 @@ dimensions: - time = UNLIMITED ; // (22 currently) bnds = 2 ; latitude = 73 ; longitude = 96 ; pressure = 9 ; + time = 22 ; variables: float air_temperature(time, pressure, latitude, longitude) ; + air_temperature:_FillValue = 9.96921e+36f ; air_temperature:standard_name = "air_temperature" ; air_temperature:units = "K" ; - air_temperature:ukmo__um_stash_source = "m01s16i203" ; + air_temperature:um_stash_source = "m01s16i203" ; air_temperature:cell_methods = "time: mean (interval: 4 hour)" ; air_temperature:grid_mapping = "latitude_longitude" ; air_temperature:coordinates = "forecast_period forecast_reference_time" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; double time(time) ; time:axis = "T" ; time:bounds = "time_bnds" ; @@ -36,9 +36,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period(time) ; + double forecast_period(time) ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(time, bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/ocean_xsect.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/ocean_xsect.b_0.cdl index 46e1f6d017..1af330948d 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/ocean_xsect.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/ocean_xsect.b_0.cdl @@ -1,21 +1,20 @@ dimensions: - depth = UNLIMITED ; // (20 currently) bnds = 2 ; + depth = 20 ; latitude = 144 ; variables: float sea_water_potential_temperature(depth, latitude) ; - sea_water_potential_temperature:_FillValue = -1.e+30f ; + sea_water_potential_temperature:_FillValue = 9.96921e+36f ; sea_water_potential_temperature:standard_name = "sea_water_potential_temperature" ; sea_water_potential_temperature:units = "degC" ; - sea_water_potential_temperature:ukmo__um_stash_source = "m02s00i101" ; + sea_water_potential_temperature:um_stash_source = "m02s00i101" ; sea_water_potential_temperature:cell_methods = "time: mean" ; sea_water_potential_temperature:grid_mapping = "latitude_longitude" ; sea_water_potential_temperature:coordinates = "forecast_period forecast_reference_time time" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; float depth(depth) ; depth:axis = "Z" ; depth:bounds = "depth_bnds" ; @@ -27,9 +26,11 @@ variables: latitude:axis = "Y" ; latitude:units = "degrees_north" ; latitude:standard_name = "latitude" ; - int forecast_period ; + double forecast_period ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/st0fc699.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/st0fc699.b_0.cdl index daddc611cc..2667dc8766 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/st0fc699.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/st0fc699.b_0.cdl @@ -1,19 +1,18 @@ dimensions: - latitude = UNLIMITED ; // (144 currently) bnds = 2 ; + latitude = 144 ; longitude = 288 ; variables: - float unknown(latitude, longitude) ; - unknown:_FillValue = -1.e+30f ; - unknown:ukmo__um_stash_source = "m02s00i???" ; - unknown:cell_methods = "time: mean (interval: 2 hour)" ; - unknown:grid_mapping = "latitude_longitude" ; - unknown:coordinates = "forecast_period forecast_reference_time time" ; + float m02s00i___(latitude, longitude) ; + m02s00i___:_FillValue = 9.96921e+36f ; + m02s00i___:um_stash_source = "m02s00i???" ; + m02s00i___:cell_methods = "time: mean (interval: 2 hour)" ; + m02s00i___:grid_mapping = "latitude_longitude" ; + m02s00i___:coordinates = "forecast_period forecast_reference_time time" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; float latitude(latitude) ; latitude:axis = "Y" ; latitude:units = "degrees_north" ; @@ -22,9 +21,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period ; + double forecast_period ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/st0fc942.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/st0fc942.b_0.cdl index 6fad35087c..bb1c0d212e 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/st0fc942.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/st0fc942.b_0.cdl @@ -1,21 +1,20 @@ dimensions: - pseudo_level = UNLIMITED ; // (4 currently) bnds = 2 ; depth = 20 ; grid_latitude = 143 ; + pseudo_level = 4 ; time = 4 ; variables: - float unknown(pseudo_level, time, depth, grid_latitude) ; - unknown:_FillValue = -1.e+30f ; - unknown:ukmo__um_stash_source = "m02s00i???" ; - unknown:cell_methods = "time: mean" ; - unknown:grid_mapping = "rotated_latitude_longitude" ; - unknown:coordinates = "forecast_period forecast_reference_time" ; + float m02s00i___(pseudo_level, time, depth, grid_latitude) ; + m02s00i___:_FillValue = 9.96921e+36f ; + m02s00i___:um_stash_source = "m02s00i???" ; + m02s00i___:cell_methods = "time: mean" ; + m02s00i___:grid_mapping = "rotated_latitude_longitude" ; + m02s00i___:coordinates = "forecast_period forecast_reference_time" ; int rotated_latitude_longitude ; rotated_latitude_longitude:grid_mapping_name = "rotated_latitude_longitude" ; rotated_latitude_longitude:longitude_of_prime_meridian = 0. ; - rotated_latitude_longitude:semi_major_axis = 6371229. ; - rotated_latitude_longitude:semi_minor_axis = 6371229. ; + rotated_latitude_longitude:earth_radius = 6371229. ; rotated_latitude_longitude:grid_north_pole_latitude = 0. ; rotated_latitude_longitude:grid_north_pole_longitude = 0. ; rotated_latitude_longitude:north_pole_grid_longitude = 0. ; @@ -38,9 +37,11 @@ variables: grid_latitude:axis = "Y" ; grid_latitude:units = "degrees" ; grid_latitude:standard_name = "grid_latitude" ; - int forecast_period(time) ; + double forecast_period(time) ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(time, bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/st30211.b_0.cdl b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/st30211.b_0.cdl index 786f2e791e..d722a55c33 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/st30211.b_0.cdl +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_netcdf/st30211.b_0.cdl @@ -1,23 +1,22 @@ dimensions: - pseudo_level = UNLIMITED ; // (4 currently) bnds = 2 ; latitude = 143 ; longitude = 1 ; + pseudo_level = 4 ; time = 4 ; variables: float northward_ocean_heat_transport(pseudo_level, time, latitude, longitude) ; - northward_ocean_heat_transport:_FillValue = -1.e+30f ; + northward_ocean_heat_transport:_FillValue = 9.96921e+36f ; northward_ocean_heat_transport:standard_name = "northward_ocean_heat_transport" ; northward_ocean_heat_transport:units = "PW" ; - northward_ocean_heat_transport:ukmo__um_stash_source = "m02s30i211" ; + northward_ocean_heat_transport:um_stash_source = "m02s30i211" ; northward_ocean_heat_transport:cell_methods = "time: mean" ; northward_ocean_heat_transport:grid_mapping = "latitude_longitude" ; northward_ocean_heat_transport:coordinates = "forecast_period forecast_reference_time" ; int latitude_longitude ; latitude_longitude:grid_mapping_name = "latitude_longitude" ; latitude_longitude:longitude_of_prime_meridian = 0. ; - latitude_longitude:semi_major_axis = 6371229. ; - latitude_longitude:semi_minor_axis = 6371229. ; + latitude_longitude:earth_radius = 6371229. ; int pseudo_level(pseudo_level) ; pseudo_level:units = "1" ; pseudo_level:long_name = "pseudo_level" ; @@ -36,9 +35,11 @@ variables: longitude:axis = "X" ; longitude:units = "degrees_east" ; longitude:standard_name = "longitude" ; - int forecast_period(time) ; + double forecast_period(time) ; + forecast_period:bounds = "forecast_period_bnds" ; forecast_period:units = "hours" ; forecast_period:standard_name = "forecast_period" ; + double forecast_period_bnds(time, bnds) ; double forecast_reference_time ; forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ; forecast_reference_time:standard_name = "forecast_reference_time" ; diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_pp/000003000000.03.236.000128.1990.12.01.00.00.b.pp.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_pp/000003000000.03.236.000128.1990.12.01.00.00.b.pp.txt index eab529b80c..fa2a873ffd 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_pp/000003000000.03.236.000128.1990.12.01.00.00.b.pp.txt +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_pp/000003000000.03.236.000128.1990.12.01.00.00.b.pp.txt @@ -51,17 +51,11 @@ bdx: 3.75 bmdi: -1e+30 bmks: 1.0 - data: [[ 240.82592773 240.82592773 240.82592773 ..., 240.82592773 - 240.82592773 240.82592773] - [ 242.12207031 241.77215576 241.44598389 ..., 242.22338867 - 242.34320068 242.34771729] - [ 247.85180664 247.38049316 247.16583252 ..., 246.6003418 247.23925781 - 247.91339111] - ..., - [ 245.66558838 245.46948242 244.70819092 ..., 246.77563477 - 246.06317139 245.80212402] - [ 244.78546143 244.65252686 244.53283691 ..., 245.31152344 - 245.09912109 244.86914062] - [ 246.94824219 246.94824219 246.94824219 ..., 246.94824219 - 246.94824219 246.94824219]] + data: [[240.82593 240.82593 240.82593 ... 240.82593 240.82593 240.82593] + [242.12207 241.77216 241.44598 ... 242.22339 242.3432 242.34772] + [247.8518 247.3805 247.16583 ... 246.60034 247.23926 247.91339] + ... + [245.66559 245.46948 244.70819 ... 246.77563 246.06317 245.80212] + [244.78546 244.65253 244.53284 ... 245.31152 245.09912 244.86914] + [246.94824 246.94824 246.94824 ... 246.94824 246.94824 246.94824]] ] \ No newline at end of file diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_pp/000003000000.03.236.004224.1990.12.01.00.00.b.pp.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_pp/000003000000.03.236.004224.1990.12.01.00.00.b.pp.txt index 55fe4b2f60..789065eafe 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_pp/000003000000.03.236.004224.1990.12.01.00.00.b.pp.txt +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_pp/000003000000.03.236.004224.1990.12.01.00.00.b.pp.txt @@ -51,17 +51,11 @@ bdx: 3.75 bmdi: -1e+30 bmks: 1.0 - data: [[ 240.82592773 240.82592773 240.82592773 ..., 240.82592773 - 240.82592773 240.82592773] - [ 242.12207031 241.77215576 241.44598389 ..., 242.22338867 - 242.34320068 242.34771729] - [ 247.85180664 247.38049316 247.16583252 ..., 246.6003418 247.23925781 - 247.91339111] - ..., - [ 245.66558838 245.46948242 244.70819092 ..., 246.77563477 - 246.06317139 245.80212402] - [ 244.78546143 244.65252686 244.53283691 ..., 245.31152344 - 245.09912109 244.86914062] - [ 246.94824219 246.94824219 246.94824219 ..., 246.94824219 - 246.94824219 246.94824219]] + data: [[240.82593 240.82593 240.82593 ... 240.82593 240.82593 240.82593] + [242.12207 241.77216 241.44598 ... 242.22339 242.3432 242.34772] + [247.8518 247.3805 247.16583 ... 246.60034 247.23926 247.91339] + ... + [245.66559 245.46948 244.70819 ... 246.77563 246.06317 245.80212] + [244.78546 244.65253 244.53284 ... 245.31152 245.09912 244.86914] + [246.94824 246.94824 246.94824 ... 246.94824 246.94824 246.94824]] ] \ No newline at end of file diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_pp/000003000000.03.236.008320.1990.12.01.00.00.b.pp.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_pp/000003000000.03.236.008320.1990.12.01.00.00.b.pp.txt index 831187f987..50c31c59e0 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_pp/000003000000.03.236.008320.1990.12.01.00.00.b.pp.txt +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_pp/000003000000.03.236.008320.1990.12.01.00.00.b.pp.txt @@ -51,17 +51,11 @@ bdx: 3.75 bmdi: -1e+30 bmks: 1.0 - data: [[ 241.99389648 241.99389648 241.99389648 ..., 241.99389648 - 241.99389648 241.99389648] - [ 243.81646729 243.47302246 243.14752197 ..., 243.89624023 - 244.00805664 244.03814697] - [ 249.7878418 249.33514404 249.13220215 ..., 248.4831543 249.08959961 - 249.80609131] - ..., - [ 248.08996582 247.90258789 247.17382812 ..., 249.07489014 - 248.41125488 248.19787598] - [ 246.16143799 246.0357666 245.93414307 ..., 246.71551514 246.487854 - 246.25048828] - [ 247.35028076 247.35028076 247.35028076 ..., 247.35028076 - 247.35028076 247.35028076]] + data: [[241.9939 241.9939 241.9939 ... 241.9939 241.9939 241.9939 ] + [243.81647 243.47302 243.14752 ... 243.89624 244.00806 244.03815] + [249.78784 249.33514 249.1322 ... 248.48315 249.0896 249.80609] + ... + [248.08997 247.90259 247.17383 ... 249.07489 248.41125 248.19788] + [246.16144 246.03577 245.93414 ... 246.71552 246.48785 246.25049] + [247.35028 247.35028 247.35028 ... 247.35028 247.35028 247.35028]] ] \ No newline at end of file diff --git a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_pp/000003000000.16.202.000128.1860.09.01.00.00.b.pp.txt b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_pp/000003000000.16.202.000128.1860.09.01.00.00.b.pp.txt index 8b708f740b..4a686468a7 100644 --- a/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_pp/000003000000.16.202.000128.1860.09.01.00.00.b.pp.txt +++ b/lib/iris/tests/results/usecases/pp_to_cf_conversion/to_pp/000003000000.16.202.000128.1860.09.01.00.00.b.pp.txt @@ -45,19 +45,19 @@ bplat: 90.0 bplon: 0.0 bgor: 0.0 - bzy: 92.5 - bdy: -2.5 - bzx: -3.75 - bdx: 3.75 + bzy: 92.499985 + bdy: -2.499999 + bzx: -3.749999 + bdx: 3.749999 bmdi: -1e+30 bmks: 1.0 - data: [[ 11203. 11203. 11203. ..., 11203. 11203. 11203.] - [ 11201. 11199. 11198. ..., 11207. 11205. 11203.] - [ 11201. 11199. 11197. ..., 11208. 11207. 11204.] - ..., - [ 10497. 10495. 10492. ..., 10507. 10504. 10501.] - [ 10482. 10481. 10480. ..., 10488. 10486. 10483.] - [ 10502. 10502. 10502. ..., 10502. 10502. 10502.]] + data: [[11203. 11203. 11203. ... 11203. 11203. 11203.] + [11201. 11199. 11198. ... 11207. 11205. 11203.] + [11201. 11199. 11197. ... 11208. 11207. 11204.] + ... + [10497. 10495. 10492. ... 10507. 10504. 10501.] + [10482. 10481. 10480. ... 10488. 10486. 10483.] + [10502. 10502. 10502. ... 10502. 10502. 10502.]] , PP Field lbyr: 1860 lbmon: 9 @@ -105,19 +105,19 @@ bplat: 90.0 bplon: 0.0 bgor: 0.0 - bzy: 92.5 - bdy: -2.5 - bzx: -3.75 - bdx: 3.75 + bzy: 92.499985 + bdy: -2.499999 + bzx: -3.749999 + bdx: 3.749999 bmdi: -1e+30 bmks: 1.0 - data: [[ 5252. 5252. 5252. ..., 5252. 5252. 5252.] - [ 5248. 5248. 5248. ..., 5249. 5249. 5248.] - [ 5250. 5249. 5248. ..., 5251. 5250. 5250.] - ..., - [ 4873. 4872. 4870. ..., 4874. 4874. 4874.] - [ 4858. 4857. 4857. ..., 4859. 4859. 4859.] - [ 4854. 4854. 4854. ..., 4854. 4854. 4854.]] + data: [[5252. 5252. 5252. ... 5252. 5252. 5252.] + [5248. 5248. 5248. ... 5249. 5249. 5248.] + [5250. 5249. 5248. ... 5251. 5250. 5250.] + ... + [4873. 4872. 4870. ... 4874. 4874. 4874.] + [4858. 4857. 4857. ... 4859. 4859. 4859.] + [4854. 4854. 4854. ... 4854. 4854. 4854.]] , PP Field lbyr: 1860 lbmon: 9 @@ -165,17 +165,17 @@ bplat: 90.0 bplon: 0.0 bgor: 0.0 - bzy: 92.5 - bdy: -2.5 - bzx: -3.75 - bdx: 3.75 + bzy: 92.499985 + bdy: -2.499999 + bzx: -3.749999 + bdx: 3.749999 bmdi: -1e+30 bmks: 1.0 - data: [[ 2818. 2818. 2818. ..., 2818. 2818. 2818.] - [ 2815. 2816. 2816. ..., 2813. 2814. 2815.] - [ 2815. 2815. 2815. ..., 2814. 2814. 2815.] - ..., - [ 2563. 2564. 2566. ..., 2555. 2558. 2561.] - [ 2555. 2555. 2555. ..., 2554. 2555. 2555.] - [ 2540. 2540. 2540. ..., 2540. 2540. 2540.]] + data: [[2818. 2818. 2818. ... 2818. 2818. 2818.] + [2815. 2816. 2816. ... 2813. 2814. 2815.] + [2815. 2815. 2815. ... 2814. 2814. 2815.] + ... + [2563. 2564. 2566. ... 2555. 2558. 2561.] + [2555. 2555. 2555. ... 2554. 2555. 2555.] + [2540. 2540. 2540. ... 2540. 2540. 2540.]] ] \ No newline at end of file diff --git a/lib/iris/tests/results/util/as_compatible_shape_collapsed.cml b/lib/iris/tests/results/util/as_compatible_shape_collapsed.cml index 76d7a7d1e3..07eeb53157 100644 --- a/lib/iris/tests/results/util/as_compatible_shape_collapsed.cml +++ b/lib/iris/tests/results/util/as_compatible_shape_collapsed.cml @@ -1,78 +1,78 @@ - + + [[0.0, 42485.4], + [0.0, 42476.3], + [0.0, 42467.1], + ..., + [0.0, 42358.5], + [0.0, 42371.5], + [0.0, 42377.8]]]]" id="9041e969" points="[[[21245.7, 21247.7, 21244.9, ..., 21195.1, + 21197.7, 21201.0], + [21232.0, 21234.2, 21235.3, ..., 21196.8, + 21199.6, 21203.8], + [21218.7, 21219.1, 21220.5, ..., 21195.1, + 21199.1, 21202.9], + ..., + [21238.5, 21234.7, 21230.5, ..., 21179.6, + 21187.6, 21193.7], + [21239.5, 21234.8, 21230.2, ..., 21182.1, + 21189.7, 21193.9], + [21242.7, 21238.1, 21233.6, ..., 21179.2, + 21185.8, 21188.9]]]" shape="(1, 100, 100)" standard_name="altitude" units="Unit('m')" value_type="float32"> - + @@ -93,44 +93,44 @@ ..., [359.666, 359.667], [359.667, 359.668], - [359.668, 359.669]]" id="5036c64b" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, + [359.668, 359.669]]" id="d3676747" points="[359.58, 359.581, 359.581, ..., 359.667, 359.668, 359.669]" shape="(100,)" standard_name="grid_longitude" units="Unit('degrees')" value_type="float32"> - + - + - + - + 300.34]]" shape="(100, 100)" standard_name="surface_altitude" units="Unit('m')" value_type="float32"/> - @@ -139,6 +139,6 @@ - + diff --git a/lib/iris/tests/results/visual_tests/test_COP_1d_plot.TestCOP1DPlot.test_COP_1d_plot.0.png b/lib/iris/tests/results/visual_tests/test_COP_1d_plot.TestCOP1DPlot.test_COP_1d_plot.0.png deleted file mode 100644 index 588c2d3528..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_COP_1d_plot.TestCOP1DPlot.test_COP_1d_plot.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_COP_maps.TestCOPMaps.test_cop_maps.0.png b/lib/iris/tests/results/visual_tests/test_COP_maps.TestCOPMaps.test_cop_maps.0.png deleted file mode 100644 index f70922a261..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_COP_maps.TestCOPMaps.test_cop_maps.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_SOI_filtering.TestSOIFiltering.test_soi_filtering.0.png b/lib/iris/tests/results/visual_tests/test_SOI_filtering.TestSOIFiltering.test_soi_filtering.0.png deleted file mode 100644 index b2049a6ce8..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_SOI_filtering.TestSOIFiltering.test_soi_filtering.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_TEC.TestTEC.test_TEC.0.png b/lib/iris/tests/results/visual_tests/test_TEC.TestTEC.test_TEC.0.png deleted file mode 100644 index 63c37f7c40..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_TEC.TestTEC.test_TEC.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_analysis.TestProject.test_cartopy_projection.0.png b/lib/iris/tests/results/visual_tests/test_analysis.TestProject.test_cartopy_projection.0.png deleted file mode 100644 index dc5b871974..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_analysis.TestProject.test_cartopy_projection.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_analysis.TestRotatedPole.test_all.0.png b/lib/iris/tests/results/visual_tests/test_analysis.TestRotatedPole.test_all.0.png deleted file mode 100644 index c2860189e8..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_analysis.TestRotatedPole.test_all.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_analysis.TestRotatedPole.test_all.1.png b/lib/iris/tests/results/visual_tests/test_analysis.TestRotatedPole.test_all.1.png deleted file mode 100644 index ca9545b3e3..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_analysis.TestRotatedPole.test_all.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_analysis.TestRotatedPole.test_all.2.png b/lib/iris/tests/results/visual_tests/test_analysis.TestRotatedPole.test_all.2.png deleted file mode 100644 index 3b10235e89..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_analysis.TestRotatedPole.test_all.2.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_analysis.TestRotatedPole.test_all.3.png b/lib/iris/tests/results/visual_tests/test_analysis.TestRotatedPole.test_all.3.png deleted file mode 100644 index 6bbfce6bf9..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_analysis.TestRotatedPole.test_all.3.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_animate.IntegrationTest.test_cube_animation.0.png b/lib/iris/tests/results/visual_tests/test_animate.IntegrationTest.test_cube_animation.0.png deleted file mode 100644 index d11fb520a1..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_animate.IntegrationTest.test_cube_animation.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_animate.IntegrationTest.test_cube_animation.1.png b/lib/iris/tests/results/visual_tests/test_animate.IntegrationTest.test_cube_animation.1.png deleted file mode 100644 index db7a1f0c74..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_animate.IntegrationTest.test_cube_animation.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_animate.IntegrationTest.test_cube_animation.2.png b/lib/iris/tests/results/visual_tests/test_animate.IntegrationTest.test_cube_animation.2.png deleted file mode 100644 index eea4a0698b..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_animate.IntegrationTest.test_cube_animation.2.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_atlantic_profiles.TestAtlanticProfiles.test_atlantic_profiles.0.png b/lib/iris/tests/results/visual_tests/test_atlantic_profiles.TestAtlanticProfiles.test_atlantic_profiles.0.png deleted file mode 100644 index 29dd9c4066..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_atlantic_profiles.TestAtlanticProfiles.test_atlantic_profiles.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_atlantic_profiles.TestAtlanticProfiles.test_atlantic_profiles.1.png b/lib/iris/tests/results/visual_tests/test_atlantic_profiles.TestAtlanticProfiles.test_atlantic_profiles.1.png deleted file mode 100644 index 86e008dedb..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_atlantic_profiles.TestAtlanticProfiles.test_atlantic_profiles.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_cross_section.TestCrossSection.test_cross_section.0.png b/lib/iris/tests/results/visual_tests/test_cross_section.TestCrossSection.test_cross_section.0.png deleted file mode 100644 index 44b897c328..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_cross_section.TestCrossSection.test_cross_section.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_cross_section.TestCrossSection.test_cross_section.1.png b/lib/iris/tests/results/visual_tests/test_cross_section.TestCrossSection.test_cross_section.1.png deleted file mode 100644 index 147440bbdc..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_cross_section.TestCrossSection.test_cross_section.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_custom_file_loading.TestCustomFileLoading.test_custom_file_loading.0.png b/lib/iris/tests/results/visual_tests/test_custom_file_loading.TestCustomFileLoading.test_custom_file_loading.0.png deleted file mode 100644 index 41e333e36a..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_custom_file_loading.TestCustomFileLoading.test_custom_file_loading.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_deriving_phenomena.TestDerivingPhenomena.test_deriving_phenomena.0.png b/lib/iris/tests/results/visual_tests/test_deriving_phenomena.TestDerivingPhenomena.test_deriving_phenomena.0.png deleted file mode 100644 index 0a01252f9f..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_deriving_phenomena.TestDerivingPhenomena.test_deriving_phenomena.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_global_map.TestGlobalMap.test_global_map.0.png b/lib/iris/tests/results/visual_tests/test_global_map.TestGlobalMap.test_global_map.0.png deleted file mode 100644 index e7d3c816ad..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_global_map.TestGlobalMap.test_global_map.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_ij_directions.0.png b/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_ij_directions.0.png deleted file mode 100644 index 6858fd6c14..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_ij_directions.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_ij_directions.1.png b/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_ij_directions.1.png deleted file mode 100644 index 0ef58c6882..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_ij_directions.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_ij_directions.2.png b/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_ij_directions.2.png deleted file mode 100644 index 1e1a07d4ec..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_ij_directions.2.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_ij_directions.3.png b/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_ij_directions.3.png deleted file mode 100644 index fb1d1acdc7..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_ij_directions.3.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_lambert_grib1.0.png b/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_lambert_grib1.0.png deleted file mode 100644 index 5829f1fd7c..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_lambert_grib1.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_lambert_grib2.0.png b/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_lambert_grib2.0.png deleted file mode 100644 index cbedbb9983..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_lambert_grib2.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_polar_stereo_grib1.0.png b/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_polar_stereo_grib1.0.png deleted file mode 100644 index 1de3583374..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_polar_stereo_grib1.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_polar_stereo_grib2.0.png b/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_polar_stereo_grib2.0.png deleted file mode 100644 index a45b613973..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_polar_stereo_grib2.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_y_fastest.0.png b/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_y_fastest.0.png deleted file mode 100644 index 53f9ce845a..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_grib_load.TestGribLoad.test_y_fastest.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_hovmoller.TestGlobalMap.test_hovmoller.0.png b/lib/iris/tests/results/visual_tests/test_hovmoller.TestGlobalMap.test_hovmoller.0.png deleted file mode 100644 index c76ec6f5fb..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_hovmoller.TestGlobalMap.test_hovmoller.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_lagged_ensemble.TestLaggedEnsemble.test_lagged_ensemble.0.png b/lib/iris/tests/results/visual_tests/test_lagged_ensemble.TestLaggedEnsemble.test_lagged_ensemble.0.png deleted file mode 100644 index 148d50c697..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_lagged_ensemble.TestLaggedEnsemble.test_lagged_ensemble.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_lagged_ensemble.TestLaggedEnsemble.test_lagged_ensemble.1.png b/lib/iris/tests/results/visual_tests/test_lagged_ensemble.TestLaggedEnsemble.test_lagged_ensemble.1.png deleted file mode 100644 index a2e9bc5aa3..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_lagged_ensemble.TestLaggedEnsemble.test_lagged_ensemble.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_lineplot_with_legend.TestLineplotWithLegend.test_lineplot_with_legend.0.png b/lib/iris/tests/results/visual_tests/test_lineplot_with_legend.TestLineplotWithLegend.test_lineplot_with_legend.0.png deleted file mode 100644 index 1898374861..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_lineplot_with_legend.TestLineplotWithLegend.test_lineplot_with_legend.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_mapping.TestBasic.test_contourf.0.png b/lib/iris/tests/results/visual_tests/test_mapping.TestBasic.test_contourf.0.png deleted file mode 100644 index 593e98168a..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_mapping.TestBasic.test_contourf.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_mapping.TestBasic.test_pcolor.0.png b/lib/iris/tests/results/visual_tests/test_mapping.TestBasic.test_pcolor.0.png deleted file mode 100644 index 0e7d3d5439..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_mapping.TestBasic.test_pcolor.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_mapping.TestBasic.test_unmappable.0.png b/lib/iris/tests/results/visual_tests/test_mapping.TestBasic.test_unmappable.0.png deleted file mode 100644 index 6685abf5bc..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_mapping.TestBasic.test_unmappable.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_mapping.TestBoundedCube.test_grid.0.png b/lib/iris/tests/results/visual_tests/test_mapping.TestBoundedCube.test_grid.0.png deleted file mode 100644 index 9a26bea98e..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_mapping.TestBoundedCube.test_grid.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_mapping.TestBoundedCube.test_pcolormesh.0.png b/lib/iris/tests/results/visual_tests/test_mapping.TestBoundedCube.test_pcolormesh.0.png deleted file mode 100644 index 0c66149743..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_mapping.TestBoundedCube.test_pcolormesh.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_mapping.TestLimitedAreaCube.test_grid.0.png b/lib/iris/tests/results/visual_tests/test_mapping.TestLimitedAreaCube.test_grid.0.png deleted file mode 100644 index a60482ea98..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_mapping.TestLimitedAreaCube.test_grid.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_mapping.TestLimitedAreaCube.test_outline.0.png b/lib/iris/tests/results/visual_tests/test_mapping.TestLimitedAreaCube.test_outline.0.png deleted file mode 100644 index 44b701dfa7..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_mapping.TestLimitedAreaCube.test_outline.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_mapping.TestLimitedAreaCube.test_pcolormesh.0.png b/lib/iris/tests/results/visual_tests/test_mapping.TestLimitedAreaCube.test_pcolormesh.0.png deleted file mode 100644 index 935b30537d..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_mapping.TestLimitedAreaCube.test_pcolormesh.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_mapping.TestLimitedAreaCube.test_scatter.0.png b/lib/iris/tests/results/visual_tests/test_mapping.TestLimitedAreaCube.test_scatter.0.png deleted file mode 100644 index 37b52782ea..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_mapping.TestLimitedAreaCube.test_scatter.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_mapping.TestLowLevel.test_keywords.0.png b/lib/iris/tests/results/visual_tests/test_mapping.TestLowLevel.test_keywords.0.png deleted file mode 100644 index 6446917505..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_mapping.TestLowLevel.test_keywords.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_mapping.TestLowLevel.test_keywords.1.png b/lib/iris/tests/results/visual_tests/test_mapping.TestLowLevel.test_keywords.1.png deleted file mode 100644 index 3695af58b6..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_mapping.TestLowLevel.test_keywords.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_mapping.TestLowLevel.test_params.0.png b/lib/iris/tests/results/visual_tests/test_mapping.TestLowLevel.test_params.0.png deleted file mode 100644 index a4c2b2f469..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_mapping.TestLowLevel.test_params.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_mapping.TestLowLevel.test_params.1.png b/lib/iris/tests/results/visual_tests/test_mapping.TestLowLevel.test_params.1.png deleted file mode 100644 index 6446917505..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_mapping.TestLowLevel.test_params.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_mapping.TestLowLevel.test_params.2.png b/lib/iris/tests/results/visual_tests/test_mapping.TestLowLevel.test_params.2.png deleted file mode 100644 index 24bb852244..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_mapping.TestLowLevel.test_params.2.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_mapping.TestLowLevel.test_simple.0.png b/lib/iris/tests/results/visual_tests/test_mapping.TestLowLevel.test_simple.0.png deleted file mode 100644 index 698ae30444..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_mapping.TestLowLevel.test_simple.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_mapping.TestMappingSubRegion.test_simple.0.png b/lib/iris/tests/results/visual_tests/test_mapping.TestMappingSubRegion.test_simple.0.png deleted file mode 100644 index b7cdd0e4e1..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_mapping.TestMappingSubRegion.test_simple.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_mapping.TestUnmappable.test_simple.0.png b/lib/iris/tests/results/visual_tests/test_mapping.TestUnmappable.test_simple.0.png deleted file mode 100644 index 0223de8f98..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_mapping.TestUnmappable.test_simple.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_coord.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_coord.0.png deleted file mode 100644 index ecdd325cde..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_coord.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_coord_coord.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_coord_coord.0.png deleted file mode 100644 index 8796a36205..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_coord_coord.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_coord_coord_map.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_coord_coord_map.0.png deleted file mode 100644 index 2d1875aac4..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_coord_coord_map.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_coord_cube.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_coord_cube.0.png deleted file mode 100644 index 1df093f99d..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_coord_cube.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_coords_deprecated.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_coords_deprecated.0.png deleted file mode 100644 index 1df093f99d..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_coords_deprecated.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_cube.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_cube.0.png deleted file mode 100644 index 196ddc588e..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_cube.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_cube_coord.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_cube_coord.0.png deleted file mode 100644 index 6ad99f0a1e..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_cube_coord.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_cube_cube.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_cube_cube.0.png deleted file mode 100644 index e48e5d48c0..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotMultiArgs.test_cube_cube.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_coord.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_coord.0.png deleted file mode 100644 index c69dc05921..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_coord.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_coord_coord.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_coord_coord.0.png deleted file mode 100644 index c683b69f97..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_coord_coord.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_coord_coord_map.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_coord_coord_map.0.png deleted file mode 100644 index 2d1875aac4..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_coord_coord_map.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_coord_cube.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_coord_cube.0.png deleted file mode 100644 index 692ca7b90d..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_coord_cube.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_coords_deprecated.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_coords_deprecated.0.png deleted file mode 100644 index 692ca7b90d..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_coords_deprecated.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_cube.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_cube.0.png deleted file mode 100644 index 961f08316c..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_cube.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_cube_coord.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_cube_coord.0.png deleted file mode 100644 index 4d6266681c..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_cube_coord.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_cube_cube.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_cube_cube.0.png deleted file mode 100644 index fbec47dafe..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotPlotMultiArgs.test_cube_cube.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotScatter.test_coord_coord.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotScatter.test_coord_coord.0.png deleted file mode 100644 index ee1a94e8cf..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotScatter.test_coord_coord.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotScatter.test_coord_coord_map.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotScatter.test_coord_coord_map.0.png deleted file mode 100644 index 68dfe4d8ef..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotScatter.test_coord_coord_map.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotScatter.test_coord_cube.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotScatter.test_coord_cube.0.png deleted file mode 100644 index 19629fc510..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotScatter.test_coord_cube.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotScatter.test_cube_coord.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotScatter.test_cube_coord.0.png deleted file mode 100644 index 20a5bd60fe..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotScatter.test_cube_coord.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotScatter.test_cube_cube.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotScatter.test_cube_cube.0.png deleted file mode 100644 index 56d2ba5da4..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dQuickplotScatter.test_cube_cube.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dScatter.test_coord_coord.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dScatter.test_coord_coord.0.png deleted file mode 100644 index 5042e076f0..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dScatter.test_coord_coord.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dScatter.test_coord_coord_map.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dScatter.test_coord_coord_map.0.png deleted file mode 100644 index 68dfe4d8ef..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dScatter.test_coord_coord_map.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dScatter.test_coord_cube.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dScatter.test_coord_cube.0.png deleted file mode 100644 index a77fbfe5a8..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dScatter.test_coord_cube.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dScatter.test_cube_coord.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dScatter.test_cube_coord.0.png deleted file mode 100644 index f9de2b5129..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dScatter.test_cube_coord.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dScatter.test_cube_cube.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dScatter.test_cube_cube.0.png deleted file mode 100644 index decf64e73d..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.Test1dScatter.test_cube_cube.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestAttributePositive.test_1d_positive_down.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestAttributePositive.test_1d_positive_down.0.png deleted file mode 100644 index 06d4baab0f..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestAttributePositive.test_1d_positive_down.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestAttributePositive.test_1d_positive_up.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestAttributePositive.test_1d_positive_up.0.png deleted file mode 100644 index fcf03ef3d3..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestAttributePositive.test_1d_positive_up.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestAttributePositive.test_2d_positive_down.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestAttributePositive.test_2d_positive_down.0.png deleted file mode 100644 index 9af4d73b40..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestAttributePositive.test_2d_positive_down.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestAttributePositive.test_2d_positive_up.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestAttributePositive.test_2d_positive_up.0.png deleted file mode 100644 index cc3cc1af9e..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestAttributePositive.test_2d_positive_up.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestContour.test_tx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestContour.test_tx.0.png deleted file mode 100644 index e16953f999..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestContour.test_tx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestContour.test_ty.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestContour.test_ty.0.png deleted file mode 100644 index da9ab09352..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestContour.test_ty.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestContour.test_tz.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestContour.test_tz.0.png deleted file mode 100644 index af1dea776e..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestContour.test_tz.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestContour.test_yx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestContour.test_yx.0.png deleted file mode 100644 index a14cc2eec5..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestContour.test_yx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestContour.test_zx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestContour.test_zx.0.png deleted file mode 100644 index 81fa6ff421..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestContour.test_zx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestContour.test_zy.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestContour.test_zy.0.png deleted file mode 100644 index 39ddab1fe9..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestContour.test_zy.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestContourf.test_tx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestContourf.test_tx.0.png deleted file mode 100644 index e697bc7ebb..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestContourf.test_tx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestContourf.test_ty.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestContourf.test_ty.0.png deleted file mode 100644 index 31d2b6f339..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestContourf.test_ty.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestContourf.test_tz.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestContourf.test_tz.0.png deleted file mode 100644 index e84664010c..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestContourf.test_tz.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestContourf.test_yx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestContourf.test_yx.0.png deleted file mode 100644 index f615b67da7..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestContourf.test_yx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestContourf.test_zx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestContourf.test_zx.0.png deleted file mode 100644 index 0e484209ce..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestContourf.test_zx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestContourf.test_zy.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestContourf.test_zy.0.png deleted file mode 100644 index 26b5c69164..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestContourf.test_zy.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestFillContinents.test_fillcontinents_ontop.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestFillContinents.test_fillcontinents_ontop.0.png deleted file mode 100644 index 80b3823603..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestFillContinents.test_fillcontinents_ontop.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestFillContinents.test_fillcontinents_underneath.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestFillContinents.test_fillcontinents_underneath.0.png deleted file mode 100644 index c20e3afa64..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestFillContinents.test_fillcontinents_underneath.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_bounds.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_bounds.0.png deleted file mode 100644 index 301c758832..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_bounds.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_bounds.1.png b/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_bounds.1.png deleted file mode 100644 index bccb5c2848..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_bounds.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_bounds.2.png b/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_bounds.2.png deleted file mode 100644 index 301c758832..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_bounds.2.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_orography.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_orography.0.png deleted file mode 100644 index 61de7af14f..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_orography.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_orography.1.png b/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_orography.1.png deleted file mode 100644 index 5e1748d9af..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_orography.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_points.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_points.0.png deleted file mode 100644 index 44b897c328..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_points.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_points.1.png b/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_points.1.png deleted file mode 100644 index c294592147..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_points.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_points.2.png b/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_points.2.png deleted file mode 100644 index bee466abbf..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_points.2.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_points.3.png b/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_points.3.png deleted file mode 100644 index 44b897c328..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_points.3.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_points.4.png b/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_points.4.png deleted file mode 100644 index 1b33050d48..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestHybridHeight.test_points.4.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestMissingCS.test_missing_cs.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestMissingCS.test_missing_cs.0.png deleted file mode 100644 index 66aa919f20..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestMissingCS.test_missing_cs.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestMissingCoord.test_no_u.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestMissingCoord.test_no_u.0.png deleted file mode 100644 index 7b63a847f3..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestMissingCoord.test_no_u.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestMissingCoord.test_no_u.1.png b/lib/iris/tests/results/visual_tests/test_plot.TestMissingCoord.test_no_u.1.png deleted file mode 100644 index 7dfe617be6..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestMissingCoord.test_no_u.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestMissingCoord.test_no_v.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestMissingCoord.test_no_v.0.png deleted file mode 100644 index 2673f28006..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestMissingCoord.test_no_v.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestMissingCoord.test_no_v.1.png b/lib/iris/tests/results/visual_tests/test_plot.TestMissingCoord.test_no_v.1.png deleted file mode 100644 index 0ad2b11d17..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestMissingCoord.test_no_v.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestMissingCoord.test_none.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestMissingCoord.test_none.0.png deleted file mode 100644 index 641a1c59c5..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestMissingCoord.test_none.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestMissingCoord.test_none.1.png b/lib/iris/tests/results/visual_tests/test_plot.TestMissingCoord.test_none.1.png deleted file mode 100644 index 40dd6dd6b2..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestMissingCoord.test_none.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolor.test_tx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolor.test_tx.0.png deleted file mode 100644 index b07301ce1c..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolor.test_tx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolor.test_ty.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolor.test_ty.0.png deleted file mode 100644 index f5a53d87e0..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolor.test_ty.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolor.test_tz.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolor.test_tz.0.png deleted file mode 100644 index 3a37a78294..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolor.test_tz.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolor.test_yx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolor.test_yx.0.png deleted file mode 100644 index d4837b578d..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolor.test_yx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolor.test_zx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolor.test_zx.0.png deleted file mode 100644 index f494039547..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolor.test_zx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolor.test_zy.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolor.test_zy.0.png deleted file mode 100644 index 967986e071..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolor.test_zy.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolorNoBounds.test_tx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolorNoBounds.test_tx.0.png deleted file mode 100644 index 000a8e4719..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolorNoBounds.test_tx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolorNoBounds.test_ty.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolorNoBounds.test_ty.0.png deleted file mode 100644 index d1215e79ec..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolorNoBounds.test_ty.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolorNoBounds.test_tz.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolorNoBounds.test_tz.0.png deleted file mode 100644 index 1c1963548e..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolorNoBounds.test_tz.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolorNoBounds.test_yx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolorNoBounds.test_yx.0.png deleted file mode 100644 index c76b852cc7..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolorNoBounds.test_yx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolorNoBounds.test_zx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolorNoBounds.test_zx.0.png deleted file mode 100644 index fc9e707f79..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolorNoBounds.test_zx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolorNoBounds.test_zy.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolorNoBounds.test_zy.0.png deleted file mode 100644 index d0e00fc21e..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolorNoBounds.test_zy.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormesh.test_tx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolormesh.test_tx.0.png deleted file mode 100644 index 9a4ddbe246..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormesh.test_tx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormesh.test_ty.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolormesh.test_ty.0.png deleted file mode 100644 index 4f448c1c53..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormesh.test_ty.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormesh.test_tz.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolormesh.test_tz.0.png deleted file mode 100644 index 5ec8232817..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormesh.test_tz.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormesh.test_yx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolormesh.test_yx.0.png deleted file mode 100644 index 0517a94397..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormesh.test_yx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormesh.test_zx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolormesh.test_zx.0.png deleted file mode 100644 index ed346e9b15..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormesh.test_zx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormesh.test_zy.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolormesh.test_zy.0.png deleted file mode 100644 index fc99158f25..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormesh.test_zy.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormeshNoBounds.test_tx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolormeshNoBounds.test_tx.0.png deleted file mode 100644 index bc22383c6c..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormeshNoBounds.test_tx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormeshNoBounds.test_ty.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolormeshNoBounds.test_ty.0.png deleted file mode 100644 index 2867db17f4..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormeshNoBounds.test_ty.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormeshNoBounds.test_tz.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolormeshNoBounds.test_tz.0.png deleted file mode 100644 index cb3ad3f02a..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormeshNoBounds.test_tz.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormeshNoBounds.test_yx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolormeshNoBounds.test_yx.0.png deleted file mode 100644 index 359ac159a1..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormeshNoBounds.test_yx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormeshNoBounds.test_zx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolormeshNoBounds.test_zx.0.png deleted file mode 100644 index dff497bbc0..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormeshNoBounds.test_zx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormeshNoBounds.test_zy.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPcolormeshNoBounds.test_zy.0.png deleted file mode 100644 index 469347cb9c..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPcolormeshNoBounds.test_zy.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlot.test_t.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlot.test_t.0.png deleted file mode 100644 index 4e14a1c5b8..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlot.test_t.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlot.test_t_dates.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlot.test_t_dates.0.png deleted file mode 100644 index 5dba9cd866..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlot.test_t_dates.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlot.test_x.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlot.test_x.0.png deleted file mode 100644 index c569ba5119..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlot.test_x.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlot.test_y.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlot.test_y.0.png deleted file mode 100644 index c3190bac26..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlot.test_y.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlot.test_z.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlot.test_z.0.png deleted file mode 100644 index 196ddc588e..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlot.test_z.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_non_cube_coordinate.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_non_cube_coordinate.0.png deleted file mode 100644 index 582424945b..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_non_cube_coordinate.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_tx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_tx.0.png deleted file mode 100644 index 91226de6a4..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_tx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_tx.1.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_tx.1.png deleted file mode 100644 index 979328a314..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_tx.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_tx.2.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_tx.2.png deleted file mode 100644 index 6460392c32..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_tx.2.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_tx.3.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_tx.3.png deleted file mode 100644 index 574c900ab5..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_tx.3.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_tx.4.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_tx.4.png deleted file mode 100644 index eddc8263a7..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_tx.4.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_tx.5.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_tx.5.png deleted file mode 100644 index 0fe9a3974f..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_tx.5.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_x.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_x.0.png deleted file mode 100644 index c7307057ff..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_x.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_y.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_y.0.png deleted file mode 100644 index 49ffd20407..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_y.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_yx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_yx.0.png deleted file mode 100644 index 09ed38b672..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_yx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_yx.1.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_yx.1.png deleted file mode 100644 index 593e98168a..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_yx.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_yx.2.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_yx.2.png deleted file mode 100644 index 34e3654231..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_yx.2.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_yx.3.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_yx.3.png deleted file mode 100644 index 67c8640f67..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_yx.3.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_yx.4.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_yx.4.png deleted file mode 100644 index 936962c2ec..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_yx.4.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_yx.5.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_yx.5.png deleted file mode 100644 index b86984f4c5..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_yx.5.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_zx.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_zx.0.png deleted file mode 100644 index 50629d0606..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_zx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_zx.1.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_zx.1.png deleted file mode 100644 index 05ce575985..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_zx.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_zx.2.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_zx.2.png deleted file mode 100644 index 730820067d..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_zx.2.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_zx.3.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_zx.3.png deleted file mode 100644 index 96d51d1487..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_zx.3.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_zx.4.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_zx.4.png deleted file mode 100644 index 05345bfd45..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_zx.4.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_zx.5.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_zx.5.png deleted file mode 100644 index 6e67ce1276..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotCoordinatesGiven.test_zx.5.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_coord_names.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_coord_names.0.png deleted file mode 100644 index 597f0937fe..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_coord_names.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_coord_names.1.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_coord_names.1.png deleted file mode 100644 index 715e8930a2..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_coord_names.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_coords.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_coords.0.png deleted file mode 100644 index 597f0937fe..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_coords.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_coords.1.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_coords.1.png deleted file mode 100644 index 715e8930a2..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_coords.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_default.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_default.0.png deleted file mode 100644 index 597f0937fe..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_default.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_yx_order.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_yx_order.0.png deleted file mode 100644 index 74de3549cf..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_yx_order.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_yx_order.1.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_yx_order.1.png deleted file mode 100644 index ee800cf17b..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotDimAndAuxCoordsKwarg.test_yx_order.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestPlotOtherCoordSystems.test_plot_tmerc.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestPlotOtherCoordSystems.test_plot_tmerc.0.png deleted file mode 100644 index 2a1ac1c9ab..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestPlotOtherCoordSystems.test_plot_tmerc.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestQuickplotPlot.test_t.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestQuickplotPlot.test_t.0.png deleted file mode 100644 index 336f1a5857..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestQuickplotPlot.test_t.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestQuickplotPlot.test_t_dates.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestQuickplotPlot.test_t_dates.0.png deleted file mode 100644 index de7e1e092d..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestQuickplotPlot.test_t_dates.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestQuickplotPlot.test_x.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestQuickplotPlot.test_x.0.png deleted file mode 100644 index ab4f8e8923..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestQuickplotPlot.test_x.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestQuickplotPlot.test_y.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestQuickplotPlot.test_y.0.png deleted file mode 100644 index c322c2ba1e..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestQuickplotPlot.test_y.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestQuickplotPlot.test_z.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestQuickplotPlot.test_z.0.png deleted file mode 100644 index 961f08316c..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestQuickplotPlot.test_z.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestSimple.test_bounds.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestSimple.test_bounds.0.png deleted file mode 100644 index 33389a771b..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestSimple.test_bounds.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestSimple.test_points.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestSimple.test_points.0.png deleted file mode 100644 index 7950fa4928..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestSimple.test_points.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.TestSymbols.test_cloud_cover.0.png b/lib/iris/tests/results/visual_tests/test_plot.TestSymbols.test_cloud_cover.0.png deleted file mode 100644 index 7c2811631b..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_plot.TestSymbols.test_cloud_cover.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_polar_stereo.TestPolarStereo.test_polar_stereo.0.png b/lib/iris/tests/results/visual_tests/test_polar_stereo.TestPolarStereo.test_polar_stereo.0.png deleted file mode 100644 index 659fcbb176..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_polar_stereo.TestPolarStereo.test_polar_stereo.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_alignment.0.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_alignment.0.png deleted file mode 100644 index adb979c69a..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_alignment.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_contour.0.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_contour.0.png deleted file mode 100644 index 9aa4dea399..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_contour.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_contour.1.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_contour.1.png deleted file mode 100644 index cd3e8133aa..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_contour.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_contourf.0.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_contourf.0.png deleted file mode 100644 index f4f5693158..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_contourf.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_contourf.1.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_contourf.1.png deleted file mode 100644 index cd3e8133aa..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_contourf.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_contourf.2.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_contourf.2.png deleted file mode 100644 index 9d3c315885..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_contourf.2.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_contourf_nameless.0.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_contourf_nameless.0.png deleted file mode 100644 index 554e74876e..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_contourf_nameless.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_map.0.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_map.0.png deleted file mode 100644 index 008bdeccde..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_map.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_map.1.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_map.1.png deleted file mode 100644 index c212f94967..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_map.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_pcolor.0.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_pcolor.0.png deleted file mode 100644 index 902b6265ca..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_pcolor.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_pcolormesh.0.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_pcolormesh.0.png deleted file mode 100644 index 18c7ddf95f..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestLabels.test_pcolormesh.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_non_cube_coordinate.0.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_non_cube_coordinate.0.png deleted file mode 100644 index 4b27925926..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_non_cube_coordinate.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_tx.0.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_tx.0.png deleted file mode 100644 index d558a9b9f8..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_tx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_tx.1.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_tx.1.png deleted file mode 100644 index 7950fa4928..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_tx.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_tx.2.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_tx.2.png deleted file mode 100644 index 8c37ce22ae..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_tx.2.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_tx.3.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_tx.3.png deleted file mode 100644 index 48221ccff5..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_tx.3.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_tx.4.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_tx.4.png deleted file mode 100644 index 7b7e86dec8..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_tx.4.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_tx.5.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_tx.5.png deleted file mode 100644 index 5ab6a90064..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_tx.5.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_x.0.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_x.0.png deleted file mode 100644 index ea100e4e6b..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_x.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_y.0.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_y.0.png deleted file mode 100644 index 20e1ae4f1d..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_y.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_yx.0.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_yx.0.png deleted file mode 100644 index a858c57552..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_yx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_yx.1.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_yx.1.png deleted file mode 100644 index eb94e1f0af..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_yx.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_yx.2.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_yx.2.png deleted file mode 100644 index ac49e9aab1..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_yx.2.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_yx.3.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_yx.3.png deleted file mode 100644 index 008bdeccde..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_yx.3.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_yx.4.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_yx.4.png deleted file mode 100644 index 2a279789fe..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_yx.4.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_yx.5.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_yx.5.png deleted file mode 100644 index db507292e4..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_yx.5.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_zx.0.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_zx.0.png deleted file mode 100644 index 9ac073cff4..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_zx.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_zx.1.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_zx.1.png deleted file mode 100644 index 147440bbdc..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_zx.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_zx.2.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_zx.2.png deleted file mode 100644 index 56a3515c1f..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_zx.2.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_zx.3.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_zx.3.png deleted file mode 100644 index 4102893914..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_zx.3.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_zx.4.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_zx.4.png deleted file mode 100644 index 65917895a1..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_zx.4.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_zx.5.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_zx.5.png deleted file mode 100644 index c48f521a3f..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestQuickplotCoordinatesGiven.test_zx.5.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestTimeReferenceUnitsLabels.test_not_reference_time_units.0.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestTimeReferenceUnitsLabels.test_not_reference_time_units.0.png deleted file mode 100644 index 2a58810ad3..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestTimeReferenceUnitsLabels.test_not_reference_time_units.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_quickplot.TestTimeReferenceUnitsLabels.test_reference_time_units.0.png b/lib/iris/tests/results/visual_tests/test_quickplot.TestTimeReferenceUnitsLabels.test_reference_time_units.0.png deleted file mode 100644 index 5713f840f9..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_quickplot.TestTimeReferenceUnitsLabels.test_reference_time_units.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_circular_subset.0.png b/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_circular_subset.0.png deleted file mode 100644 index 9b2fa62928..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_circular_subset.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_cross_section.0.png b/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_cross_section.0.png deleted file mode 100644 index 30fdb98dda..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_cross_section.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_cross_section.1.png b/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_cross_section.1.png deleted file mode 100644 index 55f5d6d6ef..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_cross_section.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_global_data_increase_res.0.png b/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_global_data_increase_res.0.png deleted file mode 100644 index e5c3f12f69..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_global_data_increase_res.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_global_data_reduce_res.0.png b/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_global_data_reduce_res.0.png deleted file mode 100644 index 1d1f4d0de7..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_global_data_reduce_res.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_global_data_same_res.0.png b/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_global_data_same_res.0.png deleted file mode 100644 index a4f4af92a9..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_global_data_same_res.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_global_data_subset.0.png b/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_global_data_subset.0.png deleted file mode 100644 index 5d18512f55..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_global_data_subset.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_hybrid_height.0.png b/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_hybrid_height.0.png deleted file mode 100644 index 72d0af0cfc..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_hybrid_height.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_hybrid_height.1.png b/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_hybrid_height.1.png deleted file mode 100644 index 463bf5e822..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_hybrid_height.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_hybrid_height.2.png b/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_hybrid_height.2.png deleted file mode 100644 index 127d668671..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_hybrid_height.2.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_non_circular_subset.0.png b/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_non_circular_subset.0.png deleted file mode 100644 index 71c4dc7deb..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_regrid_area_weighted_rectilinear_src_and_grid.TestAreaWeightedRegrid.test_non_circular_subset.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_regrid_bilinear_rectilinear_src_and_grid.TestVisual.test_osgb_to_latlon.0.png b/lib/iris/tests/results/visual_tests/test_regrid_bilinear_rectilinear_src_and_grid.TestVisual.test_osgb_to_latlon.0.png deleted file mode 100644 index 283bbaf833..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_regrid_bilinear_rectilinear_src_and_grid.TestVisual.test_osgb_to_latlon.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_regrid_bilinear_rectilinear_src_and_grid.TestVisual.test_subsample.0.png b/lib/iris/tests/results/visual_tests/test_regrid_bilinear_rectilinear_src_and_grid.TestVisual.test_subsample.0.png deleted file mode 100644 index b43fb0558b..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_regrid_bilinear_rectilinear_src_and_grid.TestVisual.test_subsample.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.0.png b/lib/iris/tests/results/visual_tests/test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.0.png deleted file mode 100644 index 3abd5b010b..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.1.png b/lib/iris/tests/results/visual_tests/test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.1.png deleted file mode 100644 index 5dd5c6e258..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.2.png b/lib/iris/tests/results/visual_tests/test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.2.png deleted file mode 100644 index 927deb4054..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.2.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.3.png b/lib/iris/tests/results/visual_tests/test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.3.png deleted file mode 100644 index 17f39e941c..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.3.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_trajectory.TestTrajectory.test_trajectory_extraction.0.png b/lib/iris/tests/results/visual_tests/test_trajectory.TestTrajectory.test_trajectory_extraction.0.png deleted file mode 100644 index ed61133b6b..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_trajectory.TestTrajectory.test_trajectory_extraction.0.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_trajectory.TestTrajectory.test_trajectory_extraction.1.png b/lib/iris/tests/results/visual_tests/test_trajectory.TestTrajectory.test_trajectory_extraction.1.png deleted file mode 100644 index 4bddcf2c7b..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_trajectory.TestTrajectory.test_trajectory_extraction.1.png and /dev/null differ diff --git a/lib/iris/tests/results/visual_tests/test_trajectory.TestTrajectory.test_tri_polar.0.png b/lib/iris/tests/results/visual_tests/test_trajectory.TestTrajectory.test_tri_polar.0.png deleted file mode 100644 index 44b788a971..0000000000 Binary files a/lib/iris/tests/results/visual_tests/test_trajectory.TestTrajectory.test_tri_polar.0.png and /dev/null differ diff --git a/lib/iris/tests/runner/__init__.py b/lib/iris/tests/runner/__init__.py new file mode 100644 index 0000000000..e07487456c --- /dev/null +++ b/lib/iris/tests/runner/__init__.py @@ -0,0 +1,23 @@ +# (C) British Crown Copyright 2010 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Empty file to allow import. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/runner/__main__.py b/lib/iris/tests/runner/__main__.py new file mode 100644 index 0000000000..8b3035fc5d --- /dev/null +++ b/lib/iris/tests/runner/__main__.py @@ -0,0 +1,50 @@ +# (C) British Crown Copyright 2010 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Provides testing capabilities for installed copies of Iris. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import argparse + +from ._runner import TestRunner + + +parser = argparse.ArgumentParser('iris.tests', + description=TestRunner.description) +for long_opt, short_opt, help_text in TestRunner.user_options: + long_opt = long_opt.strip('=') + if long_opt in TestRunner.boolean_options: + parser.add_argument('--' + long_opt, '-' + short_opt, + action='store_true', help=help_text) + else: + parser.add_argument('--' + long_opt, '-' + short_opt, + help=help_text) +args = parser.parse_args() + +runner = TestRunner() + +runner.initialize_options() +for long_opt, short_opt, help_text in TestRunner.user_options: + arg = long_opt.replace('-', '_').strip('=') + setattr(runner, arg, getattr(args, arg)) +runner.finalize_options() + +runner.run() diff --git a/lib/iris/tests/runner/_runner.py b/lib/iris/tests/runner/_runner.py new file mode 100644 index 0000000000..340923f370 --- /dev/null +++ b/lib/iris/tests/runner/_runner.py @@ -0,0 +1,190 @@ +# (C) British Crown Copyright 2010 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Provides testing capabilities for installed copies of Iris. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Because this file is imported by setup.py, there may be additional runtime +# imports later in the file. +import multiprocessing +import os +import sys + + +def failed_images_html(): + """ + Generates HTML which shows the image failures side-by-side + when viewed in a web browser. + """ + from iris.tests.idiff import step_over_diffs + + data_uri_template = '{alt}' + + def image_as_base64(fname): + with open(fname, "rb") as fh: + return fh.read().encode("base64").replace("\n", "") + + html = ['', '', ''] + rdir = os.path.join(os.path.dirname(__file__), os.path.pardir, + 'result_image_comparison') + if not os.access(rdir, os.W_OK): + rdir = os.path.join(os.getcwd(), 'iris_image_test_output') + + for expected, actual, diff in step_over_diffs(rdir, 'similar', False): + expected_html = data_uri_template.format( + alt='expected', img=image_as_base64(expected)) + actual_html = data_uri_template.format( + alt='actual', img=image_as_base64(actual)) + diff_html = data_uri_template.format( + alt='diff', img=image_as_base64(diff)) + + html.extend([expected, '
    ', + expected_html, actual_html, diff_html, + '

    ']) + + html.extend(['', '']) + return '\n'.join(html) + + +# NOTE: Do not inherit from object as distutils does not like it. +class TestRunner(): + """Run the Iris tests under nose and multiprocessor for performance""" + + description = ('Run tests under nose and multiprocessor for performance. ' + 'Default behaviour is to run all non-example tests. ' + 'Specifying one or more test flags will run *only* those ' + 'tests.') + user_options = [ + ('no-data', 'n', 'Override the paths to the data repositories so it ' + 'appears to the tests that it does not exist.'), + ('stop', 'x', 'Stop running tests after the first error or failure.'), + ('system-tests', 's', 'Run the limited subset of system tests.'), + ('example-tests', 'e', 'Run the example code tests.'), + ('default-tests', 'd', 'Run the default tests.'), + ('coding-tests', 'c', 'Run the coding standards tests. (These are a ' + 'subset of the default tests.)'), + ('num-processors=', 'p', 'The number of processors used for running ' + 'the tests.'), + ('create-missing', 'm', 'Create missing test result files.'), + ('print-failed-images', 'f', 'Print HTML encoded version of failed ' + 'images.'), + ] + boolean_options = ['no-data', 'system-tests', 'stop', 'example-tests', + 'default-tests', 'coding-tests', 'create-missing', + 'print-failed-images'] + + def initialize_options(self): + self.no_data = False + self.stop = False + self.system_tests = False + self.example_tests = False + self.default_tests = False + self.coding_tests = False + self.num_processors = None + self.create_missing = False + self.print_failed_images = False + + def finalize_options(self): + # These enviroment variables will be propagated to all the + # processes that nose.run creates. + if self.no_data: + print('Running tests in no-data mode...') + import iris.config + iris.config.TEST_DATA_DIR = None + if self.create_missing: + os.environ['IRIS_TEST_CREATE_MISSING'] = 'true' + + tests = [] + if self.system_tests: + tests.append('system') + if self.default_tests: + tests.append('default') + if self.coding_tests: + tests.append('coding') + if self.example_tests: + tests.append('example') + if not tests: + tests.append('default') + print('Running test suite(s): {}'.format(', '.join(tests))) + if self.stop: + print('Stopping tests after the first error or failure') + if self.num_processors is None: + # Choose a magic number that works reasonably well for the default + # number of processes. + self.num_processors = (multiprocessing.cpu_count() + 1) // 4 + 1 + else: + self.num_processors = int(self.num_processors) + + def run(self): + import nose + + if hasattr(self, 'distribution') and self.distribution.tests_require: + self.distribution.fetch_build_eggs(self.distribution.tests_require) + + tests = [] + if self.system_tests: + tests.append('iris.tests.system_test') + if self.default_tests: + tests.append('iris.tests') + if self.coding_tests: + tests.append('iris.tests.test_coding_standards') + if self.example_tests: + import iris.config + default_doc_path = os.path.join(sys.path[0], 'docs', 'iris') + doc_path = iris.config.get_option('Resources', 'doc_dir', + default=default_doc_path) + example_path = os.path.join(doc_path, 'example_tests') + if os.path.exists(example_path): + tests.append(example_path) + else: + print('WARNING: Example path %s does not exist.' % + (example_path)) + if not tests: + tests.append('iris.tests') + + regexp_pat = r'--match=^([Tt]est(?![Mm]ixin)|[Ss]ystem)' + + n_processors = max(self.num_processors, 1) + + args = ['', None, '--processes=%s' % n_processors, + '--verbosity=2', regexp_pat, + '--process-timeout=180'] + try: + import gribapi + except ImportError: + args.append('--exclude=^grib$') + if self.stop: + args.append('--stop') + + result = True + for test in tests: + args[1] = test + print() + print('Running test discovery on %s with %s processors.' % + (test, n_processors)) + # run the tests at module level i.e. my_module.tests + # - test must start with test/Test and must not contain the + # word Mixin. + result &= nose.run(argv=args) + if result is False: + if self.print_failed_images: + print(failed_images_html()) + exit(1) diff --git a/lib/iris/tests/stock.py b/lib/iris/tests/stock.py deleted file mode 100644 index 2c96520be1..0000000000 --- a/lib/iris/tests/stock.py +++ /dev/null @@ -1,518 +0,0 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -""" -A collection of routines which create standard Cubes for test purposes. - -""" - -import os.path - -import numpy as np -import numpy.ma as ma - -from iris.cube import Cube -import iris.aux_factory -import iris.coords -import iris.coords as icoords -import iris.tests as tests -from iris.coord_systems import GeogCS, RotatedGeogCS -import numpy.ma as ma - - -def lat_lon_cube(): - """ - Returns a cube with a latitude and longitude suitable for testing - saving to PP/NetCDF etc. - - """ - cube = Cube(np.arange(12, dtype=np.int32).reshape((3, 4))) - cs = GeogCS(6371229) - coord = iris.coords.DimCoord(points=np.array([-1, 0, 1], dtype=np.int32), - standard_name='latitude', - units='degrees', - coord_system=cs) - cube.add_dim_coord(coord, 0) - coord = iris.coords.DimCoord(points=np.array([-1, 0, 1, 2], dtype=np.int32), - standard_name='longitude', - units='degrees', - coord_system=cs) - cube.add_dim_coord(coord, 1) - return cube - - -def global_pp(): - """ - Returns a two-dimensional cube derived from PP/aPPglob1/global.pp. - - The standard_name and unit attributes are added to compensate for the - broken STASH encoding in that file. - - """ - def callback_global_pp(cube, field, filename): - cube.standard_name = 'air_temperature' - cube.units = 'K' - path = tests.get_data_path(('PP', 'aPPglob1', 'global.pp')) - cube = iris.load_cube(path, callback=callback_global_pp) - return cube - - -def simple_pp(): - filename = tests.get_data_path(['PP', 'simple_pp', 'global.pp']) # Differs from global_pp() - cube = iris.load_cube(filename) - return cube - - -def simple_1d(with_bounds=True): - """ - Returns an abstract, one-dimensional cube. - - >>> print simple_1d() - thingness (foo: 11) - Dimension coordinates: - foo x - - >>> print `simple_1d().data` - [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - - """ - cube = Cube(np.arange(11, dtype=np.int32)) - cube.long_name = 'thingness' - cube.units = '1' - points = np.arange(11, dtype=np.int32) + 1 - bounds = np.column_stack([np.arange(11, dtype=np.int32), np.arange(11, dtype=np.int32) + 1]) - coord = iris.coords.DimCoord(points, long_name='foo', units='1', bounds=bounds) - cube.add_dim_coord(coord, 0) - return cube - - -def simple_2d(with_bounds=True): - """ - Returns an abstract, two-dimensional, optionally bounded, cube. - - >>> print simple_2d() - thingness (bar: 3; foo: 4) - Dimension coordinates: - bar x - - foo - x - - >>> print `simple_2d().data` - [[ 0 1 2 3] - [ 4 5 6 7] - [ 8 9 10 11]] - - - """ - cube = Cube(np.arange(12, dtype=np.int32).reshape((3, 4))) - cube.long_name = 'thingness' - cube.units = '1' - y_points = np.array([ 2.5, 7.5, 12.5]) - y_bounds = np.array([[0, 5], [5, 10], [10, 15]], dtype=np.int32) - y_coord = iris.coords.DimCoord(y_points, long_name='bar', units='1', bounds=y_bounds if with_bounds else None) - x_points = np.array([ -7.5, 7.5, 22.5, 37.5]) - x_bounds = np.array([[-15, 0], [0, 15], [15, 30], [30, 45]], dtype=np.int32) - x_coord = iris.coords.DimCoord(x_points, long_name='foo', units='1', bounds=x_bounds if with_bounds else None) - - cube.add_dim_coord(y_coord, 0) - cube.add_dim_coord(x_coord, 1) - return cube - - -def simple_2d_w_multidim_coords(with_bounds=True): - """ - Returns an abstract, two-dimensional, optionally bounded, cube. - - >>> print simple_2d_w_multidim_coords() - thingness (*ANONYMOUS*: 3; *ANONYMOUS*: 4) - Auxiliary coordinates: - bar x x - foo x x - - >>> print `simple_2d().data` - [[ 0, 1, 2, 3], - [ 4, 5, 6, 7], - [ 8, 9, 10, 11]] - - """ - cube = simple_3d_w_multidim_coords(with_bounds)[0, :, :] - cube.remove_coord('wibble') - cube.data = np.arange(12, dtype=np.int32).reshape((3, 4)) - return cube - - -def simple_3d_w_multidim_coords(with_bounds=True): - """ - Returns an abstract, two-dimensional, optionally bounded, cube. - - >>> print simple_3d_w_multidim_coords() - thingness (wibble: 2; *ANONYMOUS*: 3; *ANONYMOUS*: 4) - Dimension coordinates: - wibble x - - - Auxiliary coordinates: - bar - x x - foo - x x - - >>> print simple_3d_w_multidim_coords().data - [[[ 0 1 2 3] - [ 4 5 6 7] - [ 8 9 10 11]] - - [[12 13 14 15] - [16 17 18 19] - [20 21 22 23]]] - - """ - cube = Cube(np.arange(24, dtype=np.int32).reshape((2, 3, 4))) - cube.long_name = 'thingness' - cube.units = '1' - - y_points = np.array([[2.5, 7.5, 12.5, 17.5], - [10., 17.5, 27.5, 42.5], - [15., 22.5, 32.5, 50.]]) - y_bounds = np.array([[[0, 5], [5, 10], [10, 15], [15, 20]], - [[5, 15], [15, 20], [20, 35], [35, 50]], - [[10, 20], [20, 25], [25, 40], [40, 60]]], - dtype=np.int32) - y_coord = iris.coords.AuxCoord(points=y_points, long_name='bar', - units='1', - bounds=y_bounds if with_bounds else None) - x_points = np.array([[-7.5, 7.5, 22.5, 37.5], - [-12.5, 4., 26.5, 47.5], - [2.5, 14., 36.5, 44.]]) - x_bounds = np.array([[[-15, 0], [0, 15], [15, 30], [30, 45]], - [[-25, 0], [0, 8], [8, 45], [45, 50]], - [[-5, 10], [10, 18], [18, 55], [18, 70]]], - dtype=np.int32) - x_coord = iris.coords.AuxCoord(points=x_points, long_name='foo', - units='1', - bounds=x_bounds if with_bounds else None) - wibble_coord = iris.coords.DimCoord(np.array([10., 30.], - dtype=np.float32), - long_name='wibble', units='1') - - cube.add_dim_coord(wibble_coord, [0]) - cube.add_aux_coord(y_coord, [1, 2]) - cube.add_aux_coord(x_coord, [1, 2]) - return cube - - -def simple_3d(): - """ - Returns an abstract three dimensional cube. - - >>>print simple_3d() - thingness / (1) (wibble: 2; latitude: 3; longitude: 4) - Dimension coordinates: - wibble x - - - latitude - x - - longitude - - x - - >>> print simple_3d().data - [[[ 0 1 2 3] - [ 4 5 6 7] - [ 8 9 10 11]] - - [[12 13 14 15] - [16 17 18 19] - [20 21 22 23]]] - - """ - cube = Cube(np.arange(24, dtype=np.int32).reshape((2, 3, 4))) - cube.long_name = 'thingness' - cube.units = '1' - wibble_coord = iris.coords.DimCoord(np.array([10., 30.], - dtype=np.float32), - long_name='wibble', units='1') - lon = iris.coords.DimCoord([-180, -90, 0, 90], - standard_name='longitude', - units='degrees', circular=True) - lat = iris.coords.DimCoord([90, 0, -90], - standard_name='latitude', units='degrees') - cube.add_dim_coord(wibble_coord, [0]) - cube.add_dim_coord(lat, [1]) - cube.add_dim_coord(lon, [2]) - return cube - - -def simple_3d_mask(): - """ - Returns an abstract three dimensional cube that has data masked. - - >>>print simple_3d_mask() - thingness / (1) (wibble: 2; latitude: 3; longitude: 4) - Dimension coordinates: - wibble x - - - latitude - x - - longitude - - x - - >>> print simple_3d_mask().data - [[[-- -- -- --] - [-- -- -- --] - [-- 9 10 11]] - - [[12 13 14 15] - [16 17 18 19] - [20 21 22 23]]] - - """ - cube = simple_3d() - cube.data = ma.asanyarray(cube.data) - cube.data = ma.masked_less_equal(cube.data, 8.) - return cube - - -def track_1d(duplicate_x=False): - """ - Returns a one-dimensional track through two-dimensional space. - - >>> print track_1d() - air_temperature (y, x: 11) - Dimensioned coords: - x -> x - y -> y - Single valued coords: - - >>> print `track_1d().data` - array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) - - """ - cube = Cube(np.arange(11, dtype=np.int32), standard_name='air_temperature', units='K') - bounds = np.column_stack([np.arange(11, dtype=np.int32), np.arange(11, dtype=np.int32) + 1]) - pts = bounds[:, 1] - coord = iris.coords.AuxCoord(pts, 'projection_x_coordinate', units='1', bounds=bounds) - cube.add_aux_coord(coord, [0]) - if duplicate_x: - coord = iris.coords.AuxCoord(pts, 'projection_x_coordinate', units='1', bounds=bounds) - cube.add_aux_coord(coord, [0]) - coord = iris.coords.AuxCoord(pts * 2, 'projection_y_coordinate', units='1', bounds=bounds * 2) - cube.add_aux_coord(coord, 0) - return cube - - -def simple_2d_w_multidim_and_scalars(): - data = np.arange(50, dtype=np.int32).reshape((5, 10)) - cube = iris.cube.Cube(data, long_name='test 2d dimensional cube', units='meters') - - # DimCoords - dim1 = iris.coords.DimCoord(np.arange(5, dtype=np.float32) * 5.1 + 3.0, long_name='dim1', units='meters') - dim2 = iris.coords.DimCoord(np.arange(10, dtype=np.int32), long_name='dim2', units='meters', - bounds=np.arange(20, dtype=np.int32).reshape(10, 2)) - - # Scalars - an_other = iris.coords.AuxCoord(3.0, long_name='an_other', units='meters') - yet_an_other = iris.coords.DimCoord(23.3, standard_name='air_temperature', - long_name='custom long name', - var_name='custom_var_name', - units='K') - - # Multidim - my_multi_dim_coord = iris.coords.AuxCoord(np.arange(50, dtype=np.int32).reshape(5, 10), - long_name='my_multi_dim_coord', units='1', - bounds=np.arange(200, dtype=np.int32).reshape(5, 10, 4)) - - cube.add_dim_coord(dim1, 0) - cube.add_dim_coord(dim2, 1) - cube.add_aux_coord(an_other) - cube.add_aux_coord(yet_an_other) - cube.add_aux_coord(my_multi_dim_coord, [0, 1]) - - return cube - - -def hybrid_height(): - """ - Returns a two-dimensional (Z, X), hybrid-height cube. - - >>> print hybrid_height() - TODO: Update! - air_temperature (level_height: 3; *ANONYMOUS*: 4) - Dimension coordinates: - level_height x - - Auxiliary coordinates: - model_level_number x - - sigma x - - surface_altitude - x - Derived coordinates: - altitude x x - - >>> print hybrid_height().data - [[[ 0 1 2 3] - [ 4 5 6 7] - [ 8 9 10 11]] - - """ - data = np.arange(12, dtype='i8').reshape((3, 4)) - - orography = icoords.AuxCoord([10, 25, 50, 5], standard_name='surface_altitude', units='m') - model_level = icoords.AuxCoord([2, 1, 0], standard_name='model_level_number') - level_height = icoords.DimCoord([100, 50, 10], long_name='level_height', - units='m', attributes={'positive': 'up'}, - bounds=[[150, 75], [75, 20], [20, 0]]) - sigma = icoords.AuxCoord([0.8, 0.9, 0.95], long_name='sigma', - bounds=[[0.7, 0.85], [0.85, 0.97], [0.97, 1.0]]) - hybrid_height = iris.aux_factory.HybridHeightFactory(level_height, sigma, orography) - - cube = iris.cube.Cube(data, standard_name='air_temperature', units='K', - dim_coords_and_dims=[(level_height, 0)], - aux_coords_and_dims=[(orography, 1), (model_level, 0), (sigma, 0)], - aux_factories=[hybrid_height]) - return cube - - -def simple_4d_with_hybrid_height(): - cube = iris.cube.Cube(np.arange(3*4*5*6, dtype='i8').reshape(3,4,5,6), - "air_temperature", units="K") - - cube.add_dim_coord(iris.coords.DimCoord(np.arange(3, dtype='i8'), "time", - units="hours since epoch"), 0) - cube.add_dim_coord(iris.coords.DimCoord(np.arange(4, dtype='i8')+10, - "model_level_number", units="1"), 1) - cube.add_dim_coord(iris.coords.DimCoord(np.arange(5, dtype='i8')+20, - "grid_latitude", - units="degrees"), 2) - cube.add_dim_coord(iris.coords.DimCoord(np.arange(6, dtype='i8')+30, - "grid_longitude", - units="degrees"), 3) - - cube.add_aux_coord(iris.coords.AuxCoord(np.arange(4, dtype='i8')+40, - long_name="level_height", - units="m"), 1) - cube.add_aux_coord(iris.coords.AuxCoord(np.arange(4, dtype='i8')+50, - long_name="sigma", units="1"), 1) - cube.add_aux_coord(iris.coords.AuxCoord(np.arange(5*6, dtype='i8').reshape(5,6)+100, - long_name="surface_altitude", - units="m"), [2,3]) - - cube.add_aux_factory(iris.aux_factory.HybridHeightFactory( - delta=cube.coord("level_height"), - sigma=cube.coord("sigma"), - orography=cube.coord("surface_altitude"))) - return cube - - -def realistic_4d(): - """ - Returns a realistic 4d cube. - - >>> print repr(realistic_4d()) - - - """ - # the stock arrays were created in Iris 0.8 with: -# >>> fname = iris.sample_data_path('PP', 'COLPEX', 'theta_and_orog_subset.pp') -# >>> theta = iris.load_cube(fname, 'air_potential_temperature') -# >>> for coord in theta.coords(): -# ... print coord.name, coord.has_points(), coord.has_bounds(), coord.units -# ... -# grid_latitude True True degrees -# grid_longitude True True degrees -# level_height True True m -# model_level True False 1 -# sigma True True 1 -# time True False hours since 1970-01-01 00:00:00 -# source True False no_unit -# forecast_period True False hours -# >>> arrays = [] -# >>> for coord in theta.coords(): -# ... if coord.has_points(): arrays.append(coord.points) -# ... if coord.has_bounds(): arrays.append(coord.bounds) -# >>> arrays.append(theta.data) -# >>> arrays.append(theta.coord('sigma').coord_system.orography.data) -# >>> np.savez('stock_arrays.npz', *arrays) - - data_path = os.path.join(os.path.dirname(__file__), 'stock_arrays.npz') - r = np.load(data_path) - # sort the arrays based on the order they were originally given. The names given are of the form 'arr_1' or 'arr_10' - _, arrays = zip(*sorted(r.iteritems(), key=lambda item: int(item[0][4:]))) - - lat_pts, lat_bnds, lon_pts, lon_bnds, level_height_pts, \ - level_height_bnds, model_level_pts, sigma_pts, sigma_bnds, time_pts, \ - _source_pts, forecast_period_pts, data, orography = arrays - - - ll_cs = RotatedGeogCS(37.5, 177.5, ellipsoid=GeogCS(6371229.0)) - - lat = icoords.DimCoord(lat_pts, standard_name='grid_latitude', units='degrees', - bounds=lat_bnds, coord_system=ll_cs) - lon = icoords.DimCoord(lon_pts, standard_name='grid_longitude', units='degrees', - bounds=lon_bnds, coord_system=ll_cs) - level_height = icoords.DimCoord(level_height_pts, long_name='level_height', - units='m', bounds=level_height_bnds, - attributes={'positive': 'up'}) - model_level = icoords.DimCoord(model_level_pts, standard_name='model_level_number', - units='1', attributes={'positive': 'up'}) - sigma = icoords.AuxCoord(sigma_pts, long_name='sigma', units='1', bounds=sigma_bnds) - orography = icoords.AuxCoord(orography, standard_name='surface_altitude', units='m') - time = icoords.DimCoord(time_pts, standard_name='time', units='hours since 1970-01-01 00:00:00') - forecast_period = icoords.DimCoord(forecast_period_pts, standard_name='forecast_period', units='hours') - - hybrid_height = iris.aux_factory.HybridHeightFactory(level_height, sigma, orography) - - cube = iris.cube.Cube(data, standard_name='air_potential_temperature', units='K', - dim_coords_and_dims=[(time, 0), (model_level, 1), (lat, 2), (lon, 3)], - aux_coords_and_dims=[(orography, (2, 3)), (level_height, 1), (sigma, 1), - (forecast_period, None)], - attributes={'source': 'Iris test case'}, - aux_factories=[hybrid_height]) - return cube - - -def realistic_4d_no_derived(): - """ - Returns a realistic 4d cube without hybrid height - - >>> print repr(realistic_4d()) - - - """ - cube = realistic_4d() - - # TODO determine appropriate way to remove aux_factory from a cube - cube._aux_factories = [] - - return cube - - -def realistic_4d_w_missing_data(): - data_path = os.path.join(os.path.dirname(__file__), 'stock_mdi_arrays.npz') - data_archive = np.load(data_path) - data = ma.masked_array(data_archive['arr_0'], mask=data_archive['arr_1']) - - # sort the arrays based on the order they were originally given. The names given are of the form 'arr_1' or 'arr_10' - - ll_cs = GeogCS(6371229) - - lat = iris.coords.DimCoord(np.arange(20, dtype=np.float32), standard_name='grid_latitude', - units='degrees', coord_system=ll_cs) - lon = iris.coords.DimCoord(np.arange(20, dtype=np.float32), standard_name='grid_longitude', - units='degrees', coord_system=ll_cs) - time = iris.coords.DimCoord([1000., 1003., 1006.], standard_name='time', - units='hours since 1970-01-01 00:00:00') - forecast_period = iris.coords.DimCoord([0.0, 3.0, 6.0], standard_name='forecast_period', units='hours') - pressure = iris.coords.DimCoord(np.array([ 800., 900., 1000.], dtype=np.float32), - long_name='pressure', units='hPa') - - cube = iris.cube.Cube(data, long_name='missing data test data', units='K', - dim_coords_and_dims=[(time, 0), (pressure, 1), (lat, 2), (lon, 3)], - aux_coords_and_dims=[(forecast_period, 0)], - attributes={'source':'Iris test case'}) - return cube - - -def global_grib2(): - path = tests.get_data_path(('GRIB', 'global_t', 'global.grib2')) - cube = iris.load_cube(path) - return cube diff --git a/lib/iris/tests/stock/__init__.py b/lib/iris/tests/stock/__init__.py new file mode 100644 index 0000000000..5965d5a208 --- /dev/null +++ b/lib/iris/tests/stock/__init__.py @@ -0,0 +1,648 @@ +# (C) British Crown Copyright 2010 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +A collection of routines which create standard Cubes for test purposes. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +import os.path + +import numpy as np +import numpy.ma as ma + +from cf_units import Unit +from iris.cube import Cube +import iris.aux_factory +import iris.coords +import iris.coords as icoords +from iris.coords import DimCoord, AuxCoord +import iris.tests as tests +from iris.coord_systems import GeogCS, RotatedGeogCS +from ._stock_2d_latlons import (sample_2d_latlons, + make_bounds_discontiguous_at_point) + +def lat_lon_cube(): + """ + Returns a cube with a latitude and longitude suitable for testing + saving to PP/NetCDF etc. + + """ + cube = Cube(np.arange(12, dtype=np.int32).reshape((3, 4))) + cs = GeogCS(6371229) + coord = DimCoord(points=np.array([-1, 0, 1], dtype=np.int32), + standard_name='latitude', + units='degrees', + coord_system=cs) + cube.add_dim_coord(coord, 0) + coord = DimCoord(points=np.array([-1, 0, 1, 2], dtype=np.int32), + standard_name='longitude', + units='degrees', + coord_system=cs) + cube.add_dim_coord(coord, 1) + return cube + + +def global_pp(): + """ + Returns a two-dimensional cube derived from PP/aPPglob1/global.pp. + + The standard_name and unit attributes are added to compensate for the + broken STASH encoding in that file. + + """ + def callback_global_pp(cube, field, filename): + cube.standard_name = 'air_temperature' + cube.units = 'K' + path = tests.get_data_path(('PP', 'aPPglob1', 'global.pp')) + cube = iris.load_cube(path, callback=callback_global_pp) + return cube + + +def simple_pp(): + filename = tests.get_data_path(['PP', 'simple_pp', 'global.pp']) # Differs from global_pp() + cube = iris.load_cube(filename) + return cube + + +def simple_1d(with_bounds=True): + """ + Returns an abstract, one-dimensional cube. + + >>> print(simple_1d()) + thingness (foo: 11) + Dimension coordinates: + foo x + + >>> print(repr(simple_1d().data)) + [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + + """ + cube = Cube(np.arange(11, dtype=np.int32)) + cube.long_name = 'thingness' + cube.units = '1' + points = np.arange(11, dtype=np.int32) + 1 + bounds = np.column_stack([np.arange(11, dtype=np.int32), np.arange(11, dtype=np.int32) + 1]) + coord = DimCoord(points, long_name='foo', units='1', bounds=bounds) + cube.add_dim_coord(coord, 0) + return cube + + +def simple_2d(with_bounds=True): + """ + Returns an abstract, two-dimensional, optionally bounded, cube. + + >>> print(simple_2d()) + thingness (bar: 3; foo: 4) + Dimension coordinates: + bar x - + foo - x + + >>> print(repr(simple_2d().data)) + [[ 0 1 2 3] + [ 4 5 6 7] + [ 8 9 10 11]] + + + """ + cube = Cube(np.arange(12, dtype=np.int32).reshape((3, 4))) + cube.long_name = 'thingness' + cube.units = '1' + y_points = np.array([2.5, 7.5, 12.5]) + y_bounds = np.array([[0, 5], [5, 10], [10, 15]], dtype=np.int32) + y_coord = DimCoord(y_points, long_name='bar', units='1', + bounds=y_bounds if with_bounds else None) + x_points = np.array([ -7.5, 7.5, 22.5, 37.5]) + x_bounds = np.array([[-15, 0], [0, 15], [15, 30], [30, 45]], + dtype=np.int32) + x_coord = DimCoord(x_points, long_name='foo', units='1', + bounds=x_bounds if with_bounds else None) + + cube.add_dim_coord(y_coord, 0) + cube.add_dim_coord(x_coord, 1) + return cube + + +def simple_2d_w_multidim_coords(with_bounds=True): + """ + Returns an abstract, two-dimensional, optionally bounded, cube. + + >>> print(simple_2d_w_multidim_coords()) + thingness (*ANONYMOUS*: 3; *ANONYMOUS*: 4) + Auxiliary coordinates: + bar x x + foo x x + + >>> print(repr(simple_2d().data)) + [[ 0, 1, 2, 3], + [ 4, 5, 6, 7], + [ 8, 9, 10, 11]] + + """ + cube = simple_3d_w_multidim_coords(with_bounds)[0, :, :] + cube.remove_coord('wibble') + cube.data = np.arange(12, dtype=np.int32).reshape((3, 4)) + return cube + + +def simple_3d_w_multidim_coords(with_bounds=True): + """ + Returns an abstract, two-dimensional, optionally bounded, cube. + + >>> print(simple_3d_w_multidim_coords()) + thingness (wibble: 2; *ANONYMOUS*: 3; *ANONYMOUS*: 4) + Dimension coordinates: + wibble x - - + Auxiliary coordinates: + bar - x x + foo - x x + + >>> print(simple_3d_w_multidim_coords().data) + [[[ 0 1 2 3] + [ 4 5 6 7] + [ 8 9 10 11]] + + [[12 13 14 15] + [16 17 18 19] + [20 21 22 23]]] + + """ + cube = Cube(np.arange(24, dtype=np.int32).reshape((2, 3, 4))) + cube.long_name = 'thingness' + cube.units = '1' + + y_points = np.array([[2.5, 7.5, 12.5, 17.5], + [10., 17.5, 27.5, 42.5], + [15., 22.5, 32.5, 50.]]) + y_bounds = np.array([[[0, 5], [5, 10], [10, 15], [15, 20]], + [[5, 15], [15, 20], [20, 35], [35, 50]], + [[10, 20], [20, 25], [25, 40], [40, 60]]], + dtype=np.int32) + y_coord = AuxCoord(points=y_points, long_name='bar', units='1', + bounds=y_bounds if with_bounds else None) + x_points = np.array([[-7.5, 7.5, 22.5, 37.5], + [-12.5, 4., 26.5, 47.5], + [2.5, 14., 36.5, 44.]]) + x_bounds = np.array([[[-15, 0], [0, 15], [15, 30], [30, 45]], + [[-25, 0], [0, 8], [8, 45], [45, 50]], + [[-5, 10], [10, 18], [18, 55], [18, 70]]], + dtype=np.int32) + x_coord = AuxCoord(points=x_points, long_name='foo', units='1', + bounds=x_bounds if with_bounds else None) + wibble_coord = DimCoord(np.array([10., 30.], dtype=np.float32), + long_name='wibble', units='1') + + cube.add_dim_coord(wibble_coord, [0]) + cube.add_aux_coord(y_coord, [1, 2]) + cube.add_aux_coord(x_coord, [1, 2]) + return cube + + +def simple_3d(): + """ + Returns an abstract three dimensional cube. + + >>> print(simple_3d()) + thingness / (1) (wibble: 2; latitude: 3; longitude: 4) + Dimension coordinates: + wibble x - - + latitude - x - + longitude - - x + + >>> print(simple_3d().data) + [[[ 0 1 2 3] + [ 4 5 6 7] + [ 8 9 10 11]] + + [[12 13 14 15] + [16 17 18 19] + [20 21 22 23]]] + + """ + cube = Cube(np.arange(24, dtype=np.int32).reshape((2, 3, 4))) + cube.long_name = 'thingness' + cube.units = '1' + wibble_coord = DimCoord(np.array([10., 30.], + dtype=np.float32), + long_name='wibble', units='1') + lon = DimCoord([-180, -90, 0, 90], + standard_name='longitude', + units='degrees', circular=True) + lat = DimCoord([90, 0, -90], + standard_name='latitude', units='degrees') + cube.add_dim_coord(wibble_coord, [0]) + cube.add_dim_coord(lat, [1]) + cube.add_dim_coord(lon, [2]) + return cube + + +def simple_3d_mask(): + """ + Returns an abstract three dimensional cube that has data masked. + + >>> print(simple_3d_mask()) + thingness / (1) (wibble: 2; latitude: 3; longitude: 4) + Dimension coordinates: + wibble x - - + latitude - x - + longitude - - x + + >>> print(simple_3d_mask().data) + [[[-- -- -- --] + [-- -- -- --] + [-- 9 10 11]] + + [[12 13 14 15] + [16 17 18 19] + [20 21 22 23]]] + + """ + cube = simple_3d() + cube.data = ma.asanyarray(cube.data) + cube.data = ma.masked_less_equal(cube.data, 8.) + return cube + + +def track_1d(duplicate_x=False): + """ + Returns a one-dimensional track through two-dimensional space. + + >>> print(track_1d()) + air_temperature (y, x: 11) + Dimensioned coords: + x -> x + y -> y + Single valued coords: + + >>> print(repr(track_1d().data)) + array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) + + """ + cube = Cube(np.arange(11, dtype=np.int32), standard_name='air_temperature', + units='K') + bounds = np.column_stack([np.arange(11, dtype=np.int32), + np.arange(11, dtype=np.int32) + 1]) + pts = bounds[:, 1] + coord = AuxCoord(pts, 'projection_x_coordinate', units='1', bounds=bounds) + cube.add_aux_coord(coord, [0]) + if duplicate_x: + coord = AuxCoord(pts, 'projection_x_coordinate', units='1', + bounds=bounds) + cube.add_aux_coord(coord, [0]) + coord = AuxCoord(pts * 2, 'projection_y_coordinate', units='1', + bounds=bounds * 2) + cube.add_aux_coord(coord, 0) + return cube + + +def simple_2d_w_multidim_and_scalars(): + data = np.arange(50, dtype=np.int32).reshape((5, 10)) + cube = iris.cube.Cube(data, long_name='test 2d dimensional cube', + units='meters') + + # DimCoords + dim1 = DimCoord(np.arange(5, dtype=np.float32) * 5.1 + 3.0, + long_name='dim1', units='meters') + dim2 = DimCoord(np.arange(10, dtype=np.int32), + long_name='dim2', units='meters', + bounds=np.arange(20, dtype=np.int32).reshape(10, 2)) + + # Scalars + an_other = AuxCoord(3.0, long_name='an_other', units='meters') + yet_an_other = DimCoord(23.3, standard_name='air_temperature', + long_name='custom long name', + var_name='custom_var_name', units='K') + + # Multidim + my_multi_dim_coord = AuxCoord(np.arange(50, dtype=np.int32).reshape(5, 10), + long_name='my_multi_dim_coord', units='1', + bounds=np.arange(200, dtype=np.int32). + reshape(5, 10, 4)) + + cube.add_dim_coord(dim1, 0) + cube.add_dim_coord(dim2, 1) + cube.add_aux_coord(an_other) + cube.add_aux_coord(yet_an_other) + cube.add_aux_coord(my_multi_dim_coord, [0, 1]) + + return cube + + +def hybrid_height(): + """ + Returns a two-dimensional (Z, X), hybrid-height cube. + + >>> print(hybrid_height()) + TODO: Update! + air_temperature (level_height: 3; *ANONYMOUS*: 4) + Dimension coordinates: + level_height x - + Auxiliary coordinates: + model_level_number x - + sigma x - + surface_altitude - x + Derived coordinates: + altitude x x + + >>> print(hybrid_height().data) + [[[ 0 1 2 3] + [ 4 5 6 7] + [ 8 9 10 11]] + + """ + data = np.arange(12, dtype='i8').reshape((3, 4)) + + orography = AuxCoord([10, 25, 50, 5], standard_name='surface_altitude', + units='m') + model_level = AuxCoord([2, 1, 0], standard_name='model_level_number') + level_height = DimCoord([100, 50, 10], long_name='level_height', + units='m', attributes={'positive': 'up'}, + bounds=[[150, 75], [75, 20], [20, 0]]) + sigma = AuxCoord([0.8, 0.9, 0.95], long_name='sigma', + bounds=[[0.7, 0.85], [0.85, 0.97], [0.97, 1.0]]) + hybrid_height = iris.aux_factory.HybridHeightFactory(level_height, + sigma, orography) + + cube = iris.cube.Cube(data, standard_name='air_temperature', units='K', + dim_coords_and_dims=[(level_height, 0)], + aux_coords_and_dims=[(orography, 1), + (model_level, 0), (sigma, 0)], + aux_factories=[hybrid_height]) + return cube + + +def simple_4d_with_hybrid_height(): + cube = iris.cube.Cube(np.arange(3*4*5*6, dtype='i8').reshape(3, 4, 5, 6), + "air_temperature", units="K") + + cube.add_dim_coord(DimCoord(np.arange(3, dtype='i8'), "time", + units="hours since epoch"), 0) + cube.add_dim_coord(DimCoord(np.arange(4, dtype='i8')+10, + "model_level_number", units="1"), 1) + cube.add_dim_coord(DimCoord(np.arange(5, dtype='i8')+20, + "grid_latitude", + units="degrees"), 2) + cube.add_dim_coord(DimCoord(np.arange(6, dtype='i8')+30, + "grid_longitude", + units="degrees"), 3) + + cube.add_aux_coord(AuxCoord(np.arange(4, dtype='i8')+40, + long_name="level_height", + units="m"), 1) + cube.add_aux_coord(AuxCoord(np.arange(4, dtype='i8')+50, + long_name="sigma", units="1"), 1) + cube.add_aux_coord(AuxCoord(np.arange(5*6, dtype='i8').reshape(5, 6)+100, + long_name="surface_altitude", + units="m"), [2, 3]) + + cube.add_aux_factory(iris.aux_factory.HybridHeightFactory( + delta=cube.coord("level_height"), + sigma=cube.coord("sigma"), + orography=cube.coord("surface_altitude"))) + return cube + + +def realistic_3d(): + """ + Returns a realistic 3d cube. + + >>> print(repr(realistic_3d())) + + + """ + data = np.arange(7*9*11).reshape((7,9,11)) + lat_pts = np.linspace(-4, 4, 9) + lon_pts = np.linspace(-5, 5, 11) + time_pts = np.linspace(394200, 394236, 7) + forecast_period_pts = np.linspace(0, 36, 7) + ll_cs = RotatedGeogCS(37.5, 177.5, ellipsoid=GeogCS(6371229.0)) + + lat = icoords.DimCoord(lat_pts, standard_name='grid_latitude', + units='degrees', coord_system=ll_cs) + lon = icoords.DimCoord(lon_pts, standard_name='grid_longitude', + units='degrees', coord_system=ll_cs) + time = icoords.DimCoord(time_pts, standard_name='time', + units='hours since 1970-01-01 00:00:00') + forecast_period = icoords.DimCoord(forecast_period_pts, + standard_name='forecast_period', + units='hours') + height = icoords.DimCoord(1000.0, standard_name='air_pressure', + units='Pa') + cube = iris.cube.Cube(data, standard_name='air_potential_temperature', + units='K', + dim_coords_and_dims=[(time, 0), (lat, 1), (lon, 2)], + aux_coords_and_dims=[(forecast_period, 0), + (height, None)], + attributes={'source': 'Iris test case'}) + return cube + + +def realistic_4d(): + """ + Returns a realistic 4d cube. + + >>> print(repr(realistic_4d())) + + + """ + # the stock arrays were created in Iris 0.8 with: +# >>> fname = iris.sample_data_path('PP', 'COLPEX', 'theta_and_orog_subset.pp') +# >>> theta = iris.load_cube(fname, 'air_potential_temperature') +# >>> for coord in theta.coords(): +# ... print(coord.name, coord.has_points(), coord.has_bounds(), coord.units) +# ... +# grid_latitude True True degrees +# grid_longitude True True degrees +# level_height True True m +# model_level True False 1 +# sigma True True 1 +# time True False hours since 1970-01-01 00:00:00 +# source True False no_unit +# forecast_period True False hours +# >>> arrays = [] +# >>> for coord in theta.coords(): +# ... if coord.has_points(): arrays.append(coord.points) +# ... if coord.has_bounds(): arrays.append(coord.bounds) +# >>> arrays.append(theta.data) +# >>> arrays.append(theta.coord('sigma').coord_system.orography.data) +# >>> np.savez('stock_arrays.npz', *arrays) + data_path = tests.get_data_path(('stock', 'stock_arrays.npz')) + if not os.path.isfile(data_path): + raise IOError('Test data is not available at {}.'.format(data_path)) + r = np.load(data_path) + # sort the arrays based on the order they were originally given. + # The names given are of the form 'arr_1' or 'arr_10' + _, arrays = zip(*sorted(six.iteritems(r), key=lambda item: int(item[0][4:]))) + + lat_pts, lat_bnds, lon_pts, lon_bnds, level_height_pts, \ + level_height_bnds, model_level_pts, sigma_pts, sigma_bnds, time_pts, \ + _source_pts, forecast_period_pts, data, orography = arrays + + ll_cs = RotatedGeogCS(37.5, 177.5, ellipsoid=GeogCS(6371229.0)) + + lat = icoords.DimCoord(lat_pts, standard_name='grid_latitude', + units='degrees', bounds=lat_bnds, + coord_system=ll_cs) + lon = icoords.DimCoord(lon_pts, standard_name='grid_longitude', + units='degrees', bounds=lon_bnds, + coord_system=ll_cs) + level_height = icoords.DimCoord(level_height_pts, long_name='level_height', + units='m', bounds=level_height_bnds, + attributes={'positive': 'up'}) + model_level = icoords.DimCoord(model_level_pts, + standard_name='model_level_number', + units='1', attributes={'positive': 'up'}) + sigma = icoords.AuxCoord(sigma_pts, long_name='sigma', units='1', + bounds=sigma_bnds) + orography = icoords.AuxCoord(orography, standard_name='surface_altitude', + units='m') + time = icoords.DimCoord(time_pts, standard_name='time', + units='hours since 1970-01-01 00:00:00') + forecast_period = icoords.DimCoord(forecast_period_pts, + standard_name='forecast_period', + units='hours') + + hybrid_height = iris.aux_factory.HybridHeightFactory(level_height, + sigma, orography) + + cube = iris.cube.Cube(data, standard_name='air_potential_temperature', + units='K', + dim_coords_and_dims=[(time, 0), (model_level, 1), + (lat, 2), (lon, 3)], + aux_coords_and_dims=[(orography, (2, 3)), + (level_height, 1), (sigma, 1), + (forecast_period, None)], + attributes={'source': 'Iris test case'}, + aux_factories=[hybrid_height]) + return cube + + +def realistic_4d_no_derived(): + """ + Returns a realistic 4d cube without hybrid height + + >>> print(repr(realistic_4d())) + + + """ + cube = realistic_4d() + + # TODO determine appropriate way to remove aux_factory from a cube + cube._aux_factories = [] + + return cube + + +def realistic_4d_w_missing_data(): + data_path = tests.get_data_path(('stock', 'stock_mdi_arrays.npz')) + if not os.path.isfile(data_path): + raise IOError('Test data is not available at {}.'.format(data_path)) + data_archive = np.load(data_path) + data = ma.masked_array(data_archive['arr_0'], mask=data_archive['arr_1']) + + # sort the arrays based on the order they were originally given. + # The names given are of the form 'arr_1' or 'arr_10' + + ll_cs = GeogCS(6371229) + + lat = DimCoord(np.arange(20, dtype=np.float32), + standard_name='grid_latitude', + units='degrees', coord_system=ll_cs) + lon = DimCoord(np.arange(20, dtype=np.float32), + standard_name='grid_longitude', + units='degrees', coord_system=ll_cs) + time = DimCoord([1000., 1003., 1006.], standard_name='time', + units='hours since 1970-01-01 00:00:00') + forecast_period = DimCoord([0.0, 3.0, 6.0], + standard_name='forecast_period', + units='hours') + pressure = DimCoord(np.array([800., 900., 1000.], dtype=np.float32), + long_name='pressure', units='hPa') + + cube = iris.cube.Cube(data, long_name='missing data test data', units='K', + dim_coords_and_dims=[(time, 0), (pressure, 1), + (lat, 2), (lon, 3)], + aux_coords_and_dims=[(forecast_period, 0)], + attributes={'source': 'Iris test case'}) + return cube + + +def global_grib2(): + path = tests.get_data_path(('GRIB', 'global_t', 'global.grib2')) + cube = iris.load_cube(path) + return cube + + +def ocean_sigma_z(): + """ + Return a sample cube with an + :class:`iris.aux_factory.OceanSigmaZFactory` vertical coordinate. + + This is a fairly small cube with real coordinate arrays. The coordinate + values are derived from the sample data linked at + https://github.com/SciTools/iris/pull/509#issuecomment-23565381. + + """ + co_time = DimCoord([0.0, 1.0], standard_name='time', units='') + co_lats = DimCoord([-58.1, -52.7, -46.9], + standard_name='latitude', units=Unit('degrees')) + co_lons = DimCoord([65.1, 72.9, 83.7, 96.5], + standard_name='longitude', units=Unit('degrees')) + co_ssh = AuxCoord([[[-0.63157895, -0.52631579, -0.42105263, -0.31578947], + [-0.78947368, -0.68421053, -0.57894737, -0.47368421], + [-0.94736842, -0.84210526, -0.73684211, -0.63157895]], + [[-0.84210526, -0.73684211, -0.63157895, -0.52631579], + [-1.00000000, -0.89473684, -0.78947368, -0.68421053], + [-1.15789474, -1.05263158, -0.94736842, -0.84210526]]], + standard_name=u'sea_surface_height', units=Unit('m')) + + co_sigma = AuxCoord([0., -0.1, -0.6, -1., -1.], + standard_name=u'ocean_sigma_z_coordinate', + units=Unit('1'), + attributes={'positive': 'up'}) + + co_zlay = AuxCoord([-137.2, -137.3, -137.4, -368.4, -1495.6], + long_name='layer_depth', units=Unit('m')) + co_depth = AuxCoord([[1625.7, 3921.2, 4106.4, 5243.5], + [3615.4, 4942.6, 3883.6, 4823.1], + [3263.2, 2816.3, 2741.8, 3883.6]], + standard_name=u'depth', units=Unit('m')) + co_depthc = DimCoord(137.9, long_name='depth_c', units=Unit('m')) + co_nsigma = DimCoord(3, long_name='nsigma') + + cube = Cube(np.zeros((2, 5, 3, 4))) + cube.add_dim_coord(co_time, 0) + cube.add_dim_coord(co_lats, 2) + cube.add_dim_coord(co_lons, 3) + cube.add_aux_coord(co_zlay, 1) + cube.add_aux_coord(co_sigma, 1) + cube.add_aux_coord(co_ssh, (0, 2, 3)) + cube.add_aux_coord(co_depth, (2, 3)) + cube.add_aux_coord(co_depthc) + cube.add_aux_coord(co_nsigma) + + fact = iris.aux_factory.OceanSigmaZFactory( + depth=co_depth, eta=co_ssh, depth_c=co_depthc, zlev=co_zlay, + sigma=co_sigma, nsigma=co_nsigma) + cube.add_aux_factory(fact) + return cube diff --git a/lib/iris/tests/stock/_stock_2d_latlons.py b/lib/iris/tests/stock/_stock_2d_latlons.py new file mode 100644 index 0000000000..4fb3979a06 --- /dev/null +++ b/lib/iris/tests/stock/_stock_2d_latlons.py @@ -0,0 +1,365 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Extra stock routines for making and manipulating cubes with 2d coordinates, +to mimic ocean grid data. + +""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import numpy as np +import numpy.ma as ma + +from iris.analysis.cartography import unrotate_pole +from iris.cube import Cube +from iris.coords import AuxCoord, DimCoord +from iris.coord_systems import RotatedGeogCS + + +def expand_1d_x_and_y_bounds_to_2d_xy(x_bounds_1d, y_bounds_1d): + """ + Convert bounds for separate 1-D X and Y coords into bounds for the + equivalent 2D coordinates. + + The output arrays have 4 points per cell, for 4 'corners' of a gridcell, + in the usual anticlockwise order + (bottom-left, bottom-right, top-right, top-left). + + If 1-dimensional X and Y coords have shapes nx and ny, then their bounds + have shapes (nx, 2) and (ny, 2). + The equivalent 2d coordinates would have values which are a "meshgrid" of + the original 1-D points, both having the shape (ny, ny). + The outputs are 2d bounds arrays suitable for such 2d coordinates. + + Args: + + * x_bounds_1d, y_bounds_1d : (array) + Coordinate bounds arrays, with shapes (nx, 2) and (ny, 2). + + Result: + + * x_bounds_2d, y_bounds_2d : (array) + Expanded 2d bounds arrays, both of shape (ny, nx, 4). + + """ + shapes = [bds.shape for bds in (x_bounds_1d, y_bounds_1d)] + for shape in shapes: + if len(shape) != 2 or shape[1] != 2: + msg = ('One-dimensional bounds arrays must have shapes (ny, 2) ' + 'and (nx, 2). Got {} and {}.') + raise ValueError(msg.format(*shapes)) + + # Construct output arrays, which are both (ny, nx, 4). + nx, ny = [shape[0] for shape in shapes] + bds_2d_x = np.zeros((ny, nx, 4)) + bds_2d_y = bds_2d_x.copy() + + # Expand x bounds to 2D array (ny, nx, 4) : the same over all 'Y'. + # Bottom left+right corners are the original 1-D x bounds. + bds_2d_x[:, :, 0] = x_bounds_1d[:, 0].reshape((1, nx)) + bds_2d_x[:, :, 1] = x_bounds_1d[:, 1].reshape((1, nx)) + # Top left+right corners are the same as bottom left+right. + bds_2d_x[:, :, 2] = bds_2d_x[:, :, 1].copy() + bds_2d_x[:, :, 3] = bds_2d_x[:, :, 0].copy() + + # Expand y bounds to 2D array (ny, nx, 4) : the same over all 'X'. + # Left-hand lower+upper corners are the original 1-D y bounds. + bds_2d_y[:, :, 0] = y_bounds_1d[:, 0].reshape((ny, 1)) + bds_2d_y[:, :, 3] = y_bounds_1d[:, 1].reshape((ny, 1)) + # Right-hand lower+upper corners are the same as the left-hand ones. + bds_2d_y[:, :, 1] = bds_2d_y[:, :, 0].copy() + bds_2d_y[:, :, 2] = bds_2d_y[:, :, 3].copy() + + return bds_2d_x, bds_2d_y + + +def grid_coords_2d_from_1d(x_coord_1d, y_coord_1d): + """ + Calculate a pair of 2d X+Y coordinates from 1d ones, in a "meshgrid" style. + If the inputs are bounded, the outputs have 4 points per bounds in the + usual way, i.e. points 0,1,2,3 are the gridcell corners anticlockwise from + the bottom left. + + """ + for coord in (x_coord_1d, y_coord_1d): + if coord.ndim != 1: + msg = ('Input coords must be one-dimensional. ' + 'Coordinate "{}" has shape {}.') + raise ValueError(msg.format(coord.name(), coord.shape)) + + # Calculate centre-points as a mesh of the 2 inputs. + pts_2d_x, pts_2d_y = np.meshgrid(x_coord_1d.points, y_coord_1d.points) + if not x_coord_1d.has_bounds() or not y_coord_1d.has_bounds(): + bds_2d_x = None + bds_2d_y = None + else: + bds_2d_x, bds_2d_y = expand_1d_x_and_y_bounds_to_2d_xy( + x_coord_1d.bounds, y_coord_1d.bounds) + + # Make two new coords + return them. + result = [] + for pts, bds, name in zip((pts_2d_x, pts_2d_y), + (bds_2d_x, bds_2d_y), + ('longitude', 'latitude')): + coord = AuxCoord(pts, bounds=bds, standard_name=name, units='degrees') + result.append(coord) + + return result + + +def sample_2d_latlons(regional=False, rotated=False, transformed=False): + """ + Construct small 2d cubes with 2d X and Y coordinates. + + This makes cubes with 'expanded' coordinates (4 bounds per cell), analagous + to ORCA data. + The coordinates are always geographical, so either it has a coord system + or they are "true" lats + lons. + ( At present, they are always latitudes and longitudes, but maybe in a + rotated system. ) + The results always have fully contiguous bounds. + + Kwargs: + * regional (bool): + If False (default), results cover the whole globe, and there is + implicit connectivity between rhs + lhs of the array. + If True, coverage is regional and edges do not connect. + * rotated (bool): + If False, X and Y coordinates are true-latitudes and longitudes, with + an implicit coordinate system (i.e. None). + If True, the X and Y coordinates are lats+lons in a selected + rotated-latlon coordinate system. + * transformed (bool): + Build coords from rotated coords as for 'rotated', but then replace + their values with the equivalent "true" lats + lons, and no + coord-system (defaults to true-latlon). + In this case, the X and Y coords are no longer 'meshgrid' style, + i.e. the points + bounds values vary in *both* dimensions. + + .. note:: + + 'transformed' is an alternative to 'rotated' : when 'transformed' is + set, then 'rotated' has no effect. + + .. Some sample results printouts :: + + >>> print(sample_2d_latlons()) + test_data / (unknown) (-- : 5; -- : 6) + Auxiliary coordinates: + latitude x x + longitude x x + >>> + >>> print(sample_2d_latlons().coord(axis='x')[0, :2]) + AuxCoord(array([ 37.5 , 93.75]), + bounds=array([[ 0. , 65.625, 65.625, 0. ], + [ 65.625, 121.875, 121.875, 65.625]]), + standard_name='longitude', units=Unit('degrees')) + >>> print(np.round(sample_2d_latlons().coord(axis='x').points, 3)) + [[ 37.5 93.75 150. 206.25 262.5 318.75] + [ 37.5 93.75 150. 206.25 262.5 318.75] + [ 37.5 93.75 150. 206.25 262.5 318.75] + [ 37.5 93.75 150. 206.25 262.5 318.75] + [ 37.5 93.75 150. 206.25 262.5 318.75]] + >>> print(np.round(sample_2d_latlons().coord(axis='y').points, 3)) + [[-85. -85. -85. -85. -85. -85. ] + [-47.5 -47.5 -47.5 -47.5 -47.5 -47.5] + [-10. -10. -10. -10. -10. -10. ] + [ 27.5 27.5 27.5 27.5 27.5 27.5] + [ 65. 65. 65. 65. 65. 65. ]] + + + >>> print(np.round( + sample_2d_latlons(rotated=True).coord(axis='x').points, 3)) + [[ 37.5 93.75 150. 206.25 262.5 318.75] + [ 37.5 93.75 150. 206.25 262.5 318.75] + [ 37.5 93.75 150. 206.25 262.5 318.75] + [ 37.5 93.75 150. 206.25 262.5 318.75] + [ 37.5 93.75 150. 206.25 262.5 318.75]] + >>> print(sample_2d_latlons(rotated=True).coord(axis='y').coord_system) + RotatedGeogCS(75.0, 120.0) + + + >>> print( + sample_2d_latlons(transformed=True).coord(axis='y').coord_system) + None + >>> print(np.round( + sample_2d_latlons(transformed=True).coord(axis='x').points, 3)) + [[ -50.718 -40.983 -46.74 -71.938 -79.293 -70.146] + [ -29.867 17.606 77.936 157.145 -141.037 -93.172] + [ -23.139 31.007 87.699 148.322 -154.639 -100.505] + [ -16.054 41.218 92.761 143.837 -164.738 -108.105] + [ 10.86 61.78 100.236 137.285 175.511 -135.446]] + >>> print(np.round( + sample_2d_latlons(transformed=True).coord(axis='y').points, 3)) + [[-70.796 -74.52 -79.048 -79.26 -74.839 -70.96 ] + [-34.99 -46.352 -59.721 -60.34 -47.305 -35.499] + [ 1.976 -10.626 -22.859 -23.349 -11.595 1.37 ] + [ 38.914 25.531 14.312 13.893 24.585 38.215] + [ 74.197 60.258 51.325 51.016 59.446 73.268]] + >>> + + """ + def sample_cube(xargs, yargs): + # Make a test cube with given latitude + longitude coordinates. + # xargs/yargs are args for np.linspace (start, stop, N), to make the X + # and Y coordinate points. + x0, x1, nx = xargs + y0, y1, ny = yargs + # Data has cycling values, staggered a bit in successive rows. + data = np.zeros((ny, nx)) + data.flat[:] = np.arange(ny * nx) % (nx + 2) + # Build a 2d cube with longitude + latitude coordinates. + cube = Cube(data, long_name='test_data') + x_pts = np.linspace(x0, x1, nx, endpoint=True) + y_pts = np.linspace(y0, y1, ny, endpoint=True) + co_x = DimCoord(x_pts, standard_name='longitude', units='degrees') + co_y = DimCoord(y_pts, standard_name='latitude', units='degrees') + cube.add_dim_coord(co_y, 0) + cube.add_dim_coord(co_x, 1) + return cube + + # Start by making a "normal" cube with separate 1-D X and Y coords. + if regional: + # Make a small regional cube. + cube = sample_cube(xargs=(150., 243.75, 6), yargs=(-10., 40., 5)) + + # Add contiguous bounds. + for ax in ('x', 'y'): + cube.coord(axis=ax).guess_bounds() + else: + # Global data, but at a drastically reduced resolution. + cube = sample_cube(xargs=(37.5, 318.75, 6), yargs=(-85., 65., 5)) + + # Make contiguous bounds and adjust outer edges to ensure it is global. + for name in ('longitude', 'latitude'): + coord = cube.coord(name) + coord.guess_bounds() + bds = coord.bounds.copy() + # Make bounds global, by fixing lowest and uppermost values. + if name == 'longitude': + bds[0, 0] = 0.0 + bds[-1, 1] = 360.0 + else: + bds[0, 0] = -90.0 + bds[-1, 1] = 90.0 + coord.bounds = bds + + # Now convert the 1-d coords to 2-d equivalents. + # Get original 1-d coords. + co_1d_x, co_1d_y = [cube.coord(axis=ax).copy() for ax in ('x', 'y')] + + # Calculate 2-d equivalents. + co_2d_x, co_2d_y = grid_coords_2d_from_1d(co_1d_x, co_1d_y) + + # Remove the old grid coords. + for coord in (co_1d_x, co_1d_y): + cube.remove_coord(coord) + + # Add the new grid coords. + for coord in (co_2d_x, co_2d_y): + cube.add_aux_coord(coord, (0, 1)) + + if transformed or rotated: + # Put the cube locations into a rotated coord system. + pole_lat, pole_lon = 75.0, 120.0 + if transformed: + # Reproject coordinate values from rotated to true lat-lons. + co_x, co_y = [cube.coord(axis=ax) for ax in ('x', 'y')] + # Unrotate points. + lons, lats = co_x.points, co_y.points + lons, lats = unrotate_pole(lons, lats, pole_lon, pole_lat) + co_x.points, co_y.points = lons, lats + # Unrotate bounds. + lons, lats = co_x.bounds, co_y.bounds + # Note: save the shape, flatten + then re-apply the shape, because + # "unrotate_pole" uses "cartopy.crs.CRS.transform_points", which + # only works on arrays of 1 or 2 dimensions. + shape = lons.shape + lons, lats = unrotate_pole(lons.flatten(), lats.flatten(), + pole_lon, pole_lat) + co_x.bounds, co_y.bounds = lons.reshape(shape), lats.reshape(shape) + else: + # "Just" rotate operation : add a coord-system to each coord. + cs = RotatedGeogCS(pole_lat, pole_lon) + for coord in cube.coords(): + coord.coord_system = cs + + return cube + + +def make_bounds_discontiguous_at_point(cube, at_iy, at_ix, in_y=False): + """ + Meddle with the XY grid bounds of a 2D cube to make the grid discontiguous. + + Changes the points and bounds of a single gridcell, so that it becomes + discontinuous with an adjacent gridcell : either the one to its right, or + the one above it (if 'in_y' is True). + + Also masks the cube data at the given point. + + The cube must be 2-dimensional and have bounded 2d 'x' and 'y' coordinates. + + """ + x_coord = cube.coord(axis='x') + y_coord = cube.coord(axis='y') + assert x_coord.shape == y_coord.shape + assert (coord.bounds.ndim == 3 and coord.shape[-1] == 4 + for coord in (x_coord, y_coord)) + + # For both X and Y coord, move points + bounds to create a discontinuity. + def adjust_coord(coord): + pts, bds = coord.points, coord.bounds + # Fetch the 4 bounds (bottom-left, bottom-right, top-right, top-left) + bds_bl, bds_br, bds_tr, bds_tl = bds[at_iy, at_ix] + if not in_y: + # Make a discontinuity "at" (iy, ix), by moving the right-hand edge + # of the cell to the midpoint of the existing left+right bounds. + new_bds_br = 0.5 * (bds_bl + bds_br) + new_bds_tr = 0.5 * (bds_tl + bds_tr) + bds_br, bds_tr = new_bds_br, new_bds_tr + else: + # Same but in the 'grid y direction' : + # Make a discontinuity "at" (iy, ix), by moving the **top** edge of + # the cell to the midpoint of the existing **top+bottom** bounds. + new_bds_tl = 0.5 * (bds_bl + bds_tl) + new_bds_tr = 0.5 * (bds_br + bds_tr) + bds_tl, bds_tr = new_bds_tl, new_bds_tr + + # Write in the new bounds (all 4 corners). + bds[at_iy, at_ix] = [bds_bl, bds_br, bds_tr, bds_tl] + # Also reset the cell midpoint to the middle of the 4 new corners, + # in case having a midpoint outside the corners might cause a problem. + new_pt = 0.25 * sum([bds_bl, bds_br, bds_tr, bds_tl]) + pts[at_iy, at_ix] = new_pt + # Write back the coord points+bounds (can only assign whole arrays). + coord.points, coord.bounds = pts, bds + + adjust_coord(x_coord) + adjust_coord(y_coord) + + # Check which dimensions are spanned by each coordinate. + for coord in (x_coord, y_coord): + span = set(cube.coord_dims(coord)) + if not span: + msg = 'The coordinate {!r} doesn\'t span a data dimension.' + raise ValueError(msg.format(coord.name())) + + masked_data = ma.masked_array(cube.data) + masked_data[at_iy, at_ix] = ma.masked + + cube.data = masked_data diff --git a/lib/iris/tests/stock_arrays.npz b/lib/iris/tests/stock_arrays.npz deleted file mode 100644 index 76fa668266..0000000000 Binary files a/lib/iris/tests/stock_arrays.npz and /dev/null differ diff --git a/lib/iris/tests/system_test.py b/lib/iris/tests/system_test.py index 9dc6d7a14c..767e5da160 100644 --- a/lib/iris/tests/system_test.py +++ b/lib/iris/tests/system_test.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -22,30 +22,33 @@ The system tests can be run with ``python setup.py test --system-tests``. """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised before importing anything else -import sys +import cf_units import numpy as np import iris -import iris.fileformats.grib as grib import iris.fileformats.netcdf as netcdf import iris.fileformats.pp as pp import iris.tests as tests -import iris.unit + class SystemInitialTest(tests.IrisTest): def system_test_supported_filetypes(self): nx, ny = 60, 60 - dataarray = np.arange(nx * ny, dtype='>f4').reshape(nx, ny) + data = np.arange(nx * ny, dtype='>f4').reshape(nx, ny) laty = np.linspace(0, 59, ny).astype('f8') lonx = np.linspace(30, 89, nx).astype('f8') horiz_cs = lambda : iris.coord_systems.GeogCS(6371229) - cm = iris.cube.Cube(data=dataarray, long_name="System test data", units='m s-1') + cm = iris.cube.Cube(data, 'wind_speed', units='m s-1') cm.add_dim_coord( iris.coords.DimCoord(laty, 'latitude', units='degrees', coord_system=horiz_cs()), @@ -56,23 +59,26 @@ def system_test_supported_filetypes(self): 1) cm.add_aux_coord(iris.coords.AuxCoord(np.array([9], 'i8'), 'forecast_period', units='hours')) - hours_since_epoch = iris.unit.Unit('hours since epoch', - iris.unit.CALENDAR_GREGORIAN) + hours_since_epoch = cf_units.Unit('hours since epoch', + cf_units.CALENDAR_GREGORIAN) cm.add_aux_coord(iris.coords.AuxCoord(np.array([3], 'i8'), 'time', units=hours_since_epoch)) cm.add_aux_coord(iris.coords.AuxCoord(np.array([99], 'i8'), long_name='pressure', units='Pa')) - cm.assert_valid() - - for filetype in ('.nc', '.pp' , '.grib2'): + filetypes = ('.nc', '.pp') + if tests.GRIB_AVAILABLE: + filetypes += ('.grib2',) + for filetype in filetypes: saved_tmpfile = iris.util.create_temp_filename(suffix=filetype) iris.save(cm, saved_tmpfile) new_cube = iris.load_cube(saved_tmpfile) + self.assertCML(new_cube, + ('system', + 'supported_filetype_%s.cml' % filetype)) - self.assertCML(new_cube, ('system', 'supported_filetype_%s.cml' % filetype)) - + @tests.skip_grib def system_test_grib_patch(self): import gribapi gm = gribapi.grib_new_from_samples("GRIB2") @@ -85,7 +91,8 @@ def system_test_grib_patch(self): self.assertEqual(new_result, new_missing_value) def system_test_imports_general(self): - import matplotlib + if tests.MPL_AVAILABLE: + import matplotlib import netCDF4 diff --git a/lib/iris/tests/test_abf.py b/lib/iris/tests/test_abf.py index 93a192d99c..30272b2687 100644 --- a/lib/iris/tests/test_abf.py +++ b/lib/iris/tests/test_abf.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2012 - 2014, Met Office +# (C) British Crown Copyright 2012 - 2017, Met Office # # This file is part of Iris. # @@ -15,6 +15,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised before # importing anything else import iris.tests as tests @@ -25,8 +28,8 @@ import iris.fileformats.abf -@iris.tests.skip_data -class TestAbfLoad(tests.GraphicsTest): +@tests.skip_data +class TestAbfLoad(tests.IrisTest): def setUp(self): self.path = tests.get_data_path(('abf', 'AVHRRBUVI01.1985apra.abf')) diff --git a/lib/iris/tests/test_aggregate_by.py b/lib/iris/tests/test_aggregate_by.py index 1bd3223229..9b2b815060 100644 --- a/lib/iris/tests/test_aggregate_by.py +++ b/lib/iris/tests/test_aggregate_by.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -15,6 +15,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before # importing anything else @@ -62,7 +64,7 @@ def setUp(self): long_name='height', units='m') - model_level = iris.coords.DimCoord(range(z_points.size), + model_level = iris.coords.DimCoord(np.arange(z_points.size), standard_name='model_level_number') self.cube_single.add_aux_coord(self.coord_z_single, 0) @@ -93,7 +95,7 @@ def setUp(self): long_name='level', units='1') - model_level = iris.coords.DimCoord(range(z1_points.size), + model_level = iris.coords.DimCoord(np.arange(z1_points.size), standard_name='model_level_number') self.cube_multi.add_aux_coord(self.coord_z1_multi, 0) diff --git a/lib/iris/tests/test_analysis.py b/lib/iris/tests/test_analysis.py index f1a91ef7a3..e07848a3d8 100644 --- a/lib/iris/tests/test_analysis.py +++ b/lib/iris/tests/test_analysis.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -16,35 +16,41 @@ # along with Iris. If not, see . -from __future__ import division +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests -import itertools - import cartopy.crs as ccrs -import matplotlib -import matplotlib.pyplot as plt +import cf_units import numpy as np import numpy.ma as ma -import shapely.geometry import iris import iris.analysis.cartography -import iris.analysis.geometry import iris.analysis.maths import iris.coord_systems import iris.coords import iris.cube import iris.tests.stock +# Run tests in no graphics mode if matplotlib is not available. +if tests.MPL_AVAILABLE: + import matplotlib + import matplotlib.pyplot as plt + class TestAnalysisCubeCoordComparison(tests.IrisTest): - def assertComparisonDict(self, comarison_dict, reference_filename): + def assertComparisonDict(self, comparison_dict, reference_filename): string = '' - for key, coord_groups in comarison_dict.iteritems(): + for key in sorted(comparison_dict): + coord_groups = comparison_dict[key] string += ('%40s ' % key) - names = [[coord.name() if coord is not None else 'None' for coord in coords] for coords in coord_groups] + names = [[coord.name() if coord is not None else 'None' + for coord in coords] + for coords in coord_groups] string += str(sorted(names)) string += '\n' self.assertString(string, reference_filename) @@ -83,15 +89,26 @@ def test_coord_comparison(self): cube4.add_dim_coord(lon, 1) cube4.add_dim_coord(lat, 0) + # Test when coords are the same object + lon = cube1.coord('longitude') + lat = cube1.coord('latitude') + cube5 = iris.cube.Cube(np.zeros((41, 41))) + cube5.add_dim_coord(lon, 0) + cube5.add_dim_coord(lat, 1) + coord_comparison = iris.analysis.coord_comparison self.assertComparisonDict(coord_comparison(cube1, cube1), ('analysis', 'coord_comparison', 'cube1_cube1.txt')) self.assertComparisonDict(coord_comparison(cube1, cube2), ('analysis', 'coord_comparison', 'cube1_cube2.txt')) self.assertComparisonDict(coord_comparison(cube1, cube3), ('analysis', 'coord_comparison', 'cube1_cube3.txt')) self.assertComparisonDict(coord_comparison(cube1, cube4), ('analysis', 'coord_comparison', 'cube1_cube4.txt')) + self.assertComparisonDict(coord_comparison(cube1, cube5), ('analysis', 'coord_comparison', 'cube1_cube5.txt')) self.assertComparisonDict(coord_comparison(cube2, cube3), ('analysis', 'coord_comparison', 'cube2_cube3.txt')) self.assertComparisonDict(coord_comparison(cube2, cube4), ('analysis', 'coord_comparison', 'cube2_cube4.txt')) + self.assertComparisonDict(coord_comparison(cube2, cube5), ('analysis', 'coord_comparison', 'cube2_cube5.txt')) self.assertComparisonDict(coord_comparison(cube3, cube4), ('analysis', 'coord_comparison', 'cube3_cube4.txt')) + self.assertComparisonDict(coord_comparison(cube3, cube5), ('analysis', 'coord_comparison', 'cube3_cube5.txt')) + self.assertComparisonDict(coord_comparison(cube4, cube5), ('analysis', 'coord_comparison', 'cube4_cube5.txt')) self.assertComparisonDict(coord_comparison(cube1, cube1, cube1), ('analysis', 'coord_comparison', 'cube1_cube1_cube1.txt')) self.assertComparisonDict(coord_comparison(cube1, cube2, cube1), ('analysis', 'coord_comparison', 'cube1_cube2_cube1.txt')) @@ -117,17 +134,30 @@ def test_weighted_mean_little(self): self.assertCML(cube, ('analysis', 'weighted_mean_source.cml')) a = cube.collapsed('lat', iris.analysis.MEAN, weights=weights) + # np.ma.average doesn't apply type promotion rules in some versions, + # and instead makes the result type float64. To ignore that case we + # fix up the dtype here if it is promotable from float32. We still want + # to catch cases where there is a loss of precision however. + if a.dtype > np.float32: + cast_data = a.data.astype(np.float32) + a.data = cast_data self.assertCMLApproxData(a, ('analysis', 'weighted_mean_lat.cml')) b = cube.collapsed(lon_coord, iris.analysis.MEAN, weights=weights) + if b.dtype > np.float32: + cast_data = b.data.astype(np.float32) + b.data = cast_data b.data = np.asarray(b.data) self.assertCMLApproxData(b, ('analysis', 'weighted_mean_lon.cml')) - self.assertEquals(b.coord("dummy").shape, (1,)) + self.assertEqual(b.coord('dummy').shape, (1, )) # test collapsing multiple coordinates (and the fact that one of the coordinates isn't the same coordinate instance as on the cube) c = cube.collapsed([lat_coord[:], lon_coord], iris.analysis.MEAN, weights=weights) + if c.dtype > np.float32: + cast_data = c.data.astype(np.float32) + c.data = cast_data self.assertCMLApproxData(c, ('analysis', 'weighted_mean_latlon.cml')) - self.assertEquals(c.coord("dummy").shape, (1,)) + self.assertEqual(c.coord('dummy').shape, (1, )) # Check new coord bounds - made from points self.assertArrayEqual(c.coord('lat').bounds, [[1, 3]]) @@ -141,7 +171,7 @@ def test_weighted_mean_little(self): # Check there was no residual change self.assertCML(cube, ('analysis', 'weighted_mean_source.cml')) - @iris.tests.skip_data + @tests.skip_data def test_weighted_mean(self): ### compare with pp_area_avg - which collapses both lat and lon # @@ -160,10 +190,10 @@ def test_weighted_mean(self): e.coord('longitude').bounds = None f, collapsed_area_weights = e.collapsed('latitude', iris.analysis.MEAN, weights=area_weights, returned=True) g = f.collapsed('longitude', iris.analysis.MEAN, weights=collapsed_area_weights) - # check it's a 1D, scalar cube (actually, it should really be 0D)! - self.assertEquals(g.shape, (1,)) + # check it's a 0d, scalar cube + self.assertEqual(g.shape, ()) # check the value - pp_area_avg's result of 287.927 differs by factor of 1.00002959 - np.testing.assert_approx_equal(g.data[0], 287.935, significant=5) + np.testing.assert_approx_equal(g.data, 287.935, significant=5) #check we get summed weights even if we don't give any h, summed_weights = e.collapsed('latitude', iris.analysis.MEAN, returned=True) @@ -180,7 +210,7 @@ def test_weighted_mean(self): # Test collpasing of non data coord self.assertRaises(iris.exceptions.CoordinateCollapseError, e.collapsed, 'pressure', iris.analysis.MEAN) -@iris.tests.skip_data +@tests.skip_data class TestAnalysisBasic(tests.IrisTest): def setUp(self): file = tests.get_data_path(('PP', 'aPProt1', 'rotatedMHtimecube.pp')) @@ -206,30 +236,30 @@ def _common(self, name, aggregate, original_name='original_common.cml', *args, * self.assertCML(self.cube, ('analysis', original_name)) def test_mean(self): - self._common('mean', iris.analysis.MEAN, decimal=1) + self._common('mean', iris.analysis.MEAN, rtol=1e-05) def test_std_dev(self): # as the numbers are so high, trim off some trailing digits & compare to 0dp - self._common('std_dev', iris.analysis.STD_DEV, decimal=1) + self._common('std_dev', iris.analysis.STD_DEV, rtol=1e-05) def test_hmean(self): # harmonic mean requires data > 0 self.cube.data *= self.cube.data - self._common('hmean', iris.analysis.HMEAN, 'original_hmean.cml', decimal=1) + self._common('hmean', iris.analysis.HMEAN, 'original_hmean.cml', rtol=1e-05) def test_gmean(self): - self._common('gmean', iris.analysis.GMEAN, decimal=1) + self._common('gmean', iris.analysis.GMEAN, rtol=1e-05) def test_variance(self): # as the numbers are so high, trim off some trailing digits & compare to 0dp - self._common('variance', iris.analysis.VARIANCE, decimal=1) + self._common('variance', iris.analysis.VARIANCE, rtol=1e-05) def test_median(self): self._common('median', iris.analysis.MEDIAN) def test_sum(self): # as the numbers are so high, trim off some trailing digits & compare to 0dp - self._common('sum', iris.analysis.SUM, decimal=1) + self._common('sum', iris.analysis.SUM, rtol=1e-05) def test_max(self): self._common('max', iris.analysis.MAX) @@ -243,27 +273,6 @@ def test_rms(self): def test_duplicate_coords(self): self.assertRaises(ValueError, tests.stock.track_1d, duplicate_x=True) - def test_xy_range(self): - result_non_circ = iris.analysis.cartography._xy_range(self.cube) - self.assertEqual(self.cube.coord('grid_longitude').circular, False) - np.testing.assert_array_almost_equal( - result_non_circ, ((313.02, 392.11), (-22.49, 24.92)), decimal=0) - - def test_xy_range_geog_cs(self): - cube = iris.tests.stock.global_pp() - self.assertTrue(cube.coord('longitude').circular) - result = iris.analysis.cartography._xy_range(cube) - np.testing.assert_array_almost_equal( - result, ((0, 360), (-90, 90)), decimal=0) - - def test_xy_range_geog_cs_regional(self): - cube = iris.tests.stock.global_pp() - cube = cube[10:20, 20:30] - self.assertFalse(cube.coord('longitude').circular) - result = iris.analysis.cartography._xy_range(cube) - np.testing.assert_array_almost_equal( - result, ((75, 108.75), (42.5, 65)), decimal=0) - class TestMissingData(tests.IrisTest): def setUp(self): @@ -301,6 +310,54 @@ def test_sum(self): np.testing.assert_array_equal(cube.data, np.array([6, 18, 17])) +class TestAuxCoordCollapse(tests.IrisTest): + + def setUp(self): + self.cube_with_aux_coord = tests.stock.simple_4d_with_hybrid_height() + + # Guess bounds to get the weights + self.cube_with_aux_coord.coord('grid_latitude').guess_bounds() + self.cube_with_aux_coord.coord('grid_longitude').guess_bounds() + + def test_max(self): + cube = self.cube_with_aux_coord.collapsed('grid_latitude', + iris.analysis.MAX) + np.testing.assert_array_equal(cube.coord('surface_altitude').points, + np.array([112, 113, 114, + 115, 116, 117])) + + np.testing.assert_array_equal(cube.coord('surface_altitude').bounds, + np.array([[100, 124], + [101, 125], + [102, 126], + [103, 127], + [104, 128], + [105, 129]])) + + # Check collapsing over the whole coord still works + cube = self.cube_with_aux_coord.collapsed('altitude', + iris.analysis.MAX) + + np.testing.assert_array_equal(cube.coord('surface_altitude').points, + np.array([114])) + + np.testing.assert_array_equal(cube.coord('surface_altitude').bounds, + np.array([[100, 129]])) + + cube = self.cube_with_aux_coord.collapsed('grid_longitude', + iris.analysis.MAX) + + np.testing.assert_array_equal(cube.coord('surface_altitude').points, + np.array([102, 108, 114, 120, 126])) + + np.testing.assert_array_equal(cube.coord('surface_altitude').bounds, + np.array([[100, 105], + [106, 111], + [112, 117], + [118, 123], + [124, 129]])) + + class TestAggregator_mdtol_keyword(tests.IrisTest): def setUp(self): data = ma.array([[1, 2], [4, 5]], dtype=np.float32, @@ -338,114 +395,169 @@ def test_multi_coord_no_mdtol(self): collapsed = self.cube.collapsed( [self.cube.coord('lat'), self.cube.coord('lon')], iris.analysis.MEAN) - t = np.array([2.5]) + t = np.array(2.5) self.assertArrayEqual(collapsed.data, t) def test_multi_coord_mdtol(self): collapsed = self.cube.collapsed( [self.cube.coord('lat'), self.cube.coord('lon')], iris.analysis.MEAN, mdtol=0.4) - t = ma.array([2.5], mask=[True]) + t = ma.array(2.5, mask=True) self.assertMaskedArrayEqual(collapsed.data, t) class TestAggregators(tests.IrisTest): - def test_percentile_1d(self): + + def _check_collapsed_percentile(self, cube, percents, collapse_coord, + expected_result, CML_filename=None, + **kwargs): + expected_result = np.array(expected_result, dtype=np.float32) + result = cube.collapsed(collapse_coord, iris.analysis.PERCENTILE, + percent=percents, **kwargs) + np.testing.assert_array_almost_equal(result.data, expected_result) + if CML_filename is not None: + self.assertCML(result, ('analysis', CML_filename), checksum=False) + + def _check_percentile(self, data, axis, percents, expected_result, + **kwargs): + result = iris.analysis._percentile(data, axis, percents, **kwargs) + np.testing.assert_array_almost_equal(result, expected_result) + + def test_percentile_1d_25_percent(self): cube = tests.stock.simple_1d() + self._check_collapsed_percentile( + cube, 25, 'foo', 2.5, CML_filename='first_quartile_foo_1d.cml') - first_quartile = cube.collapsed('foo', iris.analysis.PERCENTILE, - percent=25) - np.testing.assert_array_almost_equal(first_quartile.data, - np.array([2.5], dtype=np.float32)) - self.assertCML(first_quartile, ('analysis', - 'first_quartile_foo_1d.cml'), - checksum=False) + def test_percentile_1d_75_percent(self): + cube = tests.stock.simple_1d() + self._check_collapsed_percentile( + cube, 75, 'foo', 7.5, CML_filename='third_quartile_foo_1d.cml') - third_quartile = cube.collapsed('foo', iris.analysis.PERCENTILE, - percent=75) - np.testing.assert_array_almost_equal(third_quartile.data, - np.array([7.5], - dtype=np.float32)) - self.assertCML(third_quartile, - ('analysis', 'third_quartile_foo_1d.cml'), - checksum=False) + def test_fast_percentile_1d_25_percent(self): + cube = tests.stock.simple_1d() + self._check_collapsed_percentile( + cube, 25, 'foo', 2.5, fast_percentile_method=True, + CML_filename='first_quartile_foo_1d_fast_percentile.cml') + + def test_fast_percentile_1d_75_percent(self): + cube = tests.stock.simple_1d() + self._check_collapsed_percentile( + cube, 75, 'foo', 7.5, fast_percentile_method=True, + CML_filename='third_quartile_foo_1d_fast_percentile.cml') - def test_percentile_2d(self): + def test_percentile_2d_single_coord(self): cube = tests.stock.simple_2d() + self._check_collapsed_percentile( + cube, 25, 'foo', [0.75, 4.75, 8.75], + CML_filename='first_quartile_foo_2d.cml') - first_quartile = cube.collapsed('foo', iris.analysis.PERCENTILE, - percent=25) - np.testing.assert_array_almost_equal(first_quartile.data, - np.array([0.75, 4.75, 8.75], - dtype=np.float32)) - self.assertCML(first_quartile, ('analysis', - 'first_quartile_foo_2d.cml'), - checksum=False) + def test_percentile_2d_two_coords(self): + cube = tests.stock.simple_2d() + self._check_collapsed_percentile( + cube, 25, ['foo', 'bar'], [2.75], + CML_filename='first_quartile_foo_bar_2d.cml') - first_quartile = cube.collapsed(('foo', 'bar'), - iris.analysis.PERCENTILE, percent=25) - np.testing.assert_array_almost_equal(first_quartile.data, - np.array([2.75], - dtype=np.float32)) - self.assertCML(first_quartile, ('analysis', - 'first_quartile_foo_bar_2d.cml'), - checksum=False) + def test_fast_percentile_2d_single_coord(self): + cube = tests.stock.simple_2d() + self._check_collapsed_percentile( + cube, 25, 'foo', [0.75, 4.75, 8.75], fast_percentile_method=True, + CML_filename='first_quartile_foo_2d_fast_percentile.cml') + + def test_fast_percentile_2d_two_coords(self): + cube = tests.stock.simple_2d() + self._check_collapsed_percentile( + cube, 25, ['foo', 'bar'], [2.75], fast_percentile_method=True, + CML_filename='first_quartile_foo_bar_2d_fast_percentile.cml') def test_percentile_3d(self): array_3d = np.arange(24, dtype=np.int32).reshape((2, 3, 4)) + expected_result = np.array([[6., 7., 8., 9.], + [10., 11., 12., 13.], + [14., 15., 16., 17.]], + dtype=np.float32) + self._check_percentile(array_3d, 0, 50, expected_result) - last_quartile = iris.analysis._percentile(array_3d, 0, 50) - np.testing.assert_array_almost_equal(last_quartile, - np.array([[6., 7., 8., 9.], - [10., 11., 12., 13.], - [14., 15., 16., 17.]], - dtype=np.float32)) + def test_fast_percentile_3d(self): + array_3d = np.arange(24, dtype=np.int32).reshape((2, 3, 4)) + expected_result = np.array([[6., 7., 8., 9.], + [10., 11., 12., 13.], + [14., 15., 16., 17.]], + dtype=np.float32) + self._check_percentile(array_3d, 0, 50, expected_result, + fast_percentile_method=True) def test_percentile_3d_axis_one(self): array_3d = np.arange(24, dtype=np.int32).reshape((2, 3, 4)) + expected_result = np.array([[4., 5., 6., 7.], + [16., 17., 18., 19.]], + dtype=np.float32) - last_quartile = iris.analysis._percentile(array_3d, 1, 50) - np.testing.assert_array_almost_equal(last_quartile, - np.array([[4., 5., 6., 7.], - [16., 17., 18., 19.]], - dtype=np.float32)) + self._check_percentile(array_3d, 1, 50, expected_result) + + def test_fast_percentile_3d_axis_one(self): + array_3d = np.arange(24, dtype=np.int32).reshape((2, 3, 4)) + expected_result = np.array([[4., 5., 6., 7.], + [16., 17., 18., 19.]], + dtype=np.float32) + + self._check_percentile(array_3d, 1, 50, expected_result, + fast_percentile_method=True) def test_percentile_3d_axis_two(self): array_3d = np.arange(24, dtype=np.int32).reshape((2, 3, 4)) + expected_result = np.array([[1.5, 5.5, 9.5], + [13.5, 17.5, 21.5]], + dtype=np.float32) + + self._check_percentile(array_3d, 2, 50, expected_result) + + def test_fast_percentile_3d_axis_two(self): + array_3d = np.arange(24, dtype=np.int32).reshape((2, 3, 4)) + expected_result = np.array([[1.5, 5.5, 9.5], + [13.5, 17.5, 21.5]], + dtype=np.float32) - last_quartile = iris.analysis._percentile(array_3d, 2, 50) - np.testing.assert_array_almost_equal(last_quartile, - np.array([[1.5, 5.5, 9.5], - [13.5, 17.5, 21.5]], - dtype=np.float32)) + self._check_percentile(array_3d, 2, 50, expected_result, + fast_percentile_method=True) def test_percentile_3d_masked(self): cube = tests.stock.simple_3d_mask() + expected_result = [[12., 13., 14., 15.], + [16., 17., 18., 19.], + [20., 18., 19., 20.]] - last_quartile = cube.collapsed('wibble', - iris.analysis.PERCENTILE, percent=75) - np.testing.assert_array_almost_equal(last_quartile.data, - np.array([[12., 13., 14., 15.], - [16., 17., 18., 19.], - [20., 18., 19., 20.]], - dtype=np.float32)) - self.assertCML(last_quartile, ('analysis', - 'last_quartile_foo_3d_masked.cml'), - checksum=False) + self._check_collapsed_percentile( + cube, 75, 'wibble', expected_result, + CML_filename='last_quartile_foo_3d_masked.cml') + + def test_fast_percentile_3d_masked(self): + cube = tests.stock.simple_3d_mask() + msg = 'Cannot use fast np.percentile method with masked array.' + + with self.assertRaisesRegexp(TypeError, msg): + cube.collapsed('wibble', + iris.analysis.PERCENTILE, percent=75, + fast_percentile_method=True) def test_percentile_3d_notmasked(self): cube = tests.stock.simple_3d() + expected_result = [[9., 10., 11., 12.], + [13., 14., 15., 16.], + [17., 18., 19., 20.]] - last_quartile = cube.collapsed('wibble', - iris.analysis.PERCENTILE, percent=75) - np.testing.assert_array_almost_equal(last_quartile.data, - np.array([[9., 10., 11., 12.], - [13., 14., 15., 16.], - [17., 18., 19., 20.]], - dtype=np.float32)) - self.assertCML(last_quartile, ('analysis', - 'last_quartile_foo_3d_notmasked.cml'), - checksum=False) + self._check_collapsed_percentile( + cube, 75, 'wibble', expected_result, + CML_filename='last_quartile_foo_3d_notmasked.cml') + + def test_fast_percentile_3d_notmasked(self): + cube = tests.stock.simple_3d() + expected_result = [[9., 10., 11., 12.], + [13., 14., 15., 16.], + [17., 18., 19., 20.]] + + self._check_collapsed_percentile( + cube, 75, 'wibble', expected_result, fast_percentile_method=True, + CML_filename='last_quartile_foo_3d_notmasked_fast_percentile.cml') def test_proportion(self): cube = tests.stock.simple_1d() @@ -548,19 +660,24 @@ def test_weighted_rms(self): checksum=False) -@iris.tests.skip_data +@tests.skip_data class TestRotatedPole(tests.IrisTest): - def _check_both_conversions(self, cube): + def _check_both_conversions(self, cube, index): rlons, rlats = iris.analysis.cartography.get_xy_grids(cube) rcs = cube.coord_system('RotatedGeogCS') x, y = iris.analysis.cartography.unrotate_pole( rlons, rlats, rcs.grid_north_pole_longitude, rcs.grid_north_pole_latitude) - plt.scatter(x, y) - self.check_graphic() - - plt.scatter(rlons, rlats) - self.check_graphic() + self.assertDataAlmostEqual(x, ('analysis', + 'rotated_pole.{}.x.json'.format(index))) + self.assertDataAlmostEqual(y, ('analysis', + 'rotated_pole.{}.y.json'.format(index))) + self.assertDataAlmostEqual(rlons, + ('analysis', + 'rotated_pole.{}.rlon.json'.format(index))) + self.assertDataAlmostEqual(rlats, + ('analysis', + 'rotated_pole.{}.rlat.json'.format(index))) def test_all(self): path = tests.get_data_path(('PP', 'ukVorog', 'ukv_orog_refonly.pp')) @@ -568,15 +685,15 @@ def test_all(self): # Check overall behaviour. cube = master_cube[::10, ::10] - self._check_both_conversions(cube) + self._check_both_conversions(cube, 0) # Check numerical stability. cube = master_cube[210:238, 424:450] - self._check_both_conversions(cube) + self._check_both_conversions(cube, 1) def test_unrotate_nd(self): - rlons = np.array([[350., 352.],[350., 352.]]) - rlats = np.array([[-5., -0.],[-4., -1.]]) + rlons = np.array([[350., 352.], [350., 352.]]) + rlats = np.array([[-5., -0.], [-4., -1.]]) resx, resy = iris.analysis.cartography.unrotate_pole(rlons, rlats, 178.0, 38.0) @@ -607,8 +724,8 @@ def test_unrotate_1d(self): self.assertArrayAlmostEqual(resy, soly) def test_rotate_nd(self): - rlons = np.array([[350., 351.],[352., 353.]]) - rlats = np.array([[10., 15.],[20., 25.]]) + rlons = np.array([[350., 351.], [352., 353.]]) + rlats = np.array([[10., 15.], [20., 25.]]) resx, resy = iris.analysis.cartography.rotate_pole(rlons, rlats, 20., 80.) @@ -639,7 +756,7 @@ def test_rotate_1d(self): self.assertArrayAlmostEqual(resy, soly) -@iris.tests.skip_data +@tests.skip_data class TestAreaWeights(tests.IrisTest): def test_area_weights(self): small_cube = iris.tests.stock.simple_pp() @@ -656,11 +773,11 @@ def test_area_weights(self): small_cube.coord('longitude').guess_bounds() area_weights = iris.analysis.cartography.area_weights(small_cube) expected_results = np.array( - [[3.11955916e+12, 3.11956058e+12, 3.11955916e+12, 3.11956058e+12], - [5.21950793e+12, 5.21951031e+12, 5.21950793e+12, 5.21951031e+12], - [6.68991432e+12, 6.68991737e+12, 6.68991432e+12, 6.68991737e+12], - [7.35341320e+12, 7.35341655e+12, 7.35341320e+12, 7.35341655e+12], - [7.12998265e+12, 7.12998589e+12, 7.12998265e+12, 7.12998589e+12]], + [[3.11955866e+12, 3.11956008e+12, 3.11955866e+12, 3.11956008e+12], + [5.21951065e+12, 5.21951303e+12, 5.21951065e+12, 5.21951303e+12], + [6.68991281e+12, 6.68991585e+12, 6.68991281e+12, 6.68991585e+12], + [7.35341305e+12, 7.35341640e+12, 7.35341305e+12, 7.35341640e+12], + [7.12998335e+12, 7.12998660e+12, 7.12998335e+12, 7.12998660e+12]], dtype=np.float64) self.assertArrayAllClose(area_weights, expected_results, rtol=1e-8) @@ -670,46 +787,7 @@ def test_area_weights(self): self.assertCML(small_cube, ('analysis', 'areaweights_original.cml'), checksum=False) - def test_quadrant_area(self): - - degrees = iris.unit.Unit("degrees") - radians = iris.unit.Unit("radians") - - def lon2radlon(lons): - return [degrees.convert(lon, radians) for lon in lons] - - def lat2radcolat(lats): - return [degrees.convert(lat + 90, radians) for lat in lats] - - lats = np.array([lat2radcolat([-80, -70])]) - lons = np.array([lon2radlon([0, 10])]) - area = iris.analysis.cartography._quadrant_area(lats, lons, iris.analysis.cartography.DEFAULT_SPHERICAL_EARTH_RADIUS) - self.assertAlmostEquals(area, [[319251845980.763671875]]) - - lats = np.array([lat2radcolat([0, 10])]) - lons = np.array([lon2radlon([0, 10])]) - area = iris.analysis.cartography._quadrant_area(lats, lons, iris.analysis.cartography.DEFAULT_SPHERICAL_EARTH_RADIUS) - self.assertAlmostEquals(area, [[1228800593851.443115234375]]) - - lats = np.array([lat2radcolat([10, 0])]) - lons = np.array([lon2radlon([0, 10])]) - area = iris.analysis.cartography._quadrant_area(lats, lons, iris.analysis.cartography.DEFAULT_SPHERICAL_EARTH_RADIUS) - self.assertAlmostEquals(area, [[1228800593851.443115234375]]) - - lats = np.array([lat2radcolat([70, 80])]) - lons = np.array([lon2radlon([0, 10])]) - area = iris.analysis.cartography._quadrant_area(lats, lons, iris.analysis.cartography.DEFAULT_SPHERICAL_EARTH_RADIUS) - self.assertAlmostEquals(area, [[319251845980.7646484375]]) - - lats = np.array([lat2radcolat([-80, -70]), lat2radcolat([0, 10]), lat2radcolat([70, 80])]) - lons = np.array([lon2radlon([0, 10])]) - area = iris.analysis.cartography._quadrant_area(lats, lons, iris.analysis.cartography.DEFAULT_SPHERICAL_EARTH_RADIUS) - - self.assertAlmostEquals(area[0], [319251845980.763671875]) - self.assertAlmostEquals(area[1], [1228800593851.443115234375]) - self.assertAlmostEquals(area[2], [319251845980.7646484375]) - - +@tests.skip_data class TestAreaWeightGeneration(tests.IrisTest): def setUp(self): self.cube = iris.tests.stock.realistic_4d() @@ -796,7 +874,7 @@ def test_area_weights_no_lat_bounds(self): iris.analysis.cartography.area_weights(self.cube) -@iris.tests.skip_data +@tests.skip_data class TestLatitudeWeightGeneration(tests.IrisTest): def setUp(self): @@ -821,7 +899,7 @@ def test_cosine_latitude_weights_range(self): # latitude range lat_coord = iris.coords.DimCoord(np.linspace(-90, 90, 73), standard_name='latitude', - units=iris.unit.Unit('degrees_north')) + units=cf_units.Unit('degrees_north')) cube = iris.cube.Cube(np.ones([73], dtype=np.float64), long_name='test_cube', units='1') cube.add_dim_coord(lat_coord, 0) @@ -1047,124 +1125,5 @@ def test_mean_with_weights(self): self.assertArrayAlmostEqual(expected_result, res_cube.data) -class TestGeometry(tests.IrisTest): - - @iris.tests.skip_data - def test_distinct_xy(self): - cube = iris.tests.stock.simple_pp() - cube = cube[:4, :4] - lon = cube.coord('longitude') - lat = cube.coord('latitude') - lon.guess_bounds() - lat.guess_bounds() - from iris.fileformats.rules import regular_step - quarter = abs(regular_step(lon) * regular_step(lat) * 0.25) - half = abs(regular_step(lon) * regular_step(lat) * 0.5) - minx = 3.7499990463256836 - maxx = 7.499998092651367 - miny = 84.99998474121094 - maxy = 89.99998474121094 - geometry = shapely.geometry.box(minx, miny, maxx, maxy) - weights = iris.analysis.geometry.geometry_area_weights(cube, geometry) - target = np.array([ - [0, quarter, quarter, 0], - [0, half, half, 0], - [0, quarter, quarter, 0], - [0, 0, 0, 0]]) - self.assertTrue(np.allclose(weights, target)) - - def test_shared_xy(self): - cube = tests.stock.track_1d() - geometry = shapely.geometry.box(1, 4, 3.5, 7) - weights = iris.analysis.geometry.geometry_area_weights(cube, geometry) - target = np.array([0, 0, 2, 0.5, 0, 0, 0, 0, 0, 0, 0]) - self.assertTrue(np.allclose(weights, target)) - - -class TestProject(tests.GraphicsTest): - def setUp(self): - cube = iris.tests.stock.realistic_4d_no_derived() - # Remove some slices to speed testing. - self.cube = cube[0:2, 0:3] - self.target_proj = ccrs.Robinson() - - def test_bad_resolution(self): - with self.assertRaises(ValueError): - iris.analysis.cartography.project(self.cube, - self.target_proj, - nx=-200, ny=200) - with self.assertRaises(ValueError): - iris.analysis.cartography.project(self.cube, - self.target_proj, - nx=200, ny='abc') - - def test_missing_latlon(self): - cube = self.cube.copy() - cube.remove_coord('grid_latitude') - with self.assertRaises(ValueError): - iris.analysis.cartography.project(cube, self.target_proj) - cube = self.cube.copy() - cube.remove_coord('grid_longitude') - with self.assertRaises(ValueError): - iris.analysis.cartography.project(cube, self.target_proj) - self.cube.remove_coord('grid_longitude') - self.cube.remove_coord('grid_latitude') - with self.assertRaises(ValueError): - iris.analysis.cartography.project(self.cube, self.target_proj) - - def test_default_resolution(self): - new_cube, extent = iris.analysis.cartography.project(self.cube, - self.target_proj) - self.assertEqual(new_cube.shape, self.cube.shape) - - @iris.tests.skip_data - def test_cartopy_projection(self): - cube = iris.load_cube(tests.get_data_path(('PP', 'aPPglob1', - 'global.pp'))) - projections = {} - projections['RotatedPole'] = ccrs.RotatedPole(pole_longitude=177.5, - pole_latitude=37.5) - projections['Robinson'] = ccrs.Robinson() - projections['PlateCarree'] = ccrs.PlateCarree() - projections['NorthPolarStereo'] = ccrs.NorthPolarStereo() - projections['Orthographic'] = ccrs.Orthographic(central_longitude=-90, - central_latitude=45) - projections['InterruptedGoodeHomolosine'] = ccrs.InterruptedGoodeHomolosine() - projections['LambertCylindrical'] = ccrs.LambertCylindrical() - - # Set up figure - fig = plt.figure(figsize=(10, 10)) - gs = matplotlib.gridspec.GridSpec(nrows=3, ncols=3, hspace=1.5, wspace=0.5) - for subplot_spec, (name, target_proj) in itertools.izip(gs, projections.iteritems()): - # Set up axes and title - ax = plt.subplot(subplot_spec, frameon=False, projection=target_proj) - ax.set_title(name) - # Transform cube to target projection - new_cube, extent = iris.analysis.cartography.project(cube, target_proj, - nx=150, ny=150) - # Plot - plt.pcolor(new_cube.coord('projection_x_coordinate').points, - new_cube.coord('projection_y_coordinate').points, - new_cube.data) - # Add coastlines - ax.coastlines() - - # Tighten up layout - gs.tight_layout(plt.gcf()) - - # Verify resulting plot - self.check_graphic(tol=1.0) - - @iris.tests.skip_data - def test_no_coord_system(self): - cube = iris.load_cube(tests.get_data_path(('PP', 'aPPglob1', 'global.pp'))) - cube.coord('longitude').coord_system = None - cube.coord('latitude').coord_system = None - new_cube, extent = iris.analysis.cartography.project(cube, - self.target_proj) - self.assertCML(new_cube, - ('analysis', 'project', 'default_source_cs.cml')) - - if __name__ == "__main__": tests.main() diff --git a/lib/iris/tests/test_analysis_calculus.py b/lib/iris/tests/test_analysis_calculus.py index c6c72d5a51..cac7855e8d 100644 --- a/lib/iris/tests/test_analysis_calculus.py +++ b/lib/iris/tests/test_analysis_calculus.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -15,6 +15,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests @@ -31,10 +33,10 @@ import iris.tests.stock from iris.coords import DimCoord -from iris.tests.test_interpolation import normalise_order class TestCubeDelta(tests.IrisTest): + @tests.skip_data def test_invalid(self): cube = iris.tests.stock.realistic_4d() with self.assertRaises(iris.exceptions.CoordinateMultiDimError): @@ -310,9 +312,14 @@ def build_cube(data, spherical=False): dimz = data.ndim - 3 if data.ndim > 2 else None if spherical: - hcs = iris.coord_systems.GeogCS(6321) - cube.add_dim_coord(DimCoord(np.arange(-180, 180, 360./nx, dtype=np.float32), 'longitude', units='degrees', coord_system=hcs, circular=True), dimx) - cube.add_dim_coord(DimCoord(np.arange(-90, 90, 180./ny, dtype=np.float32), 'latitude', units='degrees',coord_system=hcs), dimy) + if spherical == 'rotated': + hcs = iris.coord_systems.RotatedGeogCS(10, 20) + lon_name, lat_name = 'grid_longitude', 'grid_latitude' + else: + hcs = iris.coord_systems.GeogCS(6321) + lon_name, lat_name = 'longitude', 'latitude' + cube.add_dim_coord(DimCoord(np.arange(-180, 180, 360./nx, dtype=np.float32), lon_name, units='degrees', coord_system=hcs, circular=True), dimx) + cube.add_dim_coord(DimCoord(np.arange(-90, 90, 180./ny, dtype=np.float32), lat_name, units='degrees', coord_system=hcs), dimy) else: cube.add_dim_coord(DimCoord(np.arange(nx, dtype=np.float32) * 2.21 + 2, 'projection_x_coordinate', units='meters'), dimx) @@ -389,7 +396,7 @@ def test_contrived_differential1(self): y = df_dlon.coord('latitude') sin_x_pts = np.sin(np.radians(x.points)).reshape(1, x.shape[0]) - y_ones = np.ones((y.shape[0] , 1)) + y_ones = np.ones((y.shape[0], 1)) data = - sin_x_pts * y_ones result = df_dlon.copy(data=data) @@ -432,7 +439,12 @@ def test_contrived_non_spherical_curl1(self): # Curl returns None when there is no components of Curl self.assertEqual(r[0], None) self.assertEqual(r[1], None) - self.assertCML(r[2], ('analysis', 'calculus', 'grad_contrived_non_spherical1.cml')) + cube = r[2] + self.assertCML( + cube, + ('analysis', 'calculus', 'grad_contrived_non_spherical1.cml'), + checksum=False) + self.assertTrue(np.all(np.abs(cube.data - (-1.0)) < 1.0e-7)) def test_contrived_non_spherical_curl2(self): # testing : @@ -458,8 +470,8 @@ def test_contrived_non_spherical_curl2(self): # result = r[0].copy(data=True) # x_pts, x_ones, y_pts, y_ones, z_pts, z_ones = self.get_coord_pts(result) # result.data = y_pts * 2. * x_ones * z_ones -# print repr(r[0].data[0:1, 0:5, 0:25:5]) -# print repr(result.data[0:1, 0:5, 0:25:5]) +# print(repr(r[0].data[0:1, 0:5, 0:25:5])) +# print(repr(result.data[0:1, 0:5, 0:25:5])) # np.testing.assert_array_almost_equal(result.data, r[0].data, decimal=2) # # result = r[1].copy(data=True) @@ -471,7 +483,6 @@ def test_contrived_non_spherical_curl2(self): result.data = result.data * 0 + 1 np.testing.assert_array_almost_equal(result.data, r[2].data, decimal=4) - normalise_order(r[1]) self.assertCML(r, ('analysis', 'calculus', 'curl_contrived_cartesian2.cml'), checksum=False) def test_contrived_spherical_curl1(self): @@ -503,7 +514,7 @@ def test_contrived_spherical_curl1(self): np.testing.assert_array_almost_equal(result.data[5:-5], r.data[5:-5]/1000.0, decimal=1) self.assertCML(r, ('analysis', 'calculus', 'grad_contrived1.cml'), checksum=False) - def test_contrived_sphrical_curl2(self): + def test_contrived_spherical_curl2(self): # testing: # F(lon, lat, r) = (r sin(lat) cos(lon), -r sin(lon), 0) # curl( F(x, y, z) ) = (0, 0, -2 cos(lon) cos(lat) ) @@ -517,7 +528,7 @@ def test_contrived_sphrical_curl2(self): sin_x_pts = np.sin(np.radians(x.points)).reshape(1, x.shape[0]) cos_y_pts = np.cos(np.radians(y.points)).reshape(y.shape[0], 1) sin_y_pts = np.sin(np.radians(y.points)).reshape(y.shape[0], 1) - y_ones = np.ones((cube.shape[0] , 1)) + y_ones = np.ones((cube.shape[0], 1)) u = cube.copy(data=sin_y_pts * cos_x_pts * radius) v = cube.copy(data=-sin_x_pts * y_ones * radius) @@ -541,7 +552,8 @@ def test_contrived_sphrical_curl2(self): cos_x_pts = np.cos(np.radians(x.points)).reshape(1, x.shape[0]) cos_y_pts = np.cos(np.radians(y.points)).reshape(y.shape[0], 1) - result = r.copy(data=2*cos_x_pts*cos_y_pts) + # Expected r-component value: -2 cos(lon) cos(lat) + result = r.copy(data=-2*cos_x_pts*cos_y_pts) # Note: This numerical comparison was created when the radius was 1000 times smaller np.testing.assert_array_almost_equal(result.data[30:-30, :], r.data[30:-30, :]/1000.0, decimal=1) @@ -554,7 +566,7 @@ def test_non_conformed(self): v = u.copy() y = v.coord('latitude') - y.points += 5 + y.points = y.points + 5 self.assertRaises(ValueError, iris.analysis.calculus.curl, u, v) def test_standard_name(self): @@ -605,6 +617,15 @@ def test_standard_name(self): v.rename('northward_foobar2') self.assertRaises(ValueError, iris.analysis.calculus.spatial_vectors_with_phenom_name, u, v) + def test_rotated_pole(self): + u = build_cube(np.empty((30, 20)), spherical='rotated') + v = u.copy() + u.rename('u_wind') + v.rename('v_wind') + + x, y, z = iris.analysis.calculus.curl(u, v) + self.assertEqual(z.coord_system(), u.coord_system()) + if __name__ == "__main__": unittest.main() diff --git a/lib/iris/tests/test_basic_maths.py b/lib/iris/tests/test_basic_maths.py index 5dcb42a821..ca15dea4b1 100644 --- a/lib/iris/tests/test_basic_maths.py +++ b/lib/iris/tests/test_basic_maths.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -15,12 +15,16 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests import operator +import math +import cf_units import numpy as np import numpy.ma as ma @@ -31,7 +35,7 @@ import iris.tests.stock -@iris.tests.skip_data +@tests.skip_data class TestBasicMaths(tests.IrisTest): def setUp(self): self.cube = iris.tests.stock.global_pp() @@ -67,13 +71,6 @@ def test_minus(self): # Check that the subtraction has had no effect on the original self.assertCML(e, ('analysis', 'maths_original.cml')) - def test_minus_in_need_of_transpose(self): - a = self.cube - e = self.cube.copy() - e.transpose([1, 0]) - self.assertRaises(ValueError, iris.analysis.maths.subtract, a, e) - - def test_minus_with_data_describing_coordinate(self): a = self.cube e = self.cube.copy() @@ -127,8 +124,10 @@ def test_minus_coord(self): xdim = a.ndim-1 ydim = a.ndim-2 - c_x = iris.coords.DimCoord(points=range(a.shape[xdim]), long_name='x_coord', units=self.cube.units) - c_y = iris.coords.AuxCoord(points=range(a.shape[ydim]), long_name='y_coord', units=self.cube.units) + c_x = iris.coords.DimCoord(points=np.arange(a.shape[xdim]), + long_name='x_coord', units=self.cube.units) + c_y = iris.coords.AuxCoord(points=np.arange(a.shape[ydim]), + long_name='y_coord', units=self.cube.units) self.assertCML(a, ('analysis', 'maths_original.cml')) @@ -157,8 +156,10 @@ def test_addition_coord(self): xdim = a.ndim-1 ydim = a.ndim-2 - c_x = iris.coords.DimCoord(points=range(a.shape[xdim]), long_name='x_coord', units=self.cube.units) - c_y = iris.coords.AuxCoord(points=range(a.shape[ydim]), long_name='y_coord', units=self.cube.units) + c_x = iris.coords.DimCoord(points=np.arange(a.shape[xdim]), + long_name='x_coord', units=self.cube.units) + c_y = iris.coords.AuxCoord(points=np.arange(a.shape[ydim]), + long_name='y_coord', units=self.cube.units) self.assertCML(a, ('analysis', 'maths_original.cml')) @@ -192,8 +193,12 @@ def test_addition_fail(self): xdim = a.ndim-1 ydim = a.ndim-2 - c_axis_length_fail = iris.coords.DimCoord(points=range(a.shape[ydim]), long_name='x_coord', units=self.cube.units) - c_unit_fail = iris.coords.AuxCoord(points=range(a.shape[xdim]), long_name='x_coord', units='volts') + c_axis_length_fail = iris.coords.DimCoord( + points=np.arange(a.shape[ydim]), + long_name='x_coord', + units=self.cube.units) + c_unit_fail = iris.coords.AuxCoord(points=np.arange(a.shape[xdim]), + long_name='x_coord', units='volts') self.assertRaises(ValueError, iris.analysis.maths.add, a, c_axis_length_fail) self.assertRaises(iris.exceptions.NotYetImplementedError, iris.analysis.maths.add, a, c_unit_fail) @@ -221,12 +226,137 @@ def test_addition_different_attributes(self): self.assertIsNone(c.standard_name) self.assertEqual(c.attributes, {}) + def test_apply_ufunc(self): + a = self.cube + + b = iris.analysis.maths.apply_ufunc(np.square, a, + new_name='squared temperature', new_unit=a.units**2, + in_place=False) + self.assertCMLApproxData(a, ('analysis', 'apply_ufunc_original.cml')) + self.assertCMLApproxData(b, ('analysis', 'apply_ufunc.cml')) + + b = iris.analysis.maths.apply_ufunc(np.square, a, + new_name='squared temperature', new_unit=a.units**2, + in_place=True) + self.assertCMLApproxData(b, ('analysis', 'apply_ufunc.cml')) + self.assertCMLApproxData(a, ('analysis', 'apply_ufunc.cml')) + + def vec_mag(u, v): + return math.sqrt(u**2 + v**2) + + c = a.copy() + 2 + + vec_mag_ufunc = np.frompyfunc(vec_mag, 2, 1) + b = iris.analysis.maths.apply_ufunc(vec_mag_ufunc, a, c) + self.assertCMLApproxData(b, ('analysis', 'apply_ufunc_frompyfunc.cml')) + + def test_apply_ufunc_fail(self): + a = self.cube + + # should fail because 'blah' is a string, not a np.ufunc + self.assertRaises(TypeError, iris.analysis.maths.apply_ufunc, 'blah', a) + + # should fail because math.sqrt is not a np.ufunc + self.assertRaises(TypeError, iris.analysis.maths.apply_ufunc, math.sqrt, a) + + # should fail because np.frexp gives 2 arrays as output + self.assertRaises(ValueError, iris.analysis.maths.apply_ufunc, np.frexp, a) + + def test_ifunc(self): + a = self.cube + + my_ifunc = iris.analysis.maths.IFunc(np.square, + lambda a: a.units**2 + ) + b = my_ifunc(a, new_name='squared temperature', in_place=False) + + self.assertCMLApproxData(a, ('analysis', 'apply_ifunc_original.cml')) + self.assertCMLApproxData(b, ('analysis', 'apply_ifunc.cml')) + + b = my_ifunc(a, new_name='squared temperature', in_place=True) + + self.assertCMLApproxData(b, ('analysis', 'apply_ifunc.cml')) + self.assertCMLApproxData(a, ('analysis', 'apply_ifunc.cml')) + + def vec_mag(u, v): + return math.sqrt(u**2 + v**2) + + c = a.copy() + 2 + + vec_mag_ufunc = np.frompyfunc(vec_mag, 2, 1) + my_ifunc = iris.analysis.maths.IFunc(vec_mag_ufunc, + lambda a, b: (a + b).units) + + b = my_ifunc(a, c) + self.assertCMLApproxData(b, ('analysis', 'apply_ifunc_frompyfunc.cml')) + + def test_ifunc_init_fail(self): + + # should fail because 'blah' is a string not a python function + self.assertRaises(TypeError, iris.analysis.maths.IFunc, 'blah', + lambda cube: cf_units.Unit('1')) + + # should fail because math.sqrt is built-in function, which can not be + # used in inspect.getargspec + self.assertRaises(TypeError, iris.analysis.maths.IFunc, math.sqrt, + lambda cube: cf_units.Unit('1')) + + # should fail because np.frexp gives 2 arrays as output + self.assertRaises(ValueError, iris.analysis.maths.IFunc, np.frexp, + lambda cube: cf_units.Unit('1')) + + # should fail because data function has 3 arguments + self.assertRaises(ValueError, iris.analysis.maths.IFunc, + lambda a, b, c: a + b + c, + lambda cube: cf_units.Unit('1') + ) + + def test_ifunc_call_fail(self): + a = self.cube + + my_ifunc = iris.analysis.maths.IFunc(np.square, + lambda a: a.units**2 + ) + + # should fail because giving 2 arguments to an ifunc that expects + # only one + with self.assertRaises(ValueError): + my_ifunc(a, a) + + my_ifunc = iris.analysis.maths.IFunc(np.multiply, + lambda a: cf_units.Unit('1') + ) + + # should fail because giving 1 arguments to an ifunc that expects + # 2 + with self.assertRaises(ValueError): + my_ifunc(a) + + my_ifunc = iris.analysis.maths.IFunc( + lambda a: (a, a**2.0), + lambda cube: cf_units.Unit('1') + ) + + # should fail because data function returns a tuple + with self.assertRaises(ValueError): + my_ifunc(a) + + my_ifunc = iris.analysis.maths.IFunc( + lambda a: math.sqrt(a), + lambda cube: cf_units.Unit('1') + ) + + # should fail because data function does not work when its argument + # is a numpy array + with self.assertRaises(TypeError): + my_ifunc(a) + def test_type_error(self): with self.assertRaises(TypeError): iris.analysis.maths.add('not a cube', 123) -@iris.tests.skip_data +@tests.skip_data class TestDivideAndMultiply(tests.IrisTest): def setUp(self): self.cube = iris.tests.stock.global_pp() @@ -298,7 +428,7 @@ def test_divide_by_coordinate_dim2(self): # Check that the division has had no effect on the original self.assertCML(a, ('analysis', 'maths_original.cml')) - def test_divide_by_singluar_coordinate(self): + def test_divide_by_singular_coordinate(self): a = self.cube coord = iris.coords.DimCoord(points=2, long_name='foo', units='1') @@ -359,17 +489,8 @@ def test_multiplication_not_in_place(self): b = iris.analysis.maths.multiply(a, 5, in_place=False) self.assertIsNot(a, b) - def test_type_error(self): - with self.assertRaises(TypeError): - iris.analysis.maths.multiply('not a cube', 2) - with self.assertRaises(TypeError): - iris.analysis.maths.multiply(self.cube, 'not a cube') - with self.assertRaises(TypeError): - iris.analysis.maths.multiply(self.cube, 'not a cube', - in_place=True) - -@iris.tests.skip_data +@tests.skip_data class TestExponentiate(tests.IrisTest): def setUp(self): self.cube = iris.tests.stock.global_pp() @@ -407,7 +528,89 @@ def test_exp(self): self.assertCMLApproxData(e, ('analysis', 'exp.cml')) -@iris.tests.skip_data +class TestApplyUfunc(tests.IrisTest): + def setUp(self): + self.cube = iris.tests.stock.simple_2d() + + def test_apply_ufunc(self): + a = self.cube + a.units = cf_units.Unit('meters') + + b = iris.analysis.maths.apply_ufunc(np.square, a, + new_name='more_thingness', new_unit=a.units**2, in_place=False) + + ans = a.data**2 + + self.assertArrayEqual(b.data, ans) + self.assertEqual(b.name(), 'more_thingness') + self.assertEqual(b.units, cf_units.Unit('m^2')) + + def vec_mag(u, v): + return math.sqrt(u**2 + v**2) + + c = a.copy() + 2 + + vec_mag_ufunc = np.frompyfunc(vec_mag, 2, 1) + b = iris.analysis.maths.apply_ufunc(vec_mag_ufunc, a, c) + + ans = a.data**2 + c.data**2 + b2 = b**2 + + self.assertArrayAlmostEqual(b2.data, ans) + + +class TestIFunc(tests.IrisTest): + def setUp(self): + self.cube = iris.tests.stock.simple_2d() + + def test_ifunc(self): + a = self.cube + a.units = cf_units.Unit('meters') + + my_ifunc = iris.analysis.maths.IFunc(np.square, + lambda x: x.units**2) + b = my_ifunc(a, new_name='more_thingness', in_place=False) + + ans = a.data**2 + + self.assertArrayEqual(b.data, ans) + self.assertEqual(b.name(), 'more_thingness') + self.assertEqual(b.units, cf_units.Unit('m^2')) + + def vec_mag(u, v): + return math.sqrt(u**2 + v**2) + + c = a.copy() + 2 + + vec_mag_ufunc = np.frompyfunc(vec_mag, 2, 1) + my_ifunc = iris.analysis.maths.IFunc(vec_mag_ufunc, + lambda x,y: (x + y).units) + b = my_ifunc(a, c) + + ans = ( a.data**2 + c.data**2 ) ** 0.5 + + self.assertArrayAlmostEqual(b.data, ans) + + def vec_mag_data_func(u_data, v_data): + return np.sqrt( u_data**2 + v_data**2 ) + + vec_mag_ifunc = iris.analysis.maths.IFunc(vec_mag_data_func, lambda a,b: (a + b).units) + b2 = vec_mag_ifunc(a, c) + + self.assertArrayAlmostEqual(b.data, b2.data) + + cs_ifunc = iris.analysis.maths.IFunc(np.cumsum, + lambda a: a.units + ) + + b = cs_ifunc(a, axis=1) + ans = a.data.copy() + ans = np.cumsum(ans, axis=1) + + self.assertArrayAlmostEqual(b.data, ans) + + +@tests.skip_data class TestLog(tests.IrisTest): def setUp(self): self.cube = iris.tests.stock.global_pp() @@ -422,59 +625,192 @@ def test_log2(self): def test_log10(self): e = iris.analysis.maths.log10(self.cube) - self.assertCMLApproxData(e, ('analysis', 'log10.cml')) - + self.assertCMLApproxData(e, ('analysis', 'log10.cml'), rtol=1e-6) -class TestMaskedArrays(tests.IrisTest): - ops = (operator.add, operator.sub, operator.mul, operator.div) - iops = (operator.iadd, operator.isub, operator.imul, operator.idiv) +class TestMathOperations(tests.IrisTest): def setUp(self): - self.data1 = ma.MaskedArray([[9,9,9],[8,8,8,]],mask=[[0,1,0],[0,0,1]]) - self.data2 = ma.MaskedArray([[3,3,3],[2,2,2,]],mask=[[0,1,0],[0,1,1]]) - - self.cube1 = iris.cube.Cube(self.data1) - self.cube2 = iris.cube.Cube(self.data2) + self.data_1f = np.array([[9, 9, 9], [8, 8, 8]], + dtype=np.float64) + self.data_2f = np.array([[3, 3, 3], [2, 2, 2]], + dtype=np.float64) + self.data_1i = np.array([[9, 9, 9], [8, 8, 8]], + dtype=np.int64) + self.data_2i = np.array([[3, 3, 3], [2, 2, 2]], + dtype=np.int64) + self.data_1u = np.array([[9, 9, 9], [8, 8, 8]], + dtype=np.uint64) + self.data_2u = np.array([[3, 3, 3], [2, 2, 2]], + dtype=np.uint64) + + self.cube_1f = iris.cube.Cube(self.data_1f) + self.cube_2f = iris.cube.Cube(self.data_2f) + self.cube_1i = iris.cube.Cube(self.data_1i) + self.cube_2i = iris.cube.Cube(self.data_2i) + self.cube_1u = iris.cube.Cube(self.data_1u) + self.cube_2u = iris.cube.Cube(self.data_2u) + + self.ops = (operator.add, operator.sub, operator.mul, operator.truediv) + self.iops = (operator.iadd, operator.isub, + operator.imul, operator.itruediv) def test_operator(self): for test_op in self.ops: - result1 = test_op(self.cube1, self.cube2) - result2 = test_op(self.data1, self.data2) - - np.testing.assert_array_equal(result1.data, result2) - - def test_operator_in_place(self): + result1 = test_op(self.cube_1f, self.cube_2f) + result2 = test_op(self.data_1f, self.data_2f) + self.assertArrayAlmostEqual(result1.data, result2) + result3 = test_op(self.cube_1i, self.cube_2i) + result4 = test_op(self.data_1i, self.data_2i) + self.assertArrayAlmostEqual(result3.data, result4) + result3 = test_op(self.cube_1u, self.cube_2u) + result4 = test_op(self.data_1u, self.data_2u) + self.assertArrayAlmostEqual(result3.data, result4) + + def test_operator__mixed_floats_ints(self): + for test_op in self.ops: + result1 = test_op(self.cube_1f, self.cube_2i) + result2 = test_op(self.data_1f, self.data_2i) + self.assertArrayAlmostEqual(result1.data, result2) + result3 = test_op(self.cube_1i, self.cube_2f) + result4 = test_op(self.data_1i, self.data_2f) + self.assertArrayAlmostEqual(result3.data, result4) + + def test_operator__inplace(self): for test_op in self.iops: - test_op(self.cube1, self.cube2) - test_op(self.data1, self.data2) - - np.testing.assert_array_equal(self.cube1.data, self.data1) - - def test_operator_scalar(self): + test_op(self.cube_1f, self.cube_2f) + test_op(self.data_1f, self.data_2f) + self.assertArrayAlmostEqual(self.cube_1f.data, self.data_1f) + if test_op != operator.itruediv: + # You can't safely cast floats from true-dividing back to ints + # to satisfy the in-place requirement. + test_op(self.cube_1i, self.cube_2i) + expected = test_op(self.data_1i, self.data_2i) + self.assertArrayAlmostEqual(self.cube_1i.data, expected) + test_op(self.cube_1u, self.cube_2u) + expected = test_op(self.data_1u, self.data_2u) + self.assertArrayAlmostEqual(self.cube_1u.data, expected) + + def test_operator__inplace__mixed_floats_ints_uints(self): + # Can only test float-type numerators as int-type numerators + # would require casting ints to floats to satisfy the in-place + # requirement, which cannot be done 'safely'. + for test_op in self.iops: + result1 = test_op(self.cube_1f, self.cube_2i) + result2 = test_op(self.data_1f, self.data_2i) + self.assertArrayAlmostEqual(result1.data, result2) + result1 = test_op(self.cube_1f, self.cube_2u) + result2 = test_op(self.data_1f, self.data_2u) + self.assertArrayAlmostEqual(result1.data, result2) + + def test_operator__inplace__mixed_ints_uints_floats(self): + # Math operations on int-type numerators float-type denominators + # would require casting floats to ints to satisfy the in-place + # requirement. + for test_op in self.iops: + test_emsg = 'Cannot perform inplace' + with self.assertRaisesRegexp(ArithmeticError, test_emsg): + test_op(self.cube_1i, self.cube_2f) + with self.assertRaisesRegexp(ArithmeticError, test_emsg): + test_op(self.cube_1u, self.cube_2f) + + def test_operator__inplace__scalar_int(self): + # Math operations on int-type numerators float-type denominators + # would require casting floats to ints to satisfy the in-place + # requirement. + scalar = 2 + for test_op in self.iops: + if test_op != operator.itruediv: + # You can't safely cast floats from true-dividing back to ints + # to satisfy the in-place requirement. + test_op(self.cube_1i, scalar) + test_op(self.data_1i, scalar) + self.assertArrayAlmostEqual(self.cube_1i.data, self.data_1i) + test_op(self.cube_1u, scalar) + test_op(self.data_1u, scalar) + self.assertArrayAlmostEqual(self.cube_1u.data, self.data_1u) + + def test_operator__inplace__scalar_float(self): + # Math operations on int-type numerators float-type denominators + # would require casting floats to ints to satisfy the in-place + # requirement. + scalar = 2.5 + for test_op in self.iops: + test_emsg = 'Cannot perform inplace' + with self.assertRaisesRegexp(ArithmeticError, test_emsg): + test_op(self.cube_1i, scalar) + with self.assertRaisesRegexp(ArithmeticError, test_emsg): + test_op(self.cube_1u, scalar) + + def test_operator__scalar_float(self): + scalar = 2.5 for test_op in self.ops: - result1 = test_op(self.cube1, 2) - result2 = test_op(self.data1, 2) - - np.testing.assert_array_equal(result1.data, result2) + result1 = test_op(self.cube_1f, scalar) + result2 = test_op(self.data_1f, scalar) + self.assertArrayAlmostEqual(result1.data, result2) + result3 = test_op(self.cube_1i, scalar) + result4 = test_op(self.data_1i, scalar) + self.assertArrayAlmostEqual(result3.data, result4) + + def test_operator_scalar__int(self): + scalar = 2 + for test_op in self.ops: + result1 = test_op(self.cube_1f, scalar) + result2 = test_op(self.data_1f, scalar) + self.assertArrayAlmostEqual(result1.data, result2) + result3 = test_op(self.cube_1i, scalar) + result4 = test_op(self.data_1i, scalar) + self.assertArrayAlmostEqual(result3.data, result4) def test_operator_array(self): for test_op in self.ops: - result1 = test_op(self.cube1, self.data2) - result2 = test_op(self.data1, self.data2) + result1 = test_op(self.cube_1f, self.data_2f) + result2 = test_op(self.data_1f, self.data_2f) + self.assertArrayAlmostEqual(result1.data, result2) + result3 = test_op(self.cube_1i, self.data_2i) + result4 = test_op(self.data_1i, self.data_2i) + self.assertArrayAlmostEqual(result3.data, result4) + + def test_cube_itruediv__int(self): + with self.assertRaisesRegexp(ArithmeticError, + 'Cannot perform inplace division'): + operator.itruediv(self.cube_1i, self.cube_2i) + + def test_cube_itruediv__uint(self): + with self.assertRaisesRegexp(ArithmeticError, + 'Cannot perform inplace division'): + operator.itruediv(self.cube_1u, self.cube_2u) + + def test_int_cube_itruediv__scalar(self): + with self.assertRaisesRegexp(ArithmeticError, + 'Cannot perform inplace division'): + operator.itruediv(self.cube_1i, 5) + + def test_uint_cube_itruediv__scalar(self): + with self.assertRaisesRegexp(ArithmeticError, + 'Cannot perform inplace division'): + operator.itruediv(self.cube_1u, 5) - np.testing.assert_array_equal(result1.data, result2) + +class TestMaskedArrays(tests.IrisTest): + def setUp(self): + self.data = ma.MaskedArray([[9, 9, 9], [8, 8, 8]], + mask=[[0, 1, 0], [0, 0, 1]], + dtype=np.float64) + self.cube = iris.cube.Cube(self.data) def test_incompatible_dimensions(self): - data3 = ma.MaskedArray([[3,3,3,4],[2,2,2]],mask=[[0,1,0,0],[0,1,1]]) + data3 = ma.MaskedArray([[3, 3, 3, 4], [2, 2, 2]], + mask=[[0, 1, 0, 0], [0, 1, 1]]) with self.assertRaises(ValueError): - # incompatible dimensions - self.cube1 + data3 + # Incompatible dimensions. + self.cube + data3 def test_increase_cube_dimensionality(self): with self.assertRaises(ValueError): - # This would increase the dimensionality of the cube due to auto broadcasting - cubex = iris.cube.Cube(ma.MaskedArray([[9,]],mask=[[0]])) - cubex + ma.MaskedArray([[3,3,3,3]],mask=[[0,1,0,1]]) + # This would increase the dimensionality of the cube + # due to auto-broadcasting. + cube_x = iris.cube.Cube(ma.MaskedArray([[9]], mask=[[0]])) + cube_x + ma.MaskedArray([[3, 3, 3, 3]], mask=[[0, 1, 0, 1]]) if __name__ == "__main__": diff --git a/lib/iris/tests/test_cartography.py b/lib/iris/tests/test_cartography.py index 9f89bc3505..6ec5f37bef 100644 --- a/lib/iris/tests/test_cartography.py +++ b/lib/iris/tests/test_cartography.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -19,6 +19,9 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests diff --git a/lib/iris/tests/test_cdm.py b/lib/iris/tests/test_cdm.py index 302403a131..be08a9c5c6 100644 --- a/lib/iris/tests/test_cdm.py +++ b/lib/iris/tests/test_cdm.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -18,6 +18,11 @@ Test cube indexing, slicing, and extracting, and also the dot graphs. """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests @@ -25,9 +30,9 @@ import os import re import sys -import warnings +import unittest -import biggus +import cf_units import numpy as np import numpy.ma as ma @@ -36,7 +41,7 @@ import iris.coords import iris.cube import iris.fileformats -import iris.unit +import iris.fileformats.dot import iris.tests.pp as pp import iris.tests.stock @@ -46,11 +51,12 @@ def check_dot(self, cube, reference_filename): test_string = iris.fileformats.dot.cube_text(cube) reference_path = tests.get_result_path(reference_filename) if os.path.isfile(reference_path): - reference = ''.join(open(reference_path, 'r').readlines()) + with open(reference_path, 'r') as reference_fh: + reference = ''.join(reference_fh.readlines()) self._assert_str_same(reference, test_string, reference_filename, type_comparison_name='DOT files') else: - tests.logger.warning('Creating result file: %s', reference_path) - open(reference_path, 'w').writelines(test_string) + with open(reference_path, 'w') as reference_fh: + reference_fh.writelines(test_string) class TestBasicCubeConstruction(tests.IrisTest): @@ -208,38 +214,49 @@ def test_immutable_auxcoord_dims(self): dims[0] = 1 +@tests.skip_data class TestStockCubeStringRepresentations(tests.IrisTest): def setUp(self): self.cube = iris.tests.stock.realistic_4d() - def _check(self, cube): - prefix = 'realistic_{}d'.format(cube.ndim) - self.assertString(str(cube), ('cdm', 'str_repr', prefix + '.str.txt')) - self.assertString(repr(cube), ('cdm', 'str_repr', prefix + '.repr.txt')) + def test_4d_str(self): + self.assertString(str(self.cube)) + + def test_4d_repr(self): + self.assertString(repr(self.cube)) + + def test_3d_str(self): + self.assertString(str(self.cube[0])) - def test_4d(self): - self._check(self.cube) + def test_3d_repr(self): + self.assertString(repr(self.cube[0])) - def test_3d(self): - self._check(self.cube[0]) + def test_2d_str(self): + self.assertString(str(self.cube[0, 0])) - def test_2d(self): - self._check(self.cube[0, 0]) + def test_2d_repr(self): + self.assertString(repr(self.cube[0, 0])) - def test_1d(self): - self._check(self.cube[0, 0, 0]) + def test_1d_str(self): + self.assertString(str(self.cube[0, 0, 0])) - def test_0d(self): - self._check(self.cube[0, 0, 0, 0]) + def test_1d_repr(self): + self.assertString(repr(self.cube[0, 0, 0])) + def test_0d_str(self): + self.assertString(str(self.cube[0, 0, 0, 0])) -@iris.tests.skip_data + def test_0d_repr(self): + self.assertString(repr(self.cube[0, 0, 0, 0])) + + +@tests.skip_data class TestCubeStringRepresentations(IrisDotTest): def setUp(self): path = tests.get_data_path(('PP', 'simple_pp', 'global.pp')) self.cube_2d = iris.load_cube(path) # Generate the unicode cube up here now it's used in two tests. - unicode_str = unichr(40960) + u'abcd' + unichr(1972) + unicode_str = six.unichr(40960) + u'abcd' + six.unichr(1972) self.unicode_cube = iris.tests.stock.simple_1d() self.unicode_cube.attributes['source'] = unicode_str @@ -260,10 +277,12 @@ def test_dot_simple_pp(self): del cube.attributes['my_attribute'] # TODO hybrid height and dot output - relatitionship links + @tests.skip_data def test_dot_4d(self): cube = iris.tests.stock.realistic_4d() self.check_dot(cube, ('file_load', '4d_pp.dot')) + @tests.skip_data def test_missing_coords(self): cube = iris.tests.stock.realistic_4d() cube.remove_coord('time') @@ -273,6 +292,7 @@ def test_missing_coords(self): self.assertString(str(cube), ('cdm', 'str_repr', 'missing_coords_cube.str.txt')) + @tests.skip_data def test_cubelist_string(self): cube_list = iris.cube.CubeList([iris.tests.stock.realistic_4d(), iris.tests.stock.global_pp()]) @@ -282,7 +302,7 @@ def test_cubelist_string(self): def test_basic_0d_cube(self): self.assertString(repr(self.cube_2d[0, 0]), ('cdm', 'str_repr', '0d_cube.__repr__.txt')) - self.assertString(unicode(self.cube_2d[0, 0]), + self.assertString(six.text_type(self.cube_2d[0, 0]), ('cdm', 'str_repr', '0d_cube.__unicode__.txt')) self.assertString(str(self.cube_2d[0, 0]), ('cdm', 'str_repr', '0d_cube.__str__.txt')) @@ -313,7 +333,7 @@ def test_cube_summary_cell_methods(self): # Create a list of values used to create cell methods test_values = ((("mean",), (u'longitude', 'latitude'), (u'6 minutes', '12 minutes'), (u'This is a test comment',)), - (("average",), (u'longitude', 'latitude'), (u'6 minutes', '15 minutes'), (u'This is another test comment','This is another comment')), + (("average",), (u'longitude', 'latitude'), (u'6 minutes', '15 minutes'), (u'This is another test comment', 'This is another comment')), (("average",), (u'longitude', 'latitude'), (), ()), (("percentile",), (u'longitude',), (u'6 minutes',), (u'This is another test comment',))) @@ -327,9 +347,13 @@ def test_cube_summary_cell_methods(self): def test_cube_summary_alignment(self): # Test the cube summary dimension alignment and coord name clipping cube = iris.tests.stock.simple_1d() - aux = iris.coords.AuxCoord(range(11), long_name='This is a really, really, really long long_name that requires to be clipped because it is too long') + aux = iris.coords.AuxCoord( + np.arange(11), + long_name='This is a really, really, really, really long ' + 'long_name that must be clipped because it is too long') cube.add_aux_coord(aux, 0) - aux = iris.coords.AuxCoord(range(11), long_name='This is a short long_name') + aux = iris.coords.AuxCoord(np.arange(11), + long_name='This is a short long_name') cube.add_aux_coord(aux, 0) self.assertString(str(cube), ('cdm', 'str_repr', 'simple.__str__.txt')) @@ -341,6 +365,7 @@ def unicode_encoding_change(self, new_encoding): sys.setdefaultencoding(default_encoding) del sys.setdefaultencoding + @unittest.skipIf(six.PY3, 'Encodings are sane in Python 3.') def test_adjusted_default_encoding(self): # Test cube str representation on non-system-default encodings. # Doing this requires access to a sys method that is removed by default @@ -360,11 +385,11 @@ def test_adjusted_default_encoding(self): def test_unicode_attribute(self): self.assertString( - unicode(self.unicode_cube), ('cdm', 'str_repr', - 'unicode_attribute.__unicode__.txt')) + six.text_type(self.unicode_cube), + ('cdm', 'str_repr', 'unicode_attribute.__unicode__.txt')) -@iris.tests.skip_data +@tests.skip_data class TestValidity(tests.IrisTest): def setUp(self): self.cube_2d = iris.load_cube(tests.get_data_path(('PP', 'simple_pp', 'global.pp'))) @@ -669,7 +694,7 @@ def test_cube_extract_by_coord_advanced(self): self.assertCML(self.t.subset(c), ('cube_slice', '2d_intersect_and_reverse.cml')) -@iris.tests.skip_data +@tests.skip_data class TestCubeExtract(tests.IrisTest): def setUp(self): self.single_cube = iris.load_cube(tests.get_data_path(('PP', 'globClim1', 'theta.pp')), 'air_potential_temperature') @@ -705,6 +730,16 @@ def test_var_name(self): self.t.var_name = 'bar' self.assertEqual(self.t.var_name, 'bar') + def test_default_name(self): + self.t.long_name = '' + self.assertEqual(self.t.name(), 'unknown') + self.assertEqual(self.t.name('a_default'), 'a_default') + + def test_stash_name(self): + self.t.long_name = '' + self.t.attributes['STASH'] = iris.fileformats.pp.STASH(1, 2, 3) + self.assertEqual(self.t.name(), 'm01s02i003') + def test_name_and_var_name(self): # Assign only var_name. self.t.standard_name = None @@ -731,12 +766,12 @@ def test_setting_empty_var_name(self): self.t.var_name = '' def test_getting_units(self): - self.assertEqual(self.t.units, iris.unit.Unit('meters')) + self.assertEqual(self.t.units, cf_units.Unit('meters')) def test_setting_units(self): - self.assertEqual(self.t.units, iris.unit.Unit('meters')) + self.assertEqual(self.t.units, cf_units.Unit('meters')) self.t.units = 'kelvin' - self.assertEqual(self.t.units, iris.unit.Unit('kelvin')) + self.assertEqual(self.t.units, cf_units.Unit('kelvin')) def test_clearing_units(self): self.t.units = None @@ -744,7 +779,7 @@ def test_clearing_units(self): def test_convert_units(self): # Set to 'volt' - self.t.units = iris.unit.Unit('volt') + self.t.units = cf_units.Unit('volt') data = self.t.data.copy() # Change to 'kV' - data should be scaled automatically. self.t.convert_units('kV') @@ -799,6 +834,7 @@ class Metadata(object): pass metadata.units = '' metadata.attributes = {'random': '12'} metadata.cell_methods = () + metadata.cell_measures_and_dims = [] self.t.metadata = metadata self.assertEqual(self.t.standard_name, 'air_pressure') self.assertEqual(self.t.long_name, 'foo') @@ -807,12 +843,13 @@ class Metadata(object): pass self.assertEqual(self.t.attributes, metadata.attributes) self.assertIsNot(self.t.attributes, metadata.attributes) self.assertEqual(self.t.cell_methods, ()) + self.assertEqual(self.t._cell_measures_and_dims, []) def test_metadata_fail(self): with self.assertRaises(TypeError): self.t.metadata = ('air_pressure', 'foo', 'bar', '', {'random': '12'}) with self.assertRaises(TypeError): - self.t.metadata = ('air_pressure', 'foo', 'bar', '', {'random': '12'}, (), ()) + self.t.metadata = ('air_pressure', 'foo', 'bar', '', {'random': '12'}, (), [], (), ()) with self.assertRaises(TypeError): self.t.metadata = {'standard_name': 'air_pressure', 'long_name': 'foo', @@ -833,7 +870,7 @@ class Metadata(object): pass class TestCubeEquality(TestCube2d): def test_simple_equality(self): self.assertEqual(self.t, self.t.copy()) - + def test_data_inequality(self): self.assertNotEqual(self.t, self.t + 1) @@ -916,34 +953,34 @@ def test_is_compatible_metadata(self): self.assertTrue(self.t.is_compatible(metadata)) -@iris.tests.skip_data +@tests.skip_data class TestDataManagerIndexing(TestCube2d): def setUp(self): self.cube = iris.load_cube(tests.get_data_path(('PP', 'aPProt1', 'rotatedMHtimecube.pp'))) - def _is_lazy(self, cube): + def assert_is_lazy(self, cube): self.assertTrue(cube.has_lazy_data()) - def _is_concrete(self, cube): + def assert_is_not_lazy(self, cube): self.assertFalse(cube.has_lazy_data()) def test_slices(self): - lat_cube = self.cube.slices(['grid_latitude', ]).next() - self._is_lazy(lat_cube) - self._is_lazy(self.cube) - + lat_cube = next(self.cube.slices(['grid_latitude', ])) + self.assert_is_lazy(lat_cube) + self.assert_is_lazy(self.cube) + def test_cube_empty_indexing(self): test_filename = ('cube_slice', 'real_empty_data_indexing.cml') r = self.cube[:5, ::-1][3] rshape = r.shape # Make sure we still have deferred data. - self._is_lazy(r) + self.assert_is_lazy(r) # check the CML of this result self.assertCML(r, test_filename) # The CML was checked, meaning the data must have been loaded. # Check that the cube no longer has deferred data. - self._is_concrete(r) + self.assert_is_not_lazy(r) r_data = r.data @@ -989,23 +1026,32 @@ def partial_compare(self, dual, single): self.assertEqual(dual.shape, single.shape, "dual and single stage shape differ") def collapse_test_common(self, cube, a_name, b_name, *args, **kwargs): - # preserve filenames from before the introduction of "grid_" in rotated coord names. a_filename = a_name.replace("grid_", "") b_filename = b_name.replace("grid_", "") - + # compare dual and single stage collapsing dual_stage = cube.collapsed(a_name, iris.analysis.MEAN) dual_stage = dual_stage.collapsed(b_name, iris.analysis.MEAN) + # np.ma.average doesn't apply type promotion rules in some versions, + # and instead makes the result type float64. To ignore that case we + # fix up the dtype here if it is promotable from cube.dtype. We still + # want to catch cases where there is a loss of precision however. + if dual_stage.dtype > cube.dtype: + data = dual_stage.data.astype(cube.dtype) + dual_stage.data = data self.assertCMLApproxData(dual_stage, ('cube_collapsed', '%s_%s_dual_stage.cml' % (a_filename, b_filename)), *args, **kwargs) single_stage = cube.collapsed([a_name, b_name], iris.analysis.MEAN) + if single_stage.dtype > cube.dtype: + data = single_stage.data.astype(cube.dtype) + single_stage.data = data self.assertCMLApproxData(single_stage, ('cube_collapsed', '%s_%s_single_stage.cml' % (a_filename, b_filename)), *args, **kwargs) # Compare the cube bits that should match self.partial_compare(dual_stage, single_stage) - @iris.tests.skip_data + @tests.skip_data def test_multi_d(self): cube = iris.tests.stock.realistic_4d() @@ -1016,39 +1062,66 @@ def test_multi_d(self): self.assertCML(cube, ('cube_collapsed', 'original.cml')) - # Compare 2-stage collapsing with a single stage collapse over 2 Coords. - self.collapse_test_common(cube, 'grid_latitude', 'grid_longitude', decimal=1) - self.collapse_test_common(cube, 'grid_longitude', 'grid_latitude', decimal=1) + # Compare 2-stage collapsing with a single stage collapse + # over 2 Coords. + self.collapse_test_common(cube, 'grid_latitude', 'grid_longitude', + rtol=1e-05) + self.collapse_test_common(cube, 'grid_longitude', 'grid_latitude', + rtol=1e-05) - self.collapse_test_common(cube, 'time', 'grid_latitude', decimal=1) - self.collapse_test_common(cube, 'grid_latitude', 'time', decimal=1) + self.collapse_test_common(cube, 'time', 'grid_latitude', rtol=1e-05) + self.collapse_test_common(cube, 'grid_latitude', 'time', rtol=1e-05) - self.collapse_test_common(cube, 'time', 'grid_longitude', decimal=1) - self.collapse_test_common(cube, 'grid_longitude', 'time', decimal=1) + self.collapse_test_common(cube, 'time', 'grid_longitude', rtol=1e-05) + self.collapse_test_common(cube, 'grid_longitude', 'time', rtol=1e-05) - self.collapse_test_common(cube, 'grid_latitude', 'model_level_number', decimal=1) - self.collapse_test_common(cube, 'model_level_number', 'grid_latitude', decimal=1) + self.collapse_test_common(cube, 'grid_latitude', 'model_level_number', + rtol=5e-04) + self.collapse_test_common(cube, 'model_level_number', 'grid_latitude', + rtol=5e-04) - self.collapse_test_common(cube, 'grid_longitude', 'model_level_number', decimal=1) - self.collapse_test_common(cube, 'model_level_number', 'grid_longitude', decimal=1) + self.collapse_test_common(cube, 'grid_longitude', 'model_level_number', + rtol=5e-04) + self.collapse_test_common(cube, 'model_level_number', 'grid_longitude', + rtol=5e-04) - self.collapse_test_common(cube, 'time', 'model_level_number', decimal=1) - self.collapse_test_common(cube, 'model_level_number', 'time', decimal=1) + self.collapse_test_common(cube, 'time', 'model_level_number', + rtol=5e-04) + self.collapse_test_common(cube, 'model_level_number', 'time', + rtol=5e-04) - self.collapse_test_common(cube, 'model_level_number', 'time', decimal=1) - self.collapse_test_common(cube, 'time', 'model_level_number', decimal=1) + self.collapse_test_common(cube, 'model_level_number', 'time', + rtol=5e-04) + self.collapse_test_common(cube, 'time', 'model_level_number', + rtol=5e-04) # Collapse 3 things at once. - triple_collapse = cube.collapsed(['model_level_number', 'time', 'grid_longitude'], iris.analysis.MEAN) - self.assertCMLApproxData(triple_collapse, ('cube_collapsed', 'triple_collapse_ml_pt_lon.cml'), decimal=1) - - triple_collapse = cube.collapsed(['grid_latitude', 'model_level_number', 'time'], iris.analysis.MEAN) - self.assertCMLApproxData(triple_collapse, ('cube_collapsed', 'triple_collapse_lat_ml_pt.cml'), decimal=1) + triple_collapse = cube.collapsed(['model_level_number', + 'time', 'grid_longitude'], + iris.analysis.MEAN) + self.assertCMLApproxData(triple_collapse, ('cube_collapsed', + ('triple_collapse_ml_pt_' + 'lon.cml')), + rtol=5e-04) + + triple_collapse = cube.collapsed(['grid_latitude', + 'model_level_number', 'time'], + iris.analysis.MEAN) + self.assertCMLApproxData(triple_collapse, ('cube_collapsed', + ('triple_collapse_lat_ml' + '_pt.cml')), + rtol=0.05) + # KNOWN PROBLEM: the previous 'rtol' is very large. + # Numpy 1.10 and 1.11 give significantly different results here. + # This may relate to known problems with summing over large arrays, + # which were largely fixed in numpy 1.9 but still occur in some cases, + # as-of numpy 1.11. # Ensure no side effects self.assertCML(cube, ('cube_collapsed', 'original.cml')) - - + + +@tests.skip_data class TestTrimAttributes(tests.IrisTest): def test_non_string_attributes(self): cube = iris.tests.stock.realistic_4d() @@ -1069,10 +1142,12 @@ def test_non_string_attributes(self): self.fail('Attribute not found in summary output of cube.') -@iris.tests.skip_data +@tests.skip_data class TestMaskedData(tests.IrisTest, pp.PPTest): def _load_3d_cube(self): - # This 3D data set has a missing a slice with SOME missing values (0) + # This 3D data set has a missing a slice with SOME missing values. + # The missing data is in the pressure = 1000 hPa, forcast_period = 0, + # time = 1970-02-11 16:00:00 slice. return iris.load_cube(tests.get_data_path(["PP", "mdi_handmade_small", "*.pp"])) def test_complete_field(self): @@ -1090,7 +1165,7 @@ def test_missing_file(self): cube = self._load_3d_cube() self.assertIsInstance(cube.data, ma.core.MaskedArray) self.assertCML(cube, ('cdm', 'masked_cube.cml')) - + def test_slicing(self): cube = self._load_3d_cube() @@ -1110,48 +1185,57 @@ def test_slicing(self): def test_save_and_merge(self): cube = self._load_3d_cube() + dtype = cube.dtype + fill_value = 123456 # extract the 2d field that has SOME missing values masked_slice = cube[0] - masked_slice.data.fill_value = 123456 - + masked_slice.data.fill_value = fill_value + # test saving masked data reference_txt_path = tests.get_result_path(('cdm', 'masked_save_pp.txt')) with self.cube_save_test(reference_txt_path, reference_cubes=masked_slice) as temp_pp_path: iris.save(masked_slice, temp_pp_path) - + # test merge keeps the mdi we just saved cube1 = iris.load_cube(temp_pp_path) + self.assertEqual(cube1.dtype, dtype) + cube2 = cube1.copy() # make cube1 and cube2 differ on a scalar coord, to make them mergeable into a 3d cube - cube2.coord("pressure").points[0] = 1001.0 + cube2.coord("pressure").points = [1001.0] merged_cubes = iris.cube.CubeList([cube1, cube2]).merge() self.assertEqual(len(merged_cubes), 1, "expected a single merged cube") merged_cube = merged_cubes[0] - self.assertEqual(merged_cube.data.fill_value, 123456) + self.assertEqual(merged_cube.dtype, dtype) + # Check that the original masked-array fill-value is *ignored*. + self.assertArrayAllClose(merged_cube.data.fill_value, -1e30) +@tests.skip_data class TestConversionToCoordList(tests.IrisTest): def test_coord_conversion(self): cube = iris.tests.stock.realistic_4d() # Single string - self.assertEquals(len(cube._as_list_of_coords('grid_longitude')), 1) + self.assertEqual(len(cube._as_list_of_coords('grid_longitude')), 1) # List of string and unicode - self.assertEquals(len(cube._as_list_of_coords(['grid_longitude', u'grid_latitude'], )), 2) + self.assertEqual(len(cube._as_list_of_coords(['grid_longitude', + u'grid_latitude'], )), 2) # Coord object(s) lat = cube.coords("grid_latitude")[0] lon = cube.coords("grid_longitude")[0] - self.assertEquals(len(cube._as_list_of_coords(lat)), 1) - self.assertEquals(len(cube._as_list_of_coords([lat, lon])), 2) + self.assertEqual(len(cube._as_list_of_coords(lat)), 1) + self.assertEqual(len(cube._as_list_of_coords([lat, lon])), 2) # Mix of string-like and coord - self.assertEquals(len(cube._as_list_of_coords(["grid_latitude", lon])), 2) + self.assertEqual(len(cube._as_list_of_coords(['grid_latitude', lon])), + 2) # Empty list - self.assertEquals(len(cube._as_list_of_coords([])), 0) + self.assertEqual(len(cube._as_list_of_coords([])), 0) # Invalid coords invalid_choices = [iris.analysis.MEAN, # Caused by mixing up argument order in call to cube.collasped for example diff --git a/lib/iris/tests/test_cell.py b/lib/iris/tests/test_cell.py index 335204fa91..8a1a0fbe46 100644 --- a/lib/iris/tests/test_cell.py +++ b/lib/iris/tests/test_cell.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -16,20 +16,19 @@ # along with Iris. If not, see . -from __future__ import division +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests -import unittest - import numpy as np import iris.coords from iris.coords import Cell -class TestCells(unittest.TestCase): +class TestCells(tests.IrisTest): def setUp(self): self.cell1 = iris.coords.Cell(3, [2, 4]) self.cell2 = iris.coords.Cell(360., [350., 370.]) @@ -125,8 +124,8 @@ def test_coord_equality(self): # Ensure the Cell's operators return NotImplemented. class Terry(object): pass - self.assertEquals(self.d.__eq__(Terry()), NotImplemented) - self.assertEquals(self.d.__ne__(Terry()), NotImplemented) + self.assertEqual(self.d.__eq__(Terry()), NotImplemented) + self.assertEqual(self.d.__ne__(Terry()), NotImplemented) def test_numpy_int_equality(self): dtypes = (np.int, np.int16, np.int32, np.int64) diff --git a/lib/iris/tests/test_cf.py b/lib/iris/tests/test_cf.py index b5186f34d2..846fe0f829 100644 --- a/lib/iris/tests/test_cf.py +++ b/lib/iris/tests/test_cf.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -18,18 +18,19 @@ Test the cf module. """ -# import iris tests first so that some things can be initialised before importing anything else -import iris.tests as tests -import unittest +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa -import mock +# import iris tests first so that some things can be initialised before importing anything else +import iris.tests as tests import iris import iris.fileformats.cf as cf +from iris.tests import mock -class TestCaching(unittest.TestCase): +class TestCaching(tests.IrisTest): def test_cached(self): # Make sure attribute access to the underlying netCDF4.Variable # is cached. @@ -60,7 +61,7 @@ def test_cached(self): self.assertTrue('standard_name' in cf_var.__dict__) -@iris.tests.skip_data +@tests.skip_data class TestCFReader(tests.IrisTest): def setUp(self): filename = tests.get_data_path( @@ -236,39 +237,43 @@ def test_variable_attribute_touch_pass_0(self): ('units', 'degrees_north'))) -@iris.tests.skip_data +@tests.skip_data class TestLoad(tests.IrisTest): def test_attributes_empty(self): filename = tests.get_data_path(('NetCDF', 'global', 'xyt', 'SMALL_hires_wind_u_for_ipcc4.nc')) cube = iris.load_cube(filename) - self.assertEquals(cube.coord('time').attributes, {}) + self.assertEqual(cube.coord('time').attributes, {}) def test_attributes_contain_positive(self): filename = tests.get_data_path(('NetCDF', 'global', 'xyt', 'SMALL_hires_wind_u_for_ipcc4.nc')) cube = iris.load_cube(filename) - self.assertEquals(cube.coord('height').attributes['positive'], 'up') + self.assertEqual(cube.coord('height').attributes['positive'], 'up') def test_attributes_populated(self): filename = tests.get_data_path( ('NetCDF', 'label_and_climate', 'small_FC_167_mon_19601101.nc')) - cube = iris.load_cube(filename) - self.assertEquals( + cube = iris.load_cube(filename, 'air_temperature') + self.assertEqual( sorted(cube.coord('longitude').attributes.items()), [('data_type', 'float'), ('modulo', 360), - ('topology', 'circular') - ] - ) + ('topology', 'circular'), + ('valid_max', 359.0), + ('valid_min', 0.0)]) def test_cell_methods(self): filename = tests.get_data_path(('NetCDF', 'global', 'xyt', 'SMALL_hires_wind_u_for_ipcc4.nc')) cube = iris.load_cube(filename) - self.assertEquals(cube.cell_methods, (iris.coords.CellMethod(method=u'mean', coords=(u'time',), intervals=(u'6 minutes',), comments=()),)) + self.assertEqual(cube.cell_methods, + (iris.coords.CellMethod(method=u'mean', + coords=(u'time', ), + intervals=(u'6 minutes', ), + comments=()), )) -@iris.tests.skip_data +@tests.skip_data class TestClimatology(tests.IrisTest): def setUp(self): filename = tests.get_data_path(('NetCDF', 'label_and_climate', @@ -279,14 +284,14 @@ def test_bounds(self): time = self.cfr.cf_group['temp_dmax_tmean_abs'].cf_group.coordinates['time'] climatology = time.cf_group.climatology self.assertEqual(len(climatology), 1) - self.assertEqual(climatology.keys(), ['climatology_bounds']) + self.assertEqual(list(climatology.keys()), ['climatology_bounds']) climatology_var = climatology['climatology_bounds'] self.assertEqual(climatology_var.ndim, 2) self.assertEqual(climatology_var.shape, (1, 2)) -@iris.tests.skip_data +@tests.skip_data class TestLabels(tests.IrisTest): def setUp(self): filename = tests.get_data_path( diff --git a/lib/iris/tests/test_coding_standards.py b/lib/iris/tests/test_coding_standards.py index 6bb23cb559..c24ac46cb3 100644 --- a/lib/iris/tests/test_coding_standards.py +++ b/lib/iris/tests/test_coding_standards.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office +# (C) British Crown Copyright 2013 - 2018, Met Office # # This file is part of Iris. # @@ -15,13 +15,20 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris.tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + from datetime import datetime from fnmatch import fnmatch from glob import glob +from itertools import chain import os import re import subprocess -import unittest import pep8 @@ -58,27 +65,26 @@ IRIS_DIR = os.path.realpath(os.path.dirname(iris.__file__)) REPO_DIR = os.path.dirname(os.path.dirname(IRIS_DIR)) DOCS_DIR = os.path.join(REPO_DIR, 'docs', 'iris') +DOCS_DIR = iris.config.get_option('Resources', 'doc_dir', default=DOCS_DIR) exclusion = ['Makefile', 'build'] DOCS_DIRS = glob(os.path.join(DOCS_DIR, '*')) DOCS_DIRS = [DOC_DIR for DOC_DIR in DOCS_DIRS if os.path.basename(DOC_DIR) not in exclusion] +# pycodestyle / pep8 error codes that should be ignored: +PYCODESTYLE_IGNORE_OPTIONS = ( + # "Module level import not at top of file" - due to conditional imports + 'E402', +) + + class StandardReportWithExclusions(pep8.StandardReport): expected_bad_files = [ '*/iris/std_names.py', - '*/iris/analysis/calculus.py', - '*/iris/analysis/geometry.py', - '*/iris/analysis/interpolate.py', - '*/iris/analysis/maths.py', - '*/iris/analysis/trajectory.py', '*/iris/fileformats/cf.py', '*/iris/fileformats/dot.py', - '*/iris/fileformats/grib/__init__.py', - '*/iris/fileformats/grib/_grib_cf_map.py', - '*/iris/fileformats/grib/load_rules.py', - '*/iris/fileformats/pp.py', - '*/iris/fileformats/pp_rules.py', + '*/iris/fileformats/pp_load_rules.py', '*/iris/fileformats/rules.py', '*/iris/fileformats/um_cf_map.py', '*/iris/fileformats/_pyke_rules/compiled_krb/compiled_pyke_files.py', @@ -87,7 +93,7 @@ class StandardReportWithExclusions(pep8.StandardReport): '*/iris/io/format_picker.py', '*/iris/tests/__init__.py', '*/iris/tests/pp.py', - '*/iris/tests/stock.py', + '*/iris/tests/stock/__init__.py', '*/iris/tests/system_test.py', '*/iris/tests/test_analysis.py', '*/iris/tests/test_analysis_calculus.py', @@ -106,60 +112,28 @@ class StandardReportWithExclusions(pep8.StandardReport): '*/iris/tests/test_grib_save.py', '*/iris/tests/test_grib_save_rules.py', '*/iris/tests/test_hybrid.py', - '*/iris/tests/test_interpolation.py', '*/iris/tests/test_intersect.py', '*/iris/tests/test_io_init.py', '*/iris/tests/test_iterate.py', '*/iris/tests/test_load.py', - '*/iris/tests/test_mapping.py', '*/iris/tests/test_merge.py', - '*/iris/tests/test_pickling.py', '*/iris/tests/test_pp_cf.py', '*/iris/tests/test_pp_module.py', '*/iris/tests/test_pp_stash.py', '*/iris/tests/test_pp_to_cube.py', '*/iris/tests/test_quickplot.py', - '*/iris/tests/test_regrid.py', - '*/iris/tests/test_rules.py', '*/iris/tests/test_std_names.py', - '*/iris/tests/test_trajectory.py', - '*/iris/tests/test_unit.py', '*/iris/tests/test_uri_callback.py', - '*/iris/tests/test_util.py', - '*/iris/tests/test_verbose_logging.py'] + '*/iris/tests/test_util.py'] + + # Auto-generated by install process, though not always. + optional_bad_files = ['*/iris/fileformats/_old_pp_packing.py'] + expected_bad_files += optional_bad_files if DOCS_DIRS: expected_bad_docs_files = [ - '*/example_code/graphics/COP_1d_plot.py', - '*/example_code/graphics/COP_maps.py', - '*/example_code/graphics/SOI_filtering.py', - '*/example_code/graphics/cross_section.py', - '*/example_code/graphics/custom_file_loading.py', - '*/example_code/graphics/global_map.py', - '*/example_code/graphics/hovmoller.py', - '*/example_code/graphics/lagged_ensemble.py', - '*/example_tests/test_COP_1d_plot.py', - '*/example_tests/test_COP_maps.py', - '*/example_tests/test_SOI_filtering.py', - '*/example_tests/test_TEC.py', - '*/example_tests/test_cross_section.py', - '*/example_tests/test_custom_file_loading.py', - '*/example_tests/test_deriving_phenomena.py', - '*/example_tests/test_global_map.py', - '*/example_tests/test_hovmoller.py', - '*/example_tests/test_lagged_ensemble.py', - '*/example_tests/test_lineplot_with_legend.py', - '*/example_tests/test_rotated_pole_mapping.py', '*/src/conf.py', - '*/src/developers_guide/gitwash_dumper.py', - '*/src/sphinxext/custom_class_autodoc.py', - '*/src/sphinxext/gen_example_directory.py', - '*/src/sphinxext/gen_gallery.py', - '*/src/sphinxext/gen_rst.py', - '*/src/sphinxext/generate_package_rst.py', - '*/src/sphinxext/plot_directive.py', - '*/src/userguide/plotting_examples/1d_with_legend.py', - '*/src/userguide/plotting_examples/brewer.py'] + '*/src/developers_guide/gitwash_dumper.py'] expected_bad_files += expected_bad_docs_files @@ -191,21 +165,22 @@ def get_file_results(self): self).get_file_results() -class TestCodeFormat(unittest.TestCase): +class TestCodeFormat(tests.IrisTest): def test_pep8_conformance(self): -# -# Tests the iris codebase against the "pep8" tool. -# -# Users can add their own excluded files (should files exist in the -# local directory which is not in the repository) by adding a -# ".pep8_test_exclude.txt" file in the same directory as this test. -# The file should be a line separated list of filenames/directories -# as can be passed to the "pep8" tool's exclude list. + # + # Tests the iris codebase against the "pep8" tool. + # + # Users can add their own excluded files (should files exist in the + # local directory which is not in the repository) by adding a + # ".pep8_test_exclude.txt" file in the same directory as this test. + # The file should be a line separated list of filenames/directories + # as can be passed to the "pep8" tool's exclude list. # To get a list of bad files, rather than the specific errors, add # "reporter=pep8.FileReport" to the StyleGuide constructor. pep8style = pep8.StyleGuide(quiet=False, reporter=StandardReportWithExclusions) + pep8style.options.ignore += PYCODESTYLE_IGNORE_OPTIONS # Allow users to add their own exclude list. extra_exclude_file = os.path.join(os.path.dirname(__file__), @@ -228,6 +203,7 @@ def test_pep8_conformance(self): # exclude files unnecessarily. if reporter is StandardReportWithExclusions: unexpectedly_good = sorted(set(reporter.expected_bad_files) - + set(reporter.optional_bad_files) - reporter.matched_exclusions) if unexpectedly_good: @@ -237,7 +213,7 @@ def test_pep8_conformance(self): '{}'.format('\n '.join(unexpectedly_good))) -class TestLicenseHeaders(unittest.TestCase): +class TestLicenseHeaders(tests.IrisTest): @staticmethod def years_of_license_in_file(fh): """ @@ -311,7 +287,7 @@ def last_change_by_fname(): output = subprocess.check_output(['git', 'whatchanged', "--pretty=TIME:%ct"], cwd=REPO_DIR) - output = output.split('\n') + output = output.decode().split('\n') res = {} for fname, dt in TestLicenseHeaders.whatchanged_parse(output): if fname not in res or dt > res[fname]: @@ -323,16 +299,15 @@ def test_license_headers(self): exclude_patterns = ('setup.py', 'build/*', 'dist/*', - 'docs/iris/example_code/graphics/*.py', + 'docs/iris/example_code/*/*.py', 'docs/iris/src/developers_guide/documenting/*.py', 'docs/iris/src/sphinxext/gen_gallery.py', - 'docs/iris/src/sphinxext/gen_rst.py', - 'docs/iris/src/sphinxext/plot_directive.py', 'docs/iris/src/userguide/plotting_examples/*.py', + 'docs/iris/src/userguide/regridding_plots/*.py', 'docs/iris/src/developers_guide/gitwash_dumper.py', 'docs/iris/build/*', - 'lib/iris/fileformats/_pyke_rules/*', - 'lib/iris/fileformats/grib/_grib_cf_map.py') + 'lib/iris/analysis/_scipy_interpolate.py', + 'lib/iris/fileformats/_pyke_rules/*') try: last_change_by_fname = self.last_change_by_fname() @@ -364,5 +339,65 @@ def test_license_headers(self): raise ValueError('There were license header failures. See stdout.') +class TestFutureImports(tests.IrisTest): + excluded = ( + '*/iris/fileformats/_old_pp_packing.py', + '*/iris/fileformats/_pyke_rules/__init__.py', + '*/iris/fileformats/_pyke_rules/compiled_krb/__init__.py', + '*/iris/fileformats/_pyke_rules/compiled_krb/compiled_pyke_files.py', + '*/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py', + '*/docs/iris/example_code/*/*.py', + '*/docs/iris/src/examples/*/*.py', + '*/docs/iris/src/developers_guide/documenting/*.py', + ) + + future_imports_pattern = re.compile( + r"^from __future__ import \(absolute_import,\s*division,\s*" + r"print_function(,\s*unicode_literals)?\)$", + flags=re.MULTILINE) + + six_import_pattern = re.compile( + r"^from six.moves import \(filter, input, map, range, zip\) # noqa$", + flags=re.MULTILINE) + + def test_future_imports(self): + # Tests that every single Python file includes the appropriate + # __future__ import to enforce consistent behaviour. + check_paths = [os.path.dirname(iris.__file__)] + if DOCS_DIRS: + check_paths.extend(DOCS_DIRS) + + failed = False + for dirpath, _, files in chain.from_iterable(os.walk(path) + for path in check_paths): + for fname in files: + full_fname = os.path.join(dirpath, fname) + if not full_fname.endswith('.py'): + continue + if not os.path.isfile(full_fname): + continue + if any(fnmatch(full_fname, pat) for pat in self.excluded): + continue + + with open(full_fname, "r") as fh: + content = fh.read() + + if re.search(self.future_imports_pattern, content) is None: + print('The file {} has no valid __future__ imports ' + 'and has not been excluded from the imports ' + 'test.'.format(full_fname)) + failed = True + + if re.search(self.six_import_pattern, content) is None: + print('The file {} has no valid six import ' + 'and has not been excluded from the imports ' + 'test.'.format(full_fname)) + failed = True + + if failed: + raise AssertionError('There were Python 3 compatibility import ' + 'check failures. See stdout.') + + if __name__ == '__main__': - unittest.main() + tests.main() diff --git a/lib/iris/tests/test_concatenate.py b/lib/iris/tests/test_concatenate.py index 6406eafea5..73be435a6b 100644 --- a/lib/iris/tests/test_concatenate.py +++ b/lib/iris/tests/test_concatenate.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -19,6 +19,9 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised # before importing anything else. import iris.tests as tests @@ -26,7 +29,6 @@ import numpy as np import numpy.ma as ma -from iris._concatenate import _CubeSignature as ConcatenateCubeSignature import iris.cube from iris.coords import DimCoord, AuxCoord import iris.tests.stock as stock @@ -215,13 +217,13 @@ def concatenate(cubes, order=None): for cube in result: if ma.isMaskedArray(cube.data): -# cube.data = ma.copy(cube.data, order=order) + # cube.data = ma.copy(cube.data, order=order) data = np.array(cube.data.data, copy=True, order=order) mask = np.array(cube.data.mask, copy=True, order=order) fill_value = cube.data.fill_value cube.data = ma.array(data, mask=mask, fill_value=fill_value) else: -# cube.data = np.copy(cube.data, order=order) + # cube.data = np.copy(cube.data, order=order) cube.data = np.array(cube.data, copy=True, order=order) return result @@ -242,7 +244,7 @@ def test_multi_equal(self): class TestNoConcat(tests.IrisTest): - def test_anonymous(self): + def test_one_cube_has_anon_dim(self): cubes = [] y = (0, 2) cubes.append(_make_cube((0, 2), y, 1)) @@ -307,7 +309,7 @@ def test_uncommon(self): result = concatenate(cubes) self.assertEqual(len(result), 2) - def test_order(self): + def test_order_difference(self): cubes = [] y = (0, 2) cubes.append(_make_cube((0, 2), y, 1)) @@ -315,7 +317,19 @@ def test_order(self): result = concatenate(cubes) self.assertEqual(len(result), 2) - def test_masked_vs_unmasked(self): + +class Test2D(tests.IrisTest): + def test_masked_and_unmasked(self): + cubes = [] + y = (0, 2) + cube = _make_cube((2, 4), y, 2) + cube.data = ma.asarray(cube.data) + cubes.append(cube) + cubes.append(_make_cube((0, 2), y, 1)) + result = concatenate(cubes) + self.assertEqual(len(result), 1) + + def test_unmasked_and_masked(self): cubes = [] y = (0, 2) cubes.append(_make_cube((0, 2), y, 1)) @@ -323,7 +337,7 @@ def test_masked_vs_unmasked(self): cube.data = ma.asarray(cube.data) cubes.append(cube) result = concatenate(cubes) - self.assertEqual(len(result), 2) + self.assertEqual(len(result), 1) def test_masked_fill_value(self): cubes = [] @@ -337,10 +351,8 @@ def test_masked_fill_value(self): cube.data.fill_value = 20 cubes.append(cube) result = concatenate(cubes) - self.assertEqual(len(result), 2) - + self.assertEqual(len(result), 1) -class Test2D(tests.IrisTest): def test_concat_masked_2x2d(self): cubes = [] y = (0, 2) @@ -381,6 +393,50 @@ def test_concat_masked_2y2d(self): [True, False]], dtype=np.bool) self.assertArrayEqual(result[0].data.mask, mask) + def test_concat_masked_2y2d_with_concrete_and_lazy(self): + cubes = [] + x = (0, 2) + cube = _make_cube(x, (0, 2), 1) + cube.data = np.ma.asarray(cube.data) + cube.data[(0, 1), (0, 1)] = ma.masked + cubes.append(cube) + cube = _make_cube(x, (2, 4), 2) + cube.data = ma.asarray(cube.data) + cube.data[(0, 1), (1, 0)] = ma.masked + cube.data = cube.lazy_data() + cubes.append(cube) + result = concatenate(cubes) + self.assertCML(result, ('concatenate', 'concat_masked_2y2d.cml')) + self.assertEqual(len(result), 1) + self.assertEqual(result[0].shape, (4, 2)) + mask = np.array([[True, False], + [False, True], + [False, True], + [True, False]], dtype=np.bool) + self.assertArrayEqual(result[0].data.mask, mask) + + def test_concat_masked_2y2d_with_lazy_and_concrete(self): + cubes = [] + x = (0, 2) + cube = _make_cube(x, (0, 2), 1) + cube.data = np.ma.asarray(cube.data) + cube.data[(0, 1), (0, 1)] = ma.masked + cube.data = cube.lazy_data() + cubes.append(cube) + cube = _make_cube(x, (2, 4), 2) + cube.data = ma.asarray(cube.data) + cube.data[(0, 1), (1, 0)] = ma.masked + cubes.append(cube) + result = concatenate(cubes) + self.assertCML(result, ('concatenate', 'concat_masked_2y2d.cml')) + self.assertEqual(len(result), 1) + self.assertEqual(result[0].shape, (4, 2)) + mask = np.array([[True, False], + [False, True], + [False, True], + [True, False]], dtype=np.bool) + self.assertArrayEqual(result[0].data.mask, mask) + def test_concat_2x2d(self): cubes = [] y = (0, 2) @@ -867,14 +923,5 @@ def test_concat_3d_mega(self): self.assertEqual(result[0].shape, (8, 8, 8)) -class TestCubeSignatureEquality(tests.IrisTest): - def test_not_implemented(self): - class Terry(object): - pass - sig = ConcatenateCubeSignature(iris.cube.Cube(0)) - self.assertIs(sig.__eq__(Terry()), NotImplemented) - self.assertIs(sig.__ne__(Terry()), NotImplemented) - - if __name__ == "__main__": tests.main() diff --git a/lib/iris/tests/test_constraints.py b/lib/iris/tests/test_constraints.py index 704840b4d5..fd74bf8e53 100644 --- a/lib/iris/tests/test_constraints.py +++ b/lib/iris/tests/test_constraints.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -18,10 +18,15 @@ Test the constrained cube loading mechanism. """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests -import biggus +import datetime import iris import iris.tests.stock as stock @@ -40,8 +45,11 @@ def workaround_pending_1262(cubes): cubes[i] = cube[::-1] +@tests.skip_data class TestSimple(tests.IrisTest): - slices = iris.cube.CubeList(stock.realistic_4d().slices(['grid_latitude', 'grid_longitude'])) + def setUp(self): + names = ['grid_latitude', 'grid_longitude'] + self.slices = iris.cube.CubeList(stock.realistic_4d().slices(names)) def test_constraints(self): constraint = iris.Constraint(model_level_number=10) @@ -52,16 +60,19 @@ def test_constraints(self): sub_list = self.slices.extract(constraint) self.assertEqual(len(sub_list), 2 * 6) - constraint = iris.Constraint(model_level_number=lambda c: ( c > 30 ) | (c <= 3)) + constraint = iris.Constraint( + model_level_number=lambda c: (c > 30) | (c <= 3)) sub_list = self.slices.extract(constraint) self.assertEqual(len(sub_list), 43 * 6) - constraint = iris.Constraint(coord_values={'model_level_number': lambda c: c > 1000}) + constraint = iris.Constraint( + coord_values={'model_level_number': lambda c: c > 1000}) sub_list = self.slices.extract(constraint) self.assertEqual(len(sub_list), 0) constraint = (iris.Constraint(model_level_number=10) & - iris.Constraint(time=347922.)) + iris.Constraint( + time=datetime.datetime(2009, 9, 9, 18, 0))) sub_list = self.slices.extract(constraint) self.assertEqual(len(sub_list), 1) @@ -240,7 +251,7 @@ def test_dual_atomic_constraint(self): self.assertCML(cubes, 'theta_and_theta_10') -@iris.tests.skip_data +@tests.skip_data class TestCubeLoadConstraint(RelaxedConstraintMixin, tests.IrisTest): suffix = 'load_match' @@ -251,7 +262,7 @@ def load_match(self, files, constraints): return cubes -@iris.tests.skip_data +@tests.skip_data class TestCubeListConstraint(RelaxedConstraintMixin, tests.IrisTest): suffix = 'load_match' @@ -262,7 +273,7 @@ def load_match(self, files, constraints): return cubes -@iris.tests.skip_data +@tests.skip_data class TestCubeListStrictConstraint(StrictConstraintMixin, tests.IrisTest): suffix = 'load_strict' @@ -271,7 +282,7 @@ def load_match(self, files, constraints): return cubes -@iris.tests.skip_data +@tests.skip_data class TestCubeExtract(TestMixin, tests.IrisTest): def setUp(self): TestMixin.setUp(self) @@ -325,14 +336,16 @@ def test_non_existant_coordinate(self): self.assertEqual(self.cube.extract(iris.Constraint(wibble=10)), None) -@iris.tests.skip_data +@tests.skip_data class TestConstraints(TestMixin, tests.IrisTest): def test_constraint_expressions(self): rt = repr(self.theta) rl10 = repr(self.level_10) rt_l10 = repr(self.theta & self.level_10) - self.assertEqual(rt_l10, "ConstraintCombination(%s, %s, )" % (rt, rl10)) + expr = 'ConstraintCombination(%s, %s, )' % ( + rt, rl10, '__and__' if six.PY2 else 'and_') + self.assertEqual(expr, rt_l10) def test_string_repr(self): rt = repr(iris.Constraint(SN_AIR_POTENTIAL_TEMPERATURE)) diff --git a/lib/iris/tests/test_coord_api.py b/lib/iris/tests/test_coord_api.py index f2b09f6981..4708e2febb 100644 --- a/lib/iris/tests/test_coord_api.py +++ b/lib/iris/tests/test_coord_api.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -16,15 +16,15 @@ # along with Iris. If not, see . -from __future__ import division +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests -import unittest from xml.dom.minidom import Document -import logging +import cf_units import numpy as np import iris @@ -32,79 +32,14 @@ import iris.coord_systems import iris.coords import iris.exceptions -import iris.unit +from iris._data_manager import DataManager import iris.tests.stock -logger = logging.getLogger('tests') -class TestLazy(unittest.TestCase): - def setUp(self): - # Start with a coord with LazyArray points. - shape = (3, 4) - point_func = lambda: np.arange(12).reshape(shape) - points = iris.aux_factory.LazyArray(shape, point_func) - self.coord = iris.coords.AuxCoord(points=points) - - def _check_lazy(self, coord): - self.assertIsInstance(self.coord._points, iris.aux_factory.LazyArray) - self.assertIsNone(self.coord._points._array) - - def test_nop(self): - self._check_lazy(self.coord) - - def _check_both_lazy(self, new_coord): - # Make sure both coords have an "empty" LazyArray. - self._check_lazy(self.coord) - self._check_lazy(new_coord) - - def test_lazy_slice1(self): - self._check_both_lazy(self.coord[:]) - - def test_lazy_slice2(self): - self._check_both_lazy(self.coord[:, :]) - - def test_lazy_slice3(self): - self._check_both_lazy(self.coord[...]) - - def _check_concrete(self, new_coord): - # Taking a genuine subset slice should trigger the evaluation - # of the original LazyArray, and result in a normal ndarray for - # the new coord. - self.assertIsInstance(self.coord._points, iris.aux_factory.LazyArray) - self.assertIsInstance(self.coord._points._array, np.ndarray) - self.assertIsInstance(new_coord._points, np.ndarray) - - def test_concrete_slice1(self): - self._check_concrete(self.coord[0]) - - def test_concrete_slice2(self): - self._check_concrete(self.coord[0, :]) - - def test_shape(self): - # Checking the shape shouldn't trigger a lazy load. - self.assertEqual(self.coord.shape, (3, 4)) - self._check_lazy(self.coord) - - def _check_shared_data(self, coord): - # Updating the original coord's points should update the sliced - # coord's points too. - points = coord.points - new_points = coord[:].points - np.testing.assert_array_equal(points, new_points) - points[0, 0] = 999 - self.assertEqual(points[0, 0], new_points[0, 0]) - - def test_concrete_shared_data(self): - coord = iris.coords.AuxCoord(np.arange(12).reshape((3, 4))) - self._check_shared_data(coord) - - def test_lazy_shared_data(self): - self._check_shared_data(self.coord) - - -class TestCoordSlicing(unittest.TestCase): +@tests.skip_data +class TestCoordSlicing(tests.IrisTest): def setUp(self): cube = iris.tests.stock.realistic_4d() self.lat = cube.coord('grid_latitude') @@ -205,6 +140,7 @@ def test_no_intersection_on_unit(self): self.a.units = 'kilometer' self.assertRaises(ValueError, self.a.intersect, self.b) + @tests.skip_data def test_commutative(self): cube = iris.tests.stock.realistic_4d() coord = cube.coord('grid_longitude') @@ -230,6 +166,7 @@ def test_complex(self): self.assertXMLElement(coord, ('coord_api', 'complex.xml')) +@tests.skip_data class TestCoord_ReprStr_nontime(tests.IrisTest): def setUp(self): self.lat = iris.tests.stock.realistic_4d().coord('grid_latitude')[:10] @@ -251,6 +188,7 @@ def test_AuxCoord_str(self): ('coord_api', 'str_repr', 'aux_nontime_str.txt')) +@tests.skip_data class TestCoord_ReprStr_time(tests.IrisTest): def setUp(self): self.time = iris.tests.stock.realistic_4d().coord('time') @@ -272,34 +210,43 @@ def test_AuxCoord_str(self): ('coord_api', 'str_repr', 'aux_time_str.txt')) -class TestAuxCoordCreation(unittest.TestCase): +class TestAuxCoordCreation(tests.IrisTest): def test_basic(self): - a = iris.coords.AuxCoord(range(10), 'air_temperature', units='kelvin') + a = iris.coords.AuxCoord(np.arange(10), 'air_temperature', + units='kelvin') result = "AuxCoord(array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), standard_name='air_temperature', units=Unit('kelvin'))" self.assertEqual(result, str(a)) - b = iris.coords.AuxCoord(range(10), attributes={'monty': 'python'}) + b = iris.coords.AuxCoord(list(range(10)), + attributes={'monty': 'python'}) result = "AuxCoord(array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), standard_name=None, units=Unit('1'), attributes={'monty': 'python'})" self.assertEqual(result, str(b)) def test_excluded_attributes(self): with self.assertRaises(ValueError): - iris.coords.AuxCoord(range(10), 'air_temperature', units='kelvin', attributes={'standard_name': 'whoopsy'}) + iris.coords.AuxCoord(np.arange(10), 'air_temperature', + units='kelvin', + attributes={'standard_name': 'whoopsy'}) - a = iris.coords.AuxCoord(range(10), 'air_temperature', units='kelvin') + a = iris.coords.AuxCoord(np.arange(10), 'air_temperature', + units='kelvin') with self.assertRaises(ValueError): a.attributes['standard_name'] = 'whoopsy' with self.assertRaises(ValueError): a.attributes.update({'standard_name': 'whoopsy'}) def test_coord_system(self): - a = iris.coords.AuxCoord(range(10), 'air_temperature', units='kelvin', coord_system=iris.coord_systems.GeogCS(6000)) + a = iris.coords.AuxCoord(np.arange(10), 'air_temperature', + units='kelvin', + coord_system=iris.coord_systems.GeogCS(6000)) result = "AuxCoord(array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), standard_name='air_temperature', units=Unit('kelvin'), "\ "coord_system=GeogCS(6000.0))" self.assertEqual(result, str(a)) def test_bounded(self): - a = iris.coords.AuxCoord(range(10), 'air_temperature', units='kelvin', bounds=np.arange(0, 20).reshape(10, 2)) + a = iris.coords.AuxCoord(np.arange(10), 'air_temperature', + units='kelvin', + bounds=np.arange(0, 20).reshape(10, 2)) result = ("AuxCoord(array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])" ", bounds=array([[ 0, 1],\n [ 2, 3],\n [ 4, 5],\n [ 6, 7],\n [ 8, 9],\n "\ "[10, 11],\n [12, 13],\n [14, 15],\n [16, 17],\n [18, 19]])" @@ -321,34 +268,43 @@ def test_AuxCoord_fromcoord(self): self.assertIsNot(a.coord_system, b.coord_system) -class TestDimCoordCreation(unittest.TestCase): +class TestDimCoordCreation(tests.IrisTest): def test_basic(self): - a = iris.coords.DimCoord(range(10), 'air_temperature', units='kelvin') + a = iris.coords.DimCoord(np.arange(10), 'air_temperature', + units='kelvin') result = "DimCoord(array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), standard_name='air_temperature', units=Unit('kelvin'))" self.assertEqual(result, str(a)) - b = iris.coords.DimCoord(range(10), attributes={'monty': 'python'}) + b = iris.coords.DimCoord(list(range(10)), + attributes={'monty': 'python'}) result = "DimCoord(array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), standard_name=None, units=Unit('1'), attributes={'monty': 'python'})" self.assertEqual(result, str(b)) def test_excluded_attributes(self): with self.assertRaises(ValueError): - iris.coords.DimCoord(range(10), 'air_temperature', units='kelvin', attributes={'standard_name': 'whoopsy'}) + iris.coords.DimCoord(np.arange(10), 'air_temperature', + units='kelvin', + attributes={'standard_name': 'whoopsy'}) - a = iris.coords.DimCoord(range(10), 'air_temperature', units='kelvin') + a = iris.coords.DimCoord(np.arange(10), 'air_temperature', + units='kelvin') with self.assertRaises(ValueError): a.attributes['standard_name'] = 'whoopsy' with self.assertRaises(ValueError): a.attributes.update({'standard_name': 'whoopsy'}) def test_coord_system(self): - a = iris.coords.DimCoord(range(10), 'air_temperature', units='kelvin', coord_system=iris.coord_systems.GeogCS(6000)) + a = iris.coords.DimCoord(np.arange(10), 'air_temperature', + units='kelvin', + coord_system=iris.coord_systems.GeogCS(6000)) result = "DimCoord(array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), standard_name='air_temperature', units=Unit('kelvin'), "\ "coord_system=GeogCS(6000.0))" self.assertEqual(result, str(a)) def test_bounded(self): - a = iris.coords.DimCoord(range(10), 'air_temperature', units='kelvin', bounds=np.arange(0, 20).reshape(10, 2)) + a = iris.coords.DimCoord(np.arange(10), 'air_temperature', + units='kelvin', + bounds=np.arange(0, 20).reshape(10, 2)) result = ("DimCoord(array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])" ", bounds=array([[ 0, 1],\n [ 2, 3],\n [ 4, 5],\n [ 6, 7],\n [ 8, 9],\n "\ "[10, 11],\n [12, 13],\n [14, 15],\n [16, 17],\n [18, 19]])" @@ -358,21 +314,22 @@ def test_bounded(self): def test_dim_coord_restrictions(self): # 1d - with self.assertRaisesRegexp(ValueError, 'must be 1-dim'): - iris.coords.DimCoord([[1,2,3], [4,5,6]]) + with self.assertRaisesRegexp(ValueError, 'must be scalar or 1-dim'): + iris.coords.DimCoord([[1, 2, 3], [4, 5, 6]]) # monotonic with self.assertRaisesRegexp(ValueError, 'must be strictly monotonic'): - iris.coords.DimCoord([1,2,99,4,5]) + iris.coords.DimCoord([1, 2, 99, 4, 5]) # monotonic bounds with self.assertRaisesRegexp(ValueError, 'monotonicity.*consistent.*all bounds'): - iris.coords.DimCoord([1,2,3], bounds=[[1, 12], [2, 9], [3, 6]]) + iris.coords.DimCoord([1, 2, 3], bounds=[[1, 12], [2, 9], [3, 6]]) # shapes of points and bounds - with self.assertRaisesRegexp(ValueError, 'shape of the bounds array'): - iris.coords.DimCoord([1,2,3], bounds=[0.5, 1.5, 2.5, 3.5]) + msg = 'The shape of the bounds array should be' + with self.assertRaisesRegexp(ValueError, msg): + iris.coords.DimCoord([1, 2, 3], bounds=[0.5, 1.5, 2.5, 3.5]) # another example of shapes of points and bounds - with self.assertRaisesRegexp(ValueError, 'shape of the bounds array'): - iris.coords.DimCoord([1,2,3], bounds=[[0.5, 1.5],[1.5, 2.5]]) + with self.assertRaisesRegexp(ValueError, msg): + iris.coords.DimCoord([1, 2, 3], bounds=[[0.5, 1.5], [1.5, 2.5]]) # numeric with self.assertRaises(ValueError): @@ -387,7 +344,7 @@ def test_DimCoord_equality(self): self.assertNotEqual(b, d) def test_Dim_to_Aux(self): - a = iris.coords.DimCoord(range(10), standard_name='air_temperature', long_name='custom air temp', + a = iris.coords.DimCoord(np.arange(10), standard_name='air_temperature', long_name='custom air temp', units='kelvin', attributes={'monty': 'python'}, bounds=np.arange(20).reshape(10, 2), circular=True) b = iris.coords.AuxCoord.from_coord(a) @@ -544,7 +501,7 @@ def create_1d_coord(self, bounds=None, points=None, units='meter'): return coord def test_explicit(self): - orig_coord = self.create_1d_coord(points=range(10), + orig_coord = self.create_1d_coord(points=list(range(10)), bounds=[(b, b+1) for b in range(10)]) coord_expected = self.create_1d_coord(points=5, bounds=[(0, 10)]) @@ -571,73 +528,91 @@ def test_circular_collapse(self): def test_nd_bounds(self): cube = iris.tests.stock.simple_2d_w_multidim_coords(with_bounds=True) - pcube = cube.collapsed(['bar','foo'], iris.analysis.SUM) + pcube = cube.collapsed(['bar', 'foo'], iris.analysis.SUM) pcube.data = pcube.data.astype('i8') self.assertCML(pcube, ("coord_api", "nd_bounds.cml")) +@tests.skip_data class TestGetterSetter(tests.IrisTest): def test_get_set_points_and_bounds(self): cube = iris.tests.stock.realistic_4d() coord = cube.coord("grid_latitude") - + # get bounds bounds = coord.bounds - self.assertEquals(bounds.shape, (100, 2)) - + self.assertEqual(bounds.shape, (100, 2)) + self.assertEqual(bounds.shape[-1], coord.nbounds) - + # set bounds coord.bounds = bounds + 1 - + np.testing.assert_array_equal(coord.bounds, bounds + 1) # set bounds - different length to existing points with self.assertRaises(ValueError): coord.bounds = bounds[::2, :] - + # set points/bounds to None with self.assertRaises(ValueError): coord.points = None coord.bounds = None - - # set bounds from non-numpy pair - coord._points = None # reset the undelying shape of the coordinate + + # set bounds from non-numpy pair. + # First reset the underlying shape of the coordinate. + coord._points_dm = DataManager(1) coord.points = 1 coord.bounds = [123, 456] self.assertEqual(coord.shape, (1, )) self.assertEqual(coord.bounds.shape, (1, 2)) - + # set bounds from non-numpy pairs - coord._points = None # reset the undelying shape of the coordinate - coord.points = range(3) + # First reset the underlying shape of the coord's points and bounds. + coord._points_dm = DataManager(np.arange(3)) + coord.bounds = None coord.bounds = [[123, 456], [234, 567], [345, 678]] self.assertEqual(coord.shape, (3, )) self.assertEqual(coord.bounds.shape, (3, 2)) - + class TestGuessBounds(tests.IrisTest): def test_guess_bounds(self): - coord = iris.coords.DimCoord(np.array([0, 10, 20, 30]), long_name="foo", units="1") + coord = iris.coords.DimCoord(np.array([0, 10, 20, 30]), + long_name="foo", units="1") coord.guess_bounds() - self.assertArrayEqual(coord.bounds, np.array([[-5,5], [5,15], [15,25], [25,35]])) - + self.assertArrayEqual(coord.bounds, + np.array([[-5, 5], [5, 15], [15, 25], [25, 35]])) + coord.bounds = None coord.guess_bounds(0.25) - self.assertArrayEqual(coord.bounds, np.array([[-5,5], [5,15], [15,25], [25,35]]) + 2.5) - + self.assertArrayEqual(coord.bounds, + np.array([[-5, 5], + [5, 15], + [15, 25], + [25, 35]]) + 2.5) + coord.bounds = None coord.guess_bounds(0.75) - self.assertArrayEqual(coord.bounds, np.array([[-5,5], [5,15], [15,25], [25,35]]) - 2.5) + self.assertArrayEqual(coord.bounds, + np.array([[-5, 5], + [5, 15], + [15, 25], + [25, 35]]) - 2.5) points = coord.points.copy() points[2] = 25 coord.points = points coord.bounds = None coord.guess_bounds() - self.assertArrayEqual(coord.bounds, np.array([[-5.,5.], [5.,17.5], [17.5,27.5], [27.5,32.5]])) - + self.assertArrayEqual(coord.bounds, + np.array([[-5., 5.], + [5., 17.5], + [17.5, 27.5], + [27.5, 32.5]])) + # if the points are not monotonic, then guess_bounds should fail + points = coord.points.copy() points[2] = 32 coord = iris.coords.AuxCoord.from_coord(coord) coord.points = points @@ -776,7 +751,7 @@ def test_specified_tol(self): class TestCoordCompatibility(tests.IrisTest): def setUp(self): - self.aux_coord = iris.coords.AuxCoord([1., 2. ,3.], + self.aux_coord = iris.coords.AuxCoord([1., 2., 3.], standard_name='longitude', var_name='lon', units='degrees') @@ -817,7 +792,7 @@ def test_compatible(self): r.var_name = 'foo' self.assertTrue(self.aux_coord.is_compatible(r)) # With/without bounds. - r.bounds = np.array([[0.5, 1.5],[1.5, 2.5],[2.5, 3.5]]) + r.bounds = np.array([[0.5, 1.5], [1.5, 2.5], [2.5, 3.5]]) self.assertTrue(self.aux_coord.is_compatible(r)) def test_circular(self): diff --git a/lib/iris/tests/test_coord_categorisation.py b/lib/iris/tests/test_coord_categorisation.py index c9d6a8f25c..5559b8b1c8 100644 --- a/lib/iris/tests/test_coord_categorisation.py +++ b/lib/iris/tests/test_coord_categorisation.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -18,11 +18,15 @@ Test the coordinate categorisation functions. """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests import warnings +import cf_units import numpy as np import iris @@ -61,7 +65,7 @@ def setUp(self): time_coord = iris.coords.DimCoord( day_numbers, standard_name='time', - units=iris.unit.Unit('days since epoch', 'gregorian')) + units=cf_units.Unit('days since epoch', 'gregorian')) cube.add_dim_coord(time_coord, 0) self.cube = cube @@ -87,14 +91,14 @@ def test_explicit_result_names(self): with warnings.catch_warnings(record=True): func(cube, 'time', **kwargs) result_coords = cube.coords(result_name) - self.assertEqual(len(result_coords), 1, fmt.format(func.func_name)) + self.assertEqual(len(result_coords), 1, fmt.format(func.__name__)) # Specify source coordinate by coordinate reference cube = self.cube.copy() time = cube.coord('time') with warnings.catch_warnings(record=True): func(cube, time, **kwargs) result_coords = cube.coords(result_name) - self.assertEqual(len(result_coords), 1, fmt.format(func.func_name)) + self.assertEqual(len(result_coords), 1, fmt.format(func.__name__)) def test_basic(self): cube = self.cube diff --git a/lib/iris/tests/test_coordsystem.py b/lib/iris/tests/test_coordsystem.py index dffb12ff0d..5aef363533 100644 --- a/lib/iris/tests/test_coordsystem.py +++ b/lib/iris/tests/test_coordsystem.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -16,28 +16,23 @@ # along with Iris. If not, see . -from __future__ import division +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests -import logging -import cartopy.crs -import numpy as np +import cartopy.crs as ccrs +import cf_units import iris.cube import iris.coords -import iris.plot as iplt import iris.tests.stock -import iris.unit from iris.coord_systems import * -logger = logging.getLogger('tests') - - def osgb(): return TransverseMercator(latitude_of_projection_origin=49, longitude_of_central_meridian=-2, false_easting=-400, false_northing=100, @@ -45,6 +40,12 @@ def osgb(): ellipsoid=GeogCS(6377563.396, 6356256.909)) +def stereo(): + return Stereographic(central_lat=-90, central_lon=-45, + false_easting=100, false_northing=200, + ellipsoid=GeogCS(6377563.396, 6356256.909)) + + class TestCoordSystemLookup(tests.IrisTest): def setUp(self): self.cube = iris.tests.stock.lat_lon_cube() @@ -88,7 +89,7 @@ def setUp(self): def test_simple(self): a = self.cs1 b = self.cs2 - self.assertEquals(a, b) + self.assertEqual(a, b) def test_different_class(self): a = self.cs1 @@ -108,7 +109,7 @@ def test_different_public_attributes(self): # a and b should be the same b.foo = 'a' - self.assertEquals(a, b) + self.assertEqual(a, b) b.foo = 'b' # a and b should not be the same @@ -183,9 +184,9 @@ class Test_GeogCS_as_cartopy_crs(tests.IrisTest): def test_as_cartopy_crs(self): cs = GeogCS(6543210, 6500000) res = cs.as_cartopy_crs() - globe = cartopy.crs.Globe(semimajor_axis=6543210.0, - semiminor_axis=6500000.0, ellipse=None) - expected = cartopy.crs.Geodetic(globe) + globe = ccrs.Globe(semimajor_axis=6543210.0, + semiminor_axis=6500000.0, ellipse=None) + expected = ccrs.Geodetic(globe) self.assertEqual(res, expected) @@ -266,14 +267,14 @@ def test_as_cartopy_crs(self): scale_factor_at_central_meridian, ellipsoid=ellipsoid) - expected = cartopy.crs.TransverseMercator( + expected = ccrs.TransverseMercator( central_longitude=longitude_of_central_meridian, central_latitude=latitude_of_projection_origin, false_easting=false_easting, false_northing=false_northing, scale_factor=scale_factor_at_central_meridian, - globe=cartopy.crs.Globe(semimajor_axis=6377563.396, - semiminor_axis=6356256.909, ellipse=None)) + globe=ccrs.Globe(semimajor_axis=6377563.396, + semiminor_axis=6356256.909, ellipse=None)) res = tmerc_cs.as_cartopy_crs() self.assertEqual(res, expected) @@ -297,21 +298,83 @@ def test_as_cartopy_projection(self): scale_factor_at_central_meridian, ellipsoid=ellipsoid) - expected = cartopy.crs.TransverseMercator( + expected = ccrs.TransverseMercator( central_longitude=longitude_of_central_meridian, central_latitude=latitude_of_projection_origin, false_easting=false_easting, false_northing=false_northing, scale_factor=scale_factor_at_central_meridian, - globe=cartopy.crs.Globe(semimajor_axis=6377563.396, - semiminor_axis=6356256.909, ellipse=None)) + globe=ccrs.Globe(semimajor_axis=6377563.396, + semiminor_axis=6356256.909, ellipse=None)) res = tmerc_cs.as_cartopy_projection() self.assertEqual(res, expected) +class Test_Stereographic_construction(tests.IrisTest): + def test_stereo(self): + st = stereo() + self.assertXMLElement(st, ("coord_systems", "Stereographic.xml")) + + +class Test_Stereographic_repr(tests.IrisTest): + def test_stereo(self): + st = stereo() + expected = "Stereographic(central_lat=-90.0, central_lon=-45.0, "\ + "false_easting=100.0, false_northing=200.0, true_scale_lat=None, "\ + "ellipsoid=GeogCS(semi_major_axis=6377563.396, semi_minor_axis=6356256.909))" + self.assertEqual(expected, repr(st)) + + +class Test_Stereographic_as_cartopy_crs(tests.IrisTest): + def test_as_cartopy_crs(self): + latitude_of_projection_origin=-90.0 + longitude_of_projection_origin=-45.0 + false_easting=100.0 + false_northing=200.0 + ellipsoid=GeogCS(6377563.396, 6356256.909) + + st = Stereographic(central_lat=latitude_of_projection_origin, + central_lon=longitude_of_projection_origin, + false_easting=false_easting, + false_northing=false_northing, + ellipsoid=ellipsoid) + expected = ccrs.Stereographic( + central_latitude=latitude_of_projection_origin, + central_longitude=longitude_of_projection_origin, + false_easting=false_easting, + false_northing=false_northing, + globe=ccrs.Globe(semimajor_axis=6377563.396, + semiminor_axis=6356256.909, ellipse=None)) + + res = st.as_cartopy_crs() + self.assertEqual(res, expected) -class Test_LambertConformal(tests.GraphicsTest): +class Test_Stereographic_as_cartopy_projection(tests.IrisTest): + def test_as_cartopy_projection(self): + latitude_of_projection_origin=-90.0 + longitude_of_projection_origin=-45.0 + false_easting=100.0 + false_northing=200.0 + ellipsoid=GeogCS(6377563.396, 6356256.909) + + st = Stereographic(central_lat=latitude_of_projection_origin, + central_lon=longitude_of_projection_origin, + false_easting=false_easting, + false_northing=false_northing, + ellipsoid=ellipsoid) + expected = ccrs.Stereographic( + central_latitude=latitude_of_projection_origin, + central_longitude=longitude_of_projection_origin, + false_easting=false_easting, + false_northing=false_northing, + globe=ccrs.Globe(semimajor_axis=6377563.396, + semiminor_axis=6356256.909, ellipse=None)) + + res = st.as_cartopy_projection() + self.assertEqual(res, expected) + +class Test_LambertConformal(tests.GraphicsTest): def test_north_cutoff(self): lcc = LambertConformal(0, 0, secant_latitudes=(30, 60)) ccrs = lcc.as_cartopy_crs() diff --git a/lib/iris/tests/test_cube.py b/lib/iris/tests/test_cube.py index f8f0549e9b..efd1c6a5ec 100644 --- a/lib/iris/tests/test_cube.py +++ b/lib/iris/tests/test_cube.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -15,6 +15,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised before # importing anything else import iris.tests as tests diff --git a/lib/iris/tests/test_cube_to_pp.py b/lib/iris/tests/test_cube_to_pp.py index 655941ed57..46045fb55d 100644 --- a/lib/iris/tests/test_cube_to_pp.py +++ b/lib/iris/tests/test_cube_to_pp.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -15,6 +15,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests @@ -22,16 +25,14 @@ import os import tempfile -import mock +import cf_units import numpy as np -import iris import iris.coords import iris.coord_systems -import iris.fileformats.pp as ff_pp +import iris.fileformats.pp from iris.fileformats.pp import PPField3 -import iris.io -import iris.unit +from iris.tests import mock import iris.tests.pp as pp import iris.util import iris.tests.stock as stock @@ -42,7 +43,7 @@ def itab_callback(cube, field, filename): cube.add_aux_coord(iris.coords.AuxCoord([field.lbexp], long_name='ExperimentNumber(ITAB)', units='no_unit')) -@iris.tests.skip_data +@tests.skip_data class TestPPSave(tests.IrisTest, pp.PPTest): def test_no_forecast_time(self): cube = stock.lat_lon_cube() @@ -87,29 +88,6 @@ def test_pp_save_rules(self): with self.cube_save_test(reference_txt_path, reference_cubes=cubes) as temp_pp_path: iris.save(cubes, temp_pp_path) - def test_user_pp_save_rules(self): - # Test pp save rules with user rules. - - #create a user rules file - user_rules_filename = iris.util.create_temp_filename(suffix='.txt') - try: - with open(user_rules_filename, "wt") as user_rules_file: - user_rules_file.write("IF\ncm.standard_name == 'air_temperature'\nTHEN\npp.lbuser[3] = 9222") - iris.fileformats.pp.add_save_rules(user_rules_filename) - try: - #read pp - in_filename = tests.get_data_path(('PP', 'simple_pp', 'global.pp')) - cubes = iris.load(in_filename, callback=itab_callback) - - reference_txt_path = tests.get_result_path(('cube_to_pp', 'user_rules.txt')) - with self.cube_save_test(reference_txt_path, reference_cubes=cubes) as temp_pp_path: - iris.save(cubes, temp_pp_path) - - finally: - iris.fileformats.pp.reset_save_rules() - finally: - os.remove(user_rules_filename) - def test_pp_append_singles(self): # Test pp append saving - single cubes. @@ -145,7 +123,7 @@ def test_pp_append_lists(self): def add_coords_to_cube_and_test(self, coord1, coord2): # a wrapper for creating arbitrary 2d cross-sections and run pp-saving tests - dataarray = np.arange(16, dtype='>f4').reshape(4,4) + dataarray = np.arange(16, dtype='>f4').reshape(4, 4) cm = iris.cube.Cube(data=dataarray) cm.add_dim_coord(coord1, 0) @@ -191,30 +169,31 @@ def test_non_standard_cross_sections(self): self.add_coords_to_cube_and_test( iris.coords.DimCoord(f.z, long_name='air_pressure', units='hPa', bounds=f.z_bounds), - iris.coords.DimCoord(f.y, standard_name='time', units=iris.unit.Unit('days since 0000-01-01 00:00:00', calendar=iris.unit.CALENDAR_360_DAY), bounds=f.y_bounds)) + iris.coords.DimCoord(f.y, standard_name='time', units=cf_units.Unit('days since 0000-01-01 00:00:00', calendar=cf_units.CALENDAR_360_DAY), bounds=f.y_bounds)) self.add_coords_to_cube_and_test( iris.coords.DimCoord(f.z, standard_name='depth', units='m', bounds=f.z_bounds), - iris.coords.DimCoord(f.y, standard_name='time', units=iris.unit.Unit('days since 0000-01-01 00:00:00', calendar=iris.unit.CALENDAR_360_DAY), bounds=f.y_bounds)) + iris.coords.DimCoord(f.y, standard_name='time', units=cf_units.Unit('days since 0000-01-01 00:00:00', calendar=cf_units.CALENDAR_360_DAY), bounds=f.y_bounds)) def test_365_calendar_export(self): # test for 365 day calendar export cube = stock.simple_pp() - new_unit = iris.unit.Unit('hours since 1970-01-01 00:00:00', - calendar=iris.unit.CALENDAR_365_DAY) + new_unit = cf_units.Unit('hours since 1970-01-01 00:00:00', + calendar=cf_units.CALENDAR_365_DAY) cube.coord('time').units = new_unit + # Add an extra "fill_value" property, as used by the save rules. + cube.fill_value = None pp_field = mock.MagicMock(spec=PPField3) - iris.fileformats.pp._ensure_save_rules_loaded() - iris.fileformats.pp._save_rules.verify(cube, pp_field) + iris.fileformats.pp_save_rules.verify(cube, pp_field) self.assertEqual(pp_field.lbtim.ic, 4) - + class FakePPEnvironment(object): ''' fake a minimal PP environment for use in cross-section coords, as in PP save rules ''' - y = [1,2,3,4] - z = [111,222,333,444] - y_bounds = [[0.9,1.1], [1.9,2.1], [2.9,3.1], [3.9,4.1]] - z_bounds = [[110.9,111.1], [221.9,222.1], [332.9,333.1], [443.9,444.1]] + y = [1, 2, 3, 4] + z = [111, 222, 333, 444] + y_bounds = [[0.9, 1.1], [1.9, 2.1], [2.9, 3.1], [3.9, 4.1]] + z_bounds = [[110.9, 111.1], [221.9, 222.1], [332.9, 333.1], [443.9, 444.1]] def geog_cs(self): """Return a GeogCS for this PPField. @@ -255,7 +234,7 @@ def test_default_coord_system(self): def lbproc_from_pp(self, filename): # Gets the lbproc field from the ppfile pp_file = iris.fileformats.pp.load(filename) - field = pp_file.next() + field = next(pp_file) return field.lbproc def test_pp_save_rules(self): @@ -270,7 +249,8 @@ def test_pp_save_rules(self): iris.save(ll_cube, temp_filename) # Check the lbproc is what we expect - self.assertEquals(self.lbproc_from_pp(temp_filename), iris.fileformats.pp.lbproc_map[process_desc]) + self.assertEqual(self.lbproc_from_pp(temp_filename), + iris.fileformats.pp.lbproc_map[process_desc]) os.remove(temp_filename) @@ -280,7 +260,7 @@ def test_pp_save_rules(self): # Maps lbproc value to the process flags that should be created multiple_map = {sum(bits) : [iris.fileformats.pp.lbproc_map[bit] for bit in bits] for bits in multiple_bit_values} - for lbproc, descriptions in multiple_map.iteritems(): + for lbproc, descriptions in six.iteritems(multiple_map): ll_cube = stock.lat_lon_cube() ll_cube.attributes["ukmo__process_flags"] = descriptions @@ -289,10 +269,11 @@ def test_pp_save_rules(self): iris.save(ll_cube, temp_filename) # Check the lbproc is what we expect - self.assertEquals(self.lbproc_from_pp(temp_filename), lbproc) + self.assertEqual(self.lbproc_from_pp(temp_filename), lbproc) os.remove(temp_filename) - + + @tests.skip_data def test_lbvc(self): cube = stock.realistic_4d_no_derived()[0, :4, ...] @@ -313,15 +294,18 @@ def test_lbvc(self): self.assertEqual(field.lbvc, lbvc) self.assertEqual(field.lblev, lblev) self.assertEqual(field.blev, blev) - - + + def fields_from_cube(cubes): """ Return an iterator of PP fields generated from saving the given cube(s) to a temporary file, and then subsequently loading them again """ with tempfile.NamedTemporaryFile('w+b', suffix='.pp') as tmp_file: - fh = tmp_file.file + if six.PY2: + fh = tmp_file.file + else: + fh = tmp_file iris.save(cubes, fh, saver='pp') # make sure the fh is written to disk, and move it back to the @@ -331,7 +315,7 @@ def fields_from_cube(cubes): fh.seek(0) # load in the saved pp fields and check the appropriate metadata - for field in ff_pp.load(tmp_file.name): + for field in iris.fileformats.pp.load(tmp_file.name): yield field diff --git a/lib/iris/tests/test_ff.py b/lib/iris/tests/test_ff.py index fe0fa60979..65ad14b5f6 100644 --- a/lib/iris/tests/test_ff.py +++ b/lib/iris/tests/test_ff.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -19,39 +19,22 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before # importing anything else import iris.tests as tests import collections -import warnings -import mock import numpy as np import iris -import iris.fileformats.ff as ff +import iris.fileformats._ff as ff import iris.fileformats.pp as pp -_MockField = collections.namedtuple('_MockField', - 'lbext,lblrec,lbnrec,lbpack,lbuser') -_MockLbpack = collections.namedtuple('_MockLbpack', 'n1') - -# PP-field: LBPACK N1 values. -_UNPACKED = 0 -_WGDOS = 1 -_CRAY = 2 -_GRIB = 3 # Not implemented. -_RLE = 4 # Not supported, deprecated FF format. - -# PP-field: LBUSER(1) values. -_REAL = 1 -_INTEGER = 2 -_LOGICAL = 3 # Not implemented. - - class TestFF_HEADER(tests.IrisTest): def test_initialisation(self): self.assertEqual(ff.FF_HEADER[0], ('data_set_format_version', (0,))) @@ -61,7 +44,7 @@ def test_size(self): self.assertEqual(len(ff.FF_HEADER), 31) -@iris.tests.skip_data +@tests.skip_data class TestFFHeader(tests.IrisTest): def setUp(self): self.filename = tests.get_data_path(('FF', 'n48_multi_field')) @@ -126,7 +109,7 @@ def test_shape(self): self.assertEqual(self.ff_header.shape('data'), (2961, -32768)) -@iris.tests.skip_data +@tests.skip_data class TestFF2PP2Cube(tests.IrisTest): def setUp(self): self.filename = tests.get_data_path(('FF', 'n48_multi_field')) @@ -143,8 +126,15 @@ def test_unit_pass_0(self): cube_by_name[standard_name]) self.assertCML(cube, ('FF', filename)) + def test_raw_to_table_count(self): + filename = tests.get_data_path(('FF', 'n48_multi_field_table_count')) + cubes = iris.load_raw(filename) + ff_header = ff.FFHeader(filename) + table_count = ff_header.lookup_table[2] + self.assertEqual(len(cubes), table_count) + -@iris.tests.skip_data +@tests.skip_data class TestFFieee32(tests.IrisTest): def test_iris_loading(self): ff32_fname = tests.get_data_path(('FF', 'n48_multi_field.ieee32')) @@ -159,7 +149,7 @@ def test_iris_loading(self): self.assertEqual(ff32, ff64) -@iris.tests.skip_data +@tests.skip_data class TestFFVariableResolutionGrid(tests.IrisTest): def setUp(self): self.filename = tests.get_data_path(('FF', 'n48_multi_field')) @@ -188,8 +178,8 @@ def setUp(self): self.orig_make_pp_field = pp.make_pp_field - def new_make_pp_field(header_values): - field = self.orig_make_pp_field(header_values) + def new_make_pp_field(header): + field = self.orig_make_pp_field(header) field.stash = self.ff2pp._custom_stash field.bdx = field.bdy = field.bmdi return field @@ -218,102 +208,6 @@ def test_u(self): def test_v(self): self._check_stash('m01s00i003', self.P_grid_x, self.V_grid_y) - def test_unhandled_grid_type(self): - with mock.patch('warnings.warn') as warn_fn: - self._check_stash('m01s00i005', self.P_grid_x, self.P_grid_y) - self.assertIn("Assuming the data is on a P grid.", - warn_fn.call_args[0][0]) - - -class TestFFPayload(tests.IrisTest): - def _test_payload(self, mock_field, expected_depth, expected_type): - with mock.patch('iris.fileformats.ff.FFHeader') as mock_header: - mock_header.return_value = None - ff2pp = ff.FF2PP('Not real') - data_depth, data_type = ff2pp._payload(mock_field) - self.assertEqual(data_depth, expected_depth) - self.assertEqual(data_type, expected_type) - - def test_payload_unpacked_real(self): - mock_field = _MockField(lbext=0, lblrec=100, lbnrec=-1, - lbpack=_MockLbpack(_UNPACKED), - lbuser=[_REAL]) - expected_type = ff._LBUSER_DTYPE_LOOKUP[_REAL].format(word_depth=8) - expected_type = np.dtype(expected_type) - self._test_payload(mock_field, 800, expected_type) - - def test_payload_unpacked_real_ext(self): - mock_field = _MockField(lbext=50, lblrec=100, lbnrec=-1, - lbpack=_MockLbpack(_UNPACKED), - lbuser=[_REAL]) - expected_type = ff._LBUSER_DTYPE_LOOKUP[_REAL].format(word_depth=8) - expected_type = np.dtype(expected_type) - self._test_payload(mock_field, 400, expected_type) - - def test_payload_unpacked_integer(self): - mock_field = _MockField(lbext=0, lblrec=200, lbnrec=-1, - lbpack=_MockLbpack(_UNPACKED), - lbuser=[_INTEGER]) - expected_type = ff._LBUSER_DTYPE_LOOKUP[_INTEGER].format(word_depth=8) - expected_type = np.dtype(expected_type) - self._test_payload(mock_field, 1600, expected_type) - - def test_payload_unpacked_integer_ext(self): - mock_field = _MockField(lbext=100, lblrec=200, lbnrec=-1, - lbpack=_MockLbpack(_UNPACKED), - lbuser=[_INTEGER]) - expected_type = ff._LBUSER_DTYPE_LOOKUP[_INTEGER].format(word_depth=8) - expected_type = np.dtype(expected_type) - self._test_payload(mock_field, 800, expected_type) - - def test_payload_wgdos_real(self): - mock_field = _MockField(lbext=0, lblrec=-1, lbnrec=100, - lbpack=_MockLbpack(_WGDOS), - lbuser=[_REAL]) - self._test_payload(mock_field, 796, pp.LBUSER_DTYPE_LOOKUP[_REAL]) - - def test_payload_wgdos_real_ext(self): - mock_field = _MockField(lbext=50, lblrec=-1, lbnrec=100, - lbpack=_MockLbpack(_WGDOS), - lbuser=[_REAL]) - self._test_payload(mock_field, 796, pp.LBUSER_DTYPE_LOOKUP[_REAL]) - - def test_payload_wgdos_integer(self): - mock_field = _MockField(lbext=0, lblrec=-1, lbnrec=200, - lbpack=_MockLbpack(_WGDOS), - lbuser=[_INTEGER]) - self._test_payload(mock_field, 1596, pp.LBUSER_DTYPE_LOOKUP[_INTEGER]) - - def test_payload_wgdos_integer_ext(self): - mock_field = _MockField(lbext=100, lblrec=-1, lbnrec=200, - lbpack=_MockLbpack(_WGDOS), - lbuser=[_INTEGER]) - self._test_payload(mock_field, 1596, pp.LBUSER_DTYPE_LOOKUP[_INTEGER]) - - def test_payload_cray_real(self): - mock_field = _MockField(lbext=0, lblrec=100, lbnrec=-1, - lbpack=_MockLbpack(_CRAY), - lbuser=[_REAL]) - self._test_payload(mock_field, 400, pp.LBUSER_DTYPE_LOOKUP[_REAL]) - - def test_payload_cray_real_ext(self): - mock_field = _MockField(lbext=50, lblrec=100, lbnrec=-1, - lbpack=_MockLbpack(_CRAY), - lbuser=[_REAL]) - self._test_payload(mock_field, 200, pp.LBUSER_DTYPE_LOOKUP[_REAL]) - - def test_payload_cray_integer(self): - mock_field = _MockField(lbext=0, lblrec=200, lbnrec=-1, - lbpack=_MockLbpack(_CRAY), - lbuser=[_INTEGER]) - self._test_payload(mock_field, 800, pp.LBUSER_DTYPE_LOOKUP[_INTEGER]) - - def test_payload_cray_integer_ext(self): - mock_field = _MockField(lbext=100, lblrec=200, lbnrec=-1, - lbpack=_MockLbpack(_CRAY), - lbuser=[_INTEGER]) - self._test_payload(mock_field, 400, pp.LBUSER_DTYPE_LOOKUP[_INTEGER]) - if __name__ == '__main__': tests.main() diff --git a/lib/iris/tests/test_file_load.py b/lib/iris/tests/test_file_load.py index 5b35d30d1e..11fd5c5f1c 100644 --- a/lib/iris/tests/test_file_load.py +++ b/lib/iris/tests/test_file_load.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -19,12 +19,15 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests import iris -@iris.tests.skip_data +@tests.skip_data class TestFileLoad(tests.IrisTest): def _test_file(self, src_path, reference_filename): """ diff --git a/lib/iris/tests/test_file_save.py b/lib/iris/tests/test_file_save.py index 29c2c7f680..bb8123ff8a 100644 --- a/lib/iris/tests/test_file_save.py +++ b/lib/iris/tests/test_file_save.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -19,10 +19,14 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests -import cStringIO +import io import os import unittest @@ -62,7 +66,7 @@ def save_by_filehandle(filehandle1, filehandle2, cube, fn_saver, binary_mode = T iris.save(cube, outfile) -@iris.tests.skip_data +@tests.skip_data class TestSaveMethods(tests.IrisTest): """ Base class for file saving tests. Loads data and creates/deletes tempfiles""" def setUp(self): @@ -87,14 +91,18 @@ def test_filename(self): save_by_filename(self.temp_filename1, self.temp_filename2, self.cube1, pp.save) # Compare files - self.assertEquals(self.file_checksum(self.temp_filename2), self.file_checksum(self.temp_filename1), CHKSUM_ERR.format(self.ext)) + self.assertEqual(self.file_checksum(self.temp_filename2), + self.file_checksum(self.temp_filename1), + CHKSUM_ERR.format(self.ext)) def test_filehandle(self): # Save using iris.save and pp.save save_by_filehandle(self.temp_filename1, self.temp_filename2, self.cube1, pp.save, binary_mode = True) # Compare files - self.assertEquals(self.file_checksum(self.temp_filename2), self.file_checksum(self.temp_filename1), CHKSUM_ERR.format(self.ext)) + self.assertEqual(self.file_checksum(self.temp_filename2), + self.file_checksum(self.temp_filename1), + CHKSUM_ERR.format(self.ext)) # Check we can't save when file handle is not binary with self.assertRaises(ValueError): @@ -110,33 +118,39 @@ def test_filename(self): save_by_filename(self.temp_filename1, self.temp_filename2, self.cube1, dot.save) # Compare files - self.assertEquals(self.file_checksum(self.temp_filename2), self.file_checksum(self.temp_filename1), CHKSUM_ERR.format(self.ext)) + self.assertEqual(self.file_checksum(self.temp_filename2), + self.file_checksum(self.temp_filename1), + CHKSUM_ERR.format(self.ext)) def test_filehandle(self): # Save using iris.save and dot.save save_by_filehandle(self.temp_filename1, self.temp_filename2, self.cube1, dot.save, binary_mode = False) # Compare files - self.assertEquals(self.file_checksum(self.temp_filename2), self.file_checksum(self.temp_filename1), CHKSUM_ERR.format(self.ext)) + self.assertEqual(self.file_checksum(self.temp_filename2), + self.file_checksum(self.temp_filename1), + CHKSUM_ERR.format(self.ext)) # Check we can't save when file handle is binary with self.assertRaises(ValueError): save_by_filehandle(self.temp_filename1, self.temp_filename2, self.cube1, dot.save, binary_mode = True) - def test_cstringio(self): - string_io = cStringIO.StringIO() + def test_bytesio(self): + sio = six.StringIO() # Save from dot direct dot.save(self.cube1, self.temp_filename1) # Call save on iris - iris.save(self.cube1, string_io, iris.io.find_saver(self.ext)) + iris.save(self.cube1, sio, iris.io.find_saver(self.ext)) with open(self.temp_filename1) as infile: data = infile.read() # Compare files - self.assertEquals(data, string_io.getvalue(), "Mismatch in data when comparing iris cstringio save and dot.save.") + self.assertEquals(data, sio.getvalue(), + 'Mismatch in data when comparing iris bytesio save ' + 'and dot.save.') @skip_dotpng @@ -149,14 +163,18 @@ def test_filename(self): save_by_filename(self.temp_filename1, self.temp_filename2, self.cube1, dot.save_png) # Compare files - self.assertEquals(self.file_checksum(self.temp_filename2), self.file_checksum(self.temp_filename1), CHKSUM_ERR.format(self.ext)) + self.assertEqual(self.file_checksum(self.temp_filename2), + self.file_checksum(self.temp_filename1), + CHKSUM_ERR.format(self.ext)) def test_filehandle(self): # Save using iris.save and dot.save_png save_by_filehandle(self.temp_filename1, self.temp_filename2, self.cube1, dot.save_png, binary_mode = True) # Compare files - self.assertEquals(self.file_checksum(self.temp_filename2), self.file_checksum(self.temp_filename1), CHKSUM_ERR.format(self.ext)) + self.assertEqual(self.file_checksum(self.temp_filename2), + self.file_checksum(self.temp_filename1), + CHKSUM_ERR.format(self.ext)) # Check we can't save when file handle is not binary with self.assertRaises(ValueError): @@ -172,7 +190,9 @@ def test_pp(self): save_by_filename(self.temp_filename1, self.temp_filename2, self.cube1, pp.save, pp_saver) # Compare files - self.assertEquals(self.file_checksum(self.temp_filename2), self.file_checksum(self.temp_filename1), CHKSUM_ERR.format(self.ext)) + self.assertEqual(self.file_checksum(self.temp_filename2), + self.file_checksum(self.temp_filename1), + CHKSUM_ERR.format(self.ext)) def test_dot(self): # Make our own saver @@ -180,7 +200,9 @@ def test_dot(self): save_by_filename(self.temp_filename1, self.temp_filename2, self.cube1, dot.save, dot_saver) # Compare files - self.assertEquals(self.file_checksum(self.temp_filename2), self.file_checksum(self.temp_filename1), CHKSUM_ERR.format(self.ext)) + self.assertEqual(self.file_checksum(self.temp_filename2), + self.file_checksum(self.temp_filename1), + CHKSUM_ERR.format(self.ext)) @skip_dotpng def test_png(self): @@ -189,7 +211,9 @@ def test_png(self): save_by_filename(self.temp_filename1, self.temp_filename2, self.cube1, dot.save_png, png_saver) # Compare files - self.assertEquals(self.file_checksum(self.temp_filename2), self.file_checksum(self.temp_filename1), CHKSUM_ERR.format(self.ext)) + self.assertEqual(self.file_checksum(self.temp_filename2), + self.file_checksum(self.temp_filename1), + CHKSUM_ERR.format(self.ext)) class TestSaveInvalid(TestSaveMethods): """Test iris cannot automatically save to file extensions it does not know about""" diff --git a/lib/iris/tests/test_grib_load.py b/lib/iris/tests/test_grib_load.py deleted file mode 100644 index d4104f812d..0000000000 --- a/lib/iris/tests/test_grib_load.py +++ /dev/null @@ -1,740 +0,0 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . - -# Import iris tests first so that some things can be initialised before -# importing anything else -import iris.tests as tests - -import datetime -import os - -import gribapi -import matplotlib.pyplot as plt -from matplotlib.colors import LogNorm -import mock -import numpy as np - -import iris -import iris.exceptions -import iris.fileformats.grib -import iris.plot as iplt -import iris.quickplot as qplt -import iris.tests.stock -import iris.util - -# Construct a mock object to mimic the gribapi for GribWrapper testing. -_mock_gribapi = mock.Mock(spec=gribapi) -_mock_gribapi.GribInternalError = Exception - - -def _mock_gribapi_fetch(message, key): - """ - Fake the gribapi key-fetch. - - Fetch key-value from the fake message (dictionary). - If the key is not present, raise the diagnostic exception. - - """ - if key in message.keys(): - return message[key] - else: - raise _mock_gribapi.GribInternalError - - -def _mock_gribapi__grib_is_missing(grib_message, keyname): - """ - Fake the gribapi key-existence enquiry. - - Return whether the key exists in the fake message (dictionary). - - """ - return (keyname not in grib_message) - - -def _mock_gribapi__grib_get_native_type(grib_message, keyname): - """ - Fake the gribapi type-discovery operation. - - Return type of key-value in the fake message (dictionary). - If the key is not present, raise the diagnostic exception. - - """ - if keyname in grib_message: - return type(grib_message[keyname]) - raise _mock_gribapi.GribInternalError(keyname) - -_mock_gribapi.grib_get_long = mock.Mock(side_effect=_mock_gribapi_fetch) -_mock_gribapi.grib_get_string = mock.Mock(side_effect=_mock_gribapi_fetch) -_mock_gribapi.grib_get_double = mock.Mock(side_effect=_mock_gribapi_fetch) -_mock_gribapi.grib_get_double_array = mock.Mock( - side_effect=_mock_gribapi_fetch) -_mock_gribapi.grib_is_missing = mock.Mock( - side_effect=_mock_gribapi__grib_is_missing) -_mock_gribapi.grib_get_native_type = mock.Mock( - side_effect=_mock_gribapi__grib_get_native_type) - -# define seconds in an hour, for general test usage -_hour_secs = 3600.0 - - -class FakeGribMessage(dict): - """ - A 'fake grib message' object, for testing GribWrapper construction. - - Behaves as a dictionary, containing key-values for message keys. - - """ - def __init__(self, **kwargs): - """ - Create a fake message object. - - General keys can be set/add as required via **kwargs. - The keys 'edition' and 'time_code' are specially managed. - - """ - # Start with a bare dictionary - dict.__init__(self) - # Extract specially-recognised keys. - edition = kwargs.pop('edition', 1) - time_code = kwargs.pop('time_code', None) - # Set the minimally required keys. - self._init_minimal_message(edition=edition) - # Also set a time-code, if given. - if time_code is not None: - self.set_timeunit_code(time_code) - # Finally, add any remaining passed key-values. - self.update(**kwargs) - - def _init_minimal_message(self, edition=1): - # Set values for all the required keys. - # 'edition' controls the edition-specific keys. - self.update({ - 'Ni': 1, - 'Nj': 1, - 'alternativeRowScanning': 0, - 'centre': 'ecmf', - 'year': 2007, - 'month': 3, - 'day': 23, - 'hour': 12, - 'minute': 0, - 'indicatorOfUnitOfTimeRange': 1, - 'shapeOfTheEarth': 6, - 'gridType': 'rotated_ll', - 'angleOfRotation': 0.0, - 'iDirectionIncrementInDegrees': 0.036, - 'jDirectionIncrementInDegrees': 0.036, - 'iScansNegatively': 0, - 'jScansPositively': 1, - 'longitudeOfFirstGridPointInDegrees': -5.70, - 'latitudeOfFirstGridPointInDegrees': -4.452, - 'jPointsAreConsecutive': 0, - 'values': np.array([[1.0]]), - 'indicatorOfParameter': 9999, - 'parameterNumber': 9999, - }) - # Add edition-dependent settings. - self['edition'] = edition - if edition == 1: - self.update({ - 'startStep': 24, - 'timeRangeIndicator': 1, - 'P1': 2, 'P2': 0, - # time unit - needed AS WELL as 'indicatorOfUnitOfTimeRange' - 'unitOfTime': 1, - 'table2Version': 9999, - }) - if edition == 2: - self.update({ - 'iDirectionIncrementGiven': 1, - 'jDirectionIncrementGiven': 1, - 'uvRelativeToGrid': 0, - 'forecastTime': 24, - 'productDefinitionTemplateNumber': 0, - 'stepRange': 24, - 'discipline': 9999, - 'parameterCategory': 9999, - 'tablesVersion': 4 - }) - - def set_timeunit_code(self, timecode): - # Do timecode setting (somewhat edition-dependent). - self['indicatorOfUnitOfTimeRange'] = timecode - if self['edition'] == 1: - # for some odd reason, GRIB1 code uses *both* of these - # NOTE kludge -- the 2 keys are really the same thing - self['unitOfTime'] = timecode - - -@iris.tests.skip_data -class TestGribLoad(tests.GraphicsTest): - - def setUp(self): - iris.fileformats.grib.hindcast_workaround = True - - def tearDown(self): - iris.fileformats.grib.hindcast_workaround = False - - def test_load(self): - - cubes = iris.load(tests.get_data_path(('GRIB', 'rotated_uk', - "uk_wrongparam.grib1"))) - self.assertCML(cubes, ("grib_load", "rotated.cml")) - - cubes = iris.load(tests.get_data_path(('GRIB', "time_processed", - "time_bound.grib1"))) - self.assertCML(cubes, ("grib_load", "time_bound_grib1.cml")) - - cubes = iris.load(tests.get_data_path(('GRIB', "time_processed", - "time_bound.grib2"))) - self.assertCML(cubes, ("grib_load", "time_bound_grib2.cml")) - - cubes = iris.load(tests.get_data_path(('GRIB', "3_layer_viz", - "3_layer.grib2"))) - cubes = iris.cube.CubeList([cubes[1], cubes[0], cubes[2]]) - self.assertCML(cubes, ("grib_load", "3_layer.cml")) - - def test_load_masked(self): - - gribfile = tests.get_data_path( - ('GRIB', 'missing_values', 'missing_values.grib2')) - cubes = iris.load(gribfile) - self.assertCML(cubes, ('grib_load', 'missing_values_grib2.cml')) - - def test_y_fastest(self): - cubes = iris.load(tests.get_data_path(("GRIB", "y_fastest", - "y_fast.grib2"))) - self.assertCML(cubes, ("grib_load", "y_fastest.cml")) - iplt.contourf(cubes[0]) - plt.gca().coastlines() - plt.title("y changes fastest") - self.check_graphic() - - def test_ij_directions(self): - - def old_compat_load(name): - cube = iris.load(tests.get_data_path(('GRIB', 'ij_directions', - name)))[0] - return [cube] - - cubes = old_compat_load("ipos_jpos.grib2") - self.assertCML(cubes, ("grib_load", "ipos_jpos.cml")) - iplt.contourf(cubes[0]) - plt.gca().coastlines() - plt.title("ipos_jpos cube") - self.check_graphic() - - cubes = old_compat_load("ipos_jneg.grib2") - self.assertCML(cubes, ("grib_load", "ipos_jneg.cml")) - iplt.contourf(cubes[0]) - plt.gca().coastlines() - plt.title("ipos_jneg cube") - self.check_graphic() - - cubes = old_compat_load("ineg_jneg.grib2") - self.assertCML(cubes, ("grib_load", "ineg_jneg.cml")) - iplt.contourf(cubes[0]) - plt.gca().coastlines() - plt.title("ineg_jneg cube") - self.check_graphic() - - cubes = old_compat_load("ineg_jpos.grib2") - self.assertCML(cubes, ("grib_load", "ineg_jpos.cml")) - iplt.contourf(cubes[0]) - plt.gca().coastlines() - plt.title("ineg_jpos cube") - self.check_graphic() - - def test_shape_of_earth(self): - - def old_compat_load(name): - cube = iris.load(tests.get_data_path(('GRIB', 'shape_of_earth', - name)))[0] - return cube - - #pre-defined sphere - cube = old_compat_load("0.grib2") - self.assertCML(cube, ("grib_load", "earth_shape_0.cml")) - - #custom sphere - cube = old_compat_load("1.grib2") - self.assertCML(cube, ("grib_load", "earth_shape_1.cml")) - - #IAU65 oblate sphere - cube = old_compat_load("2.grib2") - self.assertCML(cube, ("grib_load", "earth_shape_2.cml")) - - #custom oblate spheroid (km) - cube = old_compat_load("3.grib2") - self.assertCML(cube, ("grib_load", "earth_shape_3.cml")) - - #IAG-GRS80 oblate spheroid - cube = old_compat_load("4.grib2") - self.assertCML(cube, ("grib_load", "earth_shape_4.cml")) - - #WGS84 - cube = old_compat_load("5.grib2") - self.assertCML(cube, ("grib_load", "earth_shape_5.cml")) - - #pre-defined sphere - cube = old_compat_load("6.grib2") - self.assertCML(cube, ("grib_load", "earth_shape_6.cml")) - - #custom oblate spheroid (m) - cube = old_compat_load("7.grib2") - self.assertCML(cube, ("grib_load", "earth_shape_7.cml")) - - #grib1 - same as grib2 shape 6, above - cube = old_compat_load("global.grib1") - self.assertCML(cube, ("grib_load", "earth_shape_grib1.cml")) - - def test_custom_rules(self): - # Test custom rule evaluation. - # Default behaviour - cube = tests.stock.global_grib2() - self.assertEqual(cube.name(), 'air_temperature') - - # Custom behaviour - temp_path = iris.util.create_temp_filename() - f = open(temp_path, 'w') - f.write('\n'.join(( - 'IF', - 'grib.edition == 2', - 'grib.discipline == 0', - 'grib.parameterCategory == 0', - 'grib.parameterNumber == 0', - 'THEN', - 'CMAttribute("long_name", "customised")', - 'CMAttribute("standard_name", None)'))) - f.close() - iris.fileformats.grib.add_load_rules(temp_path) - cube = tests.stock.global_grib2() - self.assertEqual(cube.name(), 'customised') - os.remove(temp_path) - - # Back to default - iris.fileformats.grib.reset_load_rules() - cube = tests.stock.global_grib2() - self.assertEqual(cube.name(), 'air_temperature') - - def test_polar_stereo_grib1(self): - cube = iris.load_cube(tests.get_data_path( - ("GRIB", "polar_stereo", "ST4.2013052210.01h"))) - self.assertCML(cube, ("grib_load", "polar_stereo_grib1.cml")) - qplt.contourf(cube, norm=LogNorm()) - plt.gca().coastlines() - plt.gca().gridlines() - plt.title("polar stereo grib1") - self.check_graphic() - - def test_polar_stereo_grib2(self): - cube = iris.load_cube(tests.get_data_path( - ("GRIB", "polar_stereo", - "CMC_glb_TMP_ISBL_1015_ps30km_2013052000_P006.grib2"))) - self.assertCML(cube, ("grib_load", "polar_stereo_grib2.cml")) - - qplt.contourf(cube) - plt.gca().coastlines() - plt.gca().gridlines() - plt.title("polar stereo grib2") - self.check_graphic() - - def test_lambert_grib1(self): - cube = iris.load_cube(tests.get_data_path( - ("GRIB", "lambert", "lambert.grib1"))) - self.assertCML(cube, ("grib_load", "lambert_grib1.cml")) - - qplt.contourf(cube) - plt.gca().coastlines() - plt.gca().gridlines() - plt.title("lambert grib1") - self.check_graphic() - - def test_lambert_grib2(self): - cube = iris.load_cube(tests.get_data_path( - ("GRIB", "lambert", "lambert.grib2"))) - self.assertCML(cube, ("grib_load", "lambert_grib2.cml")) - - qplt.contourf(cube) - plt.gca().coastlines() - plt.gca().gridlines() - plt.title("lambert grib2") - self.check_graphic() - - def test_regular_gg_grib1(self): - cube = iris.load_cube(tests.get_data_path( - ('GRIB', 'gaussian', 'regular_gg.grib1'))) - self.assertCML(cube, ('grib_load', 'regular_gg_grib1.cml')) - - def test_regular_gg_grib2(self): - cube = iris.load_cube(tests.get_data_path( - ('GRIB', 'gaussian', 'regular_gg.grib2'))) - self.assertCML(cube, ('grib_load', 'regular_gg_grib2.cml')) - - def test_reduced_ll(self): - cube = iris.load_cube(tests.get_data_path( - ("GRIB", "reduced", "reduced_ll.grib1"))) - self.assertCML(cube, ("grib_load", "reduced_ll_grib1.cml")) - - def test_reduced_gg(self): - cube = iris.load_cube(tests.get_data_path( - ("GRIB", "reduced", "reduced_gg.grib2"))) - self.assertCML(cube, ("grib_load", "reduced_gg_grib2.cml")) - - def test_reduced_missing(self): - cube = iris.load_cube(tests.get_data_path( - ("GRIB", "reduced", "reduced_ll_missing.grib1"))) - self.assertCML(cube, ("grib_load", "reduced_ll_missing_grib1.cml")) - - -class TestGribTimecodes(tests.GraphicsTest): - def _run_timetests(self, test_set): - # Check the unit-handling for given units-codes and editions. - - # Operates on lists of cases for various time-units and grib-editions. - # Format: (edition, code, expected-exception, - # equivalent-seconds, description-string) - with mock.patch('iris.fileformats.grib.gribapi', _mock_gribapi): - for test_controls in test_set: - ( - grib_edition, timeunit_codenum, - expected_error, - timeunit_secs, timeunit_str - ) = test_controls - - # Construct a suitable fake test message. - message = FakeGribMessage( - edition=grib_edition, - time_code=timeunit_codenum - ) - - if expected_error: - # Expect GribWrapper construction to fail. - with self.assertRaises(type(expected_error)) as ar_context: - msg = iris.fileformats.grib.GribWrapper(message) - self.assertEqual( - ar_context.exception.args, - expected_error.args) - continue - - # 'ELSE'... - # Expect the wrapper construction to work. - # Make a GribWrapper object and test it. - wrapped_msg = iris.fileformats.grib.GribWrapper(message) - - # Check the units string. - forecast_timeunit = wrapped_msg._forecastTimeUnit - self.assertEqual( - forecast_timeunit, timeunit_str, - 'Bad unit string for edition={ed:01d}, ' - 'unitcode={code:01d} : ' - 'expected="{wanted}" GOT="{got}"'.format( - ed=grib_edition, - code=timeunit_codenum, - wanted=timeunit_str, - got=forecast_timeunit - ) - ) - - # Check the data-starttime calculation. - interval_start_to_end = ( - wrapped_msg._phenomenonDateTime - - wrapped_msg._referenceDateTime - ) - if grib_edition == 1: - interval_from_units = wrapped_msg.P1 - else: - interval_from_units = wrapped_msg.forecastTime - interval_from_units *= datetime.timedelta(0, timeunit_secs) - self.assertEqual( - interval_start_to_end, interval_from_units, - 'Inconsistent start time offset for edition={ed:01d}, ' - 'unitcode={code:01d} : ' - 'from-unit="{unit_str}" ' - 'from-phenom-minus-ref="{e2e_str}"'.format( - ed=grib_edition, - code=timeunit_codenum, - unit_str=interval_from_units, - e2e_str=interval_start_to_end - ) - ) - - # Test groups of testcases for various time-units and grib-editions. - # Format: (edition, code, expected-exception, - # equivalent-seconds, description-string) - def test_timeunits_common(self): - tests = ( - (1, 0, None, 60.0, 'minutes'), - (1, 1, None, _hour_secs, 'hours'), - (1, 2, None, 24.0 * _hour_secs, 'days'), - (1, 10, None, 3.0 * _hour_secs, '3 hours'), - (1, 11, None, 6.0 * _hour_secs, '6 hours'), - (1, 12, None, 12.0 * _hour_secs, '12 hours'), - ) - TestGribTimecodes._run_timetests(self, tests) - - @staticmethod - def _err_bad_timeunit(code): - return iris.exceptions.NotYetImplementedError( - 'Unhandled time unit for forecast ' - 'indicatorOfUnitOfTimeRange : {code}'.format(code=code) - ) - - def test_timeunits_grib1_specific(self): - tests = ( - (1, 13, None, 0.25 * _hour_secs, '15 minutes'), - (1, 14, None, 0.5 * _hour_secs, '30 minutes'), - (1, 254, None, 1.0, 'seconds'), - (1, 111, TestGribTimecodes._err_bad_timeunit(111), 1.0, '??'), - ) - TestGribTimecodes._run_timetests(self, tests) - - def test_timeunits_grib2_specific(self): - tests = ( - (2, 13, None, 1.0, 'seconds'), - # check the extra grib1 keys FAIL - (2, 14, TestGribTimecodes._err_bad_timeunit(14), 0.0, '??'), - (2, 254, TestGribTimecodes._err_bad_timeunit(254), 0.0, '??'), - ) - TestGribTimecodes._run_timetests(self, tests) - - def test_timeunits_calendar(self): - tests = ( - (1, 3, TestGribTimecodes._err_bad_timeunit(3), 0.0, 'months'), - (1, 4, TestGribTimecodes._err_bad_timeunit(4), 0.0, 'years'), - (1, 5, TestGribTimecodes._err_bad_timeunit(5), 0.0, 'decades'), - (1, 6, TestGribTimecodes._err_bad_timeunit(6), 0.0, '30 years'), - (1, 7, TestGribTimecodes._err_bad_timeunit(7), 0.0, 'centuries'), - ) - TestGribTimecodes._run_timetests(self, tests) - - def test_timeunits_invalid(self): - tests = ( - (1, 111, TestGribTimecodes._err_bad_timeunit(111), 1.0, '??'), - (2, 27, TestGribTimecodes._err_bad_timeunit(27), 1.0, '??'), - ) - TestGribTimecodes._run_timetests(self, tests) - - def test_load_probability_forecast(self): - # Test GribWrapper interpretation of PDT 4.9 data. - # NOTE: - # Currently Iris has only partial support for PDT 4.9. - # Though it can load the data, key metadata (thresholds) is lost. - # At present, we are not testing for this. - - # Make a testing grib message in memory, with gribapi. - grib_message = gribapi.grib_new_from_samples('GRIB2') - gribapi.grib_set_long(grib_message, 'productDefinitionTemplateNumber', - 9) - gribapi.grib_set_string(grib_message, 'stepRange', '10-55') - grib_wrapper = iris.fileformats.grib.GribWrapper(grib_message) - - # Check that it captures the statistics time period info. - # (And for now, nothing else) - self.assertEqual( - grib_wrapper._referenceDateTime, - datetime.datetime(year=2007, month=03, day=23, - hour=12, minute=0, second=0) - ) - self.assertEqual( - grib_wrapper._periodStartDateTime, - datetime.datetime(year=2007, month=03, day=23, - hour=22, minute=0, second=0) - ) - self.assertEqual( - grib_wrapper._periodEndDateTime, - datetime.datetime(year=2007, month=03, day=25, - hour=12, minute=0, second=0) - ) - - def test_warn_unknown_pdts(self): - # Test loading of an unrecognised GRIB Product Definition Template. - - # Get a temporary file by name (deleted afterward by context). - with self.temp_filename() as temp_gribfile_path: - # Write a test grib message to the temporary file. - with open(temp_gribfile_path, 'wb') as temp_gribfile: - grib_message = gribapi.grib_new_from_samples('GRIB2') - # Set the PDT to something unexpected. - gribapi.grib_set_long( - grib_message, 'productDefinitionTemplateNumber', 5) - gribapi.grib_write(grib_message, temp_gribfile) - - # Load the message from the file as a cube. - cube_generator = iris.fileformats.grib.load_cubes( - temp_gribfile_path) - cube = cube_generator.next() - - # Check the cube has an extra "warning" attribute. - self.assertEqual( - cube.attributes['GRIB_LOAD_WARNING'], - 'unsupported GRIB2 ProductDefinitionTemplate: #4.5' - ) - - -class TestGribSimple(tests.IrisTest): - # A testing class that does not need the test data. - def mock_grib(self): - # A mock grib message, with attributes that can't be Mocks themselves. - grib = mock.Mock() - grib.startStep = 0 - grib.phenomenon_points = lambda unit: 3 - grib._forecastTimeUnit = "hours" - grib.productDefinitionTemplateNumber = 0 - # define a level type (NB these 2 are effectively the same) - grib.levelType = 1 - grib.typeOfFirstFixedSurface = 1 - grib.typeOfSecondFixedSurface = 1 - return grib - - def cube_from_message(self, grib): - # Parameter translation now uses the GribWrapper, so we must convert - # the Mock-based fake message to a FakeGribMessage. - with mock.patch('iris.fileformats.grib.gribapi', _mock_gribapi): - grib_message = FakeGribMessage(**grib.__dict__) - wrapped_msg = iris.fileformats.grib.GribWrapper(grib_message) - cube, _, _ = iris.fileformats.rules._make_cube( - wrapped_msg, iris.fileformats.grib.load_rules.convert) - return cube - - -class TestGrib1LoadPhenomenon(TestGribSimple): - # Test recognition of grib phenomenon types. - def mock_grib(self): - grib = super(TestGrib1LoadPhenomenon, self).mock_grib() - grib.edition = 1 - return grib - - def test_grib1_unknownparam(self): - grib = self.mock_grib() - grib.table2Version = 0 - grib.indicatorOfParameter = 9999 - cube = self.cube_from_message(grib) - self.assertEqual(cube.standard_name, None) - self.assertEqual(cube.long_name, None) - self.assertEqual(cube.units, iris.unit.Unit("???")) - - def test_grib1_unknown_local_param(self): - grib = self.mock_grib() - grib.table2Version = 128 - grib.indicatorOfParameter = 999 - cube = self.cube_from_message(grib) - self.assertEqual(cube.standard_name, None) - self.assertEqual(cube.long_name, 'UNKNOWN LOCAL PARAM 999.128') - self.assertEqual(cube.units, iris.unit.Unit("???")) - - def test_grib1_unknown_standard_param(self): - grib = self.mock_grib() - grib.table2Version = 1 - grib.indicatorOfParameter = 975 - cube = self.cube_from_message(grib) - self.assertEqual(cube.standard_name, None) - self.assertEqual(cube.long_name, 'UNKNOWN LOCAL PARAM 975.1') - self.assertEqual(cube.units, iris.unit.Unit("???")) - - def known_grib1(self, param, standard_str, units_str): - grib = self.mock_grib() - grib.table2Version = 1 - grib.indicatorOfParameter = param - cube = self.cube_from_message(grib) - self.assertEqual(cube.standard_name, standard_str) - self.assertEqual(cube.long_name, None) - self.assertEqual(cube.units, iris.unit.Unit(units_str)) - - def test_grib1_known_standard_params(self): - # at present, there are just a very few of these - self.known_grib1(11, 'air_temperature', 'kelvin') - self.known_grib1(33, 'x_wind', 'm s-1') - self.known_grib1(34, 'y_wind', 'm s-1') - - -class TestGrib2LoadPhenomenon(TestGribSimple): - # Test recognition of grib phenomenon types. - def mock_grib(self): - grib = super(TestGrib2LoadPhenomenon, self).mock_grib() - grib.edition = 2 - grib._forecastTimeUnit = 'hours' - grib._forecastTime = 0.0 - grib.phenomenon_points = lambda unit: [0.0] - return grib - - def known_grib2(self, discipline, category, param, - standard_name, long_name, units_str): - grib = self.mock_grib() - grib.discipline = discipline - grib.parameterCategory = category - grib.parameterNumber = param - cube = self.cube_from_message(grib) - try: - iris_unit = iris.unit.Unit(units_str) - except ValueError: - iris_unit = iris.unit.Unit('???') - self.assertEqual(cube.standard_name, standard_name) - self.assertEqual(cube.long_name, long_name) - self.assertEqual(cube.units, iris_unit) - - def test_grib2_unknownparam(self): - grib = self.mock_grib() - grib.discipline = 999 - grib.parameterCategory = 999 - grib.parameterNumber = 9999 - cube = self.cube_from_message(grib) - self.assertEqual(cube.standard_name, None) - self.assertEqual(cube.long_name, None) - self.assertEqual(cube.units, iris.unit.Unit("???")) - - def test_grib2_known_standard_params(self): - # check we know how to translate at least these params - # I.E. all the ones the older scheme provided. - full_set = [ - (0, 0, 0, "air_temperature", None, "kelvin"), - (0, 0, 2, "air_potential_temperature", None, "K"), - (0, 1, 0, "specific_humidity", None, "kg kg-1"), - (0, 1, 1, "relative_humidity", None, "%"), - (0, 1, 3, None, "precipitable_water", "kg m-2"), - (0, 1, 22, None, "cloud_mixing_ratio", "kg kg-1"), - (0, 1, 13, "liquid_water_content_of_surface_snow", None, "kg m-2"), - (0, 2, 1, "wind_speed", None, "m s-1"), - (0, 2, 2, "x_wind", None, "m s-1"), - (0, 2, 3, "y_wind", None, "m s-1"), - (0, 2, 8, "lagrangian_tendency_of_air_pressure", None, "Pa s-1"), - (0, 2, 10, "atmosphere_absolute_vorticity", None, "s-1"), - (0, 3, 0, "air_pressure", None, "Pa"), - (0, 3, 1, "air_pressure_at_sea_level", None, "Pa"), - (0, 3, 3, None, "icao_standard_atmosphere_reference_height", "m"), - (0, 3, 5, "geopotential_height", None, "m"), - (0, 3, 9, "geopotential_height_anomaly", None, "m"), - (0, 6, 1, "cloud_area_fraction", None, "%"), - (0, 6, 6, "atmosphere_mass_content_of_cloud_liquid_water", None, - "kg m-2"), - (0, 7, 6, - "atmosphere_specific_convective_available_potential_energy", - None, "J kg-1"), - (0, 7, 7, None, "convective_inhibition", "J kg-1"), - (0, 7, 8, None, "storm_relative_helicity", "J kg-1"), - (0, 14, 0, "atmosphere_mole_content_of_ozone", None, "Dobson"), - (2, 0, 0, "land_area_fraction", None, "1"), - (10, 2, 0, "sea_ice_area_fraction", None, "1")] - - for (discipline, category, number, - standard_name, long_name, units) in full_set: - self.known_grib2(discipline, category, number, - standard_name, long_name, units) - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/test_grib_load_translations.py b/lib/iris/tests/test_grib_load_translations.py new file mode 100644 index 0000000000..dbb6bc8e1f --- /dev/null +++ b/lib/iris/tests/test_grib_load_translations.py @@ -0,0 +1,417 @@ +# (C) British Crown Copyright 2010 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Tests for specific implementation aspects of the grib loaders. + +""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import datetime + +import cf_units +import numpy as np + +import iris +import iris.exceptions +from iris.tests import mock +import iris.tests.stock +import iris.util + +# Run tests in no graphics mode if matplotlib is not available. +if tests.MPL_AVAILABLE: + import matplotlib.pyplot as plt + from matplotlib.colors import LogNorm + import iris.plot as iplt + import iris.quickplot as qplt + +if tests.GRIB_AVAILABLE: + import gribapi + import iris.fileformats + import iris_grib + + +def _mock_gribapi_fetch(message, key): + """ + Fake the gribapi key-fetch. + + Fetch key-value from the fake message (dictionary). + If the key is not present, raise the diagnostic exception. + + """ + if key in message: + return message[key] + else: + raise _mock_gribapi.GribInternalError + + +def _mock_gribapi__grib_is_missing(grib_message, keyname): + """ + Fake the gribapi key-existence enquiry. + + Return whether the key exists in the fake message (dictionary). + + """ + return (keyname not in grib_message) + + +def _mock_gribapi__grib_get_native_type(grib_message, keyname): + """ + Fake the gribapi type-discovery operation. + + Return type of key-value in the fake message (dictionary). + If the key is not present, raise the diagnostic exception. + + """ + if keyname in grib_message: + return type(grib_message[keyname]) + raise _mock_gribapi.GribInternalError(keyname) + + +if tests.GRIB_AVAILABLE: + # Construct a mock object to mimic the gribapi for GribWrapper testing. + _mock_gribapi = mock.Mock(spec=gribapi) + _mock_gribapi.GribInternalError = Exception + + _mock_gribapi.grib_get_long = mock.Mock(side_effect=_mock_gribapi_fetch) + _mock_gribapi.grib_get_string = mock.Mock(side_effect=_mock_gribapi_fetch) + _mock_gribapi.grib_get_double = mock.Mock(side_effect=_mock_gribapi_fetch) + _mock_gribapi.grib_get_double_array = mock.Mock( + side_effect=_mock_gribapi_fetch) + _mock_gribapi.grib_is_missing = mock.Mock( + side_effect=_mock_gribapi__grib_is_missing) + _mock_gribapi.grib_get_native_type = mock.Mock( + side_effect=_mock_gribapi__grib_get_native_type) + +# define seconds in an hour, for general test usage +_hour_secs = 3600.0 + + +class FakeGribMessage(dict): + """ + A 'fake grib message' object, for testing GribWrapper construction. + + Behaves as a dictionary, containing key-values for message keys. + + """ + def __init__(self, **kwargs): + """ + Create a fake message object. + + General keys can be set/add as required via **kwargs. + The keys 'edition' and 'time_code' are specially managed. + + """ + # Start with a bare dictionary + dict.__init__(self) + # Extract specially-recognised keys. + edition = kwargs.pop('edition', 1) + time_code = kwargs.pop('time_code', None) + # Set the minimally required keys. + self._init_minimal_message(edition=edition) + # Also set a time-code, if given. + if time_code is not None: + self.set_timeunit_code(time_code) + # Finally, add any remaining passed key-values. + self.update(**kwargs) + + def _init_minimal_message(self, edition=1): + # Set values for all the required keys. + # 'edition' controls the edition-specific keys. + self.update({ + 'Ni': 1, + 'Nj': 1, + 'numberOfValues': 1, + 'alternativeRowScanning': 0, + 'centre': 'ecmf', + 'year': 2007, + 'month': 3, + 'day': 23, + 'hour': 12, + 'minute': 0, + 'indicatorOfUnitOfTimeRange': 1, + 'shapeOfTheEarth': 6, + 'gridType': 'rotated_ll', + 'angleOfRotation': 0.0, + 'iDirectionIncrementInDegrees': 0.036, + 'jDirectionIncrementInDegrees': 0.036, + 'iScansNegatively': 0, + 'jScansPositively': 1, + 'longitudeOfFirstGridPointInDegrees': -5.70, + 'latitudeOfFirstGridPointInDegrees': -4.452, + 'jPointsAreConsecutive': 0, + 'values': np.array([[1.0]]), + 'indicatorOfParameter': 9999, + 'parameterNumber': 9999, + }) + # Add edition-dependent settings. + self['edition'] = edition + if edition == 1: + self.update({ + 'startStep': 24, + 'timeRangeIndicator': 1, + 'P1': 2, 'P2': 0, + # time unit - needed AS WELL as 'indicatorOfUnitOfTimeRange' + 'unitOfTime': 1, + 'table2Version': 9999, + }) + if edition == 2: + self.update({ + 'iDirectionIncrementGiven': 1, + 'jDirectionIncrementGiven': 1, + 'uvRelativeToGrid': 0, + 'forecastTime': 24, + 'productDefinitionTemplateNumber': 0, + 'stepRange': 24, + 'discipline': 9999, + 'parameterCategory': 9999, + 'tablesVersion': 4 + }) + + def set_timeunit_code(self, timecode): + # Do timecode setting (somewhat edition-dependent). + self['indicatorOfUnitOfTimeRange'] = timecode + if self['edition'] == 1: + # for some odd reason, GRIB1 code uses *both* of these + # NOTE kludge -- the 2 keys are really the same thing + self['unitOfTime'] = timecode + + +@tests.skip_grib +class TestGribTimecodes(tests.IrisTest): + def _run_timetests(self, test_set): + # Check the unit-handling for given units-codes and editions. + + # Operates on lists of cases for various time-units and grib-editions. + # Format: (edition, code, expected-exception, + # equivalent-seconds, description-string) + with mock.patch('iris_grib.gribapi', _mock_gribapi): + for test_controls in test_set: + ( + grib_edition, timeunit_codenum, + expected_error, + timeunit_secs, timeunit_str + ) = test_controls + + # Construct a suitable fake test message. + message = FakeGribMessage( + edition=grib_edition, + time_code=timeunit_codenum + ) + + if expected_error: + # Expect GribWrapper construction to fail. + with self.assertRaises(type(expected_error)) as ar_context: + msg = iris_grib.GribWrapper(message) + self.assertEqual( + ar_context.exception.args, + expected_error.args) + continue + + # 'ELSE'... + # Expect the wrapper construction to work. + # Make a GribWrapper object and test it. + wrapped_msg = iris_grib.GribWrapper(message) + + # Check the units string. + forecast_timeunit = wrapped_msg._forecastTimeUnit + self.assertEqual( + forecast_timeunit, timeunit_str, + 'Bad unit string for edition={ed:01d}, ' + 'unitcode={code:01d} : ' + 'expected="{wanted}" GOT="{got}"'.format( + ed=grib_edition, + code=timeunit_codenum, + wanted=timeunit_str, + got=forecast_timeunit + ) + ) + + # Check the data-starttime calculation. + interval_start_to_end = (wrapped_msg._phenomenonDateTime - + wrapped_msg._referenceDateTime) + if grib_edition == 1: + interval_from_units = wrapped_msg.P1 + else: + interval_from_units = wrapped_msg.forecastTime + interval_from_units *= datetime.timedelta(0, timeunit_secs) + self.assertEqual( + interval_start_to_end, interval_from_units, + 'Inconsistent start time offset for edition={ed:01d}, ' + 'unitcode={code:01d} : ' + 'from-unit="{unit_str}" ' + 'from-phenom-minus-ref="{e2e_str}"'.format( + ed=grib_edition, + code=timeunit_codenum, + unit_str=interval_from_units, + e2e_str=interval_start_to_end + ) + ) + + # Test groups of testcases for various time-units and grib-editions. + # Format: (edition, code, expected-exception, + # equivalent-seconds, description-string) + def test_timeunits_common(self): + tests = ( + (1, 0, None, 60.0, 'minutes'), + (1, 1, None, _hour_secs, 'hours'), + (1, 2, None, 24.0 * _hour_secs, 'days'), + (1, 10, None, 3.0 * _hour_secs, '3 hours'), + (1, 11, None, 6.0 * _hour_secs, '6 hours'), + (1, 12, None, 12.0 * _hour_secs, '12 hours'), + ) + TestGribTimecodes._run_timetests(self, tests) + + @staticmethod + def _err_bad_timeunit(code): + return iris.exceptions.NotYetImplementedError( + 'Unhandled time unit for forecast ' + 'indicatorOfUnitOfTimeRange : {code}'.format(code=code) + ) + + def test_timeunits_grib1_specific(self): + tests = ( + (1, 13, None, 0.25 * _hour_secs, '15 minutes'), + (1, 14, None, 0.5 * _hour_secs, '30 minutes'), + (1, 254, None, 1.0, 'seconds'), + (1, 111, TestGribTimecodes._err_bad_timeunit(111), 1.0, '??'), + ) + TestGribTimecodes._run_timetests(self, tests) + + def test_timeunits_calendar(self): + tests = ( + (1, 3, TestGribTimecodes._err_bad_timeunit(3), 0.0, 'months'), + (1, 4, TestGribTimecodes._err_bad_timeunit(4), 0.0, 'years'), + (1, 5, TestGribTimecodes._err_bad_timeunit(5), 0.0, 'decades'), + (1, 6, TestGribTimecodes._err_bad_timeunit(6), 0.0, '30 years'), + (1, 7, TestGribTimecodes._err_bad_timeunit(7), 0.0, 'centuries'), + ) + TestGribTimecodes._run_timetests(self, tests) + + def test_timeunits_invalid(self): + tests = ( + (1, 111, TestGribTimecodes._err_bad_timeunit(111), 1.0, '??'), + ) + TestGribTimecodes._run_timetests(self, tests) + + def test_warn_unknown_pdts(self): + # Test loading of an unrecognised GRIB Product Definition Template. + + # Get a temporary file by name (deleted afterward by context). + with self.temp_filename() as temp_gribfile_path: + # Write a test grib message to the temporary file. + with open(temp_gribfile_path, 'wb') as temp_gribfile: + grib_message = gribapi.grib_new_from_samples('GRIB2') + # Set the PDT to something unexpected. + gribapi.grib_set_long( + grib_message, 'productDefinitionTemplateNumber', 5) + gribapi.grib_write(grib_message, temp_gribfile) + + # Load the message from the file as a cube. + cube_generator = iris_grib.load_cubes( + temp_gribfile_path) + with self.assertRaises(iris.exceptions.TranslationError) as te: + cube = next(cube_generator) + self.assertEqual('Product definition template [5]' + ' is not supported', str(te.exception)) + + +@tests.skip_grib +class TestGribSimple(tests.IrisTest): + # A testing class that does not need the test data. + def mock_grib(self): + # A mock grib message, with attributes that can't be Mocks themselves. + grib = mock.Mock() + grib.startStep = 0 + grib.phenomenon_points = lambda unit: 3 + grib._forecastTimeUnit = "hours" + grib.productDefinitionTemplateNumber = 0 + # define a level type (NB these 2 are effectively the same) + grib.levelType = 1 + grib.typeOfFirstFixedSurface = 1 + grib.typeOfSecondFixedSurface = 1 + return grib + + def cube_from_message(self, grib): + # Parameter translation now uses the GribWrapper, so we must convert + # the Mock-based fake message to a FakeGribMessage. + with mock.patch('iris_grib.gribapi', _mock_gribapi): + grib_message = FakeGribMessage(**grib.__dict__) + wrapped_msg = iris_grib.GribWrapper(grib_message) + cube, _, _ = iris.fileformats.rules._make_cube( + wrapped_msg, + iris_grib._grib1_load_rules.grib1_convert) + return cube + + +@tests.skip_grib +class TestGrib1LoadPhenomenon(TestGribSimple): + # Test recognition of grib phenomenon types. + def mock_grib(self): + grib = super(TestGrib1LoadPhenomenon, self).mock_grib() + grib.edition = 1 + return grib + + def test_grib1_unknownparam(self): + grib = self.mock_grib() + grib.table2Version = 0 + grib.indicatorOfParameter = 9999 + cube = self.cube_from_message(grib) + self.assertEqual(cube.standard_name, None) + self.assertEqual(cube.long_name, None) + self.assertEqual(cube.units, cf_units.Unit("???")) + + def test_grib1_unknown_local_param(self): + grib = self.mock_grib() + grib.table2Version = 128 + grib.indicatorOfParameter = 999 + cube = self.cube_from_message(grib) + self.assertEqual(cube.standard_name, None) + self.assertEqual(cube.long_name, 'UNKNOWN LOCAL PARAM 999.128') + self.assertEqual(cube.units, cf_units.Unit("???")) + + def test_grib1_unknown_standard_param(self): + grib = self.mock_grib() + grib.table2Version = 1 + grib.indicatorOfParameter = 975 + cube = self.cube_from_message(grib) + self.assertEqual(cube.standard_name, None) + self.assertEqual(cube.long_name, 'UNKNOWN LOCAL PARAM 975.1') + self.assertEqual(cube.units, cf_units.Unit("???")) + + def known_grib1(self, param, standard_str, units_str): + grib = self.mock_grib() + grib.table2Version = 1 + grib.indicatorOfParameter = param + cube = self.cube_from_message(grib) + self.assertEqual(cube.standard_name, standard_str) + self.assertEqual(cube.long_name, None) + self.assertEqual(cube.units, cf_units.Unit(units_str)) + + def test_grib1_known_standard_params(self): + # at present, there are just a very few of these + self.known_grib1(11, 'air_temperature', 'kelvin') + self.known_grib1(33, 'x_wind', 'm s-1') + self.known_grib1(34, 'y_wind', 'm s-1') + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/test_grib_phenomenon_translations.py b/lib/iris/tests/test_grib_phenomenon_translations.py deleted file mode 100644 index e25d9ac1bc..0000000000 --- a/lib/iris/tests/test_grib_phenomenon_translations.py +++ /dev/null @@ -1,162 +0,0 @@ -# (C) British Crown Copyright 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -''' -Created on Apr 26, 2013 - -@author: itpp -''' -# Import iris tests first so that some things can be initialised before -# importing anything else -import iris.tests as itests - -import iris.fileformats.grib.grib_phenom_translation as gptx -import iris.unit - - -class TestGribLookupTableType(itests.IrisTest): - def test_lookuptable_type(self): - ll = gptx.LookupTable([('a', 1), ('b', 2)]) - assert ll['a'] == 1 - assert ll['q'] is None - ll['q'] = 15 - assert ll['q'] == 15 - ll['q'] = 15 - assert ll['q'] == 15 - with self.assertRaises(KeyError): - ll['q'] = 7 - del ll['q'] - ll['q'] = 7 - assert ll['q'] == 7 - - -class TestGribPhenomenonLookup(itests.IrisTest): - def test_grib1_cf_lookup(self): - def check_grib1_cf(param, - standard_name, long_name, units, - height=None, - t2version=128, centre=98, expect_none=False): - iris_units = iris.unit.Unit(units) - cfdata = gptx.grib1_phenom_to_cf_info(param_number=param, - table2_version=t2version, - centre_number=centre) - if expect_none: - self.assertIsNone(cfdata) - else: - self.assertEqual(cfdata.standard_name, standard_name) - self.assertEqual(cfdata.long_name, long_name) - self.assertEqual(cfdata.units, iris_units) - if height is None: - self.assertIsNone(cfdata.set_height) - else: - self.assertEqual(cfdata.set_height, float(height)) - - check_grib1_cf(165, 'x_wind', None, 'm s-1', 10.0) - check_grib1_cf(168, 'dew_point_temperature', None, 'K', 2) - check_grib1_cf(130, 'air_temperature', None, 'K') - check_grib1_cf(235, None, "grib_skin_temperature", "K") - check_grib1_cf(235, None, "grib_skin_temperature", "K", - t2version=9999, expect_none=True) - check_grib1_cf(235, None, "grib_skin_temperature", "K", - centre=9999, expect_none=True) - check_grib1_cf(9999, None, "grib_skin_temperature", "K", - expect_none=True) - - def test_grib2_cf_lookup(self): - def check_grib2_cf(discipline, category, number, - standard_name, long_name, units, - expect_none=False): - iris_units = iris.unit.Unit(units) - cfdata = gptx.grib2_phenom_to_cf_info(param_discipline=discipline, - param_category=category, - param_number=number) - if expect_none: - self.assertIsNone(cfdata) - else: - self.assertEqual(cfdata.standard_name, standard_name) - self.assertEqual(cfdata.long_name, long_name) - self.assertEqual(cfdata.units, iris_units) - - # These should work - check_grib2_cf(0, 0, 2, "air_potential_temperature", None, "K") - check_grib2_cf(0, 19, 1, None, "grib_physical_atmosphere_albedo", "%") - check_grib2_cf(2, 0, 2, "soil_temperature", None, "K") - check_grib2_cf(10, 2, 0, "sea_ice_area_fraction", None, 1) - check_grib2_cf(2, 0, 0, "land_area_fraction", None, 1) - check_grib2_cf(0, 19, 1, None, "grib_physical_atmosphere_albedo", "%") - check_grib2_cf(0, 1, 64, - "atmosphere_mass_content_of_water_vapor", None, - "kg m-2") - check_grib2_cf(2, 0, 7, "surface_altitude", None, "m") - - # These should fail - check_grib2_cf(9999, 2, 0, "sea_ice_area_fraction", None, 1, - expect_none=True) - check_grib2_cf(10, 9999, 0, "sea_ice_area_fraction", None, 1, - expect_none=True) - check_grib2_cf(10, 2, 9999, "sea_ice_area_fraction", None, 1, - expect_none=True) - - def test_cf_grib2_lookup(self): - def check_cf_grib2(standard_name, long_name, - discipline, category, number, units, - expect_none=False): - iris_units = iris.unit.Unit(units) - gribdata = gptx.cf_phenom_to_grib2_info(standard_name, long_name) - if expect_none: - self.assertIsNone(gribdata) - else: - self.assertEqual(gribdata.discipline, discipline) - self.assertEqual(gribdata.category, category) - self.assertEqual(gribdata.number, number) - self.assertEqual(gribdata.units, iris_units) - - # These should work - check_cf_grib2("sea_surface_temperature", None, - 10, 3, 0, 'K') - check_cf_grib2("air_temperature", None, - 0, 0, 0, 'K') - check_cf_grib2("soil_temperature", None, - 2, 0, 2, "K") - check_cf_grib2("land_area_fraction", None, - 2, 0, 0, '1') - check_cf_grib2("land_binary_mask", None, - 2, 0, 0, '1') - check_cf_grib2("atmosphere_mass_content_of_water_vapor", None, - 0, 1, 64, "kg m-2") - check_cf_grib2("surface_altitude", None, - 2, 0, 7, "m") - - # These should fail - check_cf_grib2("air_temperature", "user_long_UNRECOGNISED", - 0, 0, 0, 'K') - check_cf_grib2("air_temperature_UNRECOGNISED", None, - 0, 0, 0, 'K', - expect_none=True) - check_cf_grib2(None, "user_long_UNRECOGNISED", - 0, 0, 0, 'K', - expect_none=True) - check_cf_grib2(None, "precipitable_water", - 0, 1, 3, 'kg m-2') - check_cf_grib2("invalid_unknown", "precipitable_water", - 0, 1, 3, 'kg m-2', - expect_none=True) - check_cf_grib2(None, None, 0, 0, 0, '', - expect_none=True) - - -if __name__ == '__main__': - itests.main() diff --git a/lib/iris/tests/test_grib_save.py b/lib/iris/tests/test_grib_save.py index 0b6baa3829..0befc8d56a 100644 --- a/lib/iris/tests/test_grib_save.py +++ b/lib/iris/tests/test_grib_save.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -15,15 +15,16 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests import os -import warnings import datetime -import gribapi +import cf_units import numpy as np import iris @@ -31,79 +32,88 @@ import iris.coord_systems import iris.coords +if tests.GRIB_AVAILABLE: + import gribapi + from iris_grib._load_convert import _MDI as MDI -@iris.tests.skip_data -class TestLoadSave(tests.IrisTest): - # load and save grib - def setUp(self): - iris.fileformats.grib.hindcast_workaround = True - - def tearDown(self): - iris.fileformats.grib.hindcast_workaround = False - - def save_and_compare(self, source_grib, reference_text): - """Load and save grib data, generate diffs, compare with expected diffs.""" - - # load and save from Iris - cubes = iris.load(source_grib) - - saved_grib = iris.util.create_temp_filename(suffix='.grib2') - iris.save(cubes, saved_grib) +@tests.skip_data +@tests.skip_grib +class TestLoadSave(tests.TestGribMessage): - # missing reference? (the expected diffs between source_grib and saved_grib) - if not os.path.exists(reference_text): - warnings.warn("Creating grib compare reference %s" % reference_text) - os.system("grib_compare %s %s > %s" % (source_grib, saved_grib, reference_text)) - - # generate and compare diffs - compare_text = iris.util.create_temp_filename(suffix='.grib_compare.txt') - os.system("grib_compare %s %s > %s" % (source_grib, saved_grib, compare_text)) - self.assertTextFile(compare_text, reference_text, "grib_compare output") - - os.remove(saved_grib) - os.remove(compare_text) + def setUp(self): + self.skip_keys = [] def test_latlon_forecast_plev(self): source_grib = tests.get_data_path(("GRIB", "uk_t", "uk_t.grib2")) - reference_text = tests.get_result_path(("grib_save", "latlon_forecast_plev.grib_compare.txt")) - self.save_and_compare(source_grib, reference_text) + cubes = iris.load(source_grib) + with self.temp_filename(suffix='.grib2') as temp_file_path: + iris.save(cubes, temp_file_path) + expect_diffs = {'totalLength': (4837, 4832), + 'productionStatusOfProcessedData': (0, 255), + 'scaleFactorOfRadiusOfSphericalEarth': (MDI, + 0), + 'shapeOfTheEarth': (0, 1), + 'scaledValueOfRadiusOfSphericalEarth': (MDI, + 6367470), + 'typeOfGeneratingProcess': (0, 255), + 'generatingProcessIdentifier': (128, 255), + } + self.assertGribMessageDifference(source_grib, temp_file_path, + expect_diffs, self.skip_keys, + skip_sections=[2]) def test_rotated_latlon(self): - source_grib = tests.get_data_path(("GRIB", "rotated_nae_t", "sensible_pole.grib2")) - reference_text = tests.get_result_path(("grib_save", "rotated_latlon.grib_compare.txt")) - # TODO: Investigate small change in test result: - # long [iDirectionIncrement]: [109994] != [109993] - # Consider the change in dx_dy() to "InDegrees" too. - self.save_and_compare(source_grib, reference_text) - -# XXX Addressed in #1118 pending #1039 for hybrid levels -# def test_hybrid_pressure_levels(self): -# source_grib = tests.get_data_path(("GRIB", "ecmwf_standard", "t0.grib2")) -# reference_text = tests.get_result_path(("grib_save", "hybrid_pressure.grib_compare.txt")) -# self.save_and_compare(source_grib, reference_text) + source_grib = tests.get_data_path(("GRIB", "rotated_nae_t", + "sensible_pole.grib2")) + cubes = iris.load(source_grib) + with self.temp_filename(suffix='.grib2') as temp_file_path: + iris.save(cubes, temp_file_path) + expect_diffs = {'totalLength': (648196, 648191), + 'productionStatusOfProcessedData': (0, 255), + 'scaleFactorOfRadiusOfSphericalEarth': (MDI, + 0), + 'shapeOfTheEarth': (0, 1), + 'scaledValueOfRadiusOfSphericalEarth': (MDI, + 6367470), + 'longitudeOfLastGridPoint': (392109982, 32106370), + 'latitudeOfLastGridPoint': (19419996, 19419285), + 'typeOfGeneratingProcess': (0, 255), + 'generatingProcessIdentifier': (128, 255), + } + self.assertGribMessageDifference(source_grib, temp_file_path, + expect_diffs, self.skip_keys, + skip_sections=[2]) def test_time_mean(self): # This test for time-mean fields also tests negative forecast time. - # Because the results depend on the presence of our api patch, - # we currently have results for both a patched and unpatched api. - # If the api ever allows -ve ft, we should revert to a single result. source_grib = tests.get_data_path(("GRIB", "time_processed", "time_bound.grib2")) - reference_text = tests.get_result_path(("grib_save", - "time_mean.grib_compare.txt")) - # TODO: It's not ideal to have grib patch awareness here... - import unittest - try: - self.save_and_compare(source_grib, reference_text) - except unittest.TestCase.failureException: - reference_text = tests.get_result_path(( - "grib_save", - "time_mean.grib_compare.FT_PATCH.txt")) - self.save_and_compare(source_grib, reference_text) - - -@iris.tests.skip_data + cubes = iris.load(source_grib) + expect_diffs = {'totalLength': (21232, 21227), + 'productionStatusOfProcessedData': (0, 255), + 'scaleFactorOfRadiusOfSphericalEarth': (MDI, + 0), + 'shapeOfTheEarth': (0, 1), + 'scaledValueOfRadiusOfSphericalEarth': (MDI, + 6367470), + 'longitudeOfLastGridPoint': (356249908, 356249809), + 'latitudeOfLastGridPoint': (-89999938, -89999944), + 'typeOfGeneratingProcess': (0, 255), + 'generatingProcessIdentifier': (128, 255), + 'typeOfTimeIncrement': (2, 255) + } + self.skip_keys.append('stepType') + self.skip_keys.append('stepTypeInternal') + with self.temp_filename(suffix='.grib2') as temp_file_path: + iris.save(cubes, temp_file_path) + self.assertGribMessageDifference(source_grib, temp_file_path, + expect_diffs, self.skip_keys, + skip_sections=[2]) + + +@tests.skip_data +@tests.skip_grib class TestCubeSave(tests.IrisTest): # save fabricated cubes @@ -141,7 +151,7 @@ def test_non_latlon(self): def test_forecast_period(self): # unhandled unit cube = self._load_basic() - cube.coord("forecast_period").units = iris.unit.Unit("years") + cube.coord("forecast_period").units = cf_units.Unit("years") saved_grib = iris.util.create_temp_filename(suffix='.grib2') self.assertRaises(iris.exceptions.TranslationError, iris.save, cube, saved_grib) os.remove(saved_grib) @@ -190,6 +200,7 @@ def test_bounded_level(self): 1949.0) +@tests.skip_grib class TestHandmade(tests.IrisTest): def _lat_lon_cube_no_time(self): @@ -203,7 +214,7 @@ def _lat_lon_cube_no_time(self): def _cube_time_no_forecast(self): cube = self._lat_lon_cube_no_time() - unit = iris.unit.Unit('hours since epoch', calendar=iris.unit.CALENDAR_GREGORIAN) + unit = cf_units.Unit('hours since epoch', calendar=cf_units.CALENDAR_GREGORIAN) dt = datetime.datetime(2010, 12, 31, 12, 0) cube.add_aux_coord(iris.coords.AuxCoord(np.array([unit.date2num(dt)], dtype=np.float64), 'time', units=unit)) return cube @@ -220,7 +231,7 @@ def _cube_with_pressure(self): def _cube_with_time_bounds(self): cube = self._cube_with_pressure() - cube.coord("time").bounds = np.array([[0,100]]) + cube.coord("time").bounds = np.array([[0, 100]]) return cube def test_no_time_cube(self): diff --git a/lib/iris/tests/test_grib_save_rules.py b/lib/iris/tests/test_grib_save_rules.py index 671ed4f863..3f9a9eeded 100644 --- a/lib/iris/tests/test_grib_save_rules.py +++ b/lib/iris/tests/test_grib_save_rules.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -14,111 +14,79 @@ # # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . -"""Unit tests for iris.fileformats.grib_save_rules""" +"""Integration tests for :mod:`iris_grib._save_rules`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests -import gribapi -import numpy as np -import numpy.ma as ma -import mock import warnings +import cf_units +import numpy as np + import iris.cube import iris.coords -import iris.fileformats.grib.grib_save_rules as grib_save_rules +from iris.tests import mock +if tests.GRIB_AVAILABLE: + import gribapi + import iris_grib._save_rules as grib_save_rules +else: + gribapi = None -class Test_non_hybrid_surfaces(tests.IrisTest): - # Test grib_save_rules.non_hybrid_surfaces() - @mock.patch.object(gribapi, "grib_set_long") - def test_altitude_point(self, mock_set_long): +@tests.skip_grib +class Test_set_fixed_surfaces(tests.IrisTest): + @mock.patch.object(gribapi, "grib_set") + def test_altitude_point(self, mock_set): grib = None - cube = iris.cube.Cube([1,2,3,4,5]) + cube = iris.cube.Cube([1, 2, 3, 4, 5]) cube.add_aux_coord(iris.coords.AuxCoord([12345], "altitude", units="m")) - grib_save_rules.non_hybrid_surfaces(cube, grib) + grib_save_rules.set_fixed_surfaces(cube, grib) - mock_set_long.assert_any_call(grib, "typeOfFirstFixedSurface", 102) - mock_set_long.assert_any_call(grib, "scaleFactorOfFirstFixedSurface", 0) - mock_set_long.assert_any_call(grib, "scaledValueOfFirstFixedSurface", 12345) - mock_set_long.assert_any_call(grib, "typeOfSecondFixedSurface", -1) - mock_set_long.assert_any_call(grib, "scaleFactorOfSecondFixedSurface", 255) - mock_set_long.assert_any_call(grib, "scaledValueOfSecondFixedSurface", -1) + mock_set.assert_any_call(grib, "typeOfFirstFixedSurface", 102) + mock_set.assert_any_call(grib, "scaleFactorOfFirstFixedSurface", 0) + mock_set.assert_any_call(grib, "scaledValueOfFirstFixedSurface", 12345) + mock_set.assert_any_call(grib, "typeOfSecondFixedSurface", -1) + mock_set.assert_any_call(grib, "scaleFactorOfSecondFixedSurface", 255) + mock_set.assert_any_call(grib, "scaledValueOfSecondFixedSurface", -1) - @mock.patch.object(gribapi, "grib_set_long") - def test_height_point(self, mock_set_long): + @mock.patch.object(gribapi, "grib_set") + def test_height_point(self, mock_set): grib = None - cube = iris.cube.Cube([1,2,3,4,5]) + cube = iris.cube.Cube([1, 2, 3, 4, 5]) cube.add_aux_coord(iris.coords.AuxCoord([12345], "height", units="m")) - grib_save_rules.non_hybrid_surfaces(cube, grib) + grib_save_rules.set_fixed_surfaces(cube, grib) - mock_set_long.assert_any_call(grib, "typeOfFirstFixedSurface", 103) - mock_set_long.assert_any_call(grib, "scaleFactorOfFirstFixedSurface", 0) - mock_set_long.assert_any_call(grib, "scaledValueOfFirstFixedSurface", 12345) - mock_set_long.assert_any_call(grib, "typeOfSecondFixedSurface", -1) - mock_set_long.assert_any_call(grib, "scaleFactorOfSecondFixedSurface", 255) - mock_set_long.assert_any_call(grib, "scaledValueOfSecondFixedSurface", -1) + mock_set.assert_any_call(grib, "typeOfFirstFixedSurface", 103) + mock_set.assert_any_call(grib, "scaleFactorOfFirstFixedSurface", 0) + mock_set.assert_any_call(grib, "scaledValueOfFirstFixedSurface", 12345) + mock_set.assert_any_call(grib, "typeOfSecondFixedSurface", -1) + mock_set.assert_any_call(grib, "scaleFactorOfSecondFixedSurface", 255) + mock_set.assert_any_call(grib, "scaledValueOfSecondFixedSurface", -1) - @mock.patch.object(gribapi, "grib_set_long") - def test_no_vertical(self, mock_set_long): - grib = None - cube = iris.cube.Cube([1,2,3,4,5]) - grib_save_rules.non_hybrid_surfaces(cube, grib) - mock_set_long.assert_any_call(grib, "typeOfFirstFixedSurface", 1) - mock_set_long.assert_any_call(grib, "scaleFactorOfFirstFixedSurface", 0) - mock_set_long.assert_any_call(grib, "scaledValueOfFirstFixedSurface", 0) - mock_set_long.assert_any_call(grib, "typeOfSecondFixedSurface", -1) - mock_set_long.assert_any_call(grib, "scaleFactorOfSecondFixedSurface", 255) - mock_set_long.assert_any_call(grib, "scaledValueOfSecondFixedSurface", -1) - - -class Test_data(tests.IrisTest): - # Test grib_save_rules.data() - - @mock.patch.object(gribapi, "grib_set_double_array") - @mock.patch.object(gribapi, "grib_set_double") @mock.patch.object(gribapi, "grib_set") - def test_masked_array(self, mock_set, mock_set_double, grib_set_double_array): + def test_no_vertical(self, mock_set): grib = None - cube = iris.cube.Cube(ma.MaskedArray([1,2,3,4,5], fill_value=54321)) - - grib_save_rules.data(cube, grib) - - mock_set_double.assert_any_call(grib, "missingValue", float(54321)) - - @mock.patch.object(gribapi, "grib_set_double_array") - @mock.patch.object(gribapi, "grib_set_double") - def test_numpy_array(self, mock_set_double, grib_set_double_array): - grib = None - cube = iris.cube.Cube(np.array([1,2,3,4,5])) - - grib_save_rules.data(cube, grib) - - mock_set_double.assert_any_call(grib, "missingValue", float(-1e9)) - - @mock.patch.object(gribapi, "grib_set_double_array") - @mock.patch.object(gribapi, "grib_set_double") - def test_scaling(self, mock_set_double, mock_set_double_array): - # Show that data type known to be stored as %ge gets scaled - grib = None - cube = iris.cube.Cube(np.array([0.0, 0.25, 1.0]), - standard_name='cloud_area_fraction', - units=iris.unit.Unit('0.5')) - grib_save_rules.data(cube, grib) - callargs = mock_set_double_array.call_args_list - self.assertEqual(len(callargs), 1) - self.assertEqual(callargs[0][0][:2], (None, "values")) - self.assertArrayAlmostEqual(callargs[0][0][2], - np.array([0.0, 12.5, 50.0])) + cube = iris.cube.Cube([1, 2, 3, 4, 5]) + grib_save_rules.set_fixed_surfaces(cube, grib) + mock_set.assert_any_call(grib, "typeOfFirstFixedSurface", 1) + mock_set.assert_any_call(grib, "scaleFactorOfFirstFixedSurface", 0) + mock_set.assert_any_call(grib, "scaledValueOfFirstFixedSurface", 0) + mock_set.assert_any_call(grib, "typeOfSecondFixedSurface", -1) + mock_set.assert_any_call(grib, "scaleFactorOfSecondFixedSurface", 255) + mock_set.assert_any_call(grib, "scaledValueOfSecondFixedSurface", -1) +@tests.skip_grib class Test_phenomenon(tests.IrisTest): - @mock.patch.object(gribapi, "grib_set_long") - def test_phenom_unknown(self, mock_set_long): + @mock.patch.object(gribapi, "grib_set") + def test_phenom_unknown(self, mock_set): grib = None cube = iris.cube.Cube(np.array([1.0])) # Force reset of warnings registry to avoid suppression of @@ -129,64 +97,65 @@ def test_phenom_unknown(self, mock_set_long): # This should issue a warning about unrecognised data warnings.simplefilter("error") with self.assertRaises(UserWarning): - grib_save_rules.param_code(cube, grib) + grib_save_rules.set_discipline_and_parameter(cube, grib) # do it all again, and this time check the results grib = None cube = iris.cube.Cube(np.array([1.0])) - grib_save_rules.param_code(cube, grib) - mock_set_long.assert_any_call(grib, "discipline", 255) - mock_set_long.assert_any_call(grib, "parameterCategory", 255) - mock_set_long.assert_any_call(grib, "parameterNumber", 255) + grib_save_rules.set_discipline_and_parameter(cube, grib) + mock_set.assert_any_call(grib, "discipline", 255) + mock_set.assert_any_call(grib, "parameterCategory", 255) + mock_set.assert_any_call(grib, "parameterNumber", 255) - @mock.patch.object(gribapi, "grib_set_long") - def test_phenom_known_standard_name(self, mock_set_long): + @mock.patch.object(gribapi, "grib_set") + def test_phenom_known_standard_name(self, mock_set): grib = None cube = iris.cube.Cube(np.array([1.0]), standard_name='sea_surface_temperature') - grib_save_rules.param_code(cube, grib) - mock_set_long.assert_any_call(grib, "discipline", 10) - mock_set_long.assert_any_call(grib, "parameterCategory", 3) - mock_set_long.assert_any_call(grib, "parameterNumber", 0) + grib_save_rules.set_discipline_and_parameter(cube, grib) + mock_set.assert_any_call(grib, "discipline", 10) + mock_set.assert_any_call(grib, "parameterCategory", 3) + mock_set.assert_any_call(grib, "parameterNumber", 0) - @mock.patch.object(gribapi, "grib_set_long") - def test_phenom_known_long_name(self, mock_set_long): + @mock.patch.object(gribapi, "grib_set") + def test_phenom_known_long_name(self, mock_set): grib = None cube = iris.cube.Cube(np.array([1.0]), long_name='cloud_mixing_ratio') - grib_save_rules.param_code(cube, grib) - mock_set_long.assert_any_call(grib, "discipline", 0) - mock_set_long.assert_any_call(grib, "parameterCategory", 1) - mock_set_long.assert_any_call(grib, "parameterNumber", 22) + grib_save_rules.set_discipline_and_parameter(cube, grib) + mock_set.assert_any_call(grib, "discipline", 0) + mock_set.assert_any_call(grib, "parameterCategory", 1) + mock_set.assert_any_call(grib, "parameterNumber", 22) +@tests.skip_grib class Test_type_of_statistical_processing(tests.IrisTest): - @mock.patch.object(gribapi, "grib_set_long") - def test_stats_type_min(self, mock_set_long): + @mock.patch.object(gribapi, "grib_set") + def test_stats_type_min(self, mock_set): grib = None cube = iris.cube.Cube(np.array([1.0])) - time_unit = iris.unit.Unit('hours since 1970-01-01 00:00:00') + time_unit = cf_units.Unit('hours since 1970-01-01 00:00:00') time_coord = iris.coords.DimCoord([0.0], bounds=[0.0, 1], standard_name='time', units=time_unit) cube.add_aux_coord(time_coord, ()) cube.add_cell_method(iris.coords.CellMethod('maximum', time_coord)) - grib_save_rules.type_of_statistical_processing(cube, grib, time_coord) - mock_set_long.assert_any_call(grib, "typeOfStatisticalProcessing", 2) + grib_save_rules.product_definition_template_8(cube, grib) + mock_set.assert_any_call(grib, "typeOfStatisticalProcessing", 2) - @mock.patch.object(gribapi, "grib_set_long") - def test_stats_type_max(self, mock_set_long): + @mock.patch.object(gribapi, "grib_set") + def test_stats_type_max(self, mock_set): grib = None cube = iris.cube.Cube(np.array([1.0])) - time_unit = iris.unit.Unit('hours since 1970-01-01 00:00:00') + time_unit = cf_units.Unit('hours since 1970-01-01 00:00:00') time_coord = iris.coords.DimCoord([0.0], bounds=[0.0, 1], standard_name='time', units=time_unit) cube.add_aux_coord(time_coord, ()) cube.add_cell_method(iris.coords.CellMethod('minimum', time_coord)) - grib_save_rules.type_of_statistical_processing(cube, grib, time_coord) - mock_set_long.assert_any_call(grib, "typeOfStatisticalProcessing", 3) + grib_save_rules.product_definition_template_8(cube, grib) + mock_set.assert_any_call(grib, "typeOfStatisticalProcessing", 3) if __name__ == "__main__": diff --git a/lib/iris/tests/test_hybrid.py b/lib/iris/tests/test_hybrid.py index c9ff75d33e..6c83df9502 100644 --- a/lib/iris/tests/test_hybrid.py +++ b/lib/iris/tests/test_hybrid.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -19,6 +19,10 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + # import iris tests first so that some things can be initialised before # importing anything else import iris.tests as tests @@ -32,8 +36,11 @@ import iris.tests.stock +@tests.skip_plot +@tests.skip_data class TestRealistic4d(tests.GraphicsTest): def setUp(self): + super(TestRealistic4d, self).setUp() self.cube = iris.tests.stock.realistic_4d() self.altitude = self.cube.coord('altitude') @@ -66,8 +73,10 @@ def test_removing_sigma(self): # Check the factory now only has surface_altitude and delta dependencies. factory = cube.aux_factory(name='altitude') - t = [key for key, coord in factory.dependencies.iteritems() if coord is not None] - self.assertItemsEqual(t, ['orography', 'delta']) + t = [key + for key, coord in six.iteritems(factory.dependencies) + if coord is not None] + six.assertCountEqual(self, t, ['orography', 'delta']) def test_removing_orography(self): # Check the cube remains OK when the orography is removed. @@ -78,8 +87,10 @@ def test_removing_orography(self): # Check the factory now only has sigma and delta dependencies. factory = cube.aux_factory(name='altitude') - t = [key for key, coord in factory.dependencies.iteritems() if coord is not None] - self.assertItemsEqual(t, ['sigma', 'delta']) + t = [key + for key, coord in six.iteritems(factory.dependencies) + if coord is not None] + six.assertCountEqual(self, t, ['sigma', 'delta']) def test_derived_coords(self): derived_coords = self.cube.derived_coords @@ -140,16 +151,18 @@ def test_bounded_orography(self): # Make sure altitude still works OK if orography was messed # with *after* altitude was created. - altitude = self.cube.coord('altitude') orog.bounds = np.zeros(orog.shape + (4,)) - self.assertIsInstance(altitude.bounds, np.ndarray) - # Make sure altitude.bounds now raises an error. - altitude = self.cube.coord('altitude') - with self.assertRaises(ValueError): - bounds = altitude.bounds + # Check that altitude derivation now issues a warning. + msg = 'Orography.* bounds.* being disregarded' + with warnings.catch_warnings(): + # Cause all warnings to raise Exceptions + warnings.simplefilter("error") + with self.assertRaisesRegexp(UserWarning, msg): + self.cube.coord('altitude') +@tests.skip_data class TestHybridPressure(tests.IrisTest): def setUp(self): # Convert the hybrid-height into hybrid-pressure... @@ -218,15 +231,15 @@ def test_bounded_surface_pressure(self): # Make sure pressure still works OK if surface pressure was messed # with *after* pressure was created. - pressure = self.cube.coord('air_pressure') surface_pressure.bounds = np.zeros(surface_pressure.shape + (4,)) - self.assertIsInstance(pressure.bounds, np.ndarray) - - # Make sure pressure.bounds now raises an error. - pressure = self.cube.coord('air_pressure') - with self.assertRaises(ValueError): - bounds = pressure.bounds + # Check that air_pressure derivation now issues a warning. + msg = 'Surface pressure.* bounds.* being disregarded' + with warnings.catch_warnings(): + # Cause all warnings to raise Exceptions + warnings.simplefilter("error") + with self.assertRaisesRegexp(UserWarning, msg): + self.cube.coord('air_pressure') if __name__ == "__main__": tests.main() diff --git a/lib/iris/tests/test_image_json.py b/lib/iris/tests/test_image_json.py new file mode 100644 index 0000000000..48690ebe44 --- /dev/null +++ b/lib/iris/tests/test_image_json.py @@ -0,0 +1,84 @@ +# (C) British Crown Copyright 2016 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import codecs +import itertools +import json +import os +import requests +import unittest +import time + + +@tests.skip_inet +@tests.skip_data +class TestImageFile(tests.IrisTest): + def test_resolve(self): + # https://developer.github.com/v3/#user-agent-required + headers = {'User-Agent': 'scitools-bot'} + rate_limit_uri = 'https://api.github.com/rate_limit' + rl = requests.get(rate_limit_uri, headers=headers) + some_left = False + if rl.status_code == 200: + rates = rl.json() + remaining = rates.get('rate', {}) + ghapi_remaining = remaining.get('remaining') + else: + ghapi_remaining = 0 + + # Only run this test if there are IP based rate limited calls left. + # 3 is an engineering tolerance, in case of race conditions. + amin = 3 + if ghapi_remaining < amin: + return unittest.skip("Less than {} anonymous calls to " + "GH API left!".format(amin)) + iuri = ('https://api.github.com/repos/scitools/' + 'test-iris-imagehash/contents/images/v4') + r = requests.get(iuri, headers=headers) + if r.status_code != 200: + raise ValueError('Github API get failed: {}'.format(iuri, + r.text)) + rj = r.json() + base = 'https://scitools.github.io/test-iris-imagehash/images/v4' + + known_image_uris = set([os.path.join(base, rji['name']) for rji in rj]) + + repo_fname = os.path.join(os.path.dirname(__file__), 'results', + 'imagerepo.json') + with open(repo_fname, 'rb') as fi: + repo = json.load(codecs.getreader('utf-8')(fi)) + uris = set(itertools.chain.from_iterable(six.itervalues(repo))) + + amsg = ('Images are referenced in imagerepo.json but not published ' + 'in {}:\n{}') + diffs = list(uris.difference(known_image_uris)) + amsg = amsg.format(base, '\n'.join(diffs)) + + self.assertTrue(uris.issubset(known_image_uris), msg=amsg) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/test_interpolation.py b/lib/iris/tests/test_interpolation.py deleted file mode 100644 index 6938351157..0000000000 --- a/lib/iris/tests/test_interpolation.py +++ /dev/null @@ -1,912 +0,0 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -""" -Test the interpolation of Iris cubes. - -""" -# import iris tests first so that some things can be initialised before importing anything else -import iris.tests as tests - -import biggus -import numpy as np -import numpy.ma as ma -from scipy.interpolate import interp1d - -import iris -import iris.coord_systems -import iris.cube -import iris.analysis.interpolate -import iris.tests.stock -from iris.analysis.interpolate import Linear1dExtrapolator -import iris.analysis.interpolate as iintrp - - -def normalise_order(cube): - # Avoid the crazy array ordering which results from using: - # * np.append() in NumPy 1.6, which is triggered in the `linear()` - # function when the circular flag is true. - # * scipy.interpolate.interp1d in 0.11.0 which is used in - # `Linear1dExtrapolator`. - cube.data = np.ascontiguousarray(cube.data) - - -class TestLinearExtrapolator(tests.IrisTest): - def test_simple_axis0(self): - a = np.arange(12.).reshape(3, 4) - r = Linear1dExtrapolator(interp1d(np.arange(3), a, axis=0)) - - np.testing.assert_array_equal(r(0), np.array([ 0., 1., 2., 3.])) - np.testing.assert_array_equal(r(-1), np.array([-4., -3., -2., -1.])) - np.testing.assert_array_equal(r(3), np.array([ 12., 13., 14., 15.])) - np.testing.assert_array_equal(r(2.5), np.array([ 10., 11., 12., 13.])) - - # 2 Non-extrapolation point - np.testing.assert_array_equal(r(np.array([1.5, 2])), np.array([[ 6., 7., 8., 9.], - [ 8., 9., 10., 11.]])) - - # 1 Non-extrapolation point & 1 upper value extrapolation - np.testing.assert_array_equal(r(np.array([1.5, 3])), np.array([[ 6., 7., 8., 9.], - [ 12., 13., 14., 15.]])) - - # 2 upper value extrapolation - np.testing.assert_array_equal(r(np.array([2.5, 3])), np.array([[ 10., 11., 12., 13.], - [ 12., 13., 14., 15.]])) - - # 1 lower value extrapolation & 1 Non-extrapolation point - np.testing.assert_array_equal(r(np.array([-1, 1.5])), np.array([[-4., -3., -2., -1.], - [ 6., 7., 8., 9.]])) - - # 2 lower value extrapolation - np.testing.assert_array_equal(r(np.array([-1.5, -1])), np.array([[-6., -5., -4., -3.], - [-4., -3., -2., -1.]])) - - # 2 lower value extrapolation, 2 Non-extrapolation point & 2 upper value extrapolation - np.testing.assert_array_equal(r(np.array([-1.5, -1, 1, 1.5, 2.5, 3])), - np.array([[ -6., -5., -4., -3.], - [ -4., -3., -2., -1.], - [ 4., 5., 6., 7.], - [ 6., 7., 8., 9.], - [ 10., 11., 12., 13.], - [ 12., 13., 14., 15.]])) - - def test_simple_axis1(self): - a = np.arange(12).reshape(3, 4) - r = Linear1dExtrapolator(interp1d(np.arange(4), a, axis=1)) - - # check non-extrapolation given the Extrapolator object - np.testing.assert_array_equal(r(0), np.array([ 0., 4., 8.])) - - # check the result's shape in a 1d array (of len 0 & 1) - np.testing.assert_array_equal(r(np.array(0)), np.array([ 0., 4., 8.])) - np.testing.assert_array_equal(r(np.array([0])), np.array([ [0.], [4.], [8.]])) - - # check extrapolation below the minimum value (and check the equivalent 0d & 1d arrays) - np.testing.assert_array_equal(r(-1), np.array([-1., 3., 7.])) - np.testing.assert_array_equal(r(np.array(-1)), np.array([-1., 3., 7.])) - np.testing.assert_array_equal(r(np.array([-1])), np.array([[-1.], [ 3.], [ 7.]])) - - # check extrapolation above the maximum value - np.testing.assert_array_equal(r(3), np.array([ 3., 7., 11.])) - np.testing.assert_array_equal(r(2.5), np.array([ 2.5, 6.5, 10.5])) - - # 2 Non-extrapolation point - np.testing.assert_array_equal(r(np.array([1.5, 2])), np.array([[ 1.5, 2. ], - [ 5.5, 6. ], - [ 9.5, 10. ]])) - - # 1 Non-extrapolation point & 1 upper value extrapolation - np.testing.assert_array_equal(r(np.array([1.5, 5])), np.array([[ 1.5, 5. ], - [ 5.5, 9. ], - [ 9.5, 13. ]])) - - # 2 upper value extrapolation - np.testing.assert_array_equal(r(np.array([4.5, 5])), np.array([[ 4.5, 5. ], - [ 8.5, 9. ], - [ 12.5, 13. ]])) - - # 1 lower value extrapolation & 1 Non-extrapolation point - np.testing.assert_array_equal(r(np.array([-0.5, 1.5])), np.array([[-0.5, 1.5], - [ 3.5, 5.5], - [ 7.5, 9.5]])) - - # 2 lower value extrapolation - np.testing.assert_array_equal(r(np.array([-1.5, -1])), np.array([[-1.5, -1. ], - [ 2.5, 3. ], - [ 6.5, 7. ]])) - - # 2 lower value extrapolation, 2 Non-extrapolation point & 2 upper value extrapolation - np.testing.assert_array_equal(r(np.array([-1.5, -1, 1.5, 2, 4.5, 5])), - np.array([[ -1.5, -1. , 1.5, 2. , 4.5, 5. ], - [ 2.5, 3. , 5.5, 6. , 8.5, 9. ], - [ 6.5, 7. , 9.5, 10. , 12.5, 13. ]])) - - - def test_simple_3d_axis1(self): - a = np.arange(24.).reshape(3, 4, 2) - r = Linear1dExtrapolator(interp1d(np.arange(4.), a, axis=1)) - -# a: -# [[[ 0 1] -# [ 2 3] -# [ 4 5] -# [ 6 7]] -# -# [[ 8 9] -# [10 11] -# [12 13] -# [14 15]] -# -# [[16 17] -# [18 19] -# [20 21] -# [22 23]] -# ] - - np.testing.assert_array_equal(r(0), np.array([[ 0., 1.], - [ 8., 9.], - [ 16., 17.]])) - - np.testing.assert_array_equal(r(1), np.array([[ 2., 3.], - [ 10., 11.], - [ 18., 19.]])) - - np.testing.assert_array_equal(r(-1), np.array([[ -2., -1.], - [ 6., 7.], - [ 14., 15.]])) - - np.testing.assert_array_equal(r(4), np.array([[ 8., 9.], - [ 16., 17.], - [ 24., 25.]])) - - np.testing.assert_array_equal(r(0.25), np.array([[ 0.5, 1.5], - [ 8.5, 9.5], - [ 16.5, 17.5]])) - - np.testing.assert_array_equal(r(-0.25), np.array([[ -0.5, 0.5], - [ 7.5, 8.5], - [ 15.5, 16.5]])) - - np.testing.assert_array_equal(r(4.25), np.array([[ 8.5, 9.5], - [ 16.5, 17.5], - [ 24.5, 25.5]])) - - np.testing.assert_array_equal(r(np.array([0.5, 1])), np.array([[[ 1., 2.], [ 2., 3.]], - [[ 9., 10.], [ 10., 11.]], - [[ 17., 18.], [ 18., 19.]]])) - - np.testing.assert_array_equal(r(np.array([0.5, 4])), np.array([[[ 1., 2.], [ 8., 9.]], - [[ 9., 10.], [ 16., 17.]], - [[ 17., 18.], [ 24., 25.]]])) - - np.testing.assert_array_equal(r(np.array([-0.5, 0.5])), np.array([[[ -1., 0.], [ 1., 2.]], - [[ 7., 8.], [ 9., 10.]], - [[ 15., 16.], [ 17., 18.]]])) - - np.testing.assert_array_equal(r(np.array([-1.5, -1, 0.5, 1, 4.5, 5])), - np.array([[[ -3., -2.], [ -2., -1.], [ 1., 2.], [ 2., 3.], [ 9., 10.], [ 10., 11.]], - [[ 5., 6.], [ 6., 7.], [ 9., 10.], [ 10., 11.], [ 17., 18.], [ 18., 19.]], - [[ 13., 14.], [ 14., 15.], [ 17., 18.], [ 18., 19.], [ 25., 26.], [ 26., 27.]]])) - - def test_variable_gradient(self): - a = np.array([[2, 4, 8], [0, 5, 11]]) - r = Linear1dExtrapolator(interp1d(np.arange(2), a, axis=0)) - - np.testing.assert_array_equal(r(0), np.array([ 2., 4., 8.])) - np.testing.assert_array_equal(r(-1), np.array([ 4., 3., 5.])) - np.testing.assert_array_equal(r(3), np.array([ -4., 7., 17.])) - np.testing.assert_array_equal(r(2.5), np.array([ -3. , 6.5, 15.5])) - - np.testing.assert_array_equal(r(np.array([1.5, 2])), np.array([[ -1. , 5.5, 12.5], - [ -2. , 6. , 14. ]])) - - np.testing.assert_array_equal(r(np.array([-1.5, 3.5])), np.array([[ 5. , 2.5, 3.5], - [ -5. , 7.5, 18.5]])) - - -class TestLinearLengthOneCoord(tests.IrisTest): - def setUp(self): - self.cube = iris.tests.stock.lat_lon_cube() - self.cube.data = self.cube.data.astype(float) - - def test_single_point(self): - # Slice to form (3, 1) shaped cube. - cube = self.cube[:, 2:3] - r = iris.analysis.interpolate.linear(cube, [('longitude', [1.])]) - self.assertCMLApproxData(r, ('analysis', 'interpolation', 'linear', - 'single_pt_to_single_pt_0')) - - # Slice to form (1, 4) shaped cube. - cube = self.cube[1:2, :] - r = iris.analysis.interpolate.linear(cube, [('latitude', [1.])]) - self.assertCMLApproxData(r, ('analysis', 'interpolation', 'linear', - 'single_pt_to_single_pt_1')) - - def test_multiple_points(self): - # Slice to form (3, 1) shaped cube. - cube = self.cube[:, 2:3] - r = iris.analysis.interpolate.linear(cube, [('longitude', - [1., 2., 3., 4.])]) - self.assertCMLApproxData(r, ('analysis', 'interpolation', 'linear', - 'single_pt_to_many_0')) - - # Slice to form (1, 4) shaped cube. - cube = self.cube[1:2, :] - r = iris.analysis.interpolate.linear(cube, [('latitude', - [1., 2., 3., 4.])]) - self.assertCMLApproxData(r, ('analysis', 'interpolation', 'linear', - 'single_pt_to_many_1')) - - def test_single_point_to_scalar(self): - # Slice to form (3, 1) shaped cube. - cube = self.cube[:, 2:3] - r = iris.analysis.interpolate.linear(cube, [('longitude', 1.)]) - self.assertCMLApproxData(r, ('analysis', 'interpolation', 'linear', - 'single_pt_to_scalar_0')) - - # Slice to form (1, 4) shaped cube. - cube = self.cube[1:2, :] - r = iris.analysis.interpolate.linear(cube, [('latitude', 1.)]) - self.assertCMLApproxData(r, ('analysis', 'interpolation', 'linear', - 'single_pt_to_scalar_1')) - - def test_extrapolation_mode_same_pt(self): - # Slice to form (3, 1) shaped cube. - cube = self.cube[:, 2:3] - src_points = cube.coord('longitude').points - r = iris.analysis.interpolate.linear(cube, [('longitude', src_points)], - extrapolation_mode='linear') - self.assertCMLApproxData(r, ('analysis', 'interpolation', 'linear', - 'single_pt_to_same_pt')) - r = iris.analysis.interpolate.linear(cube, [('longitude', src_points)], - extrapolation_mode='nan') - self.assertCMLApproxData(r, ('analysis', 'interpolation', 'linear', - 'single_pt_to_same_pt')) - r = iris.analysis.interpolate.linear(cube, [('longitude', src_points)], - extrapolation_mode='error') - self.assertCMLApproxData(r, ('analysis', 'interpolation', 'linear', - 'single_pt_to_same_pt')) - - def test_extrapolation_mode_multiple_same_pts(self): - # Slice to form (3, 1) shaped cube. - cube = self.cube[:, 2:3] - src_points = cube.coord('longitude').points - new_points = [src_points[0]] * 3 - r = iris.analysis.interpolate.linear(cube, [('longitude', new_points)], - extrapolation_mode='linear') - self.assertCMLApproxData(r, ('analysis', 'interpolation', 'linear', - 'single_pt_to_many_same')) - r = iris.analysis.interpolate.linear(cube, [('longitude', new_points)], - extrapolation_mode='nan') - self.assertCMLApproxData(r, ('analysis', 'interpolation', 'linear', - 'single_pt_to_many_same')) - r = iris.analysis.interpolate.linear(cube, [('longitude', new_points)], - extrapolation_mode='error') - self.assertCMLApproxData(r, ('analysis', 'interpolation', 'linear', - 'single_pt_to_many_same')) - - def test_extrapolation_mode_different_pts(self): - # Slice to form (3, 1) shaped cube. - cube = self.cube[:, 2:3] - src_points = cube.coord('longitude').points - new_points_single = src_points + 0.2 - new_points_multiple = [src_points[0], - src_points[0] + 0.2, - src_points[0] + 0.4] - new_points_scalar = src_points[0] + 0.2 - - # 'nan' mode - r = iris.analysis.interpolate.linear(cube, [('longitude', - new_points_single)], - extrapolation_mode='nan') - self.assertCMLApproxData(r, ('analysis', 'interpolation', 'linear', - 'single_pt_to_single_pt_nan')) - r = iris.analysis.interpolate.linear(cube, [('longitude', - new_points_multiple)], - extrapolation_mode='nan') - self.assertCMLApproxData(r, ('analysis', 'interpolation', 'linear', - 'single_pt_to_many_nan')) - r = iris.analysis.interpolate.linear(cube, [('longitude', - new_points_scalar)], - extrapolation_mode='nan') - self.assertCMLApproxData(r, ('analysis', 'interpolation', 'linear', - 'single_pt_to_scalar_nan')) - - # 'error' mode - with self.assertRaises(ValueError): - r = iris.analysis.interpolate.linear(cube, [('longitude', - new_points_single)], - extrapolation_mode='error') - with self.assertRaises(ValueError): - r = iris.analysis.interpolate.linear(cube, [('longitude', - new_points_multiple)], - extrapolation_mode='error') - with self.assertRaises(ValueError): - r = iris.analysis.interpolate.linear(cube, [('longitude', - new_points_scalar)], - extrapolation_mode='error') - - -class TestLinear1dInterpolation(tests.IrisTest): - def setUp(self): - data = np.arange(12., dtype=np.float32).reshape((4, 3)) - c2 = iris.cube.Cube(data) - - c2.long_name = 'test 2d dimensional cube' - c2.units = 'kelvin' - - pts = 3 + np.arange(4, dtype=np.float32) * 2 - b = iris.coords.DimCoord(pts, long_name='dim1', units=1) - d = iris.coords.AuxCoord([3, 3.5, 6], long_name='dim2', units=1) - e = iris.coords.AuxCoord(3.0, long_name='an_other', units=1) - - c2.add_dim_coord(b, 0) - c2.add_aux_coord(d, 1) - c2.add_aux_coord(e) - - self.simple2d_cube = c2 - - d = iris.coords.AuxCoord([5, 9, 20], long_name='shared_x_coord', units=1) - c3 = c2.copy() - c3.add_aux_coord(d, 1) - self.simple2d_cube_extended = c3 - - pts = 0.1 + np.arange(5, dtype=np.float32) * 0.1 - f = iris.coords.DimCoord(pts, long_name='r', units=1) - g = iris.coords.DimCoord([0.0, 90.0, 180.0, 270.0], long_name='theta', units='degrees', circular=True) - data = np.arange(20., dtype=np.float32).reshape((5, 4)) - c4 = iris.cube.Cube(data) - c4.add_dim_coord(f, 0) - c4.add_dim_coord(g, 1) - self.simple2d_cube_circular = c4 - - def test_dim_to_aux(self): - cube = self.simple2d_cube - other = iris.coords.DimCoord([1, 2, 3, 4], long_name='was_dim') - cube.add_aux_coord(other, 0) - r = iris.analysis.interpolate.linear(cube, [('dim1', [7, 3, 5])]) - normalise_order(r) - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'dim_to_aux.cml')) - - def test_integer_interpol(self): - c = self.simple2d_cube - c.data = c.data.astype(np.int16) - self.assertRaises(ValueError, iris.analysis.interpolate.linear, c, [('dim1', 4)]) - - def test_bad_sample_point_format(self): - self.assertRaises(TypeError, iris.analysis.interpolate.linear, self.simple2d_cube, ('dim1', 4)) - - def test_simple_single_point(self): - r = iris.analysis.interpolate.linear(self.simple2d_cube, [('dim1', 4)]) - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'simple_single_point.cml')) - np.testing.assert_array_equal(r.data, np.array([1.5, 2.5, 3.5], dtype=self.simple2d_cube.data.dtype)) - - def test_monotonic_decreasing_coord(self): - c = self.simple2d_cube[::-1] - r = iris.analysis.interpolate.linear(c, [('dim1', 4)]) - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'simple_single_point.cml')) - np.testing.assert_array_equal(r.data, np.array([1.5, 2.5, 3.5], dtype=self.simple2d_cube.data.dtype)) - - def test_overspecified(self): - self.assertRaises(ValueError, iris.analysis.interpolate.linear, self.simple2d_cube[0, :], [('dim1', 4)]) - - def test_bounded_coordinate(self): - # The results should be exactly the same as for the - # non-bounded case. - cube = self.simple2d_cube - cube.coord('dim1').guess_bounds() - r = iris.analysis.interpolate.linear(cube, [('dim1', [4, 5])]) - np.testing.assert_array_equal(r.data, np.array([[ 1.5, 2.5, 3.5], [ 3. , 4. , 5. ]])) - normalise_order(r) - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'simple_multiple_points.cml')) - - def test_simple_multiple_point(self): - r = iris.analysis.interpolate.linear(self.simple2d_cube, [('dim1', [4, 5])]) - np.testing.assert_array_equal(r.data, np.array([[ 1.5, 2.5, 3.5], [ 3. , 4. , 5. ]])) - normalise_order(r) - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'simple_multiple_points.cml')) - - # Check that numpy arrays specifications work - r = iris.analysis.interpolate.linear(self.simple2d_cube, [('dim1', np.array([4, 5]))]) - normalise_order(r) - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'simple_multiple_points.cml')) - - def test_circular_vs_non_circular_coord(self): - cube = self.simple2d_cube_circular - other = iris.coords.AuxCoord([10, 6, 7, 4], long_name='other') - cube.add_aux_coord(other, 1) - samples = [0, 60, 300] - r = iris.analysis.interpolate.linear(cube, [('theta', samples)]) - normalise_order(r) - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'circular_vs_non_circular.cml')) - - def test_simple_multiple_points_circular(self): - r = iris.analysis.interpolate.linear(self.simple2d_cube_circular, [('theta', [0. , 60. , 120. , 180. ])]) - normalise_order(r) - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'simple_multiple_points_circular.cml')) - - # check that the values returned by theta 0 & 360 are the same... - r1 = iris.analysis.interpolate.linear(self.simple2d_cube_circular, [('theta', 360)]) - r2 = iris.analysis.interpolate.linear(self.simple2d_cube_circular, [('theta', 0)]) - np.testing.assert_array_almost_equal(r1.data, r2.data) - - def test_simple_multiple_coords(self): - expected_result = np.array(2.5) - r = iris.analysis.interpolate.linear(self.simple2d_cube, [('dim1', 4), ('dim2', 3.5), ]) - np.testing.assert_array_equal(r.data, expected_result) - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'simple_multiple_coords.cml'), checksum=False) - - # Check that it doesn't matter if you do the interpolation in separate steps... - r = iris.analysis.interpolate.linear(self.simple2d_cube, [('dim2', 3.5)]) - r = iris.analysis.interpolate.linear(r, [('dim1', 4)]) - np.testing.assert_array_equal(r.data, expected_result) - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'simple_multiple_coords.cml'), checksum=False) - - r = iris.analysis.interpolate.linear(self.simple2d_cube, [('dim1', 4)]) - r = iris.analysis.interpolate.linear(r, [('dim2', 3.5)]) - np.testing.assert_array_equal(r.data, expected_result) - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'simple_multiple_coords.cml'), checksum=False) - - def test_coord_not_found(self): - self.assertRaises(KeyError, iris.analysis.interpolate.linear, self.simple2d_cube, - [('non_existant_coord', [3.5, 3.25])]) - - def test_simple_coord_error_extrapolation(self): - self.assertRaises(ValueError, iris.analysis.interpolate.linear, self.simple2d_cube, [('dim2', 2.5)], extrapolation_mode='error') - - def test_simple_coord_linear_extrapolation(self): - r = iris.analysis.interpolate.linear( self.simple2d_cube, [('dim2', 2.5)], extrapolation_mode='linear') - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'simple_coord_linear_extrapolation.cml')) - - np.testing.assert_array_equal(r.data, np.array([-1., 2., 5., 8.], dtype=self.simple2d_cube.data.dtype)) - - r = iris.analysis.interpolate.linear(self.simple2d_cube, [('dim1', 1)]) - np.testing.assert_array_equal(r.data, np.array([-3., -2., -1.], dtype=self.simple2d_cube.data.dtype)) - - def test_simple_coord_linear_extrapolation_multipoint1(self): - r = iris.analysis.interpolate.linear( self.simple2d_cube, [('dim1', [-1, 1, 10, 11])], extrapolation_mode='linear') - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'simple_coord_linear_extrapolation_multipoint1.cml')) - - def test_simple_coord_linear_extrapolation_multipoint2(self): - r = iris.analysis.interpolate.linear( self.simple2d_cube, [('dim1', [1, 10])], extrapolation_mode='linear') - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'simple_coord_linear_extrapolation_multipoint2.cml')) - - def test_simple_coord_nan_extrapolation(self): - r = iris.analysis.interpolate.linear( self.simple2d_cube, [('dim2', 2.5)], extrapolation_mode='nan') - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'simple_coord_nan_extrapolation.cml')) - - def test_multiple_coord_extrapolation(self): - self.assertRaises(ValueError, iris.analysis.interpolate.linear, self.simple2d_cube, [('dim2', 2.5), ('dim1', 12.5)], extrapolation_mode='error') - - def test_multiple_coord_linear_extrapolation(self): - r = iris.analysis.interpolate.linear(self.simple2d_cube, [('dim2', 9), ('dim1', 1.5)]) - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'simple_multiple_coords_extrapolation.cml')) - - def test_lots_of_points(self): - r = iris.analysis.interpolate.linear(self.simple2d_cube, [('dim1', np.linspace(3, 9, 20))]) - - def test_shared_axis(self): - c = self.simple2d_cube_extended - r = iris.analysis.interpolate.linear(c, [('dim2', [3.5, 3.25])]) - normalise_order(r) - - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'simple_shared_axis.cml')) - - self.assertRaises(ValueError, iris.analysis.interpolate.linear, c, [('dim2', [3.5, 3.25]), ('shared_x_coord', [9, 7])]) - - def test_points_datatype_casting(self): - # this test tries to extract a float from an array of type integer. the result should be of type float. - r = iris.analysis.interpolate.linear(self.simple2d_cube_extended, [('shared_x_coord', 7.5)]) - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'simple_casting_datatype.cml')) - - def test_mask(self): - # Test np.append bug with masked arrays. - # Based on the bug reported in https://github.com/SciTools/iris/issues/106 - cube = tests.stock.realistic_4d_w_missing_data() - cube = cube[0, 2, 18::-1] - cube.coord('grid_longitude').circular = True - _ = iris.analysis.interpolate.linear(cube, [('grid_longitude',0), ('grid_latitude',0)]) - # Did np.append go wrong? - self.assertArrayEqual(cube.data.data.shape, cube.data.mask.shape) - - def test_scalar_mask(self): - # Testing the bug raised in https://github.com/SciTools/iris/pull/123#issuecomment-9309872 - # (the fix workaround for the np.append bug failed for scalar masks) - cube = tests.stock.realistic_4d_w_missing_data() - cube.data = ma.arange(np.product(cube.shape), dtype=np.float32).reshape(cube.shape) - cube.coord('grid_longitude').circular = True - # There's no result to test, just make sure we don't cause an exception with the scalar mask. - _ = iris.analysis.interpolate.linear(cube, [('grid_longitude',0), ('grid_latitude',0)]) - - -@iris.tests.skip_data -class TestNearestLinearInterpolRealData(tests.IrisTest): - def setUp(self): - file = tests.get_data_path(('PP', 'globClim1', 'theta.pp')) - self.cube = iris.load_cube(file) - - def test_slice(self): - r = iris.analysis.interpolate.linear(self.cube, [('latitude', 0)]) - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'real_2dslice.cml')) - - def test_2slices(self): - r = iris.analysis.interpolate.linear(self.cube, [('latitude', 0.0), ('longitude', 0.0)]) - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'real_2slices.cml')) - - def test_circular(self): - r = iris.analysis.interpolate.linear(self.cube, [('longitude', 359.8)]) - normalise_order(r) - self.assertCML(r, ('analysis', 'interpolation', 'linear', 'real_circular_2dslice.cml')) - - # check that the values returned by lon 0 & 360 are the same... - r1 = iris.analysis.interpolate.linear(self.cube, [('longitude', 360)]) - r2 = iris.analysis.interpolate.linear(self.cube, [('longitude', 0)]) - np.testing.assert_array_equal(r1.data, r2.data) - - -@iris.tests.skip_data -class TestNearestNeighbour(tests.IrisTest): - def setUp(self): - self.cube = iris.tests.stock.global_pp() - points = np.arange(self.cube.coord('latitude').shape[0], dtype=np.float32) - coord_to_add = iris.coords.DimCoord(points, long_name='i', units='meters') - self.cube.add_aux_coord(coord_to_add, 0) - - def test_nearest_neighbour(self): - point_spec = [('latitude', 40), ('longitude', 39)] - - indices = iris.analysis.interpolate.nearest_neighbour_indices(self.cube, point_spec) - self.assertEqual(indices, (20, 10)) - - b = iris.analysis.interpolate.extract_nearest_neighbour(self.cube, point_spec) - - # Check that the data has not been loaded on either the original cube, - # nor the interpolated one. - self.assertTrue(b.has_lazy_data()) - self.assertTrue(self.cube.has_lazy_data()) - self.assertCML(b, ('analysis', 'interpolation', 'nearest_neighbour_extract_latitude_longitude.cml')) - - value = iris.analysis.interpolate.nearest_neighbour_data_value(self.cube, point_spec) - self.assertEqual(value, np.array(285.98785, dtype=np.float32)) - - # Check that the value back is that which was returned by the extract method - self.assertEqual(value, b.data) - - def test_nearest_neighbour_slice(self): - point_spec = [('latitude', 40)] - - indices = iris.analysis.interpolate.nearest_neighbour_indices(self.cube, point_spec) - self.assertEqual(indices, (20, slice(None, None))) - - b = iris.analysis.interpolate.extract_nearest_neighbour(self.cube, point_spec) - self.assertCML(b, ('analysis', 'interpolation', 'nearest_neighbour_extract_latitude.cml')) - - # cannot get a specific point from these point specifications - self.assertRaises(ValueError, iris.analysis.interpolate.nearest_neighbour_data_value, self.cube, point_spec) - - def test_nearest_neighbour_over_specification_which_is_consistent(self): - # latitude 40 is the 20th point - point_spec = [('latitude', 40), ('i', 20), ('longitude', 38)] - - indices = iris.analysis.interpolate.nearest_neighbour_indices(self.cube, point_spec) - self.assertEqual(indices, (20, 10)) - - b = iris.analysis.interpolate.extract_nearest_neighbour(self.cube, point_spec) - self.assertCML(b, ('analysis', 'interpolation', 'nearest_neighbour_extract_latitude_longitude.cml')) - - value = iris.analysis.interpolate.nearest_neighbour_data_value(self.cube, point_spec) - # Check that the value back is that which was returned by the extract method - self.assertEqual(value, b.data) - - def test_nearest_neighbour_over_specification_mis_aligned(self): - # latitude 40 is the 20th point - point_spec = [('latitude', 40), ('i', 10), ('longitude', 38)] - - # assert that we get a ValueError for over specifying our interpolation - self.assertRaises(ValueError, iris.analysis.interpolate.nearest_neighbour_data_value, self.cube, point_spec) - - def test_nearest_neighbour_bounded_simple(self): - point_spec = [('latitude', 37), ('longitude', 38)] - - coord = self.cube.coord('latitude') - coord.guess_bounds(0.5) - - b = iris.analysis.interpolate.extract_nearest_neighbour(self.cube, point_spec) - self.assertCML(b, ('analysis', 'interpolation', 'nearest_neighbour_extract_bounded.cml')) - - def test_nearest_neighbour_bounded_requested_midpoint(self): - # This test checks the "point inside cell" logic - point_spec = [('latitude', 38), ('longitude', 38)] - - coord = self.cube.coord('latitude') - coord.guess_bounds(0.5) - - b = iris.analysis.interpolate.extract_nearest_neighbour(self.cube, point_spec) - self.assertCML(b, ('analysis', 'interpolation', 'nearest_neighbour_extract_bounded_mid_point.cml')) - - def test_nearest_neighbour_locator_style_coord(self): - point_spec = [('latitude', 39)] - - b = iris.analysis.interpolate.extract_nearest_neighbour(self.cube, point_spec) - self.assertCML(b, ('analysis', 'interpolation', 'nearest_neighbour_extract_latitude.cml')) - - def test_nearest_neighbour_circular(self): - # test on non-circular coordinate (latitude) - lat_vals = np.array([ - [-150.0, -90], [-97, -90], [-92, -90], [-91, -90], [-90.1, -90], - [-90.0, -90], [-89.9, -90], - [-89, -90], [-88, -87.5], [-87, -87.5], - [-86, -85], [-85.5, -85], - [81, 80], [84, 85], [84.8, 85], [85, 85], [86, 85], - [87, 87.5], [88, 87.5], [89, 90], - [89.9, 90], [90.0, 90], [90.1, 90], - [95, 90], [100, 90], [150, 90]]) - lat_test_vals = lat_vals[:, 0] - lat_expect_vals = lat_vals[:, 1] - lat_coord_vals = self.cube.coord('latitude').points - - def near_value(val, vals): - # return the *exact* value from vals that is closest to val. - # - and raise an exception if there isn't a close match. - best_val = vals[np.argmin(np.abs(vals - val))] - if val == 0.0: - # absolute tolerance to 0.0 (ok for magnitudes >= 1.0 or so) - error_level = best_val - else: - # calculate relative-tolerance - error_level = abs(0.5 * (val - best_val) / (val + best_val)) - self.assertTrue(error_level < 1.0e-6, - 'error_level {}% match of {} to one of {}'.format( - 100.0 * error_level, val, vals)) - return best_val - - lat_expect_vals = [near_value(v, lat_coord_vals) - for v in lat_expect_vals] - lat_nearest_inds = [ - iintrp.nearest_neighbour_indices( - self.cube, [('latitude', point_val)]) - for point_val in lat_test_vals] - lat_nearest_vals = [lat_coord_vals[i[0]] for i in lat_nearest_inds] - self.assertArrayAlmostEqual(lat_nearest_vals, lat_expect_vals) - - # repeat with *circular* coordinate (longitude) - lon_vals = np.array([ - [0.0, 0.0], - [-3.75, 356.25], - [-1.0, 0], [-0.01, 0], [0.5, 0], - [2, 3.75], [3, 3.75], [4, 3.75], [5, 3.75], [6, 7.5], - [350.5, 348.75], [351, 352.5], [354, 352.5], - [355, 356.25], [358, 356.25], - [358.7, 0], [359, 0], [360, 0], [361, 0], - [362, 3.75], [363, 3.75], [364, 3.75], [365, 3.75], [366, 7.5], - [-725.0, 356.25], [-722, 356.25], [-721, 0], [-719, 0.0], - [-718, 3.75], - [1234.56, 153.75], [-1234.56, 206.25]]) - lon_test_vals = lon_vals[:, 0] - lon_expect_vals = lon_vals[:, 1] - lon_coord_vals = self.cube.coord('longitude').points - lon_expect_vals = [near_value(v, lon_coord_vals) - for v in lon_expect_vals] - lon_nearest_inds = [ - iintrp.nearest_neighbour_indices(self.cube, - [('longitude', point_val)]) - for point_val in lon_test_vals] - lon_nearest_vals = [lon_coord_vals[i[1]] for i in lon_nearest_inds] - self.assertArrayAlmostEqual(lon_nearest_vals, lon_expect_vals) - - -class TestNearestNeighbourAdditional(tests.IrisTest): - """ - More detailed testing for coordinate nearest_neighbour function. - - Includes (especially) circular operation. - - """ - def _test_nn_breakpoints(self, points, breaks, expected, - bounds=None, guess_bounds=False, bounds_point=0.2, - circular=False, - test_min=-500.0, test_max=750.0): - """ - Make a test coordinate + test the nearest-neighbour calculation - - Check that the result index changes at the specified points. - Includes support for circular and bounded cases. - - Args: - - points : 1-d array-like - Points of the test coordinate (see also Kwargs) - breaks : list - Input points at which we expect the output result to change - expected : list - Expected results (cell index values) - Length must == len(breaks) + 1 - result == expected[i] between breaks[i] and breaks[i+1] - - Kwargs: - - bounds : 2d array-like - use these bounds - guess_bounds, bounds_point : bool, float - use guessed bounds - circular : bool - make a circular coordinate (360 degrees) - test_min, test_max : float - outer extreme values (non-circular only) - - """ - points = np.array(points, np.float) - if bounds: - bounds = np.array(bounds, np.float) - assert len(expected) == len(breaks) + 1 - if circular: - breaks = np.array(breaks) - breaks = np.hstack([i * 360.0 + breaks for i in range(-2, 3)]) - lower_lims = breaks[:-1] - upper_lims = breaks[1:] - expected = np.hstack([expected[1:] for i in range(-2, 3)]) - else: - lower_lims = np.hstack(([test_min], breaks)) - upper_lims = np.hstack((breaks, [test_max])) - - # construct coord : AuxCoord, or DimCoord if it needs to be circular - if circular: - test_coord = iris.coords.DimCoord(points, - bounds=bounds, - long_name='x', - units=iris.unit.Unit('degrees'), - circular=True) - else: - test_coord = iris.coords.AuxCoord(points, - bounds=bounds, - long_name='x', - units=iris.unit.Unit('degrees')) - if guess_bounds: - test_coord.guess_bounds(bounds_point) - - # test at a few 'random' points within each supposed result region - test_fractions = np.array([0.01, 0.2, 0.45, 0.75, 0.99]) - for (lower, upper, expect) in zip(lower_lims, upper_lims, expected): - test_pts = lower + test_fractions * (upper - lower) - results = [test_coord.nearest_neighbour_index(x) for x in test_pts] - self.assertTrue(np.all([r == expect for r in results])) - - def test_nearest_neighbour_circular(self): - # First test (simplest): ascending-order, unbounded - points = [0.0, 90.0, 180.0, 270.0] - breaks = [45.0, 135.0, 225.0] - results = [0, 1, 2, 3] - self._test_nn_breakpoints(points, breaks, results) - - # same, but *CIRCULAR* - breaks_circ = [-45.0] + breaks - results_circ = [3] + results - self._test_nn_breakpoints(points, breaks_circ, results_circ, - circular=True) - - # repeat circular test with different coordinate offsets - offset = 32.7 - points_offset = np.array(points) + offset - breaks_offset = np.array(breaks_circ) + offset - self._test_nn_breakpoints(points_offset, breaks_offset, results_circ, - circular=True) - - offset = -106.3 - points_offset = np.array(points) + offset - breaks_offset = np.array(breaks_circ) + offset - self._test_nn_breakpoints(points_offset, breaks_offset, results_circ, - circular=True) - - # ascending order, guess-bounded - # N.B. effect of bounds_position = 2/3 - # x_bounds = [[-60, 30], [30, 120], [120, 210], [210, 300]] - points = [0.0, 90, 180, 270] - breaks = [30.0, 120.0, 210.0] - results = [0, 1, 2, 3] - self._test_nn_breakpoints(points, breaks, results, - guess_bounds=True, bounds_point=2.0 / 3) - - # same but circular... - breaks_circ = [-60.0] + breaks - results_circ = [3] + results - self._test_nn_breakpoints(points, breaks_circ, results_circ, - guess_bounds=True, bounds_point=2.0 / 3, - circular=True) - - def test_nearest_neighbour_descending_circular(self): - # descending order, unbounded - points = [270.0, 180, 90, 0] - breaks = [45.0, 135.0, 225.0] - results = [3, 2, 1, 0] - self._test_nn_breakpoints(points, breaks, results) - - # same but circular... - breaks = [-45.0] + breaks - results = [0] + results - self._test_nn_breakpoints(points, breaks, results, circular=True) - - # repeat circular test with different coordinate offsets - offset = 32.7 - points_offset = np.array(points) + offset - breaks_offset = np.array(breaks) + offset - self._test_nn_breakpoints(points_offset, breaks_offset, results, - circular=True) - - offset = -106.3 - points_offset = np.array(points) + offset - breaks_offset = np.array(breaks) + offset - self._test_nn_breakpoints(points_offset, breaks_offset, results, - circular=True) - - # descending order, guess-bounded - points = [250.0, 150, 50, -50] - # N.B. equivalent effect of bounds_position = 0.4 - # x_bounds = [[290, 190], [190, 90], [90, -10], [-10, -110]] - breaks = [-10.0, 90.0, 190.0] - results = [3, 2, 1, 0] - self._test_nn_breakpoints(points, breaks, results, - guess_bounds=True, bounds_point=0.4) - # same but circular... - breaks = [-110.0] + breaks - results = [0] + results - self._test_nn_breakpoints(points, breaks, results, - guess_bounds=True, bounds_point=0.4, - circular=True) - - def test_nearest_neighbour_odd_bounds(self): - # additional: test with overlapping bounds - points = [0.0, 90, 180, 270] - bounds = [[-90.0, 90], [0, 180], [90, 270], [180, 360]] - breaks = [45.0, 135.0, 225.0] - results = [0, 1, 2, 3] - self._test_nn_breakpoints(points, breaks, results, bounds=bounds) - - # additional: test with disjoint bounds - points = [40.0, 90, 150, 270] - bounds = [[0, 60], [70, 90], [140, 200], [210, 360]] - breaks = [65.0, 115.0, 205.0] - results = [0, 1, 2, 3] - self._test_nn_breakpoints(points, breaks, results, bounds=bounds) - - def test_nearest_neighbour_scalar(self): - points = [1.0] - breaks = [] - results = [0] - self._test_nn_breakpoints(points, breaks, results) - - def test_nearest_neighbour_nonmonotonic(self): - # a bounded example - points = [3.0, 4.0, 1.0, 7.0, 10.0] - bounds = [[2.5, 3.5], - [3.5, 4.5], - [0.5, 1.5], - [6.5, 7.5], - [9.5, 10.5]] - breaks = [2.0, 3.5, 5.5, 8.5] - results = [2, 0, 1, 3, 4] - self._test_nn_breakpoints(points, breaks, results, bounds=bounds) - - # a pointwise example - points = [3.0, 3.5, 1.0, 8.0, 12.0] - breaks = [2.0, 3.25, 5.75, 10.0] - results = [2, 0, 1, 3, 4] - self._test_nn_breakpoints(points, breaks, results) - - # NOTE: no circular cases, as AuxCoords _cannot_ be circular. - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/test_intersect.py b/lib/iris/tests/test_intersect.py index 62ae623ccf..e068bc8654 100644 --- a/lib/iris/tests/test_intersect.py +++ b/lib/iris/tests/test_intersect.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -18,6 +18,10 @@ Test the intersection of Coords """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests @@ -32,11 +36,11 @@ class TestCubeIntersectTheoretical(tests.IrisTest): def test_simple_intersect(self): - cube = iris.cube.Cube(np.array([[1,2,3,4,5], - [2,3,4,5,6], - [3,4,5,6,7], - [4,5,6,7,8], - [5,6,7,8,9]], dtype=np.int32)) + cube = iris.cube.Cube(np.array([[1, 2, 3, 4, 5], + [2, 3, 4, 5, 6], + [3, 4, 5, 6, 7], + [4, 5, 6, 7, 8], + [5, 6, 7, 8, 9]], dtype=np.int32)) lonlat_cs = iris.coord_systems.RotatedGeogCS(10, 20) cube.add_dim_coord(iris.coords.DimCoord(np.arange(5, dtype=np.float32) * 90 - 180, 'longitude', units='degrees', coord_system=lonlat_cs), 1) @@ -45,11 +49,11 @@ def test_simple_intersect(self): cube.rename("temperature") cube.units = "K" - cube2 = iris.cube.Cube(np.array([[1,2,3,4,5], - [2,3,4,5,6], - [3,4,5,6,7], - [4,5,6,7,8], - [5,6,7,8,50]], dtype=np.int32)) + cube2 = iris.cube.Cube(np.array([[1, 2, 3, 4, 5], + [2, 3, 4, 5, 6], + [3, 4, 5, 6, 7], + [4, 5, 6, 7, 8], + [5, 6, 7, 8, 50]], dtype=np.int32)) lonlat_cs = iris.coord_systems.RotatedGeogCS(10, 20) cube2.add_dim_coord(iris.coords.DimCoord(np.arange(5, dtype=np.float32) * 90, 'longitude', units='degrees', coord_system=lonlat_cs), 1) diff --git a/lib/iris/tests/test_io_init.py b/lib/iris/tests/test_io_init.py index df553a6af5..4a946047ce 100644 --- a/lib/iris/tests/test_io_init.py +++ b/lib/iris/tests/test_io_init.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -18,18 +18,20 @@ Test the io/__init__.py module. """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests -import unittest from io import BytesIO import iris.fileformats as iff -import iris.io.format_picker as fp import iris.io -class TestDecodeUri(unittest.TestCase): +class TestDecodeUri(tests.IrisTest): def test_decode_uri(self): tests = { '/data/local/someDir/PP/COLPEX/COLPEX_16a_pj001.pp': ( @@ -58,7 +60,7 @@ def test_known_formats(self): tests.get_result_path(('file_load', 'known_loaders.txt'))) - @iris.tests.skip_data + @tests.skip_data def test_format_picker(self): # ways to test the format picker = list of (format-name, file-spec) test_specs = [ @@ -78,6 +80,8 @@ def test_format_picker(self): ['GRIB', 'jpeg2000', 'file.grib2']), ('UM Post Processing file (PP)', ['PP', 'simple_pp', 'global.pp']), + ('UM Post Processing file (PP) little-endian', + ['PP', 'little_endian', 'qrparm.orog.pp']), ('UM Fieldsfile (FF) ancillary', ['FF', 'ancillary_fixed_length_header']), # ('BUFR', @@ -94,7 +98,7 @@ def test_format_picker(self): # test that each filespec is identified as the expected format for (expected_format_name, file_spec) in test_specs: test_path = tests.get_data_path(file_spec) - with open(test_path, 'r') as test_file: + with open(test_path, 'rb') as test_file: a = iff.FORMAT_AGENT.get_spec(test_path, test_file) self.assertEqual(a.name, expected_format_name) @@ -107,8 +111,8 @@ def test_format_picker_nodata(self): # specific to WMO bulletin headers header_lengths = [21, 80, 41, 42] for header_length in header_lengths: - binary_string = header_length * '\x00' + 'GRIB' + '\x00' * 100 - with BytesIO('rw') as bh: + binary_string = header_length * b'\x00' + b'GRIB' + b'\x00' * 100 + with BytesIO(b'rw') as bh: bh.write(binary_string) bh.name = 'fake_file_handle' a = iff.FORMAT_AGENT.get_spec(bh.name, bh) @@ -123,12 +127,5 @@ def test_open_dap(self): self.assertEqual(a.name, 'NetCDF OPeNDAP') -@iris.tests.skip_data -class TestFileExceptions(tests.IrisTest): - def test_pp_little_endian(self): - filename = tests.get_data_path(('PP', 'aPPglob1', 'global_little_endian.pp')) - self.assertRaises(ValueError, iris.load_cube, filename) - - if __name__ == '__main__': tests.main() diff --git a/lib/iris/tests/test_iterate.py b/lib/iris/tests/test_iterate.py index ee44155a57..6fd601ae19 100644 --- a/lib/iris/tests/test_iterate.py +++ b/lib/iris/tests/test_iterate.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2016, Met Office # # This file is part of Iris. # @@ -18,6 +18,10 @@ Test the iteration of cubes in step. """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised before # importing anything else import iris.tests as tests @@ -33,8 +37,10 @@ import iris.analysis import iris.iterate import iris.tests.stock +from functools import reduce +@tests.skip_data class TestIterateFunctions(tests.IrisTest): def setUp(self): @@ -106,40 +112,50 @@ def test_izip_missing_slice_coords(self): with self.assertRaises(iris.exceptions.CoordinateNotFoundError): iris.iterate.izip(self.cube_a, self.cube_b, coords=self.coord_names) - def test_izip_onecube(self): + def test_izip_onecube_no_coords(self): # Should do the same as slices() but bearing in mind izip.next() # returns a tuple of cubes + # Reduce the size to speed things up - we're going to iterate + # over *every* data point. + self.cube_b = self.cube_b[:2, :4, :3] + # Empty list as coords slice_iterator = self.cube_b.slices([]) zip_iterator = iris.iterate.izip(self.cube_b, coords=[]) for cube_slice in slice_iterator: # First element of tuple: (extractedcube, ) - zip_slice = zip_iterator.next()[0] + zip_slice = next(zip_iterator)[0] self.assertEqual(cube_slice, zip_slice) with self.assertRaises(StopIteration): - zip_iterator.next() # Should raise exception if we continue - # to try to iterate + next(zip_iterator) # Should raise exception if we continue try to + # to iterate + + def test_izip_onecube_lat_lon(self): # Two coords slice_iterator = self.cube_b.slices(self.coord_names) zip_iterator = iris.iterate.izip(self.cube_b, coords=self.coord_names) for cube_slice in slice_iterator: # First element of tuple: (extractedcube, ) - zip_slice = zip_iterator.next()[0] + zip_slice = next(zip_iterator)[0] self.assertEqual(cube_slice, zip_slice) with self.assertRaises(StopIteration): - zip_iterator.next() # Should raise exception if we continue - #to try to iterate + next(zip_iterator) # Should raise exception if we continue to try + # to iterate + + def test_izip_onecube_lat(self): # One coord slice_iterator = self.cube_b.slices('grid_latitude') zip_iterator = iris.iterate.izip(self.cube_b, coords='grid_latitude') for cube_slice in slice_iterator: # First element of tuple: (extractedcube, ) - zip_slice = zip_iterator.next()[0] + zip_slice = next(zip_iterator)[0] self.assertEqual(cube_slice, zip_slice) with self.assertRaises(StopIteration): - zip_iterator.next() # Should raise exception if we continue - # to try to iterate + next(zip_iterator) # Should raise exception if we continue to try + # to iterate + + def test_izip_onecube_height_lat_long(self): # All coords slice_iterator = self.cube_b.slices(['level_height', 'grid_latitude', 'grid_longitude']) @@ -148,13 +164,13 @@ def test_izip_onecube(self): 'grid_longitude']) for cube_slice in slice_iterator: # First element of tuple: (extractedcube, ) - zip_slice = zip_iterator.next()[0] + zip_slice = next(zip_iterator)[0] self.assertEqual(cube_slice, zip_slice) with self.assertRaises(StopIteration): - zip_iterator.next() # Should raise exception if we continue - #to try to iterate + next(zip_iterator) # Should raise exception if we continue to try + # to iterate - def test_izip_same_cube(self): + def test_izip_same_cube_lat_lon(self): nslices = self.cube_b.shape[0] slice_iterator = self.cube_b.slices(self.coord_names) count = 0 @@ -162,10 +178,11 @@ def test_izip_same_cube(self): self.cube_b, coords=self.coord_names): self.assertEqual(slice_first, slice_second) # Equal to each other - self.assertEqual(slice_first, slice_iterator.next()) # Equal to the truth (from slice()) + self.assertEqual(slice_first, next(slice_iterator)) # Equal to the truth (from slice()) count += 1 self.assertEqual(count, nslices) - # Another case + + def test_izip_same_cube_lat(self): nslices = self.cube_a.shape[0] * self.cube_a.shape[2] # Calc product of dimensions # excluding the latitude # (2nd data dim) @@ -175,10 +192,15 @@ def test_izip_same_cube(self): self.cube_a, coords=['grid_latitude']): self.assertEqual(slice_first, slice_second) - self.assertEqual(slice_first, slice_iterator.next()) # Equal to the truth (from slice()) + self.assertEqual(slice_first, next(slice_iterator)) # Equal to the truth (from slice()) count += 1 self.assertEqual(count, nslices) - # third case - full iteration + + def test_izip_same_cube_no_coords(self): + # Reduce the size to speed things up - we're going to iterate + # over *every* data point. + self.cube_b = self.cube_b[:2, :4, :3] + nslices = reduce(operator.mul, self.cube_b.shape) slice_iterator = self.cube_b.slices([]) count = 0 @@ -186,12 +208,12 @@ def test_izip_same_cube(self): self.cube_b, coords=[]): self.assertEqual(slice_first, slice_second) - self.assertEqual(slice_first, slice_iterator.next()) # Equal to the truth (from slice()) + self.assertEqual(slice_first, next(slice_iterator)) # Equal to the truth (from slice()) count += 1 self.assertEqual(count, nslices) def test_izip_subcube_of_same(self): - for _ in xrange(3): + for _ in range(3): super_cube = self.cube_a # Random int to pick coord value to calc subcube k = random.randint(0, super_cube.shape[0]-1) @@ -203,7 +225,7 @@ def test_izip_subcube_of_same(self): self.assertEqual(sub_slice, sub_cube) # This cube should not change # as lat and long are the only # data dimensions in this cube) - self.assertEqual(super_slice, super_slice_iterator.next()) + self.assertEqual(super_slice, next(super_slice_iterator)) if j == k: self.assertEqual(super_slice, sub_slice) else: @@ -217,13 +239,13 @@ def test_izip_same_dims(self): nslices = reduce(operator.mul, self.cube_a.shape[1:]) nslices_to_check = 20 # This is only approximate as we use random to select slices # Fraction of slices to check - check_eq_probability = max(0.0, min(1.0, float(nslices_to_check)/nslices)) + check_eq_probability = max(0.0, min(1.0, nslices_to_check / nslices)) ij_iterator = np.ndindex(self.cube_a.shape[1], self.cube_a.shape[2]) count = 0 for slice_a, slice_b in iris.iterate.izip(self.cube_a, self.cube_b, coords='level_height'): - i, j = ij_iterator.next() + i, j = next(ij_iterator) if random.random() < check_eq_probability: # Check these slices slice_a_truth = self.cube_a[:, i, j] slice_b_truth = self.cube_b[:, i, j] @@ -233,11 +255,11 @@ def test_izip_same_dims(self): self.assertEqual(count, nslices) # Two coords nslices = self.cube_a.shape[0] - i_iterator = iter(xrange(self.cube_a.shape[0])) + i_iterator = iter(range(self.cube_a.shape[0])) count = 0 for slice_a, slice_b in iris.iterate.izip(self.cube_a, self.cube_b, coords=self.coord_names): - i = i_iterator.next() + i = next(i_iterator) slice_a_truth = self.cube_a[i, :, :] slice_b_truth = self.cube_b[i, :, :] self.assertEqual(slice_a_truth, slice_a) @@ -296,12 +318,12 @@ def test_izip_extra_dim(self): nslices = big_cube.shape[0]*big_cube.shape[2] nslices_to_check = 20 # This is only approximate as we use random to select slices # Fraction of slices to check - check_eq_probability = max(0.0, min(1.0, float(nslices_to_check)/nslices)) + check_eq_probability = max(0.0, min(1.0, nslices_to_check / nslices)) ij_iterator = np.ndindex(big_cube.shape[0], big_cube.shape[2]) count = 0 for big_slice, little_slice in iris.iterate.izip(big_cube, little_cube, coords='grid_latitude'): - i, j = ij_iterator.next() + i, j = next(ij_iterator) if random.random() < check_eq_probability: big_slice_truth = big_cube[i, :, j] little_slice_truth = little_cube # Just 1d so slice is entire cube @@ -429,7 +451,7 @@ def test_izip_nd_ortho(self): cube1.add_dim_coord(iris.coords.DimCoord(np.arange(5, dtype='i8'), long_name='z'), [0]) cube1.add_aux_coord(iris.coords.AuxCoord(np.arange(25, dtype='i8').reshape(5, 5), - long_name='y'), [1,2]) + long_name='y'), [1, 2]) cube1.add_aux_coord(iris.coords.AuxCoord(np.arange(25, dtype='i8').reshape(5, 5), long_name='x'), [3, 4]) cube2 = cube1.copy() diff --git a/lib/iris/tests/test_load.py b/lib/iris/tests/test_load.py index a52b4c9683..65755e4a1b 100644 --- a/lib/iris/tests/test_load.py +++ b/lib/iris/tests/test_load.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -18,6 +18,10 @@ Test the main loading API. """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests @@ -25,7 +29,7 @@ import iris.io -@iris.tests.skip_data +@tests.skip_data class TestLoad(tests.IrisTest): def test_normal(self): paths = ( @@ -41,8 +45,8 @@ def test_nonexist(self): ) with self.assertRaises(IOError) as error_trap: cubes = iris.load(paths) - self.assertTrue(error_trap.exception.message.startswith( - 'One or more of the files specified did not exist')) + self.assertIn('One or more of the files specified did not exist', + str(error_trap.exception)) def test_nonexist_wild(self): paths = ( @@ -51,8 +55,8 @@ def test_nonexist_wild(self): ) with self.assertRaises(IOError) as error_trap: cubes = iris.load(paths) - self.assertTrue(error_trap.exception.message.startswith( - 'One or more of the files specified did not exist')) + self.assertIn('One or more of the files specified did not exist', + str(error_trap.exception)) def test_bogus(self): paths = ( @@ -77,7 +81,7 @@ def test_duplicate(self): self.assertEqual(len(cubes), 2) -@iris.tests.skip_data +@tests.skip_data class TestLoadCube(tests.IrisTest): def test_normal(self): paths = ( @@ -101,7 +105,7 @@ def test_too_many(self): iris.load_cube(paths) -@iris.tests.skip_data +@tests.skip_data class TestLoadCubes(tests.IrisTest): def test_normal(self): paths = ( diff --git a/lib/iris/tests/test_mapping.py b/lib/iris/tests/test_mapping.py index 76f58d3621..05d5652bc6 100644 --- a/lib/iris/tests/test_mapping.py +++ b/lib/iris/tests/test_mapping.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -18,11 +18,13 @@ Tests map creation. """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa -# import iris tests first so that some things can be initialised before importing anything else +# import iris tests first so that some things can be initialised before +# importing anything else import iris.tests as tests -import matplotlib.pyplot as plt import numpy as np import numpy.testing as np_testing import cartopy.crs as ccrs @@ -30,12 +32,26 @@ import iris import iris.coord_systems import iris.cube -import iris.plot as iplt import iris.tests.stock +# Run tests in no graphics mode if matplotlib is not available. +if tests.MPL_AVAILABLE: + import matplotlib.pyplot as plt + import iris.plot as iplt -class TestBasic(tests.IrisTest): - cube = iris.tests.stock.realistic_4d() + +# A specific cartopy Globe matching the iris RotatedGeogCS default. +_DEFAULT_GLOBE = ccrs.Globe(semimajor_axis=6371229.0, + semiminor_axis=6371229.0, + ellipse=None) + + +@tests.skip_plot +@tests.skip_data +class TestBasic(tests.GraphicsTest): + def setUp(self): + super(TestBasic, self).setUp() + self.cube = iris.tests.stock.realistic_4d() def test_contourf(self): cube = self.cube[0, 0] @@ -55,38 +71,48 @@ def test_unmappable(self): def test_default_projection_and_extent(self): self.assertEqual(iplt.default_projection(self.cube), - ccrs.RotatedPole(357.5 - 180, 37.5) - ) + ccrs.RotatedPole(357.5 - 180, 37.5, + globe=_DEFAULT_GLOBE)) - np_testing.assert_array_almost_equal(iplt.default_projection_extent(self.cube), - (3.59579163e+02, 3.59669159e+02, -1.28250003e-01, -3.82499993e-02), - decimal=3 - ) + np_testing.assert_array_almost_equal( + iplt.default_projection_extent(self.cube), + (3.59579163e+02, 3.59669159e+02, -1.28250003e-01, -3.82499993e-02), + decimal=3) -@iris.tests.skip_data -class TestUnmappable(tests.IrisTest): +@tests.skip_data +@tests.skip_plot +class TestUnmappable(tests.GraphicsTest): def setUp(self): + super(TestUnmappable, self).setUp() src_cube = iris.tests.stock.global_pp() # Make a cube that can't be located on the globe. cube = iris.cube.Cube(src_cube.data) - cube.add_dim_coord(iris.coords.DimCoord(np.arange(96, dtype=np.float32) * 100, long_name='x', units='m'), 1) - cube.add_dim_coord(iris.coords.DimCoord(np.arange(73, dtype=np.float32) * 100, long_name='y', units='m'), 0) + cube.add_dim_coord( + iris.coords.DimCoord(np.arange(96, dtype=np.float32) * 100, + long_name='x', units='m'), + 1) + cube.add_dim_coord( + iris.coords.DimCoord(np.arange(73, dtype=np.float32) * 100, + long_name='y', units='m'), + 0) cube.standard_name = 'air_temperature' cube.units = 'K' - cube.assert_valid() self.cube = cube def test_simple(self): - iplt.contourf(self.cube) + iplt.contourf(self.cube, coords=['y', 'x']) self.check_graphic() -@iris.tests.skip_data -class TestMappingSubRegion(tests.IrisTest): +@tests.skip_data +@tests.skip_plot +class TestMappingSubRegion(tests.GraphicsTest): def setUp(self): - cube_path = tests.get_data_path(('PP', 'aPProt1', 'rotatedMHtimecube.pp')) + super(TestMappingSubRegion, self).setUp() + cube_path = tests.get_data_path( + ('PP', 'aPProt1', 'rotatedMHtimecube.pp')) cube = iris.load_cube(cube_path)[0] # make the data smaller to speed things up. self.cube = cube[::10, ::10] @@ -121,20 +147,24 @@ def test_simple(self): def test_default_projection_and_extent(self): self.assertEqual(iplt.default_projection(self.cube), - ccrs.RotatedPole(357.5 - 180, 37.5) - ) + ccrs.RotatedPole(357.5 - 180, 37.5, + globe=_DEFAULT_GLOBE)) + + np_testing.assert_array_almost_equal( + iplt.default_projection_extent(self.cube), + (313.01998901, 391.11999512, -22.48999977, 24.80999947)) - np_testing.assert_array_almost_equal(iplt.default_projection_extent(self.cube), - (313.01998901, 391.11999512, -22.48999977, 24.80999947) - ) -@iris.tests.skip_data -class TestLowLevel(tests.IrisTest): +@tests.skip_data +@tests.skip_plot +class TestLowLevel(tests.GraphicsTest): def setUp(self): + super(TestLowLevel, self).setUp() self.cube = iris.tests.stock.global_pp() self.few = 4 - self.few_levels = range(280, 300, 5) - self.many_levels = np.linspace(self.cube.data.min(), self.cube.data.max(), 40) + self.few_levels = list(range(280, 300, 5)) + self.many_levels = np.linspace( + self.cube.data.min(), self.cube.data.max(), 40) def test_simple(self): iplt.contour(self.cube) @@ -158,17 +188,21 @@ def test_keywords(self): self.check_graphic() -@iris.tests.skip_data -class TestBoundedCube(tests.IrisTest): +@tests.skip_data +@tests.skip_plot +class TestBoundedCube(tests.GraphicsTest): def setUp(self): + super(TestBoundedCube, self).setUp() self.cube = iris.tests.stock.global_pp() - # Add some bounds to this data (this will actually make the bounds invalid as they - # will straddle the north pole and overlap on the date line, but that doesn't matter for this test.) + # Add some bounds to this data (this will actually make the bounds + # invalid as they will straddle the north pole and overlap on the + # dateline, but that doesn't matter for this test.) self.cube.coord('latitude').guess_bounds() self.cube.coord('longitude').guess_bounds() def test_pcolormesh(self): - # pcolormesh can only be drawn in native coordinates (or more specifically, in coordinates that don't wrap). + # pcolormesh can only be drawn in native coordinates (or more + # specifically, in coordinates that don't wrap). plt.axes(projection=ccrs.PlateCarree(central_longitude=180)) iplt.pcolormesh(self.cube) self.check_graphic() @@ -179,23 +213,21 @@ def test_grid(self): def test_default_projection_and_extent(self): self.assertEqual(iplt.default_projection(self.cube), - ccrs.PlateCarree() - ) - + ccrs.PlateCarree()) np_testing.assert_array_almost_equal( - iplt.default_projection_extent(self.cube), - [0., 360., -89.99995422, 89.99998474] - ) - + iplt.default_projection_extent(self.cube), + [0., 360., -89.99995422, 89.99998474]) np_testing.assert_array_almost_equal( - iplt.default_projection_extent(self.cube, mode=iris.coords.BOUND_MODE), - (-1.87499952, 358.12500048, -91.24995422, 91.24998474) - ) + iplt.default_projection_extent( + self.cube, mode=iris.coords.BOUND_MODE), + [-1.875046, 358.124954, -90, 90]) -@iris.tests.skip_data -class TestLimitedAreaCube(tests.IrisTest): +@tests.skip_data +@tests.skip_plot +class TestLimitedAreaCube(tests.GraphicsTest): def setUp(self): + super(TestLimitedAreaCube, self).setUp() cube_path = tests.get_data_path(('PP', 'aPProt1', 'rotated.pp')) self.cube = iris.load_cube(cube_path)[::20, ::20] self.cube.coord('grid_latitude').guess_bounds() @@ -207,8 +239,8 @@ def test_pcolormesh(self): def test_grid(self): iplt.pcolormesh(self.cube, facecolors='none', edgecolors='blue') - # the result is a graphic which has coloured edges. This is a mpl bug, see - # https://github.com/matplotlib/matplotlib/issues/1302 + # the result is a graphic which has coloured edges. This is a mpl bug, + # see https://github.com/matplotlib/matplotlib/issues/1302 self.check_graphic() def test_outline(self): diff --git a/lib/iris/tests/test_merge.py b/lib/iris/tests/test_merge.py index 8f8349eafd..c7bdfd8042 100644 --- a/lib/iris/tests/test_merge.py +++ b/lib/iris/tests/test_merge.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -19,16 +19,24 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests +from collections import Iterable +import datetime +import itertools import numpy as np +import numpy.ma as ma import iris +from iris._lazy_data import as_lazy_data import iris.cube -import iris.exceptions from iris.coords import DimCoord, AuxCoord -import iris.coords +import iris.exceptions import iris.tests.stock @@ -60,7 +68,7 @@ def test_duplication(self): self.assertEqual(len(cubes2), 2 * len(cubes)) -@iris.tests.skip_data +@tests.skip_data class TestSingleCube(tests.IrisTest, TestMixin): def setUp(self): self._data_path = tests.get_data_path(('PP', 'globClim1', 'theta.pp')) @@ -68,7 +76,7 @@ def setUp(self): self._prefix = 'theta' -@iris.tests.skip_data +@tests.skip_data class TestMultiCube(tests.IrisTest, TestMixin): def setUp(self): self._data_path = tests.get_data_path(('PP', 'globClim1', 'dec_subset.pp')) @@ -90,7 +98,7 @@ def custom_coord_callback(cube, field, filename): assert(cube.coord('time').attributes['brain'] == 'hurts') -@iris.tests.skip_data +@tests.skip_data class TestColpex(tests.IrisTest): def setUp(self): self._data_path = tests.get_data_path(('PP', 'COLPEX', 'small_colpex_theta_p_alt.pp')) @@ -101,19 +109,212 @@ def test_colpex(self): self.assertCML(cubes, ('COLPEX', 'small_colpex_theta_p_alt.cml')) -@iris.tests.skip_data +class TestDataMergeCombos(tests.IrisTest): + def _make_data(self, data, dtype=np.dtype('int32'), fill_value=None, + mask=None, lazy=False, N=3): + if isinstance(data, Iterable): + shape = (len(data), N, N) + data = np.array(data).reshape(-1, 1, 1) + else: + shape = (N, N) + if mask is not None: + payload = ma.empty(shape, dtype=dtype, fill_value=fill_value) + payload.data[:] = data + if isinstance(mask, bool): + payload.mask = mask + else: + payload[mask] = ma.masked + else: + payload = np.empty(shape, dtype=dtype) + payload[:] = data + if lazy: + payload = as_lazy_data(payload) + return payload + + def _make_cube(self, data, dtype=np.dtype('int32'), fill_value=None, + mask=None, lazy=False, N=3): + x = np.arange(N) + y = np.arange(N) + payload = self._make_data(data, dtype=dtype, fill_value=fill_value, + mask=mask, lazy=lazy, N=N) + cube = iris.cube.Cube(payload) + lat = DimCoord(y, standard_name='latitude', units='degrees') + cube.add_dim_coord(lat, 0) + lon = DimCoord(x, standard_name='longitude', units='degrees') + cube.add_dim_coord(lon, 1) + height = DimCoord(data, standard_name='height', units='m') + cube.add_aux_coord(height) + return cube + + @staticmethod + def _expected_fill_value(fill0='none', fill1='none'): + result = None + if fill0 != 'none' or fill1 != 'none': + if fill0 == 'none': + result = fill1 + elif fill1 == 'none': + result = fill0 + elif fill0 == fill1: + result = fill0 + return result + + def _check_fill_value(self, result, fill0='none', fill1='none'): + expected_fill_value = self._expected_fill_value(fill0, fill1) + if expected_fill_value is None: + data = result.data + if ma.isMaskedArray(data): + np_fill_value = ma.masked_array(0, + dtype=result.dtype).fill_value + self.assertEqual(data.fill_value, np_fill_value) + else: + data = result.data + if ma.isMaskedArray(data): + self.assertEqual(data.fill_value, expected_fill_value) + + def setUp(self): + self.dtype = np.dtype('int32') + fill_value = 1234 + self.lazy_combos = itertools.product([False, True], + [False, True]) + fill_combos = itertools.product([None, fill_value], + [fill_value, None]) + single_fill_combos = itertools.product([None, fill_value]) + self.combos = itertools.product(self.lazy_combos, fill_combos) + self.mixed_combos = itertools.product(self.lazy_combos, + single_fill_combos) + + def test__ndarray_ndarray(self): + for (lazy0, lazy1) in self.lazy_combos: + cubes = iris.cube.CubeList() + cubes.append(self._make_cube(0, dtype=self.dtype, lazy=lazy0)) + cubes.append(self._make_cube(1, dtype=self.dtype, lazy=lazy1)) + result = cubes.merge_cube() + expected = self._make_data([0, 1], dtype=self.dtype) + self.assertArrayEqual(result.data, expected) + self.assertEqual(result.dtype, self.dtype) + self._check_fill_value(result) + + def test__masked_masked(self): + for (lazy0, lazy1), (fill0, fill1) in self.combos: + cubes = iris.cube.CubeList() + mask = [(0,), (0,)] + cubes.append(self._make_cube(0, mask=mask, lazy=lazy0, + dtype=self.dtype, + fill_value=fill0)) + mask = [(1,), (1,)] + cubes.append(self._make_cube(1, mask=mask, lazy=lazy1, + dtype=self.dtype, + fill_value=fill1)) + result = cubes.merge_cube() + mask = [(0, 1), (0, 1), (0, 1)] + expected_fill_value = self._expected_fill_value(fill0, fill1) + expected = self._make_data([0, 1], mask=mask, dtype=self.dtype, + fill_value=expected_fill_value) + self.assertMaskedArrayEqual(result.data, expected) + self.assertEqual(result.dtype, self.dtype) + self._check_fill_value(result, fill0, fill1) + + def test__ndarray_masked(self): + for (lazy0, lazy1), (fill,) in self.mixed_combos: + cubes = iris.cube.CubeList() + cubes.append(self._make_cube(0, lazy=lazy0, dtype=self.dtype)) + mask = [(0, 1), (0, 1)] + cubes.append(self._make_cube(1, mask=mask, lazy=lazy1, + dtype=self.dtype, + fill_value=fill)) + result = cubes.merge_cube() + mask = [(1, 1), (0, 1), (0, 1)] + expected_fill_value = self._expected_fill_value(fill) + expected = self._make_data([0, 1], mask=mask, dtype=self.dtype, + fill_value=expected_fill_value) + self.assertMaskedArrayEqual(result.data, expected) + self.assertEqual(result.dtype, self.dtype) + self._check_fill_value(result, fill1=fill1) + + def test__masked_ndarray(self): + for (lazy0, lazy1), (fill,) in self.mixed_combos: + cubes = iris.cube.CubeList() + mask = [(0, 1), (0, 1)] + cubes.append(self._make_cube(0, mask=mask, lazy=lazy0, + dtype=self.dtype, + fill_value=fill)) + cubes.append(self._make_cube(1, lazy=lazy1, dtype=self.dtype)) + result = cubes.merge_cube() + mask = [(0, 0), (0, 1), (0, 1)] + expected_fill_value = self._expected_fill_value(fill) + expected = self._make_data([0, 1], mask=mask, dtype=self.dtype, + fill_value=expected_fill_value) + self.assertMaskedArrayEqual(result.data, expected) + self.assertEqual(result.dtype, self.dtype) + self._check_fill_value(result, fill0=fill) + + def test_maksed_array_preserved(self): + for (lazy0, lazy1), (fill,) in self.mixed_combos: + cubes = iris.cube.CubeList() + mask = False + cubes.append(self._make_cube(0, mask=mask, lazy=lazy0, + dtype=self.dtype, + fill_value=fill)) + cubes.append(self._make_cube(1, lazy=lazy1, dtype=self.dtype)) + result = cubes.merge_cube() + mask = False + expected_fill_value = self._expected_fill_value(fill) + expected = self._make_data([0, 1], mask=mask, dtype=self.dtype, + fill_value=expected_fill_value) + self.assertEqual(type(result.data), ma.MaskedArray) + self.assertMaskedArrayEqual(result.data, expected) + self.assertEqual(result.dtype, self.dtype) + self._check_fill_value(result, fill0=fill) + + def test_fill_value_invariant_to_order__same_non_None(self): + fill_value = 1234 + cubes = [self._make_cube(i, mask=True, + fill_value=fill_value) for i in range(3)] + for combo in itertools.permutations(cubes): + result = iris.cube.CubeList(combo).merge_cube() + self.assertEqual(result.data.fill_value, fill_value) + + def test_fill_value_invariant_to_order__all_None(self): + cubes = [self._make_cube(i, mask=True, + fill_value=None) for i in range(3)] + for combo in itertools.permutations(cubes): + result = iris.cube.CubeList(combo).merge_cube() + np_fill_value = ma.masked_array(0, dtype=result.dtype).fill_value + self.assertEqual(result.data.fill_value, np_fill_value) + + def test_fill_value_invariant_to_order__different_non_None(self): + cubes = [self._make_cube(0, mask=True, fill_value=1234)] + cubes.append(self._make_cube(1, mask=True, fill_value=2341)) + cubes.append(self._make_cube(2, mask=True, fill_value=3412)) + cubes.append(self._make_cube(3, mask=True, fill_value=4123)) + for combo in itertools.permutations(cubes): + result = iris.cube.CubeList(combo).merge_cube() + np_fill_value = ma.masked_array(0, dtype=result.dtype).fill_value + self.assertEqual(result.data.fill_value, np_fill_value) + + def test_fill_value_invariant_to_order__mixed(self): + cubes = [self._make_cube(0, mask=True, fill_value=None)] + cubes.append(self._make_cube(1, mask=True, fill_value=1234)) + cubes.append(self._make_cube(2, mask=True, fill_value=4321)) + for combo in itertools.permutations(cubes): + result = iris.cube.CubeList(combo).merge_cube() + np_fill_value = ma.masked_array(0, dtype=result.dtype).fill_value + self.assertEqual(result.data.fill_value, np_fill_value) + + +@tests.skip_data class TestDataMerge(tests.IrisTest): def test_extended_proxy_data(self): # Get the empty theta cubes for T+1.5 and T+2 data_path = tests.get_data_path( ('PP', 'COLPEX', 'theta_and_orog_subset.pp')) phenom_constraint = iris.Constraint('air_potential_temperature') - time_value_1 = 347921.33333332836627960205 - time_value_2 = 347921.83333333209156990051 - time_constraint1 = iris.Constraint(time=time_value_1) - time_constraint2 = iris.Constraint(time=time_value_2) + datetime_1 = datetime.datetime(2009, 9, 9, 17, 20) + datetime_2 = datetime.datetime(2009, 9, 9, 17, 50) + time_constraint1 = iris.Constraint(time=datetime_1) + time_constraint2 = iris.Constraint(time=datetime_2) time_constraint_1_and_2 = iris.Constraint( - time=lambda c: c in (time_value_1, time_value_2)) + time=lambda c: c in (datetime_1, datetime_2)) cube1 = iris.load_cube(data_path, phenom_constraint & time_constraint1) cube2 = iris.load_cube(data_path, phenom_constraint & time_constraint2) @@ -190,7 +391,7 @@ def _make_cube(self, a, b, c, d, data=0): long_name='y', units='1'), 0) for name, value in zip(['a', 'b', 'c', 'd'], [a, b, c, d]): - dtype = np.str if isinstance(value, basestring) else np.float32 + dtype = np.str if isinstance(value, six.string_types) else np.float32 cube.add_aux_coord(AuxCoord(np.array([value], dtype=dtype), long_name=name, units='1')) @@ -256,7 +457,7 @@ def _make_cube(self, a, b, data=0, a_dim=False, b_dim=False): long_name='y', units='1'), 0) for name, value, dim in zip(['a', 'b'], [a, b], [a_dim, b_dim]): - dtype = np.str if isinstance(value, basestring) else np.float32 + dtype = np.str if isinstance(value, six.string_types) else np.float32 ctype = DimCoord if dim else AuxCoord coord = ctype(np.array([value], dtype=dtype), long_name=name, units='1') @@ -484,11 +685,9 @@ def test_simple2(self): ]) cube = cubes.merge()[0] self.assertCML(cube, ('merge', 'time_triple_merging2.cml'), checksum=False) - self.assertIsNone(cube.assert_valid()) cube = iris.cube.CubeList(cubes[:-1]).merge()[0] self.assertCML(cube, ('merge', 'time_triple_merging3.cml'), checksum=False) - self.assertIsNone(cube.assert_valid()) def test_simple3(self): cubes = iris.cube.CubeList([ @@ -501,11 +700,9 @@ def test_simple3(self): ]) cube = cubes.merge()[0] self.assertCML(cube, ('merge', 'time_triple_merging4.cml'), checksum=False) - self.assertIsNone(cube.assert_valid()) cube = iris.cube.CubeList(cubes[:-1]).merge()[0] self.assertCML(cube, ('merge', 'time_triple_merging5.cml'), checksum=False) - self.assertIsNone(cube.assert_valid()) class TestCubeMergeTheoretical(tests.IrisTest): diff --git a/lib/iris/tests/test_name.py b/lib/iris/tests/test_name.py index a50db8fd52..75b14dfd66 100644 --- a/lib/iris/tests/test_name.py +++ b/lib/iris/tests/test_name.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2014 - 2016, Met Office # # This file is part of Iris. # @@ -16,13 +16,16 @@ # along with Iris. If not, see . """Tests for NAME loading.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised before # importing anything else import iris.tests as tests import iris -@iris.tests.skip_data +@tests.skip_data class TestLoad(tests.IrisTest): def test_NAMEIII_field(self): cubes = iris.load(tests.get_data_path(('NAME', 'NAMEIII_field.txt'))) @@ -42,6 +45,11 @@ def test_NAMEII_timeseries(self): 'NAMEII_timeseries.txt'))) self.assertCMLApproxData(cubes, ('name', 'NAMEII_timeseries.cml')) + def test_NAMEIII_version2(self): + cubes = iris.load(tests.get_data_path(('NAME', + 'NAMEIII_version2.txt'))) + self.assertCMLApproxData(cubes, ('name', 'NAMEIII_version2.cml')) + def test_NAMEII_trajectory(self): cubes = iris.load(tests.get_data_path(('NAME', 'NAMEIII_trajectory.txt'))) diff --git a/lib/iris/tests/test_netcdf.py b/lib/iris/tests/test_netcdf.py index baaefc0801..a942f4b398 100644 --- a/lib/iris/tests/test_netcdf.py +++ b/lib/iris/tests/test_netcdf.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -19,17 +19,20 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + # Import iris tests first so that some things can be initialised before # importing anything else. import iris.tests as tests import os +import os.path import shutil import stat import tempfile -import warnings -import mock import netCDF4 as nc import numpy as np import numpy.ma as ma @@ -41,14 +44,17 @@ import iris.std_names import iris.util import iris.coord_systems as icoord_systems +from iris.tests import mock import iris.tests.stock as stock +from iris._lazy_data import is_lazy_data -@iris.tests.skip_data +@tests.skip_data class TestNetCDFLoad(tests.IrisTest): def test_monotonic(self): cubes = iris.load(tests.get_data_path( ('NetCDF', 'testing', 'test_monotonic_coordinate.nc'))) + cubes = sorted(cubes, key=lambda cube: cube.var_name) self.assertCML(cubes, ('netcdf', 'netcdf_monotonic.cml')) def test_load_global_xyt_total(self): @@ -81,6 +87,7 @@ def test_load_global_xyzt_gems(self): # Test loading single xyzt CF-netCDF file (multi-cube). cubes = iris.load(tests.get_data_path(('NetCDF', 'global', 'xyz_t', 'GEMS_CO2_Apr2006.nc'))) + cubes = sorted(cubes, key=lambda cube: cube.name()) self.assertCML(cubes, ('netcdf', 'netcdf_global_xyzt_gems.cml')) # Check the masked array fill value is propogated through the data @@ -91,9 +98,11 @@ def test_load_global_xyzt_gems(self): def test_load_global_xyzt_gems_iter(self): # Test loading stepped single xyzt CF-netCDF file (multi-cube). - for i, cube in enumerate(iris.load( - tests.get_data_path(('NetCDF', 'global', 'xyz_t', - 'GEMS_CO2_Apr2006.nc')))): + for i, cube in enumerate(sorted( + iris.load( + tests.get_data_path(('NetCDF', 'global', 'xyz_t', + 'GEMS_CO2_Apr2006.nc'))), + key=lambda cube: cube.name())): self.assertCML(cube, ('netcdf', 'netcdf_global_xyzt_gems_iter_%d.cml' % i)) @@ -101,11 +110,9 @@ def test_load_rotated_xy_land(self): # Test loading single xy rotated pole CF-netCDF file. cube = iris.load_cube(tests.get_data_path( ('NetCDF', 'rotated', 'xy', 'rotPole_landAreaFraction.nc'))) - self.assertCML(cube, ('netcdf', 'netcdf_rotated_xy_land.cml')) - # Make sure the AuxCoords have lazy data. - self.assertIsInstance(cube.coord('latitude')._points, - iris.aux_factory.LazyArray) + self.assertTrue(is_lazy_data(cube.coord('latitude').core_points())) + self.assertCML(cube, ('netcdf', 'netcdf_rotated_xy_land.cml')) def test_load_rotated_xyt_precipitation(self): # Test loading single xyt rotated pole CF-netCDF file. @@ -145,6 +152,14 @@ def test_load_tmerc_grid_with_projection_origin(self): self.assertEqual(cube.coord('projection_y_coordinate').coord_system, expected) + def test_load_lcc_grid(self): + # Test loading a single CF-netCDF file with Lambert conformal conic + # grid mapping. + cube = iris.load_cube( + tests.get_data_path(('NetCDF', 'lambert_conformal', + 'test_lcc.nc'))) + self.assertCML(cube, ('netcdf', 'netcdf_lcc.cml')) + def test_missing_climatology(self): # Check we can cope with a missing climatology variable. with self.temp_filename(suffix='nc') as filename: @@ -158,6 +173,21 @@ def test_missing_climatology(self): dataset.close() cube = iris.load_cube(filename, 'Mean temperature') + def test_load_merc_grid(self): + # Test loading a single CF-netCDF file with a Mercator grid_mapping + cube = iris.load_cube( + tests.get_data_path(('NetCDF', 'mercator', + 'toa_brightness_temperature.nc'))) + self.assertCML(cube, ('netcdf', 'netcdf_merc.cml')) + + def test_load_stereographic_grid(self): + # Test loading a single CF-netCDF file with a stereographic + # grid_mapping. + cube = iris.load_cube( + tests.get_data_path(('NetCDF', 'stereographic', + 'toa_brightness_temperature.nc'))) + self.assertCML(cube, ('netcdf', 'netcdf_stereo.cml')) + def test_cell_methods(self): # Test exercising CF-netCDF cell method parsing. cubes = iris.load(tests.get_data_path(('NetCDF', 'testing', @@ -167,6 +197,15 @@ def test_cell_methods(self): # can pass by manual sorting... cubes = iris.cube.CubeList(sorted(cubes, key=lambda cube: cube.name())) + # TEST_COMPAT mod - different versions of the Python module + # `netCDF4` give different data arrays: MaskedArray vs ndarray + # Since we're not interested in the data we can just normalise + # to MaskedArray (to minimise the change). + for cube in cubes: + # Force the fill value to be the default netCDF fill value + # to ensure it matches the previous behaviour. + cube.data = ma.masked_equal(cube.data, -2147483647) + self.assertCML(cubes, ('netcdf', 'netcdf_cell_methods.cml')) def test_deferred_loading(self): @@ -206,8 +245,10 @@ def test_deferred_loading(self): def test_units(self): # Test exercising graceful cube and coordinate units loading. - cube0, cube1 = iris.load(tests.get_data_path(('NetCDF', 'testing', - 'units.nc'))) + cube0, cube1 = sorted(iris.load(tests.get_data_path(('NetCDF', + 'testing', + 'units.nc'))), + key=lambda cube: cube.var_name) self.assertCML(cube0, ('netcdf', 'netcdf_units_0.cml')) self.assertCML(cube1, ('netcdf', 'netcdf_units_1.cml')) @@ -259,30 +300,30 @@ def test_bad_permissions(self): os.rmdir(dir_name) +@tests.skip_data class TestSave(tests.IrisTest): def test_hybrid(self): cube = stock.realistic_4d() # Write Cube to netCDF file. - file_out = iris.util.create_temp_filename(suffix='.nc') - iris.save(cube, file_out, netcdf_format='NETCDF3_CLASSIC') + with self.temp_filename(suffix='.nc') as file_out: + iris.save(cube, file_out, netcdf_format='NETCDF3_CLASSIC') - # Check the netCDF file against CDL expected output. - self.assertCDL(file_out, ('netcdf', 'netcdf_save_realistic_4d.cdl')) - os.remove(file_out) + # Check the netCDF file against CDL expected output. + self.assertCDL(file_out, ('netcdf', + 'netcdf_save_realistic_4d.cdl')) def test_no_hybrid(self): cube = stock.realistic_4d() cube.remove_aux_factory(cube.aux_factories[0]) # Write Cube to netCDF file. - file_out = iris.util.create_temp_filename(suffix='.nc') - iris.save(cube, file_out, netcdf_format='NETCDF3_CLASSIC') + with self.temp_filename(suffix='.nc') as file_out: + iris.save(cube, file_out, netcdf_format='NETCDF3_CLASSIC') - # Check the netCDF file against CDL expected output. - self.assertCDL(file_out, ('netcdf', - 'netcdf_save_realistic_4d_no_hybrid.cdl')) - os.remove(file_out) + # Check the netCDF file against CDL expected output. + self.assertCDL( + file_out, ('netcdf', 'netcdf_save_realistic_4d_no_hybrid.cdl')) def test_scalar_cube(self): cube = stock.realistic_4d()[0, 0, 0, 0] @@ -341,50 +382,48 @@ def setUp(self): var_name='temp3', units='K') - @iris.tests.skip_data + @tests.skip_data def test_netcdf_save_format(self): # Read netCDF input file. file_in = tests.get_data_path( ('NetCDF', 'global', 'xyt', 'SMALL_total_column_co2.nc')) cube = iris.load_cube(file_in) - file_out = iris.util.create_temp_filename(suffix='.nc') - - # Test default NETCDF4 file format saving. - iris.save(cube, file_out) - ds = nc.Dataset(file_out) - self.assertEqual(ds.file_format, 'NETCDF4', - 'Failed to save as NETCDF4 format') - ds.close() - - # Test NETCDF4_CLASSIC file format saving. - iris.save(cube, file_out, netcdf_format='NETCDF4_CLASSIC') - ds = nc.Dataset(file_out) - self.assertEqual(ds.file_format, 'NETCDF4_CLASSIC', - 'Failed to save as NETCDF4_CLASSIC format') - ds.close() - - # Test NETCDF3_CLASSIC file format saving. - iris.save(cube, file_out, netcdf_format='NETCDF3_CLASSIC') - ds = nc.Dataset(file_out) - self.assertEqual(ds.file_format, 'NETCDF3_CLASSIC', - 'Failed to save as NETCDF3_CLASSIC format') - ds.close() - - # Test NETCDF4_64BIT file format saving. - iris.save(cube, file_out, netcdf_format='NETCDF3_64BIT') - ds = nc.Dataset(file_out) - self.assertEqual(ds.file_format, 'NETCDF3_64BIT', - 'Failed to save as NETCDF3_64BIT format') - ds.close() - - # Test invalid file format saving. - with self.assertRaises(ValueError): - iris.save(cube, file_out, netcdf_format='WIBBLE') - - os.remove(file_out) - - @iris.tests.skip_data + with self.temp_filename(suffix='.nc') as file_out: + # Test default NETCDF4 file format saving. + iris.save(cube, file_out) + ds = nc.Dataset(file_out) + self.assertEqual(ds.file_format, 'NETCDF4', + 'Failed to save as NETCDF4 format') + ds.close() + + # Test NETCDF4_CLASSIC file format saving. + iris.save(cube, file_out, netcdf_format='NETCDF4_CLASSIC') + ds = nc.Dataset(file_out) + self.assertEqual(ds.file_format, 'NETCDF4_CLASSIC', + 'Failed to save as NETCDF4_CLASSIC format') + ds.close() + + # Test NETCDF3_CLASSIC file format saving. + iris.save(cube, file_out, netcdf_format='NETCDF3_CLASSIC') + ds = nc.Dataset(file_out) + self.assertEqual(ds.file_format, 'NETCDF3_CLASSIC', + 'Failed to save as NETCDF3_CLASSIC format') + ds.close() + + # Test NETCDF4_64BIT file format saving. + iris.save(cube, file_out, netcdf_format='NETCDF3_64BIT') + ds = nc.Dataset(file_out) + self.assertTrue(ds.file_format in ['NETCDF3_64BIT', + 'NETCDF3_64BIT_OFFSET'], + 'Failed to save as NETCDF3_64BIT format') + ds.close() + + # Test invalid file format saving. + with self.assertRaises(ValueError): + iris.save(cube, file_out, netcdf_format='WIBBLE') + + @tests.skip_data def test_netcdf_save_single(self): # Test saving a single CF-netCDF file. # Read PP input file. @@ -394,16 +433,15 @@ def test_netcdf_save_single(self): cube = iris.load_cube(file_in) # Write Cube to netCDF file. - file_out = iris.util.create_temp_filename(suffix='.nc') - iris.save(cube, file_out) + with self.temp_filename(suffix='.nc') as file_out: + iris.save(cube, file_out) - # Check the netCDF file against CDL expected output. - self.assertCDL(file_out, ('netcdf', 'netcdf_save_single.cdl')) - os.remove(file_out) + # Check the netCDF file against CDL expected output. + self.assertCDL(file_out, ('netcdf', 'netcdf_save_single.cdl')) # TODO investigate why merge now make time an AuxCoord rather than a # DimCoord and why forecast_period is 'preferred'. - @iris.tests.skip_data + @tests.skip_data def test_netcdf_save_multi2multi(self): # Test saving multiple CF-netCDF files. # Read PP input file. @@ -414,16 +452,14 @@ def test_netcdf_save_multi2multi(self): # Save multiple cubes to multiple files. for index, cube in enumerate(cubes): # Write Cube to netCDF file. - file_out = iris.util.create_temp_filename(suffix='.nc') + with self.temp_filename(suffix='.nc') as file_out: + iris.save(cube, file_out) - iris.save(cube, file_out) - - # Check the netCDF file against CDL expected output. - self.assertCDL(file_out, ('netcdf', - 'netcdf_save_multi_%d.cdl' % index)) - os.remove(file_out) + # Check the netCDF file against CDL expected output. + self.assertCDL(file_out, ('netcdf', + 'netcdf_save_multi_%d.cdl' % index)) - @iris.tests.skip_data + @tests.skip_data def test_netcdf_save_multi2single(self): # Test saving multiple cubes to a single CF-netCDF file. # Read PP input file. @@ -432,34 +468,31 @@ def test_netcdf_save_multi2single(self): cubes = iris.load(file_in) # Write Cube to netCDF file. - file_out = iris.util.create_temp_filename(suffix='.nc') - - # Check that it is the same on loading - iris.save(cubes, file_out) + with self.temp_filename(suffix='.nc') as file_out: + # Check that it is the same on loading + iris.save(cubes, file_out) - # Check the netCDF file against CDL expected output. - self.assertCDL(file_out, ('netcdf', 'netcdf_save_multiple.cdl')) + # Check the netCDF file against CDL expected output. + self.assertCDL(file_out, ('netcdf', 'netcdf_save_multiple.cdl')) def test_netcdf_multi_nocoord(self): # Testing the saving of a cublist with no coords. cubes = iris.cube.CubeList([self.cube, self.cube2, self.cube3]) - file_out = iris.util.create_temp_filename(suffix='.nc') - iris.save(cubes, file_out) + with self.temp_filename(suffix='.nc') as file_out: + iris.save(cubes, file_out) - # Check the netCDF file against CDL expected output. - self.assertCDL(file_out, ('netcdf', 'netcdf_save_nocoord.cdl')) - os.remove(file_out) + # Check the netCDF file against CDL expected output. + self.assertCDL(file_out, ('netcdf', 'netcdf_save_nocoord.cdl')) def test_netcdf_multi_samevarnme(self): # Testing the saving of a cublist with cubes of the same var_name. self.cube2.var_name = self.cube.var_name cubes = iris.cube.CubeList([self.cube, self.cube2]) - file_out = iris.util.create_temp_filename(suffix='.nc') - iris.save(cubes, file_out) + with self.temp_filename(suffix='.nc') as file_out: + iris.save(cubes, file_out) - # Check the netCDF file against CDL expected output. - self.assertCDL(file_out, ('netcdf', 'netcdf_save_samevar.cdl')) - os.remove(file_out) + # Check the netCDF file against CDL expected output. + self.assertCDL(file_out, ('netcdf', 'netcdf_save_samevar.cdl')) def test_netcdf_multi_with_coords(self): # Testing the saving of a cublist with coordinates. @@ -479,12 +512,11 @@ def test_netcdf_multi_with_coords(self): self.cube2.add_dim_coord(rcoord, 0) cubes = iris.cube.CubeList([self.cube, self.cube2]) - file_out = iris.util.create_temp_filename(suffix='.nc') - iris.save(cubes, file_out) + with self.temp_filename(suffix='.nc') as file_out: + iris.save(cubes, file_out) - # Check the netCDF file against CDL expected output. - self.assertCDL(file_out, ('netcdf', 'netcdf_save_wcoord.cdl')) - os.remove(file_out) + # Check the netCDF file against CDL expected output. + self.assertCDL(file_out, ('netcdf', 'netcdf_save_wcoord.cdl')) def test_netcdf_multi_wtih_samedimcoord(self): time1 = iris.coords.DimCoord(np.arange(10), @@ -499,12 +531,12 @@ def test_netcdf_multi_wtih_samedimcoord(self): self.cube6.add_dim_coord(time1, 0) cubes = iris.cube.CubeList([self.cube4, self.cube5, self.cube6]) - file_out = iris.util.create_temp_filename(suffix='.nc') - iris.save(cubes, file_out) + with self.temp_filename(suffix='.nc') as file_out: + iris.save(cubes, file_out) - # Check the netCDF file against CDL expected output. - self.assertCDL(file_out, ('netcdf', 'netcdf_save_samedimcoord.cdl')) - os.remove(file_out) + # Check the netCDF file against CDL expected output. + self.assertCDL(file_out, ('netcdf', + 'netcdf_save_samedimcoord.cdl')) def test_netcdf_multi_conflict_name_dup_coord(self): # Duplicate coordinates with modified variable names lookup. @@ -520,39 +552,41 @@ def test_netcdf_multi_conflict_name_dup_coord(self): self.cube.add_dim_coord(time2[:], 0) cubes = iris.cube.CubeList([self.cube, self.cube6, self.cube6.copy()]) - file_out = iris.util.create_temp_filename(suffix='.nc') - iris.save(cubes, file_out) + with self.temp_filename(suffix='.nc') as file_out: + iris.save(cubes, file_out) - # Check the netCDF file against CDL expected output. - self.assertCDL(file_out, ('netcdf', - 'multi_dim_coord_slightly_different.cdl')) - os.remove(file_out) + # Check the netCDF file against CDL expected output. + self.assertCDL( + file_out, ('netcdf', 'multi_dim_coord_slightly_different.cdl')) - @iris.tests.skip_data + @tests.skip_data def test_netcdf_hybrid_height(self): # Test saving a CF-netCDF file which contains a hybrid height # (i.e. dimensionless vertical) coordinate. # Read PP input file. + names = ['air_potential_temperature', 'surface_altitude'] file_in = tests.get_data_path( ('PP', 'COLPEX', 'small_colpex_theta_p_alt.pp')) - cube = iris.load_cube(file_in, 'air_potential_temperature') + cube = iris.load_cube(file_in, names[0]) # Write Cube to netCDF file. - file_out = iris.util.create_temp_filename(suffix='.nc') - iris.save(cube, file_out) - - # Check the netCDF file against CDL expected output. - self.assertCDL(file_out, ('netcdf', 'netcdf_save_hybrid_height.cdl')) + with self.temp_filename(suffix='.nc') as file_out: + iris.save(cube, file_out) - # Read netCDF file. - cube = iris.load_cube(file_out) + # Check the netCDF file against CDL expected output. + self.assertCDL(file_out, + ('netcdf', 'netcdf_save_hybrid_height.cdl')) - # Check the PP read, netCDF write, netCDF read mechanism. - self.assertCML(cube, ('netcdf', 'netcdf_save_load_hybrid_height.cml')) + # Read netCDF file. + cubes = iris.load(file_out) + cubes_names = [c.name() for c in cubes] + self.assertEqual(cubes_names, names) - os.remove(file_out) + # Check the PP read, netCDF write, netCDF read mechanism. + self.assertCML(cubes.extract(names[0])[0], + ('netcdf', 'netcdf_save_load_hybrid_height.cml')) - @iris.tests.skip_data + @tests.skip_data def test_netcdf_save_ndim_auxiliary(self): # Test saving CF-netCDF with multi-dimensional auxiliary coordinates. # Read netCDF input file. @@ -561,19 +595,19 @@ def test_netcdf_save_ndim_auxiliary(self): cube = iris.load_cube(file_in) # Write Cube to nerCDF file. - file_out = iris.util.create_temp_filename(suffix='.nc') - iris.save(cube, file_out) - - # Check the netCDF file against CDL expected output. - self.assertCDL(file_out, ('netcdf', 'netcdf_save_ndim_auxiliary.cdl')) + with self.temp_filename(suffix='.nc') as file_out: + iris.save(cube, file_out) - # Read the netCDF file. - cube = iris.load_cube(file_out) + # Check the netCDF file against CDL expected output. + self.assertCDL(file_out, ('netcdf', + 'netcdf_save_ndim_auxiliary.cdl')) - # Check the netCDF read, write, read mechanism. - self.assertCML(cube, ('netcdf', 'netcdf_save_load_ndim_auxiliary.cml')) + # Read the netCDF file. + cube = iris.load_cube(file_out) - os.remove(file_out) + # Check the netCDF read, write, read mechanism. + self.assertCML(cube, ('netcdf', + 'netcdf_save_load_ndim_auxiliary.cml')) def test_netcdf_save_conflicting_aux(self): # Test saving CF-netCDF with multi-dimensional auxiliary coordinates, @@ -584,12 +618,11 @@ def test_netcdf_save_conflicting_aux(self): 'time'), 0) cubes = iris.cube.CubeList([self.cube4, self.cube6]) - file_out = iris.util.create_temp_filename(suffix='.nc') - iris.save(cubes, file_out) + with self.temp_filename(suffix='.nc') as file_out: + iris.save(cubes, file_out) - # Check the netCDF file against CDL expected output. - self.assertCDL(file_out, ('netcdf', 'netcdf_save_conf_aux.cdl')) - os.remove(file_out) + # Check the netCDF file against CDL expected output. + self.assertCDL(file_out, ('netcdf', 'netcdf_save_conf_aux.cdl')) def test_netcdf_save_gridmapping(self): # Test saving CF-netCDF from a cubelist with various grid mappings. @@ -603,33 +636,33 @@ def test_netcdf_save_gridmapping(self): coord_system3 = icoord_systems.RotatedGeogCS(30, 30) c1.add_dim_coord(iris.coords.DimCoord( - np.arange(1, 3), 'latitude', long_name='1', + np.arange(1, 3), 'latitude', long_name='1', units='degrees', coord_system=coord_system), 1) c1.add_dim_coord(iris.coords.DimCoord( - np.arange(1, 3), 'longitude', long_name='1', + np.arange(1, 3), 'longitude', long_name='1', units='degrees', coord_system=coord_system), 0) c2.add_dim_coord(iris.coords.DimCoord( - np.arange(1, 3), 'latitude', long_name='2', + np.arange(1, 3), 'latitude', long_name='2', units='degrees', coord_system=coord_system2), 1) c2.add_dim_coord(iris.coords.DimCoord( - np.arange(1, 3), 'longitude', long_name='2', + np.arange(1, 3), 'longitude', long_name='2', units='degrees', coord_system=coord_system2), 0) c3.add_dim_coord(iris.coords.DimCoord( - np.arange(1, 3), 'grid_latitude', long_name='3', + np.arange(1, 3), 'grid_latitude', long_name='3', units='degrees', coord_system=coord_system3), 1) c3.add_dim_coord(iris.coords.DimCoord( - np.arange(1, 3), 'grid_longitude', long_name='3', + np.arange(1, 3), 'grid_longitude', long_name='3', units='degrees', coord_system=coord_system3), 0) cubes = iris.cube.CubeList([c1, c2, c3]) - file_out = iris.util.create_temp_filename(suffix='.nc') - iris.save(cubes, file_out) + with self.temp_filename(suffix='.nc') as file_out: + iris.save(cubes, file_out) - # Check the netCDF file against CDL expected output. - self.assertCDL(file_out, ('netcdf', 'netcdf_save_gridmapmulti.cdl')) - os.remove(file_out) + # Check the netCDF file against CDL expected output. + self.assertCDL(file_out, ('netcdf', + 'netcdf_save_gridmapmulti.cdl')) def test_netcdf_save_conflicting_names(self): # Test saving CF-netCDF with a dimension name corresponding to @@ -639,14 +672,13 @@ def test_netcdf_save_conflicting_names(self): self.cube6.add_aux_coord(iris.coords.AuxCoord(1, 'time'), None) cubes = iris.cube.CubeList([self.cube4, self.cube6]) - file_out = iris.util.create_temp_filename(suffix='.nc') - iris.save(cubes, file_out) + with self.temp_filename(suffix='.nc') as file_out: + iris.save(cubes, file_out) - # Check the netCDF file against CDL expected output. - self.assertCDL(file_out, ('netcdf', 'netcdf_save_conf_name.cdl')) - os.remove(file_out) + # Check the netCDF file against CDL expected output. + self.assertCDL(file_out, ('netcdf', 'netcdf_save_conf_name.cdl')) - @iris.tests.skip_data + @tests.skip_data def test_trajectory(self): file_in = tests.get_data_path(('PP', 'aPPglob1', 'global.pp')) cube = iris.load_cube(file_in) @@ -661,24 +693,58 @@ def test_trajectory(self): with self.temp_filename(suffix='.nc') as temp_filename: iris.save(traj, temp_filename) reloaded = iris.load_cube(temp_filename) - self.assertCML(reloaded, ('netcdf', 'save_load_traj.cml')) + self.assertCML(reloaded, + ('netcdf', 'save_load_traj.cml'), + checksum=False) + self.assertArrayEqual(traj.data, reloaded.data) def test_attributes(self): # Should be global attributes. - self.cube.attributes['history'] = 'A long time ago...' - self.cube.attributes['title'] = 'Attribute test' - self.cube.attributes['foo'] = 'bar' - # Should be data varible attributes. - self.cube.attributes['standard_error_multiplier'] = 23 - self.cube.attributes['flag_masks'] = 'a' - self.cube.attributes['flag_meanings'] = 'b' - self.cube.attributes['flag_values'] = 'c' - self.cube.attributes['STASH'] = iris.fileformats.pp.STASH(1, 2, 3) + aglobals = {'history': 'A long time ago...', + 'title': 'Attribute test', + 'foo': 'bar'} + for k, v in six.iteritems(aglobals): + self.cube.attributes[k] = v # Should be overriden. - self.cube.attributes['conventions'] = 'TEST' + aover = {'Conventions': 'TEST'} + for k, v in six.iteritems(aover): + self.cube.attributes[k] = v + # Should be data varible attributes. + avars = {'standard_error_multiplier': 23, + 'flag_masks': 'a', + 'flag_meanings': 'b', + 'flag_values': 'c', + 'missing_value': 1.e20, + 'STASH': iris.fileformats.pp.STASH(1, 2, 3)} + for k, v in six.iteritems(avars): + self.cube.attributes[k] = v with self.temp_filename(suffix='.nc') as filename: iris.save(self.cube, filename) - self.assertCDL(filename, ('netcdf', 'netcdf_save_attr.cdl')) + # Load the dataset. + ds = nc.Dataset(filename, 'r') + exceptions = [] + # Should be global attributes. + for gkey in aglobals: + if getattr(ds, gkey) != aglobals.get(gkey): + exceptions.append('{} != {}'.format(getattr(ds, gkey), + aglobals.get(gkey))) + # Should be overriden. + for okey in aover: + if getattr(ds, okey) == aover.get(okey): + exceptions.append('{} != {}'.format(getattr(ds, okey), + avars.get(okey))) + dv = ds['temp'] + # Should be data varible attributes; + # except STASH -> um_stash_source. + for vkey in avars: + if vkey != 'STASH' and (getattr(dv, vkey) != avars.get(vkey)): + exceptions.append('{} != {}'.format(getattr(dv, vkey), + avars.get(vkey))) + if getattr(dv, 'um_stash_source') != avars.get('STASH'): + exc = '{} != {}'.format(getattr(dv, 'um_stash_source'), + avars.get(vkey)) + exceptions.append(exc) + self.assertEqual(exceptions, []) def test_conflicting_attributes(self): # Should be data variable attributes. @@ -844,7 +910,7 @@ def test_std_name_lookup_fail(self): self.assertFalse('phenomenon_time' in iris.std_names.STD_NAMES) -@iris.tests.skip_data +@tests.skip_data class TestNetCDFUKmoProcessFlags(tests.IrisTest): def test_process_flags(self): # Test single process flags @@ -854,19 +920,18 @@ def test_process_flags(self): ll_cube.attributes["ukmo__process_flags"] = (process_desc,) # Save cube to netCDF - temp_filename = iris.util.create_temp_filename(".nc") - iris.save(ll_cube, temp_filename) - - # Reload cube - cube = iris.load_cube(temp_filename) + with self.temp_filename(suffix='.nc') as temp_filename: + iris.save(ll_cube, temp_filename) - # Check correct number and type of flags - self.assertTrue(len(cube.attributes["ukmo__process_flags"]) == 1, - "Mismatch in number of process flags.") - process_flag = cube.attributes["ukmo__process_flags"][0] - self.assertEquals(process_flag, process_desc) + # Reload cube + cube = iris.load_cube(temp_filename) - os.remove(temp_filename) + # Check correct number and type of flags + self.assertTrue( + len(cube.attributes["ukmo__process_flags"]) == 1, + "Mismatch in number of process flags.") + process_flag = cube.attributes["ukmo__process_flags"][0] + self.assertEqual(process_flag, process_desc) # Test mutiple process flags multiple_bit_values = ((128, 64), (4096, 1024), (8192, 1024)) @@ -875,25 +940,23 @@ def test_process_flags(self): multiple_map = {bits: [iris.fileformats.pp.lbproc_map[bit] for bit in bits] for bits in multiple_bit_values} - for bits, descriptions in multiple_map.iteritems(): + for bits, descriptions in six.iteritems(multiple_map): ll_cube = stock.lat_lon_cube() ll_cube.attributes["ukmo__process_flags"] = descriptions # Save cube to netCDF - temp_filename = iris.util.create_temp_filename(".nc") - iris.save(ll_cube, temp_filename) - - # Reload cube - cube = iris.load_cube(temp_filename) + with self.temp_filename(suffix='.nc') as temp_filename: + iris.save(ll_cube, temp_filename) - # Check correct number and type of flags - process_flags = cube.attributes["ukmo__process_flags"] - self.assertTrue(len(process_flags) == len(bits), 'Mismatch in ' - 'number of process flags.') - self.assertEquals(set(process_flags), set(descriptions)) + # Reload cube + cube = iris.load_cube(temp_filename) - os.remove(temp_filename) + # Check correct number and type of flags + process_flags = cube.attributes["ukmo__process_flags"] + self.assertTrue(len(process_flags) == len(bits), 'Mismatch in ' + 'number of process flags.') + self.assertEqual(set(process_flags), set(descriptions)) if __name__ == "__main__": diff --git a/lib/iris/tests/test_nimrod.py b/lib/iris/tests/test_nimrod.py index 2f67fa220d..136544e1a9 100644 --- a/lib/iris/tests/test_nimrod.py +++ b/lib/iris/tests/test_nimrod.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -15,6 +15,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before # importing anything else @@ -34,8 +36,7 @@ def mock_nimrod_field(): class TestLoad(tests.IrisTest): - - @iris.tests.skip_data + @tests.skip_data def test_multi_field_load(self): # load a cube with two fields cube = iris.load(tests.get_data_path( diff --git a/lib/iris/tests/test_pandas.py b/lib/iris/tests/test_pandas.py index 682ec65adf..51a163b728 100644 --- a/lib/iris/tests/test_pandas.py +++ b/lib/iris/tests/test_pandas.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2018, Met Office # # This file is part of Iris. # @@ -15,22 +15,33 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before # importing anything else import iris.tests as tests +import copy import datetime import unittest -import netcdftime +import cf_units +import cftime +import matplotlib.units +import netCDF4 import numpy as np + +# Importing pandas has the side-effect of messing with the formatters +# used by matplotlib for handling dates. +default_units_registry = copy.copy(matplotlib.units.registry) try: import pandas except ImportError: # Disable all these tests if pandas is not installed. pandas = None +matplotlib.units.registry = default_units_registry skip_pandas = unittest.skipIf(pandas is None, 'Test(s) require "pandas", ' @@ -40,7 +51,6 @@ from iris.coords import DimCoord from iris.cube import Cube import iris.pandas - import iris.unit @skip_pandas @@ -50,30 +60,24 @@ class TestAsSeries(tests.IrisTest): def test_no_dim_coord(self): cube = Cube(np.array([0, 1, 2, 3, 4]), long_name="foo") series = iris.pandas.as_series(cube) + expected_index = np.array([0, 1, 2, 3, 4]) self.assertArrayEqual(series, cube.data) - self.assertString( - str(series), - tests.get_result_path(('pandas', 'as_series', - 'no_dim_coord.txt'))) + self.assertArrayEqual(series.index, expected_index) def test_simple(self): cube = Cube(np.array([0, 1, 2, 3, 4.4]), long_name="foo") dim_coord = DimCoord([5, 6, 7, 8, 9], long_name="bar") cube.add_dim_coord(dim_coord, 0) + expected_index = np.array([5, 6, 7, 8, 9]) series = iris.pandas.as_series(cube) self.assertArrayEqual(series, cube.data) - self.assertString( - str(series), - tests.get_result_path(('pandas', 'as_series', 'simple.txt'))) + self.assertArrayEqual(series.index, expected_index) def test_masked(self): data = np.ma.MaskedArray([0, 1, 2, 3, 4.4], mask=[0, 1, 0, 1, 0]) cube = Cube(data, long_name="foo") series = iris.pandas.as_series(cube) self.assertArrayEqual(series, cube.data.astype('f').filled(np.nan)) - self.assertString( - str(series), - tests.get_result_path(('pandas', 'as_series', 'masked.txt'))) def test_time_gregorian(self): cube = Cube(np.array([0, 1, 2, 3, 4]), long_name="ts") @@ -81,26 +85,31 @@ def test_time_gregorian(self): long_name="time", units="days since 2000-01-01 00:00") cube.add_dim_coord(time_coord, 0) + expected_index = [datetime.datetime(2000, 1, 1, 0, 0), + datetime.datetime(2000, 4, 10, 2, 24), + datetime.datetime(2000, 7, 19, 4, 48), + datetime.datetime(2000, 10, 27, 7, 12), + datetime.datetime(2001, 2, 4, 9, 36)] series = iris.pandas.as_series(cube) self.assertArrayEqual(series, cube.data) - self.assertString( - str(series), - tests.get_result_path(('pandas', 'as_series', - 'time_gregorian.txt'))) + self.assertListEqual(list(series.index), expected_index) def test_time_360(self): cube = Cube(np.array([0, 1, 2, 3, 4]), long_name="ts") - time_unit = iris.unit.Unit("days since 2000-01-01 00:00", - calendar=iris.unit.CALENDAR_360_DAY) + time_unit = cf_units.Unit("days since 2000-01-01 00:00", + calendar=cf_units.CALENDAR_360_DAY) time_coord = DimCoord([0, 100.1, 200.2, 300.3, 400.4], long_name="time", units=time_unit) cube.add_dim_coord(time_coord, 0) + expected_index = [cftime.Datetime360Day(2000, 1, 1, 0, 0), + cftime.Datetime360Day(2000, 4, 11, 2, 24), + cftime.Datetime360Day(2000, 7, 21, 4, 48), + cftime.Datetime360Day(2000, 11, 1, 7, 12), + cftime.Datetime360Day(2001, 2, 11, 9, 36)] + series = iris.pandas.as_series(cube) self.assertArrayEqual(series, cube.data) - self.assertString( - str(series), - tests.get_result_path(('pandas', 'as_series', - 'time_360.txt'))) + self.assertArrayEqual(series.index, expected_index) def test_copy_true(self): cube = Cube(np.array([0, 1, 2, 3, 4]), long_name="foo") @@ -147,36 +156,36 @@ class TestAsDataFrame(tests.IrisTest): def test_no_dim_coords(self): cube = Cube(np.array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]), long_name="foo") + expected_index = [0, 1] + expected_columns = [0, 1, 2, 3, 4] data_frame = iris.pandas.as_data_frame(cube) self.assertArrayEqual(data_frame, cube.data) - self.assertString( - str(data_frame), - tests.get_result_path(('pandas', 'as_dataframe', - 'no_dim_coords.txt'))) + self.assertArrayEqual(data_frame.index, expected_index) + self.assertArrayEqual(data_frame.columns, expected_columns) def test_no_x_coord(self): cube = Cube(np.array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]), long_name="foo") y_coord = DimCoord([10, 11], long_name="bar") cube.add_dim_coord(y_coord, 0) + expected_index = [10, 11] + expected_columns = [0, 1, 2, 3, 4] data_frame = iris.pandas.as_data_frame(cube) self.assertArrayEqual(data_frame, cube.data) - self.assertString( - str(data_frame), - tests.get_result_path(('pandas', 'as_dataframe', - 'no_x_coord.txt'))) + self.assertArrayEqual(data_frame.index, expected_index) + self.assertArrayEqual(data_frame.columns, expected_columns) def test_no_y_coord(self): cube = Cube(np.array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]), long_name="foo") x_coord = DimCoord([10, 11, 12, 13, 14], long_name="bar") cube.add_dim_coord(x_coord, 1) + expected_index = [0, 1] + expected_columns = [10, 11, 12, 13, 14] data_frame = iris.pandas.as_data_frame(cube) self.assertArrayEqual(data_frame, cube.data) - self.assertString( - str(data_frame), - tests.get_result_path(('pandas', 'as_dataframe', - 'no_y_coord.txt'))) + self.assertArrayEqual(data_frame.index, expected_index) + self.assertArrayEqual(data_frame.columns, expected_columns) def test_simple(self): cube = Cube(np.array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]), @@ -185,23 +194,23 @@ def test_simple(self): y_coord = DimCoord([15, 16], long_name="milk") cube.add_dim_coord(x_coord, 1) cube.add_dim_coord(y_coord, 0) + expected_index = [15, 16] + expected_columns = [10, 11, 12, 13, 14] data_frame = iris.pandas.as_data_frame(cube) self.assertArrayEqual(data_frame, cube.data) - self.assertString( - str(data_frame), - tests.get_result_path(('pandas', 'as_dataframe', - 'simple.txt'))) + self.assertArrayEqual(data_frame.index, expected_index) + self.assertArrayEqual(data_frame.columns, expected_columns) def test_masked(self): data = np.ma.MaskedArray([[0, 1, 2, 3, 4.4], [5, 6, 7, 8, 9]], mask=[[0, 1, 0, 1, 0], [1, 0, 1, 0, 1]]) cube = Cube(data, long_name="foo") + expected_index = [0, 1] + expected_columns = [0, 1, 2, 3, 4] data_frame = iris.pandas.as_data_frame(cube) self.assertArrayEqual(data_frame, cube.data.astype('f').filled(np.nan)) - self.assertString( - str(data_frame), - tests.get_result_path(('pandas', 'as_dataframe', - 'masked.txt'))) + self.assertArrayEqual(data_frame.index, expected_index) + self.assertArrayEqual(data_frame.columns, expected_columns) def test_time_gregorian(self): cube = Cube(np.array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]), @@ -224,17 +233,19 @@ def test_time_gregorian(self): def test_time_360(self): cube = Cube(np.array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]), long_name="ts") - time_unit = iris.unit.Unit("days since 2000-01-01 00:00", - calendar=iris.unit.CALENDAR_360_DAY) + time_unit = cf_units.Unit("days since 2000-01-01 00:00", + calendar=cf_units.CALENDAR_360_DAY) time_coord = DimCoord([100.1, 200.2], long_name="time", units=time_unit) cube.add_dim_coord(time_coord, 0) + expected_index = [cftime.Datetime360Day(2000, 4, 11, 2, 24), + cftime.Datetime360Day(2000, 7, 21, 4, 48)] + + expected_columns = [0, 1, 2, 3, 4] data_frame = iris.pandas.as_data_frame(cube) self.assertArrayEqual(data_frame, cube.data) - self.assertString( - str(data_frame), - tests.get_result_path(('pandas', 'as_dataframe', - 'time_360.txt'))) + self.assertArrayEqual(data_frame.index, expected_index) + self.assertArrayEqual(data_frame.columns, expected_columns) def test_copy_true(self): cube = Cube(np.array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]), @@ -279,6 +290,13 @@ def test_copy_masked_false(self): with self.assertRaises(ValueError): data_frame = iris.pandas.as_data_frame(cube, copy=False) + def test_copy_false_with_cube_view(self): + data = np.array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]) + cube = Cube(data[:], long_name="foo") + data_frame = iris.pandas.as_data_frame(cube, copy=False) + data_frame[0][0] = 99 + self.assertEqual(cube.data[0, 0], 99) + @skip_pandas class TestSeriesAsCube(tests.IrisTest): @@ -310,27 +328,27 @@ def test_series_masked(self): def test_series_datetime_gregorian(self): series = pandas.Series( [0, 1, 2, 3, 4], - index=[datetime.datetime(2001, 01, 01, 01, 01, 01), - datetime.datetime(2002, 02, 02, 02, 02, 02), - datetime.datetime(2003, 03, 03, 03, 03, 03), - datetime.datetime(2004, 04, 04, 04, 04, 04), - datetime.datetime(2005, 05, 05, 05, 05, 05)]) + index=[datetime.datetime(2001, 1, 1, 1, 1, 1), + datetime.datetime(2002, 2, 2, 2, 2, 2), + datetime.datetime(2003, 3, 3, 3, 3, 3), + datetime.datetime(2004, 4, 4, 4, 4, 4), + datetime.datetime(2005, 5, 5, 5, 5, 5)]) self.assertCML( iris.pandas.as_cube(series), tests.get_result_path(('pandas', 'as_cube', 'series_datetime_gregorian.cml'))) - def test_series_netcdftime_360(self): + def test_series_cftime_360(self): series = pandas.Series( [0, 1, 2, 3, 4], - index=[netcdftime.datetime(2001, 01, 01, 01, 01, 01), - netcdftime.datetime(2002, 02, 02, 02, 02, 02), - netcdftime.datetime(2003, 03, 03, 03, 03, 03), - netcdftime.datetime(2004, 04, 04, 04, 04, 04), - netcdftime.datetime(2005, 05, 05, 05, 05, 05)]) + index=[cftime.datetime(2001, 1, 1, 1, 1, 1), + cftime.datetime(2002, 2, 2, 2, 2, 2), + cftime.datetime(2003, 3, 3, 3, 3, 3), + cftime.datetime(2004, 4, 4, 4, 4, 4), + cftime.datetime(2005, 5, 5, 5, 5, 5)]) self.assertCML( iris.pandas.as_cube(series, - calendars={0: iris.unit.CALENDAR_360_DAY}), + calendars={0: cf_units.CALENDAR_360_DAY}), tests.get_result_path(('pandas', 'as_cube', 'series_netcdfimte_360.cml'))) @@ -380,17 +398,28 @@ def test_data_frame_masked(self): tests.get_result_path(('pandas', 'as_cube', 'data_frame_masked.cml'))) - def test_data_frame_netcdftime_360(self): + def test_data_frame_multidim(self): + data_frame = pandas.DataFrame([[0, 1, 2, 3, 4], + [5, 6, 7, 8, 9]], + index=[0, 1], + columns=['col_1', 'col_2', 'col_3', + 'col_4', 'col_5']) + self.assertCML( + iris.pandas.as_cube(data_frame), + tests.get_result_path(('pandas', 'as_cube', + 'data_frame_multidim.cml'))) + + def test_data_frame_cftime_360(self): data_frame = pandas.DataFrame( [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]], - index=[netcdftime.datetime(2001, 01, 01, 01, 01, 01), - netcdftime.datetime(2002, 02, 02, 02, 02, 02)], + index=[cftime.datetime(2001, 1, 1, 1, 1, 1), + cftime.datetime(2002, 2, 2, 2, 2, 2)], columns=[10, 11, 12, 13, 14]) self.assertCML( iris.pandas.as_cube( data_frame, - calendars={0: iris.unit.CALENDAR_360_DAY}), + calendars={0: cf_units.CALENDAR_360_DAY}), tests.get_result_path(('pandas', 'as_cube', 'data_frame_netcdftime_360.cml'))) @@ -398,8 +427,8 @@ def test_data_frame_datetime_gregorian(self): data_frame = pandas.DataFrame( [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]], - index=[datetime.datetime(2001, 01, 01, 01, 01, 01), - datetime.datetime(2002, 02, 02, 02, 02, 02)], + index=[datetime.datetime(2001, 1, 1, 1, 1, 1), + datetime.datetime(2002, 2, 2, 2, 2, 2)], columns=[10, 11, 12, 13, 14]) self.assertCML( iris.pandas.as_cube(data_frame), diff --git a/lib/iris/tests/test_peak.py b/lib/iris/tests/test_peak.py index 371be5f1b8..5f37c89a84 100644 --- a/lib/iris/tests/test_peak.py +++ b/lib/iris/tests/test_peak.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -15,6 +15,10 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import iris.analysis import iris.tests as tests import iris.tests.stock import numpy as np @@ -38,7 +42,7 @@ def test_peak_coord_length_1(self): def test_peak_coord_length_2(self): # Coordinate contains 2 points. - latitude = iris.coords.DimCoord(range(0, 2, 1), + latitude = iris.coords.DimCoord(np.arange(0, 2, 1), standard_name='latitude', units='degrees') cube = iris.cube.Cube(np.array([1, 2]), @@ -52,7 +56,7 @@ def test_peak_coord_length_2(self): def test_peak_coord_length_3(self): # Coordinate contains 3 points. - latitude = iris.coords.DimCoord(range(0, 3, 1), + latitude = iris.coords.DimCoord(np.arange(0, 3, 1), standard_name='latitude', units='degrees') cube = iris.cube.Cube(np.array([1, 2, 1]), @@ -66,7 +70,7 @@ def test_peak_coord_length_3(self): def test_peak_1d(self): # Collapse a 1d cube. - latitude = iris.coords.DimCoord(range(0, 11, 1), + latitude = iris.coords.DimCoord(np.arange(0, 11, 1), standard_name='latitude', units='degrees') cube = iris.cube.Cube(np.array([1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]), @@ -80,7 +84,7 @@ def test_peak_1d(self): def test_peak_duplicate_coords(self): # Collapse cube along 2 coordinates (both the same). - latitude = iris.coords.DimCoord(range(0, 4, 1), + latitude = iris.coords.DimCoord(np.arange(0, 4, 1), standard_name='latitude', units='degrees') cube = iris.cube.Cube(np.array([1, 2, 3, 1]), @@ -99,10 +103,10 @@ def test_peak_duplicate_coords(self): def test_peak_2d(self): # Collapse a 2d cube. - longitude = iris.coords.DimCoord(range(0, 4, 1), + longitude = iris.coords.DimCoord(np.arange(0, 4, 1), standard_name='longitude', units='degrees') - latitude = iris.coords.DimCoord(range(0, 3, 1), + latitude = iris.coords.DimCoord(np.arange(0, 3, 1), standard_name='latitude', units='degrees') cube = iris.cube.Cube(np.array([[1, 2, 3, 1], [4, 5, 7, 4], @@ -136,7 +140,7 @@ def test_peak_2d(self): def test_peak_without_peak_value(self): # No peak in column (values equal). - latitude = iris.coords.DimCoord(range(0, 4, 1), + latitude = iris.coords.DimCoord(np.arange(0, 4, 1), standard_name='latitude', units='degrees') cube = iris.cube.Cube(np.array([1, 1, 1, 1]), @@ -150,7 +154,7 @@ def test_peak_without_peak_value(self): def test_peak_with_nan(self): # Single nan in column. - latitude = iris.coords.DimCoord(range(0, 5, 1), + latitude = iris.coords.DimCoord(np.arange(0, 5, 1), standard_name='latitude', units='degrees') cube = iris.cube.Cube(np.array([1, 4, 2, 3, 1], dtype=np.float32), @@ -174,7 +178,7 @@ def test_peak_with_nan(self): def test_peak_with_mask(self): # Single value in column masked. - latitude = iris.coords.DimCoord(range(0, 5, 1), + latitude = iris.coords.DimCoord(np.arange(0, 5, 1), standard_name='latitude', units='degrees') cube = iris.cube.Cube(ma.array([1, 4, 2, 3, 2], dtype=np.float32), @@ -201,7 +205,7 @@ def test_peak_with_mask(self): def test_peak_with_nan_and_mask(self): # Single nan in column with single value masked. - latitude = iris.coords.DimCoord(range(0, 5, 1), + latitude = iris.coords.DimCoord(np.arange(0, 5, 1), standard_name='latitude', units='degrees') cube = iris.cube.Cube(ma.array([1, 4, 2, 3, 1], dtype=np.float32), @@ -228,7 +232,7 @@ def test_peak_with_nan_and_mask(self): def test_peak_against_max(self): # Cube with data that infers a peak value greater than the column max. - latitude = iris.coords.DimCoord(range(0, 7, 1), + latitude = iris.coords.DimCoord(np.arange(0, 7, 1), standard_name='latitude', units='degrees') cube = iris.cube.Cube(np.array([0, 1, 3, 7, 7, 4, 2], diff --git a/lib/iris/tests/test_pickling.py b/lib/iris/tests/test_pickling.py index 2d19c4e45d..b94ddfd947 100644 --- a/lib/iris/tests/test_pickling.py +++ b/lib/iris/tests/test_pickling.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -18,52 +18,65 @@ Test pickling of Iris objects. """ -from __future__ import with_statement -# import iris tests first so that some things can be initialised before importing anything else +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris tests first so that some things can be initialised +# before importing anything else. import iris.tests as tests -import cPickle -import StringIO +import six.moves.cPickle as pickle +import io -import biggus -import numpy as np +import cf_units import iris +from iris._lazy_data import as_concrete_data class TestPickle(tests.IrisTest): def pickle_then_unpickle(self, obj): - """Returns a generator of ("cpickle protocol number", object) tuples.""" - for protocol in xrange(1 + cPickle.HIGHEST_PROTOCOL): - str_buffer = StringIO.StringIO() - cPickle.dump(obj, str_buffer, protocol) + """ + Returns a generator of ("cpickle protocol number", object) tuples. + + """ + for protocol in range(1 + pickle.HIGHEST_PROTOCOL): + bio = io.BytesIO() + pickle.dump(obj, bio, protocol) - # move the str_buffer back to the start and reconstruct - str_buffer.seek(0) - reconstructed_obj = cPickle.load(str_buffer) + # move the bio back to the start and reconstruct + bio.seek(0) + reconstructed_obj = pickle.load(bio) yield protocol, reconstructed_obj + @staticmethod + def _real_data(cube): + # Get the concrete data of the cube for performing data values + # comparison checks. + return as_concrete_data(cube.core_data()) + def assertCubeData(self, cube1, cube2): - np.testing.assert_array_equal(cube1.lazy_data().ndarray(), - cube2.lazy_data().ndarray()) + self.assertArrayEqual(self._real_data(cube1), self._real_data(cube2)) - @iris.tests.skip_data + @tests.skip_data def test_cube_pickle(self): - cube = iris.load_cube(tests.get_data_path(('PP', 'globClim1', 'theta.pp'))) + cube = iris.load_cube(tests.get_data_path(('PP', + 'globClim1', + 'theta.pp'))) self.assertTrue(cube.has_lazy_data()) - self.assertCML(cube, ('cube_io', 'pickling', 'theta.cml'), checksum=False) + self.assertCML(cube, ('cube_io', 'pickling', 'theta.cml'), + checksum=False) - for _, recon_cube in self.pickle_then_unpickle(cube): + for p, recon_cube in self.pickle_then_unpickle(cube): self.assertTrue(recon_cube.has_lazy_data()) - self.assertCML(recon_cube, ('cube_io', 'pickling', 'theta.cml'), checksum=False) + self.assertCML(recon_cube, ('cube_io', 'pickling', 'theta.cml'), + checksum=False) self.assertCubeData(cube, recon_cube) - @iris.tests.skip_data - def test_cube_with_deferred_coord_points(self): - # Data with 2d lats and lons that when loaded results in points that - # are LazyArray objects. + @tests.skip_data + def test_cube_with_coord_points(self): filename = tests.get_data_path(('NetCDF', 'rotated', 'xy', @@ -74,37 +87,42 @@ def test_cube_with_deferred_coord_points(self): _, recon_cube = next(self.pickle_then_unpickle(cube)) self.assertEqual(recon_cube, cube) - @iris.tests.skip_data + @tests.skip_data def test_cubelist_pickle(self): - cubelist = iris.load(tests.get_data_path(('PP', 'COLPEX', 'theta_and_orog_subset.pp'))) + cubelist = iris.load(tests.get_data_path(('PP', 'COLPEX', + 'theta_and_orog_subset.pp'))) single_cube = cubelist[0] self.assertCML(cubelist, ('cube_io', 'pickling', 'cubelist.cml')) self.assertCML(single_cube, ('cube_io', 'pickling', 'single_cube.cml')) for _, reconstructed_cubelist in self.pickle_then_unpickle(cubelist): - self.assertCML(reconstructed_cubelist, ('cube_io', 'pickling', 'cubelist.cml')) - self.assertCML(reconstructed_cubelist[0], ('cube_io', 'pickling', 'single_cube.cml')) + self.assertCML(reconstructed_cubelist, ('cube_io', 'pickling', + 'cubelist.cml')) + self.assertCML(reconstructed_cubelist[0], ('cube_io', 'pickling', + 'single_cube.cml')) - for cube_orig, cube_reconstruct in zip(cubelist, reconstructed_cubelist): + for cube_orig, cube_reconstruct in zip(cubelist, + reconstructed_cubelist): self.assertArrayEqual(cube_orig.data, cube_reconstruct.data) self.assertEqual(cube_orig, cube_reconstruct) def test_picking_equality_misc(self): items_to_test = [ - iris.unit.Unit("hours since 2007-01-15 12:06:00", calendar=iris.unit.CALENDAR_STANDARD), - iris.unit.as_unit('1'), - iris.unit.as_unit('meters'), - iris.unit.as_unit('no-unit'), - iris.unit.as_unit('unknown') + cf_units.Unit("hours since 2007-01-15 12:06:00", + calendar=cf_units.CALENDAR_STANDARD), + cf_units.as_unit('1'), + cf_units.as_unit('meters'), + cf_units.as_unit('no-unit'), + cf_units.as_unit('unknown') ] for orig_item in items_to_test: - for protocol, reconstructed_item in self.pickle_then_unpickle(orig_item): - fail_msg = ('Items are different after pickling at protocol %s.' - '\nOrig item: %r\nNew item: %r' % (protocol, orig_item, reconstructed_item) - ) - self.assertEqual(orig_item, reconstructed_item, fail_msg) + for protocol, reconst_item in self.pickle_then_unpickle(orig_item): + fail_msg = ('Items are different after pickling ' + 'at protocol {}.\nOrig item: {!r}\nNew item: {!r}') + fail_msg = fail_msg.format(protocol, orig_item, reconst_item) + self.assertEqual(orig_item, reconst_item, fail_msg) if __name__ == "__main__": diff --git a/lib/iris/tests/test_plot.py b/lib/iris/tests/test_plot.py index b345d4762c..0a8e0e44f8 100644 --- a/lib/iris/tests/test_plot.py +++ b/lib/iris/tests/test_plot.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -15,6 +15,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six # import iris tests first so that some things can be initialised before # importing anything else @@ -24,18 +27,22 @@ import types import warnings -import matplotlib.pyplot as plt +import cf_units import numpy as np import iris import iris.coords as coords -import iris.plot as iplt -import iris.quickplot as qplt -import iris.symbols import iris.tests.stock -import iris.tests.test_mapping as test_mapping +# Run tests in no graphics mode if matplotlib is not available. +if tests.MPL_AVAILABLE: + import matplotlib.pyplot as plt + import iris.plot as iplt + import iris.quickplot as qplt + import iris.symbols + +@tests.skip_data def simple_cube(): cube = iris.tests.stock.realistic_4d() cube = cube[:, 0, 0, :] @@ -43,6 +50,7 @@ def simple_cube(): return cube +@tests.skip_plot class TestSimple(tests.GraphicsTest): def test_points(self): cube = simple_cube() @@ -55,6 +63,7 @@ def test_bounds(self): self.check_graphic() +@tests.skip_plot class TestMissingCoord(tests.GraphicsTest): def _check(self, cube): qplt.contourf(cube) @@ -80,9 +89,10 @@ def test_none(self): self._check(cube) -@iris.tests.skip_data +@tests.skip_data +@tests.skip_plot class TestMissingCS(tests.GraphicsTest): - @iris.tests.skip_data + @tests.skip_data def test_missing_cs(self): cube = tests.stock.simple_pp() cube.coord("latitude").coord_system = None @@ -92,8 +102,11 @@ def test_missing_cs(self): self.check_graphic() +@tests.skip_plot +@tests.skip_data class TestHybridHeight(tests.GraphicsTest): def setUp(self): + super(TestHybridHeight, self).setUp() self.cube = iris.tests.stock.realistic_4d()[0, :15, 0, :] def _check(self, plt_method, test_altitude=True): @@ -139,10 +152,13 @@ def test_orography(self): self.check_graphic() +@tests.skip_plot +@tests.skip_data class Test1dPlotMultiArgs(tests.GraphicsTest): # tests for iris.plot using multi-argument calling convention def setUp(self): + super(Test1dPlotMultiArgs, self).setUp() self.cube1d = _load_4d_testcube()[0, :, 0, 0] self.draw_method = iplt.plot @@ -190,8 +206,8 @@ def test_cube_cube(self): cube2 = self.cube1d.copy() cube1.rename('some phenomenon') cube2.rename('some other phenomenon') - cube1.units = iris.unit.Unit('no_unit') - cube2.units = iris.unit.Unit('no_unit') + cube1.units = cf_units.Unit('no_unit') + cube2.units = cf_units.Unit('no_unit') cube1.data[:] = np.linspace(0, 1, 7) cube2.data[:] = np.exp(cube1.data) self.draw_method(cube1, cube2) @@ -215,40 +231,29 @@ def test_not_cube_or_coord(self): with self.assertRaises(TypeError): self.draw_method(xdim, self.cube1d) - def test_coords_deprecated(self): - # ensure a warning is raised if the old coords keyword argument is - # used, and make sure the plot produced is consistent with the old - # interface - msg = 'Missing deprecation warning for coords keyword.' - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter('always') - self.draw_method(self.cube1d, coords=['sigma']) - self.assertEqual(len(w), 1, msg) - self.check_graphic() - - def test_coords_deprecation_too_many(self): - # in deprecation mode, too many coords is an error - with self.assertRaises(ValueError): - self.draw_method(self.cube1d, coords=['sigma', 'sigma']) - - def test_coords_deprecation_invalid_span(self): - # in deprecation mode, a coordinate that doesn't span data is an error - with self.assertRaises(ValueError): - self.draw_method(self.cube1d, coords=['time']) + def test_plot_old_coords_kwarg(self): + # Coords used to be a valid kwarg to plot, but it was deprecated and + # we are maintaining a reasonable exception, check that it is raised + # here. + with self.assertRaises(TypeError): + self.draw_method(self.cube1d, coords=None) +@tests.skip_plot class Test1dQuickplotPlotMultiArgs(Test1dPlotMultiArgs): # tests for iris.plot using multi-argument calling convention def setUp(self): + tests.GraphicsTest.setUp(self) self.cube1d = _load_4d_testcube()[0, :, 0, 0] self.draw_method = qplt.plot @tests.skip_data +@tests.skip_plot class Test1dScatter(tests.GraphicsTest): - def setUp(self): + super(Test1dScatter, self).setUp() self.cube = iris.load_cube( tests.get_data_path(('NAME', 'NAMEIII_trajectory.txt')), 'Temperature') @@ -256,7 +261,7 @@ def setUp(self): def test_coord_coord(self): x = self.cube.coord('longitude') - y = self.cube.coord('height') + y = self.cube.coord('altitude') c = self.cube.data self.draw_method(x, y, c=c, edgecolor='none') self.check_graphic() @@ -278,7 +283,7 @@ def test_coord_cube(self): def test_cube_coord(self): x = self.cube - y = self.cube.coord('height') + y = self.cube.coord('altitude') c = self.cube.coord('Travel Time').points self.draw_method(x, y, c=c, edgecolor='none') self.check_graphic() @@ -295,7 +300,7 @@ def test_cube_cube(self): def test_incompatible_objects(self): # cubes/coordinates of different sizes cannot be plotted x = self.cube - y = self.cube.coord('height')[:-1] + y = self.cube.coord('altitude')[:-1] with self.assertRaises(ValueError): self.draw_method(x, y) @@ -315,16 +320,18 @@ def test_not_cube_or_coord(self): @tests.skip_data +@tests.skip_plot class Test1dQuickplotScatter(Test1dScatter): - def setUp(self): + tests.GraphicsTest.setUp(self) self.cube = iris.load_cube( tests.get_data_path(('NAME', 'NAMEIII_trajectory.txt')), 'Temperature') self.draw_method = qplt.scatter -@iris.tests.skip_data +@tests.skip_data +@tests.skip_plot class TestAttributePositive(tests.GraphicsTest): def test_1d_positive_up(self): path = tests.get_data_path(('NetCDF', 'ORCA2', 'votemper.nc')) @@ -341,7 +348,7 @@ def test_1d_positive_down(self): def test_2d_positive_up(self): path = tests.get_data_path(('NetCDF', 'testing', 'small_theta_colpex.nc')) - cube = iris.load_cube(path)[0, :, 42, :] + cube = iris.load_cube(path, 'air_potential_temperature')[0, :, 42, :] qplt.pcolormesh(cube) self.check_graphic() @@ -363,6 +370,7 @@ def inner(*args, **kwargs): @cache +@tests.skip_data def _load_4d_testcube(): # Load example 4d data (TZYX). test_cube = iris.tests.stock.realistic_4d() @@ -381,7 +389,7 @@ def _load_4d_testcube(): points=point_values, bounds=bound_values, standard_name='forecast_period', - units=iris.unit.Unit('hours') + units=cf_units.Unit('hours') ) test_cube.add_aux_coord(new_forecast_coord, forecast_dims) # Heavily reduce dimensions for faster testing. @@ -421,6 +429,7 @@ def _date_series(src_cube): return cube +@tests.skip_plot class SliceMixin(object): """Mixin class providing tests for each 2-dimensional permutation of axes. @@ -458,34 +467,38 @@ def test_tz(self): self.check_graphic() -@iris.tests.skip_data +@tests.skip_data class TestContour(tests.GraphicsTest, SliceMixin): """Test the iris.plot.contour routine.""" def setUp(self): + super(TestContour, self).setUp() self.wind = _load_4d_testcube() self.draw_method = iplt.contour -@iris.tests.skip_data +@tests.skip_data class TestContourf(tests.GraphicsTest, SliceMixin): """Test the iris.plot.contourf routine.""" def setUp(self): + super(TestContourf, self).setUp() self.wind = _load_4d_testcube() self.draw_method = iplt.contourf -@iris.tests.skip_data +@tests.skip_data class TestPcolor(tests.GraphicsTest, SliceMixin): """Test the iris.plot.pcolor routine.""" def setUp(self): + super(TestPcolor, self).setUp() self.wind = _load_4d_testcube() self.draw_method = iplt.pcolor -@iris.tests.skip_data +@tests.skip_data class TestPcolormesh(tests.GraphicsTest, SliceMixin): """Test the iris.plot.pcolormesh routine.""" def setUp(self): + super(TestPcolormesh, self).setUp() self.wind = _load_4d_testcube() self.draw_method = iplt.pcolormesh @@ -567,34 +580,39 @@ def override_with_decorated_methods(attr_dict, target_dict, return type.__new__(cls, name, bases, local) -@iris.tests.skip_data -class TestPcolorNoBounds(tests.GraphicsTest, SliceMixin): +@tests.skip_data +@tests.iristest_timing_decorator +class TestPcolorNoBounds(six.with_metaclass(CheckForWarningsMetaclass, + tests.GraphicsTest_nometa, + SliceMixin)): """ Test the iris.plot.pcolor routine on a cube with coordinates that have no bounds. """ - __metaclass__ = CheckForWarningsMetaclass - def setUp(self): + super(TestPcolorNoBounds, self).setUp() self.wind = _load_wind_no_bounds() self.draw_method = iplt.pcolor -@iris.tests.skip_data -class TestPcolormeshNoBounds(tests.GraphicsTest, SliceMixin): +@tests.skip_data +@tests.iristest_timing_decorator +class TestPcolormeshNoBounds(six.with_metaclass(CheckForWarningsMetaclass, + tests.GraphicsTest_nometa, + SliceMixin)): """ Test the iris.plot.pcolormesh routine on a cube with coordinates that have no bounds. """ - __metaclass__ = CheckForWarningsMetaclass - def setUp(self): + super(TestPcolormeshNoBounds, self).setUp() self.wind = _load_wind_no_bounds() self.draw_method = iplt.pcolormesh +@tests.skip_plot class Slice1dMixin(object): """Mixin class providing tests for each 1-dimensional permutation of axes. @@ -630,18 +648,20 @@ def test_t_dates(self): self.check_graphic() -@iris.tests.skip_data +@tests.skip_data class TestPlot(tests.GraphicsTest, Slice1dMixin): """Test the iris.plot.plot routine.""" def setUp(self): + super(TestPlot, self).setUp() self.wind = _load_4d_testcube() self.draw_method = iplt.plot -@iris.tests.skip_data +@tests.skip_data class TestQuickplotPlot(tests.GraphicsTest, Slice1dMixin): """Test the iris.quickplot.plot routine.""" def setUp(self): + super(TestQuickplotPlot, self).setUp() self.wind = _load_4d_testcube() self.draw_method = qplt.plot @@ -679,9 +699,11 @@ def __repr__(self): return self.repr -@iris.tests.skip_data +@tests.skip_data +@tests.skip_plot class TestPlotCoordinatesGiven(tests.GraphicsTest): def setUp(self): + super(TestPlotCoordinatesGiven, self).setUp() filename = tests.get_data_path(('PP', 'COLPEX', 'theta_and_orog_subset.pp')) self.cube = load_cube_once(filename, 'air_potential_temperature') @@ -745,7 +767,7 @@ def run_tests(self, cube, results): draw_method(cube, coords=coords) try: self.check_graphic() - except AssertionError, err: + except AssertionError as err: self.fail('Draw method %r failed with coords: %r. ' 'Assertion message: %s' % (draw_method, coords, err)) @@ -807,9 +829,11 @@ def test_non_cube_coordinate(self): self.draw('contourf', cube, coords=['grid_latitude', x]) -@iris.tests.skip_data +@tests.skip_data +@tests.skip_plot class TestPlotDimAndAuxCoordsKwarg(tests.GraphicsTest): def setUp(self): + super(TestPlotDimAndAuxCoordsKwarg, self).setUp() filename = tests.get_data_path(('NetCDF', 'rotated', 'xy', 'rotPole_landAreaFraction.nc')) self.cube = iris.load_cube(filename) @@ -851,14 +875,18 @@ def test_yx_order(self): self.check_graphic() +@tests.skip_plot class TestSymbols(tests.GraphicsTest): def test_cloud_cover(self): - iplt.symbols(range(10), [0] * 10, [iris.symbols.CLOUD_COVER[i] - for i in range(10)], 0.375) + iplt.symbols(list(range(10)), + [0] * 10, + [iris.symbols.CLOUD_COVER[i] for i in range(10)], + 0.375) iplt.plt.axis('off') self.check_graphic() +@tests.skip_plot class TestPlottingExceptions(tests.IrisTest): def setUp(self): self.bounded_cube = tests.stock.lat_lon_cube() @@ -898,7 +926,8 @@ def test_different_coord_systems(self): iplt.pcolormesh(cube, coords=['longitude', 'latitude']) -@iris.tests.skip_data +@tests.skip_data +@tests.skip_plot class TestPlotOtherCoordSystems(tests.GraphicsTest): def test_plot_tmerc(self): filename = tests.get_data_path(('NetCDF', 'transverse_mercator', @@ -909,5 +938,28 @@ def test_plot_tmerc(self): self.check_graphic() +@tests.skip_plot +class TestPlotCitation(tests.GraphicsTest): + def setUp(self): + super(TestPlotCitation, self).setUp() + self.figure = plt.figure() + self.axes = self.figure.gca() + self.text = ('Lorem ipsum dolor sit amet, consectetur adipiscing ' + 'elit, sed do eiusmod tempor incididunt ut labore et ' + 'dolore magna aliqua.') + + def test(self): + iplt.citation(self.text) + self.check_graphic() + + def test_figure(self): + iplt.citation(self.text, figure=self.figure) + self.check_graphic() + + def test_axes(self): + iplt.citation(self.text, axes=self.axes) + self.check_graphic() + + if __name__ == "__main__": tests.main() diff --git a/lib/iris/tests/test_pp_cf.py b/lib/iris/tests/test_pp_cf.py index 215e4125f9..a2c3aa0514 100644 --- a/lib/iris/tests/test_pp_cf.py +++ b/lib/iris/tests/test_pp_cf.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -15,6 +15,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests @@ -22,9 +24,12 @@ import os import subprocess +import tempfile import types import warnings +import netCDF4 + import iris import iris.tests.pp as pp import iris.util @@ -77,7 +82,7 @@ def callback_aaxzc_n10r13xy_b_pp(cube, field, filename): cube.add_aux_coord(height_coord) -@iris.tests.skip_data +@tests.skip_data class TestAll(tests.IrisTest, pp.PPTest): _ref_dir = ('usecases', 'pp_to_cf_conversion') @@ -101,42 +106,18 @@ def _test_file(self, name): nc_filenames = [] for index, cube in enumerate(cubes): - # Write Cube to netCDF file - must be NETCDF3_CLASSIC format for the cfchecker. - file_nc = os.path.join(os.path.sep, 'var', 'tmp', '%s_%d.nc' % (fname_name, index)) - #file_nc = tests.get_result_path(self._ref_dir + ('to_netcdf', '%s_%d.nc' % (fname_name, index))) - iris.save(cube, file_nc, netcdf_format='NETCDF3_CLASSIC') + # Explicitly set a fill-value as a workaround for + # https://github.com/Unidata/netcdf4-python/issues/725 + fill_value = netCDF4.default_fillvals[cube.dtype.str[1:]]; + + file_nc = tempfile.NamedTemporaryFile(suffix='.nc', delete=False).name + iris.save(cube, file_nc, netcdf_format='NETCDF3_CLASSIC', + fill_value=fill_value) # Check the netCDF file against CDL expected output. self.assertCDL(file_nc, self._ref_dir + ('to_netcdf', '%s_%d.cdl' % (fname_name, index))) nc_filenames.append(file_nc) - # Perform CF-netCDF conformance checking. - with open('/dev/null', 'w') as dev_null: - try: - # Check for the availability of the "cfchecker" application - subprocess.check_call(['which', 'cfchecker'], stderr=dev_null, stdout=dev_null) - except subprocess.CalledProcessError: - warnings.warn('CF-netCDF "cfchecker" application not available. Skipping CF-netCDF compliance checking.') - else: - file_checker = os.path.join(os.path.dirname(file_nc), '%s_%d.txt' % (fname_name, index)) - - with open(file_checker, 'w') as report: - # Generate cfchecker text report on the file. - # Don't use check_call() here, as cfchecker returns a non-zero status code - # for any non-compliant file, causing check_call() to raise an exception. - subprocess.call(['cfchecker', file_nc], stderr=report, stdout=report) - - if not os.path.isfile(file_checker): - os.remove(file_nc) - self.fail('Failed to process %r with cfchecker' % file_nc) - - with open(file_checker, 'r') as report: - # Get the cfchecker report and purge unwanted lines. - checker_report = ''.join([line for line in report.readlines() if not line.startswith('Using')]) - - os.remove(file_checker) - self.assertString(checker_report, self._ref_dir + ('to_netcdf', 'cf_checker', '%s_%d.txt' % (fname_name, index))) - # 3) Load the netCDF and check the Cube for index, nc_filename in enumerate(nc_filenames): # Read netCDF to Cube. @@ -203,8 +184,7 @@ def attach_tests(): for file_name in TestAll.files_to_check: func_name = 'test_{}'.format(file_name.replace('.', '_')) test_func = make_test_function(func_name, file_name) - test_method = types.MethodType(test_func, None, TestAll) - setattr(TestAll, func_name, test_method) + setattr(TestAll, func_name, test_func) attach_tests() diff --git a/lib/iris/tests/test_pp_module.py b/lib/iris/tests/test_pp_module.py index f0bfe29878..2c7ac0f1cf 100644 --- a/lib/iris/tests/test_pp_module.py +++ b/lib/iris/tests/test_pp_module.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office +# (C) British Crown Copyright 2013 - 2018, Met Office # # This file is part of Iris. # @@ -15,6 +15,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests @@ -24,44 +26,42 @@ from types import GeneratorType import unittest -import biggus -import netcdftime +import cftime +from numpy.testing import assert_array_equal import iris.fileformats import iris.fileformats.pp as pp +from iris.tests import mock import iris.util - -@iris.tests.skip_data +@tests.skip_data class TestPPCopy(tests.IrisTest): def setUp(self): self.filename = tests.get_data_path(('PP', 'aPPglob1', 'global.pp')) def test_copy_field_deferred(self): - field = pp.load(self.filename).next() + field = next(pp.load(self.filename)) clone = field.copy() - self.assertIsInstance(clone._data, biggus.Array) self.assertEqual(field, clone) clone.lbyr = 666 self.assertNotEqual(field, clone) def test_deepcopy_field_deferred(self): - field = pp.load(self.filename).next() + field = next(pp.load(self.filename)) clone = deepcopy(field) - self.assertIsInstance(clone._data, biggus.Array) self.assertEqual(field, clone) clone.lbyr = 666 self.assertNotEqual(field, clone) def test_copy_field_non_deferred(self): - field = pp.load(self.filename, True).next() + field = next(pp.load(self.filename, True)) clone = field.copy() self.assertEqual(field, clone) clone.data[0][0] = 666 self.assertNotEqual(field, clone) def test_deepcopy_field_non_deferred(self): - field = pp.load(self.filename, True).next() + field = next(pp.load(self.filename, True)) clone = deepcopy(field) self.assertEqual(field, clone) clone.data[0][0] = 666 @@ -85,14 +85,15 @@ def check_pp(self, pp_fields, reference_filename): test_string = str(pp_fields) reference_path = tests.get_result_path(reference_filename) if os.path.isfile(reference_path): - reference = ''.join(open(reference_path, 'r').readlines()) + with open(reference_path, 'r') as reference_fh: + reference = ''.join(reference_fh.readlines()) self._assert_str_same(reference+'\n', test_string+'\n', reference_filename, type_comparison_name='PP files') else: - tests.logger.warning('Creating result file: %s', reference_path) - open(reference_path, 'w').writelines(test_string) + with open(reference_path, 'w') as reference_fh: + reference_fh.writelines(test_string) -class TestPPHeaderDerived(unittest.TestCase): +class TestPPHeaderDerived(tests.IrisTest): def setUp(self): self.pp = pp.PPField2() @@ -119,11 +120,11 @@ def test_lbtim_setter(self): def test_lbproc_access(self): # lbproc == 65539 - self.assertEqual(self.pp.lbproc[0], 9) - self.assertEqual(self.pp.lbproc[19], 0) - self.assertEqual(self.pp.lbproc.flag1, 1) - self.assertEqual(self.pp.lbproc.flag65536, 1) - self.assertEqual(self.pp.lbproc.flag131072, 0) + with mock.patch('warnings.warn') as warn: + self.assertEqual(self.pp.lbproc.flag1, 1) + self.assertEqual(self.pp.lbproc.flag65536, 1) + self.assertEqual(self.pp.lbproc.flag131072, 0) + self.assertEqual(warn.call_count, 3) def test_set_lbuser(self): self.pp.stash = 'm02s12i003' @@ -147,14 +148,14 @@ def test_set_stash(self): def test_lbproc_bad_access(self): try: - print self.pp.lbproc.flag65537 + print(self.pp.lbproc.flag65537) except AttributeError: pass - except Exception, err: + except Exception as err: self.fail("Should return a better error: " + str(err)) -@iris.tests.skip_data +@tests.skip_data class TestPPField_GlobalTemperature(IrisPPTest): def setUp(self): self.original_pp_filepath = tests.get_data_path(('PP', 'aPPglob1', 'global.pp')) @@ -168,55 +169,79 @@ def test_lbtim_access(self): self.assertEqual(self.r[0].lbtim.ic, 2) def test_lbproc_access(self): - self.assertEqual(self.r[0].lbproc[0], 8) - self.assertEqual(self.r[0].lbproc[19], 0) - self.assertEqual(self.r[0].lbproc.flag1, 0) - self.assertEqual(self.r[0].lbproc.flag65536, 0) - self.assertEqual(self.r[0].lbproc.flag131072, 0) + with mock.patch('warnings.warn') as warn: + self.assertEqual(self.r[0].lbproc.flag1, 0) + self.assertEqual(self.r[0].lbproc.flag65536, 0) + self.assertEqual(self.r[0].lbproc.flag131072, 0) + self.assertEqual(warn.call_count, 3) def test_t1_t2_access(self): - self.assertEqual(self.r[0].t1.timetuple(), netcdftime.datetime(1994, 12, 1, 0, 0).timetuple()) + self.assertEqual(self.r[0].t1.timetuple(), + cftime.datetime(1994, 12, 1, 0, 0).timetuple()) def test_save_single(self): temp_filename = iris.util.create_temp_filename(".pp") - self.r[0].save(open(temp_filename, 'wb')) + with open(temp_filename, 'wb') as temp_fh: + self.r[0].save(temp_fh) self.assertEqual(self.file_checksum(temp_filename), self.file_checksum(self.original_pp_filepath)) os.remove(temp_filename) def test_save_api(self): filepath = self.original_pp_filepath - f = pp.load(filepath).next() + f = next(pp.load(filepath)) temp_filename = iris.util.create_temp_filename(".pp") - f.save(open(temp_filename, 'wb')) + with open(temp_filename, 'wb') as temp_fh: + f.save(temp_fh) self.assertEqual(self.file_checksum(temp_filename), self.file_checksum(filepath)) - + os.remove(temp_filename) - -@iris.tests.skip_data + +@tests.skip_data class TestPackedPP(IrisPPTest): def test_wgdos(self): - r = pp.load(tests.get_data_path(('PP', 'wgdos_packed', 'nae.20100104-06_0001.pp'))) - - # Check that the result is a generator and convert to a list so that we can index and get the first one - self.assertEqual( type(r), GeneratorType) + filepath = tests.get_data_path(('PP', 'wgdos_packed', + 'nae.20100104-06_0001.pp')) + r = pp.load(filepath) + + # Check that the result is a generator and convert to a list so that we + # can index and get the first one + self.assertEqual(type(r), GeneratorType) r = list(r) - + self.check_pp(r, ('PP', 'nae_unpacked.pp.txt')) - - # check that trying to save this field again raises an error (we cannot currently write WGDOS packed fields) + + # check that trying to save this field again raises an error + # (we cannot currently write WGDOS packed fields without mo_pack) temp_filename = iris.util.create_temp_filename(".pp") - self.assertRaises(NotImplementedError, r[0].save, open(temp_filename, 'wb')) + with mock.patch('iris.fileformats.pp.mo_pack', None): + with self.assertRaises(NotImplementedError): + with open(temp_filename, 'wb') as temp_fh: + r[0].save(temp_fh) os.remove(temp_filename) - + + @unittest.skipIf(pp.mo_pack is None, 'Requires mo_pack.') + def test_wgdos_mo_pack(self): + filepath = tests.get_data_path(('PP', 'wgdos_packed', + 'nae.20100104-06_0001.pp')) + orig_fields = pp.load(filepath) + with self.temp_filename('.pp') as temp_filename: + with open(temp_filename, 'wb') as fh: + for field in orig_fields: + field.save(fh) + saved_fields = pp.load(temp_filename) + for orig_field, saved_field in zip(orig_fields, saved_fields): + assert_array_equal(orig_field.data, saved_field.data) + def test_rle(self): r = pp.load(tests.get_data_path(('PP', 'ocean_rle', 'ocean_rle.pp'))) - # Check that the result is a generator and convert to a list so that we can index and get the first one - self.assertEqual( type(r), GeneratorType) + # Check that the result is a generator and convert to a list so that we + # can index and get the first one + self.assertEqual(type(r), GeneratorType) r = list(r) self.check_pp(r, ('PP', 'rle_unpacked.pp.txt')) @@ -225,10 +250,11 @@ def test_rle(self): # (we cannot currently write RLE packed fields) with self.temp_filename('.pp') as temp_filename: with self.assertRaises(NotImplementedError): - r[0].save(open(temp_filename, 'wb')) + with open(temp_filename, 'wb') as temp_fh: + r[0].save(temp_fh) -@iris.tests.skip_data +@tests.skip_data class TestPPFile(IrisPPTest): def test_lots_of_extra_data(self): r = pp.load(tests.get_data_path(('PP', 'cf_processing', 'HadCM2_ts_SAT_ann_18602100.b.pp'))) @@ -239,7 +265,7 @@ def test_lots_of_extra_data(self): self.check_pp(r, ('PP', 'extra_data_time_series.pp.txt')) -@iris.tests.skip_data +@tests.skip_data class TestPPFileExtraXData(IrisPPTest): def setUp(self): self.original_pp_filepath = tests.get_data_path(('PP', 'ukV1', 'ukVpmslont.pp')) @@ -250,12 +276,13 @@ def test_full_file(self): def test_save_single(self): filepath = tests.get_data_path(('PP', 'ukV1', 'ukVpmslont_first_field.pp')) - f = pp.load(filepath).next() + f = next(pp.load(filepath)) temp_filename = iris.util.create_temp_filename(".pp") - f.save(open(temp_filename, 'wb')) + with open(temp_filename, 'wb') as temp_fh: + f.save(temp_fh) - s = pp.load(temp_filename).next() + s = next(pp.load(temp_filename)) # force the data to be loaded (this was done for f when save was run) s.data @@ -265,10 +292,10 @@ def test_save_single(self): os.remove(temp_filename) -@iris.tests.skip_data +@tests.skip_data class TestPPFileWithExtraCharacterData(IrisPPTest): def setUp(self): - self.original_pp_filepath = tests.get_data_path(('PP', 'model_comp', 'dec_subset.pp')) + self.original_pp_filepath = tests.get_data_path(('PP', 'globClim1', 'dec_subset.pp')) self.r = pp.load(self.original_pp_filepath) self.r_loaded_data = pp.load(self.original_pp_filepath, read_data=True) @@ -289,12 +316,13 @@ def test_full_file(self): def test_save_single(self): filepath = tests.get_data_path(('PP', 'model_comp', 'dec_first_field.pp')) - f = pp.load(filepath).next() + f = next(pp.load(filepath)) temp_filename = iris.util.create_temp_filename(".pp") - f.save(open(temp_filename, 'wb')) + with open(temp_filename, 'wb') as temp_fh: + f.save(temp_fh) - s = pp.load(temp_filename).next() + s = next(pp.load(temp_filename)) # force the data to be loaded (this was done for f when save was run) s.data @@ -302,102 +330,9 @@ def test_save_single(self): self.assertEqual(self.file_checksum(temp_filename), self.file_checksum(filepath)) os.remove(temp_filename) - - -class TestBitwiseInt(unittest.TestCase): - - def test_3(self): - t = pp.BitwiseInt(3) - self.assertEqual(t[0], 3) - self.assertTrue(t.flag1) - self.assertTrue(t.flag2) - self.assertRaises(AttributeError, getattr, t, "flag1024") - - def test_setting_flags(self): - t = pp.BitwiseInt(3) - self.assertEqual(t._value, 3) - - t.flag1 = False - self.assertEqual(t._value, 2) - t.flag2 = False - self.assertEqual(t._value, 0) - - t.flag1 = True - self.assertEqual(t._value, 1) - t.flag2 = True - self.assertEqual(t._value, 3) - - self.assertRaises(AttributeError, setattr, t, "flag1024", True) - self.assertRaises(TypeError, setattr, t, "flag2", 1) - - t = pp.BitwiseInt(3, num_bits=11) - t.flag1024 = True - self.assertEqual(t._value, 1027) - - def test_standard_operators(self): - t = pp.BitwiseInt(323) - - self.assertTrue(t == 323) - self.assertFalse(t == 324) - - self.assertFalse(t != 323) - self.assertTrue(t != 324) - - self.assertTrue(t >= 323) - self.assertFalse(t >= 324) - - self.assertFalse(t > 323) - self.assertTrue(t > 322) - - self.assertTrue(t <= 323) - self.assertFalse(t <= 322) - - self.assertFalse(t < 323) - self.assertTrue(t < 324) - self.assertTrue(t in [323]) - self.assertFalse(t in [324]) - - def test_323(self): - t = pp.BitwiseInt(323) - self.assertRaises(AttributeError, getattr, t, 'flag0') - - self.assertEqual(t.flag1, 1) - self.assertEqual(t.flag2, 1) - self.assertEqual(t.flag4, 0) - self.assertEqual(t.flag8, 0) - self.assertEqual(t.flag16, 0) - self.assertEqual(t.flag32, 0) - self.assertEqual(t.flag64, 1) - self.assertEqual(t.flag128, 0) - self.assertEqual(t.flag256, 1) - - - def test_33214(self): - t = pp.BitwiseInt(33214) - self.assertEqual(t[0], 4) - self.assertEqual(t.flag1, 0) - self.assertEqual(t.flag2, 1) - - def test_negative_number(self): - try: - _ = pp.BitwiseInt(-5) - except ValueError, err: - self.assertEqual(str(err), 'Negative numbers not supported with splittable integers object') - - def test_128(self): - t = pp.BitwiseInt(128) - self.assertEqual(t.flag1, 0) - self.assertEqual(t.flag2, 0) - self.assertEqual(t.flag4, 0) - self.assertEqual(t.flag8, 0) - self.assertEqual(t.flag16, 0) - self.assertEqual(t.flag32, 0) - self.assertEqual(t.flag64, 0) - self.assertEqual(t.flag128, 1) - -class TestSplittableInt(unittest.TestCase): +class TestSplittableInt(tests.IrisTest): def test_3(self): t = pp.SplittableInt(3) @@ -492,11 +427,11 @@ def test_negative_number(self): self.assertRaises(ValueError, pp.SplittableInt, -5) try: _ = pp.SplittableInt(-5) - except ValueError, err: + except ValueError as err: self.assertEqual(str(err), 'Negative numbers not supported with splittable integers object') -class TestSplittableIntEquality(unittest.TestCase): +class TestSplittableIntEquality(tests.IrisTest): def test_not_implemented(self): class Terry(object): pass sin = pp.SplittableInt(0) @@ -504,16 +439,16 @@ class Terry(object): pass self.assertIs(sin.__ne__(Terry()), NotImplemented) -class TestPPDataProxyEquality(unittest.TestCase): +class TestPPDataProxyEquality(tests.IrisTest): def test_not_implemented(self): class Terry(object): pass pox = pp.PPDataProxy("john", "michael", "eric", "graham", "brian", - "spam", "beans", "eggs") + "spam", "beans", "eggs", "parrot") self.assertIs(pox.__eq__(Terry()), NotImplemented) self.assertIs(pox.__ne__(Terry()), NotImplemented) -class TestPPFieldEquality(unittest.TestCase): +class TestPPFieldEquality(tests.IrisTest): def test_not_implemented(self): class Terry(object): pass pox = pp.PPField3() diff --git a/lib/iris/tests/test_pp_stash.py b/lib/iris/tests/test_pp_stash.py index 1f831220e3..303dc4cc7e 100644 --- a/lib/iris/tests/test_pp_stash.py +++ b/lib/iris/tests/test_pp_stash.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -15,6 +15,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests @@ -28,7 +30,7 @@ class TestPPStash(tests.IrisTest): - @iris.tests.skip_data + @tests.skip_data def test_cube_attributes(self): cube = tests.stock.simple_pp() self.assertEqual('m01s16i203', cube.attributes['STASH']) @@ -36,7 +38,7 @@ def test_cube_attributes(self): self.assertEqual(cube.attributes['STASH'], 'm01s16i203') self.assertNotEqual(cube.attributes['STASH'], 'm01s16i999') - @iris.tests.skip_data + @tests.skip_data def test_ppfield(self): data_path = tests.get_data_path(('PP', 'simple_pp', 'global.pp')) pps = iris.fileformats.pp.load(data_path) @@ -47,83 +49,87 @@ def test_ppfield(self): self.assertNotEqual(pp.stash, 'm01s16i999') def test_stash_against_stash(self): - self.assertEqual(iris.fileformats.pp.STASH(1,2,3), iris.fileformats.pp.STASH(1,2,3)) - self.assertNotEqual(iris.fileformats.pp.STASH(1,2,3), iris.fileformats.pp.STASH(2,3,4)) + self.assertEqual(iris.fileformats.pp.STASH(1, 2, 3), iris.fileformats.pp.STASH(1, 2, 3)) + self.assertNotEqual(iris.fileformats.pp.STASH(1, 2, 3), iris.fileformats.pp.STASH(2, 3, 4)) def test_stash_against_str(self): - self.assertEqual(iris.fileformats.pp.STASH(1,2,3), 'm01s02i003') - self.assertEqual('m01s02i003', iris.fileformats.pp.STASH(1,2,3)) - self.assertNotEqual(iris.fileformats.pp.STASH(1,2,3), 'm02s03i004') - self.assertNotEqual('m02s03i004', iris.fileformats.pp.STASH(1,2,3)) + self.assertEqual(iris.fileformats.pp.STASH(1, 2, 3), 'm01s02i003') + self.assertEqual('m01s02i003', iris.fileformats.pp.STASH(1, 2, 3)) + self.assertNotEqual(iris.fileformats.pp.STASH(1, 2, 3), 'm02s03i004') + self.assertNotEqual('m02s03i004', iris.fileformats.pp.STASH(1, 2, 3)) def test_irregular_stash_str(self): - self.assertEqual(iris.fileformats.pp.STASH(1,2,3), 'm01s02i0000000003') - self.assertEqual(iris.fileformats.pp.STASH(1,2,3), 'm01s02i3') - self.assertEqual(iris.fileformats.pp.STASH(1,2,3), 'm01s2i3') - self.assertEqual(iris.fileformats.pp.STASH(1,2,3), 'm1s2i3') - - self.assertEqual('m01s02i0000000003', iris.fileformats.pp.STASH(1,2,3)) - self.assertEqual('m01s02i3', iris.fileformats.pp.STASH(1,2,3)) - self.assertEqual('m01s2i3', iris.fileformats.pp.STASH(1,2,3)) - self.assertEqual('m1s2i3', iris.fileformats.pp.STASH(1,2,3)) - - self.assertNotEqual(iris.fileformats.pp.STASH(2,3,4), 'm01s02i0000000003') - self.assertNotEqual(iris.fileformats.pp.STASH(2,3,4), 'm01s02i3') - self.assertNotEqual(iris.fileformats.pp.STASH(2,3,4), 'm01s2i3') - self.assertNotEqual(iris.fileformats.pp.STASH(2,3,4), 'm1s2i3') - - self.assertNotEqual('m01s02i0000000003', iris.fileformats.pp.STASH(2,3,4)) - self.assertNotEqual('m01s02i3', iris.fileformats.pp.STASH(2,3,4)) - self.assertNotEqual('m01s2i3', iris.fileformats.pp.STASH(2,3,4)) - self.assertNotEqual('m1s2i3', iris.fileformats.pp.STASH(2,3,4)) + self.assertEqual(iris.fileformats.pp.STASH(1, 2, 3), 'm01s02i0000000003') + self.assertEqual(iris.fileformats.pp.STASH(1, 2, 3), 'm01s02i3') + self.assertEqual(iris.fileformats.pp.STASH(1, 2, 3), 'm01s2i3') + self.assertEqual(iris.fileformats.pp.STASH(1, 2, 3), 'm1s2i3') + + self.assertEqual('m01s02i0000000003', iris.fileformats.pp.STASH(1, 2, 3)) + self.assertEqual('m01s02i3', iris.fileformats.pp.STASH(1, 2, 3)) + self.assertEqual('m01s2i3', iris.fileformats.pp.STASH(1, 2, 3)) + self.assertEqual('m1s2i3', iris.fileformats.pp.STASH(1, 2, 3)) + + self.assertNotEqual(iris.fileformats.pp.STASH(2, 3, 4), 'm01s02i0000000003') + self.assertNotEqual(iris.fileformats.pp.STASH(2, 3, 4), 'm01s02i3') + self.assertNotEqual(iris.fileformats.pp.STASH(2, 3, 4), 'm01s2i3') + self.assertNotEqual(iris.fileformats.pp.STASH(2, 3, 4), 'm1s2i3') + + self.assertNotEqual('m01s02i0000000003', iris.fileformats.pp.STASH(2, 3, 4)) + self.assertNotEqual('m01s02i3', iris.fileformats.pp.STASH(2, 3, 4)) + self.assertNotEqual('m01s2i3', iris.fileformats.pp.STASH(2, 3, 4)) + self.assertNotEqual('m1s2i3', iris.fileformats.pp.STASH(2, 3, 4)) self.assertEqual(iris.fileformats.pp.STASH.from_msi('M01s02i003'), 'm01s02i003') self.assertEqual('m01s02i003', iris.fileformats.pp.STASH.from_msi('M01s02i003')) def test_illegal_stash_str_range(self): - self.assertEqual(iris.fileformats.pp.STASH(0,2,3), 'm??s02i003') - self.assertNotEqual(iris.fileformats.pp.STASH(0,2,3), 'm01s02i003') - self.assertEqual('m??s02i003', iris.fileformats.pp.STASH(0,2,3)) - self.assertNotEqual('m01s02i003', iris.fileformats.pp.STASH(0,2,3)) - self.assertEqual(iris.fileformats.pp.STASH(0,2,3), 'm??s02i003') - self.assertEqual(iris.fileformats.pp.STASH(0,2,3), 'm00s02i003') - self.assertEqual('m??s02i003', iris.fileformats.pp.STASH(0,2,3)) - self.assertEqual('m00s02i003', iris.fileformats.pp.STASH(0,2,3)) + self.assertEqual(iris.fileformats.pp.STASH(0, 2, 3), 'm??s02i003') + self.assertNotEqual(iris.fileformats.pp.STASH(0, 2, 3), 'm01s02i003') - self.assertEqual(iris.fileformats.pp.STASH(100,2,3), 'm??s02i003') - self.assertEqual(iris.fileformats.pp.STASH(100,2,3), 'm100s02i003') - self.assertEqual('m??s02i003', iris.fileformats.pp.STASH(100,2,3)) - self.assertEqual('m100s02i003', iris.fileformats.pp.STASH(100,2,3)) + self.assertEqual('m??s02i003', iris.fileformats.pp.STASH(0, 2, 3)) + self.assertNotEqual('m01s02i003', iris.fileformats.pp.STASH(0, 2, 3)) + + self.assertEqual(iris.fileformats.pp.STASH(0, 2, 3), 'm??s02i003') + self.assertEqual(iris.fileformats.pp.STASH(0, 2, 3), 'm00s02i003') + self.assertEqual('m??s02i003', iris.fileformats.pp.STASH(0, 2, 3)) + self.assertEqual('m00s02i003', iris.fileformats.pp.STASH(0, 2, 3)) + + self.assertEqual(iris.fileformats.pp.STASH(100, 2, 3), 'm??s02i003') + self.assertEqual(iris.fileformats.pp.STASH(100, 2, 3), 'm100s02i003') + self.assertEqual('m??s02i003', iris.fileformats.pp.STASH(100, 2, 3)) + self.assertEqual('m100s02i003', iris.fileformats.pp.STASH(100, 2, 3)) def test_illegal_stash_stash_range(self): - self.assertEqual(iris.fileformats.pp.STASH(0,2,3), iris.fileformats.pp.STASH(0,2,3)) - self.assertEqual(iris.fileformats.pp.STASH(100,2,3), iris.fileformats.pp.STASH(100,2,3)) - self.assertEqual(iris.fileformats.pp.STASH(100,2,3), iris.fileformats.pp.STASH(999,2,3)) + self.assertEqual(iris.fileformats.pp.STASH(0, 2, 3), iris.fileformats.pp.STASH(0, 2, 3)) + self.assertEqual(iris.fileformats.pp.STASH(100, 2, 3), iris.fileformats.pp.STASH(100, 2, 3)) + self.assertEqual(iris.fileformats.pp.STASH(100, 2, 3), iris.fileformats.pp.STASH(999, 2, 3)) def test_illegal_stash_format(self): - with self.assertRaises(ValueError): - self.assertEqual(iris.fileformats.pp.STASH(1,2,3), 'abc') - with self.assertRaises(ValueError): - self.assertEqual('abc', iris.fileformats.pp.STASH(1,2,3)) - - with self.assertRaises(ValueError): - self.assertEqual(iris.fileformats.pp.STASH(1,2,3), 'm01s02003') - with self.assertRaises(ValueError): - self.assertEqual('m01s02003', iris.fileformats.pp.STASH(1,2,3)) + test_values = ( + ('abc', (1, 2, 3)), + ('mlotstmin', (1, 2, 3)), + ('m01s02003', (1, 2, 3))) + + for (test_value, reference) in test_values: + msg = 'Expected STASH code .* {!r}'.format(test_value) + with self.assertRaisesRegexp(ValueError, msg): + test_value == iris.fileformats.pp.STASH(*reference) + with self.assertRaisesRegexp(ValueError, msg): + iris.fileformats.pp.STASH(*reference) == test_value def test_illegal_stash_type(self): - with self.assertRaises(TypeError): - self.assertEqual(iris.fileformats.pp.STASH.from_msi(0102003), 'm01s02i003') - - with self.assertRaises(TypeError): - self.assertEqual('m01s02i003', iris.fileformats.pp.STASH.from_msi(0102003)) - - with self.assertRaises(TypeError): - self.assertEqual(iris.fileformats.pp.STASH.from_msi(['m01s02i003']), 'm01s02i003') - - with self.assertRaises(TypeError): - self.assertEqual('m01s02i003', iris.fileformats.pp.STASH.from_msi(['m01s02i003'])) + test_values = ( + (102003, 'm01s02i003'), + (['m01s02i003'], 'm01s02i003'), + ) + + for (test_value, reference) in test_values: + msg = 'Expected STASH code .* {!r}'.format(test_value) + with self.assertRaisesRegexp(TypeError, msg): + iris.fileformats.pp.STASH.from_msi(test_value) == reference + with self.assertRaisesRegexp(TypeError, msg): + reference == iris.fileformats.pp.STASH.from_msi(test_value) def test_stash_lbuser(self): stash = iris.fileformats.pp.STASH(2, 32, 456) diff --git a/lib/iris/tests/test_pp_to_cube.py b/lib/iris/tests/test_pp_to_cube.py index 3f76231d5a..e8f8bdc766 100644 --- a/lib/iris/tests/test_pp_to_cube.py +++ b/lib/iris/tests/test_pp_to_cube.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -15,6 +15,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests @@ -23,23 +25,23 @@ import iris import iris.fileformats.pp -import iris.fileformats.pp_rules +import iris.fileformats.pp_load_rules import iris.fileformats.rules import iris.io import iris.util import iris.tests.stock -@iris.tests.skip_data +@tests.skip_data class TestPPLoadCustom(tests.IrisTest): def setUp(self): self.subcubes = iris.cube.CubeList() filename = tests.get_data_path(('PP', 'aPPglob1', 'global.pp')) - self.template = iris.fileformats.pp.load(filename).next() + self.template = next(iris.fileformats.pp.load(filename)) def _field_to_cube(self, field): cube, _, _ = iris.fileformats.rules._make_cube( - field, iris.fileformats.pp_rules.convert) + field, iris.fileformats.pp_load_rules.convert) return cube def test_lbtim_2(self): @@ -50,7 +52,7 @@ def test_lbtim_2(self): cube = self._field_to_cube(field) self.subcubes.append(cube) cube = self.subcubes.merge()[0] - self.assertCML(cube, ('pp_rules', 'lbtim_2.cml')) + self.assertCML(cube, ('pp_load_rules', 'lbtim_2.cml')) def _ocean_depth(self, bounded=False): lbuser = list(self.template.lbuser) @@ -74,22 +76,12 @@ def _ocean_depth(self, bounded=False): def test_ocean_depth(self): self._ocean_depth() cube = self.subcubes.merge()[0] - self.assertCML(cube, ('pp_rules', 'ocean_depth.cml')) + self.assertCML(cube, ('pp_load_rules', 'ocean_depth.cml')) def test_ocean_depth_bounded(self): self._ocean_depth(bounded=True) cube = self.subcubes.merge()[0] - self.assertCML(cube, ('pp_rules', 'ocean_depth_bounded.cml')) - - def test_invalid_units(self): - # UM to CF rules are mapped to the invalid unit "1e3 psu @0.035" - # for the STASH code m02s00i102. - lbuser = list(self.template.lbuser) - lbuser[6] = 2 - lbuser[3] = 102 - self.template.lbuser = tuple(lbuser) - cube = self._field_to_cube(self.template) - self.assertCML(cube, ('pp_rules', 'invalid_units.cml')) + self.assertCML(cube, ('pp_load_rules', 'ocean_depth_bounded.cml')) class TestReferences(tests.IrisTest): @@ -128,24 +120,24 @@ def test_regrid_identity(self): self.assertEqual(new_ref, self.ref) -@iris.tests.skip_data +@tests.skip_data class TestPPLoading(tests.IrisTest): def test_simple(self): cube = iris.tests.stock.simple_pp() self.assertCML(cube, ('cube_io', 'pp', 'load', 'global.cml')) -@iris.tests.skip_data +@tests.skip_data class TestPPLoadRules(tests.IrisTest): def test_pp_load_rules(self): # Test PP loading and rule evaluation. cube = iris.tests.stock.simple_pp() - self.assertCML(cube, ('pp_rules', 'global.cml')) + self.assertCML(cube, ('pp_load_rules', 'global.cml')) data_path = tests.get_data_path(('PP', 'rotated_uk', 'rotated_uk.pp')) cube = iris.load(data_path)[0] - self.assertCML(cube, ('pp_rules', 'rotated_uk.cml')) + self.assertCML(cube, ('pp_load_rules', 'rotated_uk.cml')) def test_lbproc(self): data_path = tests.get_data_path(('PP', 'meanMaxMin', '200806081200__qwpb.T24.pp')) @@ -153,54 +145,31 @@ def test_lbproc(self): constraint = iris.Constraint('air_temperature', forecast_period=24) cubes = iris.load(data_path, constraint) cubes = iris.cube.CubeList([cubes[0], cubes[3], cubes[1], cubes[2], cubes[4]]) - self.assertCML(cubes, ('pp_rules', 'lbproc_mean_max_min.cml')) - - def test_custom_rules(self): - # Test custom rule evaluation. - # Default behaviour - data_path = tests.get_data_path(('PP', 'aPPglob1', 'global.pp')) - cube = iris.load_cube(data_path) - self.assertEqual(cube.standard_name, 'air_temperature') - - # Custom behaviour - temp_path = iris.util.create_temp_filename() - f = open(temp_path, 'w') - f.write('\n'.join(( - 'IF', - 'f.lbuser[3] == 16203', - 'THEN', - 'CMAttribute("standard_name", None)', - 'CMAttribute("long_name", "customised")'))) - f.close() - iris.fileformats.pp.add_load_rules(temp_path) - cube = iris.load_cube(data_path) - self.assertEqual(cube.name(), 'customised') - os.remove(temp_path) - - # Back to default - iris.fileformats.pp.reset_load_rules() - cube = iris.load_cube(data_path) - self.assertEqual(cube.standard_name, 'air_temperature') + self.assertCML(cubes, ('pp_load_rules', 'lbproc_mean_max_min.cml')) def test_cell_methods(self): # Test cell methods are created for correct values of lbproc orig_file = tests.get_data_path(('PP', 'aPPglob1', 'global.pp')) # Values that result in cell methods being created - cell_method_values = {128 : "mean", 4096 : "minimum", 8192 : "maximum"} + cell_method_values = {64: "mean", + 128: "mean within years", + 4096: "minimum", + 8192: "maximum"} # Make test values as list of single bit values and some multiple bit values single_bit_values = list(iris.fileformats.pp.LBPROC_PAIRS) - multiple_bit_values = [(128 + 64, ""), (4096 + 2096, ""), (8192 + 1024, "")] + multiple_bit_values = [(128 + 32, ""), (4096 + 2096, ""), (8192 + 1024, "")] test_values = list(single_bit_values) + multiple_bit_values for value, _ in test_values: - f = iris.fileformats.pp.load(orig_file).next() + f = next(iris.fileformats.pp.load(orig_file)) f.lbproc = value # set value # Write out pp file temp_filename = iris.util.create_temp_filename(".pp") - f.save(open(temp_filename, 'wb')) + with open(temp_filename, 'wb') as temp_fh: + f.save(temp_fh) # Load pp file cube = iris.load_cube(temp_filename) @@ -220,16 +189,17 @@ def test_process_flags(self): orig_file = tests.get_data_path(('PP', 'aPPglob1', 'global.pp')) # Values that result in process flags attribute NOT being created - omit_process_flags_values = (128, 4096, 8192) + omit_process_flags_values = (64, 128, 4096, 8192) # Test single flag values for value, _ in iris.fileformats.pp.LBPROC_PAIRS: - f = iris.fileformats.pp.load(orig_file).next() + f = next(iris.fileformats.pp.load(orig_file)) f.lbproc = value # set value # Write out pp file temp_filename = iris.util.create_temp_filename(".pp") - f.save(open(temp_filename, 'wb')) + with open(temp_filename, 'wb') as temp_fh: + f.save(temp_fh) # Load pp file cube = iris.load_cube(temp_filename) @@ -244,35 +214,31 @@ def test_process_flags(self): os.remove(temp_filename) # Test multiple flag values - multiple_bit_values = ((128, 64), (4096, 1024), (8192, 1024)) + multiple_bit_values = ((128, 32), (4096, 1024), (8192, 1024)) # Maps lbproc value to the process flags that should be created multiple_map = {sum(x) : [iris.fileformats.pp.lbproc_map[y] for y in x] for x in multiple_bit_values} for bit_values in multiple_bit_values: - f = iris.fileformats.pp.load(orig_file).next() + f = next(iris.fileformats.pp.load(orig_file)) f.lbproc = sum(bit_values) # set value # Write out pp file temp_filename = iris.util.create_temp_filename(".pp") - f.save(open(temp_filename, 'wb')) + with open(temp_filename, 'wb') as temp_fh: + f.save(temp_fh) # Load pp file cube = iris.load_cube(temp_filename) # Check the process flags created - self.assertEquals(set(cube.attributes["ukmo__process_flags"]), set(multiple_map[sum(bit_values)]), "Mismatch between expected and actual process flags.") + self.assertEqual(set(cube.attributes['ukmo__process_flags']), + set(multiple_map[sum(bit_values)]), + 'Mismatch between expected and actual process ' + 'flags.') os.remove(temp_filename) -@iris.tests.skip_data -class TestStdName(tests.IrisTest): - def test_no_std_name(self): - fname = tests.get_data_path(['PP', 'simple_pp', 'bad_global.pp']) - cube = iris.load_cube(fname) - self.assertCML([cube], ['cube_io', 'pp', 'no_std_name.cml']) - - if __name__ == "__main__": tests.main() diff --git a/lib/iris/tests/test_quickplot.py b/lib/iris/tests/test_quickplot.py index 61dbe91df2..7261f5247a 100644 --- a/lib/iris/tests/test_quickplot.py +++ b/lib/iris/tests/test_quickplot.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -18,16 +18,21 @@ Tests the high-level plotting interface. """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests - -import matplotlib.pyplot as plt +import iris.tests.test_plot as test_plot import iris -import iris.plot as iplt -import iris.quickplot as qplt -import iris.tests.test_plot as test_plot -import iris.tests.test_mapping as test_mapping + +# Run tests in no graphics mode if matplotlib is not available. +if tests.MPL_AVAILABLE: + import matplotlib.pyplot as plt + import iris.plot as iplt + import iris.quickplot as qplt # Caches _load_theta so subsequent calls are faster @@ -51,9 +56,11 @@ def _load_theta(): return theta -@iris.tests.skip_data +@tests.skip_data +@tests.skip_plot class TestQuickplotCoordinatesGiven(test_plot.TestPlotCoordinatesGiven): def setUp(self): + tests.GraphicsTest.setUp(self) filename = tests.get_data_path(('PP', 'COLPEX', 'theta_and_orog_subset.pp')) self.cube = test_plot.load_cube_once(filename, 'air_potential_temperature') @@ -100,9 +107,11 @@ def setUp(self): } -@iris.tests.skip_data +@tests.skip_data +@tests.skip_plot class TestLabels(tests.GraphicsTest): def setUp(self): + super(TestLabels, self).setUp() self.theta = _load_theta() def _slice(self, coords): @@ -137,9 +146,36 @@ def test_contourf(self): qplt.contourf(self._small(), coords=['grid_longitude', 'model_level_number']) self.check_graphic() + def test_contourf_axes_specified(self): + # Check that the contourf function does not modify the matplotlib + # pyplot state machine. + + # Create a figure and axes to be used by contourf + plt.figure() + axes1 = plt.axes() + + # Create test figure and axes which will be the new results + # of plt.gcf and plt.gca. + plt.figure() + axes2 = plt.axes() + + # Add a title to the test axes. + plt.title('This should not be changed') + # Draw the contourf on a specific axes. + qplt.contourf(self._small(), axes=axes1) + + # Ensure that the correct axes got the appropriate title. + self.assertEqual(axes2.get_title(), 'This should not be changed') + self.assertEqual(axes1.get_title(), 'Air potential temperature') + + # Check that the axes labels were set correctly. + self.assertEqual(axes1.get_xlabel(), 'Grid longitude / degrees') + self.assertEqual(axes1.get_ylabel(), 'Altitude / m') + def test_contourf_nameless(self): cube = self._small() cube.standard_name = None + cube.attributes['STASH'] = '' qplt.contourf(cube, coords=['grid_longitude', 'model_level_number']) self.check_graphic() @@ -175,9 +211,10 @@ def test_alignment(self): @tests.skip_data +@tests.skip_plot class TestTimeReferenceUnitsLabels(tests.GraphicsTest): - def setUp(self): + super(TestTimeReferenceUnitsLabels, self).setUp() path = tests.get_data_path(('PP', 'aPProt1', 'rotatedMHtimecube.pp')) self.cube = iris.load_cube(path)[:, 0, 0] diff --git a/lib/iris/tests/test_regrid.py b/lib/iris/tests/test_regrid.py deleted file mode 100644 index 9ffa3ac59b..0000000000 --- a/lib/iris/tests/test_regrid.py +++ /dev/null @@ -1,213 +0,0 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . - - -# import iris tests first so that some things can be initialised before importing anything else -import iris.tests as tests - -import numpy as np - -import iris -from iris import load_cube -from iris.analysis.interpolate import regrid_to_max_resolution -from iris.cube import Cube -from iris.coords import DimCoord -from iris.coord_systems import GeogCS - - -@iris.tests.skip_data -class TestRegrid(tests.IrisTest): - @staticmethod - def patch_data(cube): - # Workaround until regrid can handle factories - for factory in cube.aux_factories: - cube.remove_aux_factory(factory) - - # Remove coords that share lat/lon dimensions - dim = cube.coord_dims(cube.coord('grid_longitude'))[0] - for coord in cube.coords(contains_dimension=dim, dim_coords=False): - cube.remove_coord(coord) - dim = cube.coord_dims(cube.coord('grid_latitude'))[0] - for coord in cube.coords(contains_dimension=dim, dim_coords=False): - cube.remove_coord(coord) - - def setUp(self): - self.theta_p_alt_path = tests.get_data_path( - ('PP', 'COLPEX', 'small_colpex_theta_p_alt.pp')) - self.theta_constraint = iris.Constraint('air_potential_temperature') - self.airpress_constraint = iris.Constraint('air_pressure') - self.level_constraint = iris.Constraint(model_level_number=1) - self.multi_level_constraint = iris.Constraint( - model_level_number=lambda c: 1 <= c < 6) - self.forecast_constraint = iris.Constraint( - forecast_period=lambda dt: 0.49 < dt < 0.51) - - def test_regrid_low_dimensional(self): - theta = load_cube( - self.theta_p_alt_path, - (self.theta_constraint - & self.level_constraint - & self.forecast_constraint) - ) - airpress = load_cube( - self.theta_p_alt_path, - (self.airpress_constraint - & self.level_constraint - & self.forecast_constraint) - ) - TestRegrid.patch_data(theta) - TestRegrid.patch_data(airpress) - - # 0-dimensional - theta_0 = theta[0, 0] - airpress_0 = airpress[0, 0] - theta0_regridded = theta_0.regridded(airpress_0, mode='nearest') - airpress0_regridded = airpress_0.regridded(theta_0, mode='nearest') - self.assertEqual(theta_0, theta0_regridded) - self.assertEqual(airpress_0, airpress0_regridded) - self.assertCMLApproxData( - theta0_regridded, - ('regrid', 'theta_on_airpress_0d.cml')) - self.assertCMLApproxData( - airpress0_regridded, - ('regrid', 'airpress_on_theta_0d.cml')) - - # 1-dimensional - theta_1 = theta[0, 1:4] - airpress_1 = airpress[0, 0:4] - self.assertCMLApproxData( - theta_1.regridded(airpress_1, mode='nearest'), - ('regrid', 'theta_on_airpress_1d.cml')) - self.assertCMLApproxData( - airpress_1.regridded(theta_1, mode='nearest'), - ('regrid', 'airpress_on_theta_1d.cml')) - - # 2-dimensional - theta_2 = theta[1:3, 1:4] - airpress_2 = airpress[0:4, 0:4] - self.assertCMLApproxData( - theta_2.regridded(airpress_2, mode='nearest'), - ('regrid', 'theta_on_airpress_2d.cml')) - self.assertCMLApproxData( - airpress_2.regridded(theta_2, mode='nearest'), - ('regrid', 'airpress_on_theta_2d.cml')) - - def test_regrid_3d(self): - theta = load_cube( - self.theta_p_alt_path, - (self.theta_constraint - & self.multi_level_constraint - & self.forecast_constraint) - ) - airpress = load_cube( - self.theta_p_alt_path, - (self.airpress_constraint - & self.multi_level_constraint - & self.forecast_constraint) - ) - TestRegrid.patch_data(theta) - TestRegrid.patch_data(airpress) - - theta_part = theta[:, 1:3, 1:4] - airpress_part = airpress[:, 0:4, 0:4] - self.assertCMLApproxData( - theta_part.regridded(airpress_part, mode='nearest'), - ('regrid', 'theta_on_airpress_3d.cml')) - self.assertCMLApproxData( - airpress_part.regridded(theta_part, mode='nearest'), - ('regrid', 'airpress_on_theta_3d.cml')) - - def test_regrid_max_resolution(self): - low = Cube(np.arange(12).reshape((3, 4))) - cs = GeogCS(6371229) - low.add_dim_coord(DimCoord(np.array([-1, 0, 1], dtype=np.int32), 'latitude', units='degrees', coord_system=cs), 0) - low.add_dim_coord(DimCoord(np.array([-1, 0, 1, 2], dtype=np.int32), 'longitude', units='degrees', coord_system=cs), 1) - - med = Cube(np.arange(20).reshape((4, 5))) - cs = GeogCS(6371229) - med.add_dim_coord(DimCoord(np.array([-1, 0, 1, 2], dtype=np.int32), 'latitude', units='degrees', coord_system=cs), 0) - med.add_dim_coord(DimCoord(np.array([-2, -1, 0, 1, 2], dtype=np.int32), 'longitude', units='degrees', coord_system=cs), 1) - - high = Cube(np.arange(30).reshape((5, 6))) - cs = GeogCS(6371229) - high.add_dim_coord(DimCoord(np.array([-2, -1, 0, 1, 2], dtype=np.int32), 'latitude', units='degrees', coord_system=cs), 0) - high.add_dim_coord(DimCoord(np.array([-2, -1, 0, 1, 2, 3], dtype=np.int32), 'longitude', units='degrees', coord_system=cs), 1) - - cubes = regrid_to_max_resolution([low, med, high], mode='nearest') - self.assertCMLApproxData(cubes, ('regrid', 'low_med_high.cml')) - - -class TestRegridBilinear(tests.IrisTest): - def setUp(self): - self.cs = GeogCS(6371229) - - # Source cube candidate for regridding. - cube = Cube(np.arange(12, dtype=np.float32).reshape(3, 4), long_name='unknown') - cube.units = '1' - cube.add_dim_coord(DimCoord(np.array([1, 2, 3]), 'latitude', units='degrees', coord_system=self.cs), 0) - cube.add_dim_coord(DimCoord(np.array([1, 2, 3, 4]), 'longitude', units='degrees', coord_system=self.cs), 1) - self.source = cube - - # Cube with a smaller grid in latitude and longitude than the source grid by taking the coordinate mid-points. - cube = Cube(np.arange(6, dtype=np.float).reshape(2, 3)) - cube.units = '1' - cube.add_dim_coord(DimCoord(np.array([1.5, 2.5]), 'latitude', units='degrees', coord_system=self.cs), 0) - cube.add_dim_coord(DimCoord(np.array([1.5, 2.5, 3.5]), 'longitude', units='degrees', coord_system=self.cs), 1) - self.smaller = cube - - # Cube with a larger grid in latitude and longitude than the source grid by taking the coordinate mid-points and extrapolating at extremes. - cube = Cube(np.arange(20, dtype=np.float).reshape(4, 5)) - cube.units = '1' - cube.add_dim_coord(DimCoord(np.array([0.5, 1.5, 2.5, 3.5]), 'latitude', units='degrees', coord_system=self.cs), 0) - cube.add_dim_coord(DimCoord(np.array([0.5, 1.5, 2.5, 3.5, 4.5]), 'longitude', units='degrees', coord_system=self.cs), 1) - self.larger = cube - - def test_bilinear_smaller_lon_left(self): - # Anchor smaller grid from the first point in longitude and perform mid-point linear interpolation in latitude. - self.smaller.coord('longitude').points = self.smaller.coord('longitude').points - 0.5 - self.assertCMLApproxData(self.source.regridded(self.smaller), ('regrid', 'bilinear_smaller_lon_align_left.cml')) - - def test_bilinear_smaller(self): - # Perform mid-point bilinear interpolation over both latitude and longitude. - self.assertCMLApproxData(self.source.regridded(self.smaller), ('regrid', 'bilinear_smaller.cml')) - - def test_bilinear_smaller_lon_right(self): - # Anchor smaller grid from the last point in longitude and perform mid-point linear interpolation in latitude. - self.smaller.coord('longitude').points = self.smaller.coord('longitude').points + 0.5 - self.assertCMLApproxData(self.source.regridded(self.smaller), ('regrid', 'bilinear_smaller_lon_align_right.cml')) - - def test_bilinear_larger_lon_left(self): - # Extrapolate first point of longitude with others aligned to source grid, and perform linear interpolation with extrapolation over latitude. - coord = iris.coords.DimCoord(np.array([0.5, 1, 2, 3, 4]), 'longitude', units='degrees', coord_system=self.cs) - self.larger.remove_coord('longitude') - self.larger.add_dim_coord(coord, 1) - self.assertCMLApproxData(self.source.regridded(self.larger), ('regrid', 'bilinear_larger_lon_extrapolate_left.cml')) - - def test_bilinear_larger(self): - # Perform mid-point bi-linear interpolation with extrapolation over latitude and longitude. - self.assertCMLApproxData(self.source.regridded(self.larger), ('regrid', 'bilinear_larger.cml')) - - def test_bilinear_larger_lon_right(self): - # Extrapolate last point of longitude with others aligned to source grid, and perform linear interpolation with extrapolation over latitude. - coord = iris.coords.DimCoord(np.array([1, 2, 3, 4, 4.5]), 'longitude', units='degrees', coord_system=self.cs) - self.larger.remove_coord('longitude') - self.larger.add_dim_coord(coord, 1) - self.assertCMLApproxData(self.source.regridded(self.larger), ('regrid', 'bilinear_larger_lon_extrapolate_right.cml')) - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/test_rules.py b/lib/iris/tests/test_rules.py deleted file mode 100644 index 2da9984be6..0000000000 --- a/lib/iris/tests/test_rules.py +++ /dev/null @@ -1,197 +0,0 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -""" -Test metadata translation rules. - -""" -# import iris tests first so that some things can be initialised before importing anything else -import iris.tests as tests - -import types - -from iris.aux_factory import HybridHeightFactory -from iris.cube import Cube -from iris.fileformats.rules import ConcreteReferenceTarget, Factory, Loader, \ - Reference, ReferenceTarget, RuleResult, \ - load_cubes -import iris.tests.stock as stock - - -class Mock(object): - def __repr__(self): - return ''.format(self.__dict__) - - -class TestConcreteReferenceTarget(tests.IrisTest): - def test_attributes(self): - with self.assertRaises(TypeError): - target = ConcreteReferenceTarget() - - target = ConcreteReferenceTarget('foo') - self.assertEqual(target.name, 'foo') - self.assertIsNone(target.transform) - - transform = lambda _: _ - target = ConcreteReferenceTarget('foo', transform) - self.assertEqual(target.name, 'foo') - self.assertIs(target.transform, transform) - - def test_single_cube_no_transform(self): - target = ConcreteReferenceTarget('foo') - src = stock.simple_2d() - target.add_cube(src) - self.assertIs(target.as_cube(), src) - - def test_single_cube_with_transform(self): - transform = lambda cube: {'long_name': 'wibble'} - target = ConcreteReferenceTarget('foo', transform) - src = stock.simple_2d() - target.add_cube(src) - dest = target.as_cube() - self.assertEqual(dest.long_name, 'wibble') - self.assertNotEqual(dest, src) - dest.long_name = src.long_name - self.assertEqual(dest, src) - - def test_multiple_cubes_no_transform(self): - target = ConcreteReferenceTarget('foo') - src = stock.realistic_4d() - for i in range(src.shape[0]): - target.add_cube(src[i]) - dest = target.as_cube() - self.assertIsNot(dest, src) - self.assertEqual(dest, src) - - def test_multiple_cubes_with_transform(self): - transform = lambda cube: {'long_name': 'wibble'} - target = ConcreteReferenceTarget('foo', transform) - src = stock.realistic_4d() - for i in range(src.shape[0]): - target.add_cube(src[i]) - dest = target.as_cube() - self.assertEqual(dest.long_name, 'wibble') - self.assertNotEqual(dest, src) - dest.long_name = src.long_name - self.assertEqual(dest, src) - - -class TestLoadCubes(tests.IrisTest): - def test_simple_factory(self): - # Test the creation process for a factory definition which only - # uses simple dict arguments. - - # The fake PPField which will be supplied to our converter. - field = Mock() - field.data = None - field_generator = lambda filename: [field] - # A fake conversion function returning: - # 1) A parameter cube needing a simple factory construction. - aux_factory = Mock() - factory = Mock() - factory.args = [{'name': 'foo'}] - factory.factory_class = lambda *args: \ - setattr(aux_factory, 'fake_args', args) or aux_factory - def converter(field): - return ([factory], [], '', '', '', {}, [], [], []) - # Finish by making a fake Loader - fake_loader = Loader(field_generator, {}, converter, None) - cubes = load_cubes(['fake_filename'], None, fake_loader) - - # Check the result is a generator with a single entry. - self.assertIsInstance(cubes, types.GeneratorType) - try: - # Suppress the normal Cube.coord() and Cube.add_aux_factory() - # methods. - coord_method = Cube.coord - add_aux_factory_method = Cube.add_aux_factory - Cube.coord = lambda self, **args: args - Cube.add_aux_factory = lambda self, aux_factory: \ - setattr(self, 'fake_aux_factory', aux_factory) - - cubes = list(cubes) - finally: - Cube.coord = coord_method - Cube.add_aux_factory = add_aux_factory_method - self.assertEqual(len(cubes), 1) - # Check the "cube" has an "aux_factory" added, which itself - # must have been created with the correct arguments. - self.assertTrue(hasattr(cubes[0], 'fake_aux_factory')) - self.assertIs(cubes[0].fake_aux_factory, aux_factory) - self.assertTrue(hasattr(aux_factory, 'fake_args')) - self.assertEqual(aux_factory.fake_args, ({'name': 'foo'},)) - - def test_cross_reference(self): - # Test the creation process for a factory definition which uses - # a cross-reference. - - param_cube = stock.realistic_4d_no_derived() - orog_coord = param_cube.coord('surface_altitude') - param_cube.remove_coord(orog_coord) - - orog_cube = param_cube[0, 0, :, :] - orog_cube.data = orog_coord.points - orog_cube.rename('surface_altitude') - orog_cube.units = orog_coord.units - orog_cube.attributes = orog_coord.attributes - - # We're going to test for the presence of the hybrid height - # stuff later, so let's make sure it's not already there! - assert len(param_cube.aux_factories) == 0 - assert not param_cube.coords('surface_altitude') - - # The fake PPFields which will be supplied to our converter. - press_field = Mock() - press_field.data = param_cube.data - orog_field = Mock() - orog_field.data = orog_cube.data - field_generator = lambda filename: [press_field, orog_field] - # A fake rule set returning: - # 1) A parameter cube needing an "orography" reference - # 2) An "orography" cube - def converter(field): - if field is press_field: - src = param_cube - factories = [Factory(HybridHeightFactory, - [Reference('orography')])] - references = [] - else: - src = orog_cube - factories = [] - references = [ReferenceTarget('orography', None)] - dim_coords_and_dims = [(coord, src.coord_dims(coord)[0]) - for coord in src.dim_coords] - aux_coords_and_dims = [(coord, src.coord_dims(coord)) - for coord in src.aux_coords] - return (factories, references, src.standard_name, src.long_name, - src.units, src.attributes, src.cell_methods, - dim_coords_and_dims, aux_coords_and_dims) - # Finish by making a fake Loader - fake_loader = Loader(field_generator, {}, converter, None) - cubes = load_cubes(['fake_filename'], None, fake_loader) - - # Check the result is a generator containing two Cubes. - self.assertIsInstance(cubes, types.GeneratorType) - cubes = list(cubes) - self.assertEqual(len(cubes), 2) - # Check the "cube" has an "aux_factory" added, which itself - # must have been created with the correct arguments. - self.assertEqual(len(cubes[1].aux_factories), 1) - self.assertEqual(len(cubes[1].coords('surface_altitude')), 1) - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/test_std_names.py b/lib/iris/tests/test_std_names.py index 8d4a04fe5a..3fd1d07614 100644 --- a/lib/iris/tests/test_std_names.py +++ b/lib/iris/tests/test_std_names.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -15,12 +15,16 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . -import unittest +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before importing anything else +import iris.tests as tests from iris.std_names import STD_NAMES -class TestStandardNames(unittest.TestCase): +class TestStandardNames(tests.IrisTest): """ standard_names.py is a machine generated file which contains a single dictionary called STD_NAMES @@ -47,4 +51,4 @@ def test_standard_names(self): if __name__ == "__main__": - unittest.main() + tests.main() diff --git a/lib/iris/tests/test_trajectory.py b/lib/iris/tests/test_trajectory.py deleted file mode 100644 index 4018eae47c..0000000000 --- a/lib/iris/tests/test_trajectory.py +++ /dev/null @@ -1,169 +0,0 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . - - -# import iris tests first so that some things can be initialised before importing anything else -import iris.tests as tests - -import biggus -import matplotlib.pyplot as plt -import numpy as np - -import iris.analysis.trajectory -import iris.tests.stock - - -class TestSimple(tests.IrisTest): - def test_invalid_coord(self): - cube = iris.tests.stock.realistic_4d() - sample_points = [('altitude', [0, 10, 50])] - with self.assertRaises(ValueError): - iris.analysis.trajectory.interpolate(cube, sample_points, 'nearest') - - -class TestTrajectory(tests.IrisTest): - def test_trajectory_definition(self): - # basic 2-seg line along x - waypoints = [ {'lat':0, 'lon':0}, {'lat':0, 'lon':1}, {'lat':0, 'lon':2} ] - trajectory = iris.analysis.trajectory.Trajectory(waypoints, sample_count=21) - - self.assertEqual(trajectory.length, 2.0) - self.assertEqual(trajectory.sampled_points[19], {'lat': 0.0, 'lon': 1.9000000000000001}) - - # 4-seg m-shape - waypoints = [ {'lat':0, 'lon':0}, {'lat':1, 'lon':1}, {'lat':0, 'lon':2}, {'lat':1, 'lon':3}, {'lat':0, 'lon':4} ] - trajectory = iris.analysis.trajectory.Trajectory(waypoints, sample_count=33) - - self.assertEqual(trajectory.length, 5.6568542494923806) - self.assertEqual(trajectory.sampled_points[31], {'lat': 0.12499999999999989, 'lon': 3.875}) - - @iris.tests.skip_data - def test_trajectory_extraction(self): - - # Load the COLPEX data => TZYX - path = tests.get_data_path(['PP', 'COLPEX', 'theta_and_orog_subset.pp']) - cube = iris.load_cube(path, 'air_potential_temperature') - cube.coord('grid_latitude').bounds = None - cube.coord('grid_longitude').bounds = None - # TODO: Workaround until regrid can handle factories - cube.remove_aux_factory(cube.aux_factories[0]) - cube.remove_coord('surface_altitude') - self.assertCML(cube, ('trajectory', 'big_cube.cml')) - - # Pull out a single point - single_point = iris.analysis.trajectory.interpolate( - cube, [('grid_latitude', [-0.1188]), - ('grid_longitude', [359.57958984])]) - self.assertCML(single_point, ('trajectory', 'single_point.cml')) - - # Extract a simple, axis-aligned trajectory that is similar to an indexing operation. - # (It's not exactly the same because the source cube doesn't have regular spacing.) - waypoints = [ - {'grid_latitude': -0.1188, 'grid_longitude': 359.57958984}, - {'grid_latitude': -0.1188, 'grid_longitude': 359.66870117} - ] - trajectory = iris.analysis.trajectory.Trajectory(waypoints, sample_count=100) - def traj_to_sample_points(trajectory): - sample_points = [] - src_points = trajectory.sampled_points - for name in src_points[0].iterkeys(): - values = [point[name] for point in src_points] - sample_points.append((name, values)) - return sample_points - sample_points = traj_to_sample_points(trajectory) - trajectory_cube = iris.analysis.trajectory.interpolate(cube, - sample_points) - self.assertCML(trajectory_cube, ('trajectory', 'constant_latitude.cml')) - - # Sanity check the results against a simple slice - plt.plot(cube[0, 0, 10, :].data) - plt.plot(trajectory_cube[0, 0, :].data) - self.check_graphic() - - # Extract a zig-zag trajectory - waypoints = [ - {'grid_latitude': -0.1188, 'grid_longitude': 359.5886}, - {'grid_latitude': -0.0828, 'grid_longitude': 359.6606}, - {'grid_latitude': -0.0468, 'grid_longitude': 359.6246}, - ] - trajectory = iris.analysis.trajectory.Trajectory(waypoints, sample_count=100) - sample_points = traj_to_sample_points(trajectory) - trajectory_cube = iris.analysis.trajectory.interpolate(cube, - sample_points) - self.assertCML(trajectory_cube, ('trajectory', 'zigzag.cml')) - - # Sanity check the results against a simple slice - x = cube.coord('grid_longitude').points - y = cube.coord('grid_latitude').points - plt.pcolormesh(x, y, cube[0, 0, :, :].data) - x = trajectory_cube.coord('grid_longitude').points - y = trajectory_cube.coord('grid_latitude').points - plt.scatter(x, y, c=trajectory_cube[0, 0, :].data) - self.check_graphic() - - @iris.tests.skip_data - def test_tri_polar(self): - # load data - cubes = iris.load(tests.get_data_path(['NetCDF', 'ORCA2', 'votemper.nc'])) - cube = cubes[0] - # The netCDF file has different data types for the points and - # bounds of 'depth'. This wasn't previously supported, so we - # emulate that old behaviour. - cube.coord('depth').bounds = cube.coord('depth').bounds.astype(np.float32) - - # define a latitude trajectory (put coords in a different order to the cube, just to be awkward) - latitudes = range(-90, 90, 2) - longitudes = [-90]*len(latitudes) - sample_points = [('longitude', longitudes), ('latitude', latitudes)] - - # extract - sampled_cube = iris.analysis.trajectory.interpolate(cube, sample_points) - self.assertCML(sampled_cube, ('trajectory', 'tri_polar_latitude_slice.cml')) - - # turn it upside down for the visualisation - plot_cube = sampled_cube[0] - plot_cube = plot_cube[::-1, :] - - plt.clf() - plt.pcolormesh(plot_cube.data, vmin=cube.data.min(), vmax=cube.data.max()) - plt.colorbar() - self.check_graphic() - - # Try to request linear interpolation. - # Not allowed, as we have multi-dimensional coords. - self.assertRaises(iris.exceptions.CoordinateMultiDimError, iris.analysis.trajectory.interpolate, cube, sample_points, method="linear") - - # Try to request unknown interpolation. - self.assertRaises(ValueError, iris.analysis.trajectory.interpolate, cube, sample_points, method="linekar") - - def test_hybrid_height(self): - cube = tests.stock.simple_4d_with_hybrid_height() - # Put a biggus array on the cube so we can test deferred loading. - cube.lazy_data(biggus.NumpyArrayAdapter(cube.data)) - - traj = (('grid_latitude',[20.5, 21.5, 22.5, 23.5]), - ('grid_longitude',[31, 32, 33, 34])) - xsec = iris.analysis.trajectory.interpolate(cube, traj, method='nearest') - - # Check that creating the trajectory hasn't led to the original - # data being loaded. - self.assertTrue(cube.has_lazy_data()) - self.assertCML([cube, xsec], ('trajectory', 'hybrid_height.cml')) - - -if __name__ == '__main__': - tests.main() diff --git a/lib/iris/tests/test_unit.py b/lib/iris/tests/test_unit.py deleted file mode 100644 index 5228dfa93a..0000000000 --- a/lib/iris/tests/test_unit.py +++ /dev/null @@ -1,834 +0,0 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -""" -Test Unit the wrapper class for Unidata udunits2. - -""" -# import iris tests first so that some things can be initialised before importing anything else -import iris.tests as tests - -import copy -import datetime as datetime -import operator - -import numpy as np - -import iris.unit as unit - - -Unit = unit.Unit - - -class TestUnit(tests.IrisTest): - def setUp(self): - unit._handler(unit._ut_ignore) - - def tearDown(self): - unit._handler(unit._default_handler) - - -class TestCreation(TestUnit): - # - # test: unit creation - # - def test_unit_fail_0(self): - self.assertRaises(ValueError, Unit, 'wibble') - - def test_unit_pass_0(self): - u = Unit(' meter') - self.assertTrue(u.name, 'meter') - - def test_unit_pass_1(self): - u = Unit('meter ') - self.assertTrue(u.name, 'meter') - - def test_unit_pass_2(self): - u = Unit(' meter ') - self.assertTrue(u.name, 'meter') - - def test_calendar(self): - calendar = unit.CALENDAR_365_DAY - u = Unit('hours since 1970-01-01 00:00:00', calendar=calendar) - self.assertEqual(u.calendar, calendar) - - def test_no_calendar(self): - u = Unit('hours since 1970-01-01 00:00:00') - self.assertEqual(u.calendar, unit.CALENDAR_GREGORIAN) - - def test_unknown_calendar(self): - with self.assertRaises(ValueError): - u = Unit('hours since 1970-01-01 00:00:00', calendar='wibble') - - -class TestModulus(TestUnit): - # - # test: modulus property - # - def test_modulus_pass_0(self): - u = Unit("degrees") - self.assertEqual(u.modulus, 360.0) - - def test_modulus_pass_1(self): - u = Unit("radians") - self.assertEqual(u.modulus, np.pi*2) - - def test_modulus_pass_2(self): - u = Unit("meter") - self.assertEqual(u.modulus, None) - - -class TestConvertible(TestUnit): - # - # test: convertible method - # - def test_convertible_fail_0(self): - u = Unit("meter") - v = Unit("newton") - self.assertFalse(u.is_convertible(v)) - - def test_convertible_pass_0(self): - u = Unit("meter") - v = Unit("mile") - self.assertTrue(u.is_convertible(v)) - - def test_convertible_fail_1(self): - u = Unit('meter') - v = Unit('unknown') - self.assertFalse(u.is_convertible(v)) - self.assertFalse(v.is_convertible(u)) - - def test_convertible_fail_2(self): - u = Unit('meter') - v = Unit('no unit') - self.assertFalse(u.is_convertible(v)) - self.assertFalse(v.is_convertible(u)) - - def test_convertible_fail_3(self): - u = Unit('unknown') - v = Unit('no unit') - self.assertFalse(u.is_convertible(v)) - self.assertFalse(v.is_convertible(u)) - - -class TestDimensionless(TestUnit): - # - # test: dimensionless property - # - def test_dimensionless_fail_0(self): - u = Unit("meter") - self.assertFalse(u.is_dimensionless()) - - def test_dimensionless_pass_0(self): - u = Unit("1") - self.assertTrue(u.is_dimensionless()) - - def test_dimensionless_fail_1(self): - u = Unit('unknown') - self.assertFalse(u.is_dimensionless()) - - def test_dimensionless_fail_2(self): - u = Unit('no unit') - self.assertFalse(u.is_dimensionless()) - - -class TestFormat(TestUnit): - # - # test: format method - # - def test_format_pass_0(self): - u = Unit("watt") - self.assertEqual(u.format(), "W") - - def test_format_pass_1(self): - u = Unit("watt") - self.assertEqual(u.format(unit.UT_ASCII), "W") - - def test_format_pass_2(self): - u = Unit("watt") - self.assertEqual(u.format(unit.UT_NAMES), "watt") - - def test_format_pass_3(self): - u = Unit("watt") - self.assertEqual(u.format(unit.UT_DEFINITION), "m2.kg.s-3") - - def test_format_pass_4(self): - u = Unit('?') - self.assertEqual(u.format(), 'unknown') - - def test_format_pass_5(self): - u = Unit('nounit') - self.assertEqual(u.format(), 'no_unit') - - -class TestName(TestUnit): - # - # test: name property - # - def test_name_pass_0(self): - u = Unit("newton") - self.assertEqual(u.name, 'newton') - - def test_name_pass_1(self): - u = Unit('unknown') - self.assertEqual(u.name, 'unknown') - - def test_name_pass_2(self): - u = Unit('no unit') - self.assertEqual(u.name, 'no_unit') - - -class TestSymbol(TestUnit): - # - # test: symbol property - # - def test_symbol_pass_0(self): - u = Unit("joule") - self.assertEqual(u.symbol, 'J') - - def test_symbol_pass_1(self): - u = Unit('unknown') - self.assertEqual(u.symbol, unit._UNKNOWN_UNIT_SYMBOL) - - def test_symbol_pass_2(self): - u = Unit('no unit') - self.assertEqual(u.symbol, unit._NO_UNIT_SYMBOL) - - -class TestDefinition(TestUnit): - # - # test: definition property - # - def test_definition_pass_0(self): - u = Unit("joule") - self.assertEqual(u.definition, 'm2.kg.s-2') - - def test_definition_pass_1(self): - u = Unit('unknown') - self.assertEqual(u.definition, unit._UNKNOWN_UNIT_SYMBOL) - - def test_definition_pass_2(self): - u = Unit('no unit') - self.assertEqual(u.definition, unit._NO_UNIT_SYMBOL) - - -class TestOffset(TestUnit): - # - # test: offset method - # - def test_offset_fail_0(self): - u = Unit("meter") - self.assertRaises(TypeError, operator.add, u, "naughty") - - def test_offset_fail_1(self): - u = Unit('unknown') - self.assertEqual(u + 10, 'unknown') - - def test_offset_fail_2(self): - u = Unit('no unit') - self.assertRaises(ValueError, operator.add, u, 10) - - def test_offset_pass_0(self): - u = Unit("meter") - self.assertEqual(u + 10, "m @ 10") - - def test_offset_pass_1(self): - u = Unit("meter") - self.assertEqual(u + 100.0, "m @ 100") - - def test_offset_pass_2(self): - u = Unit("meter") - self.assertEqual(u + 1000L, "m @ 1000") - - -class TestOffsetByTime(TestUnit): - # - # test: offset_by_time method - # - def test_offset_by_time_fail_0(self): - u = Unit("hour") - self.assertRaises(TypeError, u.offset_by_time, "naughty") - - def test_offset_by_time_fail_1(self): - u = Unit("mile") - self.assertRaises(ValueError, u.offset_by_time, 10) - - def test_offset_by_time_fail_2(self): - u = Unit('unknown') - self.assertRaises(ValueError, u.offset_by_time, unit.encode_time(1970, 1, 1, 0, 0, 0)) - - def test_offset_by_time_fail_3(self): - u = Unit('no unit') - self.assertRaises(ValueError, u.offset_by_time, unit.encode_time(1970, 1, 1, 0, 0, 0)) - - def test_offset_by_time_pass_0(self): - u = Unit("hour") - v = u.offset_by_time(unit.encode_time(2007, 1, 15, 12, 6, 0)) - self.assertEqual(v, "(3600 s) @ 20070115T120600.00000000 UTC") - - -class TestInvert(TestUnit): - # - # test: invert method - # - def test_invert_fail_0(self): - u = Unit('unknown') - self.assertEqual(u.invert(), u) - - def test_invert_fail_1(self): - u = Unit('no unit') - self.assertRaises(ValueError, u.invert) - - def test_invert_pass_0(self): - u = Unit("newton") - self.assertEqual(u.invert(), "m-1.kg-1.s2") - self.assertEqual(u.invert().invert(), "N") - - -class TestRoot(TestUnit): - # - # test: root method - # - def test_root_fail_0(self): - u = Unit("volt") - self.assertRaises(TypeError, u.root, "naughty") - - def test_root_fail_1(self): - u = Unit("volt") - self.assertRaises(TypeError, u.root, 1.2) - - def test_root_fail_2(self): - u = Unit("volt") - self.assertRaises(ValueError, u.root, 2) - - def test_root_fail_3(self): - u = Unit('unknown') - self.assertEqual(u.root(2), u) - - def test_root_fail_4(self): - u = Unit('no unit') - self.assertRaises(ValueError, u.root, 2) - - def test_root_pass_0(self): - u = Unit("volt^2") - self.assertEqual(u.root(2), "V") - - -class TestLog(TestUnit): - # - # test: log method - # - def test_log_fail_0(self): - u = Unit("hPa") - self.assertRaises(TypeError, u.log, "naughty") - - def test_log_fail_1(self): - u = Unit('unknown') - self.assertEqual(u.log(10), u) - - def test_log_fail_2(self): - u = Unit('no unit') - self.assertRaises(ValueError, u.log, 10) - - def test_log_pass_0(self): - u = Unit("hPa") - self.assertEqual(u.log(10), "lg(re 100 Pa)") - - -class TestMultiply(TestUnit): - def test_multiply_fail_0(self): - u = Unit("amp") - self.assertRaises(ValueError, operator.mul, u, "naughty") - - def test_multiply_fail_1(self): - u = Unit('unknown') - v = Unit('meters') - self.assertTrue((u * v).is_unknown()) - self.assertTrue((v * u).is_unknown()) - - def test_multiply_fail_3(self): - u = Unit('unknown') - v = Unit('no unit') - self.assertRaises(ValueError, operator.mul, u, v) - self.assertRaises(ValueError, operator.mul, v, u) - - def test_multiply_fail_5(self): - u = Unit('meters') - v = Unit('no unit') - self.assertRaises(ValueError, operator.mul, u, v) - self.assertRaises(ValueError, operator.mul, v, u) - - def test_multiply_pass_0(self): - u = Unit("amp") - self.assertEqual((u * 10).format(), "10 A") - - def test_multiply_pass_1(self): - u = Unit("amp") - self.assertEqual((u * 100.0).format(), "100 A") - - def test_multiply_pass_2(self): - u = Unit("amp") - self.assertEqual((u * 1000L).format(), "1000 A") - - def test_multiply_pass_3(self): - u = Unit("amp") - v = Unit("volt") - self.assertEqual((u * v).format(), "W") - - -class TestDivide(TestUnit): - def test_divide_fail_0(self): - u = Unit("watts") - self.assertRaises(ValueError, operator.div, u, "naughty") - - def test_divide_fail_1(self): - u = Unit('unknown') - v = Unit('meters') - self.assertTrue((u / v).is_unknown()) - self.assertTrue((v / u).is_unknown()) - - def test_divide_fail_3(self): - u = Unit('unknown') - v = Unit('no unit') - self.assertRaises(ValueError, operator.div, u, v) - self.assertRaises(ValueError, operator.div, v, u) - - def test_divide_fail_5(self): - u = Unit('meters') - v = Unit('no unit') - self.assertRaises(ValueError, operator.div, u, v) - self.assertRaises(ValueError, operator.div, v, u) - - def test_divide_pass_0(self): - u = Unit("watts") - self.assertEqual((u / 10).format(), "0.1 W") - - def test_divide_pass_1(self): - u = Unit("watts") - self.assertEqual((u / 100.0).format(), "0.01 W") - - def test_divide_pass_2(self): - u = Unit("watts") - self.assertEqual((u / 1000L).format(), "0.001 W") - - def test_divide_pass_3(self): - u = Unit("watts") - v = Unit("volts") - self.assertEqual((u / v).format(), "A") - - -class TestPower(TestUnit): - def test_power(self): - u = Unit("amp") - self.assertRaises(TypeError, operator.pow, u, "naughty") - self.assertRaises(TypeError, operator.pow, u, Unit('m')) - self.assertRaises(TypeError, operator.pow, u, Unit('unknown')) - self.assertRaises(TypeError, operator.pow, u, Unit('no unit')) - self.assertEqual(u ** 2, Unit('A^2')) - self.assertEqual(u ** 3.0, Unit('A^3')) - self.assertEqual(u ** 4L, Unit('A^4')) - self.assertRaises(ValueError, operator.pow, u, 2.4) - - u = Unit("m^2") - self.assertEqual(u ** 0.5, Unit('m')) - self.assertRaises(ValueError, operator.pow, u, 0.4) - - def test_power_unknown(self): - u = Unit('unknown') - self.assertRaises(TypeError, operator.pow, u, "naughty") - self.assertRaises(TypeError, operator.pow, u, Unit('m')) - self.assertEqual(u ** 2, Unit('unknown')) - self.assertEqual(u ** 3.0, Unit('unknown')) - self.assertEqual(u ** 4L, Unit('unknown')) - - def test_power_nounit(self): - u = Unit('no unit') - self.assertRaises(TypeError, operator.pow, u, "naughty") - self.assertRaises(TypeError, operator.pow, u, Unit('m')) - self.assertRaises(ValueError, operator.pow, u, 2) - - -class TestCopy(TestUnit): - # - # test: copy method - # - def test_copy_pass_0(self): - u = Unit("joule") - self.assertEqual(copy.copy(u) == u, True) - - def test_copy_pass_1(self): - u = Unit('unknown') - self.assertTrue(copy.copy(u).is_unknown()) - - def test_copy_pass_2(self): - u = Unit('no unit') - self.assertTrue(copy.copy(u).is_no_unit()) - - -class TestStringify(TestUnit): - # - # test: __str__ method - # - def test_str_pass_0(self): - u = Unit("meter") - self.assertEqual(str(u), "meter") - - # - # test: __repr__ method - # - def test_repr_pass_0(self): - u = Unit("meter") - self.assertEqual(repr(u), "Unit('meter')") - - def test_repr_pass_1(self): - u = Unit("hours since 2007-01-15 12:06:00", calendar=unit.CALENDAR_STANDARD) - #self.assertEqual(repr(u), "Unit('hour since 2007-01-15 12:06:00.00000000 UTC', calendar='standard')") - self.assertEqual(repr(u), "Unit('hours since 2007-01-15 12:06:00', calendar='standard')") - - -class TestRichComparison(TestUnit): - # - # test: __eq__ method - # - def test_eq_pass_0(self): - u = Unit("meter") - v = Unit("amp") - self.assertEqual(u == v, False) - - def test_eq_pass_1(self): - u = Unit("meter") - v = Unit("m.s-1") - w = Unit("hertz") - self.assertEqual(u == (v / w), True) - - def test_eq_pass_2(self): - u = Unit("meter") - self.assertEqual(u == "meter", True) - - def test_eq_cross_category(self): - m = Unit("meter") - u = Unit('unknown') - n = Unit('no_unit') - self.assertFalse(m == u) - self.assertFalse(m == n) - self.assertFalse(u == n) - - # - # test: __ne__ method - # - def test_neq_pass_0(self): - u = Unit("meter") - v = Unit("amp") - self.assertEqual(u != v, True) - - def test_neq_pass_1(self): - u = Unit("meter") - self.assertEqual(u != 'meter', False) - - def test_ne_cross_category(self): - m = Unit("meter") - u = Unit('unknown') - n = Unit('no_unit') - self.assertTrue(m != u) - self.assertTrue(m != n) - self.assertTrue(u != n) - - -class TestOrdering(TestUnit): - def test_order(self): - m = Unit("meter") - u = Unit('unknown') - n = Unit('no_unit') - start = [m, u, n] - self.assertEqual(sorted(start), [m, n, u]) - - -class TestTimeEncoding(TestUnit): - # - # test: encode_time module function - # - def test_encode_time_pass_0(self): - result = unit.encode_time(2006, 1, 15, 12, 6, 0) - self.assertEqual(result, 159019560.0) - - # - # test: encode_date module function - # - def test_encode_date_pass_0(self): - result = unit.encode_date(2006, 1, 15) - self.assertEqual(result, 158976000.0) - - # - # test: encode_clock module function - # - def test_encode_clock_pass_0(self): - result = unit.encode_clock(12, 6, 0) - self.assertEqual(result, 43560.0) - - # - # test: decode_time module function - # - def test_decode_time_pass_0(self): - (year, month, day, hour, min, sec, res) = unit.decode_time(158976000.0+43560.0) - self.assertEqual((year, month, day, hour, min, sec), (2006, 1, 15, 12, 6, 0)) - - -class TestConvert(TestUnit): - # - # test: convert method - # - def test_convert_float_pass_0(self): - u = Unit("meter") - v = Unit("mile") - self.assertEqual(u.convert(1609.344, v), 1.0) - - def test_convert_float_pass_1(self): - u = Unit("meter") - v = Unit("mile") - a = (np.arange(2, dtype=np.float32) + 1) * 1609.344 - res = u.convert(a, v) - e = np.arange(2, dtype=np.float32) + 1 - self.assertEqual(res[0], e[0]) - self.assertEqual(res[1], e[1]) - - def test_convert_np_float(self): - u = Unit("mile") - v = Unit("meter") - self.assertEqual(u.convert(np.float(1.0), v), 1609.344) - self.assertEqual(u.convert(np.float16(1.0), v), 1609.344) - self.assertEqual(u.convert(np.float32(1.0), v), 1609.344) - self.assertEqual(u.convert(np.float64(1.0), v), 1609.344) - - def test_convert_double_pass_0(self): - u = Unit("meter") - v = Unit("mile") - self.assertEqual(u.convert(1609.344, v, unit.FLOAT64), 1.0) - - def test_convert_double_pass_1(self): - u = Unit("meter") - v = Unit("mile") - a = (np.arange(2, dtype=np.float64) + 1) * 1609.344 - res = u.convert(a, v, unit.FLOAT64) - e = np.arange(2, dtype=np.float64) + 1 - self.assertEqual(res[0], e[0]) - self.assertEqual(res[1], e[1]) - - def test_convert_int(self): - u = Unit("mile") - v = Unit("meter") - self.assertEqual(u.convert(1, v), 1609.344) - - def test_convert_int_array(self): - u = Unit("mile") - v = Unit("meter") - a = np.arange(2, dtype=np.int) + 1 - res = u.convert(a, v) - e = (np.arange(2, dtype=np.float64) + 1) * 1609.344 - self.assertArrayAlmostEqual(res, e) - - def test_convert_int_array_ctypearg(self): - u = Unit("mile") - v = Unit("meter") - a = np.arange(2, dtype=np.int) + 1 - - res = u.convert(a, v, unit.FLOAT32) - e = (np.arange(2, dtype=np.float32) + 1) * 1609.344 - self.assertEqual(res.dtype, e.dtype) - self.assertArrayAlmostEqual(res, e) - - res = u.convert(a, v, unit.FLOAT64) - e = (np.arange(2, dtype=np.float64) + 1) * 1609.344 - self.assertEqual(res.dtype, e.dtype) - self.assertArrayAlmostEqual(res, e) - - def test_convert_np_int(self): - u = Unit("mile") - v = Unit("meter") - self.assertEqual(u.convert(np.int(1), v), 1609.344) - self.assertEqual(u.convert(np.int8(1), v), 1609.344) - self.assertEqual(u.convert(np.int16(1), v), 1609.344) - self.assertEqual(u.convert(np.int32(1), v), 1609.344) - self.assertEqual(u.convert(np.int64(1), v), 1609.344) - - def test_convert_fail_0(self): - u = Unit('unknown') - v = Unit('no unit') - w = Unit('meters') - x = Unit('kg') - a = np.arange(10) - - # unknown and/or no-unit - self.assertRaises(ValueError, u.convert, a, v) - self.assertRaises(ValueError, v.convert, a, u) - self.assertRaises(ValueError, w.convert, a, u) - self.assertRaises(ValueError, w.convert, a, v) - self.assertRaises(ValueError, u.convert, a, w) - self.assertRaises(ValueError, v.convert, a, w) - - # Incompatible units - self.assertRaises(ValueError, w.convert, a, x) - - def test_convert_time_ref_0(self): - # Test converting from one reference time to another on non-standard - # calendar. - u1 = Unit('seconds since 1978-09-01 00:00:00', calendar='360_day') - u2 = Unit('seconds since 1979-04-01 00:00:00', calendar='360_day') - u1point = np.array([ 54432000.], dtype=np.float32) - u2point = np.array([ 36288000.], dtype=np.float32) - res = u1.convert(u1point, u2) - self.assertArrayAlmostEqual(res, u2point) - - def test_convert_time_fail_0(self): - # Test converting from one reference time to another between different - # calendars raises an error. - u1 = Unit('seconds since 1978-09-01 00:00:00', calendar='360_day') - u2 = Unit('seconds since 1979-04-01 00:00:00', calendar='gregorian') - u1point = np.array([ 54432000.], dtype=np.float32) - with self.assertRaises(ValueError): - u1.convert(u1point, u2) - - -class TestNumsAndDates(TestUnit): - # - # test: num2date method - # - def test_num2date_pass_0(self): - u = Unit("hours since 2010-11-02 12:00:00", calendar=unit.CALENDAR_STANDARD) - self.assertEqual(str(u.num2date(1)), "2010-11-02 13:00:00") - - # - # test: date2num method - # - def test_date2num_pass_0(self): - u = Unit("hours since 2010-11-02 12:00:00", calendar=unit.CALENDAR_STANDARD) - d = datetime.datetime(2010, 11, 2, 13, 0, 0) - self.assertEqual(str(u.num2date(u.date2num(d))), "2010-11-02 13:00:00") - - -class TestUnknown(TestUnit): - # - # test: unknown units - # - def test_unknown_unit_pass_0(self): - u = Unit("?") - self.assertTrue(u.is_unknown()) - - def test_unknown_unit_pass_1(self): - u = Unit("???") - self.assertTrue(u.is_unknown()) - - def test_unknown_unit_pass_2(self): - u = Unit("unknown") - self.assertTrue(u.is_unknown()) - - def test_unknown_unit_fail_0(self): - u = Unit('no unit') - self.assertFalse(u.is_unknown()) - - def test_unknown_unit_fail_2(self): - u = Unit('meters') - self.assertFalse(u.is_unknown()) - - -class TestNoUnit(TestUnit): - # - # test: no unit - # - def test_no_unit_pass_0(self): - u = Unit('no_unit') - self.assertTrue(u.is_no_unit()) - - def test_no_unit_pass_1(self): - u = Unit('no unit') - self.assertTrue(u.is_no_unit()) - - def test_no_unit_pass_2(self): - u = Unit('no-unit') - self.assertTrue(u.is_no_unit()) - - def test_no_unit_pass_3(self): - u = Unit('nounit') - self.assertTrue(u.is_no_unit()) - - -class TestTimeReference(TestUnit): - # - # test: time reference - # - def test_time_reference_pass_0(self): - u = Unit('hours since epoch') - self.assertTrue(u.is_time_reference()) - - def test_time_reference_fail_0(self): - u = Unit('hours') - self.assertFalse(u.is_time_reference()) - - -class TestTitle(TestUnit): - # - # test: title - # - def test_title_pass_0(self): - u = Unit('meter') - self.assertEqual(u.title(10), '10 meter') - - def test_title_pass_1(self): - u = Unit('hours since epoch', calendar=unit.CALENDAR_STANDARD) - self.assertEqual(u.title(10), '1970-01-01 10:00:00') - - -class TestImmutable(TestUnit): - def _set_attr(self, unit, name): - setattr(unit, name, -999) - raise ValueError("'Unit' attribute '%s' is mutable!" % name) - - def test_immutable(self): - u = Unit('m') - for name in dir(u): - self.assertRaises(AttributeError, self._set_attr, u, name) - - def test_hash(self): - u1 = Unit('m') - u2 = Unit('meter') - u3 = copy.deepcopy(u1) - h = set() - for u in (u1, u2, u3): - h.add(hash(u)) - self.assertEqual(len(h), 1) - - v1 = Unit('V') - v2 = Unit('volt') - for u in (v1, v2): - h.add(hash(u)) - self.assertEqual(len(h), 2) - - -class TestInPlace(TestUnit): - - def test1(self): - # Check conversions do not change original object - c = unit.Unit('deg_c') - f = unit.Unit('deg_f') - - orig = np.arange(3, dtype=np.float32) - converted = c.convert(orig, f) - - with self.assertRaises(AssertionError): - np.testing.assert_array_equal(orig, converted) - - -if __name__ == '__main__': - tests.main() diff --git a/lib/iris/tests/test_uri_callback.py b/lib/iris/tests/test_uri_callback.py index 6bbd8e5aed..b344e883ea 100644 --- a/lib/iris/tests/test_uri_callback.py +++ b/lib/iris/tests/test_uri_callback.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -15,6 +15,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests @@ -24,19 +26,21 @@ import iris.coords -@iris.tests.skip_data +@tests.skip_data class TestCallbacks(tests.IrisTest): + @tests.skip_grib def test_grib_callback(self): def grib_thing_getter(cube, field, filename): - cube.add_aux_coord(iris.coords.AuxCoord(field.extra_keys['_periodStartDateTime'], long_name='random element', units='no_unit')) + if hasattr(field, 'sections'): + # New-style loader callback : 'field' is a GribMessage, which has 'sections'. + cube.add_aux_coord(iris.coords.AuxCoord(field.sections[1]['year'], long_name='extra_year_number_coord', units='no_unit')) + else: + # Old-style loader provides 'GribWrapper' type field. + cube.add_aux_coord(iris.coords.AuxCoord(field.extra_keys['_periodStartDateTime'], long_name='random element', units='no_unit')) - iris.fileformats.grib.hindcast_workaround = True fname = tests.get_data_path(('GRIB', 'global_t', 'global.grib2')) cube = iris.load_cube(fname, callback=grib_thing_getter) - try: - self.assertCML(cube, ['uri_callback', 'grib_global.cml']) - finally: - iris.fileformats.grib.hindcast_workaround = False + self.assertCML(cube, ['uri_callback', 'grib_global.cml']) def test_pp_callback(self): def pp_callback(cube, field, filename): diff --git a/lib/iris/tests/test_util.py b/lib/iris/tests/test_util.py index d88f9d02f9..d8cfcf648c 100644 --- a/lib/iris/tests/test_util.py +++ b/lib/iris/tests/test_util.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -18,15 +18,18 @@ Test iris.util """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + # import iris tests first so that some things can be initialised before # importing anything else import iris.tests as tests import inspect -import os -import StringIO -import unittest +import cf_units import numpy as np import iris.analysis @@ -35,7 +38,7 @@ import iris.util -class TestMonotonic(unittest.TestCase): +class TestMonotonic(tests.IrisTest): def assertMonotonic(self, array, direction=None, **kwargs): if direction is not None: mono, dir = iris.util.monotonic(array, return_direction=True, **kwargs) @@ -76,7 +79,7 @@ def test_monotonic_strict(self): b = np.array([3, 5.3, 5.3]) self.assertNotMonotonic(b, strict=True) self.assertMonotonic(b, direction=1) - + b = b[::-1] self.assertNotMonotonic(b, strict=True) self.assertMonotonic(b, direction=-1) @@ -90,32 +93,7 @@ def test_monotonic_strict(self): self.assertMonotonic(b) -class TestReverse(unittest.TestCase): - def test_simple(self): - a = np.arange(12).reshape(3, 4) - np.testing.assert_array_equal(a[::-1], iris.util.reverse(a, 0)) - np.testing.assert_array_equal(a[::-1, ::-1], iris.util.reverse(a, [0, 1])) - np.testing.assert_array_equal(a[:, ::-1], iris.util.reverse(a, 1)) - np.testing.assert_array_equal(a[:, ::-1], iris.util.reverse(a, [1])) - self.assertRaises(ValueError, iris.util.reverse, a, []) - self.assertRaises(ValueError, iris.util.reverse, a, -1) - self.assertRaises(ValueError, iris.util.reverse, a, 10) - self.assertRaises(ValueError, iris.util.reverse, a, [-1]) - self.assertRaises(ValueError, iris.util.reverse, a, [0, -1]) - - def test_single(self): - a = np.arange(36).reshape(3, 4, 3) - np.testing.assert_array_equal(a[::-1], iris.util.reverse(a, 0)) - np.testing.assert_array_equal(a[::-1, ::-1], iris.util.reverse(a, [0, 1])) - np.testing.assert_array_equal(a[:, ::-1, ::-1], iris.util.reverse(a, [1, 2])) - np.testing.assert_array_equal(a[..., ::-1], iris.util.reverse(a, 2)) - self.assertRaises(ValueError, iris.util.reverse, a, -1) - self.assertRaises(ValueError, iris.util.reverse, a, 10) - self.assertRaises(ValueError, iris.util.reverse, a, [-1]) - self.assertRaises(ValueError, iris.util.reverse, a, [0, -1]) - - -class TestClipString(unittest.TestCase): +class TestClipString(tests.IrisTest): def setUp(self): self.test_string = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." self.rider = "**^^**$$..--__" # A good chance at being unique and not in the string to be tested! @@ -158,7 +136,8 @@ def test_default_values(self): self.assertLess(len(result), len(self.test_string), "String was not clipped.") rider_returned = result[-len(arg_dict["rider"]):] - self.assertEquals(rider_returned, arg_dict["rider"], "Default rider was not applied.") + self.assertEqual(rider_returned, arg_dict['rider'], + 'Default rider was not applied.') def test_trim_string_with_no_spaces(self): @@ -172,66 +151,70 @@ def test_trim_string_with_no_spaces(self): expected_length = clip_length + len(self.rider) # Check the length of the returned string is equal to clip length + length of rider - self.assertEquals(len(result), expected_length, "Mismatch in expected length of clipped string. Length was %s, expected value is %s" % (len(result), expected_length)) - + self.assertEqual( + len(result), + expected_length, + 'Mismatch in expected length of clipped string. Length was %s, ' + 'expected value is %s' % (len(result), expected_length)) + +@tests.skip_data class TestDescribeDiff(iris.tests.IrisTest): def test_identical(self): test_cube_a = stock.realistic_4d() test_cube_b = stock.realistic_4d() - return_str_IO = StringIO.StringIO() - iris.util.describe_diff(test_cube_a, test_cube_b, output_file=return_str_IO) - return_str = return_str_IO.getvalue() + return_sio = six.StringIO() + iris.util.describe_diff(test_cube_a, test_cube_b, output_file=return_sio) + return_str = return_sio.getvalue() self.assertString(return_str, 'compatible_cubes.str.txt') def test_different(self): - return_str_IO = StringIO.StringIO() - # test incompatible attributes test_cube_a = stock.realistic_4d() test_cube_b = stock.realistic_4d() - + test_cube_a.attributes['Conventions'] = 'CF-1.5' test_cube_b.attributes['Conventions'] = 'CF-1.6' - - iris.util.describe_diff(test_cube_a, test_cube_b, output_file=return_str_IO) - return_str = return_str_IO.getvalue() - + + return_sio = six.StringIO() + iris.util.describe_diff(test_cube_a, test_cube_b, output_file=return_sio) + return_str = return_sio.getvalue() + self.assertString(return_str, 'incompatible_attr.str.txt') - + # test incompatible names test_cube_a = stock.realistic_4d() test_cube_b = stock.realistic_4d() test_cube_a.standard_name = "relative_humidity" - return_str_IO.truncate(0) - iris.util.describe_diff(test_cube_a, test_cube_b, output_file=return_str_IO) - return_str = return_str_IO.getvalue() + return_sio = six.StringIO() + iris.util.describe_diff(test_cube_a, test_cube_b, output_file=return_sio) + return_str = return_sio.getvalue() self.assertString(return_str, 'incompatible_name.str.txt') # test incompatible unit test_cube_a = stock.realistic_4d() test_cube_b = stock.realistic_4d() - - test_cube_a.units = iris.unit.Unit('m') - return_str_IO.truncate(0) - iris.util.describe_diff(test_cube_a, test_cube_b, output_file=return_str_IO) - return_str = return_str_IO.getvalue() - + test_cube_a.units = cf_units.Unit('m') + + return_sio = six.StringIO() + iris.util.describe_diff(test_cube_a, test_cube_b, output_file=return_sio) + return_str = return_sio.getvalue() + self.assertString(return_str, 'incompatible_unit.str.txt') - + # test incompatible methods test_cube_a = stock.realistic_4d() test_cube_b = stock.realistic_4d().collapsed('model_level_number', iris.analysis.MEAN) - return_str_IO.truncate(0) - iris.util.describe_diff(test_cube_a, test_cube_b, output_file=return_str_IO) - return_str = return_str_IO.getvalue() + return_sio = six.StringIO() + iris.util.describe_diff(test_cube_a, test_cube_b, output_file=return_sio) + return_str = return_sio.getvalue() self.assertString(return_str, 'incompatible_meth.str.txt') @@ -243,7 +226,7 @@ def test_output_file(self): test_cube_a.attributes['Conventions'] = 'CF-1.5' test_cube_b.attributes['Conventions'] = 'CF-1.6' test_cube_a.standard_name = "relative_humidity" - test_cube_a.units = iris.unit.Unit('m') + test_cube_a.units = cf_units.Unit('m') with self.temp_filename() as filename: with open(filename, 'w') as f: @@ -254,6 +237,7 @@ def test_output_file(self): 'incompatible_cubes.str.txt') +@tests.skip_data class TestAsCompatibleShape(tests.IrisTest): def test_slice(self): cube = tests.stock.realistic_4d() @@ -287,8 +271,7 @@ def test_collapsed(self): res = iris.util.as_compatible_shape(collapsed, cube) self.assertCML(res, ('util', 'as_compatible_shape_collapsed.cml'), checksum=False) - self.assertArrayEqual(expected_data, res.data) - self.assertArrayEqual(expected_data.mask, res.data.mask) + self.assertMaskedArrayEqual(expected_data, res.data) def test_reduce_dimensionality(self): # Test that as_compatible_shape() can demote @@ -327,6 +310,25 @@ def dim_to_aux(cube, coord_name): res = iris.util.as_compatible_shape(src, cube) self.assertEqual(res, expected) + def test_2d_auxcoord_transpose(self): + dim_coord1 = iris.coords.DimCoord(range(3), long_name='first_dim') + dim_coord2 = iris.coords.DimCoord(range(4), long_name='second_dim') + aux_coord_2d = iris.coords.AuxCoord(np.arange(12).reshape(3, 4), + long_name='spanning') + aux_coord_2d_T = iris.coords.AuxCoord(np.arange(12).reshape(3, 4).T, + long_name='spanning') + src = iris.cube.Cube( + np.ones((3, 4)), + dim_coords_and_dims=[(dim_coord1, 0), (dim_coord2, 1)], + aux_coords_and_dims=[(aux_coord_2d, (0, 1))]) + target = iris.cube.Cube( + np.ones((4, 3)), + dim_coords_and_dims=[(dim_coord1, 1), (dim_coord2, 0)], + aux_coords_and_dims=[(aux_coord_2d_T, (0, 1))]) + + res = iris.util.as_compatible_shape(src, target) + self.assertEqual(res[0], target[0]) + if __name__ == '__main__': - unittest.main() + tests.main() diff --git a/lib/iris/tests/test_verbose_logging.py b/lib/iris/tests/test_verbose_logging.py deleted file mode 100644 index 4bc9d12fd4..0000000000 --- a/lib/iris/tests/test_verbose_logging.py +++ /dev/null @@ -1,55 +0,0 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . - - -# import iris tests first so that some things can be initialised before importing anything else -import iris.tests as tests - -import os - -import iris -import iris.fileformats.pp -import iris.config as config -import iris.fileformats.rules as rules - - -@iris.tests.skip_data -class TestVerboseLogging(tests.IrisTest): - def test_verbose_logging(self): - # check that verbose logging no longer breaks in pp.save() - # load some data, enable logging, and save a cube to PP. - data_path = tests.get_data_path(('PP', 'simple_pp', 'global.pp')) - cube = iris.load_cube(data_path) - OLD_RULE_LOG_DIR = config.RULE_LOG_DIR - config.RULE_LOG_DIR = '/var/tmp' - old_log = rules.log - rules.log = rules._prepare_rule_logger(verbose=True) - - temp_filename1 = iris.util.create_temp_filename(suffix='.pp') - - # Test writing to a file handle to test that the logger uses the handle name - with open(temp_filename1, "wb") as mysavefile: - try: - iris.save(cube, mysavefile) - finally: - # Restore old logging config - config.RULE_LOG_DIR = OLD_RULE_LOG_DIR - rules.log = old_log - os.unlink(temp_filename1) - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/test_whatsnew_contributions.py b/lib/iris/tests/test_whatsnew_contributions.py new file mode 100644 index 0000000000..be917e60d8 --- /dev/null +++ b/lib/iris/tests/test_whatsnew_contributions.py @@ -0,0 +1,71 @@ +# (C) British Crown Copyright 2010 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Check the the latest "whatsnew" contributions files have usable names. + +The files in "./docs...whatsnew/contributions_/" should have filenames +with a particular structure, which encodes a summary name. +These names are interpreted by "./docs...whatsnew/aggregate_directory.py". +This test just ensures that all those files have names which that process +can accept. + +.. note: + This only works within a developer installation: In a 'normal' install the + location of the docs sources is not known. + In a Travis installation, this test silently passes and the .travis.yml + invokes the checking command directly. + +""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first. +import iris.tests as tests + +import os +import os.path +import subprocess +import sys + +import iris + + +class TestWhatsnewContribs(tests.IrisTest): + def test_check_contributions(self): + # Get dirpath of overall iris installation. + # Note: assume iris at "/lib/iris". + iris_module_dirpath = os.path.dirname(iris.__file__) + iris_dirs = iris_module_dirpath.split(os.sep) + install_dirpath = os.sep.join(iris_dirs[:-2]) + + # Construct path to docs 'whatsnew' directory. + # Note: assume docs at "/docs". + whatsnew_dirpath = os.path.join( + install_dirpath, 'docs', 'iris', 'src', 'whatsnew') + + # Quietly ignore if the directory does not exist: It is only there in + # in a developer installation, not a normal install. + # Travis bypasses this problem by running the test directly. + if os.path.exists(whatsnew_dirpath): + # Run a 'check contributions' command in that directory. + cmd = [sys.executable, 'aggregate_directory.py', '--checkonly', + '--quiet'] + subprocess.check_call(cmd, cwd=whatsnew_dirpath) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/__init__.py b/lib/iris/tests/unit/__init__.py index c9ee5609da..7d2010e304 100644 --- a/lib/iris/tests/unit/__init__.py +++ b/lib/iris/tests/unit/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Unit tests for the :mod:`iris` package.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/analysis/__init__.py b/lib/iris/tests/unit/analysis/__init__.py index dc657d90f7..42187387c2 100644 --- a/lib/iris/tests/unit/analysis/__init__.py +++ b/lib/iris/tests/unit/analysis/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,42 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Unit tests for the :mod:`iris.analysis` package.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.analysis import Linear +from iris.tests import mock + + +class Test_Linear(tests.IrisTest): + def setUp(self): + self.extrap = 'some extrapolation' + + def test___init__(self): + linear = Linear(extrapolation_mode=self.extrap) + self.assertEqual(getattr(linear, 'extrapolation_mode', None), + self.extrap) + + @mock.patch('iris.analysis.LinearInterpolator', name='LinearInterpolator') + def test_interpolator(self, linear_interp_patch): + mock_interpolator = mock.Mock(name='mocked linear interpolator') + linear_interp_patch.return_value = mock_interpolator + + linear = Linear(self.extrap) + cube = mock.Mock(name='cube') + coords = mock.Mock(name='coords') + + interpolator = linear.interpolator(cube, coords) + + self.assertIs(interpolator, mock_interpolator) + linear_interp_patch.assert_called_once_with( + cube, coords, extrapolation_mode=self.extrap) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/area_weighted/__init__.py b/lib/iris/tests/unit/analysis/area_weighted/__init__.py new file mode 100644 index 0000000000..6e266c3a96 --- /dev/null +++ b/lib/iris/tests/unit/analysis/area_weighted/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.analysis._area_weighted` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/analysis/area_weighted/test_AreaWeightedRegridder.py b/lib/iris/tests/unit/analysis/area_weighted/test_AreaWeightedRegridder.py new file mode 100644 index 0000000000..3c28ca6134 --- /dev/null +++ b/lib/iris/tests/unit/analysis/area_weighted/test_AreaWeightedRegridder.py @@ -0,0 +1,116 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for :class:`iris.analysis._area_weighted.AreaWeightedRegridder`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.analysis._area_weighted import AreaWeightedRegridder +from iris.coord_systems import GeogCS +from iris.coords import DimCoord +from iris.cube import Cube +from iris.tests import mock + + +class Test(tests.IrisTest): + def cube(self, x, y): + data = np.arange(len(x) * len(y)).reshape(len(y), len(x)) + cube = Cube(data) + lat = DimCoord(y, 'latitude', units='degrees') + lon = DimCoord(x, 'longitude', units='degrees') + cube.add_dim_coord(lat, 0) + cube.add_dim_coord(lon, 1) + return cube + + def grids(self): + src = self.cube(np.linspace(20, 30, 3), np.linspace(10, 25, 4)) + target = self.cube(np.linspace(6, 18, 8), np.linspace(11, 22, 9)) + return src, target + + def extract_grid(self, cube): + return cube.coord('latitude'), cube.coord('longitude') + + def check_mdtol(self, mdtol=None): + src_grid, target_grid = self.grids() + if mdtol is None: + regridder = AreaWeightedRegridder(src_grid, target_grid) + mdtol = 1 + else: + regridder = AreaWeightedRegridder(src_grid, target_grid, + mdtol=mdtol) + + # Make a new cube to regrid with different data so we can + # distinguish between regridding the original src grid + # definition cube and the cube passed to the regridder. + src = src_grid.copy() + src.data += 10 + + with mock.patch('iris.experimental.regrid.' + 'regrid_area_weighted_rectilinear_src_and_grid', + return_value=mock.sentinel.result) as regrid: + result = regridder(src) + + self.assertEqual(regrid.call_count, 1) + _, args, kwargs = regrid.mock_calls[0] + + self.assertEqual(args[0], src) + self.assertEqual(self.extract_grid(args[1]), + self.extract_grid(target_grid)) + self.assertEqual(kwargs, {'mdtol': mdtol}) + self.assertIs(result, mock.sentinel.result) + + def test_default(self): + self.check_mdtol() + + def test_specified_mdtol(self): + self.check_mdtol(0.5) + + def test_invalid_high_mdtol(self): + src, target = self.grids() + msg = 'mdtol must be in range 0 - 1' + with self.assertRaisesRegexp(ValueError, msg): + AreaWeightedRegridder(src, target, mdtol=1.2) + + def test_invalid_low_mdtol(self): + src, target = self.grids() + msg = 'mdtol must be in range 0 - 1' + with self.assertRaisesRegexp(ValueError, msg): + AreaWeightedRegridder(src, target, mdtol=-0.2) + + def test_mismatched_src_coord_systems(self): + src = Cube(np.zeros((3, 4))) + cs = GeogCS(6543210) + lat = DimCoord(np.arange(3), 'latitude', coord_system=cs) + lon = DimCoord(np.arange(4), 'longitude') + src.add_dim_coord(lat, 0) + src.add_dim_coord(lon, 1) + target = mock.Mock() + with self.assertRaises(ValueError): + AreaWeightedRegridder(src, target) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/analysis/cartography/__init__.py b/lib/iris/tests/unit/analysis/cartography/__init__.py index 9051563d3f..ce4cc8fbf8 100644 --- a/lib/iris/tests/unit/analysis/cartography/__init__.py +++ b/lib/iris/tests/unit/analysis/cartography/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2014, Met Office +# (C) British Crown Copyright 2014 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Unit tests for the :mod:`iris.analysis.cartography` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/analysis/cartography/test__quadrant_area.py b/lib/iris/tests/unit/analysis/cartography/test__quadrant_area.py new file mode 100644 index 0000000000..d47242c2c4 --- /dev/null +++ b/lib/iris/tests/unit/analysis/cartography/test__quadrant_area.py @@ -0,0 +1,134 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +"""Unit tests for the `iris.analysis.cartography._quadrant_area` function""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. + +import iris.tests as tests + +import cf_units +import numpy as np + +import iris +from iris.analysis.cartography import _quadrant_area +from iris.analysis.cartography import DEFAULT_SPHERICAL_EARTH_RADIUS + + +class TestExampleCases(tests.IrisTest): + + def _radian_bounds(self, coord_list, dtype): + bound_deg = np.array(coord_list, dtype=dtype) + bound_deg = np.atleast_2d(bound_deg) + degrees = cf_units.Unit("degrees") + radians = cf_units.Unit("radians") + return degrees.convert(bound_deg, radians) + + def _as_bounded_coords(self, lats, lons, dtype=np.float64): + return (self._radian_bounds(lats, dtype=dtype), + self._radian_bounds(lons, dtype=dtype)) + + def test_area_in_north(self): + lats, lons = self._as_bounded_coords([0, 10], [0, 10]) + area = _quadrant_area(lats, lons, DEFAULT_SPHERICAL_EARTH_RADIUS) + self.assertArrayAllClose(area, [[1228800593851.443115234375]]) + + def test_area_in_far_north(self): + lats, lons = self._as_bounded_coords([70, 80], [0, 10]) + area = _quadrant_area(lats, lons, DEFAULT_SPHERICAL_EARTH_RADIUS) + self.assertArrayAllClose(area, [[319251845980.7646484375]]) + + def test_area_in_far_south(self): + lats, lons = self._as_bounded_coords([-80, -70], [0, 10]) + area = _quadrant_area(lats, lons, DEFAULT_SPHERICAL_EARTH_RADIUS) + self.assertArrayAllClose(area, [[319251845980.763671875]]) + + def test_area_in_north_with_reversed_lats(self): + lats, lons = self._as_bounded_coords([10, 0], [0, 10]) + area = _quadrant_area(lats, lons, DEFAULT_SPHERICAL_EARTH_RADIUS) + self.assertArrayAllClose(area, [[1228800593851.443115234375]]) + + def test_area_multiple_lats(self): + lats, lons = self._as_bounded_coords([[-80, -70], [0, 10], [70, 80]], + [0, 10]) + area = _quadrant_area(lats, lons, DEFAULT_SPHERICAL_EARTH_RADIUS) + + self.assertArrayAllClose(area, [[319251845980.763671875], + [1228800593851.443115234375], + [319251845980.7646484375]]) + + def test_area_multiple_lats_and_lons(self): + lats, lons = self._as_bounded_coords([[-80, -70], [0, 10], [70, 80]], + [[0, 10], [10, 30]]) + area = _quadrant_area(lats, lons, DEFAULT_SPHERICAL_EARTH_RADIUS) + + self.assertArrayAllClose(area, [[3.19251846e+11, 6.38503692e+11], + [1.22880059e+12, 2.45760119e+12], + [3.19251846e+11, 6.38503692e+11]]) + + def test_symmetric_64_bit(self): + lats, lons = self._as_bounded_coords([[-90, -89.375], + [89.375, 90]], + [0, 10], + dtype=np.float64) + area = _quadrant_area(lats, lons, DEFAULT_SPHERICAL_EARTH_RADIUS) + self.assertArrayAllClose(area, area[::-1]) + + def test_symmetric_32_bit(self): + lats, lons = self._as_bounded_coords([[-90, -89.375], + [89.375, 90]], + [0, 10], + dtype=np.float32) + area = _quadrant_area(lats, lons, DEFAULT_SPHERICAL_EARTH_RADIUS) + self.assertArrayAllClose(area, area[::-1]) + + +class TestErrorHandling(tests.IrisTest): + + def test_lat_bounds_1d_error(self): + self._assert_error_on_malformed_bounds( + [0, 10], + [[0, 10]]) + + def test_lon_bounds_1d_error(self): + self._assert_error_on_malformed_bounds( + [[0, 10]], + [0, 10]) + + def test_too_many_lat_bounds_error(self): + self._assert_error_on_malformed_bounds( + [[0, 10, 20]], + [[0, 10]]) + + def test_too_many_lon_bounds_error(self): + self._assert_error_on_malformed_bounds( + [[0, 10]], + [[0, 10, 20]]) + + def _assert_error_on_malformed_bounds(self, lat_bnds, lon_bnds): + with self.assertRaisesRegexp(ValueError, + 'Bounds must be \[n,2\] array'): + _quadrant_area(np.array(lat_bnds), + np.array(lon_bnds), + 1.) + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/analysis/cartography/test__xy_range.py b/lib/iris/tests/unit/analysis/cartography/test__xy_range.py new file mode 100644 index 0000000000..ccc4d62991 --- /dev/null +++ b/lib/iris/tests/unit/analysis/cartography/test__xy_range.py @@ -0,0 +1,68 @@ +# (C) British Crown Copyright 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +"""Unit tests for :func:`iris.analysis.cartography._xy_range`""" + +# Import iris.tests first so that some things can be initialised before +# importing anything else. + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import iris.tests as tests +import iris.tests.stock as stock +import numpy as np +from iris.analysis.cartography import _xy_range + + +class Test(tests.IrisTest): + def test_bounds_mismatch(self): + cube = stock.realistic_3d() + cube.coord('grid_longitude').guess_bounds() + + with self.assertRaisesRegexp(ValueError, 'bounds'): + result_non_circ = _xy_range(cube) + + def test_non_circular(self): + cube = stock.realistic_3d() + assert not cube.coord('grid_longitude').circular + + result_non_circ = _xy_range(cube) + self.assertEqual(result_non_circ, ((-5.0, 5.0), (-4.0, 4.0))) + + @tests.skip_data + def test_geog_cs_circular(self): + cube = stock.global_pp() + assert cube.coord('longitude').circular + + result = _xy_range(cube) + np.testing.assert_array_almost_equal( + result, ((0, 360), (-90, 90)), decimal=0) + + @tests.skip_data + def test_geog_cs_regional(self): + cube = stock.global_pp() + cube = cube[10:20, 20:30] + assert not cube.coord('longitude').circular + + result = _xy_range(cube) + np.testing.assert_array_almost_equal( + result, ((75, 108.75), (42.5, 65)), decimal=0) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/analysis/cartography/test_area_weights.py b/lib/iris/tests/unit/analysis/cartography/test_area_weights.py new file mode 100644 index 0000000000..7b1f829eb1 --- /dev/null +++ b/lib/iris/tests/unit/analysis/cartography/test_area_weights.py @@ -0,0 +1,50 @@ +# (C) British Crown Copyright 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +"""Unit tests for the `iris.analysis.cartography.area_weights` function""" + +# Import iris.tests first so that some things can be initialised before +# importing anything else. + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import iris.tests as tests +import iris.tests.stock as stock +import iris.analysis.cartography + + +class TestInvalidUnits(tests.IrisTest): + def test_latitude_no_units(self): + cube = stock.lat_lon_cube() + cube.coord('longitude').guess_bounds() + cube.coord('latitude').guess_bounds() + cube.coord('latitude').units = None + with self.assertRaisesRegexp(ValueError, 'Units of degrees or ' + 'radians required'): + iris.analysis.cartography.area_weights(cube) + + def test_longitude_no_units(self): + cube = stock.lat_lon_cube() + cube.coord('latitude').guess_bounds() + cube.coord('longitude').guess_bounds() + cube.coord('longitude').units = None + with self.assertRaisesRegexp(ValueError, 'Units of degrees or ' + 'radians required'): + iris.analysis.cartography.area_weights(cube) + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/cartography/test_gridcell_angles.py b/lib/iris/tests/unit/analysis/cartography/test_gridcell_angles.py new file mode 100644 index 0000000000..4a1344e83d --- /dev/null +++ b/lib/iris/tests/unit/analysis/cartography/test_gridcell_angles.py @@ -0,0 +1,327 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the function +:func:`iris.analysis.cartography.gridcell_angles`. + +""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from cf_units import Unit +from iris.cube import Cube +from iris.coords import AuxCoord + +from iris.analysis.cartography import gridcell_angles +from iris.tests.stock import sample_2d_latlons, lat_lon_cube + + +def _2d_multicells_testcube(cellsize_degrees=1.0): + """ + Create a test cube with a grid of X and Y points, where each gridcell + is independent (disjoint), arranged at an angle == the x-coord point. + + """ + # Setup np.linspace arguments to make the coordinate points. + x0, x1, nx = -164, 164, 9 + y0, y1, ny = -75, 75, 7 + + lats = np.linspace(y0, y1, ny, endpoint=True) + lons_angles = np.linspace(x0, x1, nx, endpoint=True) + x_pts_2d, y_pts_2d = np.meshgrid(lons_angles, lats) + + # Make gridcells rectangles surrounding these centrepoints, but also + # tilted at various angles (= same as x-point lons, as that's easy). + + # Calculate centrepoint lons+lats : in radians, and shape (ny, nx, 1). + xangs, yangs = np.deg2rad(x_pts_2d), np.deg2rad(y_pts_2d) + xangs, yangs = [arr[..., None] for arr in (xangs, yangs)] + # Program which corners are up+down on each gridcell axis. + dx_corners = [[[-1, 1, 1, -1]]] + dy_corners = [[[-1, -1, 1, 1]]] + # Calculate the relative offsets in x+y at the 4 corners. + x_ofs_2d = cellsize_degrees * np.cos(xangs) * dx_corners + x_ofs_2d -= cellsize_degrees * np.sin(xangs) * dy_corners + y_ofs_2d = cellsize_degrees * np.cos(xangs) * dy_corners + y_ofs_2d += cellsize_degrees * np.sin(xangs) * dx_corners + # Apply a latitude stretch to make correct angles on the globe. + y_ofs_2d *= np.cos(yangs) + # Make bounds arrays by adding the corner offsets to the centrepoints. + x_bds_2d = x_pts_2d[..., None] + x_ofs_2d + y_bds_2d = y_pts_2d[..., None] + y_ofs_2d + + # Create a cube with these points + bounds in its 'X' and 'Y' coords. + co_x = AuxCoord(points=x_pts_2d, bounds=x_bds_2d, + standard_name='longitude', units='degrees') + co_y = AuxCoord(points=y_pts_2d, bounds=y_bds_2d, + standard_name='latitude', units='degrees') + cube = Cube(np.zeros((ny, nx))) + cube.add_aux_coord(co_x, (0, 1)) + cube.add_aux_coord(co_y, (0, 1)) + return cube + + +class TestGridcellAngles(tests.IrisTest): + def setUp(self): + # Make a small "normal" contiguous-bounded cube to test on. + # This one is regional. + self.standard_regional_cube = sample_2d_latlons( + regional=True, transformed=True) + # Record the standard correct angle answers. + result_cube = gridcell_angles(self.standard_regional_cube) + result_cube.convert_units('degrees') + self.standard_result_cube = result_cube + self.standard_small_cube_results = result_cube.data + + def _check_multiple_orientations_and_latitudes(self, + method='mid-lhs, mid-rhs', + atol_degrees=0.005, + cellsize_degrees=1.0): + + cube = _2d_multicells_testcube(cellsize_degrees=cellsize_degrees) + + # Calculate gridcell angles at each point. + angles_cube = gridcell_angles(cube, cell_angle_boundpoints=method) + + # Check that the results are a close match to the original intended + # gridcell orientation angles. + # NOTE: neither the above gridcell construction nor the calculation + # itself are exact : Errors scale as the square of gridcell sizes. + angles_cube.convert_units('degrees') + angles_calculated = angles_cube.data + + # Note: the gridcell angles **should** just match the longitudes at + # each point + angles_expected = cube.coord('longitude').points + + # Wrap both into standard range for comparison. + angles_calculated = (angles_calculated + 360.) % 360. + angles_expected = (angles_expected + 360.) % 360. + + # Assert (toleranced) equality, and return results. + self.assertArrayAllClose(angles_calculated, angles_expected, + atol=atol_degrees) + + return angles_calculated, angles_expected + + def test_various_orientations_and_locations(self): + self._check_multiple_orientations_and_latitudes() + + def test_result_form(self): + # Check properties of the result cube *other than* the data values. + test_cube = self.standard_regional_cube + result_cube = self.standard_result_cube + self.assertEqual(result_cube.long_name, + 'gridcell_angle_from_true_east') + self.assertEqual(result_cube.units, Unit('degrees')) + self.assertEqual(len(result_cube.coords()), 2) + self.assertEqual(result_cube.coord(axis='x'), + test_cube.coord(axis='x')) + self.assertEqual(result_cube.coord(axis='y'), + test_cube.coord(axis='y')) + + def test_bottom_edge_method(self): + # Get results with the "other" calculation method + check to tolerance. + # A smallish cellsize should yield similar results in both cases. + r1, _ = self._check_multiple_orientations_and_latitudes() + r2, _ = self._check_multiple_orientations_and_latitudes( + method='lower-left, lower-right', + cellsize_degrees=0.1, atol_degrees=0.1) + + # Not *exactly* the same : this checks we tested the 'other' method ! + self.assertFalse(np.allclose(r1, r2)) + # Note: results are a bit different in places. This is acceptable. + self.assertArrayAllClose(r1, r2, atol=0.1) + + def test_bounded_coord_args(self): + # Check that passing the coords gives the same result as the cube. + co_x, co_y = (self.standard_regional_cube.coord(axis=ax) + for ax in ('x', 'y')) + result = gridcell_angles(co_x, co_y) + self.assertArrayAllClose(result.data, + self.standard_small_cube_results) + + def test_coords_radians_args(self): + # Check it still works with coords converted to radians. + co_x, co_y = (self.standard_regional_cube.coord(axis=ax) + for ax in ('x', 'y')) + for coord in (co_x, co_y): + coord.convert_units('radians') + result = gridcell_angles(co_x, co_y) + self.assertArrayAllClose(result.data, + self.standard_small_cube_results) + + def test_bounds_array_args(self): + # Check we can calculate from bounds values alone. + co_x, co_y = (self.standard_regional_cube.coord(axis=ax) + for ax in ('x', 'y')) + # Results drawn from coord bounds should be nearly the same, + # but not exactly, because of the different 'midpoint' values. + result = gridcell_angles(co_x.bounds, co_y.bounds) + self.assertArrayAllClose(result.data, + self.standard_small_cube_results, atol=0.1) + + def test_unbounded_regional_coord_args(self): + # Remove the coord bounds to check points-based calculation. + co_x, co_y = (self.standard_regional_cube.coord(axis=ax) + for ax in ('x', 'y')) + for coord in (co_x, co_y): + coord.bounds = None + result = gridcell_angles(co_x, co_y) + # Note: in this case, we can expect the leftmost and rightmost columns + # to be rubbish, because the data is not global. + # But the rest should match okay. + self.assertArrayAllClose(result.data[:, 1:-1], + self.standard_small_cube_results[:, 1:-1]) + + def test_points_array_args(self): + # Check we can calculate from points arrays alone (no coords). + co_x, co_y = (self.standard_regional_cube.coord(axis=ax) + for ax in ('x', 'y')) + # As previous, the leftmost and rightmost columns are not good. + result = gridcell_angles(co_x.points, co_y.points) + self.assertArrayAllClose(result.data[:, 1:-1], + self.standard_small_cube_results[:, 1:-1]) + + def test_unbounded_global(self): + # For a contiguous global grid, a result based on points, i.e. with the + # bounds removed, should be a reasonable match for the 'ideal' one + # based on the bounds. + + # Make a global cube + calculate ideal bounds-based results. + global_cube = sample_2d_latlons(transformed=True) + result_cube = gridcell_angles(global_cube) + result_cube.convert_units('degrees') + global_cube_results = result_cube.data + + # Check a points-based calculation on the same basic grid. + co_x, co_y = (global_cube.coord(axis=ax) + for ax in ('x', 'y')) + for coord in (co_x, co_y): + coord.bounds = None + result = gridcell_angles(co_x, co_y) + # In this case, the match is actually rather poor (!). + self.assertArrayAllClose(result.data, + global_cube_results, + atol=7.5) + # Leaving off first + last columns again gives a decent result. + self.assertArrayAllClose(result.data[:, 1:-1], + global_cube_results[:, 1:-1]) + + # NOTE: although this looks just as bad as 'test_points_array_args', + # maximum errors there in the end columns are actually > 100 degrees ! + + def test_nonlatlon_coord_system(self): + # Check with points specified in an unexpected coord system. + cube = sample_2d_latlons(regional=True, rotated=True) + result = gridcell_angles(cube) + self.assertArrayAllClose(result.data, + self.standard_small_cube_results) + # Check that the result has transformed (true-latlon) coordinates. + self.assertEqual(len(result.coords()), 2) + x_coord = result.coord(axis='x') + y_coord = result.coord(axis='y') + self.assertEqual(x_coord.shape, cube.shape) + self.assertEqual(y_coord.shape, cube.shape) + self.assertIsNotNone(cube.coord_system) + self.assertIsNone(x_coord.coord_system) + self.assertIsNone(y_coord.coord_system) + + def test_fail_coords_bad_units(self): + # Check error with bad coords units. + co_x, co_y = (self.standard_regional_cube.coord(axis=ax) + for ax in ('x', 'y')) + co_y.units = 'm' + with self.assertRaisesRegexp(ValueError, 'must have angular units'): + gridcell_angles(co_x, co_y) + + def test_fail_nonarraylike(self): + # Check error with bad args. + co_x, co_y = 1, 2 + with self.assertRaisesRegexp(ValueError, + 'must have array shape property'): + gridcell_angles(co_x, co_y) + + def test_fail_non2d_coords(self): + # Check error with bad args. + cube = lat_lon_cube() + with self.assertRaisesRegexp(ValueError, + 'inputs must have 2-dimensional shape'): + gridcell_angles(cube) + + def test_fail_different_shapes(self): + # Check error with mismatched shapes. + co_x, co_y = (self.standard_regional_cube.coord(axis=ax) + for ax in ('x', 'y')) + co_y = co_y[1:] + with self.assertRaisesRegexp(ValueError, 'must have same shape'): + gridcell_angles(co_x, co_y) + + def test_fail_different_coord_system(self): + # Check error with mismatched coord systems. + cube = sample_2d_latlons(regional=True, rotated=True) + cube.coord(axis='x').coord_system = None + with self.assertRaisesRegexp(ValueError, + 'must have same coordinate system'): + gridcell_angles(cube) + + def test_fail_cube_dims(self): + # Check error with mismatched cube dims. + cube = self.standard_regional_cube + # Make 5x6 into 5x5. + cube = cube[:, :-1] + co_x = cube.coord(axis='x') + pts, bds = co_x.points, co_x.bounds + co_new_x = co_x.copy(points=pts.transpose((1, 0)), + bounds=bds.transpose((1, 0, 2))) + cube.remove_coord(co_x) + cube.add_aux_coord(co_new_x, (1, 0)) + with self.assertRaisesRegexp(ValueError, + 'must have the same cube dimensions'): + gridcell_angles(cube) + + def test_fail_coord_noncoord(self): + # Check that passing a coord + an array gives an error. + co_x, co_y = (self.standard_regional_cube.coord(axis=ax) + for ax in ('x', 'y')) + with self.assertRaisesRegexp(ValueError, + 'is a Coordinate, but .* is not'): + gridcell_angles(co_x, co_y.bounds) + + def test_fail_noncoord_coord(self): + # Check that passing an array + a coord gives an error. + co_x, co_y = (self.standard_regional_cube.coord(axis=ax) + for ax in ('x', 'y')) + with self.assertRaisesRegexp(ValueError, + 'is a Coordinate, but .* is not'): + gridcell_angles(co_x.points, co_y) + + def test_fail_bad_method(self): + with self.assertRaisesRegexp(ValueError, + 'unrecognised cell_angle_boundpoints'): + self._check_multiple_orientations_and_latitudes( + method='something_unknown') + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/cartography/test_project.py b/lib/iris/tests/unit/analysis/cartography/test_project.py index f77fcfb811..033396d13f 100644 --- a/lib/iris/tests/unit/analysis/cartography/test_project.py +++ b/lib/iris/tests/unit/analysis/cartography/test_project.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2014, Met Office +# (C) British Crown Copyright 2014 - 2017, Met Office # # This file is part of Iris. # @@ -14,31 +14,47 @@ # # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . -"""Unit tests for the :func:`iris.analysis.cartography.project` function.""" +"""Unit tests for :func:`iris.analysis.cartography.project`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import mock +import cartopy.crs as ccrs import numpy as np -import cartopy.crs as ccrs -import iris -from iris.coords import DimCoord +import iris.coord_systems +import iris.coords +import iris.cube +import iris.tests +import iris.tests.stock + from iris.analysis.cartography import project +ROBINSON = ccrs.Robinson() + + +def low_res_4d(): + cube = iris.tests.stock.realistic_4d_no_derived() + cube = cube[0:2, 0:3, ::10, ::10] + cube.remove_coord('surface_altitude') + return cube + + class TestAll(tests.IrisTest): def setUp(self): cs = iris.coord_systems.GeogCS(654321) self.cube = iris.cube.Cube(np.zeros(25).reshape(5, 5)) self.cube.add_dim_coord( - DimCoord(range(5), standard_name="latitude", units='degrees', - coord_system=cs), 0) + iris.coords.DimCoord(np.arange(5), standard_name="latitude", + units='degrees', coord_system=cs), 0) self.cube.add_dim_coord( - DimCoord(range(5), standard_name="longitude", units='degrees', - coord_system=cs), 1) + iris.coords.DimCoord(np.arange(5), standard_name="longitude", + units='degrees', coord_system=cs), 1) self.tcs = iris.coord_systems.GeogCS(600000) @@ -54,6 +70,91 @@ def test_is_iris_coord_system(self): self.assertIsNot(res.coord('projection_x_coordinate').coord_system, self.tcs) + @tests.skip_data + def test_bad_resolution_negative(self): + cube = low_res_4d() + with self.assertRaises(ValueError): + project(cube, ROBINSON, nx=-200, ny=200) + + @tests.skip_data + def test_bad_resolution_non_numeric(self): + cube = low_res_4d() + with self.assertRaises(ValueError): + project(cube, ROBINSON, nx=200, ny='abc') + + @tests.skip_data + def test_missing_lat(self): + cube = low_res_4d() + cube.remove_coord('grid_latitude') + with self.assertRaises(ValueError): + project(cube, ROBINSON) + + @tests.skip_data + def test_missing_lon(self): + cube = low_res_4d() + cube.remove_coord('grid_longitude') + with self.assertRaises(ValueError): + project(cube, ROBINSON) + + @tests.skip_data + def test_missing_latlon(self): + cube = low_res_4d() + cube.remove_coord('grid_longitude') + cube.remove_coord('grid_latitude') + with self.assertRaises(ValueError): + project(cube, ROBINSON) + + @tests.skip_data + def test_default_resolution(self): + cube = low_res_4d() + new_cube, extent = project(cube, ROBINSON) + self.assertEqual(new_cube.shape, cube.shape) + + @tests.skip_data + def test_explicit_resolution(self): + cube = low_res_4d() + nx, ny = 5, 4 + new_cube, extent = project(cube, ROBINSON, nx=nx, ny=ny) + self.assertEqual(new_cube.shape, cube.shape[:2] + (ny, nx)) + + @tests.skip_data + def test_explicit_resolution_single_point(self): + cube = low_res_4d() + nx, ny = 1, 1 + new_cube, extent = project(cube, ROBINSON, nx=nx, ny=ny) + self.assertEqual(new_cube.shape, cube.shape[:2] + (ny, nx)) + + @tests.skip_data + def test_mismatched_coord_systems(self): + cube = low_res_4d() + cube.coord('grid_longitude').coord_system = None + with self.assertRaises(ValueError): + project(cube, ROBINSON) + + @tests.skip_data + def test_extent(self): + cube = low_res_4d() + _, extent = project(cube, ROBINSON) + self.assertEqual(extent, [-17005833.33052523, 17005833.33052523, + -8625155.12857459, 8625155.12857459]) + + @tests.skip_data + def test_cube(self): + cube = low_res_4d() + new_cube, _ = project(cube, ROBINSON) + self.assertCMLApproxData(new_cube) + + @tests.skip_data + def test_no_coord_system(self): + cube = low_res_4d() + cube.coord('grid_longitude').coord_system = None + cube.coord('grid_latitude').coord_system = None + with iris.tests.mock.patch('warnings.warn') as warn: + _, _ = project(cube, ROBINSON) + warn.assert_called_once_with('Coordinate system of latitude and ' + 'longitude coordinates is not specified. ' + 'Assuming WGS84 Geodetic.') + -if __name__ == "__main__": +if __name__ == '__main__': tests.main() diff --git a/lib/iris/tests/unit/analysis/cartography/test_rotate_grid_vectors.py b/lib/iris/tests/unit/analysis/cartography/test_rotate_grid_vectors.py new file mode 100644 index 0000000000..90ec37e162 --- /dev/null +++ b/lib/iris/tests/unit/analysis/cartography/test_rotate_grid_vectors.py @@ -0,0 +1,148 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the function +:func:`iris.analysis.cartography.rotate_grid_vectors`. + +""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from mock import Mock, call as mock_call +import numpy as np + +from iris.cube import Cube +from iris.tests.stock import sample_2d_latlons + +from iris.analysis.cartography import rotate_grid_vectors + + +class TestRotateGridVectors(tests.IrisTest): + def _check_angles_calculation(self, angles_in_degrees=True, + nan_angles_mask=None): + # Check basic maths on a 2d latlon grid. + u_cube = sample_2d_latlons(regional=True, transformed=True) + u_cube.units = 'ms-1' + u_cube.rename('dx') + u_cube.data[...] = 0 + v_cube = u_cube.copy() + v_cube.name('dy') + + # Define 6 different vectors, repeated in each data row. + in_vu = np.array([(0, 1), (2, -1), (-1, -1), (-3, 1), (2, 0), (0, 0)]) + in_angs = np.rad2deg(np.arctan2(in_vu[..., 0], in_vu[..., 1])) + in_mags = np.sqrt(np.sum(in_vu * in_vu, axis=1)) + v_cube.data[...] = in_vu[..., 0] + u_cube.data[...] = in_vu[..., 1] + + # Define 5 different test rotation angles, one for each data row. + rotation_angles = np.array([0., -45., 135, -140., 90.]) + ang_cube_data = np.broadcast_to(rotation_angles[:, None], + u_cube.shape) + ang_cube = u_cube.copy() + if angles_in_degrees: + ang_cube.units = 'degrees' + else: + ang_cube.units = 'radians' + ang_cube_data = np.deg2rad(ang_cube_data) + ang_cube.data[:] = ang_cube_data + + if nan_angles_mask is not None: + ang_cube.data[nan_angles_mask] = np.nan + + # Rotate all vectors by all the given angles. + result = rotate_grid_vectors(u_cube, v_cube, ang_cube) + out_u, out_v = [cube.data for cube in result] + + # Check that vector magnitudes were unchanged. + out_mags = np.sqrt(out_u * out_u + out_v * out_v) + expect_mags = in_mags[None, :] + self.assertArrayAllClose(out_mags, expect_mags) + + # Check that vector angles are all as expected. + out_angs = np.rad2deg(np.arctan2(out_v, out_u)) + expect_angs = in_angs[None, :] + rotation_angles[:, None] + ang_diffs = out_angs - expect_angs + # Fix for null vectors, and +/-360 differences. + ang_diffs[np.abs(out_mags) < 0.001] = 0.0 + ang_diffs = ang_diffs % 360.0 + # Check that any differences are very small. + self.assertArrayAllClose(ang_diffs, 0.0) + + # Check that results are always masked arrays, masked at NaN angles. + self.assertTrue(np.ma.isMaskedArray(out_u)) + self.assertTrue(np.ma.isMaskedArray(out_v)) + if nan_angles_mask is not None: + self.assertArrayEqual(out_u.mask, nan_angles_mask) + self.assertArrayEqual(out_v.mask, nan_angles_mask) + + def test_angles_calculation(self): + self._check_angles_calculation() + + def test_angles_in_radians(self): + self._check_angles_calculation(angles_in_degrees=False) + + def test_angles_from_grid(self): + # Check it will gets angles from 'u_cube', and pass any kwargs on to + # the angles routine. + u_cube = sample_2d_latlons(regional=True, transformed=True) + u_cube = u_cube[:2, :3] + u_cube.units = 'ms-1' + u_cube.rename('dx') + u_cube.data[...] = 1.0 + v_cube = u_cube.copy() + v_cube.name('dy') + v_cube.data[...] = 0.0 + + # Setup a fake angles result from the inner call to 'gridcell_angles'. + angles_result_data = np.array([[0.0, 90.0, 180.0], + [-180.0, -90.0, 270.0]]) + angles_result_cube = Cube(angles_result_data, units='degrees') + angles_kwargs = {'this': 2} + angles_call_patch = self.patch( + 'iris.analysis._grid_angles.gridcell_angles', + Mock(return_value=angles_result_cube)) + + # Call the routine. + result = rotate_grid_vectors(u_cube, v_cube, + grid_angles_kwargs=angles_kwargs) + + self.assertEqual(angles_call_patch.call_args_list, + [mock_call(u_cube, this=2)]) + + out_u, out_v = [cube.data for cube in result] + # Records what results should be for the various n*90deg rotations. + expect_u = np.array([[1.0, 0.0, -1.0], + [-1.0, 0.0, 0.0]]) + expect_v = np.array([[0.0, 1.0, 0.0], + [0.0, -1.0, -1.0]]) + # Check results are as expected. + self.assertArrayAllClose(out_u, expect_u) + self.assertArrayAllClose(out_v, expect_v) + + def test_nan_vectors(self): + bad_angle_points = np.zeros((5, 6), dtype=bool) + bad_angle_points[2, 3] = True + self._check_angles_calculation(nan_angles_mask=bad_angle_points) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/cartography/test_rotate_winds.py b/lib/iris/tests/unit/analysis/cartography/test_rotate_winds.py new file mode 100644 index 0000000000..19ae497e48 --- /dev/null +++ b/lib/iris/tests/unit/analysis/cartography/test_rotate_winds.py @@ -0,0 +1,454 @@ +# (C) British Crown Copyright 2015 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the function +:func:`iris.analysis.cartography.rotate_winds`. + +""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np +import numpy.ma as ma + +import cartopy.crs as ccrs +from iris.analysis.cartography import rotate_winds, unrotate_pole +from iris.cube import Cube +from iris.coords import DimCoord, AuxCoord +import iris.coord_systems + + +def uv_cubes(x=None, y=None): + """Return u, v cubes with a grid in a rotated pole CRS.""" + cs = iris.coord_systems.RotatedGeogCS(grid_north_pole_latitude=37.5, + grid_north_pole_longitude=177.5) + if x is None: + x = np.linspace(311.9, 391.1, 6) + if y is None: + y = np.linspace(-23.6, 24.8, 5) + + x2d, y2d = np.meshgrid(x, y) + u = 10 * (2 * np.cos(2 * np.deg2rad(x2d) + 3 * np.deg2rad(y2d + 30)) ** 2) + v = 20 * np.cos(6 * np.deg2rad(x2d)) + lon = DimCoord(x, standard_name='grid_longitude', units='degrees', + coord_system=cs) + lat = DimCoord(y, standard_name='grid_latitude', units='degrees', + coord_system=cs) + u_cube = Cube(u, standard_name='x_wind', units='m/s') + v_cube = Cube(v, standard_name='y_wind', units='m/s') + for cube in (u_cube, v_cube): + cube.add_dim_coord(lat.copy(), 0) + cube.add_dim_coord(lon.copy(), 1) + return u_cube, v_cube + + +def uv_cubes_3d(ref_cube, n_realization=3): + """ + Return 3d u, v cubes with a grid in a rotated pole CRS taken from + the provided 2d cube, by adding a realization dimension + coordinate bound to teh zeroth dimension. + + """ + lat = ref_cube.coord('grid_latitude') + lon = ref_cube.coord('grid_longitude') + x2d, y2d = np.meshgrid(lon.points, lat.points) + u = 10 * (2 * np.cos(2 * np.deg2rad(x2d) + 3 * np.deg2rad(y2d + 30)) ** 2) + v = 20 * np.cos(6 * np.deg2rad(x2d)) + # Multiply slices by factor to give variation over 0th dim. + factor = np.arange(1, n_realization + 1).reshape(n_realization, 1, 1) + u = factor * u + v = factor * v + realization = DimCoord(np.arange(n_realization), 'realization') + u_cube = Cube(u, standard_name='x_wind', units='m/s') + v_cube = Cube(v, standard_name='y_wind', units='m/s') + for cube in (u_cube, v_cube): + cube.add_dim_coord(realization.copy(), 0) + cube.add_dim_coord(lat.copy(), 1) + cube.add_dim_coord(lon.copy(), 2) + return u_cube, v_cube + + +class TestPrerequisites(tests.IrisTest): + def test_different_coord_systems(self): + u, v = uv_cubes() + v.coord('grid_latitude').coord_system = iris.coord_systems.GeogCS(1) + with self.assertRaisesRegexp( + ValueError, 'Coordinates differ between u and v cubes'): + rotate_winds(u, v, iris.coord_systems.OSGB()) + + def test_different_xy_coord_systems(self): + u, v = uv_cubes() + u.coord('grid_latitude').coord_system = iris.coord_systems.GeogCS(1) + v.coord('grid_latitude').coord_system = iris.coord_systems.GeogCS(1) + with self.assertRaisesRegexp( + ValueError, + 'Coordinate systems of x and y coordinates differ'): + rotate_winds(u, v, iris.coord_systems.OSGB()) + + def test_different_shape(self): + x = np.linspace(311.9, 391.1, 6) + y = np.linspace(-23.6, 24.8, 5) + u, _ = uv_cubes(x, y) + _, v = uv_cubes(x[:-1], y) + with self.assertRaisesRegexp(ValueError, 'same shape'): + rotate_winds(u, v, iris.coord_systems.OSGB()) + + def test_xy_dimensionality(self): + u, v = uv_cubes() + # Replace 1d lat with 2d lat. + x = u.coord('grid_longitude').points + y = u.coord('grid_latitude').points + x2d, y2d = np.meshgrid(x, y) + lat_2d = AuxCoord(y2d, 'grid_latitude', units='degrees', + coord_system=u.coord('grid_latitude').coord_system) + for cube in (u, v): + cube.remove_coord('grid_latitude') + cube.add_aux_coord(lat_2d.copy(), (0, 1)) + + with self.assertRaisesRegexp( + ValueError, + 'x and y coordinates must have the same number of dimensions'): + rotate_winds(u, v, iris.coord_systems.OSGB()) + + def test_dim_mapping(self): + x = np.linspace(311.9, 391.1, 3) + y = np.linspace(-23.6, 24.8, 3) + u, v = uv_cubes(x, y) + v.transpose() + with self.assertRaisesRegexp(ValueError, 'Dimension mapping'): + rotate_winds(u, v, iris.coord_systems.OSGB()) + + +class TestAnalyticComparison(tests.IrisTest): + @staticmethod + def _unrotate_equation(rotated_lons, rotated_lats, + rotated_us, rotated_vs, pole_lon, pole_lat): + # Perform a rotated-pole 'unrotate winds' transformation on arrays of + # rotated-lat, rotated-lon, u and v. + # This can be defined as an analytic function : cf. UMDP015 + + # Work out the rotation angles. + lambda_angle = np.radians(pole_lon - 180.0) + phi_angle = np.radians(90.0 - pole_lat) + + # Get the locations in true lats+lons. + trueLongitude, trueLatitude = unrotate_pole(rotated_lons, + rotated_lats, + pole_lon, + pole_lat) + + # Calculate inter-coordinate rotation coefficients. + cos_rot = (np.cos(np.radians(rotated_lons)) * + np.cos(np.radians(trueLongitude) - lambda_angle) + + np.sin(np.radians(rotated_lons)) * + np.sin(np.radians(trueLongitude) - lambda_angle) * + np.cos(phi_angle)) + sin_rot = -((np.sin(np.radians(trueLongitude) - lambda_angle) * + np.sin(phi_angle)) / + np.cos(np.radians(rotated_lats))) + + # Matrix-multiply to rotate the vectors. + u_true = rotated_us * cos_rot - rotated_vs * sin_rot + v_true = rotated_vs * cos_rot + rotated_us * sin_rot + + return u_true, v_true + + def _check_rotated_to_true(self, u_rot, v_rot, target_cs, **kwds): + # Run test calculation (numeric). + u_true, v_true = rotate_winds(u_rot, v_rot, target_cs) + + # Perform same calculation via the reference method (equations). + cs_rot = u_rot.coord('grid_longitude').coord_system + pole_lat = cs_rot.grid_north_pole_latitude + pole_lon = cs_rot.grid_north_pole_longitude + rotated_lons = u_rot.coord('grid_longitude').points + rotated_lats = u_rot.coord('grid_latitude').points + rotated_lons_2d, rotated_lats_2d = np.meshgrid( + rotated_lons, rotated_lats) + rotated_u, rotated_v = u_rot.data, v_rot.data + u_ref, v_ref = self._unrotate_equation(rotated_lons_2d, + rotated_lats_2d, + rotated_u, rotated_v, + pole_lon, pole_lat) + + # Check that all the numerical results are within given tolerances. + self.assertArrayAllClose(u_true.data, u_ref, **kwds) + self.assertArrayAllClose(v_true.data, v_ref, **kwds) + + def test_rotated_to_true__small(self): + # Check for a small field with varying data. + target_cs = iris.coord_systems.GeogCS(6371229) + u_rot, v_rot = uv_cubes() + self._check_rotated_to_true(u_rot, v_rot, target_cs, + rtol=1e-5, atol=0.0005) + + def test_rotated_to_true_global(self): + # Check for global fields with various constant wind values + # - constant in the rotated pole system, that is. + # We expect less accuracy where this gets close to the true poles. + target_cs = iris.coord_systems.GeogCS(6371229) + u_rot, v_rot = uv_cubes(x=np.arange(0, 360.0, 15), + y=np.arange(-89, 89, 10)) + for vector in ((1, 0), (0, 1), (1, 1), (-3, -1.5)): + u_rot.data[...] = vector[0] + v_rot.data[...] = vector[1] + self._check_rotated_to_true(u_rot, v_rot, target_cs, + rtol=5e-4, atol=5e-4, + err_msg='vector={}'.format(vector)) + + +class TestRotatedToOSGB(tests.IrisTest): + # Define some coordinate ranges for the uv_cubes 'standard' RotatedPole + # system, that exceed the OSGB margins, but not by "too much". + _rp_x_min, _rp_x_max = -5.0, 5.0 + _rp_y_min, _rp_y_max = -5.0, 15.0 + + def _uv_cubes_limited_extent(self): + # Make test cubes suitable for transforming to OSGB, as the standard + # 'uv_cubes' result goes too far outside, leading to errors. + x = np.linspace(self._rp_x_min, self._rp_x_max, 6) + y = np.linspace(self._rp_y_min, self._rp_y_max, 5) + return uv_cubes(x=x, y=y) + + def test_name(self): + u, v = self._uv_cubes_limited_extent() + u.rename('bob') + v.rename('alice') + ut, vt = rotate_winds(u, v, iris.coord_systems.OSGB()) + self.assertEqual(ut.name(), 'transformed_' + u.name()) + self.assertEqual(vt.name(), 'transformed_' + v.name()) + + def test_new_coords(self): + u, v = self._uv_cubes_limited_extent() + x = u.coord('grid_longitude').points + y = u.coord('grid_latitude').points + x2d, y2d = np.meshgrid(x, y) + src_crs = ccrs.RotatedPole(pole_longitude=177.5, pole_latitude=37.5) + tgt_crs = ccrs.OSGB() + xyz_tran = tgt_crs.transform_points(src_crs, x2d, y2d) + + ut, vt = rotate_winds(u, v, iris.coord_systems.OSGB()) + + points = xyz_tran[..., 0].reshape(x2d.shape) + expected_x = AuxCoord(points, + standard_name='projection_x_coordinate', + units='m', + coord_system=iris.coord_systems.OSGB()) + self.assertEqual(ut.coord('projection_x_coordinate'), expected_x) + self.assertEqual(vt.coord('projection_x_coordinate'), expected_x) + + points = xyz_tran[..., 1].reshape(y2d.shape) + expected_y = AuxCoord(points, + standard_name='projection_y_coordinate', + units='m', + coord_system=iris.coord_systems.OSGB()) + self.assertEqual(ut.coord('projection_y_coordinate'), expected_y) + self.assertEqual(vt.coord('projection_y_coordinate'), expected_y) + + def test_new_coords_transposed(self): + u, v = self._uv_cubes_limited_extent() + # Transpose cubes so that cube is in xy order rather than the + # typical yx order of meshgrid. + u.transpose() + v.transpose() + x = u.coord('grid_longitude').points + y = u.coord('grid_latitude').points + x2d, y2d = np.meshgrid(x, y) + src_crs = ccrs.RotatedPole(pole_longitude=177.5, pole_latitude=37.5) + tgt_crs = ccrs.OSGB() + xyz_tran = tgt_crs.transform_points(src_crs, x2d, y2d) + + ut, vt = rotate_winds(u, v, iris.coord_systems.OSGB()) + + points = xyz_tran[..., 0].reshape(x2d.shape) + expected_x = AuxCoord(points, + standard_name='projection_x_coordinate', + units='m', + coord_system=iris.coord_systems.OSGB()) + self.assertEqual(ut.coord('projection_x_coordinate'), expected_x) + self.assertEqual(vt.coord('projection_x_coordinate'), expected_x) + + points = xyz_tran[..., 1].reshape(y2d.shape) + expected_y = AuxCoord(points, + standard_name='projection_y_coordinate', + units='m', + coord_system=iris.coord_systems.OSGB()) + self.assertEqual(ut.coord('projection_y_coordinate'), expected_y) + self.assertEqual(vt.coord('projection_y_coordinate'), expected_y) + # Check dim mapping for 2d coords is yx. + expected_dims = (u.coord_dims('grid_latitude') + + u.coord_dims('grid_longitude')) + self.assertEqual(ut.coord_dims('projection_x_coordinate'), + expected_dims) + self.assertEqual(ut.coord_dims('projection_y_coordinate'), + expected_dims) + self.assertEqual(vt.coord_dims('projection_x_coordinate'), + expected_dims) + self.assertEqual(vt.coord_dims('projection_y_coordinate'), + expected_dims) + + def test_orig_coords(self): + u, v = self._uv_cubes_limited_extent() + ut, vt = rotate_winds(u, v, iris.coord_systems.OSGB()) + self.assertEqual(u.coord('grid_latitude'), ut.coord('grid_latitude')) + self.assertEqual(v.coord('grid_latitude'), vt.coord('grid_latitude')) + self.assertEqual(u.coord('grid_longitude'), ut.coord('grid_longitude')) + self.assertEqual(v.coord('grid_longitude'), vt.coord('grid_longitude')) + + def test_magnitude_preservation(self): + u, v = self._uv_cubes_limited_extent() + ut, vt = rotate_winds(u, v, iris.coord_systems.OSGB()) + orig_sq_mag = u.data**2 + v.data**2 + res_sq_mag = ut.data**2 + vt.data**2 + self.assertArrayAllClose(orig_sq_mag, res_sq_mag, rtol=5e-4) + + def test_data_values(self): + u, v = self._uv_cubes_limited_extent() + # Slice out 4 points that lie in and outside OSGB extent. + u = u[1:3, 3:5] + v = v[1:3, 3:5] + ut, vt = rotate_winds(u, v, iris.coord_systems.OSGB()) + # Values precalculated and checked. + expected_ut_data = np.array([[0.16285514, 0.35323639], + [1.82650698, 2.62455840]]) + expected_vt_data = np.array([[19.88979966, 19.01921346], + [19.88018847, 19.01424281]]) + # Compare u and v data values against previously calculated values. + self.assertArrayAllClose(ut.data, expected_ut_data, rtol=1e-5) + self.assertArrayAllClose(vt.data, expected_vt_data, rtol=1e-5) + + def test_nd_data(self): + u2d, y2d = self._uv_cubes_limited_extent() + u, v = uv_cubes_3d(u2d) + u = u[:, 1:3, 3:5] + v = v[:, 1:3, 3:5] + ut, vt = rotate_winds(u, v, iris.coord_systems.OSGB()) + # Values precalculated and checked (as test_data_values above), + # then scaled by factor [1, 2, 3] along 0th dim (see uv_cubes_3d()). + expected_ut_data = np.array([[0.16285514, 0.35323639], + [1.82650698, 2.62455840]]) + expected_vt_data = np.array([[19.88979966, 19.01921346], + [19.88018847, 19.01424281]]) + factor = np.array([1, 2, 3]).reshape(3, 1, 1) + expected_ut_data = factor * expected_ut_data + expected_vt_data = factor * expected_vt_data + # Compare u and v data values against previously calculated values. + self.assertArrayAlmostEqual(ut.data, expected_ut_data) + self.assertArrayAlmostEqual(vt.data, expected_vt_data) + + def test_transposed(self): + # Test case where the coordinates are not ordered yx in the cube. + u, v = self._uv_cubes_limited_extent() + # Slice out 4 points that lie in and outside OSGB extent. + u = u[1:3, 3:5] + v = v[1:3, 3:5] + # Transpose cubes (in-place) + u.transpose() + v.transpose() + ut, vt = rotate_winds(u, v, iris.coord_systems.OSGB()) + # Values precalculated and checked. + expected_ut_data = np.array([[0.16285514, 0.35323639], + [1.82650698, 2.62455840]]).T + expected_vt_data = np.array([[19.88979966, 19.01921346], + [19.88018847, 19.01424281]]).T + # Compare u and v data values against previously calculated values. + self.assertArrayAllClose(ut.data, expected_ut_data, rtol=1e-5) + self.assertArrayAllClose(vt.data, expected_vt_data, rtol=1e-5) + + +class TestMasking(tests.IrisTest): + def test_rotated_to_osgb(self): + # Rotated Pole data with large extent. + x = np.linspace(311.9, 391.1, 10) + y = np.linspace(-23.6, 24.8, 8) + u, v = uv_cubes(x, y) + ut, vt = rotate_winds(u, v, iris.coord_systems.OSGB()) + + # Ensure cells with discrepancies in magnitude are masked. + self.assertTrue(ma.isMaskedArray(ut.data)) + self.assertTrue(ma.isMaskedArray(vt.data)) + + # Snapshot of mask with fixed tolerance of atol=2e-3 + expected_mask = np.array([[1, 1, 1, 0, 0, 0, 0, 0, 0, 1], + [1, 1, 1, 0, 0, 0, 0, 0, 0, 1], + [1, 1, 1, 1, 0, 0, 0, 0, 1, 1], + [1, 1, 1, 1, 0, 0, 0, 0, 1, 1], + [1, 1, 1, 1, 0, 0, 0, 0, 1, 1], + [1, 1, 1, 1, 1, 0, 0, 1, 1, 1], + [1, 1, 1, 1, 1, 0, 0, 1, 1, 1], + [1, 1, 1, 1, 1, 0, 0, 1, 1, 1]], np.bool) + self.assertArrayEqual(expected_mask, ut.data.mask) + self.assertArrayEqual(expected_mask, vt.data.mask) + + # Check unmasked values have sufficiently small error in mag. + expected_mag = np.sqrt(u.data**2 + v.data**2) + # Use underlying data to ignore mask in calculation. + res_mag = np.sqrt(ut.data.data**2 + vt.data.data**2) + # Calculate percentage error (note there are no zero magnitudes + # so we can divide safely). + anom = 100.0 * np.abs(res_mag - expected_mag) / expected_mag + self.assertTrue(anom[~ut.data.mask].max() < 0.1) + + def test_rotated_to_unrotated(self): + # Suffiently accurate so that no mask is introduced. + u, v = uv_cubes() + ut, vt = rotate_winds(u, v, iris.coord_systems.GeogCS(6371229)) + self.assertFalse(ma.isMaskedArray(ut.data)) + self.assertFalse(ma.isMaskedArray(vt.data)) + + +class TestRoundTrip(tests.IrisTest): + def test_rotated_to_unrotated(self): + # Check ability to use 2d coords as input. + u, v = uv_cubes() + ut, vt = rotate_winds(u, v, iris.coord_systems.GeogCS(6371229)) + # Remove grid lat and lon, leaving 2d projection coords. + ut.remove_coord('grid_latitude') + vt.remove_coord('grid_latitude') + ut.remove_coord('grid_longitude') + vt.remove_coord('grid_longitude') + # Change back. + orig_cs = u.coord('grid_latitude').coord_system + res_u, res_v = rotate_winds(ut, vt, orig_cs) + # Check data values - limited accuracy due to numerical approx. + self.assertArrayAlmostEqual(res_u.data, u.data, decimal=3) + self.assertArrayAlmostEqual(res_v.data, v.data, decimal=3) + # Check coords locations. + x2d, y2d = np.meshgrid(u.coord('grid_longitude').points, + u.coord('grid_latitude').points) + # Shift longitude from 0 to 360 -> -180 to 180. + x2d = np.where(x2d > 180, x2d - 360, x2d) + res_x = res_u.coord('projection_x_coordinate', + coord_system=orig_cs).points + res_y = res_u.coord('projection_y_coordinate', + coord_system=orig_cs).points + self.assertArrayAlmostEqual(res_x, x2d) + self.assertArrayAlmostEqual(res_y, y2d) + res_x = res_v.coord('projection_x_coordinate', + coord_system=orig_cs).points + res_y = res_v.coord('projection_y_coordinate', + coord_system=orig_cs).points + self.assertArrayAlmostEqual(res_x, x2d) + self.assertArrayAlmostEqual(res_y, y2d) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/geometry/__init__.py b/lib/iris/tests/unit/analysis/geometry/__init__.py new file mode 100644 index 0000000000..31c8906f83 --- /dev/null +++ b/lib/iris/tests/unit/analysis/geometry/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.analysis.geometry` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/analysis/geometry/test__extract_relevant_cube_slice.py b/lib/iris/tests/unit/analysis/geometry/test__extract_relevant_cube_slice.py new file mode 100644 index 0000000000..ca77946e57 --- /dev/null +++ b/lib/iris/tests/unit/analysis/geometry/test__extract_relevant_cube_slice.py @@ -0,0 +1,101 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for :func:`iris.analysis.geometry._extract_relevant_cube_slice`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. + +import iris.tests as tests +import iris.tests.stock as stock + +import shapely.geometry + +from iris.analysis.geometry import _extract_relevant_cube_slice + + +class Test(tests.IrisTest): + def test_polygon_smaller_than_cube(self): + cube = stock.lat_lon_cube() + cube.dim_coords[0].guess_bounds() + cube.dim_coords[1].guess_bounds() + geometry = shapely.geometry.box(-0.4, -0.4, 0.4, 0.4) + actual = _extract_relevant_cube_slice(cube, geometry) + target = (cube[1, 1], + cube[1, 1].coords(axis='x')[0], + cube[1, 1].coords(axis='y')[0], + (1, 1, 1, 1)) + self.assertEqual(target, actual) + + def test_polygon_larger_than_cube(self): + cube = stock.lat_lon_cube() + cube.dim_coords[0].guess_bounds() + cube.dim_coords[1].guess_bounds() + geometry = shapely.geometry.box(-0.6, -0.6, 0.6, 0.6) + actual = _extract_relevant_cube_slice(cube, geometry) + target = (cube[:, :3], + cube[:, :3].coords(axis='x')[0], + cube[:, :3].coords(axis='y')[0], + (0, 0, 2, 2)) + self.assertEqual(target, actual) + + def test_polygon_on_cube_boundary(self): + cube = stock.lat_lon_cube() + cube.dim_coords[0].guess_bounds() + cube.dim_coords[1].guess_bounds() + geometry = shapely.geometry.box(-0.5, -0.5, 0.5, 0.5) + actual = _extract_relevant_cube_slice(cube, geometry) + target = (cube[1, 1], + cube[1, 1].coords(axis='x')[0], + cube[1, 1].coords(axis='y')[0], + (1, 1, 1, 1)) + self.assertEqual(target, actual) + + def test_rotated_polygon_on_cube_boundary(self): + cube = stock.lat_lon_cube() + cube.dim_coords[0].guess_bounds() + cube.dim_coords[1].guess_bounds() + geometry = shapely.geometry.Polygon(((0., -.5), (-.5, 0.), (0., .5), + (.5, 0.))) + actual = _extract_relevant_cube_slice(cube, geometry) + target = (cube[1, 1], + cube[1, 1].coords(axis='x')[0], + cube[1, 1].coords(axis='y')[0], + (1, 1, 1, 1)) + self.assertEqual(target, actual) + + def test_rotated_polygon_larger_than_cube_boundary(self): + cube = stock.lat_lon_cube() + cube.dim_coords[0].guess_bounds() + cube.dim_coords[1].guess_bounds() + geometry = shapely.geometry.Polygon(((0., -.6), (-.6, 0.), (0., .6), + (.6, 0.))) + actual = _extract_relevant_cube_slice(cube, geometry) + target = (cube[:, :3], + cube[:, :3].coords(axis='x')[0], + cube[:, :3].coords(axis='y')[0], + (0, 0, 2, 2)) + self.assertEqual(target, actual) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/geometry/test_geometry_area_weights.py b/lib/iris/tests/unit/analysis/geometry/test_geometry_area_weights.py new file mode 100644 index 0000000000..4e8928542e --- /dev/null +++ b/lib/iris/tests/unit/analysis/geometry/test_geometry_area_weights.py @@ -0,0 +1,166 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the :func:`iris.analysis.geometry.geometry_area_weights` +function. + + """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. + +import iris.tests as tests +import iris.tests.stock as stock + +import warnings +import numpy as np +import shapely.geometry + +from iris.analysis.geometry import geometry_area_weights +from iris.coords import DimCoord +from iris.cube import Cube + + +class Test(tests.IrisTest): + + def setUp(self): + x_coord = DimCoord([1.0, 3.0], 'longitude', bounds=[[0, 2], [2, 4]]) + y_coord = DimCoord([1.0, 3.0], 'latitude', bounds=[[0, 2], [2, 4]]) + self.data = np.empty((4, 2, 2)) + dim_coords_and_dims = [(y_coord, (1,)), (x_coord, (2,))] + self.cube = Cube(self.data, dim_coords_and_dims=dim_coords_and_dims) + self.geometry = shapely.geometry.Polygon([(3, 3), (3, 50), (50, 50), + (50, 3)]) + + def test_no_overlap(self): + geometry = shapely.geometry.Polygon([(4, 4), (4, 6), (6, 6), (6, 4)]) + weights = geometry_area_weights(self.cube, geometry) + self.assertEqual(np.sum(weights), 0) + + def test_overlap(self): + weights = geometry_area_weights(self.cube, self.geometry) + expected = np.repeat([[[0., 0.], [0., 1.]]], self.data.shape[0], + axis=0) + self.assertArrayEqual(weights, expected) + + def test_overlap_normalize(self): + weights = geometry_area_weights(self.cube, self.geometry, + normalize=True) + expected = np.repeat([[[0., 0.], [0., 0.25]]], self.data.shape[0], + axis=0) + self.assertArrayEqual(weights, expected) + + @tests.skip_data + def test_distinct_xy(self): + cube = stock.simple_pp() + cube = cube[:4, :4] + lon = cube.coord('longitude') + lat = cube.coord('latitude') + lon.guess_bounds() + lat.guess_bounds() + from iris.util import regular_step + quarter = abs(regular_step(lon) * regular_step(lat) * 0.25) + half = abs(regular_step(lon) * regular_step(lat) * 0.5) + minx = 3.7499990463256836 + maxx = 7.499998092651367 + miny = 84.99998474121094 + maxy = 89.99998474121094 + geometry = shapely.geometry.box(minx, miny, maxx, maxy) + weights = geometry_area_weights(cube, geometry) + target = np.array([ + [0, quarter, quarter, 0], + [0, half, half, 0], + [0, quarter, quarter, 0], + [0, 0, 0, 0]]) + self.assertTrue(np.allclose(weights, target)) + + @tests.skip_data + def test_distinct_xy_bounds(self): + # cases where geometry bnds are outside cube bnds correctly handled? + cube = stock.simple_pp() + cube = cube[:4, :4] + lon = cube.coord('longitude') + lat = cube.coord('latitude') + lon.guess_bounds() + lat.guess_bounds() + from iris.util import regular_step + quarter = abs(regular_step(lon) * regular_step(lat) * 0.25) + half = abs(regular_step(lon) * regular_step(lat) * 0.5) + full = abs(regular_step(lon) * regular_step(lat)) + minx = 3.7499990463256836 + maxx = 13.12499619 + maxx_overshoot = 15. + miny = 84.99998474121094 + maxy = 89.99998474121094 + geometry = shapely.geometry.box(minx, miny, maxx, maxy) + geometry_overshoot = shapely.geometry.box(minx, miny, maxx_overshoot, + maxy) + weights = geometry_area_weights(cube, geometry) + weights_overshoot = geometry_area_weights(cube, geometry_overshoot) + target = np.array([ + [0, quarter, half, half], + [0, half, full, full], + [0, quarter, half, half], + [0, 0, 0, 0]]) + self.assertTrue(np.allclose(weights, target)) + self.assertTrue(np.allclose(weights_overshoot, target)) + + @tests.skip_data + def test_distinct_xy_bounds_pole(self): + # is UserWarning issued for out-of-bounds? results will be unexpected! + cube = stock.simple_pp() + cube = cube[:4, :4] + lon = cube.coord('longitude') + lat = cube.coord('latitude') + lon.guess_bounds() + lat.guess_bounds() + from iris.util import regular_step + quarter = abs(regular_step(lon) * regular_step(lat) * 0.25) + half = abs(regular_step(lon) * regular_step(lat) * 0.5) + top_cell_half = abs(regular_step(lon) * (90 - lat.bounds[0, 1]) * 0.5) + minx = 3.7499990463256836 + maxx = 7.499998092651367 + miny = 84.99998474121094 + maxy = 99.99998474121094 + geometry = shapely.geometry.box(minx, miny, maxx, maxy) + # see http://stackoverflow.com/a/3892301 to assert warnings + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") # always trigger all warnings + weights = geometry_area_weights(cube, geometry) + self.assertEqual(str(w[-1].message), "The geometry exceeds the " + "cube's y dimension at the upper end.") + self.assertTrue(issubclass(w[-1].category, UserWarning)) + target = np.array([ + [0, top_cell_half, top_cell_half, 0], + [0, half, half, 0], + [0, quarter, quarter, 0], + [0, 0, 0, 0]]) + self.assertTrue(np.allclose(weights, target)) + + def test_shared_xy(self): + cube = stock.track_1d() + geometry = shapely.geometry.box(1, 4, 3.5, 7) + weights = geometry_area_weights(cube, geometry) + target = np.array([0, 0, 2, 0.5, 0, 0, 0, 0, 0, 0, 0]) + self.assertTrue(np.allclose(weights, target)) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/interpolate/__init__.py b/lib/iris/tests/unit/analysis/interpolate/__init__.py deleted file mode 100644 index a3dcd7100c..0000000000 --- a/lib/iris/tests/unit/analysis/interpolate/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# (C) British Crown Copyright 2014, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -"""Unit tests for the :mod:`iris.analysis.interpolate` package.""" diff --git a/lib/iris/tests/unit/analysis/interpolate/test_linear.py b/lib/iris/tests/unit/analysis/interpolate/test_linear.py deleted file mode 100644 index ea6c192cc0..0000000000 --- a/lib/iris/tests/unit/analysis/interpolate/test_linear.py +++ /dev/null @@ -1,41 +0,0 @@ -# (C) British Crown Copyright 2014, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -"""Unit tests for the :func:`iris.analysis.interpolate.linear` function.""" - -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -import numpy as np -import numpy.ma as ma - -from iris.analysis.interpolate import linear -import iris.tests.stock as stock - - -class Test_masks(tests.IrisTest): - def test_mask_retention(self): - cube = stock.realistic_4d_w_missing_data() - interp_cube = linear(cube, [('pressure', [850, 950])]) - self.assertIsInstance(interp_cube.data, ma.MaskedArray) - # this value is masked in the input - self.assertTrue(cube.data.mask[0, 2, 2, 0]) - # and is still masked in the output - self.assertTrue(interp_cube.data.mask[0, 1, 2, 0]) - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/analysis/interpolation/__init__.py b/lib/iris/tests/unit/analysis/interpolation/__init__.py new file mode 100644 index 0000000000..62af236e70 --- /dev/null +++ b/lib/iris/tests/unit/analysis/interpolation/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.analysis._interpolation` package.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/analysis/interpolation/test_RectilinearInterpolator.py b/lib/iris/tests/unit/analysis/interpolation/test_RectilinearInterpolator.py new file mode 100644 index 0000000000..97433d2f65 --- /dev/null +++ b/lib/iris/tests/unit/analysis/interpolation/test_RectilinearInterpolator.py @@ -0,0 +1,543 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for :class:`iris.analysis._interpolation.RectilinearInterpolator`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import datetime + +from iris._lazy_data import as_lazy_data +import numpy as np + +import iris +import iris.coords +import iris.cube +import iris.exceptions +import iris.tests.stock as stock +from iris.analysis._interpolation import RectilinearInterpolator + + +LINEAR = 'linear' +NEAREST = 'nearest' + +EXTRAPOLATE = 'extrapolate' + + +class ThreeDimCube(tests.IrisTest): + def setUp(self): + cube = stock.simple_3d_w_multidim_coords() + cube.add_aux_coord(iris.coords.DimCoord(np.arange(2), 'height'), 0) + cube.add_dim_coord(iris.coords.DimCoord(np.arange(3), 'latitude'), 1) + cube.add_dim_coord(iris.coords.DimCoord(np.arange(4), 'longitude'), 2) + self.data = np.arange(24).reshape(2, 3, 4).astype(np.float32) + cube.data = self.data + self.cube = cube + + +class Test___init__(ThreeDimCube): + def test_properties(self): + interpolator = RectilinearInterpolator(self.cube, ['latitude'], LINEAR, + EXTRAPOLATE) + + self.assertEqual(interpolator.method, LINEAR) + self.assertEqual(interpolator.extrapolation_mode, EXTRAPOLATE) + + # Access to cube property of the RectilinearInterpolator instance. + self.assertEqual(interpolator.cube, self.cube) + + # Access to the resulting coordinate which we are interpolating over. + self.assertEqual(interpolator.coords, + [self.cube.coord('latitude')]) + + +class Test___init____validation(ThreeDimCube): + def test_interpolator_overspecified(self): + # Over specification by means of interpolating over two coordinates + # mapped to the same dimension. + msg = 'Coordinates repeat a data dimension - '\ + 'the interpolation would be over-specified' + with self.assertRaisesRegexp(ValueError, msg): + RectilinearInterpolator(self.cube, ['wibble', 'height'], LINEAR, + EXTRAPOLATE) + + def test_interpolator_overspecified_scalar(self): + # Over specification by means of interpolating over one dimension + # coordinate and a scalar coordinate (not mapped to a dimension). + self.cube.add_aux_coord(iris.coords.AuxCoord( + 1, long_name='scalar'), None) + + msg = 'Coordinates repeat a data dimension - '\ + 'the interpolation would be over-specified' + with self.assertRaisesRegexp(ValueError, msg): + RectilinearInterpolator(self.cube, ['wibble', 'scalar'], LINEAR, + EXTRAPOLATE) + + def test_interpolate__decreasing(self): + def check_expected(): + # Check a simple case is equivalent to extracting the first row. + self.interpolator = RectilinearInterpolator(self.cube, + ['latitude'], + LINEAR, EXTRAPOLATE) + expected = self.data[:, 0:1, :] + result = self.interpolator([[0]]) + self.assertArrayEqual(result.data, expected) + + # Check with normal cube. + check_expected() + # Check same result from a cube inverted in the latitude dimension. + self.cube = self.cube[:, ::-1] + check_expected() + + def test_interpolate_non_monotonic(self): + self.cube.add_aux_coord(iris.coords.AuxCoord( + [0, 3, 2], long_name='non-monotonic'), 1) + msg = ('Cannot interpolate over the non-monotonic coordinate ' + 'non-monotonic.') + with self.assertRaisesRegexp(ValueError, msg): + RectilinearInterpolator(self.cube, ['non-monotonic'], LINEAR, + EXTRAPOLATE) + + +class Test___call___1D(ThreeDimCube): + def setUp(self): + ThreeDimCube.setUp(self) + self.interpolator = RectilinearInterpolator(self.cube, ['latitude'], + LINEAR, EXTRAPOLATE) + + def test_interpolate_bad_coord_name(self): + with self.assertRaises(iris.exceptions.CoordinateNotFoundError): + RectilinearInterpolator(self.cube, ['doesnt exist'], LINEAR, + EXTRAPOLATE) + + def test_interpolate_data_single(self): + # Single sample point. + result = self.interpolator([[1.5]]) + expected = self.data[:, 1:, :].mean(axis=1).reshape(2, 1, 4) + self.assertArrayEqual(result.data, expected) + + foo_res = result.coord('foo').points + bar_res = result.coord('bar').points + expected_foo = self.cube[:, 1:, :].coord('foo').points.mean( + axis=0).reshape(1, 4) + expected_bar = self.cube[:, 1:, :].coord('bar').points.mean( + axis=0).reshape(1, 4) + + self.assertArrayEqual(foo_res, expected_foo) + self.assertArrayEqual(bar_res, expected_bar) + + def test_interpolate_data_multiple(self): + # Multiple sample points for a single coordinate (these points are not + # interpolated). + result = self.interpolator([[1, 2]]) + self.assertArrayEqual(result.data, self.data[:, 1:3, :]) + + foo_res = result.coord('foo').points + bar_res = result.coord('bar').points + expected_foo = self.cube[:, 1:, :].coord('foo').points + expected_bar = self.cube[:, 1:, :].coord('bar').points + + self.assertArrayEqual(foo_res, expected_foo) + self.assertArrayEqual(bar_res, expected_bar) + + def test_interpolate_data_linear_extrapolation(self): + # Sample point outside the coordinate range. + result = self.interpolator([[-1]]) + expected = self.data[:, 0:1] - (self.data[:, 1:2] - self.data[:, 0:1]) + self.assertArrayEqual(result.data, expected) + + def _extrapolation_dtype(self, dtype): + self.cube.data = self.cube.data.astype(dtype) + interpolator = RectilinearInterpolator(self.cube, ['latitude'], LINEAR, + extrapolation_mode='nan') + result = interpolator([[-1]]) + self.assertTrue(np.all(np.isnan(result.data))) + + def test_extrapolation_nan_float32(self): + # Ensure np.nan in a float32 array results. + self._extrapolation_dtype(np.float32) + + def test_extrapolation_nan_float64(self): + # Ensure np.nan in a float64 array results. + self._extrapolation_dtype(np.float64) + + def test_interpolate_data_error_on_extrapolation(self): + msg = 'One of the requested xi is out of bounds in dimension 0' + interpolator = RectilinearInterpolator(self.cube, ['latitude'], LINEAR, + extrapolation_mode='error') + with self.assertRaisesRegexp(ValueError, msg): + interpolator([[-1]]) + + def test_interpolate_data_unsupported_extrapolation(self): + msg = "Extrapolation mode 'unsupported' not supported" + with self.assertRaisesRegexp(ValueError, msg): + RectilinearInterpolator(self.cube, ['latitude'], LINEAR, + extrapolation_mode='unsupported') + + def test_multi_points_array(self): + # Providing a multidimensional sample points for a 1D interpolation. + # i.e. points given for two coordinates where there are only one + # specified. + msg = 'Expected sample points for 1 coordinates, got 2.' + with self.assertRaisesRegexp(ValueError, msg): + self.interpolator([[1, 2], [1]]) + + def test_interpolate_data_dtype_casting(self): + data = self.data.astype(int) + self.cube.data = data + self.interpolator = RectilinearInterpolator(self.cube, ['latitude'], + LINEAR, EXTRAPOLATE) + result = self.interpolator([[0.125]]) + self.assertEqual(result.data.dtype, np.float64) + + def test_default_collapse_scalar(self): + interpolator = RectilinearInterpolator(self.cube, ['wibble'], LINEAR, + EXTRAPOLATE) + result = interpolator([0]) + self.assertEqual(result.shape, (3, 4)) + + def test_collapse_scalar(self): + interpolator = RectilinearInterpolator(self.cube, ['wibble'], LINEAR, + EXTRAPOLATE) + result = interpolator([0], collapse_scalar=True) + self.assertEqual(result.shape, (3, 4)) + + def test_no_collapse_scalar(self): + interpolator = RectilinearInterpolator(self.cube, ['wibble'], LINEAR, + EXTRAPOLATE) + result = interpolator([0], collapse_scalar=False) + self.assertEqual(result.shape, (1, 3, 4)) + + def test_unsorted_datadim_mapping(self): + # Currently unsorted data dimension mapping is not supported as the + # indexing is not yet clever enough to remap the interpolated + # coordinates. + self.cube.transpose((0, 2, 1)) + interpolator = RectilinearInterpolator(self.cube, ['latitude'], LINEAR, + EXTRAPOLATE) + msg = 'Currently only increasing data_dims is supported.' + with self.assertRaisesRegexp(NotImplementedError, msg): + interpolator([0]) + + +class Test___call___1D_circular(ThreeDimCube): + # Note: all these test data interpolation. + def setUp(self): + ThreeDimCube.setUp(self) + self.cube.coord('longitude')._points = np.linspace(0, 360, 4, + endpoint=False) + self.cube.coord('longitude').circular = True + self.cube.coord('longitude').units = 'degrees' + self.interpolator = RectilinearInterpolator(self.cube, ['longitude'], + LINEAR, + extrapolation_mode='nan') + self.cube_reverselons = self.cube[:, :, ::-1] + self.interpolator_reverselons = RectilinearInterpolator( + self.cube_reverselons, ['longitude'], LINEAR, + extrapolation_mode='nan') + + self.testpoints_fully_wrapped = ([[180, 270]], [[-180, -90]]) + self.testpoints_partially_wrapped = ([[180, 90]], [[-180, 90]]) + self.testpoints_fully_wrapped_twice = ( + [np.linspace(-360, 360, 100)], + [(np.linspace(-360, 360, 100) + 360) % 360]) + + def test_fully_wrapped(self): + points, points_wrapped = self.testpoints_fully_wrapped + expected = self.interpolator(points) + result = self.interpolator(points_wrapped) + self.assertArrayEqual(expected.data, result.data) + + def test_fully_wrapped_reversed_mainpoints(self): + points, _ = self.testpoints_fully_wrapped + expected = self.interpolator(points) + result = self.interpolator_reverselons(points) + self.assertArrayEqual(expected.data, result.data) + + def test_fully_wrapped_reversed_testpoints(self): + _, points = self.testpoints_fully_wrapped + expected = self.interpolator(points) + result = self.interpolator_reverselons(points) + self.assertArrayEqual(expected.data, result.data) + + def test_partially_wrapped(self): + points, points_wrapped = self.testpoints_partially_wrapped + expected = self.interpolator(points) + result = self.interpolator(points_wrapped) + + def test_partially_wrapped_reversed_mainpoints(self): + points, _ = self.testpoints_partially_wrapped + expected = self.interpolator(points) + result = self.interpolator_reverselons(points) + self.assertArrayEqual(expected.data, result.data) + + def test_partially_wrapped_reversed_testpoints(self): + points, _ = self.testpoints_partially_wrapped + expected = self.interpolator(points) + result = self.interpolator_reverselons(points) + self.assertArrayEqual(expected.data, result.data) + + def test_fully_wrapped_twice(self): + xs, xs_not_wrapped = self.testpoints_fully_wrapped_twice + expected = self.interpolator(xs) + result = self.interpolator(xs_not_wrapped) + self.assertArrayEqual(expected.data, result.data) + + def test_fully_wrapped_twice_reversed_mainpoints(self): + _, points = self.testpoints_fully_wrapped_twice + expected = self.interpolator(points) + result = self.interpolator_reverselons(points) + self.assertArrayEqual(expected.data, result.data) + + def test_fully_wrapped_not_circular(self): + cube = stock.lat_lon_cube() + new_long = cube.coord('longitude').copy( + cube.coord('longitude').points + 710) + cube.remove_coord('longitude') + cube.add_dim_coord(new_long, 1) + + interpolator = RectilinearInterpolator(cube, ['longitude'], LINEAR, + EXTRAPOLATE) + res = interpolator([-10]) + self.assertArrayEqual(res.data, cube[:, 1].data) + + +class Test___call___1D_singlelendim(ThreeDimCube): + def setUp(self): + """ + thingness / (1) (wibble: 2; latitude: 1) + Dimension coordinates: + wibble x - + latitude - x + Auxiliary coordinates: + height x - + bar - x + foo - x + Scalar coordinates: + longitude: 0 + """ + ThreeDimCube.setUp(self) + self.cube = self.cube[:, 0:1, 0] + self.interpolator = RectilinearInterpolator(self.cube, ['latitude'], + LINEAR, EXTRAPOLATE) + + def test_interpolate_data_linear_extrapolation(self): + # Linear extrapolation of a single valued element. + result = self.interpolator([[1001]]) + self.assertArrayEqual(result.data, self.cube.data) + + def test_interpolate_data_nan_extrapolation(self): + interpolator = RectilinearInterpolator(self.cube, ['latitude'], LINEAR, + extrapolation_mode='nan') + result = interpolator([[1001]]) + self.assertTrue(np.all(np.isnan(result.data))) + + def test_interpolate_data_nan_extrapolation_not_needed(self): + # No extrapolation for a single length dimension. + interpolator = RectilinearInterpolator(self.cube, ['latitude'], LINEAR, + extrapolation_mode='nan') + result = interpolator([[0]]) + self.assertArrayEqual(result.data, self.cube.data) + + +class Test___call___masked(tests.IrisTest): + def setUp(self): + self.cube = stock.simple_4d_with_hybrid_height() + mask = np.isnan(self.cube.data) + mask[::3, ::3] = True + self.cube.data = np.ma.masked_array(self.cube.data, + mask=mask) + + def test_orthogonal_cube(self): + interpolator = RectilinearInterpolator(self.cube, ['grid_latitude'], + LINEAR, EXTRAPOLATE) + result_cube = interpolator([1]) + + # Explicit mask comparison to ensure mask retention. + # Masked value input + self.assertTrue(self.cube.data.mask[0, 0, 0, 0]) + # Mask retention on output + self.assertTrue(result_cube.data.mask[0, 0, 0]) + + self.assertCML(result_cube, ('experimental', 'analysis', + 'interpolate', 'LinearInterpolator', + 'orthogonal_cube_with_factory.cml')) + + +class Test___call___2D(ThreeDimCube): + def setUp(self): + ThreeDimCube.setUp(self) + self.interpolator = RectilinearInterpolator(self.cube, + ['latitude', 'longitude'], + LINEAR, EXTRAPOLATE) + + def test_interpolate_data(self): + result = self.interpolator([[1, 2], [2]]) + expected = self.data[:, 1:3, 2:3] + self.assertArrayEqual(result.data, expected) + + index = (slice(None), slice(1, 3, 1), slice(2, 3, 1)) + for coord in self.cube.coords(): + coord_res = result.coord(coord).points + coord_expected = self.cube[index].coord(coord).points + + self.assertArrayEqual(coord_res, coord_expected) + + def test_orthogonal_points(self): + result = self.interpolator([[1, 2], [1, 2]]) + expected = self.data[:, 1:3, 1:3] + self.assertArrayEqual(result.data, expected) + + index = (slice(None), slice(1, 3, 1), slice(1, 3, 1)) + for coord in self.cube.coords(): + coord_res = result.coord(coord).points + coord_expected = self.cube[index].coord(coord).points + + self.assertArrayEqual(coord_res, coord_expected) + + def test_multi_dim_coord_interpolation(self): + msg = 'Interpolation coords must be 1-d for rectilinear interpolation.' + with self.assertRaisesRegexp(ValueError, msg): + interpolator = RectilinearInterpolator(self.cube, ['foo', 'bar'], + LINEAR, EXTRAPOLATE) + interpolator([[15], [10]]) + + +class Test___call___2D_non_contiguous(ThreeDimCube): + def setUp(self): + ThreeDimCube.setUp(self) + coords = ['height', 'longitude'] + self.interpolator = RectilinearInterpolator(self.cube, coords, LINEAR, + EXTRAPOLATE) + + def test_interpolate_data_multiple(self): + result = self.interpolator([[1], [1, 2]]) + expected = self.data[1:2, :, 1:3] + self.assertArrayEqual(result.data, expected) + + index = (slice(1, 2), slice(None), slice(1, 3, 1)) + for coord in self.cube.coords(): + coord_res = result.coord(coord).points + coord_expected = self.cube[index].coord(coord).points + + self.assertArrayEqual(coord_res, coord_expected) + + def test_orthogonal_cube(self): + result_cube = self.interpolator([np.int64([0, 1, 1]), + np.int32([0, 1])]) + result_path = ('experimental', 'analysis', 'interpolate', + 'LinearInterpolator', 'basic_orthogonal_cube.cml') + self.assertCMLApproxData(result_cube, result_path) + self.assertEqual(result_cube.coord('longitude').dtype, np.int32) + self.assertEqual(result_cube.coord('height').dtype, np.int64) + + def test_orthogonal_cube_squash(self): + result_cube = self.interpolator([np.int64(0), + np.int32([0, 1])]) + result_path = ('experimental', 'analysis', 'interpolate', + 'LinearInterpolator', 'orthogonal_cube_1d_squashed.cml') + self.assertCMLApproxData(result_cube, result_path) + self.assertEqual(result_cube.coord('longitude').dtype, np.int32) + self.assertEqual(result_cube.coord('height').dtype, np.int64) + + non_collapsed_cube = self.interpolator([[np.int64(0)], + np.int32([0, 1])], + collapse_scalar=False) + result_path = ('experimental', 'analysis', 'interpolate', + 'LinearInterpolator', + 'orthogonal_cube_1d_squashed_2.cml') + self.assertCML(non_collapsed_cube[0, ...], result_path) + self.assertCML(result_cube, result_path) + self.assertEqual(result_cube, non_collapsed_cube[0, ...]) + + +class Test___call___lazy_data(ThreeDimCube): + def test_src_cube_data_loaded(self): + # RectilinearInterpolator operates using a snapshot of the source cube. + # If the source cube has lazy data when the interpolator is + # instantiated we want to make sure the source cube's data is + # loaded as a consequence of interpolation to avoid the risk + # of loading it again and again. + + # Modify self.cube to have lazy data. + self.cube.data = as_lazy_data(self.data) + self.assertTrue(self.cube.has_lazy_data()) + + # Perform interpolation and check the data has been loaded. + interpolator = RectilinearInterpolator(self.cube, ['latitude'], LINEAR, + EXTRAPOLATE) + interpolator([[1.5]]) + self.assertFalse(self.cube.has_lazy_data()) + + +class Test___call___time(tests.IrisTest): + def interpolator(self, method=LINEAR): + data = np.arange(12).reshape(4, 3) + cube = iris.cube.Cube(data) + time_coord = iris.coords.DimCoord(np.arange(0.0, 48.0, 12.0), 'time', + units='hours since epoch') + height_coord = iris.coords.DimCoord(np.arange(3), 'altitude', + units='m') + cube.add_dim_coord(time_coord, 0) + cube.add_dim_coord(height_coord, 1) + return RectilinearInterpolator(cube, ['time'], method, EXTRAPOLATE) + + def test_number_at_existing_value(self): + interpolator = self.interpolator() + result = interpolator([12]) + self.assertArrayEqual(result.data, [3, 4, 5]) + + def test_datetime_at_existing_value(self): + interpolator = self.interpolator() + result = interpolator([datetime.datetime(1970, 1, 1, 12)]) + self.assertArrayEqual(result.data, [3, 4, 5]) + + def test_datetime_between_existing_values(self): + interpolator = self.interpolator() + result = interpolator([datetime.datetime(1970, 1, 1, 18)]) + self.assertArrayEqual(result.data, [4.5, 5.5, 6.5]) + + def test_mixed_numbers_and_datetimes(self): + interpolator = self.interpolator() + result = interpolator([(12, datetime.datetime(1970, 1, 1, 18), + datetime.datetime(1970, 1, 2, 0), 26)]) + self.assertEqual(result.coord('time').points.dtype, float) + self.assertArrayEqual(result.data, [[3, 4, 5], + [4.5, 5.5, 6.5], + [6, 7, 8], + [6.5, 7.5, 8.5]]) + + def test_mixed_numbers_and_datetimes_nearest(self): + interpolator = self.interpolator(NEAREST) + result = interpolator([(12, datetime.datetime(1970, 1, 1, 18), + datetime.datetime(1970, 1, 2, 0), 26)]) + self.assertEqual(result.coord('time').points.dtype, float) + self.assertArrayEqual(result.data, [[3, 4, 5], + [3, 4, 5], + [6, 7, 8], + [6, 7, 8]]) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/experimental/regrid/test_get_xy_dim_coords.py b/lib/iris/tests/unit/analysis/interpolation/test_get_xy_dim_coords.py similarity index 84% rename from lib/iris/tests/experimental/regrid/test_get_xy_dim_coords.py rename to lib/iris/tests/unit/analysis/interpolation/test_get_xy_dim_coords.py index e6b89a3d01..457bd207f1 100644 --- a/lib/iris/tests/experimental/regrid/test_get_xy_dim_coords.py +++ b/lib/iris/tests/unit/analysis/interpolation/test_get_xy_dim_coords.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2016, Met Office # # This file is part of Iris. # @@ -15,9 +15,13 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """ -Test the :func:`iris.experimental.regrid._get_xy_dim_coords` function. +Unit tests for :func:`iris.analysis._interpolation.get_xy_dim_coords`. """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised # before importing anything else. import iris.tests as tests @@ -26,6 +30,7 @@ import numpy as np +from iris.analysis._interpolation import get_xy_dim_coords import iris.coords import iris.coord_systems import iris.experimental.regrid @@ -33,15 +38,16 @@ class TestGetXYCoords(tests.IrisTest): + @tests.skip_data def test_grid_lat_lon(self): cube = iris.tests.stock.realistic_4d() - x, y = iris.experimental.regrid._get_xy_dim_coords(cube) + x, y = get_xy_dim_coords(cube) self.assertIs(x, cube.coord('grid_longitude')) self.assertIs(y, cube.coord('grid_latitude')) def test_lat_lon(self): cube = iris.tests.stock.lat_lon_cube() - x, y = iris.experimental.regrid._get_xy_dim_coords(cube) + x, y = get_xy_dim_coords(cube) self.assertIs(x, cube.coord('longitude')) self.assertIs(y, cube.coord('latitude')) @@ -49,22 +55,25 @@ def test_projection_coords(self): cube = iris.tests.stock.lat_lon_cube() cube.coord('longitude').rename('projection_x_coordinate') cube.coord('latitude').rename('projection_y_coordinate') - x, y = iris.experimental.regrid._get_xy_dim_coords(cube) + x, y = get_xy_dim_coords(cube) self.assertIs(x, cube.coord('projection_x_coordinate')) self.assertIs(y, cube.coord('projection_y_coordinate')) + @tests.skip_data def test_missing_x_coord(self): cube = iris.tests.stock.realistic_4d() cube.remove_coord('grid_longitude') with self.assertRaises(ValueError): - iris.experimental.regrid._get_xy_dim_coords(cube) + get_xy_dim_coords(cube) + @tests.skip_data def test_missing_y_coord(self): cube = iris.tests.stock.realistic_4d() cube.remove_coord('grid_latitude') with self.assertRaises(ValueError): - iris.experimental.regrid._get_xy_dim_coords(cube) + get_xy_dim_coords(cube) + @tests.skip_data def test_multiple_coords(self): cube = iris.tests.stock.realistic_4d() cs = iris.coord_systems.GeogCS(6371229) @@ -86,12 +95,12 @@ def test_multiple_coords(self): cube.add_dim_coord(lon_coord, model_level_dims) with self.assertRaises(ValueError): - iris.experimental.regrid._get_xy_dim_coords(cube) + get_xy_dim_coords(cube) cube.remove_coord('grid_latitude') cube.remove_coord('grid_longitude') - x, y = iris.experimental.regrid._get_xy_dim_coords(cube) + x, y = get_xy_dim_coords(cube) self.assertIs(x, lon_coord) self.assertIs(y, lat_coord) @@ -99,7 +108,7 @@ def test_no_coordsystem(self): cube = iris.tests.stock.lat_lon_cube() for coord in cube.coords(): coord.coord_system = None - x, y = iris.experimental.regrid._get_xy_dim_coords(cube) + x, y = get_xy_dim_coords(cube) self.assertIs(x, cube.coord('longitude')) self.assertIs(y, cube.coord('latitude')) @@ -107,7 +116,7 @@ def test_one_coordsystem(self): cube = iris.tests.stock.lat_lon_cube() cube.coord('longitude').coord_system = None with self.assertRaises(ValueError): - iris.experimental.regrid._get_xy_dim_coords(cube) + get_xy_dim_coords(cube) def test_different_coordsystem(self): cube = iris.tests.stock.lat_lon_cube() @@ -121,7 +130,7 @@ def test_different_coordsystem(self): cube.coord('longitude').coord_system = lon_cs with self.assertRaises(ValueError): - iris.experimental.regrid._get_xy_dim_coords(cube) + get_xy_dim_coords(cube) if __name__ == "__main__": diff --git a/lib/iris/tests/unit/analysis/maths/__init__.py b/lib/iris/tests/unit/analysis/maths/__init__.py new file mode 100644 index 0000000000..c0c50cf88f --- /dev/null +++ b/lib/iris/tests/unit/analysis/maths/__init__.py @@ -0,0 +1,221 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.analysis.maths` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +from abc import ABCMeta, abstractproperty + +import numpy as np +from numpy import ma + +from iris.analysis import MEAN +from iris.coords import DimCoord +from iris.cube import Cube +import iris.tests as tests +import iris.tests.stock as stock +import iris.tests as tests + + +class CubeArithmeticBroadcastingTestMixin(six.with_metaclass(ABCMeta, object)): + # A framework for testing the broadcasting behaviour of the various cube + # arithmetic operations. (A test for each operation inherits this). + @abstractproperty + def data_op(self): + # Define an operator to be called, I.E. 'operator.xx'. + pass + + @abstractproperty + def cube_func(self): + # Define an iris arithmetic function to be called + # I.E. 'iris.analysis.maths.xx'. + pass + + def test_transposed(self): + cube = stock.realistic_4d_no_derived() + other = cube.copy() + other.transpose() + res = self.cube_func(cube, other) + self.assertCML(res, checksum=False) + expected_data = self.data_op(cube.data, other.data.T) + self.assertArrayEqual(res.data, expected_data) + + def test_collapse_zeroth_dim(self): + cube = stock.realistic_4d_no_derived() + other = cube.collapsed('time', MEAN) + res = self.cube_func(cube, other) + self.assertCML(res, checksum=False) + # No modification to other.data is needed as numpy broadcasting + # should be sufficient. + expected_data = self.data_op(cube.data, other.data) + # Use assertMaskedArrayEqual as collapsing with MEAN results + # in a cube with a masked data array. + self.assertMaskedArrayEqual(res.data, expected_data) + + def test_collapse_all_dims(self): + cube = stock.realistic_4d_no_derived() + other = cube.collapsed(cube.coords(dim_coords=True), MEAN) + res = self.cube_func(cube, other) + self.assertCML(res, checksum=False) + # No modification to other.data is needed as numpy broadcasting + # should be sufficient. + expected_data = self.data_op(cube.data, other.data) + # Use assertArrayEqual rather than assertMaskedArrayEqual as + # collapsing all dims does not result in a masked array. + self.assertArrayEqual(res.data, expected_data) + + def test_collapse_last_dims(self): + cube = stock.realistic_4d_no_derived() + other = cube.collapsed(['grid_latitude', 'grid_longitude'], MEAN) + res = self.cube_func(cube, other) + self.assertCML(res, checksum=False) + # Transpose the dimensions in self.cube that have been collapsed in + # other to lie at the front, thereby enabling numpy broadcasting to + # function when applying data operator. Finish by transposing back + # again to restore order. + expected_data = self.data_op(cube.data.transpose((2, 3, 0, 1)), + other.data).transpose(2, 3, 0, 1) + self.assertMaskedArrayEqual(res.data, expected_data) + + def test_collapse_middle_dim(self): + cube = stock.realistic_4d_no_derived() + other = cube.collapsed(['model_level_number'], MEAN) + res = self.cube_func(cube, other) + self.assertCML(res, checksum=False) + # Add the collapsed dimension back in via np.newaxis to enable + # numpy broadcasting to function. + expected_data = self.data_op(cube.data, + other.data[:, np.newaxis, ...]) + self.assertMaskedArrayEqual(res.data, expected_data) + + def test_slice(self): + cube = stock.realistic_4d_no_derived() + for dim in range(cube.ndim): + keys = [slice(None)] * cube.ndim + keys[dim] = 3 + other = cube[tuple(keys)] + res = self.cube_func(cube, other) + self.assertCML(res, checksum=False) + # Add the collapsed dimension back in via np.newaxis to enable + # numpy broadcasting to function. + keys[dim] = np.newaxis + expected_data = self.data_op(cube.data, + other.data[tuple(keys)]) + msg = 'Problem broadcasting cubes when sliced on dimension {}.' + self.assertArrayEqual(res.data, expected_data, + err_msg=msg.format(dim)) + + +class CubeArithmeticMaskingTestMixin(six.with_metaclass(ABCMeta, object)): + # A framework for testing the mask handling behaviour of the various cube + # arithmetic operations. (A test for each operation inherits this). + @abstractproperty + def data_op(self): + # Define an operator to be called, I.E. 'operator.xx'. + pass + + @abstractproperty + def cube_func(self): + # Define an iris arithmetic function to be called + # I.E. 'iris.analysis.maths.xx'. + pass + + def _test_partial_mask(self, in_place): + # Helper method for masked data tests. + dat_a = ma.array([2., 2., 2., 2.], mask=[1, 0, 1, 0]) + dat_b = ma.array([2., 2., 2., 2.], mask=[1, 1, 0, 0]) + + cube_a = Cube(dat_a) + cube_b = Cube(dat_b) + + com = self.data_op(dat_b, dat_a) + res = self.cube_func(cube_b, cube_a, in_place=in_place) + + return com, res, cube_b + + def test_partial_mask_in_place(self): + # Cube in_place arithmetic operation. + com, res, orig_cube = self._test_partial_mask(True) + + self.assertMaskedArrayEqual(com, res.data, strict=True) + self.assertIs(res, orig_cube) + + def test_partial_mask_not_in_place(self): + # Cube arithmetic not an in_place operation. + com, res, orig_cube = self._test_partial_mask(False) + + self.assertMaskedArrayEqual(com, res.data) + self.assertIsNot(res, orig_cube) + + +class CubeArithmeticCoordsTest(tests.IrisTest): + # This class sets up pairs of cubes to test iris' ability to reject + # arithmetic operations on coordinates which do not match. + def SetUpNonMatching(self): + # On this cube pair, the coordinates to perform operations on do not + # match in either points array or name. + data = np.zeros((3, 4)) + a = DimCoord([1, 2, 3], long_name='a') + b = DimCoord([1, 2, 3, 4], long_name='b') + x = DimCoord([4, 5, 6], long_name='x') + y = DimCoord([5, 6, 7, 8], long_name='y') + + nomatch1 = Cube(data, dim_coords_and_dims=[(a, 0), (b, 1)]) + nomatch2 = Cube(data, dim_coords_and_dims=[(x, 0), (y, 1)]) + + return nomatch1, nomatch2 + + def SetUpReversed(self): + # On this cube pair, the coordinates to perform operations on have + # matching long names but the points array on one cube is reversed + # with respect to that on the other. + data = np.zeros((3, 4)) + a1 = DimCoord([1, 2, 3], long_name='a') + b1 = DimCoord([1, 2, 3, 4], long_name='b') + a2 = DimCoord([3, 2, 1], long_name='a') + b2 = DimCoord([1, 2, 3, 4], long_name='b') + + reversed1 = Cube(data, dim_coords_and_dims=[(a1, 0), (b1, 1)]) + reversed2 = Cube(data, dim_coords_and_dims=[(a2, 0), (b2, 1)]) + + return reversed1, reversed2 + + +class CubeArithmeticMaskedConstantTestMixin( + six.with_metaclass(ABCMeta, object)): + + def test_masked_constant_in_place(self): + # Cube in_place arithmetic operation. + dtype = np.int64 + dat = ma.masked_array(0, 1, dtype) + cube = Cube(dat) + res = self.cube_func(cube, 5, in_place=True) + self.assertMaskedArrayEqual(ma.masked_array(0, 1), res.data) + self.assertEqual(dtype, res.dtype) + self.assertIs(res, cube) + + def test_masked_constant_not_in_place(self): + # Cube in_place arithmetic operation. + dtype = np.int64 + dat = ma.masked_array(0, 1, dtype) + cube = Cube(dat) + res = self.cube_func(cube, 5, in_place=False) + self.assertMaskedArrayEqual(ma.masked_array(0, 1), res.data) + self.assertEqual(dtype, res.dtype) + self.assertIsNot(res, cube) diff --git a/lib/iris/tests/unit/analysis/maths/test__get_dtype.py b/lib/iris/tests/unit/analysis/maths/test__get_dtype.py new file mode 100644 index 0000000000..f234f260f0 --- /dev/null +++ b/lib/iris/tests/unit/analysis/maths/test__get_dtype.py @@ -0,0 +1,112 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the function :func:`iris.analysis.maths._get_dtype`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np +from numpy import ma + +from iris.analysis.maths import _get_dtype +from iris.cube import Cube +from iris.coords import DimCoord, AuxCoord + + +class Test(tests.IrisTest): + def _check_call(self, obj, expected_dtype): + result = _get_dtype(obj) + self.assertEqual(expected_dtype, result) + + def test_int8(self): + n = -128 + self._check_call(n, np.int8) + + def test_int16(self): + n = -129 + self._check_call(n, np.int16) + + def test_uint8(self): + n = 255 + self._check_call(n, np.uint8) + + def test_uint16(self): + n = 256 + self._check_call(n, np.uint16) + + def test_float16(self): + n = 60000.0 + self._check_call(n, np.float16) + + def test_float32(self): + n = 65000.0 + self._check_call(n, np.float32) + + def test_float64(self): + n = 1e40 + self._check_call(n, np.float64) + + def test_scalar_demote(self): + n = np.int64(10) + self._check_call(n, np.uint8) + + def test_array(self): + a = np.array([1, 2, 3], dtype=np.int16) + self._check_call(a, np.int16) + + def test_scalar_array(self): + dtype = np.int32 + a = np.array(1, dtype=dtype) + self._check_call(a, dtype) + + def test_masked_array(self): + dtype = np.float16 + m = ma.masked_array([1, 2, 3], [1, 0, 1], dtype=dtype) + self._check_call(m, dtype) + + def test_masked_constant(self): + m = ma.masked + self._check_call(m, m.dtype) + + def test_cube(self): + dtype = np.float32 + data = np.array([1, 2, 3], dtype=dtype) + cube = Cube(data) + self._check_call(cube, dtype) + + def test_aux_coord(self): + dtype = np.int64 + points = np.array([1, 2, 3], dtype=dtype) + aux_coord = AuxCoord(points) + self._check_call(aux_coord, dtype) + + def test_dim_coord(self): + dtype = np.float16 + points = np.array([1, 2, 3], dtype=dtype) + dim_coord = DimCoord(points) + self._check_call(dim_coord, dtype) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/analysis/maths/test__inplace_common_checks.py b/lib/iris/tests/unit/analysis/maths/test__inplace_common_checks.py new file mode 100644 index 0000000000..a58de62277 --- /dev/null +++ b/lib/iris/tests/unit/analysis/maths/test__inplace_common_checks.py @@ -0,0 +1,156 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the function :func:`iris.analysis.maths._inplace_common_checks`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.cube import Cube +import numpy as np + +from iris.analysis.maths import _inplace_common_checks + + +class Test(tests.IrisTest): + # `_inplace_common_checks` is a pass-through function that does not return + # anything but will fail iff `cube` and `other` have integer dtype. Thus in + # a sense we only want to test the failing cases. Doing so, however, leaves + # us open to the case where currently known good cases fail silently. + # To avoid this all the known good cases are also tested by relying on the + # fact that functions with no return value implicitly return `None`. If + # these currently known good cases ever changed these tests would start + # failing and indicate something was wrong. + def setUp(self): + self.scalar_int = 5 + self.scalar_float = 5.5 + + self.float_data = np.array([8, 9], dtype=np.float64) + self.int_data = np.array([9, 8], dtype=np.int64) + self.uint_data = np.array([9, 8], dtype=np.uint64) + + self.float_cube = Cube(self.float_data) + self.int_cube = Cube(self.int_data) + self.uint_cube = Cube(self.uint_data) + + self.op = 'addition' + self.emsg = 'Cannot perform inplace {}'.format(self.op) + + def test_float_cubes(self): + result = _inplace_common_checks(self.float_cube, self.float_cube, + self.op) + self.assertIsNone(result) + + def test_int_cubes(self): + result = _inplace_common_checks(self.int_cube, self.int_cube, self.op) + self.assertIsNone(result) + + def test_uint_cubes(self): + result = _inplace_common_checks(self.uint_cube, self.uint_cube, + self.op) + self.assertIsNone(result) + + def test_float_cube_int_cube(self): + result = _inplace_common_checks(self.float_cube, self.int_cube, + self.op) + self.assertIsNone(result) + + def test_float_cube_uint_cube(self): + result = _inplace_common_checks(self.float_cube, self.uint_cube, + self.op) + self.assertIsNone(result) + + def test_int_cube_float_cube(self): + with self.assertRaisesRegexp(ArithmeticError, self.emsg): + _inplace_common_checks(self.int_cube, self.float_cube, self.op) + + def test_uint_cube_float_cube(self): + with self.assertRaisesRegexp(ArithmeticError, self.emsg): + _inplace_common_checks(self.uint_cube, self.float_cube, self.op) + + def test_float_cube__scalar_int(self): + result = _inplace_common_checks(self.float_cube, self.scalar_int, + self.op) + self.assertIsNone(result) + + def test_float_cube__scalar_float(self): + result = _inplace_common_checks(self.float_cube, self.scalar_float, + self.op) + self.assertIsNone(result) + + def test_float_cube__int_array(self): + result = _inplace_common_checks(self.float_cube, self.int_data, + self.op) + self.assertIsNone(result) + + def test_float_cube__float_array(self): + result = _inplace_common_checks(self.float_cube, self.float_data, + self.op) + self.assertIsNone(result) + + def test_int_cube__scalar_int(self): + result = _inplace_common_checks(self.int_cube, self.scalar_int, + self.op) + self.assertIsNone(result) + + def test_int_cube_uint_cube(self): + result = _inplace_common_checks(self.int_cube, self.uint_cube, + self.op) + self.assertIsNone(result) + + def test_uint_cube_uint_cube(self): + result = _inplace_common_checks(self.uint_cube, self.uint_cube, + self.op) + self.assertIsNone(result) + + def test_uint_cube_int_cube(self): + with self.assertRaisesRegexp(ArithmeticError, self.emsg): + _inplace_common_checks(self.uint_cube, self.int_cube, self.op) + + def test_int_cube__scalar_float(self): + with self.assertRaisesRegexp(ArithmeticError, self.emsg): + _inplace_common_checks(self.int_cube, self.scalar_float, self.op) + + def test_int_cube__int_array(self): + result = _inplace_common_checks(self.int_cube, self.int_cube, self.op) + self.assertIsNone(result) + + def test_int_cube__float_array(self): + with self.assertRaisesRegexp(ArithmeticError, self.emsg): + _inplace_common_checks(self.int_cube, self.float_data, self.op) + + def test_uint_cube__scalar_float(self): + with self.assertRaisesRegexp(ArithmeticError, self.emsg): + _inplace_common_checks(self.uint_cube, self.scalar_float, self.op) + + def test_uint_cube__int_array(self): + with self.assertRaisesRegexp(ArithmeticError, self.emsg): + _inplace_common_checks(self.uint_cube, self.int_cube, self.op) + + def test_uint_cube__float_array(self): + with self.assertRaisesRegexp(ArithmeticError, self.emsg): + _inplace_common_checks(self.uint_cube, self.float_data, self.op) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/maths/test__output_dtype.py b/lib/iris/tests/unit/analysis/maths/test__output_dtype.py new file mode 100644 index 0000000000..8a6823b042 --- /dev/null +++ b/lib/iris/tests/unit/analysis/maths/test__output_dtype.py @@ -0,0 +1,195 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the function :func:`iris.analysis.maths._output_dtype`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from itertools import product +import operator + +import numpy as np + +from iris.analysis.maths import _output_dtype + + +class Test(tests.IrisTest): + def setUp(self): + # Operators which result in a value of the same dtype as their + # arguments when the arguments' dtypes are the same. + self.same_result_ops = [operator.add, + operator.sub, + operator.mul, + operator.pow, + operator.floordiv, + np.add, + np.subtract, + np.multiply, + np.power, + np.floor_divide] + try: + self.same_result_ops.append(operator.div) + except AttributeError: + # operator.div doesn't exist in Python 3 + pass + + self.unary_same_result_ops = [np.abs] + + # Operators which always result in a float. + self.float_ops = [operator.truediv, + np.true_divide] + + self.unary_float_ops = [np.log, + np.log2, + np.log10, + np.exp] + + self.all_binary_ops = self.same_result_ops + self.float_ops + self.all_unary_ops = self.unary_same_result_ops + self.unary_float_ops + + self.dtypes = [np.dtype('i2'), np.dtype('i4'), np.dtype('i8'), + np.dtype('f2'), np.dtype('f4'), np.dtype('f8')] + + def _binary_error_message(self, op, first_dtype, second_dtype, + expected_dtype, result_dtype, in_place=False): + msg = "Output for {op.__class__.__name__} {op.__name__!r} and " \ + "arguments ({dt1!r}, {dt2!r}, in_place={in_place}) " \ + "was {res!r}. Expected {exp!r}." + return msg.format(op=op, dt1=first_dtype, dt2=second_dtype, + exp=expected_dtype, res=result_dtype, + in_place=in_place) + + def _unary_error_message(self, op, dtype, expected_dtype, result_dtype, + in_place=False): + msg = "Output for {op.__class__.__name__} {op.__name__!r} and " \ + "arguments ({dt!r}, in_place={in_place}) was {res!r}. " \ + "Expected {exp!r}." + return msg.format(op=op, dt=dtype, + exp=expected_dtype, res=result_dtype, + in_place=in_place) + + def test_same_result(self): + # Check that the result dtype is the same as the input dtypes for + # relevant operators. + for dtype in self.dtypes: + for op in self.same_result_ops: + result_dtype = _output_dtype(op, dtype, dtype) + self.assertEqual(dtype, result_dtype, + self._binary_error_message(op, dtype, dtype, + dtype, + result_dtype)) + for op in self.unary_same_result_ops: + result_dtype = _output_dtype(op, dtype) + self.assertEqual(dtype, result_dtype, + self._unary_error_message(op, dtype, dtype, + result_dtype)) + + def test_binary_float(self): + # Check that the result dtype is a float for relevant operators. + # Perform checks for a selection of cases. + cases = [(np.dtype('i2'), np.dtype('i2'), np.dtype('f8')), + (np.dtype('i2'), np.dtype('i4'), np.dtype('f8')), + (np.dtype('i4'), np.dtype('i4'), np.dtype('f8')), + (np.dtype('i2'), np.dtype('f2'), np.dtype('f4')), + (np.dtype('i2'), np.dtype('f4'), np.dtype('f4')), + (np.dtype('i8'), np.dtype('f2'), np.dtype('f8')), + (np.dtype('f2'), np.dtype('f2'), np.dtype('f2')), + (np.dtype('f4'), np.dtype('f4'), np.dtype('f4')), + (np.dtype('f2'), np.dtype('f4'), np.dtype('f4'))] + for dtype1, dtype2, expected_dtype in cases: + for op in self.float_ops: + result_dtype = _output_dtype(op, dtype1, dtype2) + self.assertEqual(expected_dtype, result_dtype, + self._binary_error_message(op, dtype1, dtype2, + expected_dtype, + result_dtype)) + + def test_unary_float(self): + cases = [(np.dtype('i2'), np.dtype('f4')), + (np.dtype('i4'), np.dtype('f8')), + (np.dtype('i8'), np.dtype('f8')), + (np.dtype('f2'), np.dtype('f2')), + (np.dtype('f4'), np.dtype('f4')), + (np.dtype('f8'), np.dtype('f8'))] + for dtype, expected_dtype in cases: + for op in self.unary_float_ops: + result_dtype = _output_dtype(op, dtype) + self.assertEqual(expected_dtype, result_dtype, + self._unary_error_message(op, dtype, + expected_dtype, + result_dtype)) + + def test_binary_float_argument(self): + # Check that when one argument is a float dtype, a float dtype results + # Unary operators are covered by other tests. + dtypes = [np.dtype('i2'), np.dtype('i4'), np.dtype('i8'), + np.dtype('f2'), np.dtype('f4'), np.dtype('f8')] + expected_dtypes = [np.dtype('f4'), np.dtype('f8'), np.dtype('f8'), + np.dtype('f2'), np.dtype('f4'), np.dtype('f8')] + for op in self.all_binary_ops: + for dtype, expected_dtype in zip(dtypes, expected_dtypes): + result_dtype = _output_dtype(op, dtype, np.dtype('f2')) + self.assertEqual(expected_dtype, result_dtype, + self._binary_error_message(op, dtype, + np.dtype('f2'), + expected_dtype, + result_dtype)) + + def test_in_place(self): + # Check that when the in_place argument is True, the result is always + # the same as first operand. + for dtype1, dtype2 in product(self.dtypes, self.dtypes): + for op in self.all_binary_ops: + result_dtype = _output_dtype(op, dtype1, dtype2, in_place=True) + self.assertEqual(result_dtype, dtype1, + self._binary_error_message(op, dtype1, dtype2, + dtype1, + result_dtype, + in_place=True)) + for dtype in self.dtypes: + for op in self.all_unary_ops: + result_dtype = _output_dtype(op, dtype, in_place=True) + self.assertEqual(result_dtype, dtype, + self._unary_error_message(op, dtype, dtype, + result_dtype, + in_place=True)) + + def test_commuative(self): + # Check that the operation is commutative if in_place is not specified. + for dtype1, dtype2 in product(self.dtypes, self.dtypes): + for op in self.all_binary_ops: + result_dtype1 = _output_dtype(op, dtype1, dtype2) + result_dtype2 = _output_dtype(op, dtype2, dtype1) + self.assertEqual( + result_dtype1, + result_dtype2, + "_output_dtype is not commutative with arguments " + "{!r} and {!r}: {!r} != {!r}".format(dtype1, + dtype2, + result_dtype1, + result_dtype2)) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/analysis/maths/test_add.py b/lib/iris/tests/unit/analysis/maths/test_add.py new file mode 100644 index 0000000000..29b4d06d63 --- /dev/null +++ b/lib/iris/tests/unit/analysis/maths/test_add.py @@ -0,0 +1,83 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :func:`iris.analysis.maths.add` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import operator + +from iris.analysis.maths import add +from iris.tests.unit.analysis.maths import \ + CubeArithmeticBroadcastingTestMixin, CubeArithmeticCoordsTest, \ + CubeArithmeticMaskedConstantTestMixin, CubeArithmeticMaskingTestMixin + + +@tests.skip_data +@tests.iristest_timing_decorator +class TestBroadcasting(tests.IrisTest_nometa, + CubeArithmeticBroadcastingTestMixin): + @property + def data_op(self): + return operator.add + + @property + def cube_func(self): + return add + + +@tests.iristest_timing_decorator +class TestMasking(tests.IrisTest_nometa, CubeArithmeticMaskingTestMixin): + @property + def data_op(self): + return operator.add + + @property + def cube_func(self): + return add + + +class TestCoordMatch(CubeArithmeticCoordsTest): + def test_no_match(self): + cube1, cube2 = self.SetUpNonMatching() + with self.assertRaises(ValueError): + add(cube1, cube2) + + def test_reversed_points(self): + cube1, cube2 = self.SetUpReversed() + with self.assertRaises(ValueError): + add(cube1, cube2) + + +@tests.iristest_timing_decorator +class TestMaskedConstant(tests.IrisTest_nometa, + CubeArithmeticMaskedConstantTestMixin): + @property + def data_op(self): + return operator.add + + @property + def cube_func(self): + return add + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/maths/test_divide.py b/lib/iris/tests/unit/analysis/maths/test_divide.py new file mode 100644 index 0000000000..f5d2c5b732 --- /dev/null +++ b/lib/iris/tests/unit/analysis/maths/test_divide.py @@ -0,0 +1,107 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :func:`iris.analysis.maths.divide` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np +import operator + +from iris.analysis.maths import divide +from iris.cube import Cube +from iris.tests.unit.analysis.maths import \ + CubeArithmeticBroadcastingTestMixin, CubeArithmeticMaskingTestMixin, \ + CubeArithmeticCoordsTest + + +@tests.skip_data +@tests.iristest_timing_decorator +class TestBroadcasting(tests.IrisTest_nometa, + CubeArithmeticBroadcastingTestMixin): + @property + def data_op(self): + try: + return operator.div + except AttributeError: + return operator.truediv + + @property + def cube_func(self): + return divide + + +@tests.iristest_timing_decorator +class TestMasking(tests.IrisTest_nometa, CubeArithmeticMaskingTestMixin): + @property + def data_op(self): + try: + return operator.div + except AttributeError: + return operator.truediv + + @property + def cube_func(self): + return divide + + def test_unmasked_div_zero(self): + # Ensure cube behaviour matches numpy operator behaviour for the + # handling of arrays containing 0. + dat_a = np.array([0., 0., 0., 0.]) + dat_b = np.array([2., 2., 2., 2.]) + + cube_a = Cube(dat_a) + cube_b = Cube(dat_b) + + com = self.data_op(dat_b, dat_a) + res = self.cube_func(cube_b, cube_a).data + + self.assertArrayEqual(com, res) + + def test_masked_div_zero(self): + # Ensure cube behaviour matches numpy operator behaviour for the + # handling of arrays containing 0. + dat_a = np.ma.array([0., 0., 0., 0.], mask=False) + dat_b = np.ma.array([2., 2., 2., 2.], mask=False) + + cube_a = Cube(dat_a) + cube_b = Cube(dat_b) + + com = self.data_op(dat_b, dat_a) + res = self.cube_func(cube_b, cube_a).data + + self.assertMaskedArrayEqual(com, res, strict=True) + + +class TestCoordMatch(CubeArithmeticCoordsTest): + def test_no_match(self): + cube1, cube2 = self.SetUpNonMatching() + with self.assertRaises(ValueError): + divide(cube1, cube2) + + def test_reversed_points(self): + cube1, cube2 = self.SetUpReversed() + with self.assertRaises(ValueError): + divide(cube1, cube2) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/maths/test_multiply.py b/lib/iris/tests/unit/analysis/maths/test_multiply.py new file mode 100644 index 0000000000..0a754ea467 --- /dev/null +++ b/lib/iris/tests/unit/analysis/maths/test_multiply.py @@ -0,0 +1,83 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :func:`iris.analysis.maths.multiply` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import operator + +from iris.analysis.maths import multiply +from iris.tests.unit.analysis.maths import \ + CubeArithmeticBroadcastingTestMixin, CubeArithmeticCoordsTest, \ + CubeArithmeticMaskedConstantTestMixin, CubeArithmeticMaskingTestMixin + + +@tests.skip_data +@tests.iristest_timing_decorator +class TestBroadcasting(tests.IrisTest_nometa, + CubeArithmeticBroadcastingTestMixin): + @property + def data_op(self): + return operator.mul + + @property + def cube_func(self): + return multiply + + +@tests.iristest_timing_decorator +class TestMasking(tests.IrisTest_nometa, CubeArithmeticMaskingTestMixin): + @property + def data_op(self): + return operator.mul + + @property + def cube_func(self): + return multiply + + +class TestCoordMatch(CubeArithmeticCoordsTest): + def test_no_match(self): + cube1, cube2 = self.SetUpNonMatching() + with self.assertRaises(ValueError): + multiply(cube1, cube2) + + def test_reversed_points(self): + cube1, cube2 = self.SetUpReversed() + with self.assertRaises(ValueError): + multiply(cube1, cube2) + + +@tests.iristest_timing_decorator +class TestMaskedConstant(tests.IrisTest_nometa, + CubeArithmeticMaskedConstantTestMixin): + @property + def data_op(self): + return operator.mul + + @property + def cube_func(self): + return multiply + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/maths/test_subtract.py b/lib/iris/tests/unit/analysis/maths/test_subtract.py new file mode 100644 index 0000000000..7ca1ee7ca0 --- /dev/null +++ b/lib/iris/tests/unit/analysis/maths/test_subtract.py @@ -0,0 +1,83 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :func:`iris.analysis.maths.subtract` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import operator + +from iris.analysis.maths import subtract +from iris.tests.unit.analysis.maths import \ + CubeArithmeticBroadcastingTestMixin, CubeArithmeticCoordsTest, \ + CubeArithmeticMaskedConstantTestMixin, CubeArithmeticMaskingTestMixin + + +@tests.skip_data +@tests.iristest_timing_decorator +class TestBroadcasting(tests.IrisTest_nometa, + CubeArithmeticBroadcastingTestMixin): + @property + def data_op(self): + return operator.sub + + @property + def cube_func(self): + return subtract + + +@tests.iristest_timing_decorator +class TestMasking(tests.IrisTest_nometa, CubeArithmeticMaskingTestMixin): + @property + def data_op(self): + return operator.sub + + @property + def cube_func(self): + return subtract + + +class TestCoordMatch(CubeArithmeticCoordsTest): + def test_no_match(self): + cube1, cube2 = self.SetUpNonMatching() + with self.assertRaises(ValueError): + subtract(cube1, cube2) + + def test_reversed_points(self): + cube1, cube2 = self.SetUpReversed() + with self.assertRaises(ValueError): + subtract(cube1, cube2) + + +@tests.iristest_timing_decorator +class TestMaskedConstant(tests.IrisTest_nometa, + CubeArithmeticMaskedConstantTestMixin): + @property + def data_op(self): + return operator.sub + + @property + def cube_func(self): + return subtract + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/regrid/__init__.py b/lib/iris/tests/unit/analysis/regrid/__init__.py new file mode 100644 index 0000000000..6d2062c278 --- /dev/null +++ b/lib/iris/tests/unit/analysis/regrid/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.analysis._regrid` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/analysis/regrid/test_RectilinearRegridder.py b/lib/iris/tests/unit/analysis/regrid/test_RectilinearRegridder.py new file mode 100644 index 0000000000..6035630aae --- /dev/null +++ b/lib/iris/tests/unit/analysis/regrid/test_RectilinearRegridder.py @@ -0,0 +1,1379 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for :class:`iris.analysis._regrid.RectilinearRegridder`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np +import numpy.ma as ma + +from iris.analysis._regrid import RectilinearRegridder as Regridder +from iris.aux_factory import HybridHeightFactory +from iris.coord_systems import GeogCS, OSGB +from iris.coords import AuxCoord, DimCoord +from iris.cube import Cube +from iris.tests import mock +from iris.tests.stock import global_pp, lat_lon_cube, realistic_4d + + +RESULT_DIR = ('analysis', 'regrid') + +# Convenience to access Regridder static method. +regrid = Regridder._regrid + + +class Test__regrid__linear(tests.IrisTest): + def setUp(self): + self.x = DimCoord(np.linspace(-2, 57, 60)) + self.y = DimCoord(np.linspace(0, 49, 50)) + self.xs, self.ys = np.meshgrid(self.x.points, self.y.points) + + def transformation(x, y): + return x + y ** 2 + + # Construct a function which adds dimensions to the 2D data array + # so that we can test higher dimensional functionality. + def dim_extender(arr): + return arr[np.newaxis, ..., np.newaxis] * [1, 2] + + self.data = dim_extender(transformation(self.xs, self.ys)) + + target_x = np.linspace(-3, 60, 4) + target_y = np.linspace(0.5, 51, 3) + self.target_x, self.target_y = np.meshgrid(target_x, target_y) + + #: Expected values, which not quite the analytical value, but + #: representative of the bilinear interpolation scheme. + self.expected = np.array([[[[np.nan, np.nan], + [18.5, 37.], + [39.5, 79.], + [np.nan, np.nan]], + [[np.nan, np.nan], + [681.25, 1362.5], + [702.25, 1404.5], + [np.nan, np.nan]], + [[np.nan, np.nan], + [np.nan, np.nan], + [np.nan, np.nan], + [np.nan, np.nan]]]]) + + self.x_dim = 2 + self.y_dim = 1 + + def assert_values(self, values): + # values is a list of [x, y, [val1, val2]] + xs, ys, expecteds = zip(*values) + expecteds = np.array(expecteds)[None, None, ...] + result = regrid(self.data, self.x_dim, self.y_dim, + self.x, self.y, + np.array([xs]), np.array([ys])) + self.assertArrayAllClose(result, expecteds, rtol=1e-04, + equal_nan=True) + + # Check that transposing the input data results in the same values + ndim = self.data.ndim + result2 = regrid(self.data.T, ndim - self.x_dim - 1, + ndim - self.y_dim - 1, + self.x, self.y, + np.array([xs]), np.array([ys])) + self.assertArrayEqual(result.T, result2) + + def test_single_values(self): + # Check that the values are sensible e.g. (3 + 4**2 == 19) + self.assert_values([[3, 4, [19, 38]], + [-2, 0, [-2, -4]], + [-2.01, 0, [np.nan, np.nan]], + [2, -0.01, [np.nan, np.nan]], + [57, 0, [57, 114]], + [57.01, 0, [np.nan, np.nan]], + [57, 49, [2458, 4916]], + [57, 49.01, [np.nan, np.nan]]]) + + def test_simple_result(self): + result = regrid(self.data, self.x_dim, self.y_dim, + self.x, self.y, + self.target_x, self.target_y) + self.assertArrayEqual(result, self.expected) + + def test_simple_masked(self): + data = ma.MaskedArray(self.data, mask=True) + data.mask[:, 1:30, 1:30] = False + result = regrid(data, self.x_dim, self.y_dim, + self.x, self.y, + self.target_x, self.target_y) + expected_mask = np.array([[[[True, True], [True, True], + [True, True], [True, True]], + [[True, True], [False, False], + [True, True], [True, True]], + [[True, True], [True, True], + [True, True], [True, True]]]], dtype=bool) + expected = ma.MaskedArray(self.expected, + mask=expected_mask) + self.assertMaskedArrayEqual(result, expected) + + def test_simple_masked_no_mask(self): + data = ma.MaskedArray(self.data, mask=False) + result = regrid(data, self.x_dim, self.y_dim, + self.x, self.y, + self.target_x, self.target_y) + self.assertIsInstance(result, ma.MaskedArray) + + def test_result_transpose_shape(self): + ndim = self.data.ndim + result = regrid(self.data.T, ndim - self.x_dim - 1, + ndim - self.y_dim - 1, self.x, self.y, + self.target_x, self.target_y) + self.assertArrayEqual(result, self.expected.T) + + def test_reverse_x_coord(self): + index = [slice(None)] * self.data.ndim + index[self.x_dim] = slice(None, None, -1) + result = regrid(self.data[index], self.x_dim, + self.y_dim, self.x[::-1], self.y, + self.target_x, self.target_y) + self.assertArrayEqual(result, self.expected) + + def test_circular_x_coord(self): + # Check that interpolation of a circular src coordinate doesn't result + # in an out of bounds value. + self.x.circular = True + self.x.units = 'degree' + result = regrid(self.data, self.x_dim, self.y_dim, + self.x, self.y, np.array([[58]]), + np.array([[0]])) + self.assertArrayAlmostEqual(result, + np.array([56.80398671, 113.60797342], + ndmin=self.data.ndim)) + + +# Check what happens to NaN values, extrapolated values, and +# masked values. +class Test__regrid__extrapolation_modes(tests.IrisTest): + values_by_method = {'linear': [[np.nan, np.nan, 2, 3, np.nan], + [np.nan, np.nan, 6, 7, np.nan], + [8, 9, 10, 11, np.nan]], + 'nearest': [[np.nan, 1, 2, 3, np.nan], + [4, 5, 6, 7, np.nan], + [8, 9, 10, 11, np.nan]]} + + extrapolate_values_by_method = {'linear': [[np.nan, np.nan, 2, 3, 4], + [np.nan, np.nan, 6, 7, 8], + [8, 9, 10, 11, 12]], + 'nearest': [[np.nan, 1, 2, 3, 3], + [4, 5, 6, 7, 7], + [8, 9, 10, 11, 11]]} + + def setUp(self): + self.methods = ('linear', 'nearest') + self.test_dtypes = [np.dtype(spec) + for spec in ('i1', 'i2', 'i4', 'i8', + 'f2', 'f4', 'f8')] + + def _regrid(self, data, method, extrapolation_mode=None): + x = np.arange(4) + y = np.arange(3) + x_coord = DimCoord(x) + y_coord = DimCoord(y) + x_dim, y_dim = 1, 0 + grid_x, grid_y = np.meshgrid(np.arange(5), y) + kwargs = dict(method=method) + if extrapolation_mode is not None: + kwargs['extrapolation_mode'] = extrapolation_mode + result = regrid(data, x_dim, y_dim, x_coord, y_coord, + grid_x, grid_y, **kwargs) + return result + + def test_default_ndarray(self): + # NaN -> NaN + # Extrapolated -> NaN + data = np.arange(12, dtype=np.float).reshape(3, 4) + data[0, 0] = np.nan + for method in self.methods: + result = self._regrid(data, method) + self.assertNotIsInstance(result, ma.MaskedArray) + expected = self.values_by_method[method] + self.assertArrayEqual(result, expected) + + def test_default_maskedarray(self): + # NaN -> NaN + # Extrapolated -> Masked + # Masked -> Masked + data = ma.arange(12, dtype=np.float).reshape(3, 4) + data[0, 0] = np.nan + data[2, 3] = ma.masked + for method in self.methods: + result = self._regrid(data, method) + self.assertIsInstance(result, ma.MaskedArray) + mask = [[0, 0, 0, 0, 1], + [0, 0, 0, 0, 1], + [0, 0, 0, 1, 1]] + values = self.values_by_method[method] + expected = ma.MaskedArray(values, mask) + self.assertMaskedArrayEqual(result, expected) + + def test_default_maskedarray_none_masked(self): + # NaN -> NaN + # Extrapolated -> Masked + # Masked -> N/A + data = ma.arange(12, dtype=np.float).reshape(3, 4) + data[0, 0] = np.nan + for method in self.methods: + result = self._regrid(data, method) + self.assertIsInstance(result, ma.MaskedArray) + mask = [[0, 0, 0, 0, 1], + [0, 0, 0, 0, 1], + [0, 0, 0, 0, 1]] + values = self.values_by_method[method] + expected = ma.MaskedArray(values, mask) + self.assertMaskedArrayEqual(result, expected) + + def test_default_maskedarray_none_masked_expanded(self): + # NaN -> NaN + # Extrapolated -> Masked + # Masked -> N/A + data = ma.arange(12, dtype=np.float).reshape(3, 4) + # Make sure the mask has been expanded + data.mask = False + data[0, 0] = np.nan + for method in self.methods: + result = self._regrid(data, method) + self.assertIsInstance(result, ma.MaskedArray) + mask = [[0, 0, 0, 0, 1], + [0, 0, 0, 0, 1], + [0, 0, 0, 0, 1]] + values = self.values_by_method[method] + expected = ma.MaskedArray(values, mask) + self.assertMaskedArrayEqual(result, expected) + + def test_method_ndarray(self): + # NaN -> NaN + # Extrapolated -> linear + data = np.arange(12, dtype=np.float).reshape(3, 4) + data[0, 0] = np.nan + for method in self.methods: + result = self._regrid(data, method, 'extrapolate') + self.assertNotIsInstance(result, ma.MaskedArray) + expected = self.extrapolate_values_by_method[method] + self.assertArrayEqual(result, expected) + + def test_method_maskedarray(self): + # NaN -> NaN + # Extrapolated -> linear + # Masked -> Masked + data = ma.arange(12, dtype=np.float).reshape(3, 4) + data[0, 0] = np.nan + data[2, 3] = ma.masked + for method in self.methods: + result = self._regrid(data, method, 'extrapolate') + self.assertIsInstance(result, ma.MaskedArray) + mask = [[0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 1, 1]] + values = self.extrapolate_values_by_method[method] + expected = ma.MaskedArray(values, mask) + self.assertMaskedArrayEqual(result, expected) + + def test_nan_ndarray(self): + # NaN -> NaN + # Extrapolated -> NaN + data = np.arange(12, dtype=np.float).reshape(3, 4) + data[0, 0] = np.nan + for method in self.methods: + result = self._regrid(data, method, 'nan') + self.assertNotIsInstance(result, ma.MaskedArray) + expected = self.values_by_method[method] + self.assertArrayEqual(result, expected) + + def test_nan_maskedarray(self): + # NaN -> NaN + # Extrapolated -> NaN + # Masked -> Masked + data = ma.arange(12, dtype=np.float).reshape(3, 4) + data[0, 0] = np.nan + data[2, 3] = ma.masked + for method in self.methods: + result = self._regrid(data, method, 'nan') + self.assertIsInstance(result, ma.MaskedArray) + mask = [[0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 1, 0]] + values = self.values_by_method[method] + expected = ma.MaskedArray(values, mask) + self.assertMaskedArrayEqual(result, expected) + + def test_error_ndarray(self): + # Values irrelevant - the function raises an error. + data = np.arange(12, dtype=np.float).reshape(3, 4) + data[0, 0] = np.nan + for method in self.methods: + with self.assertRaisesRegexp(ValueError, 'out of bounds'): + self._regrid(data, method, 'error') + + def test_error_maskedarray(self): + # Values irrelevant - the function raises an error. + data = ma.arange(12, dtype=np.float).reshape(3, 4) + data[0, 0] = np.nan + data[2, 3] = ma.masked + for method in self.methods: + with self.assertRaisesRegexp(ValueError, 'out of bounds'): + self._regrid(data, method, 'error') + + def test_mask_ndarray(self): + # NaN -> NaN + # Extrapolated -> Masked (this is different from all the other + # modes) + data = np.arange(12, dtype=np.float).reshape(3, 4) + data[0, 0] = np.nan + for method in self.methods: + result = self._regrid(data, method, 'mask') + self.assertIsInstance(result, ma.MaskedArray) + mask = [[0, 0, 0, 0, 1], + [0, 0, 0, 0, 1], + [0, 0, 0, 0, 1]] + values = self.values_by_method[method] + expected = ma.MaskedArray(values, mask) + self.assertMaskedArrayEqual(result, expected) + + def test_mask_maskedarray(self): + # NaN -> NaN + # Extrapolated -> Masked + # Masked -> Masked + data = ma.arange(12, dtype=np.float).reshape(3, 4) + data[0, 0] = np.nan + data[2, 3] = ma.masked + for method in self.methods: + result = self._regrid(data, method, 'mask') + self.assertIsInstance(result, ma.MaskedArray) + mask = [[0, 0, 0, 0, 1], + [0, 0, 0, 0, 1], + [0, 0, 0, 1, 1]] + values = self.values_by_method[method] + expected = ma.MaskedArray(values, mask) + self.assertMaskedArrayEqual(result, expected) + + def test_nanmask_ndarray(self): + # NaN -> NaN + # Extrapolated -> NaN + data = np.arange(12, dtype=np.float).reshape(3, 4) + data[0, 0] = np.nan + for method in self.methods: + result = self._regrid(data, method, 'nanmask') + self.assertNotIsInstance(result, ma.MaskedArray) + expected = self.values_by_method[method] + self.assertArrayEqual(result, expected) + + def test_nanmask_maskedarray(self): + # NaN -> NaN + # Extrapolated -> Masked + # Masked -> Masked + data = ma.arange(12, dtype=np.float).reshape(3, 4) + data[0, 0] = np.nan + data[2, 3] = ma.masked + for method in self.methods: + result = self._regrid(data, method, 'nanmask') + self.assertIsInstance(result, ma.MaskedArray) + mask = [[0, 0, 0, 0, 1], + [0, 0, 0, 0, 1], + [0, 0, 0, 1, 1]] + values = self.values_by_method[method] + expected = ma.MaskedArray(values, mask) + self.assertMaskedArrayEqual(result, expected) + + def test_invalid(self): + data = np.arange(12, dtype=np.float).reshape(3, 4) + emsg = 'Invalid extrapolation mode' + for method in self.methods: + with self.assertRaisesRegexp(ValueError, emsg): + self._regrid(data, method, 'BOGUS') + + def test_method_result_types(self): + # Check return types from basic calculation on floats and ints. + for method in self.methods: + result_dtypes = {} + for source_dtype in self.test_dtypes: + data = np.arange(12, dtype=source_dtype).reshape(3, 4) + result = self._regrid(data, method) + result_dtypes[source_dtype] = result.dtype + if method == 'linear': + # Linear results are promoted to float. + expected_types_mapping = { + test_dtype: np.promote_types(test_dtype, np.float16) + for test_dtype in self.test_dtypes} + if method == 'nearest': + # Nearest results are the same as the original data. + expected_types_mapping = {test_dtype: test_dtype + for test_dtype in self.test_dtypes} + self.assertEqual(result_dtypes, expected_types_mapping) + + +class Test___call____invalid_types(tests.IrisTest): + def setUp(self): + self.cube = lat_lon_cube() + # Regridder method and extrapolation-mode. + self.args = ('linear', 'mask') + self.regridder = Regridder(self.cube, self.cube, *self.args) + + def test_src_as_array(self): + arr = np.zeros((3, 4)) + with self.assertRaises(TypeError): + Regridder(arr, self.cube, *self.args) + with self.assertRaises(TypeError): + self.regridder(arr) + + def test_grid_as_array(self): + with self.assertRaises(TypeError): + Regridder(self.cube, np.zeros((3, 4)), *self.args) + + def test_src_as_int(self): + with self.assertRaises(TypeError): + Regridder(42, self.cube, *self.args) + with self.assertRaises(TypeError): + self.regridder(42) + + def test_grid_as_int(self): + with self.assertRaises(TypeError): + Regridder(self.cube, 42, *self.args) + + +class Test___call____missing_coords(tests.IrisTest): + def setUp(self): + self.args = ('linear', 'mask') + + def ok_bad(self, coord_names): + # Deletes the named coords from `bad`. + ok = lat_lon_cube() + bad = lat_lon_cube() + for name in coord_names: + bad.remove_coord(name) + return ok, bad + + def test_src_missing_lat(self): + ok, bad = self.ok_bad(['latitude']) + with self.assertRaises(ValueError): + Regridder(bad, ok, *self.args) + regridder = Regridder(ok, ok, *self.args) + with self.assertRaises(ValueError): + regridder(bad) + + def test_grid_missing_lat(self): + ok, bad = self.ok_bad(['latitude']) + with self.assertRaises(ValueError): + Regridder(ok, bad, *self.args) + + def test_src_missing_lon(self): + ok, bad = self.ok_bad(['longitude']) + with self.assertRaises(ValueError): + Regridder(bad, ok, *self.args) + regridder = Regridder(ok, ok, *self.args) + with self.assertRaises(ValueError): + regridder(bad) + + def test_grid_missing_lon(self): + ok, bad = self.ok_bad(['longitude']) + with self.assertRaises(ValueError): + Regridder(ok, bad, *self.args) + + def test_src_missing_lat_lon(self): + ok, bad = self.ok_bad(['latitude', 'longitude']) + with self.assertRaises(ValueError): + Regridder(bad, ok, *self.args) + regridder = Regridder(ok, ok, *self.args) + with self.assertRaises(ValueError): + regridder(bad) + + def test_grid_missing_lat_lon(self): + ok, bad = self.ok_bad(['latitude', 'longitude']) + with self.assertRaises(ValueError): + Regridder(ok, bad, *self.args) + + +class Test___call____not_dim_coord(tests.IrisTest): + def setUp(self): + self.args = ('linear', 'mask') + + def ok_bad(self, coord_name): + # Demotes the named DimCoord on `bad` to an AuxCoord. + ok = lat_lon_cube() + bad = lat_lon_cube() + coord = bad.coord(coord_name) + dims = bad.coord_dims(coord) + bad.remove_coord(coord_name) + aux_coord = AuxCoord.from_coord(coord) + bad.add_aux_coord(aux_coord, dims) + return ok, bad + + def test_src_with_aux_lat(self): + ok, bad = self.ok_bad('latitude') + with self.assertRaises(ValueError): + Regridder(bad, ok, *self.args) + regridder = Regridder(ok, ok, *self.args) + with self.assertRaises(ValueError): + regridder(bad) + + def test_grid_with_aux_lat(self): + ok, bad = self.ok_bad('latitude') + with self.assertRaises(ValueError): + Regridder(ok, bad, *self.args) + + def test_src_with_aux_lon(self): + ok, bad = self.ok_bad('longitude') + with self.assertRaises(ValueError): + Regridder(bad, ok, *self.args) + regridder = Regridder(ok, ok, *self.args) + with self.assertRaises(ValueError): + regridder(bad) + + def test_grid_with_aux_lon(self): + ok, bad = self.ok_bad('longitude') + with self.assertRaises(ValueError): + Regridder(ok, bad, *self.args) + + +class Test___call____not_dim_coord_share(tests.IrisTest): + def setUp(self): + self.args = ('linear', 'mask') + + def ok_bad(self): + # Make lat/lon share a single dimension on `bad`. + ok = lat_lon_cube() + bad = lat_lon_cube() + lat = bad.coord('latitude') + bad = bad[0, :lat.shape[0]] + bad.remove_coord('latitude') + bad.add_aux_coord(lat, 0) + return ok, bad + + def test_src_shares_dim(self): + ok, bad = self.ok_bad() + with self.assertRaises(ValueError): + Regridder(bad, ok, *self.args) + regridder = Regridder(ok, ok, *self.args) + with self.assertRaises(ValueError): + regridder(bad) + + def test_grid_shares_dim(self): + ok, bad = self.ok_bad() + with self.assertRaises(ValueError): + Regridder(ok, bad, *self.args) + + +class Test___call____bad_georeference(tests.IrisTest): + def setUp(self): + self.args = ('linear', 'mask') + + def ok_bad(self, lat_cs, lon_cs): + # Updates `bad` to use the given coordinate systems. + ok = lat_lon_cube() + bad = lat_lon_cube() + bad.coord('latitude').coord_system = lat_cs + bad.coord('longitude').coord_system = lon_cs + return ok, bad + + def test_src_no_cs(self): + ok, bad = self.ok_bad(None, None) + regridder = Regridder(bad, ok, *self.args) + with self.assertRaises(ValueError): + regridder(bad) + + def test_grid_no_cs(self): + ok, bad = self.ok_bad(None, None) + regridder = Regridder(ok, bad, *self.args) + with self.assertRaises(ValueError): + regridder(ok) + + def test_src_one_cs(self): + ok, bad = self.ok_bad(None, GeogCS(6371000)) + with self.assertRaises(ValueError): + Regridder(bad, ok, *self.args) + + def test_grid_one_cs(self): + ok, bad = self.ok_bad(None, GeogCS(6371000)) + with self.assertRaises(ValueError): + Regridder(ok, bad, *self.args) + + def test_src_inconsistent_cs(self): + ok, bad = self.ok_bad(GeogCS(6370000), GeogCS(6371000)) + with self.assertRaises(ValueError): + Regridder(bad, ok, *self.args) + + def test_grid_inconsistent_cs(self): + ok, bad = self.ok_bad(GeogCS(6370000), GeogCS(6371000)) + with self.assertRaises(ValueError): + Regridder(ok, bad, *self.args) + + +class Test___call____bad_angular_units(tests.IrisTest): + def ok_bad(self): + # Changes the longitude coord to radians on `bad`. + ok = lat_lon_cube() + bad = lat_lon_cube() + bad.coord('longitude').units = 'radians' + return ok, bad + + def test_src_radians(self): + ok, bad = self.ok_bad() + regridder = Regridder(bad, ok, 'linear', 'mask') + with self.assertRaises(ValueError): + regridder(bad) + + def test_grid_radians(self): + ok, bad = self.ok_bad() + with self.assertRaises(ValueError): + Regridder(ok, bad, 'linear', 'mask') + + +def uk_cube(): + data = np.arange(12, dtype=np.float32).reshape(3, 4) + uk = Cube(data) + cs = OSGB() + y_coord = DimCoord(np.arange(3), 'projection_y_coordinate', units='m', + coord_system=cs) + x_coord = DimCoord(np.arange(4), 'projection_x_coordinate', units='m', + coord_system=cs) + uk.add_dim_coord(y_coord, 0) + uk.add_dim_coord(x_coord, 1) + surface = AuxCoord(data * 10, 'surface_altitude', units='m') + uk.add_aux_coord(surface, (0, 1)) + uk.add_aux_factory(HybridHeightFactory(orography=surface)) + return uk + + +class Test___call____bad_linear_units(tests.IrisTest): + def ok_bad(self): + # Defines `bad` with an x coordinate in km. + ok = lat_lon_cube() + bad = uk_cube() + bad.coord(axis='x').units = 'km' + return ok, bad + + def test_src_km(self): + ok, bad = self.ok_bad() + regridder = Regridder(bad, ok, 'linear', 'mask') + with self.assertRaises(ValueError): + regridder(bad) + + def test_grid_km(self): + ok, bad = self.ok_bad() + with self.assertRaises(ValueError): + Regridder(ok, bad, 'linear', 'mask') + + +class Test___call____no_coord_systems(tests.IrisTest): + # Test behaviour in the absence of any coordinate systems. + + def setUp(self): + self.mode = 'mask' + self.methods = ('linear', 'nearest') + + def remove_coord_systems(self, cube): + for coord in cube.coords(): + coord.coord_system = None + + def test_ok(self): + # Ensure regridding is supported when the coordinate definitions match. + # NB. We change the coordinate *values* to ensure that does not + # prevent the regridding operation. + src = uk_cube() + self.remove_coord_systems(src) + grid = src.copy() + for coord in grid.dim_coords: + coord.points = coord.points + 1 + for method in self.methods: + regridder = Regridder(src, grid, method, self.mode) + result = regridder(src) + for coord in result.dim_coords: + self.assertEqual(coord, grid.coord(coord)) + expected = ma.arange(12).reshape((3, 4)) + 5 + expected[:, 3] = ma.masked + expected[2, :] = ma.masked + self.assertMaskedArrayEqual(result.data, expected) + + def test_matching_units(self): + # Check we are insensitive to the units provided they match. + # NB. We change the coordinate *values* to ensure that does not + # prevent the regridding operation. + src = uk_cube() + self.remove_coord_systems(src) + # Move to unusual units (i.e. not metres or degrees). + for coord in src.dim_coords: + coord.units = 'feet' + grid = src.copy() + for coord in grid.dim_coords: + coord.points = coord.points + 1 + for method in self.methods: + regridder = Regridder(src, grid, method, self.mode) + result = regridder(src) + for coord in result.dim_coords: + self.assertEqual(coord, grid.coord(coord)) + expected = ma.arange(12).reshape((3, 4)) + 5 + expected[:, 3] = ma.masked + expected[2, :] = ma.masked + self.assertMaskedArrayEqual(result.data, expected) + + def test_different_units(self): + src = uk_cube() + self.remove_coord_systems(src) + # Move to unusual units (i.e. not metres or degrees). + for coord in src.coords(): + coord.units = 'feet' + grid = src.copy() + grid.coord('projection_y_coordinate').units = 'yards' + # We change the coordinate *values* to ensure that does not + # prevent the regridding operation. + for coord in grid.dim_coords: + coord.points = coord.points + 1 + for method in self.methods: + regridder = Regridder(src, grid, method, self.mode) + emsg = 'matching coordinate metadata' + with self.assertRaisesRegexp(ValueError, emsg): + regridder(src) + + def test_coord_metadata_mismatch(self): + # Check for failure when coordinate definitions differ. + uk = uk_cube() + self.remove_coord_systems(uk) + lat_lon = lat_lon_cube() + self.remove_coord_systems(lat_lon) + for method in self.methods: + regridder = Regridder(uk, lat_lon, method, self.mode) + with self.assertRaises(ValueError): + regridder(uk) + + +class Test___call____extrapolation_modes(tests.IrisTest): + values = [[np.nan, 6, 7, np.nan], + [9, 10, 11, np.nan], + [np.nan, np.nan, np.nan, np.nan]] + + extrapolate_values_by_method = {'linear': [[np.nan, 6, 7, 8], + [9, 10, 11, 12], + [13, 14, 15, 16]], + 'nearest': [[np.nan, 6, 7, 7], + [9, 10, 11, 11], + [9, 10, 11, 11]]} + + surface_values = [[50, 60, 70, np.nan], + [90, 100, 110, np.nan], + [np.nan, np.nan, np.nan, np.nan]] + + def setUp(self): + self.methods = ('linear', 'nearest') + + def _ndarray_cube(self, method): + assert method in self.methods + src = uk_cube() + index = (0, 0) if method == 'linear' else (1, 1) + src.data[index] = np.nan + return src + + def _masked_cube(self, method): + assert method in self.methods + src = uk_cube() + src.data = ma.asarray(src.data) + nan_index = (0, 0) if method == 'linear' else (1, 1) + mask_index = (2, 3) + src.data[nan_index] = np.nan + src.data[mask_index] = ma.masked + return src + + def _regrid(self, src, method, extrapolation_mode='mask'): + grid = src.copy() + for coord in grid.dim_coords: + coord.points = coord.points + 1 + regridder = Regridder(src, grid, method, extrapolation_mode) + result = regridder(src) + + surface = result.coord('surface_altitude').points + self.assertNotIsInstance(surface, ma.MaskedArray) + self.assertArrayEqual(surface, self.surface_values) + + return result.data + + def test_default_ndarray(self): + # NaN -> NaN + # Extrapolated -> Masked + for method in self.methods: + src = self._ndarray_cube(method) + result = self._regrid(src, method) + self.assertIsInstance(result, ma.MaskedArray) + mask = [[0, 0, 0, 1], + [0, 0, 0, 1], + [1, 1, 1, 1]] + expected = ma.MaskedArray(self.values, mask) + self.assertMaskedArrayEqual(result, expected) + + def test_default_maskedarray(self): + # NaN -> NaN + # Extrapolated -> Masked + # Masked -> Masked + for method in self.methods: + src = self._masked_cube(method) + result = self._regrid(src, method) + self.assertIsInstance(result, ma.MaskedArray) + mask = [[0, 0, 0, 1], + [0, 0, 1, 1], + [1, 1, 1, 1]] + expected = ma.MaskedArray(self.values, mask) + self.assertMaskedArrayEqual(result, expected) + + def test_default_maskedarray_none_masked(self): + # NaN -> NaN + # Extrapolated -> Masked + # Masked -> N/A + for method in self.methods: + src = uk_cube() + src.data = ma.asarray(src.data) + index = (0, 0) if method == 'linear' else (1, 1) + src.data[index] = np.nan + result = self._regrid(src, method) + self.assertIsInstance(result, ma.MaskedArray) + mask = [[0, 0, 0, 1], + [0, 0, 0, 1], + [1, 1, 1, 1]] + expected = ma.MaskedArray(self.values, mask) + self.assertMaskedArrayEqual(result, expected) + + def test_default_maskedarray_none_masked_expanded(self): + # NaN -> NaN + # Extrapolated -> Masked + # Masked -> N/A + for method in self.methods: + src = uk_cube() + src.data = ma.asarray(src.data) + # Make sure the mask has been expanded + src.data.mask = False + index = (0, 0) if method == 'linear' else (1, 1) + src.data[index] = np.nan + result = self._regrid(src, method) + self.assertIsInstance(result, ma.MaskedArray) + mask = [[0, 0, 0, 1], + [0, 0, 0, 1], + [1, 1, 1, 1]] + expected = ma.MaskedArray(self.values, mask) + self.assertMaskedArrayEqual(result, expected) + + def test_method_ndarray(self): + # NaN -> NaN + # Extrapolated -> linear + for method in self.methods: + src = self._ndarray_cube(method) + result = self._regrid(src, method, 'extrapolate') + self.assertNotIsInstance(result, ma.MaskedArray) + expected = self.extrapolate_values_by_method[method] + self.assertArrayEqual(result, expected) + + def test_nan_ndarray(self): + # NaN -> NaN + # Extrapolated -> NaN + for method in self.methods: + src = self._ndarray_cube(method) + result = self._regrid(src, method, 'nan') + self.assertNotIsInstance(result, ma.MaskedArray) + self.assertArrayEqual(result, self.values) + + def test_nan_maskedarray(self): + # NaN -> NaN + # Extrapolated -> NaN + # Masked -> Masked + for method in self.methods: + src = self._masked_cube(method) + result = self._regrid(src, method, 'nan') + self.assertIsInstance(result, ma.MaskedArray) + mask = [[0, 0, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 0]] + expected = ma.MaskedArray(self.values, mask) + self.assertMaskedArrayEqual(result, expected) + + def test_error_ndarray(self): + # Values irrelevant - the function raises an error. + for method in self.methods: + src = self._ndarray_cube(method) + with self.assertRaisesRegexp(ValueError, 'out of bounds'): + self._regrid(src, method, 'error') + + def test_error_maskedarray(self): + # Values irrelevant - the function raises an error. + for method in self.methods: + src = self._masked_cube(method) + with self.assertRaisesRegexp(ValueError, 'out of bounds'): + self._regrid(src, method, 'error') + + def test_mask_ndarray(self): + # NaN -> NaN + # Extrapolated -> Masked (this is different from all the other + # modes) + for method in self.methods: + src = self._ndarray_cube(method) + result = self._regrid(src, method, 'mask') + self.assertIsInstance(result, ma.MaskedArray) + mask = [[0, 0, 0, 1], + [0, 0, 0, 1], + [1, 1, 1, 1]] + expected = ma.MaskedArray(self.values, mask) + self.assertMaskedArrayEqual(result, expected) + + def test_mask_maskedarray(self): + # NaN -> NaN + # Extrapolated -> Masked + # Masked -> Masked + for method in self.methods: + src = self._masked_cube(method) + result = self._regrid(src, method, 'mask') + self.assertIsInstance(result, ma.MaskedArray) + mask = [[0, 0, 0, 1], + [0, 0, 1, 1], + [1, 1, 1, 1]] + expected = ma.MaskedArray(self.values, mask) + self.assertMaskedArrayEqual(result, expected) + + def test_nanmask_ndarray(self): + # NaN -> NaN + # Extrapolated -> NaN + for method in self.methods: + src = self._ndarray_cube(method) + result = self._regrid(src, method, 'nanmask') + self.assertNotIsInstance(result, ma.MaskedArray) + self.assertArrayEqual(result, self.values) + + def test_nanmask_maskedarray(self): + # NaN -> NaN + # Extrapolated -> Masked + # Masked -> Masked + for method in self.methods: + src = self._masked_cube(method) + result = self._regrid(src, method, 'nanmask') + self.assertIsInstance(result, ma.MaskedArray) + mask = [[0, 0, 0, 1], + [0, 0, 1, 1], + [1, 1, 1, 1]] + expected = ma.MaskedArray(self.values, mask) + self.assertMaskedArrayEqual(result, expected) + + def test_invalid(self): + src = uk_cube() + emsg = 'Invalid extrapolation mode' + for method in self.methods: + with self.assertRaisesRegexp(ValueError, emsg): + self._regrid(src, method, 'BOGUS') + + +@tests.skip_data +class Test___call____rotated_to_lat_lon(tests.IrisTest): + def setUp(self): + self.src = realistic_4d()[:5, :2, ::40, ::30] + self.mode = 'mask' + self.methods = ('linear', 'nearest') + + def test_single_point(self): + src = self.src[0, 0] + grid = global_pp()[:1, :1] + # These coordinate values have been derived by converting the + # rotated coordinates of src[1, 1] into lat/lon by using cs2cs. + grid.coord('longitude').points = -3.144870 + grid.coord('latitude').points = 52.406444 + for method in self.methods: + regridder = Regridder(src, grid, method, self.mode) + result = regridder(src) + self.assertEqual(src.data[1, 1], result.data) + + def test_transposed_src(self): + # The source dimensions are in a non-standard order. + src = self.src + src.transpose([3, 1, 2, 0]) + grid = self._grid_subset() + for method in self.methods: + regridder = Regridder(src, grid, method, self.mode) + result = regridder(src) + result.transpose([3, 1, 2, 0]) + cml = RESULT_DIR + ('{}_subset.cml'.format(method),) + self.assertCMLApproxData(result, cml) + + def _grid_subset(self): + # The destination grid points are entirely contained within the + # src grid points. + grid = global_pp()[:4, :5] + grid.coord('longitude').points = np.linspace(-3.182, -3.06, 5) + grid.coord('latitude').points = np.linspace(52.372, 52.44, 4) + return grid + + def test_reversed(self): + src = self.src + grid = self._grid_subset() + + for method in self.methods: + cml = RESULT_DIR + ('{}_subset.cml'.format(method),) + regridder = Regridder(src, grid[::-1], method, self.mode) + result = regridder(src) + self.assertCMLApproxData(result[:, :, ::-1], cml) + + sample = src[:, :, ::-1] + regridder = Regridder(sample, grid[::-1], method, self.mode) + result = regridder(sample) + self.assertCMLApproxData(result[:, :, ::-1], cml) + + sample = src[:, :, :, ::-1] + regridder = Regridder(sample, grid[::-1], method, self.mode) + result = regridder(sample) + self.assertCMLApproxData(result[:, :, ::-1], cml) + + sample = src[:, :, ::-1, ::-1] + regridder = Regridder(sample, grid[::-1], method, self.mode) + result = regridder(sample) + self.assertCMLApproxData(result[:, :, ::-1], cml) + + regridder = Regridder(src, grid[:, ::-1], method, self.mode) + result = regridder(src) + self.assertCMLApproxData(result[:, :, :, ::-1], cml) + + sample = src[:, :, ::-1] + regridder = Regridder(sample, grid[:, ::-1], method, self.mode) + result = regridder(sample) + self.assertCMLApproxData(result[:, :, :, ::-1], cml) + + sample = src[:, :, :, ::-1] + regridder = Regridder(sample, grid[:, ::-1], method, self.mode) + result = regridder(sample) + self.assertCMLApproxData(result[:, :, :, ::-1], cml) + + sample = src[:, :, ::-1, ::-1] + regridder = Regridder(sample, grid[:, ::-1], method, self.mode) + result = regridder(sample) + self.assertCMLApproxData(result[:, :, :, ::-1], cml) + + regridder = Regridder(src, grid[::-1, ::-1], method, self.mode) + result = regridder(src) + self.assertCMLApproxData(result[:, :, ::-1, ::-1], cml) + + sample = src[:, :, ::-1] + regridder = Regridder(sample, grid[::-1, ::-1], method, self.mode) + result = regridder(sample) + self.assertCMLApproxData(result[:, :, ::-1, ::-1], cml) + + sample = src[:, :, :, ::-1] + regridder = Regridder(sample, grid[::-1, ::-1], method, self.mode) + result = regridder(sample) + self.assertCMLApproxData(result[:, :, ::-1, ::-1], cml) + + sample = src[:, :, ::-1, ::-1] + regridder = Regridder(sample, grid[::-1, ::-1], method, self.mode) + result = regridder(sample) + self.assertCMLApproxData(result[:, :, ::-1, ::-1], cml) + + def test_grid_subset(self): + # The destination grid points are entirely contained within the + # src grid points. + grid = self._grid_subset() + for method in self.methods: + regridder = Regridder(self.src, grid, method, self.mode) + result = regridder(self.src) + cml = RESULT_DIR + ('{}_subset.cml'.format(method),) + self.assertCMLApproxData(result, cml) + + def _big_grid(self): + grid = self._grid_subset() + big_grid = Cube(np.zeros((5, 10, 3, 4, 5))) + big_grid.add_dim_coord(grid.coord('latitude'), 3) + big_grid.add_dim_coord(grid.coord('longitude'), 4) + return big_grid + + def test_grid_subset_big(self): + # Add some extra dimensions to the destination Cube and + # these should be safely ignored. + big_grid = self._big_grid() + for method in self.methods: + regridder = Regridder(self.src, big_grid, method, self.mode) + result = regridder(self.src) + cml = RESULT_DIR + ('{}_subset.cml'.format(method),) + self.assertCMLApproxData(result, cml) + + def test_grid_subset_big_transposed(self): + # The order of the grid's dimensions (including the X and Y + # dimensions) must not affect the result. + big_grid = self._big_grid() + big_grid.transpose([4, 0, 3, 1, 2]) + for method in self.methods: + regridder = Regridder(self.src, big_grid, method, self.mode) + result = regridder(self.src) + cml = RESULT_DIR + ('{}_subset.cml'.format(method),) + self.assertCMLApproxData(result, cml) + + def test_grid_subset_anon(self): + # Must cope OK with anonymous source dimensions. + src = self.src + src.remove_coord('time') + grid = self._grid_subset() + for method in self.methods: + regridder = Regridder(src, grid, method, self.mode) + result = regridder(src) + cml = RESULT_DIR + ('{}_subset_anon.cml'.format(method),) + self.assertCMLApproxData(result, cml) + + def test_grid_subset_missing_data_1(self): + # The destination grid points are entirely contained within the + # src grid points AND we have missing data. + src = self.src + src.data = ma.MaskedArray(src.data) + src.data[:, :, 0, 0] = ma.masked + grid = self._grid_subset() + for method in self.methods: + regridder = Regridder(src, grid, method, self.mode) + result = regridder(src) + cml = RESULT_DIR + ('{}_subset_masked_1.cml'.format(method),) + self.assertCMLApproxData(result, cml) + + def test_grid_subset_missing_data_2(self): + # The destination grid points are entirely contained within the + # src grid points AND we have missing data. + src = self.src + src.data = ma.MaskedArray(src.data) + src.data[:, :, 1, 2] = ma.masked + grid = self._grid_subset() + for method in self.methods: + regridder = Regridder(src, grid, method, self.mode) + result = regridder(src) + cml = RESULT_DIR + ('{}_subset_masked_2.cml'.format(method),) + self.assertCMLApproxData(result, cml) + + def test_grid_partial_overlap(self): + # The destination grid points are partially contained within the + # src grid points. + grid = global_pp()[:4, :4] + grid.coord('longitude').points = np.linspace(-3.3, -3.06, 4) + grid.coord('latitude').points = np.linspace(52.377, 52.43, 4) + for method in self.methods: + regridder = Regridder(self.src, grid, method, self.mode) + result = regridder(self.src) + cml = RESULT_DIR + ('{}_partial_overlap.cml'.format(method),) + self.assertCMLApproxData(result, cml) + + def test_grid_no_overlap(self): + # The destination grid points are NOT contained within the + # src grid points. + grid = global_pp()[:4, :4] + grid.coord('longitude').points = np.linspace(-3.3, -3.2, 4) + grid.coord('latitude').points = np.linspace(52.377, 52.43, 4) + for method in self.methods: + regridder = Regridder(self.src, grid, method, self.mode) + result = regridder(self.src) + self.assertCMLApproxData(result, RESULT_DIR + ('no_overlap.cml',)) + + def test_grid_subset_missing_data_aux(self): + # The destination grid points are entirely contained within the + # src grid points AND we have missing data on the aux coordinate. + src = self.src + src.coord('surface_altitude').points[1, 2] = ma.masked + grid = self._grid_subset() + for method in self.methods: + regridder = Regridder(src, grid, method, self.mode) + result = regridder(src) + cml = RESULT_DIR + ('{}_masked_altitude.cml'.format(method),) + self.assertCMLApproxData(result, cml) + + +@tests.skip_data +class Test___call____NOP(tests.IrisTest): + def setUp(self): + # The destination grid points are exactly the same as the + # src grid points. + self.src = realistic_4d()[:5, :2, ::40, ::30] + self.grid = self.src.copy() + + def test_nop__linear(self): + regridder = Regridder(self.src, self.grid, 'linear', 'mask') + result = regridder(self.src) + self.assertEqual(result, self.src) + + def test_nop__nearest(self): + regridder = Regridder(self.src, self.grid, 'nearest', 'mask') + result = regridder(self.src) + self.assertEqual(result, self.src) + + +@tests.skip_data +class Test___call____circular(tests.IrisTest): + def setUp(self): + src = global_pp()[::10, ::10] + level_height = AuxCoord(0, long_name='level_height', units='m', + attributes={'positive': 'up'}) + sigma = AuxCoord(1, long_name='sigma') + surface_altitude = AuxCoord((src.data - src.data.min()) * 50, + 'surface_altitude', units='m') + src.add_aux_coord(level_height) + src.add_aux_coord(sigma) + src.add_aux_coord(surface_altitude, [0, 1]) + hybrid_height = HybridHeightFactory(level_height, sigma, + surface_altitude) + src.add_aux_factory(hybrid_height) + self.src = src + + grid = global_pp()[:4, :4] + grid.coord('longitude').points = grid.coord('longitude').points - 5 + self.grid = grid + self.mode = 'mask' + self.methods = ('linear', 'nearest') + + def test_non_circular(self): + # Non-circular src -> non-circular grid + for method in self.methods: + regridder = Regridder(self.src, self.grid, method, self.mode) + result = regridder(self.src) + self.assertFalse(result.coord('longitude').circular) + cml = RESULT_DIR + ('{}_non_circular.cml'.format(method),) + self.assertCMLApproxData(result, cml) + + def _check_circular_results(self, src_cube, missingmask=''): + results = [] + for method in self.methods: + regridder = Regridder(src_cube, self.grid, method, self.mode) + result = regridder(src_cube) + results.append(result) + self.assertFalse(result.coord('longitude').circular) + cml = RESULT_DIR + ('{}_circular_src{}.cml'.format(method, + missingmask),) + self.assertCMLApproxData(result, cml) + return results + + def test_circular_src(self): + # Circular src -> non-circular grid, standard test. + src = self.src + src.coord('longitude').circular = True + self._check_circular_results(src) + + def test_circular_src__masked_missingmask(self): + # Test the special case where src_cube.data.mask is just *False*, + # instead of being an array. + src = self.src + src.coord('longitude').circular = True + src.data = ma.MaskedArray(src.data) + self.assertEqual(src.data.mask, False) + method_results = self._check_circular_results(src, 'missingmask') + for method_result in method_results: + self.assertIsInstance(method_result.data.mask, np.ndarray) + self.assertTrue(np.all(method_result.data.mask == np.array(False))) + + def test_circular_src__masked(self): + # Test that masked source points produce the expected masked results. + + # Define source + destination sample points. + # Note: these are chosen to avoid any marginal edge-cases, such as + # where a destination value matches a source point (for 'linear'), or a + # half-way point (for 'nearest'). + src_x = [0.0, 60.0, 120.0, 180.0, 240.0, 300.0] + dst_x = [20.0, 80.0, 140.0, 200.0, 260.0, 320.0] + src_y = [100.0, 200.0, 300.0, 400.0, 500.0] + dst_y = [40.0, 140.0, 240.0, 340.0, 440.0, 540.0] + + # Define the expected result masks for the tested methods, + # when just the middle source point is masked... + result_masks = { + 'nearest': np.array( + [[0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0], + [0, 0, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0]], + dtype=bool), + 'linear': np.array( + [[0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0], + [0, 1, 1, 0, 0, 0], + [0, 1, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0]], + dtype=bool), + } + + # Cook up some distinctive data values. + src_nx, src_ny, dst_nx, dst_ny = (len(dd) for dd in + (src_x, src_y, dst_x, dst_y)) + data_x = np.arange(src_nx).reshape((1, src_nx)) + data_y = np.arange(src_ny).reshape((src_ny, 1)) + data = 3.0 + data_x + 20.0 * data_y + + # Make src and dst test cubes. + def make_2d_cube(x_points, y_points, data): + cube = Cube(data) + y_coord = DimCoord(y_points, standard_name='latitude', + units='degrees') + x_coord = DimCoord(x_points, standard_name='longitude', + units='degrees') + x_coord.circular = True + cube.add_dim_coord(y_coord, 0) + cube.add_dim_coord(x_coord, 1) + return cube + + src_cube_full = make_2d_cube(src_x, src_y, data) + dst_cube = make_2d_cube(dst_x, dst_y, np.zeros((dst_ny, dst_nx))) + + src_cube_masked = src_cube_full.copy() + src_cube_masked.data = ma.array(src_cube_masked.data, + mask=np.zeros((src_ny, src_nx))) + + # Mask the middle source point, and give it a huge underlying data + # value to ensure that it does not take any part in the results. + src_cube_masked.data[2, 2] = 1e19 + src_cube_masked.data.mask[2, 2] = True + + # Test results against the unmasked operation, for each method. + for method in self.methods: + regridder = Regridder(src_cube_full, dst_cube, method, + extrapolation_mode='nan') + result_basic = regridder(src_cube_full) + result_masked = regridder(src_cube_masked) + # Check we get a masked result + self.assertIsInstance(result_masked.data, ma.MaskedArray) + # Check that the result matches the basic one, except for being + # masked at the specific expected points. + expected_result_data = ma.array(result_basic.data) + expected_result_data.mask = result_masks[method] + self.assertMaskedArrayEqual(result_masked.data, + expected_result_data) + + def test_circular_grid(self): + # Non-circular src -> circular grid + grid = self.grid + grid.coord('longitude').circular = True + for method in self.methods: + regridder = Regridder(self.src, grid, method, self.mode) + result = regridder(self.src) + self.assertTrue(result.coord('longitude').circular) + cml = RESULT_DIR + ('{}_circular_grid.cml'.format(method),) + self.assertCMLApproxData(result, cml) + + def test_circular_src_and_grid(self): + # Circular src -> circular grid + src = self.src + src.coord('longitude').circular = True + grid = self.grid + grid.coord('longitude').circular = True + for method in self.methods: + regridder = Regridder(src, grid, method, self.mode) + result = regridder(src) + self.assertTrue(result.coord('longitude').circular) + cml = RESULT_DIR + ('{}_both_circular.cml'.format(method),) + self.assertCMLApproxData(result, cml) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/analysis/scipy_interpolate/test__RegularGridInterpolator.py b/lib/iris/tests/unit/analysis/scipy_interpolate/test__RegularGridInterpolator.py new file mode 100644 index 0000000000..c24fdc1aa2 --- /dev/null +++ b/lib/iris/tests/unit/analysis/scipy_interpolate/test__RegularGridInterpolator.py @@ -0,0 +1,97 @@ +# (C) British Crown Copyright 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the +:func:`iris.analysis._scipy_interpolate._RegularGridInterpolator` class.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np +import iris + +from iris.analysis._scipy_interpolate import _RegularGridInterpolator +from scipy.sparse.csr import csr_matrix +from iris.tests import mock +import iris.tests.stock as stock + + +class Test(tests.IrisTest): + def setUp(self): + # Load a source cube, then generate an interpolator instance, calculate + # the interpolation weights and set up a target grid. + self.cube = stock.simple_2d() + x_points = self.cube.coord('bar').points + y_points = self.cube.coord('foo').points + self.interpolator = _RegularGridInterpolator([x_points, y_points], + self.cube.data, + method='linear', + bounds_error=False, + fill_value=None) + newx = x_points + 0.7 + newy = y_points + 0.7 + + d_0 = self.cube.data[0, 0] + d_1 = self.cube.data[0, 1] + d_2 = self.cube.data[1, 0] + d_3 = self.cube.data[1, 1] + px_0, px_1 = x_points[0], x_points[1] + py_0, py_1 = y_points[0], y_points[1] + px_t = px_0 + 0.7 + py_t = py_0 + 0.7 + dyt_0 = self._interpolate_point(py_t, py_0, py_1, d_0, d_1) + dyt_1 = self._interpolate_point(py_t, py_0, py_1, d_2, d_3) + self.test_increment = self._interpolate_point(px_t, px_0, px_1, + dyt_0, dyt_1) + + xv, yv = np.meshgrid(newy, newx) + self.tgrid = np.dstack((yv, xv)) + self.weights = self.interpolator.compute_interp_weights(self.tgrid) + + @staticmethod + def _interpolate_point(p_t, p_0, p_1, d_0, d_1): + return d_0 + (d_1 - d_0)*((p_t - p_0)/(p_1 - p_0)) + + def test_compute_interp_weights(self): + weights = self.weights + self.assertIsInstance(weights, tuple) + self.assertEqual(len(weights), 5) + self.assertEqual(weights[0], self.tgrid.shape) + self.assertEqual(weights[1], 'linear') + self.assertIsInstance(weights[2], csr_matrix) + + def test__evaluate_linear_sparse(self): + interpolator = self.interpolator + weights = self.weights + output_data = interpolator._evaluate_linear_sparse(weights[2]) + test_data = self.cube.data.reshape(-1) + self.test_increment + self.assertArrayAlmostEqual(output_data, test_data) + + def test_interp_using_pre_computed_weights(self): + interpolator = self.interpolator + weights = self.weights + output_data = interpolator.interp_using_pre_computed_weights(weights) + test_data = self.cube.data + self.test_increment + self.assertEqual(output_data.shape, self.cube.data.shape) + self.assertArrayAlmostEqual(output_data, test_data) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/stats/__init__.py b/lib/iris/tests/unit/analysis/stats/__init__.py new file mode 100644 index 0000000000..8dd58e46b2 --- /dev/null +++ b/lib/iris/tests/unit/analysis/stats/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.analysis.stats` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/analysis/stats/test_pearsonr.py b/lib/iris/tests/unit/analysis/stats/test_pearsonr.py new file mode 100644 index 0000000000..843eaa5236 --- /dev/null +++ b/lib/iris/tests/unit/analysis/stats/test_pearsonr.py @@ -0,0 +1,155 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.analysis.stats.pearsonr` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np +import numpy.ma as ma + +import iris +import iris.analysis.stats as stats +from iris.exceptions import CoordinateNotFoundError + + +@tests.skip_data +class Test(tests.IrisTest): + def setUp(self): + # 3D cubes: + cube_temp = iris.load_cube(tests.get_data_path( + ('NetCDF', 'global', 'xyt', 'SMALL_total_column_co2.nc'))) + self.cube_a = cube_temp[0:6] + self.cube_b = cube_temp[20:26] + self.cube_b.replace_coord(self.cube_a.coord('time').copy()) + cube_temp = self.cube_a.copy() + cube_temp.coord('latitude').guess_bounds() + cube_temp.coord('longitude').guess_bounds() + self.weights = iris.analysis.cartography.area_weights(cube_temp) + + def test_perfect_corr(self): + r = stats.pearsonr(self.cube_a, self.cube_a, + ['latitude', 'longitude']) + self.assertArrayEqual(r.data, np.array([1.]*6)) + + def test_perfect_corr_all_dims(self): + r = stats.pearsonr(self.cube_a, self.cube_a) + self.assertArrayEqual(r.data, np.array([1.])) + + def test_incompatible_cubes(self): + with self.assertRaises(ValueError): + stats.pearsonr(self.cube_a[:, 0, :], self.cube_b[0, :, :], + 'longitude') + + def test_compatible_cubes(self): + r = stats.pearsonr(self.cube_a, self.cube_b, + ['latitude', 'longitude']) + self.assertArrayAlmostEqual(r.data, [0.81114936, + 0.81690538, + 0.79833135, + 0.81118674, + 0.79745386, + 0.81278484]) + + def test_broadcast_cubes(self): + r1 = stats.pearsonr(self.cube_a, self.cube_b[0, :, :], + ['latitude', 'longitude']) + r2 = stats.pearsonr(self.cube_b[0, :, :], self.cube_a, + ['latitude', 'longitude']) + r_by_slice = [ + stats.pearsonr(self.cube_a[i, :, :], self.cube_b[0, :, :], + ['latitude', 'longitude']).data for i in range(6) + ] + self.assertArrayEqual(r1.data, np.array(r_by_slice)) + self.assertArrayEqual(r2.data, np.array(r_by_slice)) + + def test_compatible_cubes_weighted(self): + r = stats.pearsonr(self.cube_a, self.cube_b, + ['latitude', 'longitude'], + self.weights) + self.assertArrayAlmostEqual(r.data, [0.79105429, + 0.79988078, + 0.78825089, + 0.79925653, + 0.79009810, + 0.80115292]) + + def test_broadcast_cubes_weighted(self): + r = stats.pearsonr(self.cube_a, self.cube_b[0, :, :], + ['latitude', 'longitude'], + weights=self.weights[0, :, :]) + r_by_slice = [ + stats.pearsonr(self.cube_a[i, :, :], self.cube_b[0, :, :], + ['latitude', 'longitude'], + weights=self.weights[0, :, :] + ).data for i in range(6) + ] + self.assertArrayAlmostEqual(r.data, np.array(r_by_slice)) + + def test_weight_error(self): + with self.assertRaises(ValueError): + stats.pearsonr(self.cube_a, self.cube_b[0, :, :], + ['latitude', 'longitude'], + weights=self.weights) + + def test_non_existent_coord(self): + with self.assertRaises(CoordinateNotFoundError): + stats.pearsonr(self.cube_a, self.cube_b, 'bad_coord') + + def test_mdtol(self): + cube_small = self.cube_a[:, 0, 0] + cube_small_masked = cube_small.copy() + cube_small_masked.data = ma.array( + cube_small.data, mask=np.array([0, 0, 0, 1, 1, 1], dtype=bool)) + r1 = stats.pearsonr(cube_small, cube_small_masked) + r2 = stats.pearsonr(cube_small, cube_small_masked, mdtol=0.49) + self.assertArrayAlmostEqual(r1.data, np.array([0.74586593])) + self.assertMaskedArrayEqual(r2.data, ma.array([0], mask=[True])) + + def test_common_mask_simple(self): + cube_small = self.cube_a[:, 0, 0] + cube_small_masked = cube_small.copy() + cube_small_masked.data = ma.array( + cube_small.data, mask=np.array([0, 0, 0, 1, 1, 1], dtype=bool)) + r = stats.pearsonr(cube_small, cube_small_masked, common_mask=True) + self.assertArrayAlmostEqual(r.data, np.array([1.])) + + def test_common_mask_broadcast(self): + cube_small = self.cube_a[:, 0, 0] + cube_small_2d = self.cube_a[:, 0:2, 0] + cube_small.data = ma.array( + cube_small.data, mask=np.array([0, 0, 0, 0, 0, 1], dtype=bool)) + cube_small_2d.data = ma.array( + np.tile(cube_small.data[:, np.newaxis], 2), + mask=np.zeros((6, 2), dtype=bool)) + # 2d mask varies on unshared coord: + cube_small_2d.data.mask[0, 1] = 1 + r = stats.pearsonr(cube_small, cube_small_2d, + weights=self.weights[:, 0, 0], common_mask=True) + self.assertArrayAlmostEqual(r.data, np.array([1., 1.])) + # 2d mask does not vary on unshared coord: + cube_small_2d.data.mask[0, 0] = 1 + r = stats.pearsonr(cube_small, cube_small_2d, common_mask=True) + self.assertArrayAlmostEqual(r.data, np.array([1., 1.])) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/analysis/test_Aggregator.py b/lib/iris/tests/unit/analysis/test_Aggregator.py index 04467996dd..e4e7b71656 100644 --- a/lib/iris/tests/unit/analysis/test_Aggregator.py +++ b/lib/iris/tests/unit/analysis/test_Aggregator.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -16,15 +16,19 @@ # along with Iris. If not, see . """Unit tests for the :class:`iris.analysis.Aggregator` class instance.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -from mock import patch, sentinel, Mock import numpy as np import numpy.ma as ma from iris.analysis import Aggregator +from iris.exceptions import LazyAggregatorError +from iris.tests import mock class Test_aggregate(tests.IrisTest): @@ -46,16 +50,16 @@ def test_masked_notol(self): # Providing masked array with no tolerance keyword (mdtol) provided. axis = 0 mock_return = self.expected_result_axis0.copy() - with patch.object(self.TEST, 'call_func', - return_value=mock_return) as mock_method: + with mock.patch.object(self.TEST, 'call_func', + return_value=mock_return) as mock_method: result = self.TEST.aggregate(self.array, axis) self.assertMaskedArrayEqual(result, self.expected_result_axis0) mock_method.assert_called_once_with(self.array, axis=axis) axis = 1 mock_return = self.expected_result_axis1.copy() - with patch.object(self.TEST, 'call_func', - return_value=mock_return) as mock_method: + with mock.patch.object(self.TEST, 'call_func', + return_value=mock_return) as mock_method: result = self.TEST.aggregate(self.array, axis) self.assertMaskedArrayEqual(result, self.expected_result_axis1) mock_method.assert_called_once_with(self.array, axis=axis) @@ -64,16 +68,16 @@ def test_masked_above_tol(self): # Providing masked array with a high tolerance (mdtol) provided. axis = 0 mock_return = self.expected_result_axis0.copy() - with patch.object(self.TEST, 'call_func', - return_value=mock_return) as mock_method: + with mock.patch.object(self.TEST, 'call_func', + return_value=mock_return) as mock_method: result = self.TEST.aggregate(self.array, axis, mdtol=.55) self.assertMaskedArrayEqual(result, self.expected_result_axis0) mock_method.assert_called_once_with(self.array, axis=axis) axis = 1 mock_return = self.expected_result_axis1.copy() - with patch.object(self.TEST, 'call_func', - return_value=mock_return) as mock_method: + with mock.patch.object(self.TEST, 'call_func', + return_value=mock_return) as mock_method: result = self.TEST.aggregate(self.array, axis, mdtol=.55) self.assertMaskedArrayEqual(result, self.expected_result_axis1) mock_method.assert_called_once_with(self.array, axis=axis) @@ -85,16 +89,16 @@ def test_masked_below_tol(self): result_axis_0 = self.expected_result_axis0.copy() result_axis_0.mask = np.array([True, True, False]) mock_return = ma.array([1, 2, 3], mask=None) - with patch.object(self.TEST, 'call_func', - return_value=mock_return) as mock_method: + with mock.patch.object(self.TEST, 'call_func', + return_value=mock_return) as mock_method: result = self.TEST.aggregate(self.array, axis, mdtol=.45) self.assertMaskedArrayAlmostEqual(result, result_axis_0) mock_method.assert_called_once_with(self.array, axis=axis) axis = 1 mock_return = self.expected_result_axis1.copy() - with patch.object(self.TEST, 'call_func', - return_value=mock_return) as mock_method: + with mock.patch.object(self.TEST, 'call_func', + return_value=mock_return) as mock_method: result = self.TEST.aggregate(self.array, axis, mdtol=.45) self.assertMaskedArrayEqual(result, self.expected_result_axis1) mock_method.assert_called_once_with(self.array, axis=axis) @@ -106,8 +110,8 @@ def test_masked_below_tol_alt(self): result_axis_1 = self.expected_result_axis1.copy() result_axis_1.mask = np.array([True, True]) mock_return = self.expected_result_axis1.copy() - with patch.object(self.TEST, 'call_func', - return_value=mock_return) as mock_method: + with mock.patch.object(self.TEST, 'call_func', + return_value=mock_return) as mock_method: result = self.TEST.aggregate(self.array, axis, mdtol=.1) self.assertMaskedArrayAlmostEqual(result, result_axis_1) mock_method.assert_called_once_with(self.array, axis=axis) @@ -119,16 +123,16 @@ def test_unmasked_with_mdtol(self): axis = 0 mock_return = self.expected_result_axis0.data.copy() - with patch.object(self.TEST, 'call_func', - return_value=mock_return) as mock_method: + with mock.patch.object(self.TEST, 'call_func', + return_value=mock_return) as mock_method: result = self.TEST.aggregate(data, axis, mdtol=0.5) self.assertArrayAlmostEqual(result, mock_return.copy()) mock_method.assert_called_once_with(data, axis=axis) axis = 1 mock_return = self.expected_result_axis1.data.copy() - with patch.object(self.TEST, 'call_func', - return_value=mock_return) as mock_method: + with mock.patch.object(self.TEST, 'call_func', + return_value=mock_return) as mock_method: result = self.TEST.aggregate(data, axis, mdtol=0.5) self.assertArrayAlmostEqual(result, mock_return.copy()) mock_method.assert_called_once_with(data, axis=axis) @@ -140,43 +144,43 @@ def test_unmasked(self): axis = 0 mock_return = self.expected_result_axis0.data.copy() - with patch.object(self.TEST, 'call_func', - return_value=mock_return) as mock_method: + with mock.patch.object(self.TEST, 'call_func', + return_value=mock_return) as mock_method: result = self.TEST.aggregate(data, axis) self.assertArrayAlmostEqual(result, mock_return.copy()) mock_method.assert_called_once_with(data, axis=axis) axis = 1 mock_return = self.expected_result_axis1.data.copy() - with patch.object(self.TEST, 'call_func', - return_value=mock_return) as mock_method: + with mock.patch.object(self.TEST, 'call_func', + return_value=mock_return) as mock_method: result = self.TEST.aggregate(data, axis) self.assertArrayAlmostEqual(result, mock_return.copy()) mock_method.assert_called_once_with(data, axis=axis) - def test_returning_array_len_one_mdtol(self): + def test_returning_scalar_mdtol(self): # Test the case when the data aggregation function returns a scalar and # turns it into a masked array. axis = -1 data = self.array.flatten() mock_return = 2 - with patch.object(self.TEST, 'call_func', - return_value=mock_return) as mock_method: + with mock.patch.object(self.TEST, 'call_func', + return_value=mock_return) as mock_method: result = self.TEST.aggregate(data, axis, mdtol=1) - self.assertMaskedArrayEqual(result, ma.array([2], mask=[False])) + self.assertMaskedArrayEqual(result, ma.array(2, mask=False)) mock_method.assert_called_once_with(data, axis=axis) - def test_returning_array_len_one_mdtol_alt(self): + def test_returning_scalar_mdtol_alt(self): # Test the case when the data aggregation function returns a scalar # with no tolerance for missing data values and turns it into a masked - # array of length one. + # array. axis = -1 data = self.array.flatten() mock_return = 2 - with patch.object(self.TEST, 'call_func', - return_value=mock_return) as mock_method: + with mock.patch.object(self.TEST, 'call_func', + return_value=mock_return) as mock_method: result = self.TEST.aggregate(data, axis, mdtol=0) - self.assertMaskedArrayEqual(result, ma.array([2], mask=[True])) + self.assertMaskedArrayEqual(result, ma.array(2, mask=True)) mock_method.assert_called_once_with(data, axis=axis) def test_returning_non_masked_array_from_masked_array(self): @@ -185,39 +189,131 @@ def test_returning_non_masked_array_from_masked_array(self): axis = 0 mock_return = self.expected_result_axis0.data.copy() result_axis_0 = ma.array(mock_return, mask=[True, True, False]) - with patch.object(self.TEST, 'call_func', - return_value=mock_return) as mock_method: + with mock.patch.object(self.TEST, 'call_func', + return_value=mock_return) as mock_method: result = self.TEST.aggregate(self.array, axis, mdtol=.45) self.assertMaskedArrayAlmostEqual(result, result_axis_0) mock_method.assert_called_once_with(self.array, axis=axis) axis = 1 mock_return = self.expected_result_axis1.data.copy() - with patch.object(self.TEST, 'call_func', - return_value=mock_return) as mock_method: + with mock.patch.object(self.TEST, 'call_func', + return_value=mock_return) as mock_method: result = self.TEST.aggregate(self.array, axis, mdtol=.45) self.assertMaskedArrayEqual(result, self.expected_result_axis1) mock_method.assert_called_once_with(self.array, axis=axis) + def test_kwarg_pass_through_no_kwargs(self): + call_func = mock.Mock() + data = mock.sentinel.data + axis = mock.sentinel.axis + aggregator = Aggregator('', call_func) + aggregator.aggregate(data, axis) + call_func.assert_called_once_with(data, axis=axis) + + def test_kwarg_pass_through_call_kwargs(self): + call_func = mock.Mock() + data = mock.sentinel.data + axis = mock.sentinel.axis + kwargs = dict(wibble='wobble', foo='bar') + aggregator = Aggregator('', call_func) + aggregator.aggregate(data, axis, **kwargs) + call_func.assert_called_once_with(data, axis=axis, **kwargs) + + def test_kwarg_pass_through_init_kwargs(self): + call_func = mock.Mock() + data = mock.sentinel.data + axis = mock.sentinel.axis + kwargs = dict(wibble='wobble', foo='bar') + aggregator = Aggregator('', call_func, **kwargs) + aggregator.aggregate(data, axis) + call_func.assert_called_once_with(data, axis=axis, **kwargs) + + def test_kwarg_pass_through_combined_kwargs(self): + call_func = mock.Mock() + data = mock.sentinel.data + axis = mock.sentinel.axis + init_kwargs = dict(wibble='wobble', var=1.0) + call_kwargs = dict(foo='foo', var=0.5) + aggregator = Aggregator('', call_func, **init_kwargs) + aggregator.aggregate(data, axis, **call_kwargs) + expected_kwargs = init_kwargs.copy() + expected_kwargs.update(call_kwargs) + call_func.assert_called_once_with(data, axis=axis, **expected_kwargs) + + def test_mdtol_intercept(self): + call_func = mock.Mock() + data = mock.sentinel.data + axis = mock.sentinel.axis + aggregator = Aggregator('', call_func) + aggregator.aggregate(data, axis, wibble='wobble', mdtol=0.8) + call_func.assert_called_once_with(data, axis=axis, wibble='wobble') + + def test_no_lazy_func(self): + dummy_agg = Aggregator('custom_op', lambda x: 1) + expected = 'custom_op aggregator does not support lazy operation' + with self.assertRaisesRegexp(LazyAggregatorError, expected): + dummy_agg.lazy_aggregate(np.arange(10), axis=0) + class Test_update_metadata(tests.IrisTest): def test_no_units_change(self): # If the Aggregator has no units_func then the units should be # left unchanged. aggregator = Aggregator('', None) - cube = Mock(units=sentinel.units) + cube = mock.Mock(units=mock.sentinel.units) aggregator.update_metadata(cube, []) - self.assertIs(cube.units, sentinel.units) + self.assertIs(cube.units, mock.sentinel.units) def test_units_change(self): # If the Aggregator has a units_func then the new units should # be defined by its return value. - units_func = Mock(return_value=sentinel.new_units) + units_func = mock.Mock(return_value=mock.sentinel.new_units) aggregator = Aggregator('', None, units_func) - cube = Mock(units=sentinel.units) + cube = mock.Mock(units=mock.sentinel.units) aggregator.update_metadata(cube, []) - units_func.assert_called_once_with(sentinel.units) - self.assertEqual(cube.units, sentinel.new_units) + units_func.assert_called_once_with(mock.sentinel.units) + self.assertEqual(cube.units, mock.sentinel.new_units) + + +class Test_lazy_aggregate(tests.IrisTest): + def test_kwarg_pass_through_no_kwargs(self): + lazy_func = mock.Mock() + data = mock.sentinel.data + axis = mock.sentinel.axis + aggregator = Aggregator('', None, lazy_func=lazy_func) + aggregator.lazy_aggregate(data, axis) + lazy_func.assert_called_once_with(data, axis=axis) + + def test_kwarg_pass_through_call_kwargs(self): + lazy_func = mock.Mock() + data = mock.sentinel.data + axis = mock.sentinel.axis + kwargs = dict(wibble='wobble', foo='bar') + aggregator = Aggregator('', None, lazy_func=lazy_func) + aggregator.lazy_aggregate(data, axis, **kwargs) + lazy_func.assert_called_once_with(data, axis=axis, **kwargs) + + def test_kwarg_pass_through_init_kwargs(self): + lazy_func = mock.Mock() + data = mock.sentinel.data + axis = mock.sentinel.axis + kwargs = dict(wibble='wobble', foo='bar') + aggregator = Aggregator('', None, lazy_func=lazy_func, **kwargs) + aggregator.lazy_aggregate(data, axis) + lazy_func.assert_called_once_with(data, axis=axis, **kwargs) + + def test_kwarg_pass_through_combined_kwargs(self): + lazy_func = mock.Mock() + data = mock.sentinel.data + axis = mock.sentinel.axis + init_kwargs = dict(wibble='wobble', var=1.0) + call_kwargs = dict(foo='foo', var=0.5) + aggregator = Aggregator('', None, lazy_func=lazy_func, **init_kwargs) + aggregator.lazy_aggregate(data, axis, **call_kwargs) + expected_kwargs = init_kwargs.copy() + expected_kwargs.update(call_kwargs) + lazy_func.assert_called_once_with(data, axis=axis, **expected_kwargs) if __name__ == "__main__": diff --git a/lib/iris/tests/unit/analysis/test_AreaWeighted.py b/lib/iris/tests/unit/analysis/test_AreaWeighted.py new file mode 100644 index 0000000000..e4b39b7ce1 --- /dev/null +++ b/lib/iris/tests/unit/analysis/test_AreaWeighted.py @@ -0,0 +1,69 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for :class:`iris.analysis.AreaWeighted`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.analysis import AreaWeighted +from iris.tests import mock + + +class Test(tests.IrisTest): + def check_call(self, mdtol=None): + # Check that `iris.analysis.AreaWeighted` correctly calls an + # `iris.analysis._area_weighted.AreaWeightedRegridder` object. + if mdtol is None: + area_weighted = AreaWeighted() + mdtol = 1 + else: + area_weighted = AreaWeighted(mdtol=mdtol) + self.assertEqual(area_weighted.mdtol, mdtol) + + with mock.patch('iris.analysis.AreaWeightedRegridder', + return_value=mock.sentinel.regridder) as awr: + regridder = area_weighted.regridder(mock.sentinel.src, + mock.sentinel.target) + + awr.assert_called_once_with(mock.sentinel.src, + mock.sentinel.target, + mdtol=mdtol) + self.assertIs(regridder, mock.sentinel.regridder) + + def test_default(self): + self.check_call() + + def test_specified_mdtol(self): + self.check_call(0.5) + + def test_invalid_high_mdtol(self): + msg = 'mdtol must be in range 0 - 1' + with self.assertRaisesRegexp(ValueError, msg): + AreaWeighted(mdtol=1.2) + + def test_invalid_low_mdtol(self): + msg = 'mdtol must be in range 0 - 1' + with self.assertRaisesRegexp(ValueError, msg): + AreaWeighted(mdtol=-0.2) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/analysis/test_COUNT.py b/lib/iris/tests/unit/analysis/test_COUNT.py index c3d228b8e8..5422a197e0 100644 --- a/lib/iris/tests/unit/analysis/test_COUNT.py +++ b/lib/iris/tests/unit/analysis/test_COUNT.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2018, Met Office # # This file is part of Iris. # @@ -16,13 +16,65 @@ # along with Iris. If not, see . """Unit tests for the :data:`iris.analysis.COUNT` aggregator.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import mock +import numpy as np +import numpy.ma as ma from iris.analysis import COUNT +from iris.cube import Cube +from iris.coords import DimCoord +from iris._lazy_data import as_lazy_data, is_lazy_data + + +class Test_basics(tests.IrisTest): + def setUp(self): + data = np.array([1, 2, 3, 4, 5]) + coord = DimCoord([6, 7, 8, 9, 10], long_name='foo') + self.cube = Cube(data) + self.cube.add_dim_coord(coord, 0) + self.lazy_cube = Cube(as_lazy_data(data)) + self.lazy_cube.add_dim_coord(coord, 0) + self.func = lambda x: x >= 3 + + def test_name(self): + self.assertEqual(COUNT.name(), 'count') + + def test_no_function(self): + exp_emsg = r"function must be a callable. Got <.* 'NoneType'>" + with self.assertRaisesRegexp(TypeError, exp_emsg): + COUNT.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0) + + def test_not_callable(self): + with self.assertRaisesRegexp(TypeError, 'function must be a callable'): + COUNT.aggregate(self.cube.data, axis=0, function='wibble') + + def test_lazy_not_callable(self): + with self.assertRaisesRegexp(TypeError, 'function must be a callable'): + COUNT.lazy_aggregate(self.lazy_cube.lazy_data(), + axis=0, + function='wibble') + + def test_collapse(self): + data = COUNT.aggregate(self.cube.data, axis=0, function=self.func) + self.assertArrayEqual(data, [3]) + + def test_lazy(self): + lazy_data = COUNT.lazy_aggregate(self.lazy_cube.lazy_data(), + axis=0, + function=self.func) + self.assertTrue(is_lazy_data(lazy_data)) + + def test_lazy_collapse(self): + lazy_data = COUNT.lazy_aggregate(self.lazy_cube.lazy_data(), + axis=0, + function=self.func) + self.assertArrayEqual(lazy_data.compute(), [3]) class Test_units_func(tests.IrisTest): @@ -32,5 +84,42 @@ def test(self): self.assertEqual(new_units, 1) +class Test_masked(tests.IrisTest): + def setUp(self): + self.cube = Cube(ma.masked_equal([1, 2, 3, 4, 5], 3)) + self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0) + self.func = lambda x: x >= 3 + + def test_ma(self): + data = COUNT.aggregate(self.cube.data, axis=0, function=self.func) + self.assertArrayEqual(data, [2]) + + +class Test_lazy_masked(tests.IrisTest): + def setUp(self): + lazy_data = as_lazy_data(ma.masked_equal([1, 2, 3, 4, 5], 3)) + self.lazy_cube = Cube(lazy_data) + self.lazy_cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], + long_name='foo'), + 0) + self.func = lambda x: x >= 3 + + def test_ma(self): + lazy_data = COUNT.lazy_aggregate(self.lazy_cube.lazy_data(), + axis=0, + function=self.func) + self.assertTrue(is_lazy_data(lazy_data)) + self.assertArrayEqual(lazy_data.compute(), [2]) + + +class Test_aggregate_shape(tests.IrisTest): + def test(self): + shape = () + kwargs = dict() + self.assertTupleEqual(COUNT.aggregate_shape(**kwargs), shape) + kwargs = dict(wibble='wobble') + self.assertTupleEqual(COUNT.aggregate_shape(**kwargs), shape) + + if __name__ == "__main__": tests.main() diff --git a/lib/iris/tests/unit/analysis/test_Linear.py b/lib/iris/tests/unit/analysis/test_Linear.py new file mode 100644 index 0000000000..7044e58f1a --- /dev/null +++ b/lib/iris/tests/unit/analysis/test_Linear.py @@ -0,0 +1,152 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for :class:`iris.analysis.Linear`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.analysis import Linear +from iris.tests import mock + + +def create_scheme(mode=None): + kwargs = {} + if mode is not None: + kwargs['extrapolation_mode'] = mode + return Linear(**kwargs) + + +class Test_extrapolation_mode(tests.IrisTest): + def check_mode(self, mode): + linear = create_scheme(mode) + self.assertEqual(linear.extrapolation_mode, mode) + + def test_default(self): + linear = Linear() + self.assertEqual(linear.extrapolation_mode, 'linear') + + def test_extrapolate(self): + self.check_mode('extrapolate') + + def test_linear(self): + self.check_mode('linear') + + def test_nan(self): + self.check_mode('nan') + + def test_error(self): + self.check_mode('error') + + def test_mask(self): + self.check_mode('mask') + + def test_nanmask(self): + self.check_mode('nanmask') + + def test_invalid(self): + with self.assertRaisesRegexp(ValueError, 'Extrapolation mode'): + Linear('bogus') + + +class Test_interpolator(tests.IrisTest): + def check_mode(self, mode=None): + linear = create_scheme(mode) + + # Check that calling `linear.interpolator(...)` returns an + # instance of RectilinearInterpolator which has been created + # using the correct arguments. + with mock.patch('iris.analysis.RectilinearInterpolator', + return_value=mock.sentinel.interpolator) as ri: + interpolator = linear.interpolator(mock.sentinel.cube, + mock.sentinel.coords) + if mode is None or mode == 'linear': + expected_mode = 'extrapolate' + else: + expected_mode = mode + ri.assert_called_once_with(mock.sentinel.cube, mock.sentinel.coords, + 'linear', expected_mode) + self.assertIs(interpolator, mock.sentinel.interpolator) + + def test_default(self): + self.check_mode() + + def test_extrapolate(self): + self.check_mode('extrapolate') + + def test_linear(self): + self.check_mode('linear') + + def test_nan(self): + self.check_mode('nan') + + def test_error(self): + self.check_mode('error') + + def test_mask(self): + self.check_mode('mask') + + def test_nanmask(self): + self.check_mode('nanmask') + + +class Test_regridder(tests.IrisTest): + def check_mode(self, mode=None): + linear = create_scheme(mode) + + # Check that calling `linear.regridder(...)` returns an instance + # of RectilinearRegridder which has been created using the correct + # arguments. + with mock.patch('iris.analysis.RectilinearRegridder', + return_value=mock.sentinel.regridder) as lr: + regridder = linear.regridder(mock.sentinel.src, + mock.sentinel.target) + if mode is None or mode == 'linear': + expected_mode = 'extrapolate' + else: + expected_mode = mode + lr.assert_called_once_with(mock.sentinel.src, mock.sentinel.target, + 'linear', expected_mode) + self.assertIs(regridder, mock.sentinel.regridder) + + def test_default(self): + self.check_mode() + + def test_extrapolate(self): + self.check_mode('extrapolate') + + def test_linear(self): + self.check_mode('linear') + + def test_nan(self): + self.check_mode('nan') + + def test_error(self): + self.check_mode('error') + + def test_mask(self): + self.check_mode('mask') + + def test_nanmask(self): + self.check_mode('nanmask') + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/analysis/test_MAX.py b/lib/iris/tests/unit/analysis/test_MAX.py new file mode 100644 index 0000000000..f3a523bc93 --- /dev/null +++ b/lib/iris/tests/unit/analysis/test_MAX.py @@ -0,0 +1,92 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :data:`iris.analysis.MAX` aggregator.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np +import numpy.ma as ma + +from iris.analysis import MAX +from iris.cube import Cube +from iris.coords import DimCoord +from iris._lazy_data import as_lazy_data, is_lazy_data + + +class Test_basics(tests.IrisTest): + def setUp(self): + data = np.array([1, 2, 3, 4, 5]) + coord = DimCoord([6, 7, 8, 9, 10], long_name='foo') + self.cube = Cube(data) + self.cube.add_dim_coord(coord, 0) + self.lazy_cube = Cube(as_lazy_data(data)) + self.lazy_cube.add_dim_coord(coord, 0) + + def test_name(self): + self.assertEqual(MAX.name(), 'maximum') + + def test_collapse(self): + data = MAX.aggregate(self.cube.data, axis=0) + self.assertArrayEqual(data, [5]) + + def test_lazy(self): + lazy_data = MAX.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0) + self.assertTrue(is_lazy_data(lazy_data)) + + def test_lazy_collapse(self): + lazy_data = MAX.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0) + self.assertArrayEqual(lazy_data.compute(), [5]) + + +class Test_masked(tests.IrisTest): + def setUp(self): + self.cube = Cube(ma.masked_greater([1, 2, 3, 4, 5], 3)) + self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0) + + def test_ma(self): + data = MAX.aggregate(self.cube.data, axis=0) + self.assertArrayEqual(data, [3]) + + +class Test_lazy_masked(tests.IrisTest): + def setUp(self): + masked_data = ma.masked_greater([1, 2, 3, 4, 5], 3) + self.cube = Cube(as_lazy_data(masked_data)) + self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0) + + def test_lazy_ma(self): + lazy_data = MAX.lazy_aggregate(self.cube.lazy_data(), axis=0) + self.assertTrue(is_lazy_data(lazy_data)) + self.assertArrayEqual(lazy_data.compute(), [3]) + + +class Test_aggregate_shape(tests.IrisTest): + def test(self): + shape = () + kwargs = dict() + self.assertTupleEqual(MAX.aggregate_shape(**kwargs), shape) + kwargs = dict(wibble='wobble') + self.assertTupleEqual(MAX.aggregate_shape(**kwargs), shape) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/test_MEAN.py b/lib/iris/tests/unit/analysis/test_MEAN.py new file mode 100644 index 0000000000..0fd87185f7 --- /dev/null +++ b/lib/iris/tests/unit/analysis/test_MEAN.py @@ -0,0 +1,131 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :data:`iris.analysis.MEAN` aggregator.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris._lazy_data import as_lazy_data +import numpy as np +import numpy.ma as ma + +from iris.analysis import MEAN +from iris._lazy_data import as_concrete_data + + +class Test_lazy_aggregate(tests.IrisTest): + def setUp(self): + self.data = ma.arange(12).reshape(3, 4) + self.data.mask = [[0, 0, 0, 1], + [0, 0, 1, 1], + [0, 1, 1, 1]] + # --> fractions of masked-points in columns = [0, 1/3, 2/3, 1] + self.array = as_lazy_data(self.data) + self.axis = 0 + self.expected_masked = ma.mean(self.data, axis=self.axis) + + def test_mdtol_default(self): + # Default operation is "mdtol=1" --> unmasked if *any* valid points. + # --> output column masks = [0, 0, 0, 1] + agg = MEAN.lazy_aggregate(self.array, axis=self.axis) + masked_result = as_concrete_data(agg) + self.assertMaskedArrayAlmostEqual(masked_result, + self.expected_masked) + + def test_mdtol_belowall(self): + # Mdtol=0.25 --> masked columns = [0, 1, 1, 1] + agg = MEAN.lazy_aggregate(self.array, axis=self.axis, mdtol=0.25) + masked_result = as_concrete_data(agg) + expected_masked = self.expected_masked + expected_masked.mask = [False, True, True, True] + self.assertMaskedArrayAlmostEqual(masked_result, + expected_masked) + + def test_mdtol_intermediate(self): + # mdtol=0.5 --> masked columns = [0, 0, 1, 1] + agg = MEAN.lazy_aggregate(self.array, axis=self.axis, mdtol=0.5) + masked_result = as_concrete_data(agg) + expected_masked = self.expected_masked + expected_masked.mask = [False, False, True, True] + self.assertMaskedArrayAlmostEqual(masked_result, expected_masked) + + def test_mdtol_aboveall(self): + # mdtol=0.75 --> masked columns = [0, 0, 0, 1] + # In this case, effectively the same as mdtol=None. + agg = MEAN.lazy_aggregate(self.array, axis=self.axis, mdtol=0.75) + masked_result = as_concrete_data(agg) + self.assertMaskedArrayAlmostEqual(masked_result, + self.expected_masked) + + def test_multi_axis(self): + data = np.arange(24.0).reshape((2, 3, 4)) + collapse_axes = (0, 2) + lazy_data = as_lazy_data(data) + agg = MEAN.lazy_aggregate(lazy_data, axis=collapse_axes) + result = as_concrete_data(agg) + expected = np.mean(data, axis=collapse_axes) + self.assertArrayAllClose(result, expected) + + def test_last_axis(self): + # From setUp: + # self.data.mask = [[0, 0, 0, 1], + # [0, 0, 1, 1], + # [0, 1, 1, 1]] + # --> fractions of masked-points in ROWS = [1/4, 1/2, 3/4] + axis = -1 + agg = MEAN.lazy_aggregate(self.array, axis=axis, mdtol=0.51) + expected_masked = ma.mean(self.data, axis=-1) + expected_masked = np.ma.masked_array(expected_masked, [0, 0, 1]) + masked_result = as_concrete_data(agg) + self.assertMaskedArrayAlmostEqual(masked_result, + expected_masked) + + def test_all_axes_belowtol(self): + agg = MEAN.lazy_aggregate(self.array, axis=None, mdtol=0.75) + expected_masked = ma.mean(self.data) + masked_result = as_concrete_data(agg) + self.assertMaskedArrayAlmostEqual(masked_result, + expected_masked) + + def test_all_axes_abovetol(self): + agg = MEAN.lazy_aggregate(self.array, axis=None, mdtol=0.45) + expected_masked = ma.masked_less([0.0], 1) + masked_result = as_concrete_data(agg) + self.assertMaskedArrayAlmostEqual(masked_result, + expected_masked) + + +class Test_name(tests.IrisTest): + def test(self): + self.assertEqual(MEAN.name(), 'mean') + + +class Test_aggregate_shape(tests.IrisTest): + def test(self): + shape = () + kwargs = dict() + self.assertTupleEqual(MEAN.aggregate_shape(**kwargs), shape) + kwargs = dict(one=1, two=2) + self.assertTupleEqual(MEAN.aggregate_shape(**kwargs), shape) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/test_MIN.py b/lib/iris/tests/unit/analysis/test_MIN.py new file mode 100644 index 0000000000..13860f5306 --- /dev/null +++ b/lib/iris/tests/unit/analysis/test_MIN.py @@ -0,0 +1,92 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :data:`iris.analysis.MIN` aggregator.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np +import numpy.ma as ma + +from iris.analysis import MIN +from iris.cube import Cube +from iris.coords import DimCoord +from iris._lazy_data import as_lazy_data, is_lazy_data + + +class Test_basics(tests.IrisTest): + def setUp(self): + data = np.array([1, 2, 3, 4, 5]) + coord = DimCoord([6, 7, 8, 9, 10], long_name='foo') + self.cube = Cube(data) + self.cube.add_dim_coord(coord, 0) + self.lazy_cube = Cube(as_lazy_data(data)) + self.lazy_cube.add_dim_coord(coord, 0) + + def test_name(self): + self.assertEqual(MIN.name(), 'minimum') + + def test_collapse(self): + data = MIN.aggregate(self.cube.data, axis=0) + self.assertArrayEqual(data, [1]) + + def test_lazy(self): + lazy_data = MIN.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0) + self.assertTrue(is_lazy_data(lazy_data)) + + def test_lazy_collapse(self): + lazy_data = MIN.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0) + self.assertArrayEqual(lazy_data.compute(), [1]) + + +class Test_masked(tests.IrisTest): + def setUp(self): + self.cube = Cube(ma.masked_less([1, 2, 3, 4, 5], 3)) + self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0) + + def test_ma(self): + data = MIN.aggregate(self.cube.data, axis=0) + self.assertArrayEqual(data, [3]) + + +class Test_lazy_masked(tests.IrisTest): + def setUp(self): + masked_data = ma.masked_less([1, 2, 3, 4, 5], 3) + self.cube = Cube(as_lazy_data(masked_data)) + self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0) + + def test_lazy_ma(self): + lazy_data = MIN.lazy_aggregate(self.cube.lazy_data(), axis=0) + self.assertTrue(is_lazy_data(lazy_data)) + self.assertArrayEqual(lazy_data.compute(), [3]) + + +class Test_aggregate_shape(tests.IrisTest): + def test(self): + shape = () + kwargs = dict() + self.assertTupleEqual(MIN.aggregate_shape(**kwargs), shape) + kwargs = dict(wibble='wobble') + self.assertTupleEqual(MIN.aggregate_shape(**kwargs), shape) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/test_Nearest.py b/lib/iris/tests/unit/analysis/test_Nearest.py new file mode 100644 index 0000000000..cda3f49f24 --- /dev/null +++ b/lib/iris/tests/unit/analysis/test_Nearest.py @@ -0,0 +1,144 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for :class:`iris.analysis.Nearest`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.analysis import Nearest +from iris.tests import mock + + +def create_scheme(mode=None): + kwargs = {} + if mode is not None: + kwargs['extrapolation_mode'] = mode + return Nearest(**kwargs) + + +class Test___init__(tests.IrisTest): + def test_invalid(self): + with self.assertRaisesRegexp(ValueError, 'Extrapolation mode'): + Nearest('bogus') + + +class Test_extrapolation_mode(tests.IrisTest): + def check_mode(self, mode): + scheme = create_scheme(mode) + self.assertEqual(scheme.extrapolation_mode, mode) + + def test_default(self): + scheme = Nearest() + self.assertEqual(scheme.extrapolation_mode, 'extrapolate') + + def test_extrapolate(self): + self.check_mode('extrapolate') + + def test_nan(self): + self.check_mode('nan') + + def test_error(self): + self.check_mode('error') + + def test_mask(self): + self.check_mode('mask') + + def test_nanmask(self): + self.check_mode('nanmask') + + +class Test_interpolator(tests.IrisTest): + def check_mode(self, mode=None): + scheme = create_scheme(mode) + + # Check that calling `scheme.interpolator(...)` returns an + # instance of RectilinearInterpolator which has been created + # using the correct arguments. + with mock.patch('iris.analysis.RectilinearInterpolator', + return_value=mock.sentinel.interpolator) as ri: + interpolator = scheme.interpolator(mock.sentinel.cube, + mock.sentinel.coords) + if mode is None: + expected_mode = 'extrapolate' + else: + expected_mode = mode + ri.assert_called_once_with(mock.sentinel.cube, mock.sentinel.coords, + 'nearest', expected_mode) + self.assertIs(interpolator, mock.sentinel.interpolator) + + def test_default(self): + self.check_mode() + + def test_extrapolate(self): + self.check_mode('extrapolate') + + def test_nan(self): + self.check_mode('nan') + + def test_error(self): + self.check_mode('error') + + def test_mask(self): + self.check_mode('mask') + + def test_nanmask(self): + self.check_mode('nanmask') + + +class Test_regridder(tests.IrisTest): + def check_mode(self, mode=None): + scheme = create_scheme(mode) + + # Ensure that calling the regridder results in an instance of + # RectilinearRegridder being returned, which has been created with + # the expected arguments. + with mock.patch('iris.analysis.RectilinearRegridder', + return_value=mock.sentinel.regridder) as rr: + regridder = scheme.regridder(mock.sentinel.src_grid, + mock.sentinel.tgt_grid) + + expected_mode = 'extrapolate' if mode is None else mode + rr.assert_called_once_with(mock.sentinel.src_grid, + mock.sentinel.tgt_grid, + 'nearest', expected_mode) + self.assertIs(regridder, mock.sentinel.regridder) + + def test_default(self): + self.check_mode() + + def test_extrapolate(self): + self.check_mode('extrapolate') + + def test_nan(self): + self.check_mode('nan') + + def test_error(self): + self.check_mode('error') + + def test_mask(self): + self.check_mode('mask') + + def test_nanmask(self): + self.check_mode('nanmask') + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/analysis/test_PERCENTILE.py b/lib/iris/tests/unit/analysis/test_PERCENTILE.py new file mode 100644 index 0000000000..0ebdffa7ef --- /dev/null +++ b/lib/iris/tests/unit/analysis/test_PERCENTILE.py @@ -0,0 +1,150 @@ +# (C) British Crown Copyright 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :data:`iris.analysis.PERCENTILE` aggregator.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np +import numpy.ma as ma + +from iris.analysis import PERCENTILE + + +class Test_aggregate(tests.IrisTest): + def test_missing_mandatory_kwarg(self): + emsg = "percentile aggregator requires .* keyword argument 'percent'" + with self.assertRaisesRegexp(ValueError, emsg): + PERCENTILE.aggregate('dummy', axis=0) + + def test_1d_single(self): + data = np.arange(11) + actual = PERCENTILE.aggregate(data, axis=0, percent=50) + expected = 5 + self.assertTupleEqual(actual.shape, ()) + self.assertEqual(actual, expected) + + def test_masked_1d_single(self): + data = ma.arange(11) + data[3:7] = ma.masked + actual = PERCENTILE.aggregate(data, axis=0, percent=50) + expected = 7 + self.assertTupleEqual(actual.shape, ()) + self.assertEqual(actual, expected) + + def test_1d_multi(self): + data = np.arange(11) + percent = np.array([20, 50, 90]) + actual = PERCENTILE.aggregate(data, axis=0, percent=percent) + expected = [2, 5, 9] + self.assertTupleEqual(actual.shape, percent.shape) + self.assertArrayEqual(actual, expected) + + def test_masked_1d_multi(self): + data = ma.arange(11) + data[3:9] = ma.masked + percent = np.array([25, 50, 75]) + actual = PERCENTILE.aggregate(data, axis=0, percent=percent) + expected = [1, 2, 9] + self.assertTupleEqual(actual.shape, percent.shape) + self.assertArrayEqual(actual, expected) + + def test_2d_single(self): + shape = (2, 11) + data = np.arange(np.prod(shape)).reshape(shape) + actual = PERCENTILE.aggregate(data, axis=0, percent=50) + self.assertTupleEqual(actual.shape, shape[-1:]) + expected = np.arange(shape[-1]) + 5.5 + self.assertArrayEqual(actual, expected) + + def test_masked_2d_single(self): + shape = (2, 11) + data = ma.arange(np.prod(shape)).reshape(shape) + data[0, ::2] = ma.masked + data[1, 1::2] = ma.masked + actual = PERCENTILE.aggregate(data, axis=0, percent=50) + self.assertTupleEqual(actual.shape, shape[-1:]) + expected = np.empty(shape[-1:]) + expected[1::2] = data[0, 1::2] + expected[::2] = data[1, ::2] + self.assertArrayEqual(actual, expected) + + def test_2d_multi(self): + shape = (2, 10) + data = np.arange(np.prod(shape)).reshape(shape) + percent = np.array([10, 50, 90, 100]) + actual = PERCENTILE.aggregate(data, axis=0, percent=percent) + self.assertTupleEqual(actual.shape, (shape[-1], percent.size)) + expected = np.tile(np.arange(shape[-1]), percent.size) + expected = expected.reshape(percent.size, shape[-1]).T + 1 + expected = expected + (percent / 10 - 1) + self.assertArrayAlmostEqual(actual, expected) + + def test_masked_2d_multi(self): + shape = (3, 10) + data = ma.arange(np.prod(shape)).reshape(shape) + data[1] = ma.masked + percent = np.array([10, 50, 70, 80]) + actual = PERCENTILE.aggregate(data, axis=0, percent=percent) + self.assertTupleEqual(actual.shape, (shape[-1], percent.size)) + expected = np.tile(np.arange(shape[-1]), percent.size) + expected = expected.reshape(percent.size, shape[-1]).T + expected = expected + (percent / 10 * 2) + self.assertArrayAlmostEqual(actual, expected) + + +class Test_name(tests.IrisTest): + def test(self): + self.assertEqual(PERCENTILE.name(), 'percentile') + + +class Test_aggregate_shape(tests.IrisTest): + def test_missing_mandatory_kwarg(self): + emsg = "percentile aggregator requires .* keyword argument 'percent'" + with self.assertRaisesRegexp(ValueError, emsg): + PERCENTILE.aggregate_shape() + with self.assertRaisesRegexp(ValueError, emsg): + kwargs = dict() + PERCENTILE.aggregate_shape(**kwargs) + with self.assertRaisesRegexp(ValueError, emsg): + kwargs = dict(point=10) + PERCENTILE.aggregate_shape(**kwargs) + + def test_mandatory_kwarg_no_shape(self): + kwargs = dict(percent=50) + self.assertTupleEqual(PERCENTILE.aggregate_shape(**kwargs), ()) + kwargs = dict(percent=[50]) + self.assertTupleEqual(PERCENTILE.aggregate_shape(**kwargs), ()) + + def test_mandatory_kwarg_shape(self): + kwargs = dict(percent=(10, 20)) + self.assertTupleEqual(PERCENTILE.aggregate_shape(**kwargs), (2,)) + kwargs = dict(percent=list(range(13))) + self.assertTupleEqual(PERCENTILE.aggregate_shape(**kwargs), (13,)) + + +class Test_cell_method(tests.IrisTest): + def test(self): + self.assertIsNone(PERCENTILE.cell_method) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/test_PROPORTION.py b/lib/iris/tests/unit/analysis/test_PROPORTION.py index b6963b92d8..4eef258bd8 100644 --- a/lib/iris/tests/unit/analysis/test_PROPORTION.py +++ b/lib/iris/tests/unit/analysis/test_PROPORTION.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -16,13 +16,18 @@ # along with Iris. If not, see . """Unit tests for the :data:`iris.analysis.PROPORTION` aggregator.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import mock +import numpy.ma as ma from iris.analysis import PROPORTION +import iris.cube +from iris.coords import DimCoord class Test_units_func(tests.IrisTest): @@ -32,5 +37,31 @@ def test(self): self.assertEqual(new_units, 1) +class Test_masked(tests.IrisTest): + def setUp(self): + self.cube = iris.cube.Cube(ma.masked_equal([1, 2, 3, 4, 5], 3)) + self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), + 0) + self.func = lambda x: x >= 3 + + def test_ma(self): + cube = self.cube.collapsed("foo", PROPORTION, function=self.func) + self.assertArrayEqual(cube.data, [0.5]) + + +class Test_name(tests.IrisTest): + def test(self): + self.assertEqual(PROPORTION.name(), 'proportion') + + +class Test_aggregate_shape(tests.IrisTest): + def test(self): + shape = () + kwargs = dict() + self.assertTupleEqual(PROPORTION.aggregate_shape(**kwargs), shape) + kwargs = dict(captain='caveman', penelope='pitstop') + self.assertTupleEqual(PROPORTION.aggregate_shape(**kwargs), shape) + + if __name__ == "__main__": tests.main() diff --git a/lib/iris/tests/unit/analysis/test_PercentileAggregator.py b/lib/iris/tests/unit/analysis/test_PercentileAggregator.py new file mode 100644 index 0000000000..434b23edf1 --- /dev/null +++ b/lib/iris/tests/unit/analysis/test_PercentileAggregator.py @@ -0,0 +1,139 @@ +# (C) British Crown Copyright 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the :class:`iris.analysis.PercentileAggregator` class instance. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.analysis import PercentileAggregator, _percentile +from iris.coords import AuxCoord, DimCoord +from iris.cube import Cube +from iris.tests import mock + + +class Test(tests.IrisTest): + def test_init(self): + name = 'percentile' + call_func = _percentile + units_func = mock.sentinel.units_func + lazy_func = mock.sentinel.lazy_func + aggregator = PercentileAggregator(units_func=units_func, + lazy_func=lazy_func) + self.assertEqual(aggregator.name(), name) + self.assertIs(aggregator.call_func, call_func) + self.assertIs(aggregator.units_func, units_func) + self.assertIs(aggregator.lazy_func, lazy_func) + self.assertIsNone(aggregator.cell_method) + + +class Test_post_process(tests.IrisTest): + def setUp(self): + shape = (2, 5) + data = np.arange(np.prod(shape)) + + self.coord_simple = DimCoord(data, 'time') + self.cube_simple = Cube(data) + self.cube_simple.add_dim_coord(self.coord_simple, 0) + + self.coord_multi_0 = DimCoord(np.arange(shape[0]), 'time') + self.coord_multi_1 = DimCoord(np.arange(shape[1]), 'height') + self.cube_multi = Cube(data.reshape(shape)) + self.cube_multi.add_dim_coord(self.coord_multi_0, 0) + self.cube_multi.add_dim_coord(self.coord_multi_1, 1) + + def test_missing_mandatory_kwarg(self): + aggregator = PercentileAggregator() + emsg = "percentile aggregator requires .* keyword argument 'percent'" + with self.assertRaisesRegexp(ValueError, emsg): + aggregator.aggregate('dummy', axis=0) + + def test_simple_single_point(self): + aggregator = PercentileAggregator() + percent = 50 + kwargs = dict(percent=percent) + data = np.empty(self.cube_simple.shape) + coords = [self.coord_simple] + actual = aggregator.post_process(self.cube_simple, data, coords, + **kwargs) + self.assertEqual(actual.shape, self.cube_simple.shape) + self.assertIs(actual.data, data) + name = 'percentile_over_time' + coord = actual.coord(name) + expected = AuxCoord(percent, long_name=name) + self.assertEqual(coord, expected) + + def test_simple_multiple_points(self): + aggregator = PercentileAggregator() + percent = np.array([10, 20, 50, 90]) + kwargs = dict(percent=percent) + shape = self.cube_simple.shape + percent.shape + data = np.empty(shape) + coords = [self.coord_simple] + actual = aggregator.post_process(self.cube_simple, data, coords, + **kwargs) + self.assertEqual(actual.shape, percent.shape + self.cube_simple.shape) + expected = np.rollaxis(data, -1) + self.assertArrayEqual(actual.data, expected) + name = 'percentile_over_time' + coord = actual.coord(name) + expected = AuxCoord(percent, long_name=name) + self.assertEqual(coord, expected) + + def test_multi_single_point(self): + aggregator = PercentileAggregator() + percent = 70 + kwargs = dict(percent=percent) + data = np.empty(self.cube_multi.shape) + coords = [self.coord_multi_0] + actual = aggregator.post_process(self.cube_multi, data, coords, + **kwargs) + self.assertEqual(actual.shape, self.cube_multi.shape) + self.assertIs(actual.data, data) + name = 'percentile_over_time' + coord = actual.coord(name) + expected = AuxCoord(percent, long_name=name) + self.assertEqual(coord, expected) + + def test_multi_multiple_points(self): + aggregator = PercentileAggregator() + percent = np.array([17, 29, 81]) + kwargs = dict(percent=percent) + shape = self.cube_multi.shape + percent.shape + data = np.empty(shape) + coords = [self.coord_multi_0] + actual = aggregator.post_process(self.cube_multi, data, coords, + **kwargs) + self.assertEqual(actual.shape, percent.shape + self.cube_multi.shape) + expected = np.rollaxis(data, -1) + self.assertArrayEqual(actual.data, expected) + name = 'percentile_over_time' + coord = actual.coord(name) + expected = AuxCoord(percent, long_name=name) + self.assertEqual(coord, expected) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/test_RMS.py b/lib/iris/tests/unit/analysis/test_RMS.py index 2795ad8c82..57d92cd3c6 100644 --- a/lib/iris/tests/unit/analysis/test_RMS.py +++ b/lib/iris/tests/unit/analysis/test_RMS.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -16,6 +16,9 @@ # along with Iris. If not, see . """Unit tests for the :data:`iris.analysis.RMS` aggregator.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests @@ -27,7 +30,6 @@ class Test_aggregate(tests.IrisTest): - def test_1d(self): # 1-dimensional input data = np.array([5, 2, 6, 4], dtype=np.float64) @@ -86,5 +88,19 @@ def test_masked_weighted(self): self.assertAlmostEqual(rms, expected_rms) +class Test_name(tests.IrisTest): + def test(self): + self.assertEqual(RMS.name(), 'root_mean_square') + + +class Test_aggregate_shape(tests.IrisTest): + def test(self): + shape = () + kwargs = dict() + self.assertTupleEqual(RMS.aggregate_shape(**kwargs), shape) + kwargs = dict(tom='jerry', calvin='hobbes') + self.assertTupleEqual(RMS.aggregate_shape(**kwargs), shape) + + if __name__ == "__main__": tests.main() diff --git a/lib/iris/tests/unit/analysis/test_STD_DEV.py b/lib/iris/tests/unit/analysis/test_STD_DEV.py new file mode 100644 index 0000000000..57cc00132f --- /dev/null +++ b/lib/iris/tests/unit/analysis/test_STD_DEV.py @@ -0,0 +1,96 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :data:`iris.analysis.STD_DEV` aggregator.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris._lazy_data import as_concrete_data, as_lazy_data, is_lazy_data +from iris.analysis import STD_DEV +from iris.cube import Cube +from iris.coords import DimCoord + + +class Test_basics(tests.IrisTest): + def setUp(self): + data = np.array([1, 2, 3, 4, 5]) + coord = DimCoord([6, 7, 8, 9, 10], long_name='foo') + self.cube = Cube(data) + self.cube.add_dim_coord(coord, 0) + self.lazy_cube = Cube(as_lazy_data(data)) + self.lazy_cube.add_dim_coord(coord, 0) + + def test_name(self): + self.assertEqual(STD_DEV.name(), 'standard_deviation') + + def test_collapse(self): + data = STD_DEV.aggregate(self.cube.data, axis=0) + self.assertArrayAlmostEqual(data, [1.58113883]) + + def test_lazy(self): + lazy_data = STD_DEV.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0) + self.assertTrue(is_lazy_data(lazy_data)) + + def test_lazy_collapse(self): + lazy_data = STD_DEV.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0) + self.assertArrayAlmostEqual(lazy_data.compute(), [1.58113883]) + + +class Test_lazy_aggregate(tests.IrisTest): + def test_mdtol(self): + na = -999.888 + array = np.ma.masked_equal([[1., 2., 1., 2.], + [1., 2., 3., na], + [1., 2., na, na]], + na) + array = as_lazy_data(array) + var = STD_DEV.lazy_aggregate(array, axis=1, mdtol=0.3) + masked_result = as_concrete_data(var) + masked_expected = np.ma.masked_array([0.57735, 1., 0.707107], + mask=[0, 0, 1]) + self.assertMaskedArrayAlmostEqual(masked_result, masked_expected) + + def test_ddof_one(self): + array = as_lazy_data(np.arange(8)) + var = STD_DEV.lazy_aggregate(array, axis=0, ddof=1) + result = as_concrete_data(var) + self.assertArrayAlmostEqual(result, np.array(2.449489)) + + def test_ddof_zero(self): + array = as_lazy_data(np.arange(8)) + var = STD_DEV.lazy_aggregate(array, axis=0, ddof=0) + result = as_concrete_data(var) + self.assertArrayAlmostEqual(result, np.array(2.291287)) + + +class Test_aggregate_shape(tests.IrisTest): + def test(self): + shape = () + kwargs = dict() + self.assertTupleEqual(STD_DEV.aggregate_shape(**kwargs), shape) + kwargs = dict(forfar=5, fife=4) + self.assertTupleEqual(STD_DEV.aggregate_shape(**kwargs), shape) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/analysis/test_SUM.py b/lib/iris/tests/unit/analysis/test_SUM.py new file mode 100644 index 0000000000..0a0f2332ab --- /dev/null +++ b/lib/iris/tests/unit/analysis/test_SUM.py @@ -0,0 +1,153 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :data:`iris.analysis.SUM` aggregator.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np +import numpy.ma as ma + +from iris.analysis import SUM +from iris.cube import Cube +from iris.coords import DimCoord +from iris._lazy_data import as_lazy_data, is_lazy_data + + +class Test_basics(tests.IrisTest): + def setUp(self): + data = np.array([1, 2, 3, 4, 5]) + coord = DimCoord([6, 7, 8, 9, 10], long_name='foo') + self.cube = Cube(data) + self.cube.add_dim_coord(coord, 0) + self.lazy_cube = Cube(as_lazy_data(data)) + self.lazy_cube.add_dim_coord(coord, 0) + + def test_name(self): + self.assertEqual(SUM.name(), 'sum') + + def test_collapse(self): + data = SUM.aggregate(self.cube.data, axis=0) + self.assertArrayEqual(data, [15]) + + def test_lazy(self): + lazy_data = SUM.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0) + self.assertTrue(is_lazy_data(lazy_data)) + + def test_lazy_collapse(self): + lazy_data = SUM.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0) + self.assertArrayEqual(lazy_data.compute(), [15]) + + +class Test_masked(tests.IrisTest): + def setUp(self): + self.cube = Cube(ma.masked_equal([1, 2, 3, 4, 5], 3)) + self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0) + + def test_ma(self): + data = SUM.aggregate(self.cube.data, axis=0) + self.assertArrayEqual(data, [12]) + + +class Test_lazy_masked(tests.IrisTest): + def setUp(self): + masked_data = ma.masked_equal([1, 2, 3, 4, 5], 3) + self.cube = Cube(as_lazy_data(masked_data)) + self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0) + + def test_lazy_ma(self): + lazy_data = SUM.lazy_aggregate(self.cube.lazy_data(), axis=0) + self.assertTrue(is_lazy_data(lazy_data)) + self.assertArrayEqual(lazy_data.compute(), [12]) + + +class Test_weights_and_returned(tests.IrisTest): + def setUp(self): + data_2d = np.arange(1, 11).reshape(2, 5) + coord_0 = DimCoord([11, 12], long_name='bar') + coord_1 = DimCoord([6, 7, 8, 9, 10], long_name='foo') + self.cube_2d = Cube(data_2d) + self.cube_2d.add_dim_coord(coord_0, 0) + self.cube_2d.add_dim_coord(coord_1, 1) + self.weights = np.array([2, 1, 1, 1, 1] * 2).reshape(2, 5) + + def test_weights(self): + data = SUM.aggregate(self.cube_2d.data, axis=0, weights=self.weights) + self.assertArrayEqual(data, [14, 9, 11, 13, 15]) + + def test_returned(self): + data, weights = SUM.aggregate(self.cube_2d.data, axis=0, returned=True) + self.assertArrayEqual(data, [7, 9, 11, 13, 15]) + self.assertArrayEqual(weights, [2, 2, 2, 2, 2]) + + def test_weights_and_returned(self): + data, weights = SUM.aggregate(self.cube_2d.data, axis=0, + weights=self.weights, + returned=True) + self.assertArrayEqual(data, [14, 9, 11, 13, 15]) + self.assertArrayEqual(weights, [4, 2, 2, 2, 2]) + + +class Test_lazy_weights_and_returned(tests.IrisTest): + def setUp(self): + data_2d = np.arange(1, 11).reshape(2, 5) + coord_0 = DimCoord([11, 12], long_name='bar') + coord_1 = DimCoord([6, 7, 8, 9, 10], long_name='foo') + self.cube_2d = Cube(as_lazy_data(data_2d)) + self.cube_2d.add_dim_coord(coord_0, 0) + self.cube_2d.add_dim_coord(coord_1, 1) + self.weights = np.array([2, 1, 1, 1, 1] * 2).reshape(2, 5) + + def test_weights(self): + lazy_data = SUM.lazy_aggregate(self.cube_2d.lazy_data(), axis=0, + weights=self.weights) + self.assertTrue(is_lazy_data(lazy_data)) + self.assertArrayEqual(lazy_data.compute(), [14, 9, 11, 13, 15]) + + def test_returned(self): + lazy_data, weights = SUM.lazy_aggregate(self.cube_2d.lazy_data(), + axis=0, + returned=True) + self.assertTrue(is_lazy_data(lazy_data)) + self.assertArrayEqual(lazy_data.compute(), [7, 9, 11, 13, 15]) + self.assertArrayEqual(weights, [2, 2, 2, 2, 2]) + + def test_weights_and_returned(self): + lazy_data, weights = SUM.lazy_aggregate(self.cube_2d.lazy_data(), + axis=0, + weights=self.weights, + returned=True) + self.assertTrue(is_lazy_data(lazy_data)) + self.assertArrayEqual(lazy_data.compute(), [14, 9, 11, 13, 15]) + self.assertArrayEqual(weights, [4, 2, 2, 2, 2]) + + +class Test_aggregate_shape(tests.IrisTest): + def test(self): + shape = () + kwargs = dict() + self.assertTupleEqual(SUM.aggregate_shape(**kwargs), shape) + kwargs = dict(wibble='wobble') + self.assertTupleEqual(SUM.aggregate_shape(**kwargs), shape) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/test_VARIANCE.py b/lib/iris/tests/unit/analysis/test_VARIANCE.py index 26007ac51c..d56bf3b36a 100644 --- a/lib/iris/tests/unit/analysis/test_VARIANCE.py +++ b/lib/iris/tests/unit/analysis/test_VARIANCE.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -16,13 +16,22 @@ # along with Iris. If not, see . """Unit tests for the :data:`iris.analysis.VARIANCE` aggregator.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import mock +import numpy as np +import numpy.ma as ma +from iris._lazy_data import as_lazy_data, as_concrete_data from iris.analysis import VARIANCE +import iris.cube +from iris.coords import DimCoord + +from iris.tests import mock class Test_units_func(tests.IrisTest): @@ -36,5 +45,56 @@ def test(self): self.assertEqual(new_units, mock.sentinel.new_unit) +class Test_masked(tests.IrisTest): + def setUp(self): + self.cube = iris.cube.Cube(ma.masked_equal([1, 2, 3, 4, 5], 3)) + self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], + long_name='foo'), 0) + + def test_ma_ddof0(self): + cube = self.cube.collapsed("foo", VARIANCE, ddof=0) + expected = 10 / 4. + self.assertArrayEqual(np.var(self.cube.data, ddof=0), expected) + self.assertArrayAlmostEqual(cube.data, expected) + + def test_ma_ddof1(self): + cube = self.cube.collapsed("foo", VARIANCE, ddof=1) + expected = 10 / 3. + self.assertArrayEqual(np.var(self.cube.data, ddof=1), expected) + self.assertArrayEqual(cube.data, expected) + + # test that the default ddof is 1 + default_cube = self.cube.collapsed("foo", VARIANCE) + self.assertArrayEqual(cube.data, default_cube.data) + + +class Test_lazy_aggregate(tests.IrisTest): + def test_ddof_one(self): + array = as_lazy_data(np.arange(8)) + var = VARIANCE.lazy_aggregate(array, axis=0, ddof=1) + result = as_concrete_data(var) + self.assertArrayAlmostEqual(result, np.array(6.0)) + + def test_ddof_zero(self): + array = as_lazy_data(np.arange(8)) + var = VARIANCE.lazy_aggregate(array, axis=0, ddof=0) + result = as_concrete_data(var) + self.assertArrayAlmostEqual(result, np.array(5.25)) + + +class Test_name(tests.IrisTest): + def test(self): + self.assertEqual(VARIANCE.name(), 'variance') + + +class Test_aggregate_shape(tests.IrisTest): + def test(self): + shape = () + kwargs = dict() + self.assertTupleEqual(VARIANCE.aggregate_shape(**kwargs), shape) + kwargs = dict(bat='man', wonder='woman') + self.assertTupleEqual(VARIANCE.aggregate_shape(**kwargs), shape) + + if __name__ == "__main__": tests.main() diff --git a/lib/iris/tests/unit/analysis/test_WPERCENTILE.py b/lib/iris/tests/unit/analysis/test_WPERCENTILE.py new file mode 100644 index 0000000000..09e02e152f --- /dev/null +++ b/lib/iris/tests/unit/analysis/test_WPERCENTILE.py @@ -0,0 +1,233 @@ +# (C) British Crown Copyright 2015 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :data:`iris.analysis.PERCENTILE` aggregator.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np +import numpy.ma as ma + +from iris.analysis import WPERCENTILE + + +class Test_aggregate(tests.IrisTest): + def test_missing_mandatory_kwargs(self): + emsg = "weighted_percentile aggregator requires " \ + ".* keyword argument 'percent'" + with self.assertRaisesRegexp(ValueError, emsg): + WPERCENTILE.aggregate('dummy', axis=0, weights=None) + emsg = "weighted_percentile aggregator requires " \ + ".* keyword argument 'weights'" + with self.assertRaisesRegexp(ValueError, emsg): + WPERCENTILE.aggregate('dummy', axis=0, percent=50) + + def test_wrong_weights_shape(self): + data = np.arange(11) + weights = np.ones(10) + emsg = "_weighted_percentile: weights wrong shape." + with self.assertRaisesRegexp(ValueError, emsg): + WPERCENTILE.aggregate(data, axis=0, percent=50, weights=weights) + + def test_1d_single(self): + data = np.arange(11) + weights = np.ones(data.shape) + actual = WPERCENTILE.aggregate(data, axis=0, percent=50, + weights=weights) + expected = 5 + self.assertTupleEqual(actual.shape, ()) + self.assertEqual(actual, expected) + + def test_1d_single_unequal(self): + data = np.arange(12) + weights = np.ones(data.shape) + weights[0:3] = 3 + actual, weight_total = WPERCENTILE.aggregate( + data, axis=0, percent=50, weights=weights, returned=True) + expected = 2.75 + self.assertTupleEqual(actual.shape, ()) + self.assertEqual(actual, expected) + self.assertEqual(weight_total, 18) + + def test_masked_1d_single(self): + data = ma.arange(11) + weights = np.ones(data.shape) + data[3:7] = ma.masked + actual = WPERCENTILE.aggregate(data, axis=0, percent=50, + weights=weights) + expected = 7 + self.assertTupleEqual(actual.shape, ()) + self.assertEqual(actual, expected) + + def test_1d_multi(self): + data = np.arange(11) + weights = np.ones(data.shape) + percent = np.array([20, 50, 90]) + actual = WPERCENTILE.aggregate(data, axis=0, percent=percent, + weights=weights) + expected = [1.7, 5, 9.4] + self.assertTupleEqual(actual.shape, percent.shape) + self.assertArrayAlmostEqual(actual, expected) + + def test_1d_multi_unequal(self): + data = np.arange(13) + weights = np.ones(data.shape) + weights[1::2] = 3 + percent = np.array([20, 50, 96]) + actual = WPERCENTILE.aggregate(data, axis=0, percent=percent, + weights=weights) + expected = [2.25, 6, 11.75] + self.assertTupleEqual(actual.shape, percent.shape) + self.assertArrayAlmostEqual(actual, expected) + + def test_masked_1d_multi(self): + data = ma.arange(11) + weights = np.ones(data.shape) + data[3:9] = ma.masked + percent = np.array([25, 50, 75]) + actual = WPERCENTILE.aggregate(data, axis=0, percent=percent, + weights=weights) + expected = [0.75, 2, 9.25] + self.assertTupleEqual(actual.shape, percent.shape) + self.assertArrayAlmostEqual(actual, expected) + + def test_2d_single(self): + shape = (2, 11) + data = np.arange(np.prod(shape)).reshape(shape) + weights = np.ones(shape) + actual = WPERCENTILE.aggregate(data, axis=0, percent=50, + weights=weights) + self.assertTupleEqual(actual.shape, shape[-1:]) + expected = np.arange(shape[-1]) + 5.5 + self.assertArrayEqual(actual, expected) + + def test_masked_2d_single(self): + shape = (2, 11) + data = ma.arange(np.prod(shape)).reshape(shape) + data[0, ::2] = ma.masked + data[1, 1::2] = ma.masked + weights = np.ones(shape) + actual = WPERCENTILE.aggregate(data, axis=0, percent=50, + weights=weights) + self.assertTupleEqual(actual.shape, shape[-1:]) + expected = np.empty(shape[-1:]) + expected[1::2] = data[0, 1::2] + expected[::2] = data[1, ::2] + self.assertArrayEqual(actual, expected) + + def test_2d_multi(self): + shape = (2, 10) + data = np.arange(np.prod(shape)).reshape(shape) + weights = np.ones(shape) + percent = np.array([10, 50, 70, 100]) + actual = WPERCENTILE.aggregate(data, axis=0, percent=percent, + weights=weights) + self.assertTupleEqual(actual.shape, (shape[-1], percent.size)) + expected = np.tile(np.arange(shape[-1]), percent.size).astype('f8') + expected = expected.reshape(percent.size, shape[-1]).T + expected[:, 1:-1] += (percent[1:-1]-25)*0.2 + expected[:, -1] += 10. + self.assertArrayAlmostEqual(actual, expected) + + def test_masked_2d_multi(self): + shape = (3, 10) + data = ma.arange(np.prod(shape)).reshape(shape) + weights = np.ones(shape) + data[1] = ma.masked + percent = np.array([10, 50, 70, 80]) + actual = WPERCENTILE.aggregate(data, axis=0, percent=percent, + weights=weights) + self.assertTupleEqual(actual.shape, (shape[-1], percent.size)) + expected = np.tile(np.arange(shape[-1]), percent.size).astype('f8') + expected = expected.reshape(percent.size, shape[-1]).T + expected[:, 1:-1] += (percent[1:-1]-25)*0.4 + expected[:, -1] += 20. + self.assertArrayAlmostEqual(actual, expected) + + def test_masked_2d_multi_unequal(self): + shape = (3, 10) + data = ma.arange(np.prod(shape)).reshape(shape) + weights = np.ones(shape) + weights[0] = 3 + data[1] = ma.masked + percent = np.array([30, 50, 75, 80]) + actual, weight_total = WPERCENTILE.aggregate( + data, axis=0, percent=percent, weights=weights, returned=True) + self.assertTupleEqual(actual.shape, (shape[-1], percent.size)) + expected = np.tile(np.arange(shape[-1]), percent.size) + expected = expected.reshape(percent.size, shape[-1]).T + expected[:, 1:] = 2.0 * ( + (0.875 - percent[1:]/100.0) * data[0, np.newaxis].T + + (percent[1:]/100.0 - 0.375) * data[-1, np.newaxis].T + ) + self.assertArrayAlmostEqual(actual, expected) + self.assertTupleEqual(weight_total.shape, (shape[-1],)) + self.assertArrayEqual(weight_total, np.repeat(4, shape[-1])) + + +class Test_name(tests.IrisTest): + def test(self): + self.assertEqual(WPERCENTILE.name(), 'weighted_percentile') + + +class Test_aggregate_shape(tests.IrisTest): + def test_missing_mandatory_kwarg(self): + emsg_pc = "weighted_percentile aggregator requires " \ + ".* keyword argument 'percent'" + emsg_wt = "weighted_percentile aggregator requires " \ + ".* keyword argument 'weights'" + with self.assertRaisesRegexp(ValueError, emsg_pc): + WPERCENTILE.aggregate_shape(weights=None) + with self.assertRaisesRegexp(ValueError, emsg_pc): + kwargs = dict(weights=None) + WPERCENTILE.aggregate_shape(**kwargs) + with self.assertRaisesRegexp(ValueError, emsg_pc): + kwargs = dict(point=10) + WPERCENTILE.aggregate_shape(**kwargs) + with self.assertRaisesRegexp(ValueError, emsg_wt): + WPERCENTILE.aggregate_shape(percent=50) + with self.assertRaisesRegexp(ValueError, emsg_wt): + kwargs = dict(percent=50) + WPERCENTILE.aggregate_shape(**kwargs) + with self.assertRaisesRegexp(ValueError, emsg_wt): + kwargs = dict(percent=50, weight=None) + WPERCENTILE.aggregate_shape(**kwargs) + + def test_mandatory_kwarg_no_shape(self): + kwargs = dict(percent=50, weights=None) + self.assertTupleEqual(WPERCENTILE.aggregate_shape(**kwargs), ()) + kwargs = dict(percent=[50], weights=None) + self.assertTupleEqual(WPERCENTILE.aggregate_shape(**kwargs), ()) + + def test_mandatory_kwarg_shape(self): + kwargs = dict(percent=(10, 20), weights=None) + self.assertTupleEqual(WPERCENTILE.aggregate_shape(**kwargs), (2,)) + kwargs = dict(percent=range(13), weights=None) + self.assertTupleEqual(WPERCENTILE.aggregate_shape(**kwargs), (13,)) + + +class Test_cell_method(tests.IrisTest): + def test(self): + self.assertIsNone(WPERCENTILE.cell_method) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/test_WeightedPercentileAggregator.py b/lib/iris/tests/unit/analysis/test_WeightedPercentileAggregator.py new file mode 100644 index 0000000000..bfd69f6c8f --- /dev/null +++ b/lib/iris/tests/unit/analysis/test_WeightedPercentileAggregator.py @@ -0,0 +1,151 @@ +# (C) British Crown Copyright 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the :class:`iris.analysis.PercentileAggregator` class instance. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.analysis import WeightedPercentileAggregator, _weighted_percentile +from iris.coords import AuxCoord, DimCoord +from iris.cube import Cube +from iris.tests import mock + + +class Test(tests.IrisTest): + def test_init(self): + name = 'weighted_percentile' + call_func = _weighted_percentile + units_func = mock.sentinel.units_func + lazy_func = mock.sentinel.lazy_func + aggregator = WeightedPercentileAggregator(units_func=units_func, + lazy_func=lazy_func) + self.assertEqual(aggregator.name(), name) + self.assertIs(aggregator.call_func, call_func) + self.assertIs(aggregator.units_func, units_func) + self.assertIs(aggregator.lazy_func, lazy_func) + self.assertIsNone(aggregator.cell_method) + + +class Test_post_process(tests.IrisTest): + def setUp(self): + shape = (2, 5) + data = np.arange(np.prod(shape)) + + self.coord_simple = DimCoord(data, 'time') + self.cube_simple = Cube(data) + self.cube_simple.add_dim_coord(self.coord_simple, 0) + self.weights_simple = np.ones_like(data, dtype=float) + + self.coord_multi_0 = DimCoord(np.arange(shape[0]), 'time') + self.coord_multi_1 = DimCoord(np.arange(shape[1]), 'height') + self.cube_multi = Cube(data.reshape(shape)) + self.cube_multi.add_dim_coord(self.coord_multi_0, 0) + self.cube_multi.add_dim_coord(self.coord_multi_1, 1) + self.weights_multi = np.ones(shape, dtype=float) + + def test_missing_mandatory_kwarg(self): + aggregator = WeightedPercentileAggregator() + emsg = "weighted_percentile aggregator requires " \ + ".* keyword argument 'percent'" + with self.assertRaisesRegexp(ValueError, emsg): + aggregator.aggregate('dummy', axis=0, weights=None) + emsg = "weighted_percentile aggregator requires " \ + ".* keyword argument 'weights'" + with self.assertRaisesRegexp(ValueError, emsg): + aggregator.aggregate('dummy', axis=0, percent=50) + + def test_simple_single_point(self): + aggregator = WeightedPercentileAggregator() + percent = 50 + kwargs = dict(percent=percent, weights=self.weights_simple) + data = np.empty(self.cube_simple.shape) + coords = [self.coord_simple] + actual = aggregator.post_process(self.cube_simple, data, coords, + **kwargs) + self.assertEqual(actual.shape, self.cube_simple.shape) + self.assertIs(actual.data, data) + name = 'weighted_percentile_over_time' + coord = actual.coord(name) + expected = AuxCoord(percent, long_name=name) + self.assertEqual(coord, expected) + + def test_simple_multiple_points(self): + aggregator = WeightedPercentileAggregator() + percent = np.array([10, 20, 50, 90]) + kwargs = dict(percent=percent, weights=self.weights_simple, + returned=True) + shape = self.cube_simple.shape + percent.shape + data = np.empty(shape) + total_weights = 1. + coords = [self.coord_simple] + actual = aggregator.post_process( + self.cube_simple, (data, total_weights), coords, **kwargs) + self.assertEqual(len(actual), 2) + self.assertEqual(actual[0].shape, + percent.shape + self.cube_simple.shape) + expected = np.rollaxis(data, -1) + self.assertArrayEqual(actual[0].data, expected) + self.assertIs(actual[1], total_weights) + name = 'weighted_percentile_over_time' + coord = actual[0].coord(name) + expected = AuxCoord(percent, long_name=name) + self.assertEqual(coord, expected) + + def test_multi_single_point(self): + aggregator = WeightedPercentileAggregator() + percent = 70 + kwargs = dict(percent=percent, weights=self.weights_multi) + data = np.empty(self.cube_multi.shape) + coords = [self.coord_multi_0] + actual = aggregator.post_process(self.cube_multi, data, coords, + **kwargs) + self.assertEqual(actual.shape, self.cube_multi.shape) + self.assertIs(actual.data, data) + name = 'weighted_percentile_over_time' + coord = actual.coord(name) + expected = AuxCoord(percent, long_name=name) + self.assertEqual(coord, expected) + + def test_multi_multiple_points(self): + aggregator = WeightedPercentileAggregator() + percent = np.array([17, 29, 81]) + kwargs = dict(percent=percent, weights=self.weights_multi) + shape = self.cube_multi.shape + percent.shape + data = np.empty(shape) + coords = [self.coord_multi_0] + actual = aggregator.post_process(self.cube_multi, data, coords, + **kwargs) + self.assertEqual(actual.shape, percent.shape + self.cube_multi.shape) + expected = np.rollaxis(data, -1) + self.assertArrayEqual(actual.data, expected) + name = 'weighted_percentile_over_time' + coord = actual.coord(name) + expected = AuxCoord(percent, long_name=name) + self.assertEqual(coord, expected) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/trajectory/__init__.py b/lib/iris/tests/unit/analysis/trajectory/__init__.py new file mode 100644 index 0000000000..da78cf3095 --- /dev/null +++ b/lib/iris/tests/unit/analysis/trajectory/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.analysis.trajectory` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/analysis/trajectory/test_Trajectory.py b/lib/iris/tests/unit/analysis/trajectory/test_Trajectory.py new file mode 100644 index 0000000000..e15a8c3d4f --- /dev/null +++ b/lib/iris/tests/unit/analysis/trajectory/test_Trajectory.py @@ -0,0 +1,186 @@ +# (C) British Crown Copyright 2016 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for :class:`iris.analysis.trajectory.Trajectory`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import mock + +import numpy as np + +from iris.analysis.trajectory import Trajectory +from iris.tests.stock import simple_3d, simple_4d_with_hybrid_height + + +class Test___init__(tests.IrisTest): + def test_2_points(self): + # basic 2-seg line along x + waypoints = [{'lat': 0, 'lon': 0}, {'lat': 1, 'lon': 2}] + trajectory = Trajectory(waypoints, sample_count=5) + + self.assertEqual(trajectory.length, np.sqrt(5)) + self.assertEqual(trajectory.sample_count, 5) + self.assertEqual(trajectory.sampled_points, + [{'lat': 0.0, 'lon': 0.0}, + {'lat': 0.25, 'lon': 0.5}, + {'lat': 0.5, 'lon': 1.0}, + {'lat': 0.75, 'lon': 1.5}, + {'lat': 1.0, 'lon': 2.0}]) + + def test_3_points(self): + # basic 2-seg line along x + waypoints = [{'lat': 0, 'lon': 0}, {'lat': 0, 'lon': 1}, + {'lat': 0, 'lon': 2}] + trajectory = Trajectory(waypoints, sample_count=21) + + self.assertEqual(trajectory.length, 2.0) + self.assertEqual(trajectory.sample_count, 21) + self.assertEqual(trajectory.sampled_points[19], + {'lat': 0.0, 'lon': 1.9000000000000001}) + + def test_zigzag(self): + # 4-seg m-shape + waypoints = [{'lat': 0, 'lon': 0}, {'lat': 1, 'lon': 1}, + {'lat': 0, 'lon': 2}, {'lat': 1, 'lon': 3}, + {'lat': 0, 'lon': 4}] + trajectory = Trajectory(waypoints, sample_count=33) + + self.assertEqual(trajectory.length, 5.6568542494923806) + self.assertEqual(trajectory.sample_count, 33) + self.assertEqual(trajectory.sampled_points[31], + {'lat': 0.12499999999999989, 'lon': 3.875}) + + +class Test__get_interp_points(tests.IrisTest): + def test_basic(self): + dim_names = 'lat' + waypoints = [{dim_names: 0}, {dim_names: 1}] + sample_count = 5 + trajectory = Trajectory(waypoints, sample_count=sample_count) + result = trajectory._get_interp_points() + expected_points = list(np.linspace(0, 1, sample_count)) + + self.assertEqual(len(result), len(waypoints[0])) + self.assertEqual(len(result[0][1]), sample_count) + self.assertEqual(result[0][1], expected_points) + self.assertEqual(result[0][0], dim_names) + + def test_2d(self): + dim_names = ['lat', 'lon'] + waypoints = [{dim_names[0]: 0, dim_names[1]: 0}, + {dim_names[0]: 1, dim_names[1]: 2}] + sample_count = 5 + trajectory = Trajectory(waypoints, sample_count=sample_count) + result = trajectory._get_interp_points() + + self.assertEqual(len(result), len(waypoints[0])) + self.assertEqual(len(result[0][1]), sample_count) + self.assertEqual(len(result[1][1]), sample_count) + self.assertIn(result[0][0], dim_names) + self.assertIn(result[1][0], dim_names) + + def test_3d(self): + dim_names = ['y', 'x', 'z'] + waypoints = [{dim_names[0]: 0, dim_names[1]: 0, dim_names[2]: 2}, + {dim_names[0]: 1, dim_names[1]: 2, dim_names[2]: 10}] + sample_count = 5 + trajectory = Trajectory(waypoints, sample_count=sample_count) + result = trajectory._get_interp_points() + + self.assertEqual(len(result), len(waypoints[0])) + self.assertEqual(len(result[0][1]), sample_count) + self.assertEqual(len(result[1][1]), sample_count) + self.assertEqual(len(result[2][1]), sample_count) + self.assertIn(result[0][0], dim_names) + self.assertIn(result[1][0], dim_names) + self.assertIn(result[2][0], dim_names) + + +class Test_interpolate(tests.IrisTest): + def _result_cube_metadata(self, res_cube): + dim_names = [c.name() for c in res_cube.dim_coords] + named_dims = [res_cube.coord_dims(c)[0] for c in res_cube.dim_coords] + anon_dims = list(set(range(res_cube.ndim)) - set(named_dims)) + anon_dims = None if not len(anon_dims) else anon_dims + return dim_names, named_dims, anon_dims + + def test_cube__simple_3d(self): + # Test that an 'index' coord is added to the resultant cube. + cube = simple_3d() + waypoints = [{'latitude': 40, 'longitude': 40}, + {'latitude': 0, 'longitude': 0}] + sample_count = 3 + new_coord_name = 'index' + trajectory = Trajectory(waypoints, sample_count=sample_count) + result = trajectory.interpolate(cube) + + dim_names, named_dims, anon_dims = self._result_cube_metadata(result) + new_coord = result.coord(new_coord_name) + exp_named_dims = [0, 1] + + self.assertEqual(result.ndim, cube.ndim - 1) + self.assertIn(new_coord_name, dim_names) + self.assertEqual(named_dims, exp_named_dims) + self.assertIsNone(anon_dims) + self.assertEqual(len(new_coord.points), sample_count) + + def test_cube__anon_dim(self): + cube = simple_4d_with_hybrid_height() + cube.remove_coord('model_level_number') # Make cube dim 1 anonymous. + waypoints = [{'grid_latitude': 21, 'grid_longitude': 31}, + {'grid_latitude': 23, 'grid_longitude': 33}] + sample_count = 4 + new_coord_name = 'index' + trajectory = Trajectory(waypoints, sample_count=sample_count) + result = trajectory.interpolate(cube) + + dim_names, named_dims, anon_dims = self._result_cube_metadata(result) + new_coord = result.coord(new_coord_name) + exp_named_dims = [0, 2] + exp_anon_dims = [1] + + self.assertEqual(result.ndim, cube.ndim - 1) + self.assertIn(new_coord_name, dim_names) + self.assertEqual(named_dims, exp_named_dims) + self.assertEqual(anon_dims, exp_anon_dims) + self.assertEqual(len(new_coord.points), sample_count) + + def test_call(self): + # Test that :func:`iris.analysis.trajectory.interpolate` is called by + # `Trajectory.interpolate`. + cube = simple_3d() + to_patch = 'iris.analysis.trajectory.interpolate' + waypoints = [{'latitude': 40, 'longitude': 40}, + {'latitude': 0, 'longitude': 0}] + sample_count = 3 + trajectory = Trajectory(waypoints, sample_count=sample_count) + + with mock.patch(to_patch, return_value=cube) as mock_interpolate: + trajectory.interpolate(cube) + mock_interpolate.assert_called_once() + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/trajectory/test_UnstructuredNearestNeighbourRegridder.py b/lib/iris/tests/unit/analysis/trajectory/test_UnstructuredNearestNeighbourRegridder.py new file mode 100644 index 0000000000..c911e70bc2 --- /dev/null +++ b/lib/iris/tests/unit/analysis/trajectory/test_UnstructuredNearestNeighbourRegridder.py @@ -0,0 +1,306 @@ +# (C) British Crown Copyright 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for +:class:`iris.analysis.trajectory.UnstructuredNearestNeigbourRegridder`. + +""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from contextlib import contextmanager + +import numpy as np + +from iris.coords import AuxCoord, DimCoord +from iris.coord_systems import GeogCS, RotatedGeogCS +from iris.cube import Cube, CubeList +import iris.tests.stock + +from iris.analysis.trajectory import \ + UnstructuredNearestNeigbourRegridder as unn_gridder + + +class MixinExampleSetup(object): + # Common code for regridder test classes. + + def setUp(self): + # Basic test values. + src_x_y_value = np.array([ + [20.12, 11.73, 0.01], + [120.23, -20.73, 1.12], + [290.34, 33.88, 2.23], + [-310.45, 57.8, 3.34]]) + tgt_grid_x = np.array([-173.2, -100.3, -32.5, 1.4, 46.6, 150.7]) + tgt_grid_y = np.array([-80.1, -30.2, 0.3, 47.4, 75.5]) + + # Make sample 1-D source cube. + src = Cube(src_x_y_value[:, 2]) + src.add_aux_coord(AuxCoord(src_x_y_value[:, 0], + standard_name='longitude', units='degrees'), + 0) + src.add_aux_coord(AuxCoord(src_x_y_value[:, 1], + standard_name='latitude', units='degrees'), + 0) + self.src_cube = src + + # Make sample grid cube. + grid = Cube(np.zeros(tgt_grid_y.shape + tgt_grid_x.shape)) + grid.add_dim_coord(DimCoord(tgt_grid_y, + standard_name='latitude', units='degrees'), + 0) + grid.add_dim_coord(DimCoord(tgt_grid_x, + standard_name='longitude', + units='degrees'), + 1) + self.grid_cube = grid + + # Make expected-result, from the expected source-index at each point. + expected_result_indices = np.array([ + [1, 1, 1, 1, 1, 1], + [1, 2, 0, 0, 0, 1], + [1, 2, 2, 0, 0, 1], + [3, 2, 2, 3, 3, 3], + [3, 2, 3, 3, 3, 3]]) + self.expected_data = self.src_cube.data[expected_result_indices] + + # Make a 3D source cube, based on the existing 2d test data. + z_cubes = [src.copy() for _ in range(3)] + for i_z, z_cube in enumerate(z_cubes): + z_cube.add_aux_coord(DimCoord([i_z], long_name='z')) + z_cube.data = z_cube.data + 100.0 * i_z + self.src_z_cube = CubeList(z_cubes).merge_cube() + + # Make a corresponding 3d expected result. + self.expected_data_zxy = \ + self.src_z_cube.data[:, expected_result_indices] + + def _check_expected(self, src_cube=None, grid_cube=None, + expected_data=None, + expected_coord_names=None): + # Test regridder creation + operation against expected results. + if src_cube is None: + src_cube = self.src_cube + if grid_cube is None: + grid_cube = self.grid_cube + gridder = unn_gridder(src_cube, grid_cube) + result = gridder(src_cube) + if expected_coord_names is not None: + # Check result coordinate identities. + self.assertEqual([coord.name() for coord in result.coords()], + expected_coord_names) + if expected_data is None: + # By default, check against the 'standard' data result. + expected_data = self.expected_data + self.assertArrayEqual(result.data, expected_data) + return result + + +class Test__init__(MixinExampleSetup, tests.IrisTest): + # Exercise all the constructor argument checks. + + def test_fail_no_src_x(self): + self.src_cube.remove_coord('longitude') + msg_re = 'Source cube must have X- and Y-axis coordinates' + with self.assertRaisesRegexp(ValueError, msg_re): + unn_gridder(self.src_cube, self.grid_cube) + + def test_fail_no_src_y(self): + self.src_cube.remove_coord('latitude') + msg_re = 'Source cube must have X- and Y-axis coordinates' + with self.assertRaisesRegexp(ValueError, msg_re): + unn_gridder(self.src_cube, self.grid_cube) + + def test_fail_bad_src_dims(self): + self.src_cube = self.grid_cube + msg_re = 'Source.*same cube dimensions' + with self.assertRaisesRegexp(ValueError, msg_re): + unn_gridder(self.src_cube, self.grid_cube) + + def test_fail_mixed_latlons(self): + self.src_cube.coord('longitude').rename('projection_x_coordinate') + msg_re = 'any.*latitudes/longitudes.*all must be' + with self.assertRaisesRegexp(ValueError, msg_re): + unn_gridder(self.src_cube, self.grid_cube) + + def test_fail_bad_latlon_units(self): + self.grid_cube.coord('longitude').units = 'm' + msg_re = 'does not convert to "degrees"' + with self.assertRaisesRegexp(ValueError, msg_re): + unn_gridder(self.src_cube, self.grid_cube) + + def test_fail_non_latlon_units_mismatch(self): + # Convert all to non-latlon system (does work: see in "Test__call__"). + for cube in (self.src_cube, self.grid_cube): + for axis_name in ('x', 'y'): + coord = cube.coord(axis=axis_name) + coord_name = 'projection_{}_coordinate'.format(axis_name) + coord.rename(coord_name) + coord.units = 'm' + # Change one of the output units. + self.grid_cube.coord(axis='x').units = '1' + msg_re = 'Source and target.*must have the same units' + with self.assertRaisesRegexp(ValueError, msg_re): + unn_gridder(self.src_cube, self.grid_cube) + + def test_fail_no_tgt_x(self): + self.grid_cube.remove_coord('longitude') + msg_re = 'must contain a single 1D x coordinate' + with self.assertRaisesRegexp(ValueError, msg_re): + unn_gridder(self.src_cube, self.grid_cube) + + def test_fail_no_tgt_y(self): + self.grid_cube.remove_coord('latitude') + msg_re = 'must contain a single 1D y coordinate' + with self.assertRaisesRegexp(ValueError, msg_re): + unn_gridder(self.src_cube, self.grid_cube) + + def test_fail_src_cs_mismatch(self): + cs = GeogCS(1000.0) + self.src_cube.coord('latitude').coord_system = cs + msg_re = 'must all have the same coordinate system' + with self.assertRaisesRegexp(ValueError, msg_re): + unn_gridder(self.src_cube, self.grid_cube) + + def test_fail_tgt_cs_mismatch(self): + cs = GeogCS(1000.0) + self.grid_cube.coord('latitude').coord_system = cs + msg_re = 'x.*and y.*must have the same coordinate system' + with self.assertRaisesRegexp(ValueError, msg_re): + unn_gridder(self.src_cube, self.grid_cube) + + def test_fail_src_tgt_cs_mismatch(self): + cs = GeogCS(1000.0) + self.src_cube.coord('latitude').coord_system = cs + self.src_cube.coord('longitude').coord_system = cs + msg_re = 'Source and target.*same coordinate system' + with self.assertRaisesRegexp(ValueError, msg_re): + unn_gridder(self.src_cube, self.grid_cube) + + +class Test__call__(MixinExampleSetup, tests.IrisTest): + # Test regridder operation and results. + + def test_basic_latlon(self): + # Check a test operation. + self._check_expected(expected_coord_names=['latitude', 'longitude'], + expected_data=self.expected_data) + + def test_non_latlon(self): + # Check different answer in cartesian coordinates (no wrapping, etc). + # Convert to non-latlon system, with the same coord values. + for cube in (self.src_cube, self.grid_cube): + for axis_name in ('x', 'y'): + coord = cube.coord(axis=axis_name) + coord_name = 'projection_{}_coordinate'.format(axis_name) + coord.rename(coord_name) + coord.units = 'm' + # Check for a somewhat different result. + non_latlon_indices = np.array([ + [3, 0, 0, 0, 1, 1], + [3, 0, 0, 0, 0, 1], + [3, 0, 0, 0, 0, 1], + [3, 0, 0, 0, 0, 1], + [3, 0, 0, 0, 0, 1]]) + expected_data = self.src_cube.data[non_latlon_indices] + self._check_expected(expected_data=expected_data) + + def test_multidimensional_xy(self): + # Recast the 4-point source cube as 2*2 : should yield the same result. + co_x = self.src_cube.coord(axis='x') + co_y = self.src_cube.coord(axis='y') + new_src = Cube(self.src_cube.data.reshape((2, 2))) + new_x_co = AuxCoord(co_x.points.reshape((2, 2)), + standard_name='longitude', units='degrees') + new_y_co = AuxCoord(co_y.points.reshape((2, 2)), + standard_name='latitude', units='degrees') + new_src.add_aux_coord(new_x_co, (0, 1)) + new_src.add_aux_coord(new_y_co, (0, 1)) + self._check_expected(src_cube=new_src) + + def test_transposed_grid(self): + # Show that changing the order of the grid X and Y has no effect. + new_grid_cube = self.grid_cube.copy() + new_grid_cube.transpose((1, 0)) + # Check that the new grid is in (X, Y) order. + self.assertEqual([coord.name() for coord in new_grid_cube.coords()], + ['longitude', 'latitude']) + # Check that the result is the same, dimension order is still Y,X. + self._check_expected(grid_cube=new_grid_cube, + expected_coord_names=['latitude', 'longitude']) + + def test_compatible_source(self): + # Check operation on data with different dimensions to the original + # source cube for the regridder creation. + gridder = unn_gridder(self.src_cube, self.grid_cube) + result = gridder(self.src_z_cube) + self.assertEqual([coord.name() for coord in result.coords()], + ['z', 'latitude', 'longitude']) + self.assertArrayEqual(result.data, self.expected_data_zxy) + + def test_fail_incompatible_source(self): + # Check that a slightly modified source cube is *not* acceptable. + modified_src_cube = self.src_cube.copy() + points = modified_src_cube.coord(axis='x').points + points[0] += 0.01 + modified_src_cube.coord(axis='x').points = points + gridder = unn_gridder(self.src_cube, self.grid_cube) + msg = 'not defined on the same source grid' + with self.assertRaisesRegexp(ValueError, msg): + gridder(modified_src_cube) + + def test_transposed_source(self): + # Check operation on data where the 'trajectory' dimension is not the + # last one. + src_z_cube = self.src_z_cube + src_z_cube.transpose((1, 0)) + self._check_expected(src_cube=src_z_cube, + expected_data=self.expected_data_zxy) + + def test_radians_degrees(self): + # Check source + target unit conversions, grid and result in degrees. + for axis_name in ('x', 'y'): + self.src_cube.coord(axis=axis_name).convert_units('radians') + self.grid_cube.coord(axis=axis_name).convert_units('degrees') + result = self._check_expected() + self.assertEqual(result.coord(axis='x').units, 'degrees') + + def test_degrees_radians(self): + # Check source + target unit conversions, grid and result in radians. + for axis_name in ('x', 'y'): + self.src_cube.coord(axis=axis_name).convert_units('degrees') + self.grid_cube.coord(axis=axis_name).convert_units('radians') + result = self._check_expected() + self.assertEqual(result.coord(axis='x').units, 'radians') + + def test_alternative_cs(self): + # Check the result is just the same in a different coordinate system. + cs = RotatedGeogCS(grid_north_pole_latitude=75.3, + grid_north_pole_longitude=102.5, + ellipsoid=GeogCS(100.0)) + for cube in (self.src_cube, self.grid_cube): + for coord_name in ('longitude', 'latitude'): + cube.coord(coord_name).coord_system = cs + self._check_expected() + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/trajectory/test__nearest_neighbour_indices_ndcoords.py b/lib/iris/tests/unit/analysis/trajectory/test__nearest_neighbour_indices_ndcoords.py new file mode 100644 index 0000000000..45220b398a --- /dev/null +++ b/lib/iris/tests/unit/analysis/trajectory/test__nearest_neighbour_indices_ndcoords.py @@ -0,0 +1,227 @@ +# (C) British Crown Copyright 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for +:meth:`iris.analysis.trajectory._nearest_neighbour_indices_ndcoords`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.cube import Cube +from iris.coords import DimCoord, AuxCoord + +from iris.analysis.trajectory import \ + _nearest_neighbour_indices_ndcoords as nn_ndinds + + +class Test2d(tests.IrisTest): + def test_nonlatlon_simple_2d(self): + co_y = DimCoord([10.0, 20.0], long_name='y') + co_x = DimCoord([1.0, 2.0, 3.0], long_name='x') + cube = Cube(np.zeros((2, 3))) + cube.add_dim_coord(co_y, 0) + cube.add_dim_coord(co_x, 1) + sample_point = [('x', 2.8), ('y', 18.5)] + result = nn_ndinds(cube, sample_point) + self.assertEqual(result, [(1, 2)]) + + def test_nonlatlon_multiple_2d(self): + co_y = DimCoord([10.0, 20.0], long_name='y') + co_x = DimCoord([1.0, 2.0, 3.0], long_name='x') + cube = Cube(np.zeros((2, 3))) + cube.add_dim_coord(co_y, 0) + cube.add_dim_coord(co_x, 1) + sample_points = [('x', [2.8, -350.0, 1.7]), ('y', [18.5, 8.7, 12.2])] + result = nn_ndinds(cube, sample_points) + self.assertEqual(result, [(1, 2), (0, 0), (0, 1)]) + + def test_latlon_simple_2d(self): + co_y = DimCoord([10.0, 20.0], + standard_name='latitude', units='degrees') + co_x = DimCoord([1.0, 2.0, 3.0], + standard_name='longitude', units='degrees') + cube = Cube(np.zeros((2, 3))) + cube.add_dim_coord(co_y, 0) + cube.add_dim_coord(co_x, 1) + sample_point = [('longitude', 2.8), ('latitude', 18.5)] + result = nn_ndinds(cube, sample_point) + self.assertEqual(result, [(1, 2)]) + + def test_latlon_multiple_2d(self): + co_y = DimCoord([10.0, 20.0], + standard_name='latitude', units='degrees') + co_x = DimCoord([1.0, 2.0, 3.0], + standard_name='longitude', units='degrees') + cube = Cube(np.zeros((2, 3))) + cube.add_dim_coord(co_y, 0) + cube.add_dim_coord(co_x, 1) + sample_points = [('longitude', [2.8, -350.0, 1.7]), + ('latitude', [18.5, 8.7, 12.2])] + result = nn_ndinds(cube, sample_points) + # Note slight difference from non-latlon version. + self.assertEqual(result, [(1, 2), (0, 2), (0, 1)]) + + +class Test1d(tests.IrisTest): + def test_nonlatlon_simple_1d(self): + co_x = AuxCoord([1.0, 2.0, 3.0, 1.0, 2.0, 3.0], long_name='x') + co_y = AuxCoord([10.0, 10.0, 10.0, 20.0, 20.0, 20.0], long_name='y') + cube = Cube(np.zeros(6)) + cube.add_aux_coord(co_y, 0) + cube.add_aux_coord(co_x, 0) + sample_point = [('x', 2.8), ('y', 18.5)] + result = nn_ndinds(cube, sample_point) + self.assertEqual(result, [(5,)]) + + def test_latlon_simple_1d(self): + cube = Cube([11.0, 12.0, 13.0, 21.0, 22.0, 23.0]) + co_x = AuxCoord([1.0, 2.0, 3.0, 1.0, 2.0, 3.0], + standard_name='longitude', units='degrees') + co_y = AuxCoord([10.0, 10.0, 10.0, 20.0, 20.0, 20.0], + standard_name='latitude', units='degrees') + cube.add_aux_coord(co_y, 0) + cube.add_aux_coord(co_x, 0) + sample_point = [('longitude', 2.8), ('latitude', 18.5)] + result = nn_ndinds(cube, sample_point) + self.assertEqual(result, [(5,)]) + + +class TestApiExtras(tests.IrisTest): + # Check operation with alternative calling setups. + def test_no_y_dim(self): + # Operate in X only, returned slice should be [:, ix]. + co_x = DimCoord([1.0, 2.0, 3.0], long_name='x') + co_y = DimCoord([10.0, 20.0], long_name='y') + cube = Cube(np.zeros((2, 3))) + cube.add_dim_coord(co_y, 0) + cube.add_dim_coord(co_x, 1) + sample_point = [('x', 2.8)] + result = nn_ndinds(cube, sample_point) + self.assertEqual(result, [(slice(None), 2)]) + + def test_no_x_dim(self): + # Operate in Y only, returned slice should be [iy, :]. + co_x = DimCoord([1.0, 2.0, 3.0], long_name='x') + co_y = DimCoord([10.0, 20.0], long_name='y') + cube = Cube(np.zeros((2, 3))) + cube.add_dim_coord(co_y, 0) + cube.add_dim_coord(co_x, 1) + sample_point = [('y', 18.5)] + result = nn_ndinds(cube, sample_point) + self.assertEqual(result, [(1, slice(None))]) + + def test_sample_dictionary(self): + # Pass sample_point arg as a dictionary: this usage mode is deprecated. + co_x = AuxCoord([1.0, 2.0, 3.0], long_name='x') + co_y = AuxCoord([10.0, 20.0], long_name='y') + cube = Cube(np.zeros((2, 3))) + cube.add_aux_coord(co_y, 0) + cube.add_aux_coord(co_x, 1) + sample_point = {'x': 2.8, 'y': 18.5} + exp_emsg = 'must be a list of \(coordinate, value\) pairs' + with self.assertRaisesRegexp(TypeError, exp_emsg): + nn_ndinds(cube, sample_point) + + +class TestLatlon(tests.IrisTest): + # Check correct calculations on lat-lon points. + def _testcube_latlon_1d(self, lats, lons): + cube = Cube(np.zeros(len(lons))) + co_x = AuxCoord(lons, standard_name='longitude', units='degrees') + co_y = AuxCoord(lats, standard_name='latitude', units='degrees') + cube.add_aux_coord(co_y, 0) + cube.add_aux_coord(co_x, 0) + return cube + + def _check_latlon_1d(self, lats, lons, sample_point, expect): + cube = self._testcube_latlon_1d(lats, lons) + result = nn_ndinds(cube, sample_point) + self.assertEqual(result, [(expect,)]) + + def test_lat_scaling(self): + # Check that (88, 25) is closer to (88, 0) than to (87, 25) + self._check_latlon_1d( + lats=[88, 87], + lons=[0, 25], + sample_point=[('latitude', 88), ('longitude', 25)], + expect=0) + + def test_alternate_latlon_names_okay(self): + # Check that (88, 25) is **STILL** closer to (88, 0) than to (87, 25) + # ... when coords have odd, but still recognisable, latlon names. + cube = self._testcube_latlon_1d(lats=[88, 87], + lons=[0, 25]) + cube.coord('latitude').rename('y_latitude_y') + cube.coord('longitude').rename('x_longitude_x') + sample_point = [('y_latitude_y', 88), ('x_longitude_x', 25)] + result = nn_ndinds(cube, sample_point) + self.assertEqual(result, [(0,)]) + + def test_alternate_nonlatlon_names_different(self): + # Check that (88, 25) is **NOT** closer to (88, 0) than to (87, 25) + # ... by plain XY euclidean-distance, if coords have non-latlon names. + cube = self._testcube_latlon_1d(lats=[88, 87], + lons=[0, 25]) + cube.coord('latitude').rename('y') + cube.coord('longitude').rename('x') + sample_point = [('y', 88), ('x', 25)] + result = nn_ndinds(cube, sample_point) + self.assertEqual(result, [(1,)]) + + def test_lons_wrap_359_0(self): + # Check that (0, 359) is closer to (0, 0) than to (0, 350) + self._check_latlon_1d( + lats=[0, 0], + lons=[0, 350], + sample_point=[('latitude', 0), ('longitude', 359)], + expect=0) + + def test_lons_wrap_359_neg1(self): + # Check that (0, 359) is closer to (0, -1) than to (0, 350) + self._check_latlon_1d( + lats=[0, 0], + lons=[350, -1], + sample_point=[('latitude', 0), ('longitude', 359)], + expect=1) + + def test_lons_wrap_neg179_plus179(self): + # Check that (0, -179) is closer to (0, 179) than to (0, -170) + self._check_latlon_1d( + lats=[0, 0], + lons=[-170, 179], + sample_point=[('latitude', 0), ('longitude', -179)], + expect=1) + + def test_lons_over_pole(self): + # Check that (89, 0) is closer to (89, 180) than to (85, 0) + self._check_latlon_1d( + lats=[85, 89], + lons=[0, 180], + sample_point=[('latitude', 89), ('longitude', 0)], + expect=1) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/analysis/trajectory/test_interpolate.py b/lib/iris/tests/unit/analysis/trajectory/test_interpolate.py new file mode 100644 index 0000000000..1381f2cc4c --- /dev/null +++ b/lib/iris/tests/unit/analysis/trajectory/test_interpolate.py @@ -0,0 +1,185 @@ +# (C) British Crown Copyright 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for :meth:`iris.analysis.trajectory.interpolate`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.coords import AuxCoord, DimCoord +import iris.tests.stock + +from iris.analysis.trajectory import interpolate + + +class TestFailCases(tests.IrisTest): + @tests.skip_data + def test_derived_coord(self): + cube = iris.tests.stock.realistic_4d() + sample_pts = [('altitude', [0, 10, 50])] + msg = "'altitude'.*derived coordinates are not allowed" + with self.assertRaisesRegexp(ValueError, msg): + interpolate(cube, sample_pts, 'nearest') + + # Try to request unknown interpolation method. + def test_unknown_method(self): + cube = iris.tests.stock.simple_2d() + sample_point = [('x', 2.8)] + msg = 'Unhandled interpolation.*linekar' + with self.assertRaisesRegexp(ValueError, msg): + interpolate(cube, sample_point, method="linekar") + + +class TestNearest(tests.IrisTest): + # Test interpolation with 'nearest' method. + # This is basically a wrapper to the routine: + # 'analysis._interpolate_private._nearest_neighbour_indices_ndcoords'. + # That has its own test, so we don't test the basic calculation + # exhaustively here. Instead we check the way it handles the source and + # result cubes (especially coordinates). + + def setUp(self): + cube = iris.tests.stock.simple_3d() + # Actually, this cube *isn't* terribly realistic, as the lat+lon coords + # have integer type, which in this case produces some peculiar results. + # Let's fix that (and not bother to test the peculiar behaviour). + for coord_name in ('longitude', 'latitude'): + coord = cube.coord(coord_name) + coord.points = coord.points.astype(float) + self.test_cube = cube + # Define coordinates for a single-point testcase. + y_val, x_val = 0, -90 + # Work out cube indices of the testpoint. + self.single_point_iy = \ + np.where(cube.coord('latitude').points == y_val)[0][0] + self.single_point_ix = \ + np.where(cube.coord('longitude').points == x_val)[0][0] + # Use slightly-different values to test nearest-neighbour operation. + self.single_sample_point = [('latitude', [y_val + 19.23]), + ('longitude', [x_val - 17.54])] + + def test_single_point_same_cube(self): + # Check exact result matching for a single point. + cube = self.test_cube + result = interpolate(cube, self.single_sample_point, method='nearest') + # Check that the result is a single trajectory point, exactly equal to + # the expected part of the original data. + self.assertEqual(result.shape[-1], 1) + result = result[..., 0] + expected = cube[:, self.single_point_iy, self.single_point_ix] + self.assertEqual(result, expected) + + def test_multi_point_same_cube(self): + # Check an exact result for multiple points. + cube = self.test_cube + # Use latitude selection to recreate a whole row of the original cube. + sample_points = [('longitude', [-180, -90, 0, 90]), + ('latitude', [0, 0, 0, 0])] + result = interpolate(cube, sample_points, method='nearest') + + # The result should be identical to a single latitude section of the + # original, but with modified coords (latitude has 4 repeated zeros). + expected = cube[:, 1, :] + # Result 'longitude' is now an aux coord. + co_x = expected.coord('longitude') + expected.remove_coord(co_x) + expected.add_aux_coord(co_x, 1) + # Result 'latitude' is now an aux coord containing 4*[0]. + expected.remove_coord('latitude') + co_y = AuxCoord([0, 0, 0, 0], + standard_name='latitude', units='degrees') + expected.add_aux_coord(co_y, 1) + self.assertEqual(result, expected) + + def test_aux_coord_noninterpolation_dim(self): + # Check exact result with an aux-coord mapped to an uninterpolated dim. + cube = self.test_cube + cube.add_aux_coord(DimCoord([17, 19], long_name='aux0'), 0) + + # The result cube should exactly equal a single source point. + result = interpolate(cube, self.single_sample_point, method='nearest') + self.assertEqual(result.shape[-1], 1) + result = result[..., 0] + expected = cube[:, self.single_point_iy, self.single_point_ix] + self.assertEqual(result, expected) + + def test_aux_coord_one_interp_dim(self): + # Check exact result with an aux-coord over one interpolation dims. + cube = self.test_cube + cube.add_aux_coord(AuxCoord([11, 12, 13, 14], long_name='aux_x'), + 2) + + # The result cube should exactly equal a single source point. + result = interpolate(cube, self.single_sample_point, method='nearest') + self.assertEqual(result.shape[-1], 1) + result = result[..., 0] + expected = cube[:, self.single_point_iy, self.single_point_ix] + self.assertEqual(result, expected) + + def test_aux_coord_both_interp_dims(self): + # Check exact result with an aux-coord over both interpolation dims. + cube = self.test_cube + cube.add_aux_coord(AuxCoord([[11, 12, 13, 14], + [21, 22, 23, 24], + [31, 32, 33, 34]], long_name='aux_xy'), + (1, 2)) + + # The result cube should exactly equal a single source point. + result = interpolate(cube, self.single_sample_point, method='nearest') + self.assertEqual(result.shape[-1], 1) + result = result[..., 0] + expected = cube[:, self.single_point_iy, self.single_point_ix] + self.assertEqual(result, expected) + + def test_aux_coord_fail_mixed_dims(self): + # Check behaviour with an aux-coord mapped over both interpolation and + # non-interpolation dims : not supported. + cube = self.test_cube + cube.add_aux_coord(AuxCoord([[111, 112, 113, 114], + [211, 212, 213, 214]], + long_name='aux_0x'), + (0, 2)) + msg = ('Coord aux_0x at one x-y position has the shape.*' + 'instead of being a single point') + with self.assertRaisesRegexp(ValueError, msg): + interpolate(cube, self.single_sample_point, method='nearest') + + def test_metadata(self): + # Check exact result matching for a single point, with additional + # attributes and cell-methods. + cube = self.test_cube + cube.attributes['ODD_ATTR'] = 'string-value-example' + cube.add_cell_method(iris.coords.CellMethod('mean', 'area')) + result = interpolate(cube, self.single_sample_point, method='nearest') + # Check that the result is a single trajectory point, exactly equal to + # the expected part of the original data. + self.assertEqual(result.shape[-1], 1) + result = result[..., 0] + expected = cube[:, self.single_point_iy, self.single_point_ix] + self.assertEqual(result, expected) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/aux_factory/__init__.py b/lib/iris/tests/unit/aux_factory/__init__.py index 8b6504eeea..2e95470f7f 100644 --- a/lib/iris/tests/unit/aux_factory/__init__.py +++ b/lib/iris/tests/unit/aux_factory/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2014, Met Office +# (C) British Crown Copyright 2014 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Unit tests for the :mod:`iris.aux_factory` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/aux_factory/test_AuxCoordFactory.py b/lib/iris/tests/unit/aux_factory/test_AuxCoordFactory.py new file mode 100644 index 0000000000..83d10e307f --- /dev/null +++ b/lib/iris/tests/unit/aux_factory/test_AuxCoordFactory.py @@ -0,0 +1,179 @@ +# (C) British Crown Copyright 2015 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for `iris.aux_factory.AuxCoordFactory`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +import iris +from iris._lazy_data import as_lazy_data, is_lazy_data +from iris.aux_factory import AuxCoordFactory +from iris.coords import AuxCoord + + +class Test__nd_points(tests.IrisTest): + def test_numpy_scalar_coord__zero_ndim(self): + points = np.array(1) + coord = AuxCoord(points) + result = AuxCoordFactory._nd_points(coord, (), 0) + expected = np.array([1]) + self.assertArrayEqual(result, expected) + + def test_numpy_scalar_coord(self): + value = 1 + points = np.array(value) + coord = AuxCoord(points) + result = AuxCoordFactory._nd_points(coord, (), 2) + expected = np.array(value).reshape(1, 1) + self.assertArrayEqual(result, expected) + + def test_numpy_simple(self): + points = np.arange(12).reshape(4, 3) + coord = AuxCoord(points) + result = AuxCoordFactory._nd_points(coord, (0, 1), 2) + expected = points + self.assertArrayEqual(result, expected) + + def test_numpy_complex(self): + points = np.arange(12).reshape(4, 3) + coord = AuxCoord(points) + result = AuxCoordFactory._nd_points(coord, (3, 2), 5) + expected = points.T[np.newaxis, np.newaxis, ..., np.newaxis] + self.assertArrayEqual(result, expected) + + def test_lazy_simple(self): + raw_points = np.arange(12).reshape(4, 3) + points = as_lazy_data(raw_points, raw_points.shape) + coord = AuxCoord(points) + self.assertTrue(is_lazy_data(coord.core_points())) + result = AuxCoordFactory._nd_points(coord, (0, 1), 2) + # Check we haven't triggered the loading of the coordinate values. + self.assertTrue(is_lazy_data(coord.core_points())) + self.assertTrue(is_lazy_data(result)) + expected = raw_points + self.assertArrayEqual(result, expected) + + def test_lazy_complex(self): + raw_points = np.arange(12).reshape(4, 3) + points = as_lazy_data(raw_points, raw_points.shape) + coord = AuxCoord(points) + self.assertTrue(is_lazy_data(coord.core_points())) + result = AuxCoordFactory._nd_points(coord, (3, 2), 5) + # Check we haven't triggered the loading of the coordinate values. + self.assertTrue(is_lazy_data(coord.core_points())) + self.assertTrue(is_lazy_data(result)) + expected = raw_points.T[np.newaxis, np.newaxis, ..., np.newaxis] + self.assertArrayEqual(result, expected) + + +class Test__nd_bounds(tests.IrisTest): + def test_numpy_scalar_coord__zero_ndim(self): + points = np.array(0.5) + bounds = np.arange(2) + coord = AuxCoord(points, bounds=bounds) + result = AuxCoordFactory._nd_bounds(coord, (), 0) + expected = bounds + self.assertArrayEqual(result, expected) + + def test_numpy_scalar_coord(self): + points = np.array(0.5) + bounds = np.arange(2).reshape(1, 2) + coord = AuxCoord(points, bounds=bounds) + result = AuxCoordFactory._nd_bounds(coord, (), 2) + expected = bounds[np.newaxis] + self.assertArrayEqual(result, expected) + + def test_numpy_simple(self): + points = np.arange(12).reshape(4, 3) + bounds = np.arange(24).reshape(4, 3, 2) + coord = AuxCoord(points, bounds=bounds) + result = AuxCoordFactory._nd_bounds(coord, (0, 1), 2) + expected = bounds + self.assertArrayEqual(result, expected) + + def test_numpy_complex(self): + points = np.arange(12).reshape(4, 3) + bounds = np.arange(24).reshape(4, 3, 2) + coord = AuxCoord(points, bounds=bounds) + result = AuxCoordFactory._nd_bounds(coord, (3, 2), 5) + expected = bounds.transpose((1, 0, 2)).reshape(1, 1, 3, 4, 1, 2) + self.assertArrayEqual(result, expected) + + def test_lazy_simple(self): + raw_points = np.arange(12).reshape(4, 3) + points = as_lazy_data(raw_points, raw_points.shape) + raw_bounds = np.arange(24).reshape(4, 3, 2) + bounds = as_lazy_data(raw_bounds, raw_bounds.shape) + coord = AuxCoord(points, bounds=bounds) + self.assertTrue(is_lazy_data(coord.core_bounds())) + result = AuxCoordFactory._nd_bounds(coord, (0, 1), 2) + # Check we haven't triggered the loading of the coordinate values. + self.assertTrue(is_lazy_data(coord.core_bounds())) + self.assertTrue(is_lazy_data(result)) + expected = raw_bounds + self.assertArrayEqual(result, expected) + + def test_lazy_complex(self): + raw_points = np.arange(12).reshape(4, 3) + points = as_lazy_data(raw_points, raw_points.shape) + raw_bounds = np.arange(24).reshape(4, 3, 2) + bounds = as_lazy_data(raw_bounds, raw_bounds.shape) + coord = AuxCoord(points, bounds=bounds) + self.assertTrue(is_lazy_data(coord.core_bounds())) + result = AuxCoordFactory._nd_bounds(coord, (3, 2), 5) + # Check we haven't triggered the loading of the coordinate values. + self.assertTrue(is_lazy_data(coord.core_bounds())) + self.assertTrue(is_lazy_data(result)) + expected = raw_bounds.transpose((1, 0, 2)).reshape(1, 1, 3, 4, 1, 2) + self.assertArrayEqual(result, expected) + + +@tests.skip_data +class Test_lazy_aux_coords(tests.IrisTest): + def setUp(self): + path = tests.get_data_path(['NetCDF', 'testing', + 'small_theta_colpex.nc']) + self.cube = iris.load_cube(path, 'air_potential_temperature') + + def _check_lazy(self): + coords = self.cube.aux_coords + self.cube.derived_coords + for coord in coords: + self.assertTrue(coord.has_lazy_points()) + if coord.has_bounds(): + self.assertTrue(coord.has_lazy_bounds()) + + def test_lazy_coord_loading(self): + # Test that points and bounds arrays stay lazy upon cube loading. + self._check_lazy() + + def test_lazy_coord_printing(self): + # Test that points and bounds arrays stay lazy after cube printing. + _ = str(self.cube) + self._check_lazy() + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/aux_factory/test_HybridPressureFactory.py b/lib/iris/tests/unit/aux_factory/test_HybridPressureFactory.py index 0d86cbb8b4..66a21d9afe 100644 --- a/lib/iris/tests/unit/aux_factory/test_HybridPressureFactory.py +++ b/lib/iris/tests/unit/aux_factory/test_HybridPressureFactory.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2014, Met Office +# (C) British Crown Copyright 2014 - 2015, Met Office # # This file is part of Iris. # @@ -20,23 +20,26 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import mock - +import cf_units import numpy as np import iris from iris.aux_factory import HybridPressureFactory +from iris.tests import mock class Test___init__(tests.IrisTest): def setUp(self): - self.delta = mock.Mock(units=iris.unit.Unit('Pa'), nbounds=0) - self.sigma = mock.Mock(units=iris.unit.Unit('1'), nbounds=0) - self.surface_air_pressure = mock.Mock(units=iris.unit.Unit('Pa'), + self.delta = mock.Mock(units=cf_units.Unit('Pa'), nbounds=0) + self.sigma = mock.Mock(units=cf_units.Unit('1'), nbounds=0) + self.surface_air_pressure = mock.Mock(units=cf_units.Unit('Pa'), nbounds=0) def test_insufficient_coords(self): @@ -52,29 +55,29 @@ def test_insufficient_coords(self): surface_air_pressure=self.surface_air_pressure) def test_incompatible_delta_units(self): - self.delta.units = iris.unit.Unit('m') + self.delta.units = cf_units.Unit('m') with self.assertRaises(ValueError): HybridPressureFactory( delta=self.delta, sigma=self.sigma, surface_air_pressure=self.surface_air_pressure) def test_incompatible_sigma_units(self): - self.sigma.units = iris.unit.Unit('Pa') + self.sigma.units = cf_units.Unit('Pa') with self.assertRaises(ValueError): HybridPressureFactory( delta=self.delta, sigma=self.sigma, surface_air_pressure=self.surface_air_pressure) def test_incompatible_surface_air_pressure_units(self): - self.surface_air_pressure.units = iris.unit.Unit('unknown') + self.surface_air_pressure.units = cf_units.Unit('unknown') with self.assertRaises(ValueError): HybridPressureFactory( delta=self.delta, sigma=self.sigma, surface_air_pressure=self.surface_air_pressure) def test_different_pressure_units(self): - self.delta.units = iris.unit.Unit('hPa') - self.surface_air_pressure.units = iris.unit.Unit('Pa') + self.delta.units = cf_units.Unit('hPa') + self.surface_air_pressure.units = cf_units.Unit('Pa') with self.assertRaises(ValueError): HybridPressureFactory( delta=self.delta, sigma=self.sigma, @@ -109,9 +112,9 @@ def test_factory_metadata(self): class Test_dependencies(tests.IrisTest): def setUp(self): - self.delta = mock.Mock(units=iris.unit.Unit('Pa'), nbounds=0) - self.sigma = mock.Mock(units=iris.unit.Unit('1'), nbounds=0) - self.surface_air_pressure = mock.Mock(units=iris.unit.Unit('Pa'), + self.delta = mock.Mock(units=cf_units.Unit('Pa'), nbounds=0) + self.sigma = mock.Mock(units=cf_units.Unit('1'), nbounds=0) + self.surface_air_pressure = mock.Mock(units=cf_units.Unit('Pa'), nbounds=0) def test_value(self): @@ -217,9 +220,9 @@ def test_with_bounds(self): class Test_update(tests.IrisTest): def setUp(self): - self.delta = mock.Mock(units=iris.unit.Unit('Pa'), nbounds=0) - self.sigma = mock.Mock(units=iris.unit.Unit('1'), nbounds=0) - self.surface_air_pressure = mock.Mock(units=iris.unit.Unit('Pa'), + self.delta = mock.Mock(units=cf_units.Unit('Pa'), nbounds=0) + self.sigma = mock.Mock(units=cf_units.Unit('1'), nbounds=0) + self.surface_air_pressure = mock.Mock(units=cf_units.Unit('Pa'), nbounds=0) self.factory = HybridPressureFactory( @@ -227,27 +230,27 @@ def setUp(self): surface_air_pressure=self.surface_air_pressure) def test_good_delta(self): - new_delta_coord = mock.Mock(units=iris.unit.Unit('Pa'), nbounds=0) + new_delta_coord = mock.Mock(units=cf_units.Unit('Pa'), nbounds=0) self.factory.update(self.delta, new_delta_coord) self.assertIs(self.factory.delta, new_delta_coord) def test_bad_delta(self): - new_delta_coord = mock.Mock(units=iris.unit.Unit('1'), nbounds=0) + new_delta_coord = mock.Mock(units=cf_units.Unit('1'), nbounds=0) with self.assertRaises(ValueError): self.factory.update(self.delta, new_delta_coord) def test_alternative_bad_delta(self): - new_delta_coord = mock.Mock(units=iris.unit.Unit('Pa'), nbounds=4) + new_delta_coord = mock.Mock(units=cf_units.Unit('Pa'), nbounds=4) with self.assertRaises(ValueError): self.factory.update(self.delta, new_delta_coord) def test_good_surface_air_pressure(self): - new_surface_p_coord = mock.Mock(units=iris.unit.Unit('Pa'), nbounds=0) + new_surface_p_coord = mock.Mock(units=cf_units.Unit('Pa'), nbounds=0) self.factory.update(self.surface_air_pressure, new_surface_p_coord) self.assertIs(self.factory.surface_air_pressure, new_surface_p_coord) def test_bad_surface_air_pressure(self): - new_surface_p_coord = mock.Mock(units=iris.unit.Unit('km'), nbounds=0) + new_surface_p_coord = mock.Mock(units=cf_units.Unit('km'), nbounds=0) with self.assertRaises(ValueError): self.factory.update(self.surface_air_pressure, new_surface_p_coord) diff --git a/lib/iris/tests/unit/aux_factory/test_OceanSFactory.py b/lib/iris/tests/unit/aux_factory/test_OceanSFactory.py new file mode 100644 index 0000000000..ed6f9ef92a --- /dev/null +++ b/lib/iris/tests/unit/aux_factory/test_OceanSFactory.py @@ -0,0 +1,261 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the +`iris.aux_factory.OceanSFactory` class. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from cf_units import Unit +import numpy as np + +from iris.aux_factory import OceanSFactory +from iris.coords import AuxCoord, DimCoord +from iris.tests import mock + + +class Test___init__(tests.IrisTest): + def setUp(self): + self.s = mock.Mock(units=Unit('1'), nbounds=0) + self.eta = mock.Mock(units=Unit('m'), nbounds=0) + self.depth = mock.Mock(units=Unit('m'), nbounds=0) + self.a = mock.Mock(units=Unit('1'), nbounds=0, shape=(1,)) + self.b = mock.Mock(units=Unit('1'), nbounds=0, shape=(1,)) + self.depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(1,)) + self.kwargs = dict(s=self.s, eta=self.eta, depth=self.depth, + a=self.a, b=self.b, depth_c=self.depth_c) + + def test_insufficient_coordinates(self): + with self.assertRaises(ValueError): + OceanSFactory() + with self.assertRaises(ValueError): + OceanSFactory(s=None, eta=self.eta, depth=self.depth, + a=self.a, b=self.b, depth_c=self.depth_c) + with self.assertRaises(ValueError): + OceanSFactory(s=self.s, eta=None, depth=self.depth, + a=self.a, b=self.b, depth_c=self.depth_c) + with self.assertRaises(ValueError): + OceanSFactory(s=self.s, eta=self.eta, depth=None, + a=self.a, b=self.b, depth_c=self.depth_c) + with self.assertRaises(ValueError): + OceanSFactory(s=self.s, eta=self.eta, depth=self.depth, + a=None, b=self.b, depth_c=self.depth_c) + with self.assertRaises(ValueError): + OceanSFactory(s=self.s, eta=self.eta, depth=self.depth, + a=self.a, b=None, depth_c=self.depth_c) + with self.assertRaises(ValueError): + OceanSFactory(s=self.s, eta=self.eta, depth=self.depth, + a=self.a, b=self.b, depth_c=None) + + def test_s_too_many_bounds(self): + self.s.nbounds = 4 + with self.assertRaises(ValueError): + OceanSFactory(**self.kwargs) + + def test_a_non_scalar(self): + self.a.shape = (2,) + with self.assertRaises(ValueError): + OceanSFactory(**self.kwargs) + + def test_b_non_scalar(self): + self.b.shape = (2,) + with self.assertRaises(ValueError): + OceanSFactory(**self.kwargs) + + def test_depth_c_non_scalar(self): + self.depth_c.shape = (2,) + with self.assertRaises(ValueError): + OceanSFactory(**self.kwargs) + + def test_s_incompatible_units(self): + self.s.units = Unit('km') + with self.assertRaises(ValueError): + OceanSFactory(**self.kwargs) + + def test_eta_incompatible_units(self): + self.eta.units = Unit('km') + with self.assertRaises(ValueError): + OceanSFactory(**self.kwargs) + + def test_depth_c_incompatible_units(self): + self.depth_c.units = Unit('km') + with self.assertRaises(ValueError): + OceanSFactory(**self.kwargs) + + def test_depth_incompatible_units(self): + self.depth.units = Unit('km') + with self.assertRaises(ValueError): + OceanSFactory(**self.kwargs) + + +class Test_dependencies(tests.IrisTest): + def setUp(self): + self.s = mock.Mock(units=Unit('1'), nbounds=0) + self.eta = mock.Mock(units=Unit('m'), nbounds=0) + self.depth = mock.Mock(units=Unit('m'), nbounds=0) + self.a = mock.Mock(units=Unit('1'), nbounds=0, shape=(1,)) + self.b = mock.Mock(units=Unit('1'), nbounds=0, shape=(1,)) + self.depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(1,)) + self.kwargs = dict(s=self.s, eta=self.eta, depth=self.depth, + a=self.a, b=self.b, depth_c=self.depth_c) + + def test_values(self): + factory = OceanSFactory(**self.kwargs) + self.assertEqual(factory.dependencies, self.kwargs) + + +class Test_make_coord(tests.IrisTest): + @staticmethod + def coord_dims(coord): + mapping = dict(s=(0,), eta=(1, 2), depth=(1, 2), + a=(), b=(), depth_c=()) + return mapping[coord.name()] + + @staticmethod + def derive(s, eta, depth, a, b, depth_c, coord=True): + c = ((1 - b) * np.sinh(a * s) / np.sinh(a) + b * + (np.tanh(a * (s + 0.5)) / (2 * np.tanh(0.5 * a)) - 0.5)) + result = eta * (1 + s) + depth_c * s + (depth - depth_c) * c + if coord: + name = 'sea_surface_height_above_reference_ellipsoid' + result = AuxCoord(result, + standard_name=name, + units='m', + attributes=dict(positive='up')) + return result + + def setUp(self): + self.s = DimCoord(np.arange(-0.975, 0, 0.05, dtype=float), units='1', + long_name='s') + self.eta = AuxCoord(np.arange(-1, 3, dtype=np.float).reshape(2, 2), + long_name='eta', units='m') + self.depth = AuxCoord(np.arange(4, dtype=np.float).reshape(2, 2) * 1e3, + long_name='depth', units='m') + self.a = AuxCoord([4], units='1', long_name='a') + self.b = AuxCoord([0.9], units='1', long_name='b') + self.depth_c = AuxCoord([4], long_name='depth_c', units='m') + self.kwargs = dict(s=self.s, eta=self.eta, depth=self.depth, + a=self.a, b=self.b, depth_c=self.depth_c) + + def test_derived_points(self): + # Broadcast expected points given the known dimensional mapping. + s = self.s.points[..., np.newaxis, np.newaxis] + eta = self.eta.points[np.newaxis, ...] + depth = self.depth.points[np.newaxis, ...] + a = self.a.points + b = self.b.points + depth_c = self.depth_c.points + # Calculate the expected result. + expected_coord = self.derive(s, eta, depth, a, b, depth_c) + # Calculate the actual result. + factory = OceanSFactory(**self.kwargs) + coord = factory.make_coord(self.coord_dims) + self.assertEqual(expected_coord, coord) + + +class Test_update(tests.IrisTest): + def setUp(self): + self.s = mock.Mock(units=Unit('1'), nbounds=0) + self.eta = mock.Mock(units=Unit('m'), nbounds=0) + self.depth = mock.Mock(units=Unit('m'), nbounds=0) + self.a = mock.Mock(units=Unit('1'), nbounds=0, shape=(1,)) + self.b = mock.Mock(units=Unit('1'), nbounds=0, shape=(1,)) + self.depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(1,)) + self.kwargs = dict(s=self.s, eta=self.eta, depth=self.depth, + a=self.a, b=self.b, depth_c=self.depth_c) + self.factory = OceanSFactory(**self.kwargs) + + def test_s(self): + new_s = mock.Mock(units=Unit('1'), nbounds=0) + self.factory.update(self.s, new_s) + self.assertIs(self.factory.s, new_s) + + def test_s_too_many_bounds(self): + new_s = mock.Mock(units=Unit('1'), nbounds=4) + with self.assertRaises(ValueError): + self.factory.update(self.s, new_s) + + def test_s_incompatible_units(self): + new_s = mock.Mock(units=Unit('Pa'), nbounds=0) + with self.assertRaises(ValueError): + self.factory.update(self.s, new_s) + + def test_eta(self): + new_eta = mock.Mock(units=Unit('m'), nbounds=0) + self.factory.update(self.eta, new_eta) + self.assertIs(self.factory.eta, new_eta) + + def test_eta_incompatible_units(self): + new_eta = mock.Mock(units=Unit('Pa'), nbounds=0) + with self.assertRaises(ValueError): + self.factory.update(self.eta, new_eta) + + def test_depth(self): + new_depth = mock.Mock(units=Unit('m'), nbounds=0) + self.factory.update(self.depth, new_depth) + self.assertIs(self.factory.depth, new_depth) + + def test_depth_incompatible_units(self): + new_depth = mock.Mock(units=Unit('Pa'), nbounds=0) + with self.assertRaises(ValueError): + self.factory.update(self.depth, new_depth) + + def test_a(self): + new_a = mock.Mock(units=Unit('1'), nbounds=0, shape=(1,)) + self.factory.update(self.a, new_a) + self.assertIs(self.factory.a, new_a) + + def test_a_non_scalar(self): + new_a = mock.Mock(units=Unit('1'), nbounds=0, shape=(10,)) + with self.assertRaises(ValueError): + self.factory.update(self.a, new_a) + + def test_b(self): + new_b = mock.Mock(units=Unit('1'), nbounds=0, shape=(1,)) + self.factory.update(self.b, new_b) + self.assertIs(self.factory.b, new_b) + + def test_b_non_scalar(self): + new_b = mock.Mock(units=Unit('1'), nbounds=0, shape=(10,)) + with self.assertRaises(ValueError): + self.factory.update(self.b, new_b) + + def test_depth_c(self): + new_depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(1,)) + self.factory.update(self.depth_c, new_depth_c) + self.assertIs(self.factory.depth_c, new_depth_c) + + def test_depth_c_non_scalar(self): + new_depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(10,)) + with self.assertRaises(ValueError): + self.factory.update(self.depth_c, new_depth_c) + + def test_depth_c_incompatible_units(self): + new_depth_c = mock.Mock(units=Unit('Pa'), nbounds=0, shape=(1,)) + with self.assertRaises(ValueError): + self.factory.update(self.depth_c, new_depth_c) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/aux_factory/test_OceanSg1Factory.py b/lib/iris/tests/unit/aux_factory/test_OceanSg1Factory.py new file mode 100644 index 0000000000..3df2ca832a --- /dev/null +++ b/lib/iris/tests/unit/aux_factory/test_OceanSg1Factory.py @@ -0,0 +1,249 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the +`iris.aux_factory.OceanSg1Factory` class. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from cf_units import Unit +import numpy as np + +from iris.aux_factory import OceanSg1Factory +from iris.coords import AuxCoord, DimCoord +from iris.tests import mock + + +class Test___init__(tests.IrisTest): + def setUp(self): + self.s = mock.Mock(units=Unit('1'), nbounds=0) + self.c = mock.Mock(units=Unit('1'), nbounds=0, shape=(1,)) + self.eta = mock.Mock(units=Unit('m'), nbounds=0) + self.depth = mock.Mock(units=Unit('m'), nbounds=0) + self.depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(1,)) + self.kwargs = dict(s=self.s, c=self.c, eta=self.eta, + depth=self.depth, depth_c=self.depth_c) + + def test_insufficient_coordinates(self): + with self.assertRaises(ValueError): + OceanSg1Factory() + with self.assertRaises(ValueError): + OceanSg1Factory(s=None, c=self.c, eta=self.eta, + depth=self.depth, depth_c=self.depth_c) + with self.assertRaises(ValueError): + OceanSg1Factory(s=self.s, c=None, eta=self.eta, + depth=self.depth, depth_c=self.depth_c) + with self.assertRaises(ValueError): + OceanSg1Factory(s=self.s, c=self.c, eta=None, + depth=self.depth, depth_c=self.depth_c) + with self.assertRaises(ValueError): + OceanSg1Factory(s=self.s, c=self.c, eta=self.eta, + depth=None, depth_c=self.depth_c) + with self.assertRaises(ValueError): + OceanSg1Factory(s=self.s, c=self.c, eta=self.eta, + depth=self.depth, depth_c=None) + + def test_s_too_many_bounds(self): + self.s.nbounds = 4 + with self.assertRaises(ValueError): + OceanSg1Factory(**self.kwargs) + + def test_c_too_many_bounds(self): + self.c.nbounds = 4 + with self.assertRaises(ValueError): + OceanSg1Factory(**self.kwargs) + + def test_depth_c_non_scalar(self): + self.depth_c.shape = (2,) + with self.assertRaises(ValueError): + OceanSg1Factory(**self.kwargs) + + def test_s_incompatible_units(self): + self.s.units = Unit('km') + with self.assertRaises(ValueError): + OceanSg1Factory(**self.kwargs) + + def test_c_incompatible_units(self): + self.c.units = Unit('km') + with self.assertRaises(ValueError): + OceanSg1Factory(**self.kwargs) + + def test_eta_incompatible_units(self): + self.eta.units = Unit('km') + with self.assertRaises(ValueError): + OceanSg1Factory(**self.kwargs) + + def test_depth_c_incompatible_units(self): + self.depth_c.units = Unit('km') + with self.assertRaises(ValueError): + OceanSg1Factory(**self.kwargs) + + def test_depth_incompatible_units(self): + self.depth.units = Unit('km') + with self.assertRaises(ValueError): + OceanSg1Factory(**self.kwargs) + + +class Test_dependencies(tests.IrisTest): + def setUp(self): + self.s = mock.Mock(units=Unit('1'), nbounds=0) + self.c = mock.Mock(units=Unit('1'), nbounds=0, shape=(1,)) + self.eta = mock.Mock(units=Unit('m'), nbounds=0) + self.depth = mock.Mock(units=Unit('m'), nbounds=0) + self.depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(1,)) + self.kwargs = dict(s=self.s, c=self.c, eta=self.eta, + depth=self.depth, depth_c=self.depth_c) + + def test_values(self): + factory = OceanSg1Factory(**self.kwargs) + self.assertEqual(factory.dependencies, self.kwargs) + + +class Test_make_coord(tests.IrisTest): + @staticmethod + def coord_dims(coord): + mapping = dict(s=(0,), c=(0,), eta=(1, 2), depth=(1, 2), + depth_c=()) + return mapping[coord.name()] + + @staticmethod + def derive(s, c, eta, depth, depth_c, coord=True): + S = depth_c * s + (depth - depth_c) * c + result = S + eta * (1 + S / depth) + if coord: + name = 'sea_surface_height_above_reference_ellipsoid' + result = AuxCoord(result, + standard_name=name, + units='m', + attributes=dict(positive='up')) + return result + + def setUp(self): + self.s = DimCoord(np.linspace(-0.985, -0.014, 36), units='1', + long_name='s') + self.c = DimCoord(np.linspace(-0.959, -0.001, 36), units='1', + long_name='c') + self.eta = AuxCoord(np.arange(-1, 3, dtype=np.float).reshape(2, 2), + long_name='eta', units='m') + self.depth = AuxCoord(np.array([[5, 200], [1000, 4000]], + dtype=np.float), + long_name='depth', units='m') + self.depth_c = AuxCoord([5], long_name='depth_c', units='m') + self.kwargs = dict(s=self.s, c=self.c, eta=self.eta, + depth=self.depth, depth_c=self.depth_c) + + def test_derived_points(self): + # Broadcast expected points given the known dimensional mapping. + s = self.s.points[..., np.newaxis, np.newaxis] + c = self.c.points[..., np.newaxis, np.newaxis] + eta = self.eta.points[np.newaxis, ...] + depth = self.depth.points[np.newaxis, ...] + depth_c = self.depth_c.points + # Calculate the expected result. + expected_coord = self.derive(s, c, eta, depth, depth_c) + # Calculate the actual result. + factory = OceanSg1Factory(**self.kwargs) + coord = factory.make_coord(self.coord_dims) + self.assertEqual(expected_coord, coord) + + +class Test_update(tests.IrisTest): + def setUp(self): + self.s = mock.Mock(units=Unit('1'), nbounds=0) + self.c = mock.Mock(units=Unit('1'), nbounds=0, shape=(1,)) + self.eta = mock.Mock(units=Unit('m'), nbounds=0) + self.depth = mock.Mock(units=Unit('m'), nbounds=0) + self.depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(1,)) + self.kwargs = dict(s=self.s, c=self.c, eta=self.eta, + depth=self.depth, depth_c=self.depth_c) + self.factory = OceanSg1Factory(**self.kwargs) + + def test_s(self): + new_s = mock.Mock(units=Unit('1'), nbounds=0) + self.factory.update(self.s, new_s) + self.assertIs(self.factory.s, new_s) + + def test_c(self): + new_c = mock.Mock(units=Unit('1'), nbounds=0) + self.factory.update(self.c, new_c) + self.assertIs(self.factory.c, new_c) + + def test_s_too_many_bounds(self): + new_s = mock.Mock(units=Unit('1'), nbounds=4) + with self.assertRaises(ValueError): + self.factory.update(self.s, new_s) + + def test_c_too_many_bounds(self): + new_c = mock.Mock(units=Unit('1'), nbounds=4) + with self.assertRaises(ValueError): + self.factory.update(self.c, new_c) + + def test_s_incompatible_units(self): + new_s = mock.Mock(units=Unit('Pa'), nbounds=0) + with self.assertRaises(ValueError): + self.factory.update(self.s, new_s) + + def test_c_incompatible_units(self): + new_c = mock.Mock(units=Unit('Pa'), nbounds=0) + with self.assertRaises(ValueError): + self.factory.update(self.c, new_c) + + def test_eta(self): + new_eta = mock.Mock(units=Unit('m'), nbounds=0) + self.factory.update(self.eta, new_eta) + self.assertIs(self.factory.eta, new_eta) + + def test_eta_incompatible_units(self): + new_eta = mock.Mock(units=Unit('Pa'), nbounds=0) + with self.assertRaises(ValueError): + self.factory.update(self.eta, new_eta) + + def test_depth(self): + new_depth = mock.Mock(units=Unit('m'), nbounds=0) + self.factory.update(self.depth, new_depth) + self.assertIs(self.factory.depth, new_depth) + + def test_depth_incompatible_units(self): + new_depth = mock.Mock(units=Unit('Pa'), nbounds=0) + with self.assertRaises(ValueError): + self.factory.update(self.depth, new_depth) + + def test_depth_c(self): + new_depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(1,)) + self.factory.update(self.depth_c, new_depth_c) + self.assertIs(self.factory.depth_c, new_depth_c) + + def test_depth_c_non_scalar(self): + new_depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(10,)) + with self.assertRaises(ValueError): + self.factory.update(self.depth_c, new_depth_c) + + def test_depth_c_incompatible_units(self): + new_depth_c = mock.Mock(units=Unit('Pa'), nbounds=0, shape=(1,)) + with self.assertRaises(ValueError): + self.factory.update(self.depth_c, new_depth_c) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/aux_factory/test_OceanSg2Factory.py b/lib/iris/tests/unit/aux_factory/test_OceanSg2Factory.py new file mode 100644 index 0000000000..a2919fe223 --- /dev/null +++ b/lib/iris/tests/unit/aux_factory/test_OceanSg2Factory.py @@ -0,0 +1,249 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the +`iris.aux_factory.OceanSg2Factory` class. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from cf_units import Unit +import numpy as np + +from iris.aux_factory import OceanSg2Factory +from iris.coords import AuxCoord, DimCoord +from iris.tests import mock + + +class Test___init__(tests.IrisTest): + def setUp(self): + self.s = mock.Mock(units=Unit('1'), nbounds=0) + self.c = mock.Mock(units=Unit('1'), nbounds=0, shape=(1,)) + self.eta = mock.Mock(units=Unit('m'), nbounds=0) + self.depth = mock.Mock(units=Unit('m'), nbounds=0) + self.depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(1,)) + self.kwargs = dict(s=self.s, c=self.c, eta=self.eta, + depth=self.depth, depth_c=self.depth_c) + + def test_insufficient_coordinates(self): + with self.assertRaises(ValueError): + OceanSg2Factory() + with self.assertRaises(ValueError): + OceanSg2Factory(s=None, c=self.c, eta=self.eta, + depth=self.depth, depth_c=self.depth_c) + with self.assertRaises(ValueError): + OceanSg2Factory(s=self.s, c=None, eta=self.eta, + depth=self.depth, depth_c=self.depth_c) + with self.assertRaises(ValueError): + OceanSg2Factory(s=self.s, c=self.c, eta=None, + depth=self.depth, depth_c=self.depth_c) + with self.assertRaises(ValueError): + OceanSg2Factory(s=self.s, c=self.c, eta=self.eta, + depth=None, depth_c=self.depth_c) + with self.assertRaises(ValueError): + OceanSg2Factory(s=self.s, c=self.c, eta=self.eta, + depth=self.depth, depth_c=None) + + def test_s_too_many_bounds(self): + self.s.nbounds = 4 + with self.assertRaises(ValueError): + OceanSg2Factory(**self.kwargs) + + def test_c_too_many_bounds(self): + self.c.nbounds = 4 + with self.assertRaises(ValueError): + OceanSg2Factory(**self.kwargs) + + def test_depth_c_non_scalar(self): + self.depth_c.shape = (2,) + with self.assertRaises(ValueError): + OceanSg2Factory(**self.kwargs) + + def test_s_incompatible_units(self): + self.s.units = Unit('km') + with self.assertRaises(ValueError): + OceanSg2Factory(**self.kwargs) + + def test_c_incompatible_units(self): + self.c.units = Unit('km') + with self.assertRaises(ValueError): + OceanSg2Factory(**self.kwargs) + + def test_eta_incompatible_units(self): + self.eta.units = Unit('km') + with self.assertRaises(ValueError): + OceanSg2Factory(**self.kwargs) + + def test_depth_c_incompatible_units(self): + self.depth_c.units = Unit('km') + with self.assertRaises(ValueError): + OceanSg2Factory(**self.kwargs) + + def test_depth_incompatible_units(self): + self.depth.units = Unit('km') + with self.assertRaises(ValueError): + OceanSg2Factory(**self.kwargs) + + +class Test_dependencies(tests.IrisTest): + def setUp(self): + self.s = mock.Mock(units=Unit('1'), nbounds=0) + self.c = mock.Mock(units=Unit('1'), nbounds=0, shape=(1,)) + self.eta = mock.Mock(units=Unit('m'), nbounds=0) + self.depth = mock.Mock(units=Unit('m'), nbounds=0) + self.depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(1,)) + self.kwargs = dict(s=self.s, c=self.c, eta=self.eta, + depth=self.depth, depth_c=self.depth_c) + + def test_values(self): + factory = OceanSg2Factory(**self.kwargs) + self.assertEqual(factory.dependencies, self.kwargs) + + +class Test_make_coord(tests.IrisTest): + @staticmethod + def coord_dims(coord): + mapping = dict(s=(0,), c=(0,), eta=(1, 2), depth=(1, 2), + depth_c=()) + return mapping[coord.name()] + + @staticmethod + def derive(s, c, eta, depth, depth_c, coord=True): + S = (depth_c * s + depth * c) / (depth_c + depth) + result = eta + (eta + depth) * S + if coord: + name = 'sea_surface_height_above_reference_ellipsoid' + result = AuxCoord(result, + standard_name=name, + units='m', + attributes=dict(positive='up')) + return result + + def setUp(self): + self.s = DimCoord(np.linspace(-0.985, -0.014, 36), units='1', + long_name='s') + self.c = DimCoord(np.linspace(-0.959, -0.001, 36), units='1', + long_name='c') + self.eta = AuxCoord(np.arange(-1, 3, dtype=np.float).reshape(2, 2), + long_name='eta', units='m') + self.depth = AuxCoord(np.array([[5, 200], [1000, 4000]], + dtype=np.float), + long_name='depth', units='m') + self.depth_c = AuxCoord([1], long_name='depth_c', units='m') + self.kwargs = dict(s=self.s, c=self.c, eta=self.eta, + depth=self.depth, depth_c=self.depth_c) + + def test_derived_points(self): + # Broadcast expected points given the known dimensional mapping. + s = self.s.points[..., np.newaxis, np.newaxis] + c = self.c.points[..., np.newaxis, np.newaxis] + eta = self.eta.points[np.newaxis, ...] + depth = self.depth.points[np.newaxis, ...] + depth_c = self.depth_c.points + # Calculate the expected result. + expected_coord = self.derive(s, c, eta, depth, depth_c) + # Calculate the actual result. + factory = OceanSg2Factory(**self.kwargs) + coord = factory.make_coord(self.coord_dims) + self.assertEqual(expected_coord, coord) + + +class Test_update(tests.IrisTest): + def setUp(self): + self.s = mock.Mock(units=Unit('1'), nbounds=0) + self.c = mock.Mock(units=Unit('1'), nbounds=0, shape=(1,)) + self.eta = mock.Mock(units=Unit('m'), nbounds=0) + self.depth = mock.Mock(units=Unit('m'), nbounds=0) + self.depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(1,)) + self.kwargs = dict(s=self.s, c=self.c, eta=self.eta, + depth=self.depth, depth_c=self.depth_c) + self.factory = OceanSg2Factory(**self.kwargs) + + def test_s(self): + new_s = mock.Mock(units=Unit('1'), nbounds=0) + self.factory.update(self.s, new_s) + self.assertIs(self.factory.s, new_s) + + def test_c(self): + new_c = mock.Mock(units=Unit('1'), nbounds=0) + self.factory.update(self.c, new_c) + self.assertIs(self.factory.c, new_c) + + def test_s_too_many_bounds(self): + new_s = mock.Mock(units=Unit('1'), nbounds=4) + with self.assertRaises(ValueError): + self.factory.update(self.s, new_s) + + def test_c_too_many_bounds(self): + new_c = mock.Mock(units=Unit('1'), nbounds=4) + with self.assertRaises(ValueError): + self.factory.update(self.c, new_c) + + def test_s_incompatible_units(self): + new_s = mock.Mock(units=Unit('Pa'), nbounds=0) + with self.assertRaises(ValueError): + self.factory.update(self.s, new_s) + + def test_c_incompatible_units(self): + new_c = mock.Mock(units=Unit('Pa'), nbounds=0) + with self.assertRaises(ValueError): + self.factory.update(self.c, new_c) + + def test_eta(self): + new_eta = mock.Mock(units=Unit('m'), nbounds=0) + self.factory.update(self.eta, new_eta) + self.assertIs(self.factory.eta, new_eta) + + def test_eta_incompatible_units(self): + new_eta = mock.Mock(units=Unit('Pa'), nbounds=0) + with self.assertRaises(ValueError): + self.factory.update(self.eta, new_eta) + + def test_depth(self): + new_depth = mock.Mock(units=Unit('m'), nbounds=0) + self.factory.update(self.depth, new_depth) + self.assertIs(self.factory.depth, new_depth) + + def test_depth_incompatible_units(self): + new_depth = mock.Mock(units=Unit('Pa'), nbounds=0) + with self.assertRaises(ValueError): + self.factory.update(self.depth, new_depth) + + def test_depth_c(self): + new_depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(1,)) + self.factory.update(self.depth_c, new_depth_c) + self.assertIs(self.factory.depth_c, new_depth_c) + + def test_depth_c_non_scalar(self): + new_depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(10,)) + with self.assertRaises(ValueError): + self.factory.update(self.depth_c, new_depth_c) + + def test_depth_c_incompatible_units(self): + new_depth_c = mock.Mock(units=Unit('Pa'), nbounds=0, shape=(1,)) + with self.assertRaises(ValueError): + self.factory.update(self.depth_c, new_depth_c) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/aux_factory/test_OceanSigmaFactory.py b/lib/iris/tests/unit/aux_factory/test_OceanSigmaFactory.py new file mode 100644 index 0000000000..ece9cf583b --- /dev/null +++ b/lib/iris/tests/unit/aux_factory/test_OceanSigmaFactory.py @@ -0,0 +1,173 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the +`iris.aux_factory.OceanSigmaFactory` class. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from cf_units import Unit +import numpy as np + +from iris.aux_factory import OceanSigmaFactory +from iris.coords import AuxCoord, DimCoord +from iris.tests import mock + + +class Test___init__(tests.IrisTest): + def setUp(self): + self.sigma = mock.Mock(units=Unit('1'), nbounds=0) + self.eta = mock.Mock(units=Unit('m'), nbounds=0) + self.depth = mock.Mock(units=Unit('m'), nbounds=0) + self.kwargs = dict(sigma=self.sigma, eta=self.eta, + depth=self.depth) + + def test_insufficient_coordinates(self): + with self.assertRaises(ValueError): + OceanSigmaFactory() + with self.assertRaises(ValueError): + OceanSigmaFactory(sigma=None, eta=self.eta, depth=self.depth) + with self.assertRaises(ValueError): + OceanSigmaFactory(sigma=self.sigma, eta=None, depth=self.depth) + with self.assertRaises(ValueError): + OceanSigmaFactory(sigma=self.sigma, eta=self.eta, depth=None) + + def test_sigma_too_many_bounds(self): + self.sigma.nbounds = 4 + with self.assertRaises(ValueError): + OceanSigmaFactory(**self.kwargs) + + def test_sigma_incompatible_units(self): + self.sigma.units = Unit('km') + with self.assertRaises(ValueError): + OceanSigmaFactory(**self.kwargs) + + def test_eta_incompatible_units(self): + self.eta.units = Unit('km') + with self.assertRaises(ValueError): + OceanSigmaFactory(**self.kwargs) + + def test_depth_incompatible_units(self): + self.depth.units = Unit('km') + with self.assertRaises(ValueError): + OceanSigmaFactory(**self.kwargs) + + +class Test_dependencies(tests.IrisTest): + def setUp(self): + self.sigma = mock.Mock(units=Unit('1'), nbounds=0) + self.eta = mock.Mock(units=Unit('m'), nbounds=0) + self.depth = mock.Mock(units=Unit('m'), nbounds=0) + self.kwargs = dict(sigma=self.sigma, eta=self.eta, depth=self.depth) + + def test_values(self): + factory = OceanSigmaFactory(**self.kwargs) + self.assertEqual(factory.dependencies, self.kwargs) + + +class Test_make_coord(tests.IrisTest): + @staticmethod + def coord_dims(coord): + mapping = dict(sigma=(0,), eta=(1, 2), depth=(1, 2)) + return mapping[coord.name()] + + @staticmethod + def derive(sigma, eta, depth, coord=True): + result = eta + sigma * (depth + eta) + if coord: + name = 'sea_surface_height_above_reference_ellipsoid' + result = AuxCoord(result, + standard_name=name, + units='m', + attributes=dict(positive='up')) + return result + + def setUp(self): + self.sigma = DimCoord(np.linspace(-0.05, -1, 5), + long_name='sigma', units='1') + self.eta = AuxCoord(np.arange(-1, 3, dtype=np.float).reshape(2, 2), + long_name='eta', units='m') + self.depth = AuxCoord(np.arange(4, dtype=np.float).reshape(2, 2) * 1e3, + long_name='depth', units='m') + self.kwargs = dict(sigma=self.sigma, eta=self.eta, depth=self.depth) + + def test_derived_points(self): + # Broadcast expected points given the known dimensional mapping. + sigma = self.sigma.points[..., np.newaxis, np.newaxis] + eta = self.eta.points[np.newaxis, ...] + depth = self.depth.points[np.newaxis, ...] + # Calculate the expected result. + expected_coord = self.derive(sigma, eta, depth) + # Calculate the actual result. + factory = OceanSigmaFactory(**self.kwargs) + coord = factory.make_coord(self.coord_dims) + self.assertEqual(expected_coord, coord) + + +class Test_update(tests.IrisTest): + def setUp(self): + self.sigma = mock.Mock(units=Unit('1'), nbounds=0) + self.eta = mock.Mock(units=Unit('m'), nbounds=0) + self.depth = mock.Mock(units=Unit('m'), nbounds=0) + self.kwargs = dict(sigma=self.sigma, eta=self.eta, depth=self.depth) + self.factory = OceanSigmaFactory(**self.kwargs) + + def test_sigma(self): + new_sigma = mock.Mock(units=Unit('1'), nbounds=0) + self.factory.update(self.sigma, new_sigma) + self.assertIs(self.factory.sigma, new_sigma) + + def test_sigma_too_many_bounds(self): + new_sigma = mock.Mock(units=Unit('1'), nbounds=4) + with self.assertRaises(ValueError): + self.factory.update(self.sigma, new_sigma) + + def test_sigma_incompatible_units(self): + new_sigma = mock.Mock(units=Unit('Pa'), nbounds=0) + with self.assertRaises(ValueError): + self.factory.update(self.sigma, new_sigma) + + def test_eta(self): + new_eta = mock.Mock(units=Unit('m'), nbounds=0) + self.factory.update(self.eta, new_eta) + self.assertIs(self.factory.eta, new_eta) + + def test_eta_incompatible_units(self): + new_eta = mock.Mock(units=Unit('Pa'), nbounds=0) + with self.assertRaises(ValueError): + self.factory.update(self.eta, new_eta) + + def test_depth(self): + new_depth = mock.Mock(units=Unit('m'), nbounds=0) + self.factory.update(self.depth, new_depth) + self.assertIs(self.factory.depth, new_depth) + + def test_depth_incompatible_units(self): + new_depth = mock.Mock(units=Unit('Pa'), nbounds=0) + with self.assertRaises(ValueError): + self.factory.update(self.depth, new_depth) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/aux_factory/test_OceanSigmaZFactory.py b/lib/iris/tests/unit/aux_factory/test_OceanSigmaZFactory.py new file mode 100644 index 0000000000..bd13f4dfea --- /dev/null +++ b/lib/iris/tests/unit/aux_factory/test_OceanSigmaZFactory.py @@ -0,0 +1,395 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the +`iris.aux_factory.OceanSigmaZFactory` class. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from cf_units import Unit +import numpy as np + +from iris.aux_factory import OceanSigmaZFactory +from iris.coords import AuxCoord, DimCoord +from iris.tests import mock + + +class Test___init__(tests.IrisTest): + def setUp(self): + self.sigma = mock.Mock(units=Unit('1'), nbounds=0) + self.eta = mock.Mock(units=Unit('m'), nbounds=0) + self.depth = mock.Mock(units=Unit('m'), nbounds=0) + self.depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(1,)) + self.nsigma = mock.Mock(units=Unit('1'), nbounds=0, shape=(1,)) + self.zlev = mock.Mock(units=Unit('m'), nbounds=0) + self.kwargs = dict(sigma=self.sigma, eta=self.eta, + depth=self.depth, depth_c=self.depth_c, + nsigma=self.nsigma, zlev=self.zlev) + + def test_insufficient_coordinates(self): + with self.assertRaises(ValueError): + OceanSigmaZFactory() + with self.assertRaises(ValueError): + OceanSigmaZFactory(sigma=self.sigma, eta=self.eta, + depth=self.depth, depth_c=self.depth_c, + nsigma=self.nsigma, zlev=None) + with self.assertRaises(ValueError): + OceanSigmaZFactory(sigma=None, eta=None, depth=self.depth, + depth_c=self.depth_c, nsigma=self.nsigma, + zlev=self.zlev) + with self.assertRaises(ValueError): + OceanSigmaZFactory(sigma=self.sigma, eta=None, depth=None, + depth_c=self.depth_c, nsigma=self.nsigma, + zlev=self.zlev) + with self.assertRaises(ValueError): + OceanSigmaZFactory(sigma=self.sigma, eta=None, depth=self.depth, + depth_c=None, nsigma=self.nsigma, + zlev=self.zlev) + with self.assertRaises(ValueError): + OceanSigmaZFactory(sigma=self.sigma, eta=self.eta, + depth=self.depth, depth_c=self.depth_c, + nsigma=None, zlev=self.zlev) + + def test_sigma_too_many_bounds(self): + self.sigma.nbounds = 4 + with self.assertRaises(ValueError): + OceanSigmaZFactory(**self.kwargs) + + def test_zlev_too_many_bounds(self): + self.zlev.nbounds = 4 + with self.assertRaises(ValueError): + OceanSigmaZFactory(**self.kwargs) + + def test_sigma_zlev_same_boundedness(self): + self.zlev.nbounds = 2 + with self.assertRaises(ValueError): + OceanSigmaZFactory(**self.kwargs) + + def test_depth_c_non_scalar(self): + self.depth_c.shape = (2,) + with self.assertRaises(ValueError): + OceanSigmaZFactory(**self.kwargs) + + def test_nsigma_non_scalar(self): + self.nsigma.shape = (4,) + with self.assertRaises(ValueError): + OceanSigmaZFactory(**self.kwargs) + + def test_zlev_incompatible_units(self): + self.zlev.units = Unit('Pa') + with self.assertRaises(ValueError): + OceanSigmaZFactory(**self.kwargs) + + def test_sigma_incompatible_units(self): + self.sigma.units = Unit('km') + with self.assertRaises(ValueError): + OceanSigmaZFactory(**self.kwargs) + + def test_eta_incompatible_units(self): + self.eta.units = Unit('km') + with self.assertRaises(ValueError): + OceanSigmaZFactory(**self.kwargs) + + def test_depth_c_incompatible_units(self): + self.depth_c.units = Unit('km') + with self.assertRaises(ValueError): + OceanSigmaZFactory(**self.kwargs) + + def test_depth_incompatible_units(self): + self.depth.units = Unit('km') + with self.assertRaises(ValueError): + OceanSigmaZFactory(**self.kwargs) + + +class Test_dependencies(tests.IrisTest): + def setUp(self): + self.sigma = mock.Mock(units=Unit('1'), nbounds=0) + self.eta = mock.Mock(units=Unit('m'), nbounds=0) + self.depth = mock.Mock(units=Unit('m'), nbounds=0) + self.depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(1,)) + self.nsigma = mock.Mock(units=Unit('1'), nbounds=0, shape=(1,)) + self.zlev = mock.Mock(units=Unit('m'), nbounds=0) + self.kwargs = dict(sigma=self.sigma, eta=self.eta, + depth=self.depth, depth_c=self.depth_c, + nsigma=self.nsigma, zlev=self.zlev) + + def test_values(self): + factory = OceanSigmaZFactory(**self.kwargs) + self.assertEqual(factory.dependencies, self.kwargs) + + +class Test_make_coord(tests.IrisTest): + @staticmethod + def coord_dims(coord): + mapping = dict(sigma=(0,), eta=(1, 2), depth=(1, 2), + depth_c=(), nsigma=(), zlev=(0,)) + return mapping[coord.name()] + + @staticmethod + def derive(sigma, eta, depth, depth_c, nsigma, zlev, coord=True): + nsigma_slice = slice(0, int(nsigma)) + temp = eta + sigma * (np.minimum(depth_c, depth) + eta) + shape = temp.shape + result = np.ones(shape, dtype=temp.dtype) * zlev + result[nsigma_slice] = temp[nsigma_slice] + if coord: + name = 'sea_surface_height_above_reference_ellipsoid' + result = AuxCoord(result, + standard_name=name, + units='m', + attributes=dict(positive='up')) + return result + + def setUp(self): + self.sigma = DimCoord(np.arange(5, dtype=np.float) * 10, + long_name='sigma', units='1') + self.eta = AuxCoord(np.arange(4, dtype=np.float).reshape(2, 2), + long_name='eta', units='m') + self.depth = AuxCoord(np.arange(4, dtype=np.float).reshape(2, 2) * 10, + long_name='depth', units='m') + self.depth_c = AuxCoord([15], long_name='depth_c', units='m') + self.nsigma = AuxCoord([3], long_name='nsigma') + self.zlev = DimCoord(np.arange(5, dtype=np.float) * 10, + long_name='zlev', units='m') + self.kwargs = dict(sigma=self.sigma, eta=self.eta, depth=self.depth, + depth_c=self.depth_c, nsigma=self.nsigma, + zlev=self.zlev) + + def test_derived_points(self): + # Broadcast expected points given the known dimensional mapping. + sigma = self.sigma.points[..., np.newaxis, np.newaxis] + eta = self.eta.points[np.newaxis, ...] + depth = self.depth.points[np.newaxis, ...] + depth_c = self.depth_c.points + nsigma = self.nsigma.points + zlev = self.zlev.points[..., np.newaxis, np.newaxis] + # Calculate the expected result. + expected_coord = self.derive(sigma, eta, depth, depth_c, nsigma, zlev) + # Calculate the actual result. + factory = OceanSigmaZFactory(**self.kwargs) + coord = factory.make_coord(self.coord_dims) + self.assertEqual(expected_coord, coord) + + def test_derived_points_with_bounds(self): + self.sigma.guess_bounds() + self.zlev.guess_bounds() + # Broadcast expected points given the known dimensional mapping. + sigma = self.sigma.points[..., np.newaxis, np.newaxis] + eta = self.eta.points[np.newaxis, ...] + depth = self.depth.points[np.newaxis, ...] + depth_c = self.depth_c.points + nsigma = self.nsigma.points + zlev = self.zlev.points[..., np.newaxis, np.newaxis] + # Calculate the expected coordinate with points. + expected_coord = self.derive(sigma, eta, depth, depth_c, nsigma, zlev) + # Broadcast expected bounds given the known dimensional mapping. + sigma = self.sigma.bounds.reshape(sigma.shape + (2,)) + eta = self.eta.points.reshape(eta.shape + (1,)) + depth = self.depth.points.reshape(depth.shape + (1,)) + depth_c = self.depth_c.points.reshape(depth_c.shape + (1,)) + nsigma = self.nsigma.points.reshape(nsigma.shape + (1,)) + zlev = self.zlev.bounds.reshape(zlev.shape + (2,)) + # Calculate the expected bounds. + bounds = self.derive(sigma, eta, depth, depth_c, nsigma, zlev, + coord=False) + expected_coord.bounds = bounds + # Calculate the actual result. + factory = OceanSigmaZFactory(**self.kwargs) + coord = factory.make_coord(self.coord_dims) + self.assertEqual(expected_coord, coord) + + def test_no_eta(self): + # Broadcast expected points given the known dimensional mapping. + sigma = self.sigma.points[..., np.newaxis, np.newaxis] + eta = 0 + depth = self.depth.points[np.newaxis, ...] + depth_c = self.depth_c.points + nsigma = self.nsigma.points + zlev = self.zlev.points[..., np.newaxis, np.newaxis] + # Calculate the expected result. + expected_coord = self.derive(sigma, eta, depth, depth_c, nsigma, zlev) + # Calculate the actual result. + self.kwargs['eta'] = None + factory = OceanSigmaZFactory(**self.kwargs) + coord = factory.make_coord(self.coord_dims) + self.assertEqual(expected_coord, coord) + + def test_no_sigma(self): + # Broadcast expected points given the known dimensional mapping. + sigma = 0 + eta = self.eta.points[np.newaxis, ...] + depth = self.depth.points[np.newaxis, ...] + depth_c = self.depth_c.points + nsigma = self.nsigma.points + zlev = self.zlev.points[..., np.newaxis, np.newaxis] + # Calculate the expected result. + expected_coord = self.derive(sigma, eta, depth, depth_c, nsigma, zlev) + # Calculate the actual result. + self.kwargs['sigma'] = None + factory = OceanSigmaZFactory(**self.kwargs) + coord = factory.make_coord(self.coord_dims) + self.assertEqual(expected_coord, coord) + + def test_no_depth_c(self): + # Broadcast expected points given the known dimensional mapping. + sigma = self.sigma.points[..., np.newaxis, np.newaxis] + eta = self.eta.points[np.newaxis, ...] + depth = self.depth.points[np.newaxis, ...] + depth_c = 0 + nsigma = self.nsigma.points + zlev = self.zlev.points[..., np.newaxis, np.newaxis] + # Calculate the expected result. + expected_coord = self.derive(sigma, eta, depth, depth_c, nsigma, zlev) + # Calculate the actual result. + self.kwargs['depth_c'] = None + factory = OceanSigmaZFactory(**self.kwargs) + coord = factory.make_coord(self.coord_dims) + self.assertEqual(expected_coord, coord) + + def test_no_depth(self): + # Broadcast expected points given the known dimensional mapping. + sigma = self.sigma.points[..., np.newaxis, np.newaxis] + eta = self.eta.points[np.newaxis, ...] + depth = 0 + depth_c = self.depth_c.points + nsigma = self.nsigma.points + zlev = self.zlev.points[..., np.newaxis, np.newaxis] + # Calculate the expected result. + expected_coord = self.derive(sigma, eta, depth, depth_c, nsigma, zlev) + # Calculate the actual result. + self.kwargs['depth'] = None + factory = OceanSigmaZFactory(**self.kwargs) + coord = factory.make_coord(self.coord_dims) + self.assertEqual(expected_coord, coord) + + +class Test_update(tests.IrisTest): + def setUp(self): + self.sigma = mock.Mock(units=Unit('1'), nbounds=0) + self.eta = mock.Mock(units=Unit('m'), nbounds=0) + self.depth = mock.Mock(units=Unit('m'), nbounds=0) + self.depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(1,)) + self.nsigma = mock.Mock(units=Unit('1'), nbounds=0, shape=(1,)) + self.zlev = mock.Mock(units=Unit('m'), nbounds=0) + self.kwargs = dict(sigma=self.sigma, eta=self.eta, + depth=self.depth, depth_c=self.depth_c, + nsigma=self.nsigma, zlev=self.zlev) + self.factory = OceanSigmaZFactory(**self.kwargs) + + def test_sigma(self): + new_sigma = mock.Mock(units=Unit('1'), nbounds=0) + self.factory.update(self.sigma, new_sigma) + self.assertIs(self.factory.sigma, new_sigma) + + def test_sigma_too_many_bounds(self): + new_sigma = mock.Mock(units=Unit('1'), nbounds=4) + with self.assertRaises(ValueError): + self.factory.update(self.sigma, new_sigma) + + def test_sigma_zlev_same_boundedness(self): + new_sigma = mock.Mock(units=Unit('1'), nbounds=2) + with self.assertRaises(ValueError): + self.factory.update(self.sigma, new_sigma) + + def test_sigma_incompatible_units(self): + new_sigma = mock.Mock(units=Unit('Pa'), nbounds=0) + with self.assertRaises(ValueError): + self.factory.update(self.sigma, new_sigma) + + def test_eta(self): + new_eta = mock.Mock(units=Unit('m'), nbounds=0) + self.factory.update(self.eta, new_eta) + self.assertIs(self.factory.eta, new_eta) + + def test_eta_incompatible_units(self): + new_eta = mock.Mock(units=Unit('Pa'), nbounds=0) + with self.assertRaises(ValueError): + self.factory.update(self.eta, new_eta) + + def test_depth(self): + new_depth = mock.Mock(units=Unit('m'), nbounds=0) + self.factory.update(self.depth, new_depth) + self.assertIs(self.factory.depth, new_depth) + + def test_depth_incompatible_units(self): + new_depth = mock.Mock(units=Unit('Pa'), nbounds=0) + with self.assertRaises(ValueError): + self.factory.update(self.depth, new_depth) + + def test_depth_c(self): + new_depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(1,)) + self.factory.update(self.depth_c, new_depth_c) + self.assertIs(self.factory.depth_c, new_depth_c) + + def test_depth_c_non_scalar(self): + new_depth_c = mock.Mock(units=Unit('m'), nbounds=0, shape=(10,)) + with self.assertRaises(ValueError): + self.factory.update(self.depth_c, new_depth_c) + + def test_depth_c_incompatible_units(self): + new_depth_c = mock.Mock(units=Unit('Pa'), nbounds=0, shape=(1,)) + with self.assertRaises(ValueError): + self.factory.update(self.depth_c, new_depth_c) + + def test_nsigma(self): + new_nsigma = mock.Mock(units=Unit('1'), nbounds=0, shape=(1,)) + self.factory.update(self.nsigma, new_nsigma) + self.assertIs(self.factory.nsigma, new_nsigma) + + def test_nsigma_missing(self): + with self.assertRaises(ValueError): + self.factory.update(self.nsigma, None) + + def test_nsigma_non_scalar(self): + new_nsigma = mock.Mock(units=Unit('1'), nbounds=0, shape=(10,)) + with self.assertRaises(ValueError): + self.factory.update(self.nsigma, new_nsigma) + + def test_zlev(self): + new_zlev = mock.Mock(units=Unit('m'), nbounds=0) + self.factory.update(self.zlev, new_zlev) + self.assertIs(self.factory.zlev, new_zlev) + + def test_zlev_missing(self): + with self.assertRaises(ValueError): + self.factory.update(self.zlev, None) + + def test_zlev_too_many_bounds(self): + new_zlev = mock.Mock(units=Unit('m'), nbounds=4) + with self.assertRaises(ValueError): + self.factory.update(self.zlev, new_zlev) + + def test_zlev_same_boundedness(self): + new_zlev = mock.Mock(units=Unit('m'), nbounds=2) + with self.assertRaises(ValueError): + self.factory.update(self.zlev, new_zlev) + + def test_zlev_incompatible_units(self): + new_zlev = new_zlev = mock.Mock(units=Unit('Pa'), nbounds=0) + with self.assertRaises(ValueError): + self.factory.update(self.zlev, new_zlev) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/concatenate/__init__.py b/lib/iris/tests/unit/concatenate/__init__.py new file mode 100644 index 0000000000..5483ef78b5 --- /dev/null +++ b/lib/iris/tests/unit/concatenate/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris._concatenate` package.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/concatenate/test__CubeSignature.py b/lib/iris/tests/unit/concatenate/test__CubeSignature.py new file mode 100644 index 0000000000..7cb47746bb --- /dev/null +++ b/lib/iris/tests/unit/concatenate/test__CubeSignature.py @@ -0,0 +1,101 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Test class :class:`iris._concatenate._CubeSignature`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised +# before importing anything else. +import iris.tests as tests + +from cf_units import Unit +import numpy as np + +import iris +from iris._concatenate import _CubeSignature as CubeSignature +from iris.coords import AuxCoord, DimCoord +from iris.cube import Cube +from iris.util import new_axis + + +class Test__coordinate_dim_metadata_equality(tests.IrisTest): + def setUp(self): + nt = 10 + data = np.arange(nt, dtype=np.float32) + cube = Cube(data, standard_name='air_temperature', units='K') + # Temporal coordinate. + t_units = Unit('hours since 1970-01-01 00:00:00', calendar='gregorian') + t_coord = DimCoord(points=np.arange(nt), + standard_name='time', + units=t_units) + cube.add_dim_coord(t_coord, 0) + + # Increasing 1D time-series cube. + self.series_inc_cube = cube + self.series_inc = CubeSignature(self.series_inc_cube) + + # Decreasing 1D time-series cube. + self.series_dec_cube = self.series_inc_cube.copy() + self.series_dec_cube.remove_coord('time') + t_tmp = DimCoord(points=t_coord.points[::-1], + standard_name='time', + units=t_units) + self.series_dec_cube.add_dim_coord(t_tmp, 0) + self.series_dec = CubeSignature(self.series_dec_cube) + + # Scalar 0D time-series cube with scalar time coordinate. + cube = Cube(0, standard_name='air_temperature', units='K') + cube.add_aux_coord(DimCoord(points=nt, + standard_name='time', + units=t_units)) + self.scalar_cube = cube + + def test_scalar_non_common_axis(self): + scalar = CubeSignature(self.scalar_cube) + self.assertNotEqual(self.series_inc.dim_metadata, scalar.dim_metadata) + self.assertNotEqual(self.series_dec.dim_metadata, scalar.dim_metadata) + + def test_1d_single_value_common_axis(self): + # Manually promote scalar time cube to be a 1d cube. + single = CubeSignature(new_axis(self.scalar_cube, 'time')) + self.assertEqual(self.series_inc.dim_metadata, single.dim_metadata) + self.assertEqual(self.series_dec.dim_metadata, single.dim_metadata) + + def test_increasing_common_axis(self): + series_inc = self.series_inc + series_dec = self.series_dec + self.assertEqual(series_inc.dim_metadata, series_inc.dim_metadata) + self.assertNotEqual(series_inc.dim_metadata, series_dec.dim_metadata) + + def test_decreasing_common_axis(self): + series_inc = self.series_inc + series_dec = self.series_dec + self.assertNotEqual(series_dec.dim_metadata, series_inc.dim_metadata) + self.assertEqual(series_dec.dim_metadata, series_dec.dim_metadata) + + def test_circular(self): + series_inc = self.series_inc + circular_cube = self.series_inc_cube.copy() + circular_cube.coord('time').circular = True + circular = CubeSignature(circular_cube) + self.assertNotEqual(circular.dim_metadata, series_inc.dim_metadata) + self.assertEqual(circular.dim_metadata, circular.dim_metadata) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/concatenate/test_concatenate.py b/lib/iris/tests/unit/concatenate/test_concatenate.py new file mode 100644 index 0000000000..a958468d1f --- /dev/null +++ b/lib/iris/tests/unit/concatenate/test_concatenate.py @@ -0,0 +1,314 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Test function :func:`iris._concatenate.concatenate.py`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised +# before importing anything else. +import iris.tests as tests + +import cf_units +import numpy as np +import numpy.ma as ma + +from iris._concatenate import concatenate +from iris._lazy_data import as_lazy_data +import iris.coords +import iris.cube +from iris.exceptions import ConcatenateError + + +class TestEpoch(tests.IrisTest): + def simple_1d_time_cubes(self, reftimes, coords_points): + cubes = [] + data_points = [273, 275, 278, 277, 274] + for reftime, coord_points in zip(reftimes, coords_points): + cube = iris.cube.Cube(np.array(data_points, dtype=np.float32), + standard_name='air_temperature', + units='K') + unit = cf_units.Unit(reftime, calendar='gregorian') + coord = iris.coords.DimCoord(points=np.array(coord_points, + dtype=np.float32), + standard_name='time', + units=unit) + cube.add_dim_coord(coord, 0) + cubes.append(cube) + return cubes + + def test_concat_1d_with_same_time_units(self): + reftimes = ['hours since 1970-01-01 00:00:00', + 'hours since 1970-01-01 00:00:00'] + coords_points = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]] + cubes = self.simple_1d_time_cubes(reftimes, coords_points) + result = concatenate(cubes) + self.assertEqual(len(result), 1) + self.assertEqual(result[0].shape, (10,)) + + +class TestMessages(tests.IrisTest): + def setUp(self): + data = np.arange(24, dtype=np.float32).reshape(2, 3, 4) + cube = iris.cube.Cube(data, standard_name='air_temperature', units='K') + # Time coord + t_unit = cf_units.Unit('hours since 1970-01-01 00:00:00', + calendar='gregorian') + t_coord = iris.coords.DimCoord(points=np.arange(2, dtype=np.float32), + standard_name='time', + units=t_unit) + cube.add_dim_coord(t_coord, 0) + # Lats and lons + x_coord = iris.coords.DimCoord(points=np.arange(3, dtype=np.float32), + standard_name='longitude', + units='degrees') + cube.add_dim_coord(x_coord, 1) + y_coord = iris.coords.DimCoord(points=np.arange(4, dtype=np.float32), + standard_name='latitude', + units='degrees') + cube.add_dim_coord(y_coord, 2) + # Scalars + cube.add_aux_coord(iris.coords.AuxCoord([0], "height", units="m")) + # Aux Coords + cube.add_aux_coord(iris.coords.AuxCoord(data, + long_name='wibble', + units='1'), + data_dims=(0, 1, 2)) + cube.add_aux_coord(iris.coords.AuxCoord([0, 1, 2], + long_name='foo', + units='1'), + data_dims=(1,)) + self.cube = cube + + def test_definition_difference_message(self): + cube_1 = self.cube + cube_2 = cube_1.copy() + cube_2.units = '1' + exc_regexp = 'Cube metadata differs for phenomenon: *' + with self.assertRaisesRegexp(ConcatenateError, exc_regexp): + result = concatenate([cube_1, cube_2], True) + + def test_dimensions_difference_message(self): + cube_1 = self.cube + cube_2 = cube_1.copy() + cube_2.remove_coord('latitude') + exc_regexp = 'Dimension coordinates differ: .* != .*' + with self.assertRaisesRegexp(ConcatenateError, exc_regexp): + result = concatenate([cube_1, cube_2], True) + + def test_dimensions_metadata_difference_message(self): + cube_1 = self.cube + cube_2 = cube_1.copy() + cube_2.coord('latitude').long_name = 'bob' + exc_regexp = 'Dimension coordinates metadata differ: .* != .*' + with self.assertRaisesRegexp(ConcatenateError, exc_regexp): + result = concatenate([cube_1, cube_2], True) + + def test_aux_coords_difference_message(self): + cube_1 = self.cube + cube_2 = cube_1.copy() + cube_2.remove_coord('foo') + exc_regexp = 'Auxiliary coordinates differ: .* != .*' + with self.assertRaisesRegexp(ConcatenateError, exc_regexp): + result = concatenate([cube_1, cube_2], True) + + def test_aux_coords_metadata_difference_message(self): + cube_1 = self.cube + cube_2 = cube_1.copy() + cube_2.coord('foo').units = 'm' + exc_regexp = 'Auxiliary coordinates metadata differ: .* != .*' + with self.assertRaisesRegexp(ConcatenateError, exc_regexp): + result = concatenate([cube_1, cube_2], True) + + def test_scalar_coords_difference_message(self): + cube_1 = self.cube + cube_2 = cube_1.copy() + cube_2.remove_coord('height') + exc_regexp = 'Scalar coordinates differ: .* != .*' + with self.assertRaisesRegexp(ConcatenateError, exc_regexp): + result = concatenate([cube_1, cube_2], True) + + def test_scalar_coords_metadata_difference_message(self): + cube_1 = self.cube + cube_2 = cube_1.copy() + cube_2.coord('height').long_name = 'alice' + exc_regexp = 'Scalar coordinates metadata differ: .* != .*' + with self.assertRaisesRegexp(ConcatenateError, exc_regexp): + result = concatenate([cube_1, cube_2], True) + + def test_ndim_difference_message(self): + cube_1 = self.cube + cube_2 = iris.cube.Cube(np.arange(5, dtype=np.float32), + standard_name='air_temperature', + units='K') + x_coord = iris.coords.DimCoord(points=np.arange(5, dtype=np.float32), + standard_name='longitude', + units='degrees') + cube_2.add_dim_coord(x_coord, 0) + exc_regexp = 'Data dimensions differ: [0-9] != [0-9]' + with self.assertRaisesRegexp(ConcatenateError, exc_regexp): + result = concatenate([cube_1, cube_2], True) + + def test_datatype_difference_message(self): + cube_1 = self.cube + cube_2 = cube_1.copy() + cube_2.data.dtype = np.float64 + exc_regexp = 'Data types differ: .* != .*' + with self.assertRaisesRegexp(ConcatenateError, exc_regexp): + result = concatenate([cube_1, cube_2], True) + + +class TestOrder(tests.IrisTest): + def _make_cube(self, points, bounds=None): + nx = 4 + data = np.arange(len(points) * nx).reshape(len(points), nx) + cube = iris.cube.Cube(data, standard_name='air_temperature', units='K') + lat = iris.coords.DimCoord(points, 'latitude', bounds=bounds) + lon = iris.coords.DimCoord(np.arange(nx), 'longitude') + cube.add_dim_coord(lat, 0) + cube.add_dim_coord(lon, 1) + return cube + + def test_asc_points(self): + top = self._make_cube([10, 30, 50, 70, 90]) + bottom = self._make_cube([-90, -70, -50, -30, -10]) + result = concatenate([top, bottom]) + self.assertEqual(len(result), 1) + + def test_asc_bounds(self): + top = self._make_cube([22.5, 67.5], [[0, 45], [45, 90]]) + bottom = self._make_cube([-67.5, -22.5], [[-90, -45], [-45, 0]]) + result = concatenate([top, bottom]) + self.assertEqual(len(result), 1) + + def test_asc_points_with_singleton_ordered(self): + top = self._make_cube([5]) + bottom = self._make_cube([15, 25]) + result = concatenate([top, bottom]) + self.assertEqual(len(result), 1) + + def test_asc_points_with_singleton_unordered(self): + top = self._make_cube([25]) + bottom = self._make_cube([5, 15]) + result = concatenate([top, bottom]) + self.assertEqual(len(result), 1) + + def test_asc_bounds_with_singleton_ordered(self): + top = self._make_cube([5], [[0, 10]]) + bottom = self._make_cube([15, 25], [[10, 20], [20, 30]]) + result = concatenate([top, bottom]) + self.assertEqual(len(result), 1) + + def test_asc_bounds_with_singleton_unordered(self): + top = self._make_cube([25], [[20, 30]]) + bottom = self._make_cube([5, 15], [[0, 10], [10, 20]]) + result = concatenate([top, bottom]) + self.assertEqual(len(result), 1) + + def test_desc_points(self): + top = self._make_cube([90, 70, 50, 30, 10]) + bottom = self._make_cube([-10, -30, -50, -70, -90]) + result = concatenate([top, bottom]) + self.assertEqual(len(result), 1) + + def test_desc_bounds(self): + top = self._make_cube([67.5, 22.5], [[90, 45], [45, 0]]) + bottom = self._make_cube([-22.5, -67.5], [[0, -45], [-45, -90]]) + result = concatenate([top, bottom]) + self.assertEqual(len(result), 1) + + def test_desc_points_with_singleton_ordered(self): + top = self._make_cube([25]) + bottom = self._make_cube([15, 5]) + result = concatenate([top, bottom]) + self.assertEqual(len(result), 1) + + def test_desc_points_with_singleton_unordered(self): + top = self._make_cube([5]) + bottom = self._make_cube([25, 15]) + result = concatenate([top, bottom]) + self.assertEqual(len(result), 1) + + def test_desc_bounds_with_singleton_ordered(self): + top = self._make_cube([25], [[30, 20]]) + bottom = self._make_cube([15, 5], [[20, 10], [10, 0]]) + result = concatenate([top, bottom]) + self.assertEqual(len(result), 1) + + def test_desc_bounds_with_singleton_unordered(self): + top = self._make_cube([5], [[10, 0]]) + bottom = self._make_cube([25, 15], [[30, 20], [20, 10]]) + result = concatenate([top, bottom]) + self.assertEqual(len(result), 1) + + def test_points_all_singleton(self): + top = self._make_cube([5]) + bottom = self._make_cube([15]) + result1 = concatenate([top, bottom]) + result2 = concatenate([bottom, top]) + self.assertEqual(len(result1), 1) + self.assertEqual(len(result2), 1) + self.assertEqual(result1, result2) + + def test_asc_bounds_all_singleton(self): + top = self._make_cube([5], [0, 10]) + bottom = self._make_cube([15], [10, 20]) + result1 = concatenate([top, bottom]) + result2 = concatenate([bottom, top]) + self.assertEqual(len(result1), 1) + self.assertEqual(len(result2), 1) + self.assertEqual(result1, result2) + + def test_desc_bounds_all_singleton(self): + top = self._make_cube([5], [10, 0]) + bottom = self._make_cube([15], [20, 10]) + result1 = concatenate([top, bottom]) + result2 = concatenate([bottom, top]) + self.assertEqual(len(result1), 1) + self.assertEqual(len(result2), 1) + self.assertEqual(result1, result2) + + +class TestConcatenate__dask(tests.IrisTest): + def build_lazy_cube(self, points, bounds=None, nx=4): + data = np.arange(len(points) * nx).reshape(len(points), nx) + data = as_lazy_data(data) + cube = iris.cube.Cube(data, standard_name='air_temperature', units='K') + lat = iris.coords.DimCoord(points, 'latitude', bounds=bounds) + lon = iris.coords.DimCoord(np.arange(nx), 'longitude') + cube.add_dim_coord(lat, 0) + cube.add_dim_coord(lon, 1) + return cube + + def test_lazy_concatenate(self): + c1 = self.build_lazy_cube([1, 2]) + c2 = self.build_lazy_cube([3, 4, 5]) + cube, = concatenate([c1, c2]) + self.assertTrue(cube.has_lazy_data()) + self.assertFalse(ma.isMaskedArray(cube.data)) + + def test_lazy_concatenate_masked_array_mixed_deferred(self): + c1 = self.build_lazy_cube([1, 2]) + c2 = self.build_lazy_cube([3, 4, 5]) + c2.data = np.ma.masked_greater(c2.data, 3) + cube, = concatenate([c1, c2]) + self.assertTrue(cube.has_lazy_data()) + self.assertTrue(ma.isMaskedArray(cube.data)) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/config/__init__.py b/lib/iris/tests/unit/config/__init__.py new file mode 100644 index 0000000000..dd625e1e91 --- /dev/null +++ b/lib/iris/tests/unit/config/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.config` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/config/test_NetCDF.py b/lib/iris/tests/unit/config/test_NetCDF.py new file mode 100644 index 0000000000..3929319854 --- /dev/null +++ b/lib/iris/tests/unit/config/test_NetCDF.py @@ -0,0 +1,60 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.config.NetCDF` class.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import warnings + +import iris.config + + +class Test(tests.IrisTest): + def setUp(self): + self.options = iris.config.NetCDF() + + def test_basic(self): + self.assertFalse(self.options.conventions_override) + + def test_enabled(self): + self.options.conventions_override = True + self.assertTrue(self.options.conventions_override) + + def test_bad_value(self): + # A bad value should be ignored and replaced with the default value. + bad_value = 'wibble' + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + self.options.conventions_override = bad_value + self.assertFalse(self.options.conventions_override) + exp_wmsg = 'Attempting to set invalid value {!r}'.format(bad_value) + six.assertRegex(self, str(w[0].message), exp_wmsg) + + def test__contextmgr(self): + with self.options.context(conventions_override=True): + self.assertTrue(self.options.conventions_override) + self.assertFalse(self.options.conventions_override) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/coord_categorisation/__init__.py b/lib/iris/tests/unit/coord_categorisation/__init__.py index 80ef6b4103..5db08e8773 100644 --- a/lib/iris/tests/unit/coord_categorisation/__init__.py +++ b/lib/iris/tests/unit/coord_categorisation/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Unit tests for the :mod:`iris.coord_categorisation` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/coord_categorisation/test_add_categorised_coord.py b/lib/iris/tests/unit/coord_categorisation/test_add_categorised_coord.py index 9f014c657a..7f2aa1a721 100644 --- a/lib/iris/tests/unit/coord_categorisation/test_add_categorised_coord.py +++ b/lib/iris/tests/unit/coord_categorisation/test_add_categorised_coord.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -16,15 +16,22 @@ # along with Iris. If not, see . """Test function :func:`iris.coord_categorisation.add_categorised_coord`.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before # importing anything else import iris.tests as tests -import mock +from cf_units import CALENDARS as calendars +from cf_units import Unit import numpy as np from iris.coord_categorisation import add_categorised_coord +from iris.coord_categorisation import add_day_of_year +from iris.cube import Cube +from iris.coords import DimCoord +from iris.tests import mock class Test_add_categorised_coord(tests.IrisTest): @@ -42,7 +49,8 @@ def test_vectorise_call(self): # numpy.vectorize, before being applied to the points array. # The reason we use numpy.vectorize is to support multi-dimensional # coordinate points. - fn = lambda coord, v: v**2 + def fn(coord, v): + return v**2 with mock.patch('numpy.vectorize', return_value=self.vectorised) as vectorise_patch: @@ -68,7 +76,8 @@ def test_vectorise_call(self): def test_string_vectorised(self): # Check that special case handling of a vectorized string returning # function is taking place. - fn = lambda coord, v: '0123456789'[:v] + def fn(coord, v): + return '0123456789'[:v] with mock.patch('numpy.vectorize', return_value=self.vectorised) as vectorise_patch: @@ -82,5 +91,44 @@ def test_string_vectorised(self): .astype('|S64')) +class Test_add_day_of_year(tests.IrisTest): + def setUp(self): + self.expected = { + 'standard': np.array(list(range(360, 367)) + list(range(1, 4))), + 'gregorian': np.array(list(range(360, 367)) + list(range(1, 4))), + 'proleptic_gregorian': np.array(list(range(360, 367)) + + list(range(1, 4))), + 'noleap': np.array(list(range(359, 366)) + list(range(1, 4))), + 'julian': np.array(list(range(360, 367)) + list(range(1, 4))), + 'all_leap': np.array(list(range(360, 367)) + list(range(1, 4))), + '365_day': np.array(list(range(359, 366)) + list(range(1, 4))), + '366_day': np.array(list(range(360, 367)) + list(range(1, 4))), + '360_day': np.array(list(range(355, 361)) + list(range(1, 5)))} + + def make_cube(self, calendar): + n_times = 10 + cube = Cube(np.arange(n_times)) + time_coord = DimCoord(np.arange(n_times), standard_name='time', + units=Unit('days since 1980-12-25', + calendar=calendar)) + cube.add_dim_coord(time_coord, 0) + return cube + + def test_calendars(self): + for calendar in calendars: + # Skip the Julian calendar due to + # https://github.com/Unidata/netcdftime/issues/13 + # Remove this if block once the issue is resolved. + if calendar == 'julian': + continue + cube = self.make_cube(calendar) + add_day_of_year(cube, 'time') + points = cube.coord('day_of_year').points + expected_points = self.expected[calendar] + msg = 'Test failed for the following calendar: {}.' + self.assertArrayEqual(points, expected_points, + err_msg=msg.format(calendar)) + + if __name__ == '__main__': tests.main() diff --git a/lib/iris/tests/unit/coord_categorisation/test_add_hour.py b/lib/iris/tests/unit/coord_categorisation/test_add_hour.py new file mode 100644 index 0000000000..737d8a650b --- /dev/null +++ b/lib/iris/tests/unit/coord_categorisation/test_add_hour.py @@ -0,0 +1,92 @@ +# (C) British Crown Copyright 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test coordinate categorisation function add_hour. +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import cf_units +import numpy as np + +import iris +import iris.coord_categorisation as ccat + + +class Test_add_hour(tests.IrisTest): + def setUp(self): + # make a series of 'hour numbers' for the time + hour_numbers = np.arange(0, 200, 5, dtype=np.int32) + + # use hour numbers as data values also (don't actually use this for + # anything) + cube = iris.cube.Cube( + hour_numbers, long_name='test cube', units='metres') + + time_coord = iris.coords.DimCoord( + hour_numbers, standard_name='time', + units=cf_units.Unit('hours since epoch', 'gregorian')) + cube.add_dim_coord(time_coord, 0) + + self.hour_numbers = hour_numbers + self.cube = cube + self.time_coord = time_coord + + def test_bad_coord(self): + with self.assertRaises(iris.exceptions.CoordinateNotFoundError): + ccat.add_hour(self.cube, 'DOES NOT EXIST', name='my_hour') + + def test_explicit_result_name_specify_coord_by_name(self): + coord_name = 'my_hour' + msg = 'Missing/incorrectly named result for add_hour' + + # Specify source coordinate by name + cube = self.cube + ccat.add_hour(cube, 'time', name=coord_name) + result_coords = cube.coords(coord_name) + self.assertEqual(len(result_coords), 1, msg) + + def test_explicit_result_name_specify_coord_by_reference(self): + coord_name = 'my_hour' + msg = 'Missing/incorrectly named result for add_hour' + + # Specify source coordinate by coordinate reference + cube = self.cube + time = cube.coord('time') + ccat.add_hour(cube, time, name=coord_name) + result_coords = cube.coords(coord_name) + self.assertEqual(len(result_coords), 1, msg) + + def test_basic(self): + coord_name = 'my_hour' + cube = self.cube + time_coord = self.time_coord + expected_coord = iris.coords.AuxCoord( + self.hour_numbers % 24, long_name=coord_name) + + ccat.add_hour(cube, time_coord, coord_name) + + self.assertEqual(cube.coord(coord_name), expected_coord) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/coord_systems/__init__.py b/lib/iris/tests/unit/coord_systems/__init__.py new file mode 100644 index 0000000000..c7bfcb2dcf --- /dev/null +++ b/lib/iris/tests/unit/coord_systems/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.coord_systems` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/coord_systems/test_AlbersEqualArea.py b/lib/iris/tests/unit/coord_systems/test_AlbersEqualArea.py new file mode 100644 index 0000000000..dd428fe1c8 --- /dev/null +++ b/lib/iris/tests/unit/coord_systems/test_AlbersEqualArea.py @@ -0,0 +1,100 @@ +# (C) British Crown Copyright 2015 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the :class:`iris.coord_systems.AlbersEqualArea` class. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import cartopy.crs as ccrs +from iris.coord_systems import GeogCS, AlbersEqualArea + + +class Test_as_cartopy_crs(tests.IrisTest): + def setUp(self): + self.latitude_of_projection_origin = 0.0 + self.longitude_of_central_meridian = 0.0 + self.semi_major_axis = 6377563.396 + self.semi_minor_axis = 6356256.909 + self.false_easting = 0.0 + self.false_northing = 0.0 + self.standard_parallels = (-18., -36.) + self.ellipsoid = GeogCS(self.semi_major_axis, self.semi_minor_axis) + self.aea_cs = AlbersEqualArea( + self.latitude_of_projection_origin, + self.longitude_of_central_meridian, + self.false_easting, + self.false_northing, + self.standard_parallels, + ellipsoid=self.ellipsoid) + + def test_crs_creation(self): + res = self.aea_cs.as_cartopy_crs() + globe = ccrs.Globe(semimajor_axis=self.semi_major_axis, + semiminor_axis=self.semi_minor_axis, + ellipse=None) + expected = ccrs.AlbersEqualArea( + self.longitude_of_central_meridian, + self.latitude_of_projection_origin, + self.false_easting, + self.false_northing, + self.standard_parallels, + globe=globe) + self.assertEqual(res, expected) + + +class Test_as_cartopy_projection(tests.IrisTest): + def setUp(self): + self.latitude_of_projection_origin = 0.0 + self.longitude_of_central_meridian = 0.0 + self.semi_major_axis = 6377563.396 + self.semi_minor_axis = 6356256.909 + self.false_easting = 0.0 + self.false_northing = 0.0 + self.standard_parallels = (-18., -36.) + self.ellipsoid = GeogCS(self.semi_major_axis, self.semi_minor_axis) + self.aea_cs = AlbersEqualArea( + self.latitude_of_projection_origin, + self.longitude_of_central_meridian, + self.false_easting, + self.false_northing, + self.standard_parallels, + ellipsoid=self.ellipsoid) + + def test_projection_creation(self): + res = self.aea_cs.as_cartopy_projection() + globe = ccrs.Globe(semimajor_axis=self.semi_major_axis, + semiminor_axis=self.semi_minor_axis, + ellipse=None) + expected = ccrs.AlbersEqualArea( + self.latitude_of_projection_origin, + self.longitude_of_central_meridian, + self.false_easting, + self.false_northing, + self.standard_parallels, + globe=globe) + self.assertEqual(res, expected) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/coord_systems/test_LambertAzimuthalEqualArea.py b/lib/iris/tests/unit/coord_systems/test_LambertAzimuthalEqualArea.py new file mode 100644 index 0000000000..fe16156607 --- /dev/null +++ b/lib/iris/tests/unit/coord_systems/test_LambertAzimuthalEqualArea.py @@ -0,0 +1,94 @@ +# (C) British Crown Copyright 2015 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the :class:`iris.coord_systems.LambertAzimuthalEqualArea` class. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import cartopy.crs as ccrs +from iris.coord_systems import GeogCS, LambertAzimuthalEqualArea + + +class Test_as_cartopy_crs(tests.IrisTest): + def setUp(self): + self.latitude_of_projection_origin = 90.0 + self.longitude_of_projection_origin = 0.0 + self.semi_major_axis = 6377563.396 + self.semi_minor_axis = 6356256.909 + self.false_easting = 0.0 + self.false_northing = 0.0 + self.ellipsoid = GeogCS(self.semi_major_axis, self.semi_minor_axis) + self.laea_cs = LambertAzimuthalEqualArea( + self.latitude_of_projection_origin, + self.longitude_of_projection_origin, + self.false_easting, + self.false_northing, + ellipsoid=self.ellipsoid) + + def test_crs_creation(self): + res = self.laea_cs.as_cartopy_crs() + globe = ccrs.Globe(semimajor_axis=self.semi_major_axis, + semiminor_axis=self.semi_minor_axis, + ellipse=None) + expected = ccrs.LambertAzimuthalEqualArea( + self.longitude_of_projection_origin, + self.latitude_of_projection_origin, + self.false_easting, + self.false_northing, + globe=globe) + self.assertEqual(res, expected) + + +class Test_as_cartopy_projection(tests.IrisTest): + def setUp(self): + self.latitude_of_projection_origin = 0.0 + self.longitude_of_projection_origin = 0.0 + self.semi_major_axis = 6377563.396 + self.semi_minor_axis = 6356256.909 + self.false_easting = 0.0 + self.false_northing = 0.0 + self.ellipsoid = GeogCS(self.semi_major_axis, self.semi_minor_axis) + self.laea_cs = LambertAzimuthalEqualArea( + self.latitude_of_projection_origin, + self.longitude_of_projection_origin, + self.false_easting, + self.false_northing, + ellipsoid=self.ellipsoid) + + def test_projection_creation(self): + res = self.laea_cs.as_cartopy_projection() + globe = ccrs.Globe(semimajor_axis=self.semi_major_axis, + semiminor_axis=self.semi_minor_axis, + ellipse=None) + expected = ccrs.LambertAzimuthalEqualArea( + self.latitude_of_projection_origin, + self.longitude_of_projection_origin, + self.false_easting, + self.false_northing, + globe=globe) + self.assertEqual(res, expected) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/coord_systems/test_Mercator.py b/lib/iris/tests/unit/coord_systems/test_Mercator.py new file mode 100644 index 0000000000..a2791efe67 --- /dev/null +++ b/lib/iris/tests/unit/coord_systems/test_Mercator.py @@ -0,0 +1,109 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :class:`iris.coord_systems.Mercator` class.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import cartopy.crs as ccrs +from iris.coord_systems import GeogCS, Mercator + + +class Test_Mercator__basics(tests.IrisTest): + def setUp(self): + self.tm = Mercator(longitude_of_projection_origin=90.0, + ellipsoid=GeogCS(6377563.396, 6356256.909)) + + def test_construction(self): + self.assertXMLElement(self.tm, ("coord_systems", "Mercator.xml")) + + def test_repr(self): + expected = ("Mercator(longitude_of_projection_origin=90.0, " + "ellipsoid=GeogCS(semi_major_axis=6377563.396, " + "semi_minor_axis=6356256.909), " + "standard_parallel=0.0)") + self.assertEqual(expected, repr(self.tm)) + + +class Test_Mercator__as_cartopy_crs(tests.IrisTest): + def test_simple(self): + # Check that a projection set up with all the defaults is correctly + # converted to a cartopy CRS. + merc_cs = Mercator() + res = merc_cs.as_cartopy_crs() + expected = ccrs.Mercator(globe=ccrs.Globe()) + self.assertEqual(res, expected) + + def test_extra_kwargs(self): + # Check that a projection with non-default values is correctly + # converted to a cartopy CRS. + longitude_of_projection_origin = 90.0 + true_scale_lat = 14.0 + ellipsoid = GeogCS(semi_major_axis=6377563.396, + semi_minor_axis=6356256.909) + + merc_cs = Mercator( + longitude_of_projection_origin, + ellipsoid=ellipsoid, + standard_parallel=true_scale_lat) + + expected = ccrs.Mercator( + central_longitude=longitude_of_projection_origin, + globe=ccrs.Globe(semimajor_axis=6377563.396, + semiminor_axis=6356256.909, ellipse=None), + latitude_true_scale=true_scale_lat) + + res = merc_cs.as_cartopy_crs() + self.assertEqual(res, expected) + + +class Test_as_cartopy_projection(tests.IrisTest): + def test_simple(self): + # Check that a projection set up with all the defaults is correctly + # converted to a cartopy projection. + merc_cs = Mercator() + res = merc_cs.as_cartopy_projection() + expected = ccrs.Mercator(globe=ccrs.Globe()) + self.assertEqual(res, expected) + + def test_extra_kwargs(self): + longitude_of_projection_origin = 90.0 + true_scale_lat = 14.0 + ellipsoid = GeogCS(semi_major_axis=6377563.396, + semi_minor_axis=6356256.909) + + merc_cs = Mercator( + longitude_of_projection_origin, + ellipsoid=ellipsoid, + standard_parallel=true_scale_lat) + + expected = ccrs.Mercator( + central_longitude=longitude_of_projection_origin, + globe=ccrs.Globe(semimajor_axis=6377563.396, + semiminor_axis=6356256.909, ellipse=None), + latitude_true_scale=true_scale_lat) + + res = merc_cs.as_cartopy_projection() + self.assertEqual(res, expected) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/coord_systems/test_Orthographic.py b/lib/iris/tests/unit/coord_systems/test_Orthographic.py new file mode 100644 index 0000000000..b15387581d --- /dev/null +++ b/lib/iris/tests/unit/coord_systems/test_Orthographic.py @@ -0,0 +1,77 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :class:`iris.coord_systems.Orthographic` class.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import cartopy.crs as ccrs +from iris.coord_systems import GeogCS, Orthographic + + +class Test_as_cartopy_crs(tests.IrisTest): + def setUp(self): + self.latitude_of_projection_origin = 0.0 + self.longitude_of_projection_origin = 0.0 + self.semi_major_axis = 6377563.396 + self.semi_minor_axis = 6356256.909 + self.ellipsoid = GeogCS(self.semi_major_axis, self.semi_minor_axis) + self.ortho_cs = Orthographic(self.latitude_of_projection_origin, + self.longitude_of_projection_origin, + ellipsoid=self.ellipsoid) + + def test_crs_creation(self): + res = self.ortho_cs.as_cartopy_crs() + globe = ccrs.Globe(semimajor_axis=self.semi_major_axis, + semiminor_axis=self.semi_minor_axis, + ellipse=None) + expected = ccrs.Orthographic( + self.latitude_of_projection_origin, + self.longitude_of_projection_origin, + globe=globe) + self.assertEqual(res, expected) + + +class Test_as_cartopy_projection(tests.IrisTest): + def setUp(self): + self.latitude_of_projection_origin = 0.0 + self.longitude_of_projection_origin = 0.0 + self.semi_major_axis = 6377563.396 + self.semi_minor_axis = 6356256.909 + self.ellipsoid = GeogCS(self.semi_major_axis, self.semi_minor_axis) + self.ortho_cs = Orthographic(self.latitude_of_projection_origin, + self.longitude_of_projection_origin, + ellipsoid=self.ellipsoid) + + def test_projection_creation(self): + res = self.ortho_cs.as_cartopy_projection() + globe = ccrs.Globe(semimajor_axis=self.semi_major_axis, + semiminor_axis=self.semi_minor_axis, + ellipse=None) + expected = ccrs.Orthographic( + self.latitude_of_projection_origin, + self.longitude_of_projection_origin, + globe=globe) + self.assertEqual(res, expected) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/coord_systems/test_RotatedPole.py b/lib/iris/tests/unit/coord_systems/test_RotatedPole.py new file mode 100644 index 0000000000..c6a2f2425d --- /dev/null +++ b/lib/iris/tests/unit/coord_systems/test_RotatedPole.py @@ -0,0 +1,71 @@ +# (C) British Crown Copyright 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :class:`iris.coord_systems.RotatedPole` class.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import cartopy +import cartopy.crs as ccrs +from iris.coord_systems import GeogCS, RotatedGeogCS +from iris.tests import mock + + +class Test_init(tests.IrisTest): + def setUp(self): + self.pole_lon = 171.77 + self.pole_lat = 49.55 + self.rotation_about_new_pole = 180.0 + self.rp_crs = RotatedGeogCS(self.pole_lat, self.pole_lon, + self.rotation_about_new_pole) + + def test_crs_creation(self): + self.assertEqual(self.pole_lon, self.rp_crs.grid_north_pole_longitude) + self.assertEqual(self.pole_lat, self.rp_crs.grid_north_pole_latitude) + self.assertEqual(self.rotation_about_new_pole, + self.rp_crs.north_pole_grid_longitude) + + def test_as_cartopy_crs(self): + if cartopy.__version__ < '0.12': + with mock.patch('warnings.warn') as warn: + accrs = self.rp_crs.as_cartopy_crs() + self.assertEqual(warn.call_count, 1) + else: + accrs = self.rp_crs.as_cartopy_crs() + expected = ccrs.RotatedGeodetic(self.pole_lon, self.pole_lat, + self.rotation_about_new_pole) + self.assertEqual(sorted(accrs.proj4_init.split(' +')), + sorted(expected.proj4_init.split(' +'))) + + def test_as_cartopy_projection(self): + if cartopy.__version__ < '0.12': + with mock.patch('warnings.warn') as warn: + accrs = self.rp_crs.as_cartopy_projection() + self.assertEqual(warn.call_count, 1) + else: + accrsp = self.rp_crs.as_cartopy_projection() + expected = ccrs.RotatedPole(self.pole_lon, self.pole_lat, + self.rotation_about_new_pole) + self.assertEqual(sorted(accrsp.proj4_init.split(' +')), + sorted(expected.proj4_init.split(' +'))) + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/coord_systems/test_VerticalPerspective.py b/lib/iris/tests/unit/coord_systems/test_VerticalPerspective.py new file mode 100644 index 0000000000..e225355d11 --- /dev/null +++ b/lib/iris/tests/unit/coord_systems/test_VerticalPerspective.py @@ -0,0 +1,97 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :class:`iris.coord_systems.VerticalPerspective` class.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import cartopy.crs as ccrs +from iris.coord_systems import GeogCS, VerticalPerspective + + +class Test_cartopy_crs(tests.IrisTest): + def setUp(self): + self.latitude_of_projection_origin = 0.0 + self.longitude_of_projection_origin = 0.0 + self.semi_major_axis = 6377563.396 + self.semi_minor_axis = 6356256.909 + self.perspective_point_height = 38204820000.0 + self.ellipsoid = GeogCS(self.semi_major_axis, self.semi_minor_axis) + self.vp_cs = VerticalPerspective(self.latitude_of_projection_origin, + self.longitude_of_projection_origin, + self.perspective_point_height, + ellipsoid=self.ellipsoid) + + def test_crs_creation(self): + res = self.vp_cs.as_cartopy_crs() + globe = ccrs.Globe(semimajor_axis=self.semi_major_axis, + semiminor_axis=self.semi_minor_axis, + ellipse=None) + expected = ccrs.Geostationary( + self.longitude_of_projection_origin, + self.perspective_point_height, + globe=globe) + self.assertEqual(res, expected) + + +class Test_cartopy_projection(tests.IrisTest): + def setUp(self): + self.latitude_of_projection_origin = 0.0 + self.longitude_of_projection_origin = 0.0 + self.semi_major_axis = 6377563.396 + self.semi_minor_axis = 6356256.909 + self.perspective_point_height = 38204820000.0 + self.ellipsoid = GeogCS(self.semi_major_axis, self.semi_minor_axis) + self.vp_cs = VerticalPerspective(self.latitude_of_projection_origin, + self.longitude_of_projection_origin, + self.perspective_point_height, + ellipsoid=self.ellipsoid) + + def test_projection_creation(self): + res = self.vp_cs.as_cartopy_projection() + globe = ccrs.Globe(semimajor_axis=self.semi_major_axis, + semiminor_axis=self.semi_minor_axis, + ellipse=None) + expected = ccrs.Geostationary( + self.longitude_of_projection_origin, + self.perspective_point_height, + globe=globe) + self.assertEqual(res, expected) + + +class Test_non_zero_lat(tests.IrisTest): + def setUp(self): + self.latitude_of_projection_origin = 22.0 + self.longitude_of_projection_origin = 11.0 + self.semi_major_axis = 6377563.396 + self.semi_minor_axis = 6356256.909 + self.perspective_point_height = 38204820000.0 + self.ellipsoid = GeogCS(self.semi_major_axis, self.semi_minor_axis) + + def test_lat(self): + with self.assertRaises(ValueError): + res = VerticalPerspective(self.latitude_of_projection_origin, + self.longitude_of_projection_origin, + self.perspective_point_height, + ellipsoid=self.ellipsoid) + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/coords/__init__.py b/lib/iris/tests/unit/coords/__init__.py index 45462baa0b..9d5da3a543 100644 --- a/lib/iris/tests/unit/coords/__init__.py +++ b/lib/iris/tests/unit/coords/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -14,4 +14,120 @@ # # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . -"""Unit tests for the :mod:`iris.coords` module.""" +""" +Unit tests for the :mod:`iris.coords` module. + +Provides test methods and classes common to +:class:`~iris.tests.unit.coords.test_AuxCoord` and +:class:`~iris.tests.unit.coords.test_DimCoord`. + +""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import dask.array as da +import numpy as np + +from iris._lazy_data import is_lazy_data + + +def setup_test_arrays(self, shape): + # Create standard coordinate points and bounds test arrays, + # given a desired coord shape. + # Also create lazy versions, and save all on the 'self' object. + n_pts = np.prod(shape) + # Note: the values must be integral for testing integer dtypes. + points = 10.0 * np.arange(n_pts, dtype=float).reshape(shape) + lower = points - 2.0 + upper = points + 2.0 + bounds = np.stack((lower, upper), axis=-1) + self.pts_real = points + self.pts_lazy = da.from_array(points, points.shape) + self.bds_real = bounds + self.bds_lazy = da.from_array(bounds, bounds.shape) + + +def is_real_data(array): + # A parallel to :func:`iris._lazy_data.is_lazy_data`. + # Not just "not lazy" : ensure it is a 'real' array (i.e. numpy). + return isinstance(array, np.ndarray) + + +def arrays_share_data(a1, a2): + # Check whether 2 real arrays with the same content view the same data. + # For an ndarray x, x.base will either be None (if x owns its data) or a + # reference to the array which owns its data (if x is a view). + return a1 is a2 or \ + a1.base is a2 or \ + a2.base is a1 or \ + a1.base is a2.base and a1.base is not None + + +def lazyness_string(data): + # Represent the lazyness of an array as a string. + return 'lazy' if is_lazy_data(data) else 'real' + + +def coords_all_dtypes_and_lazynesses(self, coord_class): + # Generate coords with all possible types of points and bounds, and all + # of the given dtypes. + points_types = ['real', 'lazy'] + bounds_types = ['no', 'real', 'lazy'] + # Test a few specific combinations of points+bounds dtypes, including + # cases where they are different. + dtype_pairs = [(np.float64, np.float64), + (np.int16, np.int16), + (np.int16, np.float32), + (np.float64, np.int32)] + for pts_dtype, bds_dtype in dtype_pairs: + for points_type_name in points_types: + for bounds_type_name in bounds_types: + pts = np.asarray(self.pts_real, dtype=pts_dtype) + bds = np.asarray(self.bds_real, dtype=bds_dtype) + if points_type_name == 'lazy': + pts = da.from_array(pts, pts.shape) + if bounds_type_name == 'lazy': + bds = da.from_array(bds, bds.shape) + elif bounds_type_name == 'no': + bds = None + coord = coord_class(pts, bounds=bds) + result = (coord, points_type_name, bounds_type_name) + yield result + + +class CoordTestMixin(object): + def setupTestArrays(self, shape=(3,)): + setup_test_arrays(self, shape=shape) + + def assertArraysShareData(self, a1, a2, *args, **kwargs): + # Check that two arrays are both real, same dtype, and based on the + # same underlying data (so changing one will change the other). + self.assertIsRealArray(a1) + self.assertIsRealArray(a2) + self.assertEqual(a1.dtype, a2.dtype) + self.assertTrue(arrays_share_data(a1, a2), *args, **kwargs) + + def assertArraysDoNotShareData(self, a1, a2, *args, **kwargs): + self.assertFalse(arrays_share_data(a1, a2), *args, **kwargs) + + def assertIsRealArray(self, array, *args, **kwargs): + # Check that the arg is a real array. + self.assertTrue(is_real_data(array), *args, **kwargs) + + def assertIsLazyArray(self, array, *args, **kwargs): + # Check that the arg is a lazy array. + self.assertTrue(is_lazy_data(array), *args, **kwargs) + + def assertEqualRealArraysAndDtypes(self, a1, a2, *args, **kwargs): + # Check that two arrays are real, equal, and have same dtype. + self.assertIsRealArray(a1) + self.assertIsRealArray(a2) + self.assertEqual(a1.dtype, a2.dtype) + self.assertArrayEqual(a1, a2) + + def assertEqualLazyArraysAndDtypes(self, a1, a2, *args, **kwargs): + # Check that two arrays are lazy, equal, and have same dtype. + self.assertIsLazyArray(a1) + self.assertIsLazyArray(a2) + self.assertEqual(a1.dtype, a2.dtype) + self.assertArrayEqual(a1.compute(), a2.compute()) diff --git a/lib/iris/tests/unit/coords/test_AuxCoord.py b/lib/iris/tests/unit/coords/test_AuxCoord.py new file mode 100644 index 0000000000..39e5048b14 --- /dev/null +++ b/lib/iris/tests/unit/coords/test_AuxCoord.py @@ -0,0 +1,628 @@ +# (C) British Crown Copyright 2017 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the :class:`iris.coords.AuxCoord` class. + +Note: a lot of these methods are actually defined by the :class:`Coord` class, +but can only be tested on concrete instances (DimCoord or AuxCoord). + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.tests.unit.coords import (CoordTestMixin, + lazyness_string, + coords_all_dtypes_and_lazynesses) + +from cf_units import Unit +from iris.coords import AuxCoord +from iris._lazy_data import as_lazy_data + + +class AuxCoordTestMixin(CoordTestMixin): + # Define a 2-D default array shape. + def setupTestArrays(self, shape=(2, 3)): + super(AuxCoordTestMixin, self).setupTestArrays(shape) + + +class Test__init__(tests.IrisTest, AuxCoordTestMixin): + # Test for AuxCoord creation, with various combinations of points and + # bounds = real / lazy / None. + def setUp(self): + self.setupTestArrays() + + def test_lazyness_and_dtype_combinations(self): + for (coord, points_type_name, bounds_type_name) in \ + coords_all_dtypes_and_lazynesses(self, AuxCoord): + pts = coord.core_points() + bds = coord.core_bounds() + # Check properties of points. + if points_type_name == 'real': + # Real points. + if coord.dtype == self.pts_real.dtype: + self.assertArraysShareData( + pts, self.pts_real, + 'Points are not the same data as the provided array.') + self.assertIsNot( + pts, self.pts_real, + 'Points array is the same instance as the provided ' + 'array.') + else: + # the original points were cast to a test dtype. + check_pts = self.pts_real.astype(coord.dtype) + self.assertEqualRealArraysAndDtypes(pts, check_pts) + else: + # Lazy points : the core data may be promoted to float. + check_pts = self.pts_lazy.astype(pts.dtype) + self.assertEqualLazyArraysAndDtypes(pts, check_pts) + # The realisation type should be correct, though. + target_dtype = coord.dtype + self.assertEqual(coord.points.dtype, target_dtype) + + # Check properties of bounds. + if bounds_type_name == 'real': + # Real bounds. + if coord.bounds_dtype == self.bds_real.dtype: + self.assertArraysShareData( + bds, self.bds_real, + 'Bounds are not the same data as the provided array.') + self.assertIsNot( + pts, self.pts_real, + 'Bounds array is the same instance as the provided ' + 'array.') + else: + # the original bounds were cast to a test dtype. + check_bds = self.bds_real.astype(coord.bounds_dtype) + self.assertEqualRealArraysAndDtypes(bds, check_bds) + elif bounds_type_name == 'lazy': + # Lazy points : the core data may be promoted to float. + check_bds = self.bds_lazy.astype(bds.dtype) + self.assertEqualLazyArraysAndDtypes(bds, check_bds) + # The realisation type should be correct, though. + target_dtype = coord.bounds_dtype + self.assertEqual(coord.bounds.dtype, target_dtype) + + def test_fail_bounds_shape_mismatch(self): + bds_shape = list(self.bds_real.shape) + bds_shape[0] += 1 + bds_wrong = np.zeros(bds_shape) + msg = 'Bounds shape must be compatible with points shape' + with self.assertRaisesRegexp(ValueError, msg): + AuxCoord(self.pts_real, bounds=bds_wrong) + + +class Test_core_points(tests.IrisTest, AuxCoordTestMixin): + # Test for AuxCoord.core_points() with various types of points and bounds. + def setUp(self): + self.setupTestArrays() + + def test_real_points(self): + coord = AuxCoord(self.pts_real) + result = coord.core_points() + self.assertArraysShareData( + result, self.pts_real, + 'core_points() do not share data with the internal array.') + + def test_lazy_points(self): + coord = AuxCoord(self.pts_lazy) + result = coord.core_points() + self.assertEqualLazyArraysAndDtypes(result, self.pts_lazy) + + def test_lazy_points_realise(self): + coord = AuxCoord(self.pts_lazy) + real_points = coord.points + result = coord.core_points() + self.assertEqualRealArraysAndDtypes(result, real_points) + + +class Test_core_bounds(tests.IrisTest, AuxCoordTestMixin): + # Test for AuxCoord.core_bounds() with various types of points and bounds. + def setUp(self): + self.setupTestArrays() + + def test_no_bounds(self): + coord = AuxCoord(self.pts_real) + result = coord.core_bounds() + self.assertIsNone(result) + + def test_real_bounds(self): + coord = AuxCoord(self.pts_real, bounds=self.bds_real) + result = coord.core_bounds() + self.assertArraysShareData( + result, self.bds_real, + 'core_bounds() do not share data with the internal array.') + + def test_lazy_bounds(self): + coord = AuxCoord(self.pts_real, bounds=self.bds_lazy) + result = coord.core_bounds() + self.assertEqualLazyArraysAndDtypes(result, self.bds_lazy) + + def test_lazy_bounds_realise(self): + coord = AuxCoord(self.pts_real, bounds=self.bds_lazy) + real_bounds = coord.bounds + result = coord.core_bounds() + self.assertEqualRealArraysAndDtypes(result, real_bounds) + + +class Test_lazy_points(tests.IrisTest, AuxCoordTestMixin): + def setUp(self): + self.setupTestArrays() + + def test_real_core(self): + coord = AuxCoord(self.pts_real) + result = coord.lazy_points() + self.assertEqualLazyArraysAndDtypes(result, self.pts_lazy) + + def test_lazy_core(self): + coord = AuxCoord(self.pts_lazy) + result = coord.lazy_points() + self.assertIs(result, self.pts_lazy) + + +class Test_lazy_bounds(tests.IrisTest, AuxCoordTestMixin): + def setUp(self): + self.setupTestArrays() + + def test_no_bounds(self): + coord = AuxCoord(self.pts_real) + result = coord.lazy_bounds() + self.assertIsNone(result) + + def test_real_core(self): + coord = AuxCoord(self.pts_real, bounds=self.bds_real) + result = coord.lazy_bounds() + self.assertEqualLazyArraysAndDtypes(result, self.bds_lazy) + + def test_lazy_core(self): + coord = AuxCoord(self.pts_real, bounds=self.bds_lazy) + result = coord.lazy_bounds() + self.assertIs(result, self.bds_lazy) + + +class Test_has_lazy_points(tests.IrisTest, AuxCoordTestMixin): + def setUp(self): + self.setupTestArrays() + + def test_real_core(self): + coord = AuxCoord(self.pts_real) + result = coord.has_lazy_points() + self.assertFalse(result) + + def test_lazy_core(self): + coord = AuxCoord(self.pts_lazy) + result = coord.has_lazy_points() + self.assertTrue(result) + + def test_lazy_core_realise(self): + coord = AuxCoord(self.pts_lazy) + coord.points + result = coord.has_lazy_points() + self.assertFalse(result) + + +class Test_has_lazy_bounds(tests.IrisTest, AuxCoordTestMixin): + def setUp(self): + self.setupTestArrays() + + def test_real_core(self): + coord = AuxCoord(self.pts_real, bounds=self.bds_real) + result = coord.has_lazy_bounds() + self.assertFalse(result) + + def test_lazy_core(self): + coord = AuxCoord(self.pts_real, bounds=self.bds_lazy) + result = coord.has_lazy_bounds() + self.assertTrue(result) + + def test_lazy_core_realise(self): + coord = AuxCoord(self.pts_real, bounds=self.bds_lazy) + coord.bounds + result = coord.has_lazy_bounds() + self.assertFalse(result) + + +class Test_bounds_dtype(tests.IrisTest, AuxCoordTestMixin): + def test_i16(self): + test_dtype = np.int16 + coord = AuxCoord([1], bounds=np.array([[0, 4]], dtype=test_dtype)) + result = coord.bounds_dtype + self.assertEqual(result, test_dtype) + + def test_u16(self): + test_dtype = np.uint16 + coord = AuxCoord([1], bounds=np.array([[0, 4]], dtype=test_dtype)) + result = coord.bounds_dtype + self.assertEqual(result, test_dtype) + + def test_f16(self): + test_dtype = np.float16 + coord = AuxCoord([1], bounds=np.array([[0, 4]], dtype=test_dtype)) + result = coord.bounds_dtype + self.assertEqual(result, test_dtype) + + +class Test__getitem__(tests.IrisTest, AuxCoordTestMixin): + # Test for AuxCoord indexing with various types of points and bounds. + def setUp(self): + self.setupTestArrays() + + def test_partial_slice_data_copy(self): + parent_coord = AuxCoord([1., 2., 3.]) + sub_coord = parent_coord[:1] + values_before_change = sub_coord.points.copy() + parent_coord.points[:] = -999.9 + self.assertArrayEqual(sub_coord.points, values_before_change) + + def test_full_slice_data_copy(self): + parent_coord = AuxCoord([1., 2., 3.]) + sub_coord = parent_coord[:] + values_before_change = sub_coord.points.copy() + parent_coord.points[:] = -999.9 + self.assertArrayEqual(sub_coord.points, values_before_change) + + def test_dtypes(self): + # Index coords with all combinations of real+lazy points+bounds, and + # either an int or floating dtype. + # Check that dtypes remain the same in all cases, taking the dtypes + # directly from the core points and bounds (as we have no masking). + for (main_coord, points_type_name, bounds_type_name) in \ + coords_all_dtypes_and_lazynesses(self, AuxCoord): + + sub_coord = main_coord[:2, 1] + + coord_dtype = main_coord.dtype + msg = ('Indexing main_coord of dtype {} ' + 'with {} points and {} bounds ' + 'changed dtype of {} to {}.') + + sub_points = sub_coord.core_points() + self.assertEqual( + sub_points.dtype, coord_dtype, + msg.format(coord_dtype, + points_type_name, bounds_type_name, + 'points', sub_points.dtype)) + + if bounds_type_name is not 'no': + sub_bounds = sub_coord.core_bounds() + main_bounds_dtype = main_coord.bounds_dtype + self.assertEqual( + sub_bounds.dtype, main_bounds_dtype, + msg.format(main_bounds_dtype, + points_type_name, bounds_type_name, + 'bounds', sub_bounds.dtype)) + + def test_lazyness(self): + # Index coords with all combinations of real+lazy points+bounds, and + # either an int or floating dtype. + # Check that lazy data stays lazy and real stays real, in all cases. + for (main_coord, points_type_name, bounds_type_name) in \ + coords_all_dtypes_and_lazynesses(self, AuxCoord): + + sub_coord = main_coord[:2, 1] + + msg = ('Indexing coord of dtype {} ' + 'with {} points and {} bounds ' + 'changed laziness of {} from {!r} to {!r}.') + coord_dtype = main_coord.dtype + sub_points_lazyness = lazyness_string(sub_coord.core_points()) + self.assertEqual( + sub_points_lazyness, points_type_name, + msg.format(coord_dtype, + points_type_name, bounds_type_name, + 'points', points_type_name, sub_points_lazyness)) + + if bounds_type_name is not 'no': + sub_bounds_lazy = lazyness_string(sub_coord.core_bounds()) + self.assertEqual( + sub_bounds_lazy, bounds_type_name, + msg.format(coord_dtype, + points_type_name, bounds_type_name, + 'bounds', bounds_type_name, sub_bounds_lazy)) + + def test_real_data_copies(self): + # Index coords with all combinations of real+lazy points+bounds. + # In all cases, check that any real arrays are copied by the indexing. + for (main_coord, points_lazyness, bounds_lazyness) in \ + coords_all_dtypes_and_lazynesses(self, AuxCoord): + + sub_coord = main_coord[:2, 1] + + msg = ('Indexed coord with {} points and {} bounds ' + 'does not have its own separate {} array.') + if points_lazyness == 'real': + main_points = main_coord.core_points() + sub_points = sub_coord.core_points() + sub_main_points = main_points[:2, 1] + self.assertEqualRealArraysAndDtypes(sub_points, + sub_main_points) + self.assertArraysDoNotShareData( + sub_points, sub_main_points, + msg.format(points_lazyness, bounds_lazyness, 'points')) + + if bounds_lazyness == 'real': + main_bounds = main_coord.core_bounds() + sub_bounds = sub_coord.core_bounds() + sub_main_bounds = main_bounds[:2, 1] + self.assertEqualRealArraysAndDtypes(sub_bounds, + sub_main_bounds) + self.assertArraysDoNotShareData( + sub_bounds, sub_main_bounds, + msg.format(points_lazyness, bounds_lazyness, 'bounds')) + + +class Test_copy(tests.IrisTest, AuxCoordTestMixin): + # Test for AuxCoord.copy() with various types of points and bounds. + def setUp(self): + self.setupTestArrays() + + def test_lazyness(self): + # Copy coords with all combinations of real+lazy points+bounds, and + # either an int or floating dtype. + # Check that lazy data stays lazy and real stays real, in all cases. + for (main_coord, points_lazyness, bounds_lazyness) in \ + coords_all_dtypes_and_lazynesses(self, AuxCoord): + + coord_dtype = main_coord.dtype + copied_coord = main_coord.copy() + + msg = ('Copying main_coord of dtype {} ' + 'with {} points and {} bounds ' + 'changed lazyness of {} from {!r} to {!r}.') + + copied_pts_lazyness = lazyness_string(copied_coord.core_points()) + self.assertEqual(copied_pts_lazyness, points_lazyness, + msg.format(coord_dtype, + points_lazyness, bounds_lazyness, + 'points', + points_lazyness, copied_pts_lazyness)) + + if bounds_lazyness != 'no': + copied_bds_lazy = lazyness_string(copied_coord.core_bounds()) + self.assertEqual(copied_bds_lazy, bounds_lazyness, + msg.format(coord_dtype, + points_lazyness, bounds_lazyness, + 'bounds', + bounds_lazyness, copied_bds_lazy)) + + def test_realdata_copies(self): + # Copy coords with all combinations of real+lazy points+bounds. + # In all cases, check that any real arrays are copies, not views. + for (main_coord, points_lazyness, bounds_lazyness) in \ + coords_all_dtypes_and_lazynesses(self, AuxCoord): + + copied_coord = main_coord.copy() + + msg = ('Copied coord with {} points and {} bounds ' + 'does not have its own separate {} array.') + + if points_lazyness == 'real': + main_points = main_coord.core_points() + copied_points = copied_coord.core_points() + self.assertEqualRealArraysAndDtypes(main_points, copied_points) + self.assertArraysDoNotShareData( + main_points, copied_points, + msg.format(points_lazyness, bounds_lazyness, 'points')) + + if bounds_lazyness == 'real': + main_bounds = main_coord.core_bounds() + copied_bounds = copied_coord.core_bounds() + self.assertEqualRealArraysAndDtypes(main_bounds, copied_bounds) + self.assertArraysDoNotShareData( + main_bounds, copied_bounds, + msg.format(points_lazyness, bounds_lazyness, 'bounds')) + + +class Test_points__getter(tests.IrisTest, AuxCoordTestMixin): + def setUp(self): + self.setupTestArrays() + + def test_mutable_real_points(self): + # Check that coord.points returns a modifiable array, and changes to it + # are reflected to the coord. + data = np.array([1.0, 2.0, 3.0, 4.0]) + coord = AuxCoord(data) + initial_values = data.copy() + coord.points[1:2] += 33.1 + result = coord.points + self.assertFalse(np.all(result == initial_values)) + + def test_real_points(self): + # Getting real points does not change or copy them. + coord = AuxCoord(self.pts_real) + result = coord.points + self.assertArraysShareData( + result, self.pts_real, + 'Points do not share data with the provided array.') + + def test_lazy_points(self): + # Getting lazy points realises them. + coord = AuxCoord(self.pts_lazy) + self.assertTrue(coord.has_lazy_points()) + result = coord.points + self.assertFalse(coord.has_lazy_points()) + self.assertEqualRealArraysAndDtypes(result, self.pts_real) + + def test_real_points_with_real_bounds(self): + # Getting real points does not change real bounds. + coord = AuxCoord(self.pts_real, bounds=self.bds_real) + coord.points + result = coord.core_bounds() + self.assertArraysShareData( + result, self.bds_real, + 'Bounds do not share data with the provided array.') + + def test_real_points_with_lazy_bounds(self): + # Getting real points does not touch lazy bounds. + coord = AuxCoord(self.pts_real, bounds=self.bds_lazy) + coord.points + self.assertTrue(coord.has_lazy_bounds()) + + def test_lazy_points_with_real_bounds(self): + # Getting lazy points does not affect real bounds. + coord = AuxCoord(self.pts_lazy, bounds=self.bds_real) + coord.points + result = coord.core_bounds() + self.assertEqualRealArraysAndDtypes(result, self.bds_real) + + def test_lazy_points_with_lazy_bounds(self): + # Getting lazy points does not touch lazy bounds. + coord = AuxCoord(self.pts_lazy, bounds=self.bds_lazy) + coord.points + self.assertTrue(coord.has_lazy_bounds()) + + +class Test_points__setter(tests.IrisTest, AuxCoordTestMixin): + def setUp(self): + self.setupTestArrays() + + def test_real_set_real(self): + # Setting new real points does not make a copy. + coord = AuxCoord(self.pts_real) + new_pts = self.pts_real + 102.3 + coord.points = new_pts + result = coord.core_points() + self.assertArraysShareData( + result, new_pts, + 'Points do not share data with the assigned array.') + + def test_fail_bad_shape(self): + # Setting real points requires matching shape. + coord = AuxCoord([1.0, 2.0]) + msg = 'Require data with shape \(2,\), got \(3,\)' + with self.assertRaisesRegexp(ValueError, msg): + coord.points = np.array([1.0, 2.0, 3.0]) + + def test_real_set_lazy(self): + # Setting new lazy points does not make a copy. + coord = AuxCoord(self.pts_real) + new_pts = self.pts_lazy + 102.3 + coord.points = new_pts + result = coord.core_points() + self.assertEqualLazyArraysAndDtypes(result, new_pts) + + def test_set_points_with_lazy_bounds(self): + # Setting points does not touch lazy bounds. + coord = AuxCoord(self.pts_real, bounds=self.bds_lazy) + new_pts = self.pts_real + 102.3 + coord.points = new_pts + result = coord.core_bounds() + self.assertEqualLazyArraysAndDtypes(result, self.bds_lazy) + + +class Test_bounds__getter(tests.IrisTest, AuxCoordTestMixin): + def setUp(self): + self.setupTestArrays() + + def test_mutable_real_bounds(self): + # Check that coord.bounds returns a modifiable array, and changes to it + # are reflected to the coord. + pts_data = np.array([1.5, 2.5]) + bds_data = np.array([[1.4, 1.6], [2.4, 2.6]]) + coord = AuxCoord(pts_data, bounds=bds_data) + initial_values = bds_data.copy() + coord.bounds[1:2] += 33.1 + result = coord.bounds + self.assertFalse(np.all(result == initial_values)) + + def test_real_bounds(self): + # Getting real bounds does not change or copy them. + coord = AuxCoord(self.pts_real, bounds=self.bds_real) + result = coord.bounds + self.assertArraysShareData( + result, self.bds_real, + 'Bounds do not share data with the provided array.') + + def test_lazy_bounds(self): + # Getting lazy bounds realises them. + coord = AuxCoord(self.pts_real, bounds=self.bds_lazy) + self.assertTrue(coord.has_lazy_bounds()) + result = coord.bounds + self.assertFalse(coord.has_lazy_bounds()) + self.assertEqualRealArraysAndDtypes(result, self.bds_real) + + def test_lazy_bounds_with_lazy_points(self): + # Getting lazy bounds does not fetch the points. + coord = AuxCoord(self.pts_lazy, bounds=self.bds_lazy) + coord.bounds + self.assertTrue(coord.has_lazy_points()) + + +class Test_bounds__setter(tests.IrisTest, AuxCoordTestMixin): + def setUp(self): + self.setupTestArrays() + + def test_set_real_bounds(self): + # Setting new real bounds does not make a copy. + coord = AuxCoord(self.pts_real, bounds=self.bds_real) + new_bounds = self.bds_real + 102.3 + coord.bounds = new_bounds + result = coord.core_bounds() + self.assertArraysShareData( + result, new_bounds, + 'Bounds do not share data with the assigned array.') + + def test_fail_bad_shape(self): + # Setting real points requires matching shape. + coord = AuxCoord(self.pts_real, bounds=self.bds_real) + msg = 'must be compatible with points shape' + with self.assertRaisesRegexp(ValueError, msg): + coord.bounds = np.array([1.0, 2.0, 3.0]) + + def test_set_lazy_bounds(self): + # Setting new lazy bounds. + coord = AuxCoord(self.pts_real, bounds=self.bds_real) + new_bounds = self.bds_lazy + 102.3 + coord.bounds = new_bounds + result = coord.core_bounds() + self.assertEqualLazyArraysAndDtypes(result, new_bounds) + + def test_set_bounds_with_lazy_points(self): + # Setting bounds does not change lazy points. + coord = AuxCoord(self.pts_lazy, bounds=self.bds_real) + new_bounds = self.bds_real + 102.3 + coord.bounds = new_bounds + self.assertTrue(coord.has_lazy_points()) + + +class Test_convert_units(tests.IrisTest): + def test_preserves_lazy(self): + test_bounds = np.array([[[11.0, 12.0], [12.0, 13.0], [13.0, 14.0]], + [[21.0, 22.0], [22.0, 23.0], [23.0, 24.0]]]) + test_points = np.array([[11.1, 12.2, 13.3], + [21.4, 22.5, 23.6]]) + lazy_points = as_lazy_data(test_points) + lazy_bounds = as_lazy_data(test_bounds) + coord = AuxCoord(points=lazy_points, bounds=lazy_bounds, + units='m') + coord.convert_units('ft') + self.assertTrue(coord.has_lazy_points()) + self.assertTrue(coord.has_lazy_bounds()) + test_points_ft = Unit('m').convert(test_points, 'ft') + test_bounds_ft = Unit('m').convert(test_bounds, 'ft') + self.assertArrayAllClose(coord.points, test_points_ft) + self.assertArrayAllClose(coord.bounds, test_bounds_ft) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/coords/test_Cell.py b/lib/iris/tests/unit/coords/test_Cell.py index 28c781577c..452fe12043 100644 --- a/lib/iris/tests/unit/coords/test_Cell.py +++ b/lib/iris/tests/unit/coords/test_Cell.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office +# (C) British Crown Copyright 2013 - 2018, Met Office # # This file is part of Iris. # @@ -16,33 +16,90 @@ # along with Iris. If not, see . """Unit tests for the :class:`iris.coords.Cell` class.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests import datetime +import numpy as np -import mock +import cftime from iris.coords import Cell +from iris.tests import mock +from iris.time import PartialDateTime class Test___common_cmp__(tests.IrisTest): - def test_datetime_ordering(self): - # Check that cell comparison works with objects with a "timetuple". + def assert_raises_on_comparison(self, cell, other, exception_type, regexp): + with self.assertRaisesRegexp(exception_type, regexp): + cell < other + with self.assertRaisesRegexp(exception_type, regexp): + cell <= other + with self.assertRaisesRegexp(exception_type, regexp): + cell > other + with self.assertRaisesRegexp(exception_type, regexp): + cell >= other + + def test_cftime_cell(self): + # Check that cell comparison when the cell contains + # cftime.datetime objects raises an exception otherwise + # this will fall back to id comparison producing unreliable + # results. + cell = Cell(cftime.datetime(2010, 3, 21)) dt = mock.Mock(timetuple=mock.Mock()) - cell = Cell(datetime.datetime(2010, 3, 21)) - with mock.patch('operator.gt') as gt: - _ = cell > dt - gt.assert_called_once_with(cell.point, dt) - - # Now check that the existence of timetuple is causing that. - del dt.timetuple - with self.assertRaisesRegexp(ValueError, - 'Unexpected type of other <(.*)>'): - _ = cell > dt - - def test_datetime_equality(self): + self.assert_raises_on_comparison(cell, dt, TypeError, + 'determine the order of cftime') + self.assert_raises_on_comparison(cell, 23, TypeError, + 'determine the order of cftime') + self.assert_raises_on_comparison(cell, 'hello', TypeError, + 'Unexpected type.*str') + + def test_cftime_other(self): + # Check that cell comparison to a cftime.datetime object + # raises an exception otherwise this will fall back to id comparison + # producing unreliable results. + dt = cftime.datetime(2010, 3, 21) + cell = Cell(mock.Mock(timetuple=mock.Mock())) + self.assert_raises_on_comparison(cell, dt, TypeError, + 'determine the order of cftime') + + def test_PartialDateTime_bounded_cell(self): + # Check that bounded comparisions to a PartialDateTime + # raise an exception. These are not supported as they + # depend on the calendar. + dt = PartialDateTime(month=6) + cell = Cell(datetime.datetime(2010, 1, 1), + bound=[datetime.datetime(2010, 1, 1), + datetime.datetime(2011, 1, 1)]) + self.assert_raises_on_comparison(cell, dt, TypeError, + 'bounded region for datetime') + + def test_PartialDateTime_unbounded_cell(self): + # Check that cell comparison works with PartialDateTimes. + dt = PartialDateTime(month=6) + cell = Cell(cftime.datetime(2010, 3, 1)) + self.assertLess(cell, dt) + self.assertGreater(dt, cell) + self.assertLessEqual(cell, dt) + self.assertGreaterEqual(dt, cell) + + def test_datetime_unbounded_cell(self): + # Check that cell comparison works with datetimes. + dt = datetime.datetime(2000, 6, 15) + cell = Cell(datetime.datetime(2000, 1, 1)) + # Note the absence of the inverse of these + # e.g. self.assertGreater(dt, cell). + # See http://bugs.python.org/issue8005 + self.assertLess(cell, dt) + self.assertLessEqual(cell, dt) + + +class Test___eq__(tests.IrisTest): + def test_datetimelike(self): # Check that cell equality works with objects with a "timetuple". dt = mock.Mock(timetuple=mock.Mock()) cell = mock.MagicMock(spec=Cell, point=datetime.datetime(2010, 3, 21), @@ -50,6 +107,75 @@ def test_datetime_equality(self): _ = cell == dt cell.__eq__.assert_called_once_with(dt) + def test_datetimelike_bounded_cell(self): + # Check that equality with a datetime-like bounded cell + # raises an error. This is not supported as it + # depends on the calendar which is not always known from + # the datetime-like bound objects. + other = mock.Mock(timetuple=mock.Mock()) + cell = Cell(point=object(), + bound=[mock.Mock(timetuple=mock.Mock()), + mock.Mock(timetuple=mock.Mock())]) + with self.assertRaisesRegexp(TypeError, 'bounded region for datetime'): + cell == other + + def test_PartialDateTime_other(self): + cell = Cell(datetime.datetime(2010, 3, 2)) + # A few simple cases. + self.assertEqual(cell, PartialDateTime(month=3)) + self.assertNotEqual(cell, PartialDateTime(month=3, hour=12)) + self.assertNotEqual(cell, PartialDateTime(month=4)) + + +class Test_contains_point(tests.IrisTest): + def test_datetimelike_bounded_cell(self): + point = object() + cell = Cell(point=object(), + bound=[mock.Mock(timetuple=mock.Mock()), + mock.Mock(timetuple=mock.Mock())]) + with self.assertRaisesRegexp(TypeError, 'bounded region for datetime'): + cell.contains_point(point) + + def test_datetimelike_point(self): + point = mock.Mock(timetuple=mock.Mock()) + cell = Cell(point=object(), bound=[object(), object()]) + with self.assertRaisesRegexp(TypeError, 'bounded region for datetime'): + cell.contains_point(point) + + +class Test_numpy_comparison(tests.IrisTest): + """ + Unit tests to check that the results of comparisons with numpy types can be + used as truth values.""" + def test_cell_lhs(self): + cell = Cell(point=1.5) + n = np.float64(1.2) + + try: + bool(cell < n) + bool(cell <= n) + bool(cell > n) + bool(cell >= n) + bool(cell == n) + bool(cell != n) + except: + self.fail( + "Result of comparison could not be used as a truth value") + + def test_cell_rhs(self): + cell = Cell(point=1.5) + n = np.float64(1.2) + + try: + bool(n < cell) + bool(n <= cell) + bool(n > cell) + bool(n >= cell) + bool(n == cell) + bool(n != cell) + except: + self.fail( + "Result of comparison could not be used as a truth value") if __name__ == '__main__': tests.main() diff --git a/lib/iris/tests/unit/coords/test_CellMeasure.py b/lib/iris/tests/unit/coords/test_CellMeasure.py new file mode 100644 index 0000000000..109357aabc --- /dev/null +++ b/lib/iris/tests/unit/coords/test_CellMeasure.py @@ -0,0 +1,137 @@ +# (C) British Crown Copyright 2015 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :class:`iris.coords.CellMeasure` class.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.coords import CellMeasure +from iris._lazy_data import as_lazy_data + + +class Tests(tests.IrisTest): + def setUp(self): + self.values = np.array((10., 12., 16., 9.)) + self.measure = CellMeasure(self.values, units='m^2', + standard_name='cell_area', + long_name='measured_area', + var_name='area', + attributes={'notes': '1m accuracy'}, + measure='area') + + def test_invalid_measure(self): + msg = "measure must be 'area' or 'volume', not length" + with self.assertRaisesRegexp(ValueError, msg): + self.measure.measure = 'length' + + def test_set_measure(self): + v = 'volume' + self.measure.measure = v + self.assertEqual(self.measure.measure, v) + + def test_data(self): + self.assertArrayEqual(self.measure.data, self.values) + + def test_set_data(self): + new_vals = np.array((1., 2., 3., 4.)) + self.measure.data = new_vals + self.assertArrayEqual(self.measure.data, new_vals) + + def test_set_data__int(self): + new_vals = np.array((1, 2, 3, 4), dtype=np.int32) + self.measure.data = new_vals + self.assertArrayEqual(self.measure.data, new_vals) + + def test_set_data__uint(self): + new_vals = np.array((1, 2, 3, 4), dtype=np.uint32) + self.measure.data = new_vals + self.assertArrayEqual(self.measure.data, new_vals) + + def test_set_data__lazy(self): + new_vals = as_lazy_data(np.array((1., 2., 3., 4.))) + self.measure.data = new_vals + self.assertArrayEqual(self.measure.data, new_vals) + + def test_set_data__int__lazy(self): + new_vals = as_lazy_data(np.array((1, 2, 3, 4), dtype=np.int32)) + exp_emsg = "Cannot create cell measure with lazy data of type int32" + with self.assertRaisesRegexp(ValueError, exp_emsg): + self.measure.data = new_vals + + def test_set_data__uint__lazy(self): + new_vals = as_lazy_data(np.array((1, 2, 3, 4), dtype=np.uint32)) + exp_emsg = "Cannot create cell measure with lazy data of type uint32" + with self.assertRaisesRegexp(ValueError, exp_emsg): + self.measure.data = new_vals + + def test_data_different_shape(self): + new_vals = np.array((1., 2., 3.)) + msg = 'New data shape must match existing data shape.' + with self.assertRaisesRegexp(ValueError, msg): + self.measure.data = new_vals + + def test_shape(self): + self.assertEqual(self.measure.shape, (4,)) + + def test_ndim(self): + self.assertEqual(self.measure.ndim, 1) + + def test___getitem__(self): + sub_measure = self.measure[2] + self.assertArrayEqual(self.values[2], sub_measure.data) + + def test___getitem__data_copy(self): + # Check that a sliced cell measure has independent data. + sub_measure = self.measure[1:3] + old_values = sub_measure.data.copy() + # Change the original one. + self.measure.data[:] = 0.0 + # Check the new one has not changed. + self.assertArrayEqual(sub_measure.data, old_values) + + def test_copy(self): + new_vals = np.array((7., 8.)) + copy_measure = self.measure.copy(new_vals) + self.assertArrayEqual(copy_measure.data, new_vals) + + def test_repr_other_metadata(self): + expected = (", long_name='measured_area', " + "var_name='area', attributes={'notes': '1m accuracy'}") + self.assertEqual(self.measure._repr_other_metadata(), expected) + + def test__str__(self): + expected = ("CellMeasure(array([10., 12., 16., 9.]), " + "measure=area, standard_name='cell_area', " + "units=Unit('m^2'), long_name='measured_area', " + "var_name='area', attributes={'notes': '1m accuracy'})") + self.assertEqual(self.measure.__str__(), expected) + + def test__repr__(self): + expected = ("CellMeasure(array([10., 12., 16., 9.]), " + "measure=area, standard_name='cell_area', " + "units=Unit('m^2'), long_name='measured_area', " + "var_name='area', attributes={'notes': '1m accuracy'})") + self.assertEqual(self.measure.__repr__(), expected) + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/coords/test_Coord.py b/lib/iris/tests/unit/coords/test_Coord.py index 1ce47f30b0..d42448d609 100644 --- a/lib/iris/tests/unit/coords/test_Coord.py +++ b/lib/iris/tests/unit/coords/test_Coord.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office +# (C) British Crown Copyright 2013 - 2018, Met Office # # This file is part of Iris. # @@ -16,22 +16,198 @@ # along with Iris. If not, see . """Unit tests for the :class:`iris.coords.Coord` class.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import datetime import collections - import mock +import warnings + import numpy as np +import iris from iris.coords import DimCoord, AuxCoord, Coord +from iris.tests import mock +from iris.exceptions import UnitConversionError +from iris.tests.unit.coords import CoordTestMixin Pair = collections.namedtuple('Pair', 'points bounds') +class Test_nearest_neighbour_index__ascending(tests.IrisTest): + def setUp(self): + points = [0., 90., 180., 270.] + self.coord = DimCoord(points, circular=False, + units='degrees') + + def _test_nearest_neighbour_index(self, target, bounds=None, + circular=False): + _bounds = [[-20, 10], [10, 100], [100, 260], [260, 340]] + ext_pnts = [-70, -10, 110, 275, 370] + if bounds is True: + self.coord.bounds = _bounds + else: + self.coord.bounds = bounds + self.coord.circular = circular + results = [self.coord.nearest_neighbour_index(ind) for ind in ext_pnts] + self.assertEqual(results, target) + + def test_nobounds(self): + target = [0, 0, 1, 3, 3] + self._test_nearest_neighbour_index(target) + + def test_nobounds_circular(self): + target = [3, 0, 1, 3, 0] + self._test_nearest_neighbour_index(target, circular=True) + + def test_bounded(self): + target = [0, 0, 2, 3, 3] + self._test_nearest_neighbour_index(target, bounds=True) + + def test_bounded_circular(self): + target = [3, 0, 2, 3, 0] + self._test_nearest_neighbour_index(target, bounds=True, circular=True) + + def test_bounded_overlapping(self): + _bounds = [[-20, 50], [10, 150], [100, 300], [260, 340]] + target = [0, 0, 1, 2, 3] + self._test_nearest_neighbour_index(target, bounds=_bounds) + + def test_bounded_disjointed(self): + _bounds = [[-20, 10], [80, 170], [180, 190], [240, 340]] + target = [0, 0, 1, 3, 3] + self._test_nearest_neighbour_index(target, bounds=_bounds) + + def test_scalar(self): + self.coord = DimCoord([0], circular=False, units='degrees') + target = [0, 0, 0, 0, 0] + self._test_nearest_neighbour_index(target) + + +class Test_nearest_neighbour_index__descending(tests.IrisTest): + def setUp(self): + points = [270., 180., 90., 0.] + self.coord = DimCoord(points, circular=False, + units='degrees') + + def _test_nearest_neighbour_index(self, target, bounds=False, + circular=False): + _bounds = [[340, 260], [260, 100], [100, 10], [10, -20]] + ext_pnts = [-70, -10, 110, 275, 370] + if bounds: + self.coord.bounds = _bounds + self.coord.circular = circular + results = [self.coord.nearest_neighbour_index(ind) for ind in ext_pnts] + self.assertEqual(results, target) + + def test_nobounds(self): + target = [3, 3, 2, 0, 0] + self._test_nearest_neighbour_index(target) + + def test_nobounds_circular(self): + target = [0, 3, 2, 0, 3] + self._test_nearest_neighbour_index(target, circular=True) + + def test_bounded(self): + target = [3, 3, 1, 0, 0] + self._test_nearest_neighbour_index(target, bounds=True) + + def test_bounded_circular(self): + target = [0, 3, 1, 0, 3] + self._test_nearest_neighbour_index(target, bounds=True, circular=True) + + +class Test_guess_bounds(tests.IrisTest): + def setUp(self): + self.coord = DimCoord(np.array([-160, -120, 0, 30, 150, 170]), + units='degree', standard_name='longitude', + circular=True) + + def test_non_circular(self): + self.coord.circular = False + self.coord.guess_bounds() + target = np.array([[-180., -140.], [-140., -60.], [-60., 15.], + [15., 90.], [90., 160.], [160., 180.]]) + self.assertArrayEqual(target, self.coord.bounds) + + def test_circular_increasing(self): + self.coord.guess_bounds() + target = np.array([[-175., -140.], [-140., -60.], [-60., 15.], + [15., 90.], [90., 160.], [160., 185.]]) + self.assertArrayEqual(target, self.coord.bounds) + + def test_circular_decreasing(self): + self.coord.points = self.coord.points[::-1] + self.coord.guess_bounds() + target = np.array([[185., 160.], [160., 90.], [90., 15.], + [15., -60.], [-60., -140.], [-140., -175.]]) + self.assertArrayEqual(target, self.coord.bounds) + + def test_circular_increasing_alt_range(self): + self.coord.points = np.array([10, 30, 90, 150, 210, 220]) + self.coord.guess_bounds() + target = np.array([[-65., 20.], [20., 60.], [60., 120.], + [120., 180.], [180., 215.], [215., 295.]]) + self.assertArrayEqual(target, self.coord.bounds) + + def test_circular_decreasing_alt_range(self): + self.coord.points = np.array([10, 30, 90, 150, 210, 220])[::-1] + self.coord.guess_bounds() + target = np.array([[295, 215], [215, 180], [180, 120], [120, 60], + [60, 20], [20, -65]]) + self.assertArrayEqual(target, self.coord.bounds) + + +class Test_guess_bounds__default_enabled_latitude_clipping(tests.IrisTest): + def test_all_inside(self): + lat = DimCoord([-10, 0, 20], units='degree', standard_name='latitude') + lat.guess_bounds() + self.assertArrayEqual(lat.bounds, [[-15, -5], [-5, 10], [10, 30]]) + + def test_points_inside_bounds_outside(self): + lat = DimCoord([-80, 0, 70], units='degree', standard_name='latitude') + lat.guess_bounds() + self.assertArrayEqual(lat.bounds, [[-90, -40], [-40, 35], [35, 90]]) + + def test_points_inside_bounds_outside_grid_latitude(self): + lat = DimCoord([-80, 0, 70], units='degree', + standard_name='grid_latitude') + lat.guess_bounds() + self.assertArrayEqual(lat.bounds, [[-90, -40], [-40, 35], [35, 90]]) + + def test_points_to_edges_bounds_outside(self): + lat = DimCoord([-90, 0, 90], units='degree', standard_name='latitude') + lat.guess_bounds() + self.assertArrayEqual(lat.bounds, [[-90, -45], [-45, 45], [45, 90]]) + + def test_points_outside(self): + lat = DimCoord([-100, 0, 120], units='degree', + standard_name='latitude') + lat.guess_bounds() + self.assertArrayEqual(lat.bounds, [[-150, -50], [-50, 60], [60, 180]]) + + def test_points_inside_bounds_outside_wrong_unit(self): + lat = DimCoord([-80, 0, 70], units='feet', standard_name='latitude') + lat.guess_bounds() + self.assertArrayEqual(lat.bounds, [[-120, -40], [-40, 35], [35, 105]]) + + def test_points_inside_bounds_outside_wrong_name(self): + lat = DimCoord([-80, 0, 70], units='degree', standard_name='longitude') + lat.guess_bounds() + self.assertArrayEqual(lat.bounds, [[-120, -40], [-40, 35], [35, 105]]) + + def test_points_inside_bounds_outside_wrong_name_2(self): + lat = DimCoord([-80, 0, 70], units='degree', + long_name='other_latitude') + lat.guess_bounds() + self.assertArrayEqual(lat.bounds, [[-120, -40], [-40, 35], [35, 105]]) + + class Test_cell(tests.IrisTest): def _mock_coord(self): coord = mock.Mock(spec=Coord, ndim=1, @@ -40,37 +216,26 @@ def _mock_coord(self): mock.sentinel.upper]])) return coord - def test_time_as_number(self): - # Make sure Coord.cell() normally returns the values straight - # out of the Coord's points/bounds arrays. - coord = self._mock_coord() - cell = Coord.cell(coord, 0) - self.assertIs(cell.point, mock.sentinel.time) - self.assertEquals(cell.bound, - (mock.sentinel.lower, mock.sentinel.upper)) - def test_time_as_object(self): - # When iris.FUTURE.cell_datetime_objects is True, ensure - # Coord.cell() converts the point/bound values to "datetime" - # objects. + # Ensure Coord.cell() converts the point/bound values to + # "datetime" objects. coord = self._mock_coord() coord.units.num2date = mock.Mock( side_effect=[mock.sentinel.datetime, (mock.sentinel.datetime_lower, mock.sentinel.datetime_upper)]) - with mock.patch('iris.FUTURE', cell_datetime_objects=True): - cell = Coord.cell(coord, 0) + cell = Coord.cell(coord, 0) self.assertIs(cell.point, mock.sentinel.datetime) - self.assertEquals(cell.bound, - (mock.sentinel.datetime_lower, - mock.sentinel.datetime_upper)) + self.assertEqual(cell.bound, + (mock.sentinel.datetime_lower, + mock.sentinel.datetime_upper)) self.assertEqual(coord.units.num2date.call_args_list, [mock.call((mock.sentinel.time,)), mock.call((mock.sentinel.lower, mock.sentinel.upper))]) -class Test_collapsed(tests.IrisTest): +class Test_collapsed(tests.IrisTest, CoordTestMixin): def test_serialize(self): # Collapse a string AuxCoord, causing it to be serialised. @@ -79,6 +244,8 @@ def test_serialize(self): ['three', 'five'], ['five', 'seven'], ['seven', 'nine']])) + string_nobounds = Pair(np.array(['ecks', 'why', 'zed']), + None) string_multi = Pair(np.array(['three', 'six', 'nine']), np.array([['one', 'two', 'four', 'five'], ['four', 'five', 'seven', 'eight'], @@ -88,15 +255,17 @@ def _serialize(data): return '|'.join(str(item) for item in data.flatten()) for units in ['unknown', 'no_unit']: - for points, bounds in [string, string_multi]: + for points, bounds in [string, string_nobounds, string_multi]: coord = AuxCoord(points=points, bounds=bounds, units=units) collapsed_coord = coord.collapsed() self.assertArrayEqual(collapsed_coord.points, _serialize(points)) - for index in np.ndindex(bounds.shape[1:]): - index_slice = (slice(None),) + tuple(index) - self.assertArrayEqual(collapsed_coord.bounds[index_slice], - _serialize(bounds[index_slice])) + if bounds is not None: + for index in np.ndindex(bounds.shape[1:]): + index_slice = (slice(None),) + tuple(index) + self.assertArrayEqual( + collapsed_coord.bounds[index_slice], + _serialize(bounds[index_slice])) def test_dim_1d(self): # Numeric coords should not be serialised. @@ -111,13 +280,58 @@ def test_dim_1d(self): [[coord.bounds.min(), coord.bounds.max()]]) def test_numeric_nd(self): - # Contiguous only defined for 2d bounds. - coord = AuxCoord(points=np.array([3, 6, 9]), - bounds=np.array([[1, 2, 4, 5], + coord = AuxCoord(points=np.array([[1, 2, 4, 5], [4, 5, 7, 8], [7, 8, 10, 11]])) - with self.assertRaises(ValueError): - collapsed_coord = coord.collapsed() + + collapsed_coord = coord.collapsed() + self.assertArrayEqual(collapsed_coord.points, np.array([6])) + self.assertArrayEqual(collapsed_coord.bounds, np.array([[1, 11]])) + + # Test partially collapsing one dimension... + collapsed_coord = coord.collapsed(1) + self.assertArrayEqual(collapsed_coord.points, np.array([3., 6., 9.])) + self.assertArrayEqual(collapsed_coord.bounds, np.array([[1, 5], + [4, 8], + [7, 11]])) + + # ... and the other + collapsed_coord = coord.collapsed(0) + self.assertArrayEqual(collapsed_coord.points, np.array([4, 5, 7, 8])) + self.assertArrayEqual(collapsed_coord.bounds, np.array([[1, 7], + [2, 8], + [4, 10], + [5, 11]])) + + def test_lazy_nd_bounds(self): + import dask.array as da + + self.setupTestArrays((3, 4)) + coord = AuxCoord(self.pts_real, bounds=self.bds_lazy) + + collapsed_coord = coord.collapsed() + + # Note that the new points get recalculated from the lazy bounds + # and so end up as lazy + self.assertTrue(collapsed_coord.has_lazy_points()) + self.assertTrue(collapsed_coord.has_lazy_bounds()) + + self.assertArrayEqual(collapsed_coord.points, np.array([55])) + self.assertArrayEqual(collapsed_coord.bounds, da.array([[-2, 112]])) + + def test_lazy_nd_points_and_bounds(self): + import dask.array as da + + self.setupTestArrays((3, 4)) + coord = AuxCoord(self.pts_lazy, bounds=self.bds_lazy) + + collapsed_coord = coord.collapsed() + + self.assertTrue(collapsed_coord.has_lazy_points()) + self.assertTrue(collapsed_coord.has_lazy_bounds()) + + self.assertArrayEqual(collapsed_coord.points, da.array([55])) + self.assertArrayEqual(collapsed_coord.bounds, da.array([[-2, 112]])) class Test_is_compatible(tests.IrisTest): @@ -143,5 +357,361 @@ def test_different_array_attrs_incompatible(self): self.assertFalse(self.test_coord.is_compatible(self.other_coord)) +class Test_contiguous_bounds(tests.IrisTest): + def test_1d_coord_no_bounds_warning(self): + coord = DimCoord([0, 1, 2], standard_name='latitude') + msg = "Coordinate 'latitude' is not bounded, guessing contiguous " \ + "bounds." + with warnings.catch_warnings(): + # Cause all warnings to raise Exceptions + warnings.simplefilter("error") + with self.assertRaisesRegexp(Warning, msg): + coord.contiguous_bounds() + + def test_2d_coord_no_bounds_error(self): + coord = AuxCoord(np.array([[0, 0], [5, 5]]), standard_name='latitude') + emsg = 'Guessing bounds of 2D coords is not currently supported' + with self.assertRaisesRegexp(ValueError, emsg): + coord.contiguous_bounds() + + def test__sanity_check_bounds_call(self): + coord = DimCoord([5, 15, 25], bounds=[[0, 10], [10, 20], [20, 30]]) + with mock.patch('iris.coords.Coord._sanity_check_bounds' + ) as bounds_check: + coord.contiguous_bounds() + bounds_check.assert_called_once() + + def test_1d_coord(self): + coord = DimCoord([2, 4, 6], standard_name='latitude', + bounds=[[1, 3], [3, 5], [5, 7]]) + expected = np.array([1, 3, 5, 7]) + result = coord.contiguous_bounds() + self.assertArrayEqual(result, expected) + + def test_1d_coord_discontiguous(self): + coord = DimCoord([2, 4, 6], standard_name='latitude', + bounds=[[1, 3], [4, 5], [5, 7]]) + expected = np.array([1, 4, 5, 7]) + result = coord.contiguous_bounds() + self.assertArrayEqual(result, expected) + + def test_2d_lon_bounds(self): + coord = AuxCoord(np.array([[1, 3], [1, 3]]), + bounds=np.array([[[0, 2, 2, 0], [2, 4, 4, 2]], + [[0, 2, 2, 0], [2, 4, 4, 2]]])) + expected = np.array([[0, 2, 4], [0, 2, 4], [0, 2, 4]]) + result = coord.contiguous_bounds() + self.assertArrayEqual(result, expected) + + def test_2d_lat_bounds(self): + coord = AuxCoord(np.array([[1, 1], [3, 3]]), + bounds=np.array([[[0, 0, 2, 2], [0, 0, 2, 2]], + [[2, 2, 4, 4], [2, 2, 4, 4]]])) + expected = np.array([[0, 0, 0], [2, 2, 2], [4, 4, 4]]) + result = coord.contiguous_bounds() + self.assertArrayEqual(result, expected) + + +class Test_is_contiguous(tests.IrisTest): + def test_no_bounds(self): + coord = DimCoord([1, 3]) + result = coord.is_contiguous() + self.assertFalse(result) + + def test__discontiguity_in_bounds_call(self): + # Check that :meth:`iris.coords.Coord._discontiguity_in_bounds` is + # called. + coord = DimCoord([1, 3], bounds=[[0, 2], [2, 4]]) + with mock.patch('iris.coords.Coord._discontiguity_in_bounds' + ) as discontiguity_check: + # Discontiguity returns two objects that are unpacked in + # `coord.is_contiguous`. + discontiguity_check.return_value = [None, None] + coord.is_contiguous(rtol=1e-1, atol=1e-3) + discontiguity_check.assert_called_with(rtol=1e-1, atol=1e-3) + + +class Test__discontiguity_in_bounds(tests.IrisTest): + def setUp(self): + self.points_3by3 = np.array([[1, 2, 3], + [1, 2, 3], + [1, 2, 3]]) + self.lon_bounds_3by3 = np.array( + [[[0, 2, 2, 0], [2, 4, 4, 2], [4, 6, 6, 4]], + [[0, 2, 2, 0], [2, 4, 4, 2], [4, 6, 6, 4]], + [[0, 2, 2, 0], [2, 4, 4, 2], [4, 6, 6, 4]]]) + self.lat_bounds_3by3 = np.array( + [[[0, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2]], + [[2, 2, 4, 4], [2, 2, 4, 4], [2, 2, 4, 4]], + [[4, 4, 6, 6], [4, 4, 6, 6], [4, 4, 6, 6]]]) + + def test_1d_contiguous(self): + coord = DimCoord([-20, 0, 20], + bounds=[[-30, -10], [-10, 10], [10, 30]]) + contiguous, diffs = coord._discontiguity_in_bounds() + self.assertTrue(contiguous) + self.assertArrayEqual(diffs, np.zeros(2)) + + def test_1d_discontiguous(self): + coord = DimCoord([10, 20, 40], + bounds=[[5, 15], [15, 25], [35, 45]]) + contiguous, diffs = coord._discontiguity_in_bounds() + self.assertFalse(contiguous) + self.assertArrayEqual(diffs, np.array([0, 10])) + + def test_1d_one_cell(self): + # Test a 1D coord with a single cell. + coord = DimCoord(20, bounds=[[10, 30]]) + contiguous, diffs = coord._discontiguity_in_bounds() + self.assertTrue(contiguous) + self.assertArrayEqual(diffs, np.array([])) + + def test_2d_contiguous_both_dirs(self): + coord = AuxCoord(self.points_3by3, bounds=self.lon_bounds_3by3) + contiguous, diffs = coord._discontiguity_in_bounds() + diffs_along_x, diffs_along_y = diffs + self.assertTrue(contiguous) + self.assertTrue(not diffs_along_x.any()) + self.assertTrue(not diffs_along_y.any()) + + def test_2d_discontiguous_along_x(self): + coord = AuxCoord(self.points_3by3[:, ::2], + bounds=self.lon_bounds_3by3[:, ::2, :]) + contiguous, diffs = coord._discontiguity_in_bounds() + diffs_along_x, diffs_along_y = diffs + self.assertFalse(contiguous) + self.assertArrayEqual(diffs_along_x, + np.array([True, True, True]).reshape(3, 1)) + self.assertTrue(not diffs_along_y.any()) + + def test_2d_discontiguous_along_y(self): + coord = AuxCoord(self.points_3by3[::2, :], + bounds=self.lat_bounds_3by3[::2, :, :]) + contiguous, diffs = coord._discontiguity_in_bounds() + diffs_along_x, diffs_along_y = diffs + self.assertFalse(contiguous) + self.assertTrue(not diffs_along_x.any()) + self.assertArrayEqual(diffs_along_y, np.array([[True, True, True]])) + + def test_2d_discontiguous_along_x_and_y(self): + coord = AuxCoord(np.array([[1, 5], [3, 5]]), + bounds=np.array([[[0, 2, 2, 0], [4, 6, 6, 4]], + [[2, 4, 4, 2], [4, 6, 6, 4]]])) + contiguous, diffs = coord._discontiguity_in_bounds() + diffs_along_x, diffs_along_y = diffs + exp_x_diffs = np.array([True, False]).reshape(2, 1) + exp_y_diffs = np.array([True, False]).reshape(1, 2) + self.assertFalse(contiguous) + self.assertArrayEqual(diffs_along_x, exp_x_diffs) + self.assertArrayEqual(diffs_along_y, exp_y_diffs) + + def test_2d_contiguous_along_x_atol(self): + coord = AuxCoord(self.points_3by3[:, ::2], + bounds=self.lon_bounds_3by3[:, ::2, :]) + # Set a high atol that allows small discontiguities. + contiguous, diffs = coord._discontiguity_in_bounds(atol=5) + diffs_along_x, diffs_along_y = diffs + self.assertTrue(contiguous) + self.assertArrayEqual(diffs_along_x, + np.array([False, False, False]).reshape(3, 1)) + self.assertTrue(not diffs_along_y.any()) + + def test_2d_one_cell(self): + # Test a 2D coord with a single cell, where the coord has shape (1, 1). + coord = AuxCoord(self.points_3by3[:1, :1], + bounds=self.lon_bounds_3by3[:1, :1, :]) + contiguous, diffs = coord._discontiguity_in_bounds() + diffs_along_x, diffs_along_y = diffs + expected_diffs = np.array([], dtype=np.int64) + self.assertTrue(contiguous) + self.assertArrayEqual(diffs_along_x, expected_diffs.reshape(1, 0)) + self.assertArrayEqual(diffs_along_y, expected_diffs.reshape(0, 1)) + + def test_2d_one_cell_along_x(self): + # Test a 2D coord with a single cell along the x axis, where the coord + # has shape (2, 1). + coord = AuxCoord(self.points_3by3[:, :1], + bounds=self.lat_bounds_3by3[:, :1, :]) + contiguous, diffs = coord._discontiguity_in_bounds() + diffs_along_x, diffs_along_y = diffs + self.assertTrue(contiguous) + self.assertTrue(not diffs_along_x.any()) + self.assertArrayEqual(diffs_along_y, np.array([0, 0]).reshape(2, 1)) + + def test_2d_one_cell_along_y(self): + # Test a 2D coord with a single cell along the y axis, where the coord + # has shape (1, 2). + coord = AuxCoord(self.points_3by3[:1, :], + bounds=self.lon_bounds_3by3[:1, :, :]) + contiguous, diffs = coord._discontiguity_in_bounds() + diffs_along_x, diffs_along_y = diffs + self.assertTrue(contiguous) + self.assertTrue(not diffs_along_x.any()) + self.assertTrue(not diffs_along_y.any()) + + def test_2d_contiguous_mod_360(self): + # Test that longitude coordinates are adjusted by the 360 modulus when + # calculating the discontiguities in contiguous bounds. + coord = AuxCoord( + [[175, -175], [175, -175]], standard_name='longitude', + bounds=np.array([[[170, 180, 180, 170], [-180, -170, -170, -180]], + [[170, 180, 180, 170], [-180, -170, -170, -180]]]) + ) + contiguous, diffs = coord._discontiguity_in_bounds() + diffs_along_x, diffs_along_y = diffs + self.assertTrue(contiguous) + self.assertTrue(not diffs_along_x.any()) + self.assertTrue(not diffs_along_y.any()) + + def test_2d_discontiguous_mod_360(self): + # Test that longitude coordinates are adjusted by the 360 modulus when + # calculating the discontiguities in contiguous bounds. + coord = AuxCoord( + [[175, -175], [175, -175]], standard_name='longitude', + bounds=np.array([[[170, 180, 180, 170], [10, 20, 20, 10]], + [[170, 180, 180, 170], [10, 20, 20, 10]]])) + contiguous, diffs = coord._discontiguity_in_bounds() + diffs_along_x, diffs_along_y = diffs + self.assertFalse(contiguous) + self.assertArrayEqual(diffs_along_x, np.array([[True], [True]])) + self.assertTrue(not diffs_along_y.any()) + + def test_2d_contiguous_mod_360_not_longitude(self): + # Test that non-longitude coordinates are not adjusted by the 360 + # modulus when calculating the discontiguities in contiguous bounds. + coord = AuxCoord( + [[-150, 350], [-150, 350]], standard_name='height', + bounds=np.array([[[-400, 100, 100, -400], [100, 600, 600, 100]], + [[-400, 100, 100, -400], [100, 600, 600, 100]]]) + ) + contiguous, diffs = coord._discontiguity_in_bounds() + diffs_along_x, diffs_along_y = diffs + self.assertTrue(contiguous) + self.assertTrue(not diffs_along_x.any()) + self.assertTrue(not diffs_along_y.any()) + + def test_2d_discontiguous_mod_360_not_longitude(self): + # Test that non-longitude coordinates are not adjusted by the 360 + # modulus when calculating the discontiguities in discontiguous bounds. + coord = AuxCoord( + [[-150, 350], [-150, 350]], standard_name='height', + bounds=np.array([[[-400, 100, 100, -400], [200, 600, 600, 200]], + [[-400, 100, 100, -400], [200, 600, 600, 200]]]) + ) + contiguous, diffs = coord._discontiguity_in_bounds() + diffs_along_x, diffs_along_y = diffs + self.assertFalse(contiguous) + self.assertArrayEqual(diffs_along_x, np.array([[True], [True]])) + self.assertTrue(not diffs_along_y.any()) + + +class Test__sanity_check_bounds(tests.IrisTest): + def test_coord_1d_2_bounds(self): + # Check that a 1d coord with 2 bounds does not raise an error. + coord = iris.coords.DimCoord([0, 1], standard_name='latitude', + bounds=[[0, 1], [1, 2]]) + coord._sanity_check_bounds() + + def test_coord_1d_no_bounds(self): + coord = iris.coords.DimCoord([0, 1], standard_name='latitude') + emsg = "Contiguous bounds are only defined for 1D coordinates with " \ + "2 bounds." + with self.assertRaisesRegexp(ValueError, emsg): + coord._sanity_check_bounds() + + def test_coord_1d_1_bounds(self): + coord = iris.coords.DimCoord([0, 1], standard_name='latitude', + bounds=np.array([[0], [1]])) + emsg = "Contiguous bounds are only defined for 1D coordinates with " \ + "2 bounds." + with self.assertRaisesRegexp(ValueError, emsg): + coord._sanity_check_bounds() + + def test_coord_2d_4_bounds(self): + coord = iris.coords.AuxCoord( + [[0, 0], [1, 1]], standard_name='latitude', + bounds=np.array([[[0, 0, 1, 1], [0, 0, 1, 1]], + [[1, 1, 2, 2], [1, 1, 2, 2]]])) + coord._sanity_check_bounds() + + def test_coord_2d_no_bounds(self): + coord = iris.coords.AuxCoord([[0, 0], [1, 1]], + standard_name='latitude') + emsg = "Contiguous bounds are only defined for 2D coordinates with " \ + "4 bounds." + with self.assertRaisesRegexp(ValueError, emsg): + coord._sanity_check_bounds() + + def test_coord_2d_2_bounds(self): + coord = iris.coords.AuxCoord( + [[0, 0], [1, 1]], standard_name='latitude', + bounds=np.array([[[0, 1], [0, 1]], [[1, 2], [1, 2]]])) + emsg = "Contiguous bounds are only defined for 2D coordinates with " \ + "4 bounds." + with self.assertRaisesRegexp(ValueError, emsg): + coord._sanity_check_bounds() + + def test_coord_3d(self): + coord = iris.coords.AuxCoord(np.zeros((2, 2, 2)), + standard_name='height') + emsg = "Contiguous bounds are not defined for coordinates with more " \ + "than 2 dimensions." + with self.assertRaisesRegexp(ValueError, emsg): + coord._sanity_check_bounds() + + +class Test_convert_units(tests.IrisTest): + def test_convert_unknown_units(self): + coord = iris.coords.AuxCoord(1, units='unknown') + emsg = ('Cannot convert from unknown units. ' + 'The "coord.units" attribute may be set directly.') + with self.assertRaisesRegexp(UnitConversionError, emsg): + coord.convert_units('degrees') + + +class Test___str__(tests.IrisTest): + + def test_short_time_interval(self): + coord = DimCoord([5], standard_name='time', + units='days since 1970-01-01') + expected = ("DimCoord([1970-01-06 00:00:00], standard_name='time', " + "calendar='gregorian')") + result = coord.__str__() + self.assertEqual(expected, result) + + def test_short_time_interval__bounded(self): + coord = DimCoord([5, 6], standard_name='time', + units='days since 1970-01-01') + coord.guess_bounds() + expected = ("DimCoord([1970-01-06 00:00:00, 1970-01-07 00:00:00], " + "bounds=[[1970-01-05 12:00:00, 1970-01-06 12:00:00],\n" + " [1970-01-06 12:00:00, 1970-01-07 12:00:00]], " + "standard_name='time', calendar='gregorian')") + result = coord.__str__() + self.assertEqual(expected, result) + + def test_long_time_interval(self): + coord = DimCoord([5], standard_name='time', + units='years since 1970-01-01') + expected = "DimCoord([5], standard_name='time', calendar='gregorian')" + result = coord.__str__() + self.assertEqual(expected, result) + + def test_long_time_interval__bounded(self): + coord = DimCoord([5, 6], standard_name='time', + units='years since 1970-01-01') + coord.guess_bounds() + expected = ("DimCoord([5 6], bounds=[[4.5 5.5]\n [5.5 6.5]], " + "standard_name='time', calendar='gregorian')") + result = coord.__str__() + self.assertEqual(expected, result) + + def test_non_time_unit(self): + coord = DimCoord([1.]) + expected = repr(coord) + result = coord.__str__() + self.assertEqual(expected, result) + + if __name__ == '__main__': tests.main() diff --git a/lib/iris/tests/unit/coords/test_DimCoord.py b/lib/iris/tests/unit/coords/test_DimCoord.py new file mode 100644 index 0000000000..c373a1145c --- /dev/null +++ b/lib/iris/tests/unit/coords/test_DimCoord.py @@ -0,0 +1,486 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the :class:`iris.coords.DimCoord` class. + +Note: a lot of these methods are actually defined by the :class:`Coord` class, +but can only be tested on concrete instances (DimCoord or AuxCoord). + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.tests.unit.coords import (CoordTestMixin, + lazyness_string, + coords_all_dtypes_and_lazynesses) + +from iris.coords import DimCoord + + +class DimCoordTestMixin(CoordTestMixin): + # Define a 1-D default array shape. + def setupTestArrays(self, shape=(3, )): + super(DimCoordTestMixin, self).setupTestArrays(shape) + + +class Test__init__(tests.IrisTest, DimCoordTestMixin): + # Test for DimCoord creation, with various combinations of points and + # bounds = real / lazy / None. + def setUp(self): + self.setupTestArrays() + + def test_lazyness_and_dtype_combinations(self): + for (coord, points_type_name, bounds_type_name) in \ + coords_all_dtypes_and_lazynesses(self, DimCoord): + pts = coord.core_points() + bds = coord.core_bounds() + # Check properties of points. + # Points array should not be identical to the reference one. + self.assertArraysDoNotShareData( + pts, self.pts_real, + 'Points are the same data as the provided array.') + # the original points array was cast to a test dtype. + check_pts = self.pts_real.astype(coord.dtype) + self.assertEqualRealArraysAndDtypes(pts, check_pts) + + # Check properties of bounds. + if bounds_type_name != 'no': + # Bounds array should not be the reference data. + self.assertArraysDoNotShareData( + bds, self.bds_real, + 'Bounds are the same data as the provided array.') + # the original bounds array was cast to a test dtype. + check_bds = self.bds_real.astype(coord.bounds_dtype) + self.assertEqualRealArraysAndDtypes(bds, check_bds) + + def test_fail_bounds_shape_mismatch(self): + bds_shape = list(self.bds_real.shape) + bds_shape[0] += 1 + bds_wrong = np.zeros(bds_shape) + msg = 'The shape of the bounds array should be' + with self.assertRaisesRegexp(ValueError, msg): + DimCoord(self.pts_real, bounds=bds_wrong) + + def test_fail_nonmonotonic(self): + msg = 'must be strictly monotonic' + with self.assertRaisesRegexp(ValueError, msg): + DimCoord([1, 2, 0, 3]) + + +class Test_core_points(tests.IrisTest, DimCoordTestMixin): + # Test for DimCoord.core_points() with various types of points and bounds. + def setUp(self): + self.setupTestArrays() + + def test_real_points(self): + data = self.pts_real + coord = DimCoord(data) + result = coord.core_points() + self.assertArraysDoNotShareData( + result, self.pts_real, + 'core_points() are the same data as the internal array.') + + def test_lazy_points(self): + lazy_data = self.pts_lazy + coord = DimCoord(lazy_data) + result = coord.core_points() + self.assertEqualRealArraysAndDtypes(result, self.pts_real) + + +class Test_core_bounds(tests.IrisTest, DimCoordTestMixin): + # Test for DimCoord.core_bounds() with various types of points and bounds. + def setUp(self): + self.setupTestArrays() + + def test_no_bounds(self): + coord = DimCoord(self.pts_real) + result = coord.core_bounds() + self.assertIsNone(result) + + def test_real_bounds(self): + coord = DimCoord(self.pts_real, bounds=self.bds_real) + result = coord.core_bounds() + self.assertArraysDoNotShareData( + result, self.bds_real, + 'core_bounds() are the same data as the internal array.') + + def test_lazy_bounds(self): + coord = DimCoord(self.pts_real, bounds=self.bds_lazy) + result = coord.core_bounds() + self.assertEqualRealArraysAndDtypes(result, self.bds_real) + + +class Test_lazy_points(tests.IrisTest, DimCoordTestMixin): + def setUp(self): + self.setupTestArrays() + + def test_real_core(self): + coord = DimCoord(self.pts_real) + result = coord.lazy_points() + self.assertEqualLazyArraysAndDtypes(result, self.pts_lazy) + + def test_lazy_core(self): + coord = DimCoord(self.pts_lazy) + result = coord.lazy_points() + self.assertEqualLazyArraysAndDtypes(result, self.pts_lazy) + # NOTE: identity, as in "result is self.pts_lazy" does *NOT* work. + + +class Test_lazy_bounds(tests.IrisTest, DimCoordTestMixin): + def setUp(self): + self.setupTestArrays() + + def test_no_bounds(self): + coord = DimCoord(self.pts_real) + result = coord.lazy_bounds() + self.assertIsNone(result) + + def test_real_core(self): + coord = DimCoord(self.pts_real, bounds=self.bds_real) + result = coord.lazy_bounds() + self.assertEqualLazyArraysAndDtypes(result, self.bds_lazy) + + def test_lazy_core(self): + coord = DimCoord(self.pts_real, bounds=self.bds_lazy) + result = coord.lazy_bounds() + self.assertEqualLazyArraysAndDtypes(result, self.bds_lazy) + # NOTE: identity, as in "result is self.bds_lazy" does *NOT* work. + + +class Test_has_lazy_points(tests.IrisTest, DimCoordTestMixin): + def setUp(self): + self.setupTestArrays() + + def test_real_core(self): + coord = DimCoord(self.pts_real) + result = coord.has_lazy_points() + self.assertFalse(result) + + def test_lazy_core(self): + coord = DimCoord(self.pts_lazy) + result = coord.has_lazy_points() + self.assertFalse(result) + + +class Test_has_lazy_bounds(tests.IrisTest, DimCoordTestMixin): + def setUp(self): + self.setupTestArrays() + + def test_real_core(self): + coord = DimCoord(self.pts_real, bounds=self.bds_real) + result = coord.has_lazy_bounds() + self.assertFalse(result) + + def test_lazy_core(self): + coord = DimCoord(self.pts_real, bounds=self.bds_lazy) + result = coord.has_lazy_bounds() + self.assertFalse(result) + + +class Test_bounds_dtype(tests.IrisTest): + def test_i16(self): + test_dtype = np.int16 + coord = DimCoord([1], bounds=np.array([[0, 4]], dtype=test_dtype)) + result = coord.bounds_dtype + self.assertEqual(result, test_dtype) + + def test_u16(self): + test_dtype = np.uint16 + coord = DimCoord([1], bounds=np.array([[0, 4]], dtype=test_dtype)) + result = coord.bounds_dtype + self.assertEqual(result, test_dtype) + + def test_f16(self): + test_dtype = np.float16 + coord = DimCoord([1], bounds=np.array([[0, 4]], dtype=test_dtype)) + result = coord.bounds_dtype + self.assertEqual(result, test_dtype) + + +class Test__getitem__(tests.IrisTest, DimCoordTestMixin): + # Test for DimCoord indexing with various types of points and bounds. + def setUp(self): + self.setupTestArrays() + + def test_dtypes(self): + # Index coords with all combinations of real+lazy points+bounds, and + # either an int or floating dtype. + # Check that dtypes remain the same in all cases, taking the dtypes + # directly from the core points and bounds (as we have no masking). + for (main_coord, points_type_name, bounds_type_name) in \ + coords_all_dtypes_and_lazynesses(self, DimCoord): + + sub_coord = main_coord[:2] + + coord_dtype = main_coord.dtype + msg = ('Indexing main_coord of dtype {} ' + 'with {} points and {} bounds ' + 'changed dtype of {} to {}.') + + sub_points = sub_coord.core_points() + self.assertEqual( + sub_points.dtype, coord_dtype, + msg.format(coord_dtype, + points_type_name, bounds_type_name, + 'points', sub_points.dtype)) + + if bounds_type_name is not 'no': + sub_bounds = sub_coord.core_bounds() + main_bounds_dtype = main_coord.bounds_dtype + self.assertEqual( + sub_bounds.dtype, main_bounds_dtype, + msg.format(main_bounds_dtype, + points_type_name, bounds_type_name, + 'bounds', sub_bounds.dtype)) + + def test_lazyness(self): + # Index coords with all combinations of real+lazy points+bounds, and + # either an int or floating dtype. + # Check that lazy data stays lazy and real stays real, in all cases. + for (main_coord, points_type_name, bounds_type_name) in \ + coords_all_dtypes_and_lazynesses(self, DimCoord): + # N.B. 'points_type_name' and 'bounds_type_name' in the iteration + # are the original types (lazy/real/none) of the points+bounds, + # but the DimCoord itself only ever has real data. + if points_type_name == 'lazy': + points_type_name = 'real' + if bounds_type_name == 'lazy': + bounds_type_name = 'real' + + sub_coord = main_coord[:2] + + msg = ('Indexing coord of dtype {} ' + 'with {} points and {} bounds ' + 'changed "lazyness" of {} from {!r} to {!r}.') + coord_dtype = main_coord.dtype + sub_points_lazyness = lazyness_string(sub_coord.core_points()) + self.assertEqual( + sub_points_lazyness, points_type_name, + msg.format(coord_dtype, + points_type_name, bounds_type_name, + 'points', points_type_name, sub_points_lazyness)) + + if bounds_type_name is not 'no': + sub_bounds_lazy = lazyness_string(sub_coord.core_bounds()) + self.assertEqual( + sub_bounds_lazy, bounds_type_name, + msg.format(coord_dtype, + points_type_name, bounds_type_name, + 'bounds', bounds_type_name, sub_bounds_lazy)) + + def test_real_data_copies(self): + # Index coords with all combinations of real+lazy points+bounds. + # In all cases, check that any real arrays are copied by the indexing. + for (main_coord, points_lazyness, bounds_lazyness) in \ + coords_all_dtypes_and_lazynesses(self, DimCoord): + + sub_coord = main_coord[:2] + + msg = ('Indexed coord with {} points and {} bounds ' + 'does not have its own separate {} array.') + if points_lazyness == 'real': + main_points = main_coord.core_points() + sub_points = sub_coord.core_points() + sub_main_points = main_points[:2] + self.assertEqualRealArraysAndDtypes(sub_points, + sub_main_points) + self.assertArraysDoNotShareData( + sub_points, sub_main_points, + msg.format(points_lazyness, bounds_lazyness, 'points')) + + if bounds_lazyness == 'real': + main_bounds = main_coord.core_bounds() + sub_bounds = sub_coord.core_bounds() + sub_main_bounds = main_bounds[:2] + self.assertEqualRealArraysAndDtypes(sub_bounds, + sub_main_bounds) + self.assertArraysDoNotShareData( + sub_bounds, sub_main_bounds, + msg.format(points_lazyness, bounds_lazyness, 'bounds')) + + +class Test_copy(tests.IrisTest, DimCoordTestMixin): + # Test for DimCoord.copy() with various types of points and bounds. + def setUp(self): + self.setupTestArrays() + + def test_writable_points(self): + coord1 = DimCoord(np.arange(5), + bounds=[[0, 1], [1, 2], [2, 3], [3, 4], [4, 5]]) + coord2 = coord1.copy() + msg = 'destination is read-only' + + with self.assertRaisesRegexp(ValueError, msg): + coord1.points[:] = 0 + + with self.assertRaisesRegexp(ValueError, msg): + coord2.points[:] = 0 + + with self.assertRaisesRegexp(ValueError, msg): + coord1.bounds[:] = 0 + + with self.assertRaisesRegexp(ValueError, msg): + coord2.bounds[:] = 0 + + def test_realdata_readonly(self): + # Copy coords with all combinations of real+lazy points+bounds. + # In all cases, check that data arrays are read-only. + for (main_coord, points_type_name, bounds_type_name) in \ + coords_all_dtypes_and_lazynesses(self, DimCoord): + + copied_coord = main_coord.copy() + + copied_points = copied_coord.core_points() + expected_error_msg = 'output array is read-only' + with self.assertRaisesRegexp(ValueError, expected_error_msg): + copied_points[:1] += 33 + + if bounds_type_name != 'no': + copied_bounds = copied_coord.core_bounds() + with self.assertRaisesRegexp(ValueError, expected_error_msg): + copied_bounds[:1] += 33 + + +class Test_points__getter(tests.IrisTest, DimCoordTestMixin): + def setUp(self): + self.setupTestArrays() + + def test_real_points(self): + # Getting real points returns a copy + coord = DimCoord(self.pts_real) + result = coord.core_points() + self.assertArraysDoNotShareData( + result, self.pts_real, + 'Points are the same array as the provided data.') + + +class Test_points__setter(tests.IrisTest, DimCoordTestMixin): + def setUp(self): + self.setupTestArrays() + + def test_set_real(self): + # Setting points copies the data + coord = DimCoord(self.pts_real) + new_pts = self.pts_real + 102.3 + coord.points = new_pts + result = coord.core_points() + self.assertArraysDoNotShareData( + result, new_pts, + 'Points are the same data as the assigned array.') + + def test_fail_bad_shape(self): + # Setting real points requires matching shape. + points = [1.0, 2.0] + coord = DimCoord(points) + msg = 'Require data with shape \(2,\), got \(3,\)' + with self.assertRaisesRegexp(ValueError, msg): + coord.points = np.array([1.0, 2.0, 3.0]) + self.assertArrayEqual(coord.points, points) + + def test_fail_not_monotonic(self): + # Setting real points requires that they are monotonic. + coord = DimCoord(self.pts_real, bounds=self.bds_real) + msg = 'strictly monotonic' + with self.assertRaisesRegexp(ValueError, msg): + coord.points = np.array([3.0, 1.0, 2.0]) + self.assertArrayEqual(coord.points, self.pts_real) + + def test_set_lazy(self): + # Setting new lazy points realises them. + coord = DimCoord(self.pts_real) + new_pts = self.pts_lazy + 102.3 + coord.points = new_pts + result = coord.core_points() + self.assertEqualRealArraysAndDtypes(result, new_pts.compute()) + + def test_copy_array(self): + # Assigning points creates a copy + pts = np.array([1, 2, 3]) + coord = DimCoord(pts) + pts[1] = 5 + self.assertEqual(coord.points[1], 2) + + +class Test_bounds__getter(tests.IrisTest, DimCoordTestMixin): + def setUp(self): + self.setupTestArrays() + + def test_real_bounds(self): + # Getting real bounds does not change or copy them. + coord = DimCoord(self.pts_real, bounds=self.bds_real) + result = coord.bounds + self.assertArraysDoNotShareData( + result, self.bds_real, + 'Bounds are the same array as the provided data.') + + +class Test_bounds__setter(tests.IrisTest, DimCoordTestMixin): + def setUp(self): + self.setupTestArrays() + + def test_set_real(self): + # Setting bounds does not copy, but makes a readonly view. + coord = DimCoord(self.pts_real, bounds=self.bds_real) + new_bounds = self.bds_real + 102.3 + coord.bounds = new_bounds + result = coord.core_bounds() + self.assertArraysDoNotShareData( + result, new_bounds, + 'Bounds are the same data as the assigned array.') + + def test_fail_bad_shape(self): + # Setting real points requires matching shape. + coord = DimCoord(self.pts_real, bounds=self.bds_real) + msg = 'The shape of the bounds array should be' + with self.assertRaisesRegexp(ValueError, msg): + coord.bounds = np.array([1.0, 2.0, 3.0]) + self.assertArrayEqual(coord.bounds, self.bds_real) + + def test_fail_not_monotonic(self): + # Setting real bounds requires that they are monotonic. + coord = DimCoord(self.pts_real, bounds=self.bds_real) + msg = 'strictly monotonic' + with self.assertRaisesRegexp(ValueError, msg): + coord.bounds = np.array([[3.0, 2.0], [1.0, 0.0], [2.0, 1.0]]) + self.assertArrayEqual(coord.bounds, self.bds_real) + + def test_set_lazy(self): + # Setting new lazy bounds realises them. + coord = DimCoord(self.pts_real, bounds=self.bds_lazy) + new_bounds = self.bds_lazy + 102.3 + coord.bounds = new_bounds + result = coord.core_bounds() + self.assertEqualRealArraysAndDtypes(result, new_bounds.compute()) + + def test_copy_array(self): + # Assigning bounds creates a copy + pts = np.array([2, 4, 6]) + bnds = np.array([[1, 3], [3, 5], [5, 7]]) + coord = DimCoord(pts, bounds=bnds) + bnds[1, 1] = 10 + self.assertEqual(coord.bounds[1, 1], 5) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/cube/__init__.py b/lib/iris/tests/unit/cube/__init__.py index 2ac2d0ee09..3b49e3f75d 100644 --- a/lib/iris/tests/unit/cube/__init__.py +++ b/lib/iris/tests/unit/cube/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Unit tests for the :mod:`iris.cube` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/cube/test_Cube.py b/lib/iris/tests/unit/cube/test_Cube.py index bef0f144c0..dcc3eca7cb 100644 --- a/lib/iris/tests/unit/cube/test_Cube.py +++ b/lib/iris/tests/unit/cube/test_Cube.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office +# (C) British Crown Copyright 2013 - 2018, Met Office # # This file is part of Iris. # @@ -16,21 +16,34 @@ # along with Iris. If not, see . """Unit tests for the `iris.cube.Cube` class.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import biggus -import mock +from itertools import permutations + import numpy as np +import numpy.ma as ma -from iris import FUTURE +from cf_units import Unit + +import iris.analysis +import iris.aux_factory +import iris.coords +import iris.exceptions from iris.analysis import WeightedAggregator, Aggregator -from iris.analysis import MEAN, MIN +from iris.analysis import MEAN +from iris.aux_factory import HybridHeightFactory from iris.cube import Cube -from iris.coords import AuxCoord, DimCoord -from iris.exceptions import CoordinateNotFoundError, CoordinateCollapseError -from iris.exceptions import LazyAggregatorError +from iris.coords import AuxCoord, DimCoord, CellMeasure +from iris.exceptions import (CoordinateNotFoundError, CellMeasureNotFoundError, + UnitConversionError) +from iris._lazy_data import as_lazy_data +from iris.tests import mock +import iris.tests.stock as stock class Test___init___data(tests.IrisTest): @@ -42,10 +55,17 @@ def test_ndarray(self): self.assertArrayEqual(cube.data, data) def test_masked(self): - # np.ma.MaskedArray should be allowed through - data = np.ma.masked_greater(np.arange(12).reshape(3, 4), 1) + # ma.MaskedArray should be allowed through + data = ma.masked_greater(np.arange(12).reshape(3, 4), 1) + cube = Cube(data) + self.assertEqual(type(cube.data), ma.MaskedArray) + self.assertMaskedArrayEqual(cube.data, data) + + def test_masked_no_mask(self): + # ma.MaskedArray should be allowed through even if it has no mask + data = ma.masked_array(np.arange(12).reshape(3, 4), False) cube = Cube(data) - self.assertEqual(type(cube.data), np.ma.MaskedArray) + self.assertEqual(type(cube.data), ma.MaskedArray) self.assertMaskedArrayEqual(cube.data, data) def test_matrix(self): @@ -57,27 +77,205 @@ def test_matrix(self): self.assertArrayEqual(cube.data, data) +class Test_data_dtype_fillvalue(tests.IrisTest): + def _sample_data(self, dtype=('f4'), masked=False, fill_value=None, + lazy=False): + data = np.arange(6).reshape((2, 3)) + dtype = np.dtype(dtype) + data = data.astype(dtype) + if masked: + data = ma.masked_array(data, mask=[[0, 1, 0], [0, 0, 0]], + fill_value=fill_value) + if lazy: + data = as_lazy_data(data) + return data + + def _sample_cube(self, dtype=('f4'), masked=False, fill_value=None, + lazy=False): + data = self._sample_data(dtype=dtype, masked=masked, + fill_value=fill_value, lazy=lazy) + cube = Cube(data) + return cube + + def test_realdata_change(self): + # Check re-assigning real data. + cube = self._sample_cube() + self.assertEqual(cube.dtype, np.float32) + new_dtype = np.dtype('i4') + new_data = self._sample_data(dtype=new_dtype) + cube.data = new_data + self.assertIs(cube.core_data(), new_data) + self.assertEqual(cube.dtype, new_dtype) + + def test_realmaskdata_change(self): + # Check re-assigning real masked data. + cube = self._sample_cube(masked=True, fill_value=1234) + self.assertEqual(cube.dtype, np.float32) + new_dtype = np.dtype('i4') + new_fill_value = 4321 + new_data = self._sample_data(masked=True, + fill_value=new_fill_value, + dtype=new_dtype) + cube.data = new_data + self.assertIs(cube.core_data(), new_data) + self.assertEqual(cube.dtype, new_dtype) + self.assertEqual(cube.data.fill_value, new_fill_value) + + def test_lazydata_change(self): + # Check re-assigning lazy data. + cube = self._sample_cube(lazy=True) + self.assertEqual(cube.core_data().dtype, np.float32) + new_dtype = np.dtype('f8') + new_data = self._sample_data(new_dtype, lazy=True) + cube.data = new_data + self.assertIs(cube.core_data(), new_data) + self.assertEqual(cube.dtype, new_dtype) + + def test_lazymaskdata_change(self): + # Check re-assigning lazy masked data. + cube = self._sample_cube(masked=True, fill_value=1234, + lazy=True) + self.assertEqual(cube.core_data().dtype, np.float32) + new_dtype = np.dtype('f8') + new_fill_value = 4321 + new_data = self._sample_data(dtype=new_dtype, masked=True, + fill_value=new_fill_value, lazy=True) + cube.data = new_data + self.assertIs(cube.core_data(), new_data) + self.assertEqual(cube.dtype, new_dtype) + self.assertEqual(cube.data.fill_value, new_fill_value) + + def test_lazydata_realise(self): + # Check touching lazy data. + cube = self._sample_cube(lazy=True) + data = cube.data + self.assertIs(cube.core_data(), data) + self.assertEqual(cube.dtype, np.float32) + + def test_lazymaskdata_realise(self): + # Check touching masked lazy data. + fill_value = 27.3 + cube = self._sample_cube(masked=True, fill_value=fill_value, lazy=True) + data = cube.data + self.assertIs(cube.core_data(), data) + self.assertEqual(cube.dtype, np.float32) + self.assertEqual(data.fill_value, np.float32(fill_value)) + + def test_realmaskedconstantint_realise(self): + masked_data = ma.masked_array([666], mask=True) + masked_constant = masked_data[0] + cube = Cube(masked_constant) + data = cube.data + self.assertTrue(ma.isMaskedArray(data)) + self.assertNotIsInstance(data, ma.core.MaskedConstant) + + def test_lazymaskedconstantint_realise(self): + dtype = np.dtype('i2') + masked_data = ma.masked_array([666], mask=True, dtype=dtype) + masked_constant = masked_data[0] + masked_constant_lazy = as_lazy_data(masked_constant) + cube = Cube(masked_constant_lazy) + data = cube.data + self.assertTrue(ma.isMaskedArray(data)) + self.assertNotIsInstance(data, ma.core.MaskedConstant) + + def test_lazydata___getitem__dtype(self): + fill_value = 1234 + dtype = np.dtype('int16') + masked_array = ma.masked_array(np.arange(5), + mask=[0, 0, 1, 0, 0], + fill_value=fill_value, + dtype=dtype) + lazy_masked_array = as_lazy_data(masked_array) + cube = Cube(lazy_masked_array) + subcube = cube[3:] + self.assertEqual(subcube.dtype, dtype) + self.assertEqual(subcube.data.fill_value, fill_value) + + +class Test_extract(tests.IrisTest): + def test_scalar_cube_exists(self): + # Ensure that extract is able to extract a scalar cube. + constraint = iris.Constraint(name='a1') + cube = Cube(1, long_name='a1') + res = cube.extract(constraint) + self.assertIs(res, cube) + + def test_scalar_cube_noexists(self): + # Ensure that extract does not return a non-matching scalar cube. + constraint = iris.Constraint(name='a2') + cube = Cube(1, long_name='a1') + res = cube.extract(constraint) + self.assertIs(res, None) + + def test_scalar_cube_coord_match(self): + # Ensure that extract is able to extract a scalar cube according to + # constrained scalar coordinate. + constraint = iris.Constraint(scalar_coord=0) + cube = Cube(1, long_name='a1') + coord = iris.coords.AuxCoord(0, long_name='scalar_coord') + cube.add_aux_coord(coord, None) + res = cube.extract(constraint) + self.assertIs(res, cube) + + def test_scalar_cube_coord_nomatch(self): + # Ensure that extract is not extracting a scalar cube with scalar + # coordinate that does not match the constraint. + constraint = iris.Constraint(scalar_coord=1) + cube = Cube(1, long_name='a1') + coord = iris.coords.AuxCoord(0, long_name='scalar_coord') + cube.add_aux_coord(coord, None) + res = cube.extract(constraint) + self.assertIs(res, None) + + def test_1d_cube_exists(self): + # Ensure that extract is able to extract from a 1d cube. + constraint = iris.Constraint(name='a1') + cube = Cube([1], long_name='a1') + res = cube.extract(constraint) + self.assertIs(res, cube) + + def test_1d_cube_noexists(self): + # Ensure that extract does not return a non-matching 1d cube. + constraint = iris.Constraint(name='a2') + cube = Cube([1], long_name='a1') + res = cube.extract(constraint) + self.assertIs(res, None) + + class Test_xml(tests.IrisTest): def test_checksum_ignores_masked_values(self): # Mask out an single element. - data = np.ma.arange(12).reshape(3, 4) - data[1, 2] = np.ma.masked + data = ma.arange(12).reshape(3, 4) + data[1, 2] = ma.masked cube = Cube(data) self.assertCML(cube) # If we change the underlying value before masking it, the # checksum should be unaffected. - data = np.ma.arange(12).reshape(3, 4) + data = ma.arange(12).reshape(3, 4) data[1, 2] = 42 - data[1, 2] = np.ma.masked + data[1, 2] = ma.masked cube = Cube(data) self.assertCML(cube) + def test_byteorder_default(self): + cube = Cube(np.arange(3)) + self.assertIn('byteorder', cube.xml()) + + def test_byteorder_false(self): + cube = Cube(np.arange(3)) + self.assertNotIn('byteorder', cube.xml(byteorder=False)) + + def test_byteorder_true(self): + cube = Cube(np.arange(3)) + self.assertIn('byteorder', cube.xml(byteorder=True)) + class Test_collapsed__lazy(tests.IrisTest): def setUp(self): self.data = np.arange(6.0).reshape((2, 3)) - self.lazydata = biggus.NumpyArrayAdapter(self.data) + self.lazydata = as_lazy_data(self.data) cube = Cube(self.lazydata) for i_dim, name in enumerate(('y', 'x')): npts = cube.shape[i_dim] @@ -86,31 +284,30 @@ def setUp(self): self.cube = cube def test_dim0_lazy(self): - cube_collapsed = self.cube.collapsed('y', MEAN, lazy=True) + cube_collapsed = self.cube.collapsed('y', MEAN) self.assertTrue(cube_collapsed.has_lazy_data()) self.assertArrayAlmostEqual(cube_collapsed.data, [1.5, 2.5, 3.5]) self.assertFalse(cube_collapsed.has_lazy_data()) - def test_fail_dim1(self): - # Check that MEAN produces a suitable error message for dim != 0. - # N.B. non-lazy op can do this - with self.assertRaises(AssertionError) as err: - cube_collapsed = self.cube.collapsed('x', MEAN, lazy=True) + def test_dim1_lazy(self): + cube_collapsed = self.cube.collapsed('x', MEAN) + self.assertTrue(cube_collapsed.has_lazy_data()) + self.assertArrayAlmostEqual(cube_collapsed.data, [1.0, 4.0]) + self.assertFalse(cube_collapsed.has_lazy_data()) - def test_fail_multidims(self): - # Check that MEAN produces a suitable error message for multiple dims. - # N.B. non-lazy op can do this - with self.assertRaises(AssertionError) as err: - cube_collapsed = self.cube.collapsed(('x', 'y'), MEAN, lazy=True) + def test_multidims(self): + # Check that MEAN works with multiple dims. + cube_collapsed = self.cube.collapsed(('x', 'y'), MEAN) + self.assertTrue(cube_collapsed.has_lazy_data()) + self.assertArrayAllClose(cube_collapsed.data, 2.5) - def test_fail_no_lazy(self): - dummy_agg = Aggregator('custom_op', lambda x: 1) - with self.assertRaises(LazyAggregatorError) as err: - cube_collapsed = self.cube.collapsed('x', dummy_agg, lazy=True) - msg = err.exception.message - self.assertIn('custom_op', msg) - self.assertIn('lazy', msg) - self.assertIn('not support', msg) + def test_non_lazy_aggregator(self): + # An aggregator which doesn't have a lazy function should still work. + dummy_agg = Aggregator('custom_op', + lambda x, axis=None: np.mean(x, axis=axis)) + result = self.cube.collapsed('x', dummy_agg) + self.assertFalse(result.has_lazy_data()) + self.assertArrayEqual(result.data, np.mean(self.data, axis=1)) class Test_collapsed__warning(tests.IrisTest): @@ -131,7 +328,7 @@ def setUp(self): def _aggregator(self, uses_weighting): # Returns a mock aggregator with a mocked method (uses_weighting) # which returns the given True/False condition. - aggregator = mock.Mock(spec=WeightedAggregator) + aggregator = mock.Mock(spec=WeightedAggregator, lazy_func=None) aggregator.cell_method = None aggregator.uses_weighting = mock.Mock(return_value=uses_weighting) @@ -151,7 +348,7 @@ def _assert_nowarn_collapse_without_weight(self, coords, warn): def test_lat_lon_noweighted_aggregator(self): # Collapse latitude coordinate with unweighted aggregator. - aggregator = mock.Mock(spec=Aggregator) + aggregator = mock.Mock(spec=Aggregator, lazy_func=None) aggregator.cell_method = None coords = ['latitude', 'longitude'] @@ -169,7 +366,7 @@ def test_lat_lon_weighted_aggregator(self): with mock.patch('warnings.warn') as warn: self.cube.collapsed(coords, aggregator) - coords = filter(lambda coord: 'latitude' in coord, coords) + coords = [coord for coord in coords if 'latitude' in coord] self._assert_warn_collapse_without_weight(coords, warn) def test_lat_lon_weighted_aggregator_with_weights(self): @@ -193,7 +390,7 @@ def test_lat_lon_weighted_aggregator_alt(self): with mock.patch('warnings.warn') as warn: self.cube.collapsed(coords, aggregator) - coords = filter(lambda coord: 'latitude' in coord, coords) + coords = [coord for coord in coords if 'latitude' in coord] self._assert_warn_collapse_without_weight(coords, warn) def test_no_lat_weighted_aggregator_mixed(self): @@ -210,15 +407,22 @@ def test_no_lat_weighted_aggregator_mixed(self): class Test_summary(tests.IrisTest): + def setUp(self): + self.cube = Cube(0) + def test_cell_datetime_objects(self): # Check the scalar coordinate summary still works even when # iris.FUTURE.cell_datetime_objects is True. - cube = Cube(0) - cube.add_aux_coord(AuxCoord(42, units='hours since epoch')) - with FUTURE.context(cell_datetime_objects=True): - summary = cube.summary() + self.cube.add_aux_coord(AuxCoord(42, units='hours since epoch')) + summary = self.cube.summary() self.assertIn('1970-01-02 18:00:00', summary) + def test_scalar_str_coord(self): + str_value = 'foo' + self.cube.add_aux_coord(AuxCoord(str_value)) + summary = self.cube.summary() + self.assertIn(str_value, summary) + class Test_is_compatible(tests.IrisTest): def setUp(self): @@ -256,8 +460,11 @@ def setUp(self): self.cube.add_aux_coord(val_coord, 0) self.cube.add_aux_coord(label_coord, 0) self.mock_agg = mock.Mock(spec=Aggregator) + self.mock_agg.cell_method = [] self.mock_agg.aggregate = mock.Mock( return_value=mock.Mock(dtype='object')) + self.mock_agg.aggregate_shape = mock.Mock(return_value=()) + self.mock_agg.post_process = mock.Mock(side_effect=lambda x, y, z: x) def test_string_coord_agg_by_label(self): # Aggregate a cube on a string coordinate label where label @@ -286,6 +493,1261 @@ def test_string_coord_agg_by_val(self): self.assertEqual(res_cube.coord('val'), val_coord) self.assertEqual(res_cube.coord('label'), label_coord) + def test_single_string_aggregation(self): + aux_coords = [(AuxCoord(['a', 'b', 'a'], long_name='foo'), 0), + (AuxCoord(['a', 'a', 'a'], long_name='bar'), 0)] + cube = iris.cube.Cube(np.arange(12).reshape(3, 4), + aux_coords_and_dims=aux_coords) + result = cube.aggregated_by('foo', MEAN) + self.assertEqual(result.shape, (2, 4)) + self.assertEqual(result.coord('bar'), + AuxCoord(['a|a', 'a'], long_name='bar')) + + +class Test_rolling_window(tests.IrisTest): + def setUp(self): + self.cube = Cube(np.arange(6)) + val_coord = DimCoord([0, 1, 2, 3, 4, 5], long_name="val") + month_coord = AuxCoord(['jan', 'feb', 'mar', 'apr', 'may', 'jun'], + long_name='month') + self.cube.add_dim_coord(val_coord, 0) + self.cube.add_aux_coord(month_coord, 0) + self.mock_agg = mock.Mock(spec=Aggregator) + self.mock_agg.aggregate = mock.Mock( + return_value=np.empty([4])) + self.mock_agg.post_process = mock.Mock(side_effect=lambda x, y, z: x) + + def test_string_coord(self): + # Rolling window on a cube that contains a string coordinate. + res_cube = self.cube.rolling_window('val', self.mock_agg, 3) + val_coord = DimCoord(np.array([1, 2, 3, 4]), + bounds=np.array([[0, 2], [1, 3], [2, 4], [3, 5]]), + long_name='val') + month_coord = AuxCoord( + np.array(['jan|feb|mar', 'feb|mar|apr', 'mar|apr|may', + 'apr|may|jun']), + bounds=np.array([['jan', 'mar'], ['feb', 'apr'], + ['mar', 'may'], ['apr', 'jun']]), + long_name='month') + self.assertEqual(res_cube.coord('val'), val_coord) + self.assertEqual(res_cube.coord('month'), month_coord) + + def test_kwargs(self): + # Rolling window with missing data not tolerated + window = 2 + self.cube.data = ma.array(self.cube.data, + mask=([True, False, False, + False, True, False])) + res_cube = self.cube.rolling_window('val', iris.analysis.MEAN, + window, mdtol=0) + expected_result = ma.array([-99., 1.5, 2.5, -99., -99.], + mask=[True, False, False, True, True], + dtype=np.float64) + self.assertMaskedArrayEqual(expected_result, res_cube.data) + + +class Test_slices_dim_order(tests.IrisTest): + ''' + This class tests the capability of iris.cube.Cube.slices(), including its + ability to correctly re-order the dimensions. + ''' + def setUp(self): + ''' + setup a 4D iris cube, each dimension is length 1. + The dimensions are; + dim1: time + dim2: height + dim3: latitude + dim4: longitude + ''' + self.cube = iris.cube.Cube(np.array([[[[8.]]]])) + self.cube.add_dim_coord(iris.coords.DimCoord([0], "time"), [0]) + self.cube.add_dim_coord(iris.coords.DimCoord([0], "height"), [1]) + self.cube.add_dim_coord(iris.coords.DimCoord([0], "latitude"), [2]) + self.cube.add_dim_coord(iris.coords.DimCoord([0], "longitude"), [3]) + + @staticmethod + def expected_cube_setup(dim1name, dim2name, dim3name): + ''' + input: + ------ + dim1name: str + name of the first dimension coordinate + dim2name: str + name of the second dimension coordinate + dim3name: str + name of the third dimension coordinate + output: + ------ + cube: iris cube + iris cube with the specified axis holding the data 8 + ''' + cube = iris.cube.Cube(np.array([[[8.]]])) + cube.add_dim_coord(iris.coords.DimCoord([0], dim1name), [0]) + cube.add_dim_coord(iris.coords.DimCoord([0], dim2name), [1]) + cube.add_dim_coord(iris.coords.DimCoord([0], dim3name), [2]) + return cube + + def check_order(self, dim1, dim2, dim3, dim_to_remove): + ''' + does two things: + (1) slices the 4D cube in dim1, dim2, dim3 (and removes the scalar + coordinate) and + (2) sets up a 3D cube with dim1, dim2, dim3. + input: + ----- + dim1: str + name of first dimension + dim2: str + name of second dimension + dim3: str + name of third dimension + dim_to_remove: str + name of the dimension that transforms into a scalar coordinate + when slicing the cube. + output: + ------ + sliced_cube: 3D cube + the cube that results if slicing the original cube + expected_cube: 3D cube + a cube set up with the axis corresponding to the dims + ''' + sliced_cube = next(self.cube.slices([dim1, dim2, dim3])) + sliced_cube.remove_coord(dim_to_remove) + expected_cube = self.expected_cube_setup(dim1, dim2, dim3) + self.assertEqual(sliced_cube, expected_cube) + + def test_all_permutations(self): + for perm in permutations(["time", "height", "latitude", "longitude"]): + self.check_order(*perm) + + +@tests.skip_data +class Test_slices_over(tests.IrisTest): + def setUp(self): + self.cube = stock.realistic_4d() + # Define expected iterators for 1D and 2D test cases. + self.exp_iter_1d = range( + len(self.cube.coord('model_level_number').points)) + self.exp_iter_2d = np.ndindex(6, 70, 1, 1) + # Define maximum number of interations for particularly long + # (and so time-consuming) iterators. + self.long_iterator_max = 5 + + def test_1d_slice_coord_given(self): + res = self.cube.slices_over(self.cube.coord('model_level_number')) + for i, res_cube in zip(self.exp_iter_1d, res): + expected = self.cube[:, i] + self.assertEqual(res_cube, expected) + + def test_1d_slice_nonexistent_coord_given(self): + with self.assertRaises(CoordinateNotFoundError): + res = self.cube.slices_over(self.cube.coord('wibble')) + + def test_1d_slice_coord_name_given(self): + res = self.cube.slices_over('model_level_number') + for i, res_cube in zip(self.exp_iter_1d, res): + expected = self.cube[:, i] + self.assertEqual(res_cube, expected) + + def test_1d_slice_nonexistent_coord_name_given(self): + with self.assertRaises(CoordinateNotFoundError): + res = self.cube.slices_over('wibble') + + def test_1d_slice_dimension_given(self): + res = self.cube.slices_over(1) + for i, res_cube in zip(self.exp_iter_1d, res): + expected = self.cube[:, i] + self.assertEqual(res_cube, expected) + + def test_1d_slice_nonexistent_dimension_given(self): + with self.assertRaisesRegexp(ValueError, 'iterator over a dimension'): + res = self.cube.slices_over(self.cube.ndim + 1) + + def test_2d_slice_coord_given(self): + # Slicing over these two dimensions returns 420 2D cubes, so only check + # cubes up to `self.long_iterator_max` to keep test runtime sensible. + res = self.cube.slices_over([self.cube.coord('time'), + self.cube.coord('model_level_number')]) + for ct in range(self.long_iterator_max): + indices = list(next(self.exp_iter_2d)) + # Replace the dimensions not iterated over with spanning slices. + indices[2] = indices[3] = slice(None) + expected = self.cube[tuple(indices)] + self.assertEqual(next(res), expected) + + def test_2d_slice_nonexistent_coord_given(self): + with self.assertRaises(CoordinateNotFoundError): + res = self.cube.slices_over([self.cube.coord('time'), + self.cube.coord('wibble')]) + + def test_2d_slice_coord_name_given(self): + # Slicing over these two dimensions returns 420 2D cubes, so only check + # cubes up to `self.long_iterator_max` to keep test runtime sensible. + res = self.cube.slices_over(['time', 'model_level_number']) + for ct in range(self.long_iterator_max): + indices = list(next(self.exp_iter_2d)) + # Replace the dimensions not iterated over with spanning slices. + indices[2] = indices[3] = slice(None) + expected = self.cube[tuple(indices)] + self.assertEqual(next(res), expected) + + def test_2d_slice_nonexistent_coord_name_given(self): + with self.assertRaises(CoordinateNotFoundError): + res = self.cube.slices_over(['time', 'wibble']) + + def test_2d_slice_dimension_given(self): + # Slicing over these two dimensions returns 420 2D cubes, so only check + # cubes up to `self.long_iterator_max` to keep test runtime sensible. + res = self.cube.slices_over([0, 1]) + for ct in range(self.long_iterator_max): + indices = list(next(self.exp_iter_2d)) + # Replace the dimensions not iterated over with spanning slices. + indices[2] = indices[3] = slice(None) + expected = self.cube[tuple(indices)] + self.assertEqual(next(res), expected) + + def test_2d_slice_reversed_dimension_given(self): + # Confirm that reversing the order of the dimensions returns the same + # results as the above test. + res = self.cube.slices_over([1, 0]) + for ct in range(self.long_iterator_max): + indices = list(next(self.exp_iter_2d)) + # Replace the dimensions not iterated over with spanning slices. + indices[2] = indices[3] = slice(None) + expected = self.cube[tuple(indices)] + self.assertEqual(next(res), expected) + + def test_2d_slice_nonexistent_dimension_given(self): + with self.assertRaisesRegexp(ValueError, 'iterator over a dimension'): + res = self.cube.slices_over([0, self.cube.ndim + 1]) + + def test_multidim_slice_coord_given(self): + # Slicing over surface altitude returns 100x100 2D cubes, so only check + # cubes up to `self.long_iterator_max` to keep test runtime sensible. + res = self.cube.slices_over('surface_altitude') + # Define special ndindex iterator for the different dims sliced over. + nditer = np.ndindex(1, 1, 100, 100) + for ct in range(self.long_iterator_max): + indices = list(next(nditer)) + # Replace the dimensions not iterated over with spanning slices. + indices[0] = indices[1] = slice(None) + expected = self.cube[tuple(indices)] + self.assertEqual(next(res), expected) + + def test_duplicate_coordinate_given(self): + res = self.cube.slices_over([1, 1]) + for i, res_cube in zip(self.exp_iter_1d, res): + expected = self.cube[:, i] + self.assertEqual(res_cube, expected) + + def test_non_orthogonal_coordinates_given(self): + res = self.cube.slices_over(['model_level_number', 'sigma']) + for i, res_cube in zip(self.exp_iter_1d, res): + expected = self.cube[:, i] + self.assertEqual(res_cube, expected) + + def test_nodimension(self): + # Slicing over no dimension should return the whole cube. + res = self.cube.slices_over([]) + self.assertEqual(next(res), self.cube) + + +def create_cube(lon_min, lon_max, bounds=False): + n_lons = max(lon_min, lon_max) - min(lon_max, lon_min) + data = np.arange(4 * 3 * n_lons, dtype='f4').reshape(4, 3, -1) + data = as_lazy_data(data) + cube = Cube(data, standard_name='x_wind', units='ms-1') + cube.add_dim_coord(iris.coords.DimCoord([0, 20, 40, 80], + long_name='level_height', + units='m'), 0) + cube.add_aux_coord(iris.coords.AuxCoord([1.0, 0.9, 0.8, 0.6], + long_name='sigma'), 0) + cube.add_dim_coord(iris.coords.DimCoord([-45, 0, 45], 'latitude', + units='degrees'), 1) + step = 1 if lon_max > lon_min else -1 + circular = (abs(lon_max - lon_min) == 360) + cube.add_dim_coord(iris.coords.DimCoord(np.arange(lon_min, lon_max, step), + 'longitude', units='degrees', + circular=circular), 2) + if bounds: + cube.coord('longitude').guess_bounds() + cube.add_aux_coord(iris.coords.AuxCoord( + np.arange(3 * n_lons).reshape(3, -1) * 10, 'surface_altitude', + units='m'), [1, 2]) + cube.add_aux_factory(iris.aux_factory.HybridHeightFactory( + cube.coord('level_height'), cube.coord('sigma'), + cube.coord('surface_altitude'))) + return cube + + +# Ensure all the other coordinates and factories are correctly preserved. +class Test_intersection__Metadata(tests.IrisTest): + def test_metadata(self): + cube = create_cube(0, 360) + result = cube.intersection(longitude=(170, 190)) + self.assertCMLApproxData(result) + + def test_metadata_wrapped(self): + cube = create_cube(-180, 180) + result = cube.intersection(longitude=(170, 190)) + self.assertCMLApproxData(result) + + +# Explicitly check the handling of `circular` on the result. +class Test_intersection__Circular(tests.IrisTest): + def test_regional(self): + cube = create_cube(0, 360) + result = cube.intersection(longitude=(170, 190)) + self.assertFalse(result.coord('longitude').circular) + + def test_regional_wrapped(self): + cube = create_cube(-180, 180) + result = cube.intersection(longitude=(170, 190)) + self.assertFalse(result.coord('longitude').circular) + + def test_global(self): + cube = create_cube(-180, 180) + result = cube.intersection(longitude=(-180, 180)) + self.assertTrue(result.coord('longitude').circular) + + def test_global_wrapped(self): + cube = create_cube(-180, 180) + result = cube.intersection(longitude=(10, 370)) + self.assertTrue(result.coord('longitude').circular) + + +# Check the various error conditions. +class Test_intersection__Invalid(tests.IrisTest): + def test_reversed_min_max(self): + cube = create_cube(0, 360) + with self.assertRaises(ValueError): + cube.intersection(longitude=(30, 10)) + + def test_dest_too_large(self): + cube = create_cube(0, 360) + with self.assertRaises(ValueError): + cube.intersection(longitude=(30, 500)) + + def test_src_too_large(self): + cube = create_cube(0, 400) + with self.assertRaises(ValueError): + cube.intersection(longitude=(10, 30)) + + def test_missing_coord(self): + cube = create_cube(0, 360) + with self.assertRaises(iris.exceptions.CoordinateNotFoundError): + cube.intersection(parrots=(10, 30)) + + def test_multi_dim_coord(self): + cube = create_cube(0, 360) + with self.assertRaises(iris.exceptions.CoordinateMultiDimError): + cube.intersection(surface_altitude=(10, 30)) + + def test_null_region(self): + # 10 <= v < 10 + cube = create_cube(0, 360) + with self.assertRaises(IndexError): + cube.intersection(longitude=(10, 10, False, False)) + + +class Test_intersection__Lazy(tests.IrisTest): + def test_real_data(self): + cube = create_cube(0, 360) + cube.data + result = cube.intersection(longitude=(170, 190)) + self.assertFalse(result.has_lazy_data()) + self.assertArrayEqual(result.coord('longitude').points, + np.arange(170, 191)) + self.assertEqual(result.data[0, 0, 0], 170) + self.assertEqual(result.data[0, 0, -1], 190) + + def test_real_data_wrapped(self): + cube = create_cube(-180, 180) + cube.data + result = cube.intersection(longitude=(170, 190)) + self.assertFalse(result.has_lazy_data()) + self.assertArrayEqual(result.coord('longitude').points, + np.arange(170, 191)) + self.assertEqual(result.data[0, 0, 0], 350) + self.assertEqual(result.data[0, 0, -1], 10) + + def test_lazy_data(self): + cube = create_cube(0, 360) + result = cube.intersection(longitude=(170, 190)) + self.assertTrue(result.has_lazy_data()) + self.assertArrayEqual(result.coord('longitude').points, + np.arange(170, 191)) + self.assertEqual(result.data[0, 0, 0], 170) + self.assertEqual(result.data[0, 0, -1], 190) + + def test_lazy_data_wrapped(self): + cube = create_cube(-180, 180) + result = cube.intersection(longitude=(170, 190)) + self.assertTrue(result.has_lazy_data()) + self.assertArrayEqual(result.coord('longitude').points, + np.arange(170, 191)) + self.assertEqual(result.data[0, 0, 0], 350) + self.assertEqual(result.data[0, 0, -1], 10) + + +class Test_intersection_Points(tests.IrisTest): + def test_ignore_bounds(self): + cube = create_cube(0, 30, bounds=True) + result = cube.intersection(longitude=(9.5, 12.5), ignore_bounds=True) + self.assertArrayEqual(result.coord('longitude').points, + np.arange(10, 13)) + self.assertArrayEqual(result.coord('longitude').bounds[0], + [9.5, 10.5]) + self.assertArrayEqual(result.coord('longitude').bounds[-1], + [11.5, 12.5]) + + +# Check what happens with a regional, points-only circular intersection +# coordinate. +class Test_intersection__RegionalSrcModulus(tests.IrisTest): + def test_request_subset(self): + cube = create_cube(40, 60) + result = cube.intersection(longitude=(45, 50)) + self.assertArrayEqual(result.coord('longitude').points, + np.arange(45, 51)) + self.assertArrayEqual(result.data[0, 0], np.arange(5, 11)) + + def test_request_left(self): + cube = create_cube(40, 60) + result = cube.intersection(longitude=(35, 45)) + self.assertArrayEqual(result.coord('longitude').points, + np.arange(40, 46)) + self.assertArrayEqual(result.data[0, 0], np.arange(0, 6)) + + def test_request_right(self): + cube = create_cube(40, 60) + result = cube.intersection(longitude=(55, 65)) + self.assertArrayEqual(result.coord('longitude').points, + np.arange(55, 60)) + self.assertArrayEqual(result.data[0, 0], np.arange(15, 20)) + + def test_request_superset(self): + cube = create_cube(40, 60) + result = cube.intersection(longitude=(35, 65)) + self.assertArrayEqual(result.coord('longitude').points, + np.arange(40, 60)) + self.assertArrayEqual(result.data[0, 0], np.arange(0, 20)) + + def test_request_subset_modulus(self): + cube = create_cube(40, 60) + result = cube.intersection(longitude=(45 + 360, 50 + 360)) + self.assertArrayEqual(result.coord('longitude').points, + np.arange(45 + 360, 51 + 360)) + self.assertArrayEqual(result.data[0, 0], np.arange(5, 11)) + + def test_request_left_modulus(self): + cube = create_cube(40, 60) + result = cube.intersection(longitude=(35 + 360, 45 + 360)) + self.assertArrayEqual(result.coord('longitude').points, + np.arange(40 + 360, 46 + 360)) + self.assertArrayEqual(result.data[0, 0], np.arange(0, 6)) + + def test_request_right_modulus(self): + cube = create_cube(40, 60) + result = cube.intersection(longitude=(55 + 360, 65 + 360)) + self.assertArrayEqual(result.coord('longitude').points, + np.arange(55 + 360, 60 + 360)) + self.assertArrayEqual(result.data[0, 0], np.arange(15, 20)) + + def test_request_superset_modulus(self): + cube = create_cube(40, 60) + result = cube.intersection(longitude=(35 + 360, 65 + 360)) + self.assertArrayEqual(result.coord('longitude').points, + np.arange(40 + 360, 60 + 360)) + self.assertArrayEqual(result.data[0, 0], np.arange(0, 20)) + + def test_tolerance_f4(self): + cube = create_cube(0, 5) + cube.coord('longitude').points = np.array([0., 3.74999905, 7.49999809, + 11.24999714, 14.99999619], + dtype='f4') + result = cube.intersection(longitude=(0, 5)) + + def test_tolerance_f8(self): + cube = create_cube(0, 5) + cube.coord('longitude').points = np.array([0., 3.74999905, 7.49999809, + 11.24999714, 14.99999619], + dtype='f8') + result = cube.intersection(longitude=(0, 5)) + + +# Check what happens with a global, points-only circular intersection +# coordinate. +class Test_intersection__GlobalSrcModulus(tests.IrisTest): + def test_global_wrapped_extreme_increasing_base_period(self): + # Ensure that we can correctly handle points defined at (base + period) + cube = create_cube(-180., 180.) + lons = cube.coord('longitude') + # Redefine longitude so that points at (base + period) + lons.points = np.linspace(-180., 180, lons.points.size) + result = cube.intersection(longitude=(lons.points.min(), + lons.points.max())) + self.assertArrayEqual(result.data, cube.data) + + def test_global_wrapped_extreme_decreasing_base_period(self): + # Ensure that we can correctly handle points defined at (base + period) + cube = create_cube(180., -180.) + lons = cube.coord('longitude') + # Redefine longitude so that points at (base + period) + lons.points = np.linspace(180., -180., lons.points.size) + result = cube.intersection(longitude=(lons.points.min(), + lons.points.max())) + self.assertArrayEqual(result.data, cube.data) + + def test_global(self): + cube = create_cube(0, 360) + result = cube.intersection(longitude=(0, 360)) + self.assertEqual(result.coord('longitude').points[0], 0) + self.assertEqual(result.coord('longitude').points[-1], 359) + self.assertEqual(result.data[0, 0, 0], 0) + self.assertEqual(result.data[0, 0, -1], 359) + + def test_global_wrapped(self): + cube = create_cube(0, 360) + result = cube.intersection(longitude=(-180, 180)) + self.assertEqual(result.coord('longitude').points[0], -180) + self.assertEqual(result.coord('longitude').points[-1], 179) + self.assertEqual(result.data[0, 0, 0], 180) + self.assertEqual(result.data[0, 0, -1], 179) + + def test_aux_coord(self): + cube = create_cube(0, 360) + cube.replace_coord(iris.coords.AuxCoord.from_coord( + cube.coord('longitude'))) + result = cube.intersection(longitude=(0, 360)) + self.assertEqual(result.coord('longitude').points[0], 0) + self.assertEqual(result.coord('longitude').points[-1], 359) + self.assertEqual(result.data[0, 0, 0], 0) + self.assertEqual(result.data[0, 0, -1], 359) + + def test_aux_coord_wrapped(self): + cube = create_cube(0, 360) + cube.replace_coord(iris.coords.AuxCoord.from_coord( + cube.coord('longitude'))) + result = cube.intersection(longitude=(-180, 180)) + self.assertEqual(result.coord('longitude').points[0], 0) + self.assertEqual(result.coord('longitude').points[-1], -1) + self.assertEqual(result.data[0, 0, 0], 0) + self.assertEqual(result.data[0, 0, -1], 359) + + def test_aux_coord_non_contiguous_wrapped(self): + cube = create_cube(0, 360) + coord = iris.coords.AuxCoord.from_coord(cube.coord('longitude')) + coord.points = (coord.points * 1.5) % 360 + cube.replace_coord(coord) + result = cube.intersection(longitude=(-90, 90)) + self.assertEqual(result.coord('longitude').points[0], 0) + self.assertEqual(result.coord('longitude').points[-1], 90) + self.assertEqual(result.data[0, 0, 0], 0) + self.assertEqual(result.data[0, 0, -1], 300) + + def test_decrementing(self): + cube = create_cube(360, 0) + result = cube.intersection(longitude=(40, 60)) + self.assertEqual(result.coord('longitude').points[0], 60) + self.assertEqual(result.coord('longitude').points[-1], 40) + self.assertEqual(result.data[0, 0, 0], 300) + self.assertEqual(result.data[0, 0, -1], 320) + + def test_decrementing_wrapped(self): + cube = create_cube(360, 0) + result = cube.intersection(longitude=(-10, 10)) + self.assertEqual(result.coord('longitude').points[0], 10) + self.assertEqual(result.coord('longitude').points[-1], -10) + self.assertEqual(result.data[0, 0, 0], 350) + self.assertEqual(result.data[0, 0, -1], 10) + + def test_no_wrap_after_modulus(self): + cube = create_cube(0, 360) + result = cube.intersection(longitude=(170 + 360, 190 + 360)) + self.assertEqual(result.coord('longitude').points[0], 170 + 360) + self.assertEqual(result.coord('longitude').points[-1], 190 + 360) + self.assertEqual(result.data[0, 0, 0], 170) + self.assertEqual(result.data[0, 0, -1], 190) + + def test_wrap_after_modulus(self): + cube = create_cube(-180, 180) + result = cube.intersection(longitude=(170 + 360, 190 + 360)) + self.assertEqual(result.coord('longitude').points[0], 170 + 360) + self.assertEqual(result.coord('longitude').points[-1], 190 + 360) + self.assertEqual(result.data[0, 0, 0], 350) + self.assertEqual(result.data[0, 0, -1], 10) + + def test_select_by_coord(self): + cube = create_cube(0, 360) + coord = iris.coords.DimCoord(0, 'longitude', units='degrees') + result = cube.intersection(iris.coords.CoordExtent(coord, 10, 30)) + self.assertEqual(result.coord('longitude').points[0], 10) + self.assertEqual(result.coord('longitude').points[-1], 30) + self.assertEqual(result.data[0, 0, 0], 10) + self.assertEqual(result.data[0, 0, -1], 30) + + def test_inclusive_exclusive(self): + cube = create_cube(0, 360) + result = cube.intersection(longitude=(170, 190, True, False)) + self.assertEqual(result.coord('longitude').points[0], 170) + self.assertEqual(result.coord('longitude').points[-1], 189) + self.assertEqual(result.data[0, 0, 0], 170) + self.assertEqual(result.data[0, 0, -1], 189) + + def test_exclusive_inclusive(self): + cube = create_cube(0, 360) + result = cube.intersection(longitude=(170, 190, False)) + self.assertEqual(result.coord('longitude').points[0], 171) + self.assertEqual(result.coord('longitude').points[-1], 190) + self.assertEqual(result.data[0, 0, 0], 171) + self.assertEqual(result.data[0, 0, -1], 190) + + def test_exclusive_exclusive(self): + cube = create_cube(0, 360) + result = cube.intersection(longitude=(170, 190, False, False)) + self.assertEqual(result.coord('longitude').points[0], 171) + self.assertEqual(result.coord('longitude').points[-1], 189) + self.assertEqual(result.data[0, 0, 0], 171) + self.assertEqual(result.data[0, 0, -1], 189) + + def test_single_point(self): + # 10 <= v <= 10 + cube = create_cube(0, 360) + result = cube.intersection(longitude=(10, 10)) + self.assertEqual(result.coord('longitude').points[0], 10) + self.assertEqual(result.coord('longitude').points[-1], 10) + self.assertEqual(result.data[0, 0, 0], 10) + self.assertEqual(result.data[0, 0, -1], 10) + + def test_two_points(self): + # -1.5 <= v <= 0.5 + cube = create_cube(0, 360) + result = cube.intersection(longitude=(-1.5, 0.5)) + self.assertEqual(result.coord('longitude').points[0], -1) + self.assertEqual(result.coord('longitude').points[-1], 0) + self.assertEqual(result.data[0, 0, 0], 359) + self.assertEqual(result.data[0, 0, -1], 0) + + def test_wrap_radians(self): + cube = create_cube(0, 360) + cube.coord('longitude').convert_units('radians') + result = cube.intersection(longitude=(-1, 0.5)) + self.assertEqual(result.coord('longitude').points[0], + -0.99483767363676634) + self.assertEqual(result.coord('longitude').points[-1], + 0.48869219055841207) + self.assertEqual(result.data[0, 0, 0], 303) + self.assertEqual(result.data[0, 0, -1], 28) + + def test_tolerance_bug(self): + # Floating point changes introduced by wrapping mean + # the resulting coordinate values are not equal to their + # equivalents. This led to a bug that this test checks. + cube = create_cube(0, 400) + cube.coord('longitude').points = np.linspace(-179.55, 179.55, 400) + result = cube.intersection(longitude=(125, 145)) + self.assertArrayAlmostEqual(result.coord('longitude').points, + cube.coord('longitude').points[339:361]) + + def test_tolerance_bug_wrapped(self): + cube = create_cube(0, 400) + cube.coord('longitude').points = np.linspace(-179.55, 179.55, 400) + result = cube.intersection(longitude=(-190, -170)) + # Expected result is the last 11 and first 11 points. + expected = np.append(cube.coord('longitude').points[389:] - 360., + cube.coord('longitude').points[:11]) + self.assertArrayAlmostEqual(result.coord('longitude').points, + expected) + + +# Check what happens with a global, points-and-bounds circular +# intersection coordinate. +class Test_intersection__ModulusBounds(tests.IrisTest): + def test_global_wrapped_extreme_increasing_base_period(self): + # Ensure that we can correctly handle bounds defined at (base + period) + cube = create_cube(-180., 180., bounds=True) + lons = cube.coord('longitude') + result = cube.intersection(longitude=(lons.bounds.min(), + lons.bounds.max())) + self.assertArrayEqual(result.data, cube.data) + + def test_global_wrapped_extreme_decreasing_base_period(self): + # Ensure that we can correctly handle bounds defined at (base + period) + cube = create_cube(180., -180., bounds=True) + lons = cube.coord('longitude') + result = cube.intersection(longitude=(lons.bounds.min(), + lons.bounds.max())) + self.assertArrayEqual(result.data, cube.data) + + def test_misaligned_points_inside(self): + cube = create_cube(0, 360, bounds=True) + result = cube.intersection(longitude=(169.75, 190.25)) + self.assertArrayEqual(result.coord('longitude').bounds[0], + [169.5, 170.5]) + self.assertArrayEqual(result.coord('longitude').bounds[-1], + [189.5, 190.5]) + self.assertEqual(result.data[0, 0, 0], 170) + self.assertEqual(result.data[0, 0, -1], 190) + + def test_misaligned_points_outside(self): + cube = create_cube(0, 360, bounds=True) + result = cube.intersection(longitude=(170.25, 189.75)) + self.assertArrayEqual(result.coord('longitude').bounds[0], + [169.5, 170.5]) + self.assertArrayEqual(result.coord('longitude').bounds[-1], + [189.5, 190.5]) + self.assertEqual(result.data[0, 0, 0], 170) + self.assertEqual(result.data[0, 0, -1], 190) + + def test_misaligned_bounds(self): + cube = create_cube(-180, 180, bounds=True) + result = cube.intersection(longitude=(0, 360)) + self.assertArrayEqual(result.coord('longitude').bounds[0], + [-0.5, 0.5]) + self.assertArrayEqual(result.coord('longitude').bounds[-1], + [358.5, 359.5]) + self.assertEqual(result.data[0, 0, 0], 180) + self.assertEqual(result.data[0, 0, -1], 179) + + def test_misaligned_bounds_decreasing(self): + cube = create_cube(180, -180, bounds=True) + result = cube.intersection(longitude=(0, 360)) + self.assertArrayEqual(result.coord('longitude').bounds[0], + [359.5, 358.5]) + self.assertArrayEqual(result.coord('longitude').points[-1], 0) + self.assertArrayEqual(result.coord('longitude').bounds[-1], + [0.5, -0.5]) + self.assertEqual(result.data[0, 0, 0], 181) + self.assertEqual(result.data[0, 0, -1], 180) + + def test_aligned_inclusive(self): + cube = create_cube(0, 360, bounds=True) + result = cube.intersection(longitude=(170.5, 189.5)) + self.assertArrayEqual(result.coord('longitude').bounds[0], + [169.5, 170.5]) + self.assertArrayEqual(result.coord('longitude').bounds[-1], + [189.5, 190.5]) + self.assertEqual(result.data[0, 0, 0], 170) + self.assertEqual(result.data[0, 0, -1], 190) + + def test_aligned_exclusive(self): + cube = create_cube(0, 360, bounds=True) + result = cube.intersection(longitude=(170.5, 189.5, False, False)) + self.assertArrayEqual(result.coord('longitude').bounds[0], + [170.5, 171.5]) + self.assertArrayEqual(result.coord('longitude').bounds[-1], + [188.5, 189.5]) + self.assertEqual(result.data[0, 0, 0], 171) + self.assertEqual(result.data[0, 0, -1], 189) + + def test_negative_misaligned_points_inside(self): + cube = create_cube(0, 360, bounds=True) + result = cube.intersection(longitude=(-10.25, 10.25)) + self.assertArrayEqual(result.coord('longitude').bounds[0], + [-10.5, -9.5]) + self.assertArrayEqual(result.coord('longitude').bounds[-1], + [9.5, 10.5]) + self.assertEqual(result.data[0, 0, 0], 350) + self.assertEqual(result.data[0, 0, -1], 10) + + def test_negative_misaligned_points_outside(self): + cube = create_cube(0, 360, bounds=True) + result = cube.intersection(longitude=(-9.75, 9.75)) + self.assertArrayEqual(result.coord('longitude').bounds[0], + [-10.5, -9.5]) + self.assertArrayEqual(result.coord('longitude').bounds[-1], + [9.5, 10.5]) + self.assertEqual(result.data[0, 0, 0], 350) + self.assertEqual(result.data[0, 0, -1], 10) + + def test_negative_aligned_inclusive(self): + cube = create_cube(0, 360, bounds=True) + result = cube.intersection(longitude=(-10.5, 10.5)) + self.assertArrayEqual(result.coord('longitude').bounds[0], + [-11.5, -10.5]) + self.assertArrayEqual(result.coord('longitude').bounds[-1], + [10.5, 11.5]) + self.assertEqual(result.data[0, 0, 0], 349) + self.assertEqual(result.data[0, 0, -1], 11) + + def test_negative_aligned_exclusive(self): + cube = create_cube(0, 360, bounds=True) + result = cube.intersection(longitude=(-10.5, 10.5, False, False)) + self.assertArrayEqual(result.coord('longitude').bounds[0], + [-10.5, -9.5]) + self.assertArrayEqual(result.coord('longitude').bounds[-1], + [9.5, 10.5]) + self.assertEqual(result.data[0, 0, 0], 350) + self.assertEqual(result.data[0, 0, -1], 10) + + def test_decrementing(self): + cube = create_cube(360, 0, bounds=True) + result = cube.intersection(longitude=(40, 60)) + self.assertArrayEqual(result.coord('longitude').bounds[0], + [60.5, 59.5]) + self.assertArrayEqual(result.coord('longitude').bounds[-1], + [40.5, 39.5]) + self.assertEqual(result.data[0, 0, 0], 300) + self.assertEqual(result.data[0, 0, -1], 320) + + def test_decrementing_wrapped(self): + cube = create_cube(360, 0, bounds=True) + result = cube.intersection(longitude=(-10, 10)) + self.assertArrayEqual(result.coord('longitude').bounds[0], + [10.5, 9.5]) + self.assertArrayEqual(result.coord('longitude').bounds[-1], + [-9.5, -10.5]) + self.assertEqual(result.data[0, 0, 0], 350) + self.assertEqual(result.data[0, 0, -1], 10) + + def test_numerical_tolerance(self): + # test the tolerance on the coordinate value is not causing a + # modulus wrapping + cube = create_cube(28.5, 68.5, bounds=True) + result = cube.intersection(longitude=(27.74, 68.61)) + self.assertAlmostEqual(result.coord('longitude').points[0], 28.5) + self.assertAlmostEqual(result.coord('longitude').points[-1], 67.5) + + +def unrolled_cube(): + data = np.arange(5, dtype='f4') + cube = Cube(data) + cube.add_aux_coord(iris.coords.AuxCoord([5.0, 10.0, 8.0, 5.0, 3.0], + 'longitude', units='degrees'), 0) + cube.add_aux_coord(iris.coords.AuxCoord([1.0, 3.0, -2.0, -1.0, -4.0], + 'latitude'), 0) + return cube + + +# Check what happens with a "unrolled" scatter-point data with a circular +# intersection coordinate. +class Test_intersection__ScatterModulus(tests.IrisTest): + def test_subset(self): + cube = unrolled_cube() + result = cube.intersection(longitude=(5, 8)) + self.assertArrayEqual(result.coord('longitude').points, [5, 8, 5]) + self.assertArrayEqual(result.data, [0, 2, 3]) + + def test_subset_wrapped(self): + cube = unrolled_cube() + result = cube.intersection(longitude=(5 + 360, 8 + 360)) + self.assertArrayEqual(result.coord('longitude').points, + [365, 368, 365]) + self.assertArrayEqual(result.data, [0, 2, 3]) + + def test_superset(self): + cube = unrolled_cube() + result = cube.intersection(longitude=(0, 15)) + self.assertArrayEqual(result.coord('longitude').points, + [5, 10, 8, 5, 3]) + self.assertArrayEqual(result.data, np.arange(5)) + + +# Test the API of the cube interpolation method. +class Test_interpolate(tests.IrisTest): + def setUp(self): + self.cube = stock.simple_2d() + + self.scheme = mock.Mock(name='interpolation scheme') + self.interpolator = mock.Mock(name='interpolator') + self.interpolator.return_value = mock.sentinel.RESULT + self.scheme.interpolator.return_value = self.interpolator + self.collapse_coord = True + + def test_api(self): + sample_points = (('foo', 0.5), ('bar', 0.6)) + result = self.cube.interpolate(sample_points, self.scheme, + self.collapse_coord) + self.scheme.interpolator.assert_called_once_with( + self.cube, ('foo', 'bar')) + self.interpolator.assert_called_once_with( + (0.5, 0.6), collapse_scalar=self.collapse_coord) + self.assertIs(result, mock.sentinel.RESULT) + + +class Test_regrid(tests.IrisTest): + def test(self): + # Test that Cube.regrid() just defers to the regridder of the + # given scheme. + + # Define a fake scheme and its associated regridder which just + # capture their arguments and return them in place of the + # regridded cube. + class FakeRegridder(object): + def __init__(self, *args): + self.args = args + + def __call__(self, cube): + return self.args + (cube,) + + class FakeScheme(object): + def regridder(self, src, target): + return FakeRegridder(self, src, target) + + cube = Cube(0) + scheme = FakeScheme() + result = cube.regrid(mock.sentinel.TARGET, scheme) + self.assertEqual(result, (scheme, cube, mock.sentinel.TARGET, cube)) + + +class Test_copy(tests.IrisTest): + def _check_copy(self, cube, cube_copy): + self.assertIsNot(cube_copy, cube) + self.assertEqual(cube_copy, cube) + self.assertIsNot(cube_copy.data, cube.data) + if ma.isMaskedArray(cube.data): + self.assertMaskedArrayEqual(cube_copy.data, cube.data) + if cube.data.mask is not ma.nomask: + # "No mask" is a constant : all other cases must be distinct. + self.assertIsNot(cube_copy.data.mask, cube.data.mask) + else: + self.assertArrayEqual(cube_copy.data, cube.data) + + def test(self): + cube = stock.simple_3d() + self._check_copy(cube, cube.copy()) + + def test__masked_emptymask(self): + cube = Cube(ma.array([0, 1])) + self._check_copy(cube, cube.copy()) + + def test__masked_arraymask(self): + cube = Cube(ma.array([0, 1], mask=[True, False])) + self._check_copy(cube, cube.copy()) + + def test__scalar(self): + cube = Cube(0) + self._check_copy(cube, cube.copy()) + + def test__masked_scalar_emptymask(self): + cube = Cube(ma.array(0)) + self._check_copy(cube, cube.copy()) + + def test__masked_scalar_arraymask(self): + cube = Cube(ma.array(0, mask=False)) + self._check_copy(cube, cube.copy()) + + def test__lazy(self): + # Note: multiple chunks added as a workaround suggested to dask#3751, + # which is fixed in dask#3754. + cube = Cube(as_lazy_data(np.array([1, 0]), chunks=(1, 1))) + self._check_copy(cube, cube.copy()) + + +class Test_dtype(tests.IrisTest): + def setUp(self): + self.dtypes = (np.dtype('int'), np.dtype('uint'), + np.dtype('bool'), np.dtype('float')) + + def test_real_data(self): + for dtype in self.dtypes: + data = np.array([0, 1], dtype=dtype) + cube = Cube(data) + self.assertEqual(cube.dtype, dtype) + + def test_real_data_masked__mask_unset(self): + for dtype in self.dtypes: + data = ma.array([0, 1], dtype=dtype) + cube = Cube(data) + self.assertEqual(cube.dtype, dtype) + + def test_real_data_masked__mask_set(self): + for dtype in self.dtypes: + data = ma.array([0, 1], dtype=dtype) + data[0] = ma.masked + cube = Cube(data) + self.assertEqual(cube.dtype, dtype) + + def test_lazy_data(self): + for dtype in self.dtypes: + data = np.array([0, 1], dtype=dtype) + cube = Cube(as_lazy_data(data)) + self.assertEqual(cube.dtype, dtype) + # Check that accessing the dtype does not trigger loading + # of the data. + self.assertTrue(cube.has_lazy_data()) + + def test_lazy_data_masked__mask_unset(self): + for dtype in self.dtypes: + data = ma.array([0, 1], dtype=dtype) + cube = Cube(as_lazy_data(data)) + self.assertEqual(cube.dtype, dtype) + # Check that accessing the dtype does not trigger loading + # of the data. + self.assertTrue(cube.has_lazy_data()) + + def test_lazy_data_masked__mask_set(self): + for dtype in self.dtypes: + data = ma.array([0, 1], dtype=dtype) + data[0] = ma.masked + cube = Cube(as_lazy_data(data)) + self.assertEqual(cube.dtype, dtype) + # Check that accessing the dtype does not trigger loading + # of the data. + self.assertTrue(cube.has_lazy_data()) + + +class TestSubset(tests.IrisTest): + def test_scalar_coordinate(self): + cube = Cube(0, long_name='apricot', units='1') + cube.add_aux_coord(DimCoord([0], long_name='banana', units='1')) + result = cube.subset(cube.coord('banana')) + self.assertEqual(cube, result) + + def test_dimensional_coordinate(self): + cube = Cube(np.zeros((4)), long_name='tinned_peach', units='1') + cube.add_dim_coord(DimCoord([0, 1, 2, 3], + long_name='sixteen_ton_weight', + units='1'), + 0) + result = cube.subset(cube.coord('sixteen_ton_weight')) + self.assertEqual(cube, result) + + def test_missing_coordinate(self): + cube = Cube(0, long_name='raspberry', units='1') + cube.add_aux_coord(DimCoord([0], long_name='loganberry', units='1')) + bad_coord = DimCoord([0], long_name='tiger', units='1') + self.assertRaises(CoordinateNotFoundError, cube.subset, bad_coord) + + def test_different_coordinate(self): + cube = Cube(0, long_name='raspberry', units='1') + cube.add_aux_coord(DimCoord([0], long_name='loganberry', units='1')) + different_coord = DimCoord([2], long_name='loganberry', units='1') + result = cube.subset(different_coord) + self.assertEqual(result, None) + + def test_not_coordinate(self): + cube = Cube(0, long_name='peach', units='1') + cube.add_aux_coord(DimCoord([0], long_name='crocodile', units='1')) + self.assertRaises(ValueError, cube.subset, 'Pointed Stick') + + +class Test_add_metadata(tests.IrisTest): + def test_add_dim_coord(self): + cube = Cube(np.arange(3)) + x_coord = DimCoord(points=np.array([2, 3, 4]), + long_name='x') + cube.add_dim_coord(x_coord, 0) + self.assertEqual(cube.coord('x'), x_coord) + + def test_add_aux_coord(self): + cube = Cube(np.arange(6).reshape(2, 3)) + x_coord = AuxCoord(points=np.arange(6).reshape(2, 3), + long_name='x') + cube.add_aux_coord(x_coord, [0, 1]) + self.assertEqual(cube.coord('x'), x_coord) + + def test_add_cell_measure(self): + cube = Cube(np.arange(6).reshape(2, 3)) + a_cell_measure = CellMeasure(data=np.arange(6).reshape(2, 3), + long_name='area', measure='area') + cube.add_cell_measure(a_cell_measure, [0, 1]) + self.assertEqual(cube.cell_measure('area'), a_cell_measure) + + def test_add_valid_aux_factory(self): + cube = Cube(np.arange(8).reshape(2, 2, 2)) + delta = AuxCoord(points=[0, 1], long_name='delta', units='m') + sigma = AuxCoord(points=[0, 1], long_name='sigma') + orog = AuxCoord(np.arange(4).reshape(2, 2), units='m') + cube.add_aux_coord(delta, 0) + cube.add_aux_coord(sigma, 0) + cube.add_aux_coord(orog, (1, 2)) + factory = HybridHeightFactory(delta=delta, sigma=sigma, orography=orog) + self.assertIsNone(cube.add_aux_factory(factory)) + + def test_error_for_add_invalid_aux_factory(self): + cube = Cube(np.arange(8).reshape(2, 2, 2), long_name='bar') + delta = AuxCoord(points=[0, 1], long_name='delta', units='m') + sigma = AuxCoord(points=[0, 1], long_name='sigma') + orog = AuxCoord(np.arange(4).reshape(2, 2), units='m', long_name='foo') + cube.add_aux_coord(delta, 0) + cube.add_aux_coord(sigma, 0) + # Note orography is not added to the cube here + factory = HybridHeightFactory(delta=delta, sigma=sigma, orography=orog) + expected_error = ("foo coordinate for factory is not present on cube " + "bar") + with self.assertRaisesRegexp(ValueError, expected_error): + cube.add_aux_factory(factory) + + +class Test_remove_metadata(tests.IrisTest): + def setUp(self): + cube = Cube(np.arange(6).reshape(2, 3)) + x_coord = DimCoord(points=np.array([2, 3, 4]), + long_name='x') + cube.add_dim_coord(x_coord, 1) + z_coord = AuxCoord(points=np.arange(6).reshape(2, 3), + long_name='z') + cube.add_aux_coord(z_coord, [0, 1]) + a_cell_measure = CellMeasure(data=np.arange(6).reshape(2, 3), + long_name='area', measure='area') + self.b_cell_measure = CellMeasure(data=np.arange(6).reshape(2, 3), + long_name='other_area', + measure='area') + cube.add_cell_measure(a_cell_measure, [0, 1]) + cube.add_cell_measure(self.b_cell_measure, [0, 1]) + self.cube = cube + + def test_remove_dim_coord(self): + self.cube.remove_coord(self.cube.coord('x')) + self.assertEqual(self.cube.coords('x'), []) + + def test_remove_aux_coord(self): + self.cube.remove_coord(self.cube.coord('z')) + self.assertEqual(self.cube.coords('z'), []) + + def test_remove_cell_measure(self): + self.cube.remove_cell_measure(self.cube.cell_measure('area')) + self.assertEqual(self.cube._cell_measures_and_dims, + [[self.b_cell_measure, (0, 1)]]) + + +class Test__getitem_CellMeasure(tests.IrisTest): + def setUp(self): + cube = Cube(np.arange(6).reshape(2, 3)) + x_coord = DimCoord(points=np.array([2, 3, 4]), + long_name='x') + cube.add_dim_coord(x_coord, 1) + y_coord = DimCoord(points=np.array([5, 6]), + long_name='y') + cube.add_dim_coord(y_coord, 0) + z_coord = AuxCoord(points=np.arange(6).reshape(2, 3), + long_name='z') + cube.add_aux_coord(z_coord, [0, 1]) + a_cell_measure = CellMeasure(data=np.arange(6).reshape(2, 3), + long_name='area', measure='area') + cube.add_cell_measure(a_cell_measure, [0, 1]) + self.cube = cube + + def test_cell_measure_2d(self): + result = self.cube[0:2, 0:2] + self.assertEqual(len(result.cell_measures()), 1) + self.assertEqual(result.shape, + result.cell_measures()[0].data.shape) + + def test_cell_measure_1d(self): + result = self.cube[0, 0:2] + self.assertEqual(len(result.cell_measures()), 1) + self.assertEqual(result.shape, + result.cell_measures()[0].data.shape) + + +class TestCellMeasures(tests.IrisTest): + def setUp(self): + cube = Cube(np.arange(6).reshape(2, 3)) + x_coord = DimCoord(points=np.array([2, 3, 4]), + long_name='x') + cube.add_dim_coord(x_coord, 1) + z_coord = AuxCoord(points=np.arange(6).reshape(2, 3), + long_name='z') + cube.add_aux_coord(z_coord, [0, 1]) + self.a_cell_measure = CellMeasure(data=np.arange(6).reshape(2, 3), + long_name='area', measure='area', + units='m2') + cube.add_cell_measure(self.a_cell_measure, [0, 1]) + self.cube = cube + + def test_get_cell_measure(self): + cm = self.cube.cell_measure('area') + self.assertEqual(cm, self.a_cell_measure) + + def test_get_cell_measures(self): + cms = self.cube.cell_measures() + self.assertEqual(len(cms), 1) + self.assertEqual(cms[0], self.a_cell_measure) + + def test_get_cell_measures_obj(self): + cms = self.cube.cell_measures(self.a_cell_measure) + self.assertEqual(len(cms), 1) + self.assertEqual(cms[0], self.a_cell_measure) + + def test_fail_get_cell_measure(self): + with self.assertRaises(CellMeasureNotFoundError): + cm = self.cube.cell_measure('notarea') + + def test_fail_get_cell_measures_obj(self): + a_cell_measure = self.a_cell_measure.copy() + a_cell_measure.units = 'km2' + with self.assertRaises(CellMeasureNotFoundError): + cms = self.cube.cell_measure(a_cell_measure) + + def test_cell_measure_dims(self): + cm_dims = self.cube.cell_measure_dims(self.a_cell_measure) + self.assertEqual(cm_dims, (0, 1)) + + def test_fail_cell_measure_dims(self): + a_cell_measure = self.a_cell_measure.copy() + a_cell_measure.units = 'km2' + with self.assertRaises(CellMeasureNotFoundError): + cm_dims = self.cube.cell_measure_dims(a_cell_measure) + + +class Test_transpose(tests.IrisTest): + def setUp(self): + self.data = np.arange(24).reshape(3, 2, 4) + self.cube = Cube(self.data) + self.lazy_cube = Cube(as_lazy_data(self.data)) + + def test_lazy_data(self): + cube = self.lazy_cube + cube.transpose() + self.assertTrue(cube.has_lazy_data()) + self.assertArrayEqual(self.data.T, cube.data) + + def test_real_data(self): + self.cube.transpose() + self.assertFalse(self.cube.has_lazy_data()) + self.assertIs(self.data.base, self.cube.data.base) + self.assertArrayEqual(self.data.T, self.cube.data) + + def test_real_data__new_order(self): + new_order = [2, 0, 1] + self.cube.transpose(new_order) + self.assertFalse(self.cube.has_lazy_data()) + self.assertIs(self.data.base, self.cube.data.base) + self.assertArrayEqual(self.data.transpose(new_order), self.cube.data) + + def test_lazy_data__new_order(self): + new_order = [2, 0, 1] + cube = self.lazy_cube + cube.transpose(new_order) + self.assertTrue(cube.has_lazy_data()) + self.assertArrayEqual(self.data.transpose(new_order), cube.data) + + def test_lazy_data__transpose_order_ndarray(self): + # Check that a transpose order supplied as an array does not trip up + # a dask transpose operation. + new_order = np.array([2, 0, 1]) + cube = self.lazy_cube + cube.transpose(new_order) + self.assertTrue(cube.has_lazy_data()) + self.assertArrayEqual(self.data.transpose(new_order), cube.data) + + def test_bad_transpose_order(self): + exp_emsg = 'Incorrect number of dimensions' + with self.assertRaisesRegexp(ValueError, exp_emsg): + self.cube.transpose([1]) + + +class Test_convert_units(tests.IrisTest): + def test_convert_unknown_units(self): + cube = iris.cube.Cube(1) + emsg = ('Cannot convert from unknown units. ' + 'The "cube.units" attribute may be set directly.') + with self.assertRaisesRegexp(UnitConversionError, emsg): + cube.convert_units('mm day-1') + + def test_preserves_lazy(self): + real_data = np.arange(12.).reshape((3, 4)) + lazy_data = as_lazy_data(real_data) + cube = iris.cube.Cube(lazy_data, units='m') + real_data_ft = Unit('m').convert(real_data, 'ft') + cube.convert_units('ft') + self.assertTrue(cube.has_lazy_data()) + self.assertArrayAllClose(cube.data, real_data_ft) + -if __name__ == "__main__": +if __name__ == '__main__': tests.main() diff --git a/lib/iris/tests/unit/cube/test_CubeList.py b/lib/iris/tests/unit/cube/test_CubeList.py index cde54ea951..258408c6f8 100644 --- a/lib/iris/tests/unit/cube/test_CubeList.py +++ b/lib/iris/tests/unit/cube/test_CubeList.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2014, Met Office +# (C) British Crown Copyright 2014 - 2018, Met Office # # This file is part of Iris. # @@ -16,13 +16,106 @@ # along with Iris. If not, see . """Unit tests for the `iris.cube.CubeList` class.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests +import iris.tests.stock + +from cf_units import Unit +import numpy as np from iris.cube import Cube, CubeList -from iris.coords import AuxCoord +from iris.coords import AuxCoord, DimCoord +import iris.coord_systems import iris.exceptions +from iris.fileformats.pp import STASH +from iris.tests import mock + + +class Test_concatenate_cube(tests.IrisTest): + def setUp(self): + self.units = Unit('days since 1970-01-01 00:00:00', + calendar='gregorian') + self.cube1 = Cube([1, 2, 3], 'air_temperature', units='K') + self.cube1.add_dim_coord(DimCoord([0, 1, 2], 'time', units=self.units), + 0) + + def test_pass(self): + self.cube2 = Cube([1, 2, 3], 'air_temperature', units='K') + self.cube2.add_dim_coord(DimCoord([3, 4, 5], 'time', units=self.units), + 0) + result = CubeList([self.cube1, self.cube2]).concatenate_cube() + self.assertIsInstance(result, Cube) + + def test_fail(self): + units = Unit('days since 1970-01-02 00:00:00', + calendar='gregorian') + cube2 = Cube([1, 2, 3], 'air_temperature', units='K') + cube2.add_dim_coord(DimCoord([0, 1, 2], 'time', units=units), 0) + with self.assertRaises(iris.exceptions.ConcatenateError): + CubeList([self.cube1, cube2]).concatenate_cube() + + def test_empty(self): + exc_regexp = "can't concatenate an empty CubeList" + with self.assertRaisesRegexp(ValueError, exc_regexp): + CubeList([]).concatenate_cube() + + +class Test_extract_overlapping(tests.IrisTest): + def setUp(self): + shape = (6, 14, 19) + n_time, n_lat, n_lon = shape + n_data = n_time * n_lat * n_lon + cube = Cube(np.arange(n_data, dtype=np.int32).reshape(shape)) + coord = iris.coords.DimCoord(points=np.arange(n_time), + standard_name='time', + units='hours since epoch') + cube.add_dim_coord(coord, 0) + cs = iris.coord_systems.GeogCS(6371229) + coord = iris.coords.DimCoord(points=np.linspace(-90, 90, n_lat), + standard_name='latitude', + units='degrees', + coord_system=cs) + cube.add_dim_coord(coord, 1) + coord = iris.coords.DimCoord(points=np.linspace(-180, 180, n_lon), + standard_name='longitude', + units='degrees', + coord_system=cs) + cube.add_dim_coord(coord, 2) + self.cube = cube + + def test_extract_one_str_dim(self): + cubes = iris.cube.CubeList([self.cube[2:], self.cube[:4]]) + a, b = cubes.extract_overlapping('time') + self.assertEqual(a.coord('time'), self.cube.coord('time')[2:4]) + self.assertEqual(b.coord('time'), self.cube.coord('time')[2:4]) + + def test_extract_one_list_dim(self): + cubes = iris.cube.CubeList([self.cube[2:], self.cube[:4]]) + a, b = cubes.extract_overlapping(['time']) + self.assertEqual(a.coord('time'), self.cube.coord('time')[2:4]) + self.assertEqual(b.coord('time'), self.cube.coord('time')[2:4]) + + def test_extract_two_dims(self): + cubes = iris.cube.CubeList([self.cube[2:, 5:], self.cube[:4, :10]]) + a, b = cubes.extract_overlapping(['time', 'latitude']) + self.assertEqual(a.coord('time'), + self.cube.coord('time')[2:4]) + self.assertEqual(a.coord('latitude'), + self.cube.coord('latitude')[5:10]) + self.assertEqual(b.coord('time'), + self.cube.coord('time')[2:4]) + self.assertEqual(b.coord('latitude'), + self.cube.coord('latitude')[5:10]) + + def test_different_orders(self): + cubes = iris.cube.CubeList([self.cube[::-1][:4], self.cube[:4]]) + a, b = cubes.extract_overlapping('time') + self.assertEqual(a.coord('time'), self.cube[::-1].coord('time')[2:4]) + self.assertEqual(b.coord('time'), self.cube.coord('time')[2:4]) class Test_merge_cube(tests.IrisTest): @@ -56,5 +149,171 @@ def test_repeated_cube(self): CubeList([self.cube1, self.cube1]).merge_cube() +class Test_merge__time_triple(tests.IrisTest): + @staticmethod + def _make_cube(fp, rt, t, realization=None): + cube = Cube(np.arange(20).reshape(4, 5)) + cube.add_dim_coord(DimCoord(np.arange(5), long_name='x'), 1) + cube.add_dim_coord(DimCoord(np.arange(4), long_name='y'), 0) + cube.add_aux_coord(DimCoord(fp, standard_name='forecast_period')) + cube.add_aux_coord(DimCoord(rt, + standard_name='forecast_reference_time')) + cube.add_aux_coord(DimCoord(t, standard_name='time')) + if realization is not None: + cube.add_aux_coord(DimCoord(realization, + standard_name='realization')) + return cube + + def test_orthogonal_with_realization(self): + # => fp: 2; rt: 2; t: 2; realization: 2 + triples = ((0, 10, 1), + (0, 10, 2), + (0, 11, 1), + (0, 11, 2), + (1, 10, 1), + (1, 10, 2), + (1, 11, 1), + (1, 11, 2)) + en1_cubes = [self._make_cube(*triple, realization=1) for + triple in triples] + en2_cubes = [self._make_cube(*triple, realization=2) for + triple in triples] + cubes = CubeList(en1_cubes) + CubeList(en2_cubes) + cube, = cubes.merge() + self.assertCML(cube, checksum=False) + + def test_combination_with_realization(self): + # => fp, rt, t: 8; realization: 2 + triples = ((0, 10, 1), + (0, 10, 2), + (0, 11, 1), + (0, 11, 3), # This '3' breaks the pattern. + (1, 10, 1), + (1, 10, 2), + (1, 11, 1), + (1, 11, 2)) + en1_cubes = [self._make_cube(*triple, realization=1) for + triple in triples] + en2_cubes = [self._make_cube(*triple, realization=2) for + triple in triples] + cubes = CubeList(en1_cubes) + CubeList(en2_cubes) + cube, = cubes.merge() + self.assertCML(cube, checksum=False) + + def test_combination_with_extra_realization(self): + # => fp, rt, t, realization: 17 + triples = ((0, 10, 1), + (0, 10, 2), + (0, 11, 1), + (0, 11, 2), + (1, 10, 1), + (1, 10, 2), + (1, 11, 1), + (1, 11, 2)) + en1_cubes = [self._make_cube(*triple, realization=1) for + triple in triples] + en2_cubes = [self._make_cube(*triple, realization=2) for + triple in triples] + # Add extra that is a duplicate of one of the time triples + # but with a different realisation. + en3_cubes = [self._make_cube(0, 10, 2, realization=3)] + cubes = CubeList(en1_cubes) + CubeList(en2_cubes) + CubeList(en3_cubes) + cube, = cubes.merge() + self.assertCML(cube, checksum=False) + + def test_combination_with_extra_triple(self): + # => fp, rt, t, realization: 17 + triples = ((0, 10, 1), + (0, 10, 2), + (0, 11, 1), + (0, 11, 2), + (1, 10, 1), + (1, 10, 2), + (1, 11, 1), + (1, 11, 2)) + en1_cubes = [self._make_cube(*triple, realization=1) for + triple in triples] + # Add extra time triple on the end. + en2_cubes = [self._make_cube(*triple, realization=2) for + triple in triples + ((1, 11, 3),)] + cubes = CubeList(en1_cubes) + CubeList(en2_cubes) + cube, = cubes.merge() + self.assertCML(cube, checksum=False) + + +class Test_xml(tests.IrisTest): + def setUp(self): + self.cubes = CubeList([Cube(np.arange(3)), + Cube(np.arange(3))]) + + def test_byteorder_default(self): + self.assertIn('byteorder', self.cubes.xml()) + + def test_byteorder_false(self): + self.assertNotIn('byteorder', self.cubes.xml(byteorder=False)) + + def test_byteorder_true(self): + self.assertIn('byteorder', self.cubes.xml(byteorder=True)) + + +class Test_extract(tests.IrisTest): + def setUp(self): + self.scalar_cubes = CubeList() + for i in range(5): + for letter in 'abcd': + self.scalar_cubes.append(Cube(i, long_name=letter)) + + def test_scalar_cube_name_constraint(self): + # Test the name based extraction of a CubeList containing scalar cubes. + res = self.scalar_cubes.extract('a') + expected = CubeList([Cube(i, long_name='a') for i in range(5)]) + self.assertEqual(res, expected) + + def test_scalar_cube_data_constraint(self): + # Test the extraction of a CubeList containing scalar cubes + # when using a cube_func. + val = 2 + constraint = iris.Constraint(cube_func=lambda c: c.data == val) + res = self.scalar_cubes.extract(constraint) + expected = CubeList([Cube(val, long_name=letter) for letter in 'abcd']) + self.assertEqual(res, expected) + + +class TestPrint(tests.IrisTest): + def setUp(self): + self.cubes = CubeList([iris.tests.stock.lat_lon_cube()]) + + def test_summary(self): + expected = ('0: unknown / (unknown) ' + ' (latitude: 3; longitude: 4)') + self.assertEqual(str(self.cubes), expected) + + def test_summary_name_unit(self): + self.cubes[0].long_name = 'aname' + self.cubes[0].units = '1' + expected = ('0: aname / (1) ' + ' (latitude: 3; longitude: 4)') + self.assertEqual(str(self.cubes), expected) + + def test_summary_stash(self): + self.cubes[0].attributes['STASH'] = STASH.from_msi('m01s00i004') + expected = ('0: m01s00i004 / (unknown) ' + ' (latitude: 3; longitude: 4)') + self.assertEqual(str(self.cubes), expected) + + +class TestRealiseData(tests.IrisTest): + def test_realise_data(self): + # Simply check that calling CubeList.realise_data is calling + # _lazy_data.co_realise_cubes. + mock_cubes_list = [mock.Mock(ident=count) for count in range(3)] + test_cubelist = CubeList(mock_cubes_list) + call_patch = self.patch('iris._lazy_data.co_realise_cubes') + test_cubelist.realise_data() + # Check it was called once, passing cubes as *args. + self.assertEqual(call_patch.call_args_list, + [mock.call(*mock_cubes_list)]) + + if __name__ == "__main__": tests.main() diff --git a/lib/iris/tests/unit/cube/test_Cube__operators.py b/lib/iris/tests/unit/cube/test_Cube__operators.py new file mode 100644 index 0000000000..fad18bbde3 --- /dev/null +++ b/lib/iris/tests/unit/cube/test_Cube__operators.py @@ -0,0 +1,266 @@ +# (C) British Crown Copyright 2016 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.cube.Cube` class operators.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised +# before importing anything else. +import iris.tests as tests + +import operator + +import dask.array as da +import numpy as np +import numpy.ma as ma + +import iris +from iris._lazy_data import as_lazy_data +from iris.coords import DimCoord + + +class Test_lazy_maths(tests.IrisTest): + def build_lazy_cube(self, points, dtype=np.float64, bounds=None, nx=10): + data = np.arange(len(points) * nx, dtype=dtype) + 1 # Just avoid 0. + data = data.reshape(len(points), nx) + data = as_lazy_data(data) + cube = iris.cube.Cube(data, standard_name='air_temperature', units='K') + lat = DimCoord(points, 'latitude', bounds=bounds) + lon = DimCoord(np.arange(nx), 'longitude') + cube.add_dim_coord(lat, 0) + cube.add_dim_coord(lon, 1) + return cube + + def check_common(self, base_cube, result): + self.assertTrue(base_cube.has_lazy_data()) + self.assertTrue(result.has_lazy_data()) + self.assertIsInstance(result.lazy_data(), da.core.Array) + + def cube_cube_math_op(self, c1, math_op): + result = math_op(c1, c1) + self.check_common(c1, result) + expected = math_op(c1.data, c1.data) + self.assertArrayAlmostEqual(result.data, expected) + + def cube_scalar_math_op(self, c1, scalar, math_op, commutative=True): + result = math_op(c1, scalar) + if commutative: + self.assertEqual(math_op(c1, scalar), math_op(scalar, c1)) + self.check_common(c1, result) + expected = math_op(c1.data, scalar) + self.assertArrayAlmostEqual(result.data, expected) + + def test_add_cubes__float(self): + c1 = self.build_lazy_cube([1, 2]) + op = operator.add + self.cube_cube_math_op(c1, op) + + def test_add_scalar__float(self): + c1 = self.build_lazy_cube([1, 2]) + scalar = 5 + op = operator.add + self.cube_scalar_math_op(c1, scalar, op) + + def test_mul_cubes__float(self): + c1 = self.build_lazy_cube([1, 2]) + op = operator.mul + self.cube_cube_math_op(c1, op) + + def test_mul_scalar__float(self): + c1 = self.build_lazy_cube([1, 2]) + scalar = 5 + op = operator.mul + self.cube_scalar_math_op(c1, scalar, op) + + def test_sub_cubes__float(self): + c1 = self.build_lazy_cube([1, 2]) + op = operator.sub + self.cube_cube_math_op(c1, op) + + def test_sub_scalar__float(self): + c1 = self.build_lazy_cube([1, 2]) + scalar = 5 + op = operator.sub + self.cube_scalar_math_op(c1, scalar, op, commutative=False) + + def test_div_cubes__float(self): + c1 = self.build_lazy_cube([1, 2]) + op = operator.truediv + self.cube_cube_math_op(c1, op) + + def test_div_scalar__float(self): + c1 = self.build_lazy_cube([1, 2]) + scalar = 5 + op = operator.truediv + self.cube_scalar_math_op(c1, scalar, op, commutative=False) + + def test_add_cubes__int(self): + c1 = self.build_lazy_cube([1, 2], dtype=np.int64) + op = operator.add + self.cube_cube_math_op(c1, op) + + def test_add_scalar__int(self): + c1 = self.build_lazy_cube([1, 2], dtype=np.int64) + scalar = 5 + op = operator.add + self.cube_scalar_math_op(c1, scalar, op) + + def test_mul_cubes__int(self): + c1 = self.build_lazy_cube([1, 2], dtype=np.int64) + op = operator.mul + self.cube_cube_math_op(c1, op) + + def test_mul_scalar__int(self): + c1 = self.build_lazy_cube([1, 2], dtype=np.int64) + scalar = 5 + op = operator.mul + self.cube_scalar_math_op(c1, scalar, op) + + def test_sub_cubes__int(self): + c1 = self.build_lazy_cube([1, 2], dtype=np.int64) + op = operator.sub + self.cube_cube_math_op(c1, op) + + def test_sub_scalar__int(self): + c1 = self.build_lazy_cube([1, 2], dtype=np.int64) + scalar = 5 + op = operator.sub + self.cube_scalar_math_op(c1, scalar, op, commutative=False) + + def test_div_cubes__int(self): + c1 = self.build_lazy_cube([1, 2], dtype=np.int64) + op = operator.truediv + self.cube_cube_math_op(c1, op) + + def test_div_scalar__int(self): + c1 = self.build_lazy_cube([1, 2], dtype=np.int64) + scalar = 5 + op = operator.truediv + self.cube_scalar_math_op(c1, scalar, op, commutative=False) + + +class Test_lazy_maths__scalar_cube(tests.IrisTest): + def build_lazy_cube(self, value, dtype=np.float64): + data = as_lazy_data(np.array(value, dtype=dtype)) + return iris.cube.Cube(data, standard_name='air_temperature', units='K') + + def setUp(self): + self.c1 = self.build_lazy_cube(3) + self.c2 = self.build_lazy_cube(4) + self.c3 = self.build_lazy_cube(3, dtype=np.int64) + self.c4 = self.build_lazy_cube(4, dtype=np.int64) + + def check_common(self, c1, c2, math_op): + cube = math_op(c1, c2) + data = cube.data + self.assertTrue(isinstance(data, np.ndarray)) + self.assertEqual(data.shape, ()) + + def test_add_scalar__int(self): + c3, c4, op = self.c3, 5, operator.add + self.check_common(c3, c4, op) + + def test_add_cubes__int(self): + c3, c4, op = self.c3, self.c4, operator.add + self.check_common(c3, c4, op) + + def test_mul_scalar__int(self): + c3, c4, op = self.c3, 5, operator.mul + self.check_common(c3, c4, op) + + def test_mul_cubes__int(self): + c3, c4, op = self.c3, self.c4, operator.mul + self.check_common(c3, c4, op) + + def test_sub_scalar__int(self): + c3, c4, op = self.c3, 5, operator.sub + self.check_common(c3, c4, op) + + def test_sub_cubes__int(self): + c3, c4, op = self.c3, self.c4, operator.sub + self.check_common(c3, c4, op) + + def test_div_scalar__int(self): + c3, c4, op = self.c3, 5, operator.truediv + self.check_common(c3, c4, op) + + def test_div_cubes__int(self): + c3, c4, op = self.c3, self.c4, operator.truediv + self.check_common(c3, c4, op) + + def test_add_scalar__float(self): + c1, c2, op = self.c1, 5, operator.add + self.check_common(c1, c2, op) + + def test_add_cubes__float(self): + c1, c2, op = self.c1, self.c2, operator.add + self.check_common(c1, c2, op) + + def test_mul_scalar__float(self): + c1, c2, op = self.c1, 5, operator.mul + self.check_common(c1, c2, op) + + def test_mul_cubes__float(self): + c1, c2, op = self.c1, self.c2, operator.mul + self.check_common(c1, c2, op) + + def test_sub_scalar__float(self): + c1, c2, op = self.c1, 5, operator.sub + self.check_common(c1, c2, op) + + def test_sub_cubes__float(self): + c1, c2, op = self.c1, self.c2, operator.sub + self.check_common(c1, c2, op) + + def test_div_scalar__float(self): + c1, c2, op = self.c1, 5, operator.truediv + self.check_common(c1, c2, op) + + def test_div_cubes__float(self): + c1, c2, op = self.c1, self.c2, operator.truediv + self.check_common(c1, c2, op) + + +class Test_lazy_maths__masked_data(tests.IrisTest): + def build_lazy_cube(self, dtype=np.float64): + data = ma.array([[1., 1.], [1., 100000.]], + mask=[[0, 0], [0, 1]], + dtype=dtype) + data = as_lazy_data(data) + cube = iris.cube.Cube(data, standard_name='air_temperature', units='K') + lat = DimCoord([-10, 10], 'latitude') + lon = DimCoord([10, 20], 'longitude') + cube.add_dim_coord(lat, 0) + cube.add_dim_coord(lon, 1) + return cube + + def test_subtract__float(self): + cube_a = self.build_lazy_cube() + cube_b = self.build_lazy_cube() + cube_c = cube_a - cube_b + self.assertTrue(ma.isMaskedArray(cube_c.data)) + + def test_subtract__int(self): + cube_a = self.build_lazy_cube(dtype=np.int64) + cube_b = self.build_lazy_cube(dtype=np.int64) + cube_c = cube_a - cube_b + self.assertTrue(ma.isMaskedArray(cube_c.data)) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/data_manager/__init__.py b/lib/iris/tests/unit/data_manager/__init__.py new file mode 100644 index 0000000000..0ecab252fb --- /dev/null +++ b/lib/iris/tests/unit/data_manager/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris._data_manager` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/data_manager/test_DataManager.py b/lib/iris/tests/unit/data_manager/test_DataManager.py new file mode 100644 index 0000000000..a0f500dc11 --- /dev/null +++ b/lib/iris/tests/unit/data_manager/test_DataManager.py @@ -0,0 +1,612 @@ +# (C) British Crown Copyright 2017 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the :class:`iris._data_manager.DataManager`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import copy +import numpy as np +import numpy.ma as ma +import six + +from iris._data_manager import DataManager +from iris._lazy_data import as_lazy_data +from iris.tests import mock + + +class Test___copy__(tests.IrisTest): + def test(self): + dm = DataManager(np.array(0)) + emsg = 'Shallow-copy of {!r} is not permitted.' + name = type(dm).__name__ + with self.assertRaisesRegexp(copy.Error, emsg.format(name)): + copy.copy(dm) + + +class Test___deepcopy__(tests.IrisTest): + def test(self): + dm = DataManager(np.array(0)) + method = 'iris._data_manager.DataManager._deepcopy' + return_value = mock.sentinel.return_value + with mock.patch(method) as mocker: + mocker.return_value = return_value + result = copy.deepcopy(dm) + self.assertEqual(mocker.call_count, 1) + [args], kwargs = mocker.call_args + self.assertEqual(kwargs, dict()) + self.assertEqual(len(args), 2) + expected = [return_value, [dm]] + for item in six.itervalues(args): + self.assertIn(item, expected) + self.assertIs(result, return_value) + + +class Test___eq__(tests.IrisTest): + def setUp(self): + self.shape = (2, 3, 4) + self.size = np.prod(self.shape) + self.real_array = np.arange(self.size, dtype=float).reshape(self.shape) + + def test_real_with_real(self): + dm1 = DataManager(self.real_array) + dm2 = DataManager(self.real_array.copy()) + self.assertEqual(dm1, dm2) + + def test_real_with_real_failure(self): + dm1 = DataManager(self.real_array) + dm2 = DataManager(np.ones(self.shape)) + self.assertFalse(dm1 == dm2) + + def test_real_with_real__dtype_failure(self): + dm1 = DataManager(self.real_array) + dm2 = DataManager(self.real_array.astype(int)) + self.assertFalse(dm1 == dm2) + + def test_real_with_lazy_failure(self): + dm1 = DataManager(self.real_array) + dm2 = DataManager(as_lazy_data(self.real_array)) + self.assertFalse(dm1 == dm2) + self.assertFalse(dm2 == dm1) + + def test_lazy_with_lazy(self): + dm1 = DataManager(as_lazy_data(self.real_array)) + dm2 = DataManager(as_lazy_data(self.real_array)) + self.assertEqual(dm1, dm2) + + def test_lazy_with_lazy_failure(self): + dm1 = DataManager(as_lazy_data(self.real_array)) + dm2 = DataManager(as_lazy_data(self.real_array) * 10) + self.assertFalse(dm1 == dm2) + + def test_lazy_with_lazy__dtype_failure(self): + dm1 = DataManager(as_lazy_data(self.real_array)) + dm2 = DataManager(as_lazy_data(self.real_array).astype(int)) + self.assertFalse(dm1 == dm2) + + def test_non_DataManager_failure(self): + dm = DataManager(np.array(0)) + self.assertFalse(dm == 0) + + +class Test___ne__(tests.IrisTest): + def setUp(self): + self.shape = (2, 3, 4) + self.size = np.prod(self.shape) + self.real_array = np.arange(self.size, dtype=float).reshape(self.shape) + + def test_real_with_real(self): + dm1 = DataManager(self.real_array) + dm2 = DataManager(np.ones(self.shape)) + self.assertNotEqual(dm1, dm2) + + def test_real_with_real_failure(self): + dm1 = DataManager(self.real_array) + dm2 = DataManager(self.real_array.copy()) + self.assertFalse(dm1 != dm2) + + def test_real_with_real__dtype(self): + dm1 = DataManager(self.real_array) + dm2 = DataManager(self.real_array.astype(int)) + self.assertNotEqual(dm1, dm2) + + def test_real_with_lazy(self): + dm1 = DataManager(self.real_array) + dm2 = DataManager(as_lazy_data(self.real_array)) + self.assertNotEqual(dm1, dm2) + self.assertNotEqual(dm2, dm1) + + def test_lazy_with_lazy(self): + dm1 = DataManager(as_lazy_data(self.real_array)) + dm2 = DataManager(as_lazy_data(self.real_array) * 10) + self.assertNotEqual(dm1, dm2) + + def test_lazy_with_lazy_failure(self): + dm1 = DataManager(as_lazy_data(self.real_array)) + dm2 = DataManager(as_lazy_data(self.real_array)) + self.assertFalse(dm1 != dm2) + + def test_lazy_with_lazy__dtype(self): + dm1 = DataManager(as_lazy_data(self.real_array)) + dm2 = DataManager(as_lazy_data(self.real_array).astype(int)) + self.assertNotEqual(dm1, dm2) + + def test_non_DataManager(self): + dm = DataManager(np.array(0)) + self.assertNotEqual(dm, 0) + + +class Test___repr__(tests.IrisTest): + def setUp(self): + self.real_array = np.array(123) + masked_array = ma.array([0, 1], mask=[0, 1]) + self.lazy_array = as_lazy_data(masked_array) + self.name = DataManager.__name__ + + def test_real(self): + dm = DataManager(self.real_array) + result = repr(dm) + expected = '{}({!r})'.format(self.name, self.real_array) + self.assertEqual(result, expected) + + def test_lazy(self): + dm = DataManager(self.lazy_array) + result = repr(dm) + expected = '{}({!r})'.format(self.name, self.lazy_array) + self.assertEqual(result, expected) + + +class Test__assert_axioms(tests.IrisTest): + def setUp(self): + self.real_array = np.array(0) + self.lazy_array = as_lazy_data(self.real_array) + self.dm = DataManager(self.real_array) + + def test_array_none(self): + self.dm._real_array = None + emsg = 'Unexpected data state, got no lazy and no real data' + with self.assertRaisesRegexp(AssertionError, emsg): + self.dm._assert_axioms() + + def test_array_all(self): + self.dm._lazy_array = self.lazy_array + emsg = 'Unexpected data state, got lazy and real data' + with self.assertRaisesRegexp(AssertionError, emsg): + self.dm._assert_axioms() + + +class Test__deepcopy(tests.IrisTest): + def setUp(self): + self.shape = (2, 3, 4) + self.size = np.prod(self.shape) + self.real_array = np.arange(self.size, dtype=float).reshape(self.shape) + self.memo = dict() + + def test_real(self): + dm = DataManager(self.real_array) + result = dm._deepcopy(self.memo) + self.assertEqual(dm, result) + + def test_lazy(self): + dm = DataManager(as_lazy_data(self.real_array)) + result = dm._deepcopy(self.memo) + self.assertEqual(dm, result) + + def test_real_with_real(self): + dm = DataManager(self.real_array) + data = self.real_array.copy() * 10 + result = dm._deepcopy(self.memo, data=data) + expected = DataManager(data) + self.assertEqual(result, expected) + self.assertIs(result._real_array, data) + + def test_real_with_lazy(self): + dm = DataManager(self.real_array) + data = as_lazy_data(self.real_array) * 10 + result = dm._deepcopy(self.memo, data=data) + expected = DataManager(data) + self.assertEqual(result, expected) + self.assertIs(result._lazy_array, data) + + def test_lazy_with_real(self): + dm = DataManager(as_lazy_data(self.real_array)) + data = self.real_array.copy() * 10 + result = dm._deepcopy(self.memo, data=data) + expected = DataManager(data) + self.assertEqual(result, expected) + self.assertIs(result._real_array, data) + + def test_lazy_with_lazy(self): + dm = DataManager(as_lazy_data(self.real_array)) + data = as_lazy_data(self.real_array) * 10 + result = dm._deepcopy(self.memo, data=data) + expected = DataManager(data) + self.assertEqual(result, expected) + self.assertIs(result._lazy_array, data) + + def test_real_with_real_failure(self): + dm = DataManager(self.real_array) + emsg = 'Cannot copy' + with self.assertRaisesRegexp(ValueError, emsg): + dm._deepcopy(self.memo, data=np.array(0)) + + def test_real_with_lazy_failure(self): + dm = DataManager(self.real_array) + emsg = 'Cannot copy' + with self.assertRaisesRegexp(ValueError, emsg): + dm._deepcopy(self.memo, data=as_lazy_data(np.array(0))) + + def test_lazy_with_real_failure(self): + dm = DataManager(as_lazy_data(self.real_array)) + emsg = 'Cannot copy' + with self.assertRaisesRegexp(ValueError, emsg): + dm._deepcopy(self.memo, data=np.array(0)) + + def test_lazy_with_lazy_failure(self): + dm = DataManager(as_lazy_data(self.real_array)) + emsg = 'Cannot copy' + with self.assertRaisesRegexp(ValueError, emsg): + dm._deepcopy(self.memo, data=as_lazy_data(np.array(0))) + + +class Test_data__getter(tests.IrisTest): + def setUp(self): + shape = (2, 3, 4) + size = np.prod(shape) + self.real_array = np.arange(size).reshape(shape) + self.lazy_array = as_lazy_data(self.real_array) + self.mask_array = ma.masked_array(self.real_array) + self.mask_array_masked = self.mask_array.copy() + self.mask_array_masked[0, 0, 0] = ma.masked + self.dtype = self.mask_array.dtype + self.fill_value = self.mask_array.fill_value + self.lazy_mask_array = as_lazy_data(self.mask_array) + self.lazy_mask_array_masked = as_lazy_data(self.mask_array_masked) + + def test_with_real_array(self): + dm = DataManager(self.real_array) + self.assertFalse(dm.has_lazy_data()) + result = dm.data + self.assertFalse(dm.has_lazy_data()) + self.assertIs(result, self.real_array) + + def test_with_lazy_array(self): + dm = DataManager(self.lazy_array) + self.assertTrue(dm.has_lazy_data()) + result = dm.data + self.assertFalse(dm.has_lazy_data()) + self.assertArrayEqual(result, self.real_array) + + def test_with_lazy_mask_array__not_masked(self): + dm = DataManager(self.lazy_mask_array) + self.assertTrue(dm.has_lazy_data()) + result = dm.data + self.assertFalse(dm.has_lazy_data()) + self.assertIsInstance(result, np.core.ndarray) + self.assertEqual(dm.dtype, self.dtype) + self.assertEqual(result.fill_value, self.fill_value) + self.assertArrayEqual(result, self.real_array) + + def test_with_lazy_mask_array__masked(self): + dm = DataManager(self.lazy_mask_array_masked) + self.assertTrue(dm.has_lazy_data()) + result = dm.data + self.assertFalse(dm.has_lazy_data()) + self.assertIsInstance(result, ma.MaskedArray) + self.assertEqual(dm.dtype, self.dtype) + self.assertEqual(result.fill_value, self.fill_value) + self.assertArrayEqual(result, self.mask_array_masked) + + def test_with_real_masked_constant(self): + masked_data = ma.masked_array([666], mask=True, dtype=np.dtype('f8')) + masked_constant = masked_data[0] + dm = DataManager(masked_constant) + result = dm.data + self.assertFalse(dm.has_lazy_data()) + self.assertIsInstance(result, ma.MaskedArray) + self.assertNotIsInstance(result, ma.core.MaskedConstant) + self.assertMaskedArrayEqual(result, masked_data) + + def test_with_lazy_masked_constant(self): + masked_data = ma.masked_array([666], mask=True) + masked_constant = masked_data[0] + lazy_masked_constant = as_lazy_data(masked_constant) + dm = DataManager(lazy_masked_constant) + result = dm.data + self.assertFalse(dm.has_lazy_data()) + self.assertIsInstance(result, ma.MaskedArray) + self.assertNotIsInstance(result, ma.core.MaskedConstant) + self.assertMaskedArrayEqual(result, masked_data) + + +class Test_data__setter(tests.IrisTest): + def test_zero_ndim_real_with_scalar_int(self): + value = 456 + dm = DataManager(np.array(123)) + self.assertFalse(dm.has_lazy_data()) + dm.data = value + self.assertFalse(dm.has_lazy_data()) + self.assertArrayEqual(dm.data, np.array(value)) + + def test_zero_ndim_real_with_scalar_float(self): + value = 456.0 + dm = DataManager(np.array(123)) + self.assertFalse(dm.has_lazy_data()) + dm.data = value + self.assertFalse(dm.has_lazy_data()) + self.assertArrayEqual(dm.data, np.array(value)) + + def test_zero_ndim_real_with_zero_ndim_real(self): + real_array = np.array(456) + dm = DataManager(np.array(123)) + self.assertFalse(dm.has_lazy_data()) + dm.data = real_array + self.assertFalse(dm.has_lazy_data()) + self.assertArrayEqual(dm.data, real_array) + + def test_zero_ndim_real_with_zero_ndim_lazy(self): + lazy_array = as_lazy_data(np.array(456)) + dm = DataManager(np.array(123)) + self.assertFalse(dm.has_lazy_data()) + dm.data = lazy_array + self.assertTrue(dm.has_lazy_data()) + self.assertArrayEqual(dm.data, lazy_array.compute()) + + def test_zero_ndim_lazy_with_zero_ndim_real(self): + real_array = np.array(456) + dm = DataManager(as_lazy_data(np.array(123))) + self.assertTrue(dm.has_lazy_data()) + dm.data = real_array + self.assertFalse(dm.has_lazy_data()) + self.assertArrayEqual(dm.data, real_array) + + def test_zero_ndim_lazy_with_zero_ndim_lazy(self): + lazy_array = as_lazy_data(np.array(456)) + dm = DataManager(as_lazy_data(np.array(123))) + self.assertTrue(dm.has_lazy_data()) + dm.data = lazy_array + self.assertTrue(dm.has_lazy_data()) + self.assertArrayEqual(dm.data, lazy_array.compute()) + + def test_zero_ndim_real_to_scalar_1d_real_promote(self): + real_array = np.array([456]) + dm = DataManager(np.array(123)) + self.assertFalse(dm.has_lazy_data()) + dm.data = real_array + self.assertFalse(dm.has_lazy_data()) + self.assertArrayEqual(dm.data, real_array) + + def test_zero_ndim_real_to_scalar_1d_lazy_promote(self): + lazy_array = as_lazy_data(np.array([456])) + dm = DataManager(np.array(123)) + self.assertFalse(dm.has_lazy_data()) + dm.data = lazy_array + self.assertTrue(dm.has_lazy_data()) + self.assertArrayEqual(dm.data, lazy_array.compute()) + + def test_zero_ndim_lazy_to_scalar_1d_real_promote(self): + real_array = np.array([456]) + dm = DataManager(as_lazy_data(np.array(123))) + self.assertTrue(dm.has_lazy_data()) + dm.data = real_array + self.assertFalse(dm.has_lazy_data()) + self.assertArrayEqual(dm.data, real_array) + + def test_zero_ndim_lazy_to_scalar_1d_lazy_promote(self): + lazy_array = as_lazy_data(np.array([456])) + dm = DataManager(as_lazy_data(np.array(123))) + self.assertTrue(dm.has_lazy_data()) + dm.data = lazy_array + self.assertTrue(dm.has_lazy_data()) + self.assertArrayEqual(dm.data, lazy_array.compute()) + + def test_scalar_1d_to_zero_ndim_fail(self): + dm = DataManager(np.array([123])) + emsg = 'Require data with shape \(1,\), got \(\).' + with self.assertRaisesRegexp(ValueError, emsg): + dm.data = 456 + + def test_nd_real_to_nd_real(self): + shape = (2, 3, 4) + size = np.prod(shape) + real_array = np.arange(size).reshape(shape) + dm = DataManager(real_array * 10) + self.assertFalse(dm.has_lazy_data()) + dm.data = real_array + self.assertFalse(dm.has_lazy_data()) + self.assertArrayEqual(dm.data, real_array) + + def test_nd_real_to_nd_lazy(self): + shape = (2, 3, 4) + size = np.prod(shape) + real_array = np.arange(size).reshape(shape) + lazy_array = as_lazy_data(real_array) * 10 + dm = DataManager(real_array) + self.assertFalse(dm.has_lazy_data()) + dm.data = lazy_array + self.assertTrue(dm.has_lazy_data()) + self.assertArrayEqual(dm.data, lazy_array.compute()) + + def test_nd_lazy_to_nd_real(self): + shape = (2, 3, 4) + size = np.prod(shape) + real_array = np.arange(size).reshape(shape) + lazy_array = as_lazy_data(real_array) + dm = DataManager(lazy_array * 10) + self.assertTrue(dm.has_lazy_data()) + dm.data = real_array + self.assertFalse(dm.has_lazy_data()) + self.assertArrayEqual(dm.data, real_array) + + def test_nd_lazy_to_nd_lazy(self): + shape = (2, 3, 4) + size = np.prod(shape) + real_array = np.arange(size).reshape(shape) + lazy_array = as_lazy_data(real_array) + dm = DataManager(lazy_array * 10) + self.assertTrue(dm.has_lazy_data()) + dm.data = lazy_array + self.assertTrue(dm.has_lazy_data()) + self.assertArrayEqual(dm.data, lazy_array.compute()) + + def test_coerce_to_ndarray(self): + shape = (2, 3) + size = np.prod(shape) + real_array = np.arange(size).reshape(shape) + matrix = np.matrix(real_array) + dm = DataManager(real_array) + dm.data = matrix + self.assertIsInstance(dm._real_array, np.core.ndarray) + self.assertIsInstance(dm.data, np.core.ndarray) + self.assertArrayEqual(dm.data, real_array) + + def test_real_masked_constant_to_array(self): + masked_data = ma.masked_array([666], mask=True, dtype=np.dtype('f8')) + masked_constant = masked_data[0] + dm = DataManager(masked_constant) + self.assertIsInstance(dm._real_array, ma.MaskedArray) + self.assertNotIsInstance(dm._real_array, ma.core.MaskedConstant) + self.assertIsInstance(dm.data, ma.MaskedArray) + self.assertNotIsInstance(dm.data, ma.core.MaskedConstant) + self.assertMaskedArrayEqual(dm.data, masked_data) + + +class Test_dtype(tests.IrisTest): + def setUp(self): + self.real_array = np.array(0, dtype=np.dtype('int64')) + self.lazy_array = as_lazy_data(np.array(0, dtype=np.dtype('float64'))) + + def test_real_array(self): + dm = DataManager(self.real_array) + self.assertEqual(dm.dtype, np.dtype('int64')) + + def test_lazy_array(self): + dm = DataManager(self.lazy_array) + self.assertEqual(dm.dtype, np.dtype('float64')) + + +class Test_ndim(tests.IrisTest): + def test_ndim_0(self): + real_array = np.array(0) + dm = DataManager(real_array) + self.assertEqual(dm.ndim, 0) + lazy_array = as_lazy_data(real_array) + dm = DataManager(lazy_array) + self.assertEqual(dm.ndim, 0) + + def test_ndim_nd(self): + shape = (2, 3, 4) + real_array = np.arange(24).reshape(shape) + dm = DataManager(real_array) + self.assertEqual(dm.ndim, len(shape)) + lazy_array = as_lazy_data(real_array) + dm = DataManager(lazy_array) + self.assertEqual(dm.ndim, len(shape)) + + +class Test_shape(tests.IrisTest): + def test_shape_scalar(self): + real_array = np.array(0) + dm = DataManager(real_array) + self.assertEqual(dm.shape, ()) + lazy_array = as_lazy_data(real_array) + dm = DataManager(lazy_array) + self.assertEqual(dm.shape, ()) + + def test_shape_nd(self): + shape = (2, 3, 4) + real_array = np.arange(24).reshape(shape) + dm = DataManager(real_array) + self.assertEqual(dm.shape, shape) + lazy_array = as_lazy_data(real_array) + dm = DataManager(lazy_array) + self.assertEqual(dm.shape, shape) + + +class Test_copy(tests.IrisTest): + def setUp(self): + self.method = 'iris._data_manager.DataManager._deepcopy' + self.data = mock.sentinel.data + self.return_value = mock.sentinel.return_value + self.memo = {} + + def test(self): + dm = DataManager(np.array(0)) + kwargs = dict(data=self.data) + with mock.patch(self.method) as mocker: + mocker.return_value = self.return_value + result = dm.copy(data=self.data) + mocker.assert_called_once_with(self.memo, **kwargs) + self.assertIs(result, self.return_value) + + +class Test_core_data(tests.IrisTest): + def test_real_array(self): + real_array = np.array(0) + dm = DataManager(real_array) + self.assertIs(dm.core_data(), real_array) + + def test_lazy_array(self): + lazy_array = as_lazy_data(np.array(0)) + dm = DataManager(lazy_array) + self.assertIs(dm.core_data(), lazy_array) + + +class Test_has_lazy_data(tests.IrisTest): + def setUp(self): + self.real_array = np.array(0) + self.lazy_array = as_lazy_data(self.real_array) + + def test_with_lazy_array(self): + dm = DataManager(self.lazy_array) + self.assertTrue(dm.has_lazy_data()) + + def test_with_real_array(self): + dm = DataManager(self.real_array) + self.assertFalse(dm.has_lazy_data()) + + +class Test_lazy_data(tests.IrisTest): + def setUp(self): + self.real_array = np.array(0) + self.lazy_array = as_lazy_data(self.real_array) + + def test_with_real_array(self): + dm = DataManager(self.real_array) + self.assertFalse(dm.has_lazy_data()) + result = dm.lazy_data() + self.assertFalse(dm.has_lazy_data()) + self.assertEqual(result, self.lazy_array) + self.assertFalse(dm.has_lazy_data()) + + def test_with_lazy_array(self): + dm = DataManager(self.lazy_array) + self.assertTrue(dm.has_lazy_data()) + result = dm.lazy_data() + self.assertTrue(dm.has_lazy_data()) + self.assertIs(result, dm._lazy_array) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/experimental/__init__.py b/lib/iris/tests/unit/experimental/__init__.py index d29d4170e7..25b2d4a6ac 100644 --- a/lib/iris/tests/unit/experimental/__init__.py +++ b/lib/iris/tests/unit/experimental/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Unit tests for the :mod:`iris.experimental` package.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/experimental/equalise_cubes/__init__.py b/lib/iris/tests/unit/experimental/equalise_cubes/__init__.py index 09a709a4b6..ef318b2023 100644 --- a/lib/iris/tests/unit/experimental/equalise_cubes/__init__.py +++ b/lib/iris/tests/unit/experimental/equalise_cubes/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Unit tests for the `iris.experimental.equalise_cubes` package.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/experimental/equalise_cubes/test_equalise_attributes.py b/lib/iris/tests/unit/experimental/equalise_cubes/test_equalise_attributes.py index edc3710f08..00cd7b743e 100644 --- a/lib/iris/tests/unit/experimental/equalise_cubes/test_equalise_attributes.py +++ b/lib/iris/tests/unit/experimental/equalise_cubes/test_equalise_attributes.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -20,6 +20,9 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised # before importing anything else. import iris.tests as tests @@ -132,12 +135,14 @@ def test_array_same(self): cubes = [self.cube_a1b5v1, self.cube_a1b6v1] self._test(cubes, {'a': 1, 'v': self.v1}) + @tests.skip_data def test_complex_nonecommon(self): # Example with cell methods and factories, but no common attributes. cubes = [iris.tests.stock.global_pp(), iris.tests.stock.hybrid_height()] self._test(cubes, {}) + @tests.skip_data def test_complex_somecommon(self): # Example with cell methods and factories, plus some common attributes. cubes = [iris.tests.stock.global_pp(), iris.tests.stock.simple_pp()] diff --git a/lib/iris/tests/unit/experimental/raster/__init__.py b/lib/iris/tests/unit/experimental/raster/__init__.py index b41a305d1f..5532dda673 100644 --- a/lib/iris/tests/unit/experimental/raster/__init__.py +++ b/lib/iris/tests/unit/experimental/raster/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Unit tests for the :mod:`iris.experimental.raster` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/experimental/raster/test_export_geotiff.py b/lib/iris/tests/unit/experimental/raster/test_export_geotiff.py index ac85e47acb..c467dddff3 100644 --- a/lib/iris/tests/unit/experimental/raster/test_export_geotiff.py +++ b/lib/iris/tests/unit/experimental/raster/test_export_geotiff.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2016, Met Office # # This file is part of Iris. # @@ -16,27 +16,35 @@ # along with Iris. If not, see . """Unit tests for the `iris.experimental.raster.export_geotiff` function.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests import numpy as np -from osgeo import gdal +import re +try: + from osgeo import gdal + from iris.experimental.raster import export_geotiff +except ImportError: + gdal = None from iris.coord_systems import GeogCS from iris.coords import DimCoord from iris.cube import Cube -from iris.experimental.raster import export_geotiff +@tests.skip_gdal class TestDtypeAndValues(tests.IrisTest): def _cube(self, dtype): data = np.arange(12).reshape(3, 4).astype(dtype) + 20 cube = Cube(data, 'air_pressure_anomaly') - coord = DimCoord(range(3), 'latitude', units='degrees') + coord = DimCoord(np.arange(3), 'latitude', units='degrees') coord.guess_bounds() cube.add_dim_coord(coord, 0) - coord = DimCoord(range(4), 'longitude', units='degrees') + coord = DimCoord(np.arange(4), 'longitude', units='degrees') coord.guess_bounds() cube.add_dim_coord(coord, 1) return cube @@ -96,15 +104,16 @@ def test_invalid(self): export_geotiff(cube, temp_filename) +@tests.skip_gdal class TestProjection(tests.IrisTest): def _cube(self, ellipsoid=None): data = np.arange(12).reshape(3, 4).astype('u1') cube = Cube(data, 'air_pressure_anomaly') - coord = DimCoord(range(3), 'latitude', units='degrees', + coord = DimCoord(np.arange(3), 'latitude', units='degrees', coord_system=ellipsoid) coord.guess_bounds() cube.add_dim_coord(coord, 0) - coord = DimCoord(range(4), 'longitude', units='degrees', + coord = DimCoord(np.arange(4), 'longitude', units='degrees', coord_system=ellipsoid) coord.guess_bounds() cube.add_dim_coord(coord, 1) @@ -122,24 +131,39 @@ def test_sphere(self): with self.temp_filename('.tif') as temp_filename: export_geotiff(cube, temp_filename) dataset = gdal.Open(temp_filename, gdal.GA_ReadOnly) - self.assertEqual( - dataset.GetProjection(), - 'GEOGCS["unnamed ellipse",DATUM["unknown",' - 'SPHEROID["unnamed",6377000,0]],PRIMEM["Greenwich",0],' - 'UNIT["degree",0.0174532925199433]]') + projection_string = dataset.GetProjection() + # String has embedded floating point values, + # Test with values to N decimal places, using a regular expression. + re_pattern = ( + r'GEOGCS\["unnamed ellipse",DATUM\["unknown",' + r'SPHEROID\["unnamed",637....,0\]\],PRIMEM\["Greenwich",0\],' + r'UNIT\["degree",0.01745[0-9]*\]\]') + re_exp = re.compile(re_pattern) + self.assertIsNotNone( + re_exp.match(projection_string), + 'projection string {!r} does not match {!r}'.format( + projection_string, re_pattern)) def test_ellipsoid(self): cube = self._cube(GeogCS(6377000, 6360000)) with self.temp_filename('.tif') as temp_filename: export_geotiff(cube, temp_filename) dataset = gdal.Open(temp_filename, gdal.GA_ReadOnly) - self.assertEqual( - dataset.GetProjection(), - 'GEOGCS["unnamed ellipse",DATUM["unknown",' - 'SPHEROID["unnamed",6377000,375.117647058816]],' - 'PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]]') - - + projection_string = dataset.GetProjection() + # String has embedded floating point values, + # Test with values to N decimal places, using a regular expression. + re_pattern = ( + r'GEOGCS\["unnamed ellipse",DATUM\["unknown",' + r'SPHEROID\["unnamed",637....,375.117[0-9]*\]\],' + r'PRIMEM\["Greenwich",0\],UNIT\["degree",0.01745[0-9]*\]\]') + re_exp = re.compile(re_pattern) + self.assertIsNotNone( + re_exp.match(projection_string), + 'projection string {!r} does not match {!r}'.format( + projection_string, re_pattern)) + + +@tests.skip_gdal class TestGeoTransform(tests.IrisTest): def test_(self): data = np.arange(12).reshape(3, 4).astype(np.uint8) diff --git a/lib/iris/tests/unit/experimental/regrid/__init__.py b/lib/iris/tests/unit/experimental/regrid/__init__.py new file mode 100644 index 0000000000..2ba5c78a6e --- /dev/null +++ b/lib/iris/tests/unit/experimental/regrid/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.experimental.regrid` package.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/experimental/regrid/test_PointInCell.py b/lib/iris/tests/unit/experimental/regrid/test_PointInCell.py new file mode 100644 index 0000000000..17be3845ec --- /dev/null +++ b/lib/iris/tests/unit/experimental/regrid/test_PointInCell.py @@ -0,0 +1,46 @@ +# (C) British Crown Copyright 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for :class:`iris.experimental.regrid.PointInCell`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.experimental.regrid import PointInCell +from iris.tests import mock + + +class Test_regridder(tests.IrisTest): + def test(self): + point_in_cell = PointInCell(mock.sentinel.weights) + + with mock.patch('iris.experimental.regrid._CurvilinearRegridder', + return_value=mock.sentinel.regridder) as ecr: + regridder = point_in_cell.regridder(mock.sentinel.src, + mock.sentinel.target) + + ecr.assert_called_once_with(mock.sentinel.src, + mock.sentinel.target, + mock.sentinel.weights) + self.assertIs(regridder, mock.sentinel.regridder) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/experimental/regrid/test__CurvilinearRegridder.py b/lib/iris/tests/unit/experimental/regrid/test__CurvilinearRegridder.py new file mode 100644 index 0000000000..99dd0c483b --- /dev/null +++ b/lib/iris/tests/unit/experimental/regrid/test__CurvilinearRegridder.py @@ -0,0 +1,297 @@ +# (C) British Crown Copyright 2015 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for :class:`iris.experimental.regrid._CurvilinearRegridder`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.analysis.cartography import rotate_pole +from iris.cube import Cube +from iris.coords import AuxCoord, DimCoord +from iris.coord_systems import GeogCS, RotatedGeogCS +from iris.fileformats.pp import EARTH_RADIUS +from iris.experimental.regrid import _CurvilinearRegridder as Regridder +from iris.tests import mock +from iris.tests.stock import global_pp, lat_lon_cube + + +RESULT_DIR = ('analysis', 'regrid') + + +class Test___init__(tests.IrisTest): + def setUp(self): + self.src_grid = lat_lon_cube() + self.bad = np.ones((3, 4)) + self.weights = np.ones(self.src_grid.shape, self.src_grid.dtype) + + def test_bad_src_type(self): + with self.assertRaisesRegexp(TypeError, "'src_grid_cube'"): + Regridder(self.bad, self.src_grid, self.weights) + + def test_bad_grid_type(self): + with self.assertRaisesRegexp(TypeError, "'target_grid_cube'"): + Regridder(self.src_grid, self.bad, self.weights) + + +@tests.skip_data +class Test___call__(tests.IrisTest): + def setUp(self): + self.func_setup = ( + 'iris.experimental.regrid.' + '_regrid_weighted_curvilinear_to_rectilinear__prepare') + self.func_operate = ( + 'iris.experimental.regrid.' + '_regrid_weighted_curvilinear_to_rectilinear__perform') + # Define a test source grid and target grid, basically the same. + self.src_grid = global_pp() + self.tgt_grid = global_pp() + # Modify the names so we can tell them apart. + self.src_grid.rename('src_grid') + self.tgt_grid.rename('TARGET_GRID') + # Replace the source-grid x and y coords with equivalent 2d versions. + x_coord = self.src_grid.coord('longitude') + y_coord = self.src_grid.coord('latitude') + nx, = x_coord.shape + ny, = y_coord.shape + xx, yy = np.meshgrid(x_coord.points, y_coord.points) + self.src_grid.remove_coord(x_coord) + self.src_grid.remove_coord(y_coord) + x_coord_2d = AuxCoord(xx, + standard_name=x_coord.standard_name, + units=x_coord.units, + coord_system=x_coord.coord_system) + y_coord_2d = AuxCoord(yy, + standard_name=y_coord.standard_name, + units=y_coord.units, + coord_system=y_coord.coord_system) + self.src_grid.add_aux_coord(x_coord_2d, (0, 1)) + self.src_grid.add_aux_coord(y_coord_2d, (0, 1)) + self.weights = np.ones(self.src_grid.shape, self.src_grid.dtype) + # Define an actual, dummy cube for the internal partial result, so we + # can do a cubelist merge on it, which is too complicated to mock out. + self.dummy_slice_result = Cube([1]) + + def test_same_src_as_init(self): + # Check the regridder call calls the underlying routines as expected. + src_grid = self.src_grid + target_grid = self.tgt_grid + regridder = Regridder(src_grid, target_grid, self.weights) + with mock.patch(self.func_setup, + return_value=mock.sentinel.regrid_info) as patch_setup: + with mock.patch( + self.func_operate, + return_value=self.dummy_slice_result) as patch_operate: + result = regridder(src_grid) + patch_setup.assert_called_once_with( + src_grid, self.weights, target_grid) + patch_operate.assert_called_once_with( + src_grid, mock.sentinel.regrid_info) + # The result is a re-merged version of the internal result, so it is + # therefore '==' but not the same object. + self.assertEqual(result, self.dummy_slice_result) + + def test_no_weights(self): + # Check we can use the regridder without weights. + src_grid = self.src_grid + target_grid = self.tgt_grid + regridder = Regridder(src_grid, target_grid) + with mock.patch(self.func_setup, + return_value=mock.sentinel.regrid_info) as patch_setup: + with mock.patch( + self.func_operate, + return_value=self.dummy_slice_result) as patch_operate: + result = regridder(src_grid) + patch_setup.assert_called_once_with( + src_grid, None, target_grid) + + def test_diff_src_from_init(self): + # Check we can call the regridder with a different cube from the one we + # built it with. + src_grid = self.src_grid + target_grid = self.tgt_grid + regridder = Regridder(src_grid, target_grid, self.weights) + # Provide a "different" cube for the actual regrid. + different_src_cube = self.src_grid.copy() + # Rename so we can distinguish them. + different_src_cube.rename('Different_source') + with mock.patch(self.func_setup, + return_value=mock.sentinel.regrid_info) as patch_setup: + with mock.patch( + self.func_operate, + return_value=self.dummy_slice_result) as patch_operate: + result = regridder(different_src_cube) + patch_operate.assert_called_once_with( + different_src_cube, mock.sentinel.regrid_info) + + def test_caching(self): + # Check that it calculates regrid info just once, and re-uses it in + # subsequent calls. + src_grid = self.src_grid + target_grid = self.tgt_grid + regridder = Regridder(src_grid, target_grid, self.weights) + different_src_cube = self.src_grid.copy() + different_src_cube.rename('Different_source') + with mock.patch(self.func_setup, + return_value=mock.sentinel.regrid_info) as patch_setup: + with mock.patch( + self.func_operate, + return_value=self.dummy_slice_result) as patch_operate: + result1 = regridder(src_grid) + result2 = regridder(different_src_cube) + patch_setup.assert_called_once_with( + src_grid, self.weights, target_grid) + self.assertEqual(len(patch_operate.call_args_list), 2) + self.assertEqual( + patch_operate.call_args_list, + [mock.call(src_grid, mock.sentinel.regrid_info), + mock.call(different_src_cube, mock.sentinel.regrid_info)]) + + +@tests.skip_data +class Test___call____bad_src(tests.IrisTest): + def setUp(self): + self.src_grid = global_pp() + y = self.src_grid.coord('latitude') + x = self.src_grid.coord('longitude') + self.src_grid.remove_coord('latitude') + self.src_grid.remove_coord('longitude') + self.src_grid.add_aux_coord(y, 0) + self.src_grid.add_aux_coord(x, 1) + weights = np.ones(self.src_grid.shape, self.src_grid.dtype) + self.regridder = Regridder(self.src_grid, self.src_grid, weights) + + def test_bad_src_type(self): + with self.assertRaisesRegexp(TypeError, 'must be a Cube'): + self.regridder(np.ones((3, 4))) + + def test_bad_src_shape(self): + with self.assertRaisesRegexp(ValueError, + 'not defined on the same source grid'): + self.regridder(self.src_grid[::2, ::2]) + + +class Test__call__multidimensional(tests.IrisTest): + def test_multidim(self): + # Testing with >2D data to demonstrate correct operation over + # additional non-XY dimensions (including data masking), which is + # handled by the PointInCell wrapper class. + + # Define a simple target grid first, in plain latlon coordinates. + plain_latlon_cs = GeogCS(EARTH_RADIUS) + grid_x_coord = DimCoord(points=[15.0, 25.0, 35.0], + bounds=[[10.0, 20.0], + [20.0, 30.0], + [30.0, 40.0]], + standard_name='longitude', + units='degrees', + coord_system=plain_latlon_cs) + grid_y_coord = DimCoord(points=[-30.0, -50.0], + bounds=[[-20.0, -40.0], [-40.0, -60.0]], + standard_name='latitude', + units='degrees', + coord_system=plain_latlon_cs) + grid_cube = Cube(np.zeros((2, 3))) + grid_cube.add_dim_coord(grid_y_coord, 0) + grid_cube.add_dim_coord(grid_x_coord, 1) + + # Define some key points in true-lat/lon thta have known positions + # First 3x2 points in the centre of each output cell. + x_centres, y_centres = np.meshgrid(grid_x_coord.points, + grid_y_coord.points) + # An extra point also falling in cell 1, 1 + x_in11, y_in11 = 26.3, -48.2 + # An extra point completely outside the target grid + x_out, y_out = 70.0, -40.0 + + # Define a rotated coord system for the source data + pole_lon, pole_lat = -125.3, 53.4 + src_cs = RotatedGeogCS(grid_north_pole_latitude=pole_lat, + grid_north_pole_longitude=pole_lon, + ellipsoid=plain_latlon_cs) + + # Concatenate all the testpoints in a flat array, and find the rotated + # equivalents. + xx = list(x_centres.flat[:]) + [x_in11, x_out] + yy = list(y_centres.flat[:]) + [y_in11, y_out] + xx, yy = rotate_pole(lons=np.array(xx), + lats=np.array(yy), + pole_lon=pole_lon, + pole_lat=pole_lat) + # Define handy index numbers for all these. + i00, i01, i02, i10, i11, i12, i_in, i_out = range(8) + + # Build test data in the shape Z,YX = (3, 8) + data = [[1, 2, 3, 11, 12, 13, 7, 99], + [1, 2, 3, 11, 12, 13, 7, 99], + [7, 6, 5, 51, 52, 53, 12, 1]] + mask = [[0, 0, 0, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0, 1, 0], + [0, 0, 0, 0, 0, 0, 0, 0]] + src_data = np.ma.array(data, mask=mask, dtype=float) + + # Make the source cube. + src_cube = Cube(src_data) + src_x = AuxCoord(xx, + standard_name='grid_longitude', + units='degrees', + coord_system=src_cs) + src_y = AuxCoord(yy, + standard_name='grid_latitude', + units='degrees', + coord_system=src_cs) + src_z = DimCoord(np.arange(3), long_name='z') + src_cube.add_dim_coord(src_z, 0) + src_cube.add_aux_coord(src_x, 1) + src_cube.add_aux_coord(src_y, 1) + # Add in some extra metadata, to ensure it gets copied over. + src_cube.add_aux_coord(DimCoord([0], long_name='extra_scalar_coord')) + src_cube.attributes['extra_attr'] = 12.3 + + # Define what the expected answers should be, shaped (3, 2, 3). + expected_result = [ + [[1.0, 2.0, 3.0], + [11.0, 0.5 * (12 + 7), 13.0]], + [[1.0, -999, 3.0], + [11.0, 12.0, 13.0]], + [[7.0, 6.0, 5.0], + [51.0, 0.5 * (52 + 12), 53.0]], + ] + expected_result = np.ma.masked_less(expected_result, 0) + + # Perform the calculation with the regridder. + regridder = Regridder(src_cube, grid_cube) + + # Check all is as expected. + result = regridder(src_cube) + self.assertEqual(result.coord('z'), src_cube.coord('z')) + self.assertEqual(result.coord('extra_scalar_coord'), + src_cube.coord('extra_scalar_coord')) + self.assertEqual(result.coord('longitude'), + grid_cube.coord('longitude')) + self.assertEqual(result.coord('latitude'), + grid_cube.coord('latitude')) + self.assertMaskedArrayAlmostEqual(result.data, expected_result) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/experimental/regrid/test_regrid_area_weighted_rectilinear_src_and_grid.py b/lib/iris/tests/unit/experimental/regrid/test_regrid_area_weighted_rectilinear_src_and_grid.py new file mode 100644 index 0000000000..dbddf0468a --- /dev/null +++ b/lib/iris/tests/unit/experimental/regrid/test_regrid_area_weighted_rectilinear_src_and_grid.py @@ -0,0 +1,186 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test function +:func:`iris.experimental.regrid.regrid_area_weighted_rectilinear_src_and_grid`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import numpy as np +import numpy.ma as ma + +from iris.coords import DimCoord +from iris.coord_systems import GeogCS +from iris.cube import Cube +from iris.experimental.regrid \ + import regrid_area_weighted_rectilinear_src_and_grid as regrid +from iris.tests.experimental.regrid.\ + test_regrid_area_weighted_rectilinear_src_and_grid import \ + _resampled_grid + + +class TestMdtol(tests.IrisTest): + # Tests to check the masking behaviour controlled by mdtol kwarg. + def setUp(self): + # A (3, 2, 4) cube with a masked element. + cube = Cube(np.ma.arange(24, dtype=np.int32).reshape((3, 2, 4))) + cs = GeogCS(6371229) + coord = DimCoord(points=np.array([-1, 0, 1], dtype=np.int32), + standard_name='latitude', + units='degrees', + coord_system=cs) + cube.add_dim_coord(coord, 0) + coord = DimCoord(points=np.array([-1, 0, 1, 2], dtype=np.int32), + standard_name='longitude', + units='degrees', + coord_system=cs) + cube.add_dim_coord(coord, 2) + cube.coord('latitude').guess_bounds() + cube.coord('longitude').guess_bounds() + cube.data[1, 1, 2] = ma.masked + self.src_cube = cube + # Create (7, 2, 9) grid cube. + self.grid_cube = _resampled_grid(cube, 2.3, 2.4) + + def test_default(self): + res = regrid(self.src_cube, self.grid_cube) + expected_mask = np.zeros((7, 2, 9), bool) + expected_mask[2:5, 1, 4:7] = True + self.assertArrayEqual(res.data.mask, expected_mask) + + def test_zero(self): + res = regrid(self.src_cube, self.grid_cube, mdtol=0) + expected_mask = np.zeros((7, 2, 9), bool) + expected_mask[2:5, 1, 4:7] = True + self.assertArrayEqual(res.data.mask, expected_mask) + + def test_one(self): + res = regrid(self.src_cube, self.grid_cube, mdtol=1) + expected_mask = np.zeros((7, 2, 9), bool) + # Only a single cell has all contributing cells masked. + expected_mask[3, 1, 5] = True + self.assertArrayEqual(res.data.mask, expected_mask) + + def test_fraction_below_min(self): + # Cells in target grid that overlap with the masked src cell + # have the following fractions (approx. due to spherical area). + # 4 5 6 7 + # 2 ---------------------- + # | 0.33 | 0.66 | 0.50 | + # 3 ---------------------- + # | 0.33 | 1.00 | 0.75 | + # 4 ---------------------- + # | 0.33 | 0.66 | 0.50 | + # 5 ---------------------- + # + + # Threshold less than minimum fraction. + mdtol = 0.2 + res = regrid(self.src_cube, self.grid_cube, mdtol=mdtol) + expected_mask = np.zeros((7, 2, 9), bool) + expected_mask[2:5, 1, 4:7] = True + self.assertArrayEqual(res.data.mask, expected_mask) + + def test_fraction_between_min_and_max(self): + # Threshold between min and max fraction. See + # test_fraction_below_min() comment for picture showing + # the fractions of masked data. + mdtol = 0.6 + res = regrid(self.src_cube, self.grid_cube, mdtol=mdtol) + expected_mask = np.zeros((7, 2, 9), bool) + expected_mask[2:5, 1, 5] = True + expected_mask[3, 1, 6] = True + self.assertArrayEqual(res.data.mask, expected_mask) + + def test_src_not_masked_array(self): + self.src_cube.data = self.src_cube.data.filled(1.0) + res = regrid(self.src_cube, self.grid_cube, mdtol=0.9) + self.assertFalse(ma.isMaskedArray(res.data)) + + def test_boolean_mask(self): + self.src_cube.data = np.ma.arange(24).reshape(3, 2, 4) + res = regrid(self.src_cube, self.grid_cube, mdtol=0.9) + self.assertEqual(ma.count_masked(res.data), 0) + + def test_scalar_no_overlap(self): + # Slice src so result collapses to a scalar. + src_cube = self.src_cube[:, 1, :] + # Regrid to a single cell with no overlap with masked src cells. + grid_cube = self.grid_cube[2, 1, 3] + res = regrid(src_cube, grid_cube, mdtol=0.8) + self.assertFalse(ma.isMaskedArray(res.data)) + + def test_scalar_with_overlap_below_mdtol(self): + # Slice src so result collapses to a scalar. + src_cube = self.src_cube[:, 1, :] + # Regrid to a single cell with 50% overlap with masked src cells. + grid_cube = self.grid_cube[3, 1, 4] + # Set threshold (mdtol) to greater than 0.5 (50%). + res = regrid(src_cube, grid_cube, mdtol=0.6) + self.assertEqual(ma.count_masked(res.data), 0) + + def test_scalar_with_overlap_above_mdtol(self): + # Slice src so result collapses to a scalar. + src_cube = self.src_cube[:, 1, :] + # Regrid to a single cell with 50% overlap with masked src cells. + grid_cube = self.grid_cube[3, 1, 4] + # Set threshold (mdtol) to less than 0.5 (50%). + res = regrid(src_cube, grid_cube, mdtol=0.4) + self.assertEqual(ma.count_masked(res.data), 1) + + +class TestWrapAround(tests.IrisTest): + def test_float_tolerant_equality(self): + # Ensure that floating point numbers are treated appropriately when + # introducing precision difference from wrap_around. + source = Cube([[1]]) + cs = GeogCS(6371229) + + bounds = np.array([[-91, 0]], dtype='float') + points = bounds.mean(axis=1) + lon_coord = DimCoord(points, bounds=bounds, standard_name='longitude', + units='degrees', coord_system=cs) + source.add_aux_coord(lon_coord, 1) + + bounds = np.array([[-90, 90]], dtype='float') + points = bounds.mean(axis=1) + lat_coord = DimCoord(points, bounds=bounds, standard_name='latitude', + units='degrees', coord_system=cs) + source.add_aux_coord(lat_coord, 0) + + grid = Cube([[0]]) + bounds = np.array([[270, 360]], dtype='float') + points = bounds.mean(axis=1) + lon_coord = DimCoord(points, bounds=bounds, standard_name='longitude', + units='degrees', coord_system=cs) + grid.add_aux_coord(lon_coord, 1) + grid.add_aux_coord(lat_coord, 0) + + res = regrid(source, grid) + # The result should be equal to the source data and NOT be masked. + self.assertArrayEqual(res.data, np.array([1.0])) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/experimental/regrid/test_regrid_weighted_curvilinear_to_rectilinear.py b/lib/iris/tests/unit/experimental/regrid/test_regrid_weighted_curvilinear_to_rectilinear.py index 1732124bd7..b2b2c86cf8 100644 --- a/lib/iris/tests/unit/experimental/regrid/test_regrid_weighted_curvilinear_to_rectilinear.py +++ b/lib/iris/tests/unit/experimental/regrid/test_regrid_weighted_curvilinear_to_rectilinear.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -16,10 +16,13 @@ # along with Iris. If not, see . """ Test function -:func:`iris.experimental.regrid_weighted_curvilinear_to_rectilinear`. +:func:`iris.experimental.regrid.regrid_weighted_curvilinear_to_rectilinear`. """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised before # importing anything else import iris.tests as tests @@ -31,81 +34,109 @@ import iris import iris.coords +from iris.coords import AuxCoord, DimCoord +from iris.coord_systems import GeogCS, LambertConformal +from iris.fileformats.pp import EARTH_RADIUS import iris.cube from iris.experimental.regrid \ import regrid_weighted_curvilinear_to_rectilinear as regrid +PLAIN_LATLON_CS = GeogCS(EARTH_RADIUS) + + class Test(tests.IrisTest): def setUp(self): # Source cube. - data = ma.arange(1, 13, dtype=np.float).reshape(3, 4) - attributes = dict(wibble='wobble') - bibble = iris.coords.DimCoord([1], long_name='bibble') - self.src = iris.cube.Cube(data, - standard_name='air_temperature', - units='K', - aux_coords_and_dims=[(bibble, None)], - attributes=attributes) + self.test_src_name = 'air_temperature' + self.test_src_units = 'K' + self.test_src_data = ma.arange(1, 13, dtype=np.float).reshape(3, 4) + self.test_src_attributes = dict(wibble='wobble') + self.test_scalar_coord = iris.coords.DimCoord( + [1], long_name='test_scalar_coord') + self.src = iris.cube.Cube( + self.test_src_data, + standard_name=self.test_src_name, + units=self.test_src_units, + aux_coords_and_dims=[(self.test_scalar_coord, None)], + attributes=self.test_src_attributes) # Source cube x-coordinates. - points = np.array([[010, 020, 200, 220], + points = np.array([[10, 20, 200, 220], [110, 120, 180, 185], [190, 203, 211, 220]]) - self.src_x_positive = iris.coords.AuxCoord(points, - standard_name='longitude', - units='degrees') - self.src_x_transpose = iris.coords.AuxCoord(points.T, - standard_name='longitude', - units='degrees') + self.src_x_positive = iris.coords.AuxCoord( + points, + standard_name='longitude', + units='degrees', + coord_system=PLAIN_LATLON_CS) + self.src_x_transpose = iris.coords.AuxCoord( + points.T, + standard_name='longitude', + units='degrees', + coord_system=PLAIN_LATLON_CS) points = np.array([[-180, -176, -170, -150], [-180, -179, -178, -177], [-170, -168, -159, -140]]) - self.src_x_negative = iris.coords.AuxCoord(points, - standard_name='longitude', - units='degrees') + self.src_x_negative = iris.coords.AuxCoord( + points, + standard_name='longitude', + units='degrees', + coord_system=PLAIN_LATLON_CS) # Source cube y-coordinates. - points = np.array([[00, 04, 03, 01], - [05, 07, 10, 06], + points = np.array([[0, 4, 3, 1], + [5, 7, 10, 6], [12, 20, 15, 30]]) - self.src_y = iris.coords.AuxCoord(points, - standard_name='latitude', - units='degrees') - self.src_y_transpose = iris.coords.AuxCoord(points.T, - standard_name='latitude', - units='degrees') + self.src_y = iris.coords.AuxCoord( + points, + standard_name='latitude', + units='degrees', + coord_system=PLAIN_LATLON_CS) + self.src_y_transpose = iris.coords.AuxCoord( + points.T, + standard_name='latitude', + units='degrees', + coord_system=PLAIN_LATLON_CS) # Weights. self.weight_factor = 10 - self.weights = np.asarray(data) * self.weight_factor + self.weights = np.asarray(self.test_src_data) * self.weight_factor # Target grid cube. self.grid = iris.cube.Cube(np.zeros((2, 2))) # Target grid cube x-coordinates. - self.grid_x_inc = iris.coords.DimCoord([187, 200], - standard_name='longitude', - units='degrees', - bounds=[[180, 190], - [190, 220]]) - self.grid_x_dec = iris.coords.DimCoord([200, 187], - standard_name='longitude', - units='degrees', - bounds=[[220, 190], - [190, 180]]) + self.grid_x_inc = iris.coords.DimCoord( + [187, 200], + standard_name='longitude', + units='degrees', + bounds=[[180, 190], + [190, 220]], + coord_system=PLAIN_LATLON_CS) + self.grid_x_dec = iris.coords.DimCoord( + [200, 187], + standard_name='longitude', + units='degrees', + bounds=[[220, 190], + [190, 180]], + coord_system=PLAIN_LATLON_CS) # Target grid cube y-coordinates. - self.grid_y_inc = iris.coords.DimCoord([2, 10], - standard_name='latitude', - units='degrees', - bounds=[[0, 5], - [5, 30]]) - self.grid_y_dec = iris.coords.DimCoord([10, 2], - standard_name='latitude', - units='degrees', - bounds=[[30, 5], - [5, 0]]) + self.grid_y_inc = iris.coords.DimCoord( + [2, 10], + standard_name='latitude', + units='degrees', + bounds=[[0, 5], + [5, 30]], + coord_system=PLAIN_LATLON_CS) + self.grid_y_dec = iris.coords.DimCoord( + [10, 2], + standard_name='latitude', + units='degrees', + bounds=[[30, 5], + [5, 0]], + coord_system=PLAIN_LATLON_CS) def _weighted_mean(self, points): points = np.asarray(points, dtype=np.float) @@ -118,13 +149,13 @@ def _weighted_mean(self, points): def _expected_cube(self, data): cube = iris.cube.Cube(data) - cube.metadata = copy.deepcopy(self.src) - grid_x = self.grid.coord('longitude') - grid_y = self.grid.coord('latitude') + cube.metadata = copy.deepcopy(self.src.metadata) + grid_x = self.grid.coord(axis='x') + grid_y = self.grid.coord(axis='y') cube.add_dim_coord(grid_x.copy(), self.grid.coord_dims(grid_x)) cube.add_dim_coord(grid_y.copy(), self.grid.coord_dims(grid_y)) - src_x = self.src.coord('longitude') - src_y = self.src.coord('latitude') + src_x = self.src.coord(axis='x') + src_y = self.src.coord(axis='y') for coord in self.src.aux_coords: if coord is not src_x and coord is not src_y: if not self.src.coord_dims(coord): @@ -146,64 +177,103 @@ def test_aligned_src_x(self): mask = np.array([[True, False], [False, False]]) self.assertArrayEqual(result.data.mask, mask) - def test_aligned_src_x_mask(self): - self.src.add_aux_coord(self.src_y, (0, 1)) - self.src.add_aux_coord(self.src_x_positive, (0, 1)) - self.src.data[([1, 2, 2], [3, 0, 2])] = ma.masked - self.grid.add_dim_coord(self.grid_y_inc, 0) - self.grid.add_dim_coord(self.grid_x_inc, 1) + def test_non_latlon(self): + odd_coord_system = LambertConformal() + co_src_y = AuxCoord(self.src_y.points, + standard_name='projection_y_coordinate', + units='km', + coord_system=odd_coord_system) + co_src_x = AuxCoord(self.src_x_positive.points, + standard_name='projection_x_coordinate', + units='km', + coord_system=odd_coord_system) + co_grid_y = DimCoord(self.grid_y_inc.points, + bounds=self.grid_y_inc.bounds, + standard_name='projection_y_coordinate', + units='km', + coord_system=odd_coord_system) + co_grid_x = DimCoord(self.grid_x_inc.points, + bounds=self.grid_x_inc.bounds, + standard_name='projection_x_coordinate', + units='km', + coord_system=odd_coord_system) + self.src.add_aux_coord(co_src_y, (0, 1)) + self.src.add_aux_coord(co_src_x, (0, 1)) + self.grid.add_dim_coord(co_grid_y, 0) + self.grid.add_dim_coord(co_grid_x, 1) result = regrid(self.src, self.weights, self.grid) data = np.array([0, self._weighted_mean([3]), - self._weighted_mean([7]), - self._weighted_mean([10])]).reshape(2, 2) + self._weighted_mean([7, 8]), + self._weighted_mean([9, 10, 11])]).reshape(2, 2) expected = self._expected_cube(data) self.assertEqual(result, expected) mask = np.array([[True, False], [False, False]]) self.assertArrayEqual(result.data.mask, mask) - def test_aligned_src_x_zero_weights(self): - self.src.add_aux_coord(self.src_y, (0, 1)) - self.src.add_aux_coord(self.src_x_positive, (0, 1)) + def test_src_xy_not_2d(self): + new_shape = (2, 2, 3) + # Reshape the source cube, including the X and Y coordinates, + # from (3, 4) to (2, 2, 3). + # This is really an "invalid" reshape, but should still work because + # the XY shape is actually irrelevant to the regrid operation. + src = iris.cube.Cube( + self.test_src_data.reshape(new_shape), + standard_name=self.test_src_name, + units=self.test_src_units, + aux_coords_and_dims=[(self.test_scalar_coord, None)], + attributes=self.test_src_attributes) + co_src_y = self.src_y.copy( + points=self.src_y.points.reshape(new_shape)) + co_src_x = self.src_x_positive.copy( + points=self.src_x_positive.points.reshape(new_shape)) + src.add_aux_coord(co_src_y, (0, 1, 2)) + src.add_aux_coord(co_src_x, (0, 1, 2)) self.grid.add_dim_coord(self.grid_y_inc, 0) self.grid.add_dim_coord(self.grid_x_inc, 1) - self.weights[:, 2] = 0 - self.weights[1, :] = 0 - result = regrid(self.src, self.weights, self.grid) - data = np.array([0, 0, 0, self._weighted_mean([9, 10])]).reshape(2, 2) + weights = self.weights.reshape(new_shape) + result = regrid(src, weights, self.grid) + # NOTE: set the grid of self.src to make '_expected_cube' work ... + self.src.add_aux_coord(self.src_y, (0, 1)) + self.src.add_aux_coord(self.src_x_positive, (0, 1)) + # ... given that, we expect exactly the same 'normal' result. + data = np.array([0, + self._weighted_mean([3]), + self._weighted_mean([7, 8]), + self._weighted_mean([9, 10, 11])]).reshape(2, 2) expected = self._expected_cube(data) self.assertEqual(result, expected) - mask = np.array([[True, True], [True, False]]) + mask = np.array([[True, False], [False, False]]) self.assertArrayEqual(result.data.mask, mask) - def test_aligned_src_x_transpose(self): + def test_aligned_src_x_mask(self): self.src.add_aux_coord(self.src_y, (0, 1)) - self.src.add_aux_coord(self.src_x_transpose, (1, 0)) + self.src.add_aux_coord(self.src_x_positive, (0, 1)) + self.src.data[([1, 2, 2], [3, 0, 2])] = ma.masked self.grid.add_dim_coord(self.grid_y_inc, 0) self.grid.add_dim_coord(self.grid_x_inc, 1) result = regrid(self.src, self.weights, self.grid) data = np.array([0, self._weighted_mean([3]), - self._weighted_mean([7, 8]), - self._weighted_mean([9, 10, 11])]).reshape(2, 2) + self._weighted_mean([7]), + self._weighted_mean([10])]).reshape(2, 2) expected = self._expected_cube(data) self.assertEqual(result, expected) mask = np.array([[True, False], [False, False]]) self.assertArrayEqual(result.data.mask, mask) - def test_aligned_src_y_transpose(self): - self.src.add_aux_coord(self.src_y_transpose, (1, 0)) + def test_aligned_src_x_zero_weights(self): + self.src.add_aux_coord(self.src_y, (0, 1)) self.src.add_aux_coord(self.src_x_positive, (0, 1)) self.grid.add_dim_coord(self.grid_y_inc, 0) self.grid.add_dim_coord(self.grid_x_inc, 1) + self.weights[:, 2] = 0 + self.weights[1, :] = 0 result = regrid(self.src, self.weights, self.grid) - data = np.array([0, - self._weighted_mean([3]), - self._weighted_mean([7, 8]), - self._weighted_mean([9, 10, 11])]).reshape(2, 2) + data = np.array([0, 0, 0, self._weighted_mean([9, 10])]).reshape(2, 2) expected = self._expected_cube(data) self.assertEqual(result, expected) - mask = np.array([[True, False], [False, False]]) + mask = np.array([[True, True], [True, False]]) self.assertArrayEqual(result.data.mask, mask) def test_aligned_tgt_dec(self): diff --git a/lib/iris/tests/unit/experimental/representation/test_CubeRepresentation.py b/lib/iris/tests/unit/experimental/representation/test_CubeRepresentation.py new file mode 100644 index 0000000000..c94742a49a --- /dev/null +++ b/lib/iris/tests/unit/experimental/representation/test_CubeRepresentation.py @@ -0,0 +1,331 @@ +# (C) British Crown Copyright 2017 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.cube.CubeRepresentation` class.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.coords import CellMethod +import iris.tests.stock as stock + +from iris.experimental.representation import CubeRepresentation + + +@tests.skip_data +class Test__instantiation(tests.IrisTest): + def setUp(self): + self.cube = stock.simple_3d() + self.representer = CubeRepresentation(self.cube) + + def test_cube_attributes(self): + self.assertEqual(id(self.cube), self.representer.cube_id) + self.assertStringEqual(str(self.cube), self.representer.cube_str) + + def test__heading_contents(self): + content = set(self.representer.str_headings.values()) + self.assertEqual(len(content), 1) + self.assertIsNone(list(content)[0]) + + +@tests.skip_data +class Test__get_dim_names(tests.IrisTest): + def setUp(self): + self.cube = stock.realistic_4d() + self.dim_names = [c.name() for c in self.cube.coords(dim_coords=True)] + self.representer = CubeRepresentation(self.cube) + + def test_basic(self): + result_names = self.representer._get_dim_names() + self.assertEqual(result_names, self.dim_names) + + def test_one_anonymous_dim(self): + self.cube.remove_coord('time') + expected_names = ['--'] + expected_names.extend(self.dim_names[1:]) + result_names = self.representer._get_dim_names() + self.assertEqual(result_names, expected_names) + + def test_anonymous_dims(self): + target_dims = [1, 3] + # Replicate this here as we're about to modify it. + expected_names = [c.name() for c in self.cube.coords(dim_coords=True)] + for dim in target_dims: + this_dim_coord, = self.cube.coords(contains_dimension=dim, + dim_coords=True) + self.cube.remove_coord(this_dim_coord) + expected_names[dim] = '--' + result_names = self.representer._get_dim_names() + self.assertEqual(result_names, expected_names) + + +@tests.skip_data +class Test__summary_content(tests.IrisTest): + def setUp(self): + self.cube = stock.lat_lon_cube() + # Check we're not tripped up by names containing spaces. + self.cube.rename('Electron density') + self.cube.units = '1e11 e/m^3' + self.representer = CubeRepresentation(self.cube) + + def test_name(self): + # Check the cube name is being set and formatted correctly. + expected = self.cube.name().replace('_', ' ').title() + result = self.representer.name + self.assertEqual(expected, result) + + def test_names(self): + # Check the dimension names used as column headings are split out and + # formatted correctly. + expected_coord_names = [c.name().replace('_', ' ') + for c in self.cube.coords(dim_coords=True)] + result_coord_names = self.representer.names[1:] + for result in result_coord_names: + self.assertIn(result, expected_coord_names) + + def test_units(self): + # Check the units is being set correctly. + expected = self.cube.units + result = self.representer.units + self.assertEqual(expected, result) + + def test_shapes(self): + # Check cube dim lengths are split out correctly from the + # summary string. + expected = self.cube.shape + result = self.representer.shapes + self.assertEqual(expected, result) + + def test_ndims(self): + expected = self.cube.ndim + result = self.representer.ndims + self.assertEqual(expected, result) + + +@tests.skip_data +class Test__get_bits(tests.IrisTest): + def setUp(self): + self.cube = stock.realistic_4d() + cm = CellMethod('mean', 'time', '6hr') + self.cube.add_cell_method(cm) + self.representer = CubeRepresentation(self.cube) + self.representer._get_bits(self.representer._get_lines()) + + def test_population(self): + for v in self.representer.str_headings.values(): + self.assertIsNotNone(v) + + def test_headings__dimcoords(self): + contents = self.representer.str_headings['Dimension coordinates:'] + content_str = ','.join(content for content in contents) + dim_coords = [c.name() for c in self.cube.dim_coords] + for coord in dim_coords: + self.assertIn(coord, content_str) + + def test_headings__auxcoords(self): + contents = self.representer.str_headings['Auxiliary coordinates:'] + content_str = ','.join(content for content in contents) + aux_coords = [c.name() for c in self.cube.aux_coords + if c.shape != (1,)] + for coord in aux_coords: + self.assertIn(coord, content_str) + + def test_headings__derivedcoords(self): + contents = self.representer.str_headings['Auxiliary coordinates:'] + content_str = ','.join(content for content in contents) + derived_coords = [c.name() for c in self.cube.derived_coords] + for coord in derived_coords: + self.assertIn(coord, content_str) + + def test_headings__scalarcoords(self): + contents = self.representer.str_headings['Scalar coordinates:'] + content_str = ','.join(content for content in contents) + scalar_coords = [c.name() for c in self.cube.coords() + if c.shape == (1,)] + for coord in scalar_coords: + self.assertIn(coord, content_str) + + def test_headings__attributes(self): + contents = self.representer.str_headings['Attributes:'] + content_str = ','.join(content for content in contents) + for attr_name, attr_value in self.cube.attributes.items(): + self.assertIn(attr_name, content_str) + self.assertIn(attr_value, content_str) + + def test_headings__cellmethods(self): + contents = self.representer.str_headings['Cell methods:'] + content_str = ','.join(content for content in contents) + for cell_method in self.cube.cell_methods: + self.assertIn(str(cell_method), content_str) + + +@tests.skip_data +class Test__make_header(tests.IrisTest): + def setUp(self): + self.cube = stock.simple_3d() + self.representer = CubeRepresentation(self.cube) + self.representer._get_bits(self.representer._get_lines()) + self.header_emts = self.representer._make_header().split('\n') + + def test_name_and_units(self): + # Check the correct name and units are being written into the top-left + # table cell. + # This is found in the first cell after the `` is defined. + name_and_units_cell = self.header_emts[1] + expected = '{name} ({units})'.format(name=self.cube.name(), + units=self.cube.units) + self.assertIn(expected.lower(), name_and_units_cell.lower()) + + def test_number_of_columns(self): + # There should be one headings column, plus a column per dimension. + # Ignore opening and closing tags. + result_cols = self.header_emts[1:-1] + expected = self.cube.ndim + 1 + self.assertEqual(len(result_cols), expected) + + def test_row_headings(self): + # Get only the dimension heading cells and not the headings column. + dim_coord_names = [c.name() for c in self.cube.coords(dim_coords=True)] + dim_col_headings = self.header_emts[2:-1] + for coord_name, col_heading in zip(dim_coord_names, dim_col_headings): + self.assertIn(coord_name, col_heading) + + +@tests.skip_data +class Test__make_shapes_row(tests.IrisTest): + def setUp(self): + self.cube = stock.simple_3d() + self.representer = CubeRepresentation(self.cube) + self.representer._get_bits(self.representer._get_lines()) + self.result = self.representer._make_shapes_row().split('\n') + + def test_row_title(self): + title_cell = self.result[1] + self.assertIn('Shape', title_cell) + + def test_shapes(self): + expected_shapes = self.cube.shape + result_shapes = self.result[2:-1] + for expected, result in zip(expected_shapes, result_shapes): + self.assertIn(str(expected), result) + + +@tests.skip_data +class Test__make_row(tests.IrisTest): + def setUp(self): + self.cube = stock.simple_3d() + cm = CellMethod('mean', 'time', '6hr') + self.cube.add_cell_method(cm) + self.representer = CubeRepresentation(self.cube) + self.representer._get_bits(self.representer._get_lines()) + + def test__title_row(self): + title = 'Wibble:' + row = self.representer._make_row(title) + # A cell for the title, an empty cell for each cube dimension, plus row + # opening and closing tags. + expected_len = self.cube.ndim + 3 + self.assertEqual(len(row), expected_len) + # Check for specific content. + row_str = '\n'.join(element for element in row) + self.assertIn(title.strip(':'), row_str) + expected_html_class = 'iris-title' + self.assertIn(expected_html_class, row_str) + + def test__inclusion_row(self): + # An inclusion row has x/- to indicate whether a coordinate describes + # a dimension. + title = 'time' + body = ['x', '-', '-', '-'] + row = self.representer._make_row(title, body) + # A cell for the title, a cell for each cube dimension, plus row + # opening and closing tags. + expected_len = len(body) + 3 + self.assertEqual(len(row), expected_len) + # Check for specific content. + row_str = '\n'.join(element for element in row) + self.assertIn(title, row_str) + self.assertIn('x', row_str) + self.assertIn('-', row_str) + expected_html_class_1 = 'iris-word-cell' + expected_html_class_2 = 'iris-inclusion-cell' + self.assertIn(expected_html_class_1, row_str) + self.assertIn(expected_html_class_2, row_str) + # We do not expect a colspan to be set. + self.assertNotIn('colspan', row_str) + + def test__attribute_row(self): + # An attribute row does not contain inclusion indicators. + title = 'source' + body = 'Iris test case' + colspan = 5 + row = self.representer._make_row(title, body, colspan) + # We only expect two cells here: the row title cell and one other cell + # that spans a number of columns. We also need to open and close the + # tr html element, giving 4 bits making up the row. + self.assertEqual(len(row), 4) + # Check for specific content. + row_str = '\n'.join(element for element in row) + self.assertIn(title, row_str) + self.assertIn(body, row_str) + # We expect a colspan to be set. + colspan_str = 'colspan="{}"'.format(colspan) + self.assertIn(colspan_str, row_str) + + +@tests.skip_data +class Test__make_content(tests.IrisTest): + def setUp(self): + self.cube = stock.simple_3d() + self.representer = CubeRepresentation(self.cube) + self.representer._get_bits(self.representer._get_lines()) + self.result = self.representer._make_content() + + def test_included(self): + included = 'Dimension coordinates' + self.assertIn(included, self.result) + dim_coord_names = [c.name() for c in self.cube.dim_coords] + for coord_name in dim_coord_names: + self.assertIn(coord_name, self.result) + + def test_not_included(self): + # `stock.simple_3d()` only contains the `Dimension coordinates` attr. + not_included = list(self.representer.str_headings.keys()) + not_included.pop(not_included.index('Dimension coordinates:')) + for heading in not_included: + self.assertNotIn(heading, self.result) + + +@tests.skip_data +class Test_repr_html(tests.IrisTest): + def setUp(self): + self.cube = stock.simple_3d() + representer = CubeRepresentation(self.cube) + self.result = representer.repr_html() + + def test_contents_added(self): + included = 'Dimension coordinates' + self.assertIn(included, self.result) + not_included = 'Auxiliary coordinates' + self.assertNotIn(not_included, self.result) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/experimental/stratify/__init__.py b/lib/iris/tests/unit/experimental/stratify/__init__.py new file mode 100644 index 0000000000..f9ff55f539 --- /dev/null +++ b/lib/iris/tests/unit/experimental/stratify/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.experimental.stratify` package.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/experimental/stratify/test_relevel.py b/lib/iris/tests/unit/experimental/stratify/test_relevel.py new file mode 100644 index 0000000000..417dcda60d --- /dev/null +++ b/lib/iris/tests/unit/experimental/stratify/test_relevel.py @@ -0,0 +1,140 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the :func:`iris.experimental.stratify.relevel` function. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from functools import partial + +import numpy as np +from numpy.testing import assert_array_equal + +import iris +from iris.coords import AuxCoord, DimCoord +import iris.tests.stock as stock + +try: + import stratify + from iris.experimental.stratify import relevel +except ImportError: + stratify = None + + +@tests.skip_stratify +class Test(tests.IrisTest): + def setUp(self): + cube = stock.simple_3d()[:, :1, :1] + #: The data from which to get the levels. + self.src_levels = cube.copy() + #: The data to interpolate. + self.cube = cube.copy() + self.cube.rename('foobar') + self.cube *= 10 + self.coord = self.src_levels.coord('wibble') + self.axes = (self.coord, self.coord.name(), None, 0) + + def test_broadcast_fail_src_levels(self): + emsg = 'Cannot broadcast the cube and src_levels' + data = np.arange(60).reshape(3, 4, 5) + with self.assertRaisesRegexp(ValueError, emsg): + relevel(self.cube, AuxCoord(data), [1, 2, 3]) + + def test_broadcast_fail_tgt_levels(self): + emsg = 'Cannot broadcast the cube and tgt_levels' + data = np.arange(60).reshape(3, 4, 5) + with self.assertRaisesRegexp(ValueError, emsg): + relevel(self.cube, self.coord, data) + + def test_standard_input(self): + for axis in self.axes: + result = relevel(self.cube, + self.src_levels, + [-1, 0, 5.5], + axis=axis) + assert_array_equal(result.data.flatten(), + np.array([np.nan, 0, 55])) + expected = DimCoord([-1, 0, 5.5], units=1, long_name='thingness') + self.assertEqual(expected, result.coord('thingness')) + + def test_non_monotonic(self): + for axis in self.axes: + result = relevel(self.cube, + self.src_levels, + [2, 3, 2], + axis=axis) + assert_array_equal(result.data.flatten(), + np.array([20, 30, np.nan])) + expected = AuxCoord([2, 3, 2], units=1, long_name='thingness') + self.assertEqual(result.coord('thingness'), expected) + + def test_static_level(self): + for axis in self.axes: + result = relevel(self.cube, + self.src_levels, + [2, 2], + axis=axis) + assert_array_equal(result.data.flatten(), np.array([20, 20])) + + def test_coord_input(self): + source = AuxCoord(self.src_levels.data) + source.metadata = self.src_levels.metadata + + for axis in self.axes: + result = relevel(self.cube, + source, + [0, 12, 13], + axis=axis) + self.assertEqual(result.shape, (3, 1, 1)) + assert_array_equal(result.data.flatten(), [0, 120, np.nan]) + + def test_custom_interpolator(self): + interpolator = partial(stratify.interpolate, interpolation='nearest') + + for axis in self.axes: + result = relevel(self.cube, + self.src_levels, + [-1, 0, 6.5], + axis=axis, + interpolator=interpolator) + assert_array_equal(result.data.flatten(), + np.array([np.nan, 0, 120])) + + def test_multi_dim_target_levels(self): + interpolator = partial(stratify.interpolate, + interpolation='linear', + extrapolation='linear') + + for axis in self.axes: + result = relevel(self.cube, + self.src_levels, + self.src_levels.data, + axis=axis, + interpolator=interpolator) + assert_array_equal(result.data.flatten(), np.array([0, 120])) + self.assertCML(result) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/__init__.py b/lib/iris/tests/unit/fileformats/__init__.py index 13d895007a..d7cc3b44e7 100644 --- a/lib/iris/tests/unit/fileformats/__init__.py +++ b/lib/iris/tests/unit/fileformats/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,55 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Unit tests for the :mod:`iris.fileformats` package.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import iris.tests as tests + + +class TestField(tests.IrisTest): + def _test_for_coord(self, field, convert, coord_predicate, expected_points, + expected_bounds): + (factories, references, standard_name, long_name, units, + attributes, cell_methods, dim_coords_and_dims, + aux_coords_and_dims) = convert(field) + + # Check for one and only one matching coordinate. + coords_and_dims = dim_coords_and_dims + aux_coords_and_dims + matching_coords = [coord for coord, _ in coords_and_dims if + coord_predicate(coord)] + self.assertEqual(len(matching_coords), 1, str(matching_coords)) + coord = matching_coords[0] + + # Check points and bounds. + if expected_points is not None: + self.assertArrayEqual(coord.points, expected_points) + + if expected_bounds is None: + self.assertIsNone(coord.bounds) + else: + self.assertArrayEqual(coord.bounds, expected_bounds) + + def assertCoordsAndDimsListsMatch(self, coords_and_dims_got, + coords_and_dims_expected): + """ + Check that coords_and_dims lists are equivalent. + + The arguments are lists of pairs of (coordinate, dimensions). + The elements are compared one-to-one, by coordinate name (so the order + of the lists is _not_ significant). + It also checks that the coordinate types (DimCoord/AuxCoord) match. + + """ + def sorted_by_coordname(list): + return sorted(list, key=lambda item: item[0].name()) + + coords_and_dims_got = sorted_by_coordname(coords_and_dims_got) + coords_and_dims_expected = sorted_by_coordname( + coords_and_dims_expected) + self.assertEqual(coords_and_dims_got, coords_and_dims_expected) + # Also check coordinate type equivalences (as Coord.__eq__ does not). + self.assertEqual( + [type(coord) for coord, dims in coords_and_dims_got], + [type(coord) for coord, dims in coords_and_dims_expected]) diff --git a/lib/iris/tests/unit/fileformats/abf/__init__.py b/lib/iris/tests/unit/fileformats/abf/__init__.py index cb6c05114e..e11be995b3 100644 --- a/lib/iris/tests/unit/fileformats/abf/__init__.py +++ b/lib/iris/tests/unit/fileformats/abf/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Unit tests for the :mod:`iris.fileformats.abf` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/abf/test_ABFField.py b/lib/iris/tests/unit/fileformats/abf/test_ABFField.py index 408638acbc..d5aad27932 100644 --- a/lib/iris/tests/unit/fileformats/abf/test_ABFField.py +++ b/lib/iris/tests/unit/fileformats/abf/test_ABFField.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -16,14 +16,15 @@ # along with Iris. If not, see . """Unit tests for the `iris.fileformats.abf.ABFField` class.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import mock -import numpy as np - from iris.fileformats.abf import ABFField +from iris.tests import mock class MethodCounter(object): diff --git a/lib/iris/tests/unit/fileformats/cf/__init__.py b/lib/iris/tests/unit/fileformats/cf/__init__.py new file mode 100644 index 0000000000..c5a6ad4ca2 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/cf/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.fileformats.cf` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/cf/test_CFReader.py b/lib/iris/tests/unit/fileformats/cf/test_CFReader.py new file mode 100644 index 0000000000..033e5ae1f8 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/cf/test_CFReader.py @@ -0,0 +1,307 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the `iris.fileformats.cf.CFReader` class. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +import iris +from iris.fileformats.cf import CFReader +from iris.tests import mock + + +def netcdf_variable(name, dimensions, dtype, ancillary_variables=None, + coordinates='', bounds=None, climatology=None, + formula_terms=None, grid_mapping=None, + cell_measures=None, standard_name=None): + """Return a mock NetCDF4 variable.""" + ndim = 0 + if dimensions is not None: + dimensions = dimensions.split() + ndim = len(dimensions) + else: + dimensions = [] + ncvar = mock.Mock(name=name, dimensions=dimensions, + ncattrs=mock.Mock(return_value=[]), + ndim=ndim, dtype=dtype, + ancillary_variables=ancillary_variables, + coordinates=coordinates, + bounds=bounds, climatology=climatology, + formula_terms=formula_terms, + grid_mapping=grid_mapping, cell_measures=cell_measures, + standard_name=standard_name) + return ncvar + + +class Test_translate__global_attributes(tests.IrisTest): + + def setUp(self): + ncvar = netcdf_variable('ncvar', 'height', np.float) + ncattrs = mock.Mock(return_value=['dimensions']) + getncattr = mock.Mock(return_value='something something_else') + self.dataset = mock.Mock(file_format='NetCDF4', + variables={'ncvar': ncvar}, + ncattrs=ncattrs, + getncattr=getncattr) + + def test_create_global_attributes(self): + with mock.patch('netCDF4.Dataset', return_value=self.dataset): + global_attrs = CFReader('dummy').cf_group.global_attributes + self.assertEqual(global_attrs['dimensions'], + 'something something_else') + + +class Test_translate__formula_terms(tests.IrisTest): + def setUp(self): + self.delta = netcdf_variable('delta', 'height', np.float, + bounds='delta_bnds') + self.delta_bnds = netcdf_variable('delta_bnds', 'height bnds', + np.float) + self.sigma = netcdf_variable('sigma', 'height', np.float, + bounds='sigma_bnds') + self.sigma_bnds = netcdf_variable('sigma_bnds', 'height bnds', + np.float) + self.orography = netcdf_variable('orography', 'lat lon', np.float) + formula_terms = 'a: delta b: sigma orog: orography' + standard_name = 'atmosphere_hybrid_height_coordinate' + self.height = netcdf_variable('height', 'height', np.float, + formula_terms=formula_terms, + bounds='height_bnds', + standard_name=standard_name) + # Over-specify the formula terms on the bounds variable, + # which will be ignored by the cf loader. + formula_terms = 'a: delta_bnds b: sigma_bnds orog: orography' + self.height_bnds = netcdf_variable('height_bnds', 'height bnds', + np.float, + formula_terms=formula_terms) + self.lat = netcdf_variable('lat', 'lat', np.float) + self.lon = netcdf_variable('lon', 'lon', np.float) + # Note that, only lat and lon are explicitly associated as coordinates. + self.temp = netcdf_variable('temp', 'height lat lon', np.float, + coordinates='lat lon') + + self.variables = dict(delta=self.delta, sigma=self.sigma, + orography=self.orography, height=self.height, + lat=self.lat, lon=self.lon, temp=self.temp, + delta_bnds=self.delta_bnds, + sigma_bnds=self.sigma_bnds, + height_bnds=self.height_bnds) + ncattrs = mock.Mock(return_value=[]) + self.dataset = mock.Mock(file_format='NetCDF4', + variables=self.variables, + ncattrs=ncattrs) + # Restrict the CFReader functionality to only performing translations. + build_patch = mock.patch( + 'iris.fileformats.cf.CFReader._build_cf_groups') + reset_patch = mock.patch('iris.fileformats.cf.CFReader._reset') + build_patch.start() + reset_patch.start() + self.addCleanup(build_patch.stop) + self.addCleanup(reset_patch.stop) + + def test_create_formula_terms(self): + with mock.patch('netCDF4.Dataset', return_value=self.dataset): + cf_group = CFReader('dummy').cf_group + self.assertEqual(len(cf_group), len(self.variables)) + # Check there is a singular data variable. + group = cf_group.data_variables + self.assertEqual(len(group), 1) + self.assertEqual(list(group.keys()), ['temp']) + self.assertIs(group['temp'].cf_data, self.temp) + # Check there are three coordinates. + group = cf_group.coordinates + self.assertEqual(len(group), 3) + coordinates = ['height', 'lat', 'lon'] + self.assertEqual(set(group.keys()), set(coordinates)) + for name in coordinates: + self.assertIs(group[name].cf_data, getattr(self, name)) + # Check there are three auxiliary coordinates. + group = cf_group.auxiliary_coordinates + self.assertEqual(len(group), 3) + aux_coordinates = ['delta', 'sigma', 'orography'] + self.assertEqual(set(group.keys()), set(aux_coordinates)) + for name in aux_coordinates: + self.assertIs(group[name].cf_data, getattr(self, name)) + # Check all the auxiliary coordinates are formula terms. + formula_terms = cf_group.formula_terms + self.assertEqual(set(group.items()), set(formula_terms.items())) + # Check there are three bounds. + group = cf_group.bounds + self.assertEqual(len(group), 3) + bounds = ['height_bnds', 'delta_bnds', 'sigma_bnds'] + self.assertEqual(set(group.keys()), set(bounds)) + for name in bounds: + self.assertEqual(group[name].cf_data, getattr(self, name)) + + +class Test_build_cf_groups__formula_terms(tests.IrisTest): + def setUp(self): + self.delta = netcdf_variable('delta', 'height', np.float, + bounds='delta_bnds') + self.delta_bnds = netcdf_variable('delta_bnds', 'height bnds', + np.float) + self.sigma = netcdf_variable('sigma', 'height', np.float, + bounds='sigma_bnds') + self.sigma_bnds = netcdf_variable('sigma_bnds', 'height bnds', + np.float) + self.orography = netcdf_variable('orography', 'lat lon', np.float) + formula_terms = 'a: delta b: sigma orog: orography' + standard_name = 'atmosphere_hybrid_height_coordinate' + self.height = netcdf_variable('height', 'height', np.float, + formula_terms=formula_terms, + bounds='height_bnds', + standard_name=standard_name) + # Over-specify the formula terms on the bounds variable, + # which will be ignored by the cf loader. + formula_terms = 'a: delta_bnds b: sigma_bnds orog: orography' + self.height_bnds = netcdf_variable('height_bnds', 'height bnds', + np.float, + formula_terms=formula_terms) + self.lat = netcdf_variable('lat', 'lat', np.float) + self.lon = netcdf_variable('lon', 'lon', np.float) + self.x = netcdf_variable('x', 'lat lon', np.float) + self.y = netcdf_variable('y', 'lat lon', np.float) + # Note that, only lat and lon are explicitly associated as coordinates. + self.temp = netcdf_variable('temp', 'height lat lon', np.float, + coordinates='x y') + + self.variables = dict(delta=self.delta, sigma=self.sigma, + orography=self.orography, height=self.height, + lat=self.lat, lon=self.lon, temp=self.temp, + delta_bnds=self.delta_bnds, + sigma_bnds=self.sigma_bnds, + height_bnds=self.height_bnds, + x=self.x, y=self.y) + ncattrs = mock.Mock(return_value=[]) + self.dataset = mock.Mock(file_format='NetCDF4', + variables=self.variables, + ncattrs=ncattrs) + # Restrict the CFReader functionality to only performing translations + # and building first level cf-groups for variables. + patcher = mock.patch('iris.fileformats.cf.CFReader._reset') + patcher.start() + self.addCleanup(patcher.stop) + + def test_associate_formula_terms_with_data_variable(self): + with mock.patch('netCDF4.Dataset', return_value=self.dataset): + cf_group = CFReader('dummy').cf_group + self.assertEqual(len(cf_group), len(self.variables)) + # Check the cf-group associated with the data variable. + temp_cf_group = cf_group['temp'].cf_group + # Check the data variable is associated with eight variables. + self.assertEqual(len(temp_cf_group), 8) + # Check there are three coordinates. + group = temp_cf_group.coordinates + self.assertEqual(len(group), 3) + coordinates = ['height', 'lat', 'lon'] + self.assertEqual(set(group.keys()), set(coordinates)) + for name in coordinates: + self.assertIs(group[name].cf_data, getattr(self, name)) + # Check the height coordinate is bounded. + group = group['height'].cf_group + self.assertEqual(len(group.bounds), 1) + self.assertIn('height_bnds', group.bounds) + self.assertIs(group['height_bnds'].cf_data, self.height_bnds) + # Check there are five auxiliary coordinates. + group = temp_cf_group.auxiliary_coordinates + self.assertEqual(len(group), 5) + aux_coordinates = ['delta', 'sigma', 'orography', 'x', 'y'] + self.assertEqual(set(group.keys()), set(aux_coordinates)) + for name in aux_coordinates: + self.assertIs(group[name].cf_data, getattr(self, name)) + # Check all the auxiliary coordinates are formula terms. + formula_terms = cf_group.formula_terms + self.assertTrue( + set(formula_terms.items()).issubset(list(group.items()))) + # Check the terms by root. + for name, term in zip(aux_coordinates, ['a', 'b', 'orog']): + self.assertEqual(formula_terms[name].cf_terms_by_root, + dict(height=term)) + # Check the bounded auxiliary coordinates. + for name, name_bnds in zip(['delta', 'sigma'], + ['delta_bnds', 'sigma_bnds']): + aux_coord_group = group[name].cf_group + self.assertEqual(len(aux_coord_group.bounds), 1) + self.assertIn(name_bnds, aux_coord_group.bounds) + self.assertIs(aux_coord_group[name_bnds].cf_data, + getattr(self, name_bnds)) + + def test_promote_reference(self): + with mock.patch('netCDF4.Dataset', return_value=self.dataset): + cf_group = CFReader('dummy').cf_group + self.assertEqual(len(cf_group), len(self.variables)) + # Check the number of data variables. + self.assertEqual(len(cf_group.data_variables), 1) + self.assertEqual(list(cf_group.data_variables.keys()), ['temp']) + # Check the number of promoted variables. + self.assertEqual(len(cf_group.promoted), 1) + self.assertEqual(list(cf_group.promoted.keys()), ['orography']) + # Check the promoted variable dependencies. + group = cf_group.promoted['orography'].cf_group.coordinates + self.assertEqual(len(group), 2) + coordinates = ('lat', 'lon') + self.assertEqual(set(group.keys()), set(coordinates)) + for name in coordinates: + self.assertIs(group[name].cf_data, getattr(self, name)) + + def test_formula_terms_ignore(self): + self.orography.dimensions = ['lat', 'wibble'] + with mock.patch('netCDF4.Dataset', return_value=self.dataset), \ + mock.patch('warnings.warn') as warn: + cf_group = CFReader('dummy').cf_group + group = cf_group.promoted + self.assertEqual(list(group.keys()), ['orography']) + self.assertIs(group['orography'].cf_data, self.orography) + self.assertEqual(warn.call_count, 1) + + def test_auxiliary_ignore(self): + self.x.dimensions = ['lat', 'wibble'] + with mock.patch('netCDF4.Dataset', return_value=self.dataset), \ + mock.patch('warnings.warn') as warn: + cf_group = CFReader('dummy').cf_group + promoted = ['x', 'orography'] + group = cf_group.promoted + self.assertEqual(set(group.keys()), set(promoted)) + for name in promoted: + self.assertIs(group[name].cf_data, getattr(self, name)) + self.assertEqual(warn.call_count, 1) + + def test_promoted_auxiliary_ignore(self): + self.wibble = netcdf_variable('wibble', 'lat wibble', np.float) + self.variables['wibble'] = self.wibble + self.orography.coordinates = 'wibble' + with mock.patch('netCDF4.Dataset', return_value=self.dataset), \ + mock.patch('warnings.warn') as warn: + cf_group = CFReader('dummy').cf_group.promoted + promoted = ['wibble', 'orography'] + self.assertEqual(set(cf_group.keys()), set(promoted)) + for name in promoted: + self.assertIs(cf_group[name].cf_data, getattr(self, name)) + self.assertEqual(warn.call_count, 2) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/fileformats/dot/__init__.py b/lib/iris/tests/unit/fileformats/dot/__init__.py new file mode 100644 index 0000000000..c19a493a4b --- /dev/null +++ b/lib/iris/tests/unit/fileformats/dot/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for :mod:`iris.fileformats.dot`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/dot/test__dot_path.py b/lib/iris/tests/unit/fileformats/dot/test__dot_path.py new file mode 100644 index 0000000000..bc19f02e7e --- /dev/null +++ b/lib/iris/tests/unit/fileformats/dot/test__dot_path.py @@ -0,0 +1,84 @@ +# (C) British Crown Copyright 2016 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for :func:`iris.fileformats.dot._dot_path`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import os.path +import subprocess + +from iris.fileformats.dot import _dot_path, _DOT_EXECUTABLE_PATH +from iris.tests import mock + + +class Test(tests.IrisTest): + def setUp(self): + # Because _dot_path is triggered by the initial import we + # reset the caching status to allow us to see what happens + # under different circumstances. + self.patch('iris.fileformats.dot._DOT_CHECKED', new=False) + # Also patch the private path variable to the existing value (i.e. no + # change), and restore it after each test: As these tests modify it, + # that can potentially break subsequent 'normal' behaviour. + self.patch('iris.fileformats.dot._DOT_EXECUTABLE_PATH', + _DOT_EXECUTABLE_PATH) + + def test_valid_absolute_path(self): + # Override the configuration value for System.dot_path + real_path = os.path.abspath(__file__) + assert os.path.exists(real_path) and os.path.isabs(real_path) + with mock.patch('iris.config.get_option', return_value=real_path): + result = _dot_path() + self.assertEqual(result, real_path) + + def test_invalid_absolute_path(self): + # Override the configuration value for System.dot_path + dummy_path = '/not_a_real_path' * 10 + assert not os.path.exists(dummy_path) + with mock.patch('iris.config.get_option', return_value=dummy_path): + result = _dot_path() + self.assertIsNone(result) + + def test_valid_relative_path(self): + # Override the configuration value for System.dot_path + dummy_path = 'not_a_real_path' * 10 + assert not os.path.exists(dummy_path) + with mock.patch('iris.config.get_option', return_value=dummy_path): + # Pretend we have a valid installation of dot + with mock.patch('subprocess.check_output'): + result = _dot_path() + self.assertEqual(result, dummy_path) + + def test_valid_relative_path_broken_install(self): + # Override the configuration value for System.dot_path + dummy_path = 'not_a_real_path' * 10 + assert not os.path.exists(dummy_path) + with mock.patch('iris.config.get_option', return_value=dummy_path): + # Pretend we have a broken installation of dot + error = subprocess.CalledProcessError(-5, 'foo', 'bar') + with mock.patch('subprocess.check_output', side_effect=error): + result = _dot_path() + self.assertIsNone(result) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/fileformats/ff/__init__.py b/lib/iris/tests/unit/fileformats/ff/__init__.py index a624f898b7..5b1656950a 100644 --- a/lib/iris/tests/unit/fileformats/ff/__init__.py +++ b/lib/iris/tests/unit/fileformats/ff/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Unit tests for the :mod:`iris.fileformats.ff` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/ff/test_ArakawaC.py b/lib/iris/tests/unit/fileformats/ff/test_ArakawaC.py index 2e443b6cc7..be1b597d35 100644 --- a/lib/iris/tests/unit/fileformats/ff/test_ArakawaC.py +++ b/lib/iris/tests/unit/fileformats/ff/test_ArakawaC.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2016, Met Office # # This file is part of Iris. # @@ -16,14 +16,16 @@ # along with Iris. If not, see . """Unit tests for :class:`iris.fileformat.ff.ArakawaC`.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import mock import numpy as np -from iris.fileformats.ff import ArakawaC +from iris.fileformats._ff import ArakawaC class Test__x_vectors(tests.IrisTest): diff --git a/lib/iris/tests/unit/fileformats/ff/test_ENDGame.py b/lib/iris/tests/unit/fileformats/ff/test_ENDGame.py index 15bafbe849..d9e7dfda81 100644 --- a/lib/iris/tests/unit/fileformats/ff/test_ENDGame.py +++ b/lib/iris/tests/unit/fileformats/ff/test_ENDGame.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2016, Met Office # # This file is part of Iris. # @@ -16,14 +16,16 @@ # along with Iris. If not, see . """Unit tests for :class:`iris.fileformat.ff.ENDGame`.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import mock import numpy as np -from iris.fileformats.ff import ENDGame +from iris.fileformats._ff import ENDGame class Test(tests.IrisTest): diff --git a/lib/iris/tests/unit/fileformats/ff/test_FF2PP.py b/lib/iris/tests/unit/fileformats/ff/test_FF2PP.py index 59531dc3a8..20b2fb3c6c 100644 --- a/lib/iris/tests/unit/fileformats/ff/test_FF2PP.py +++ b/lib/iris/tests/unit/fileformats/ff/test_FF2PP.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2016, Met Office # # This file is part of Iris. # @@ -16,29 +16,56 @@ # along with Iris. If not, see . """Unit tests for the :class:`iris.fileformat.ff.FF2PP` class.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests +import collections import contextlib - -import mock import numpy as np +import warnings -from iris.fileformats.ff import FF2PP -import iris.fileformats.ff as ff +from iris.exceptions import NotYetImplementedError +import iris.fileformats._ff as ff import iris.fileformats.pp as pp +from iris.fileformats._ff import FF2PP +from iris.tests import mock + + +# PP-field: LBPACK N1 values. +_UNPACKED = 0 +_WGDOS = 1 +_CRAY = 2 + +# PP-field: LBUSER(1) values. +_REAL = 1 +_INTEGER = 2 + + +_DummyField = collections.namedtuple('_DummyField', + 'lbext lblrec lbnrec raw_lbpack ' + 'lbuser boundary_packing') +_DummyFieldWithSize = collections.namedtuple('_DummyFieldWithSize', + 'lbext lblrec lbnrec raw_lbpack ' + 'lbuser boundary_packing ' + 'lbnpt lbrow') +_DummyBoundaryPacking = collections.namedtuple('_DummyBoundaryPacking', + 'x_halo y_halo rim_width') class Test____iter__(tests.IrisTest): - @mock.patch('iris.fileformats.ff.FFHeader') + @mock.patch('iris.fileformats._ff.FFHeader') def test_call_structure(self, _FFHeader): # Check that the iter method calls the two necessary utility # functions extract_result = mock.Mock() interpret_patch = mock.patch('iris.fileformats.pp._interpret_fields', autospec=True, return_value=iter([])) - extract_patch = mock.patch('iris.fileformats.ff.FF2PP._extract_field', + extract_patch = mock.patch('iris.fileformats._ff.FF2PP._extract_field', autospec=True, return_value=extract_result) FF2PP_instance = ff.FF2PP('mock') @@ -58,27 +85,45 @@ def mock_for_extract_field(self, fields, x=None, y=None): the "make_pp_field" call. """ - with mock.patch('iris.fileformats.ff.FFHeader'): + with mock.patch('iris.fileformats._ff.FFHeader'): ff2pp = ff.FF2PP('mock') ff2pp._ff_header.lookup_table = [0, 0, len(fields)] + # Fake level constants, with shape specifying just one model-level. + ff2pp._ff_header.level_dependent_constants = np.zeros(1) grid = mock.Mock() grid.vectors = mock.Mock(return_value=(x, y)) ff2pp._ff_header.grid = mock.Mock(return_value=grid) + if six.PY3: + open_func = 'builtins.open' + else: + open_func = '__builtin__.open' with mock.patch('numpy.fromfile', return_value=[0]), \ - mock.patch('__builtin__.open'), \ + mock.patch(open_func), \ mock.patch('struct.unpack_from', return_value=[4]), \ mock.patch('iris.fileformats.pp.make_pp_field', side_effect=fields), \ - mock.patch('iris.fileformats.ff.FF2PP._payload', + mock.patch('iris.fileformats._ff.FF2PP._payload', return_value=(0, 0)): yield ff2pp + def _mock_lbc(self, **kwargs): + """Return a Mock object representing an LBC field.""" + # Default kwargs for a valid LBC field mapping just 1 model-level. + field_kwargs = dict(lbtim=0, lblev=7777, lbvc=0, lbhem=101) + # Apply provided args (replacing any defaults if specified). + field_kwargs.update(kwargs) + # Return a mock with just those properties pre-defined. + return mock.Mock(**field_kwargs) + def test_LBC_header(self): bzx, bzy = -10, 15 - field = mock.Mock(lbegin=0, stash='m01s00i001', - lbrow=10, lbnpt=12, bdx=1, bdy=1, bzx=bzx, bzy=bzy, - lbuser=[None, None, 121416]) + # stash m01s00i001 + lbuser = [None, None, 121416, 1, None, None, 1] + field = self._mock_lbc(lbegin=0, + lbrow=10, lbnpt=12, + bdx=1, bdy=1, bzx=bzx, bzy=bzy, + lbuser=lbuser) with self.mock_for_extract_field([field]) as ff2pp: ff2pp._ff_header.dataset_type = 5 result = list(ff2pp._extract_field()) @@ -91,16 +136,16 @@ def test_LBC_header(self): x_halo=slice(0, 2)) boundary_packing = pp.SplittableInt(121416, name_mapping_dict) - self.assertEqual(field.lbpack.boundary_packing, boundary_packing) + self.assertEqual(field.boundary_packing, boundary_packing) self.assertEqual(field.bzy, bzy - boundary_packing.y_halo * field.bdy) self.assertEqual(field.bzx, bzx - boundary_packing.x_halo * field.bdx) def check_non_trivial_coordinate_warning(self, field): field.lbegin = 0 - field.stash = 'm01s31i020' field.lbrow = 10 field.lbnpt = 12 - field.lbuser = [None, None, 121416] + # stash m01s31i020 + field.lbuser = [None, None, 121416, 20, None, None, 1] orig_bdx, orig_bdy = field.bdx, field.bdy x = np.array([1, 2, 6]) @@ -125,7 +170,7 @@ def check_non_trivial_coordinate_warning(self, field): def test_LBC_header_non_trivial_coords_both(self): # Check a warning is raised when both bdx and bdy are bad. - field = mock.Mock(bdx=0, bdy=0, bzx=10, bzy=10) + field = self._mock_lbc(bdx=0, bdy=0, bzx=10, bzy=10) self.check_non_trivial_coordinate_warning(field) field.bdy = field.bdx = field.bmdi @@ -133,7 +178,7 @@ def test_LBC_header_non_trivial_coords_both(self): def test_LBC_header_non_trivial_coords_x(self): # Check a warning is raised when bdx is bad. - field = mock.Mock(bdx=0, bdy=10, bzx=10, bzy=10) + field = self._mock_lbc(bdx=0, bdy=10, bzx=10, bzy=10) self.check_non_trivial_coordinate_warning(field) field.bdx = field.bmdi @@ -141,7 +186,7 @@ def test_LBC_header_non_trivial_coords_x(self): def test_LBC_header_non_trivial_coords_y(self): # Check a warning is raised when bdy is bad. - field = mock.Mock(bdx=10, bdy=0, bzx=10, bzy=10) + field = self._mock_lbc(bdx=10, bdy=0, bzx=10, bzy=10) self.check_non_trivial_coordinate_warning(field) field.bdy = field.bmdi @@ -150,8 +195,9 @@ def test_LBC_header_non_trivial_coords_y(self): def test_negative_bdy(self): # Check a warning is raised when bdy is negative, # we don't yet know what "north" means in this case. - field = mock.Mock(bdx=10, bdy=-10, bzx=10, bzy=10, lbegin=0, - lbuser=[0, 0, 121416], lbrow=10, lbnpt=12) + field = self._mock_lbc(bdx=10, bdy=-10, bzx=10, bzy=10, lbegin=0, + lbuser=[0, 0, 121416, 0, None, None, 0], + lbrow=10, lbnpt=12) with self.mock_for_extract_field([field]) as ff2pp: ff2pp._ff_header.dataset_type = 5 with mock.patch('warnings.warn') as warn: @@ -161,9 +207,150 @@ def test_negative_bdy(self): 'Northwards bdy warning not correctly raised.') +class Test__payload(tests.IrisTest): + def setUp(self): + # Create a mock LBC type PPField. + self.mock_field = mock.Mock() + field = self.mock_field + field.raw_lbpack = _UNPACKED + field.lbuser = [_REAL] + field.lblrec = 777 + field.lbext = 222 + field.lbnrec = 50 + field.boundary_packing = None + + def _test(self, mock_field, expected_depth, expected_dtype, + word_depth=None): + with mock.patch('iris.fileformats._ff.FFHeader', return_value=None): + kwargs = {} + if word_depth is not None: + kwargs['word_depth'] = word_depth + ff2pp = FF2PP('dummy_filename', **kwargs) + data_depth, data_dtype = ff2pp._payload(mock_field) + self.assertEqual(data_depth, expected_depth) + self.assertEqual(data_dtype, expected_dtype) + + def test_unpacked_real(self): + mock_field = _DummyField(lbext=0, lblrec=100, lbnrec=-1, + raw_lbpack=_UNPACKED, + lbuser=[_REAL], boundary_packing=None) + self._test(mock_field, 800, '>f8') + + def test_unpacked_real_ext(self): + mock_field = _DummyField(lbext=5, lblrec=100, lbnrec=-1, + raw_lbpack=_UNPACKED, + lbuser=[_REAL], boundary_packing=None) + self._test(mock_field, 760, '>f8') + + def test_unpacked_integer(self): + mock_field = _DummyField(lbext=0, lblrec=200, lbnrec=-1, + raw_lbpack=_UNPACKED, + lbuser=[_INTEGER], boundary_packing=None) + self._test(mock_field, 1600, '>i8') + + def test_unpacked_integer_ext(self): + mock_field = _DummyField(lbext=10, lblrec=200, lbnrec=-1, + raw_lbpack=_UNPACKED, + lbuser=[_INTEGER], boundary_packing=None) + self._test(mock_field, 1520, '>i8') + + def test_unpacked_real_ext_different_word_depth(self): + mock_field = _DummyField(lbext=5, lblrec=100, lbnrec=-1, + raw_lbpack=_UNPACKED, + lbuser=[_REAL], boundary_packing=None) + self._test(mock_field, 380, '>f4', word_depth=4) + + def test_wgdos_real(self): + mock_field = _DummyField(lbext=0, lblrec=-1, lbnrec=100, + raw_lbpack=_WGDOS, + lbuser=[_REAL], boundary_packing=None) + self._test(mock_field, 800, '>f4') + + def test_wgdos_real_ext(self): + mock_field = _DummyField(lbext=5, lblrec=-1, lbnrec=100, + raw_lbpack=_WGDOS, + lbuser=[_REAL], boundary_packing=None) + self._test(mock_field, 800, '>f4') + + def test_wgdos_integer(self): + mock_field = _DummyField(lbext=0, lblrec=-1, lbnrec=200, + raw_lbpack=_WGDOS, + lbuser=[_INTEGER], boundary_packing=None) + self._test(mock_field, 1600, '>i4') + + def test_wgdos_integer_ext(self): + mock_field = _DummyField(lbext=10, lblrec=-1, lbnrec=200, + raw_lbpack=_WGDOS, + lbuser=[_INTEGER], boundary_packing=None) + self._test(mock_field, 1600, '>i4') + + def test_cray_real(self): + mock_field = _DummyField(lbext=0, lblrec=100, lbnrec=-1, + raw_lbpack=_CRAY, + lbuser=[_REAL], boundary_packing=None) + self._test(mock_field, 400, '>f4') + + def test_cray_real_ext(self): + mock_field = _DummyField(lbext=5, lblrec=100, lbnrec=-1, + raw_lbpack=_CRAY, + lbuser=[_REAL], boundary_packing=None) + self._test(mock_field, 380, '>f4') + + def test_cray_integer(self): + mock_field = _DummyField(lbext=0, lblrec=200, lbnrec=-1, + raw_lbpack=_CRAY, + lbuser=[_INTEGER], boundary_packing=None) + self._test(mock_field, 800, '>i4') + + def test_cray_integer_ext(self): + mock_field = _DummyField(lbext=10, lblrec=200, lbnrec=-1, + raw_lbpack=_CRAY, + lbuser=[_INTEGER], boundary_packing=None) + self._test(mock_field, 760, '>i4') + + def test_lbpack_unsupported(self): + mock_field = _DummyField(lbext=10, lblrec=200, lbnrec=-1, + raw_lbpack=1239, + lbuser=[_INTEGER], boundary_packing=None) + with self.assertRaisesRegexp( + NotYetImplementedError, + 'PP fields with LBPACK of 1239 are not supported.'): + self._test(mock_field, None, None) + + def test_lbc_unpacked(self): + boundary_packing = _DummyBoundaryPacking(x_halo=11, y_halo=7, + rim_width=3) + mock_field = _DummyFieldWithSize(lbext=10, lblrec=200, lbnrec=-1, + raw_lbpack=_UNPACKED, + lbuser=[_REAL], + boundary_packing=boundary_packing, + lbnpt=47, lbrow=34) + self._test(mock_field, ((47 * 34) - (19 * 14)) * 8, '>f8') + + def test_lbc_wgdos_unsupported(self): + mock_field = _DummyField(lbext=5, lblrec=-1, lbnrec=100, + raw_lbpack=_WGDOS, + lbuser=[_REAL], + # Anything not None will do here. + boundary_packing=0) + with self.assertRaisesRegexp(ValueError, + 'packed LBC data is not supported'): + self._test(mock_field, None, None) + + def test_lbc_cray(self): + boundary_packing = _DummyBoundaryPacking(x_halo=11, y_halo=7, + rim_width=3) + mock_field = _DummyFieldWithSize(lbext=10, lblrec=200, lbnrec=-1, + raw_lbpack=_CRAY, + lbuser=[_REAL], + boundary_packing=boundary_packing, + lbnpt=47, lbrow=34) + self._test(mock_field, ((47 * 34) - (19 * 14)) * 4, '>f4') + + class Test__det_border(tests.IrisTest): def setUp(self): - _FFH_patch = mock.patch('iris.fileformats.ff.FFHeader') + _FFH_patch = mock.patch('iris.fileformats._ff.FFHeader') _FFH_patch.start() self.addCleanup(_FFH_patch.stop) @@ -199,5 +386,110 @@ def test_decreasing_field_values(self): self.assertArrayEqual(result, com) +class Test__adjust_field_for_lbc(tests.IrisTest): + def setUp(self): + # Patch FFHeader to produce a mock header instead of opening a file. + self.mock_ff_header = mock.Mock() + self.mock_ff_header.dataset_type = 5 + self.mock_ff = self.patch('iris.fileformats._ff.FFHeader', + return_value=self.mock_ff_header) + + # Create a mock LBC type PPField. + self.mock_field = mock.Mock() + field = self.mock_field + field.lbtim = 0 + field.lblev = 7777 + field.lbvc = 0 + field.lbnpt = 1001 + field.lbrow = 2001 + field.lbuser = (None, None, 80504) + field.lbpack = pp.SplittableInt(0) + field.boundary_packing = None + field.bdx = 1.0 + field.bzx = 0.0 + field.bdy = 1.0 + field.bzy = 0.0 + + def test__basic(self): + ff2pp = FF2PP('dummy_filename') + field = self.mock_field + ff2pp._adjust_field_for_lbc(field) + self.assertEqual(field.lbtim, 11) + self.assertEqual(field.lbvc, 65) + self.assertEqual(field.boundary_packing.rim_width, 8) + self.assertEqual(field.boundary_packing.y_halo, 5) + self.assertEqual(field.boundary_packing.x_halo, 4) + self.assertEqual(field.lbnpt, 1009) + self.assertEqual(field.lbrow, 2011) + + def test__bad_lbtim(self): + self.mock_field.lbtim = 717 + ff2pp = FF2PP('dummy_filename') + with self.assertRaisesRegexp(ValueError, + 'LBTIM of 717, expected only 0 or 11'): + ff2pp._adjust_field_for_lbc(self.mock_field) + + def test__bad_lbvc(self): + self.mock_field.lbvc = 312 + ff2pp = FF2PP('dummy_filename') + with self.assertRaisesRegexp(ValueError, + 'LBVC of 312, expected only 0 or 65'): + ff2pp._adjust_field_for_lbc(self.mock_field) + + +class Test__fields_over_all_levels(tests.IrisTest): + def setUp(self): + # Patch FFHeader to produce a mock header instead of opening a file. + self.mock_ff_header = mock.Mock() + self.mock_ff_header.dataset_type = 5 + + # Fake the level constants to look like 3 model levels. + self.n_all_levels = 3 + self.mock_ff_header.level_dependent_constants = \ + np.zeros((self.n_all_levels)) + self.mock_ff = self.patch('iris.fileformats._ff.FFHeader', + return_value=self.mock_ff_header) + + # Create a simple mock for a test field. + self.mock_field = mock.Mock() + field = self.mock_field + field.lbhem = 103 + self.original_lblev = mock.sentinel.untouched_lbev + field.lblev = self.original_lblev + + def _check_expected_levels(self, results, n_levels): + if n_levels is 0: + self.assertEqual(len(results), 1) + self.assertEqual(results[0].lblev, self.original_lblev) + else: + self.assertEqual(len(results), n_levels) + self.assertEqual([fld.lblev for fld in results], + list(range(n_levels))) + + def test__is_lbc(self): + ff2pp = FF2PP('dummy_filename') + field = self.mock_field + results = list(ff2pp._fields_over_all_levels(field)) + self._check_expected_levels(results, 3) + + def test__lbhem_too_small(self): + ff2pp = FF2PP('dummy_filename') + field = self.mock_field + field.lbhem = 100 + with self.assertRaisesRegexp( + ValueError, + 'hence >= 101'): + _ = list(ff2pp._fields_over_all_levels(field)) + + def test__lbhem_too_large(self): + ff2pp = FF2PP('dummy_filename') + field = self.mock_field + field.lbhem = 105 + with self.assertRaisesRegexp( + ValueError, + 'more than the total number of levels in the file = 3'): + _ = list(ff2pp._fields_over_all_levels(field)) + + if __name__ == "__main__": tests.main() diff --git a/lib/iris/tests/unit/fileformats/ff/test_FFHeader.py b/lib/iris/tests/unit/fileformats/ff/test_FFHeader.py index f4afbe5d64..5772cc6bfa 100644 --- a/lib/iris/tests/unit/fileformats/ff/test_FFHeader.py +++ b/lib/iris/tests/unit/fileformats/ff/test_FFHeader.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2016, Met Office # # This file is part of Iris. # @@ -16,15 +16,18 @@ # along with Iris. If not, see . """Unit tests for :class:`iris.fileformat.ff.FFHeader`.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests import collections +import numpy as np -import mock - -from iris.fileformats.ff import FFHeader +from iris.fileformats._ff import FFHeader +from iris.tests import mock MyGrid = collections.namedtuple('MyGrid', 'column row real horiz_grid_type') @@ -61,7 +64,7 @@ def test_end_game(self): def test_unknown(self): header = self._header(0) - with mock.patch('iris.fileformats.ff.NewDynamics', + with mock.patch('iris.fileformats._ff.NewDynamics', mock.Mock(return_value=mock.sentinel.grid)): with mock.patch('warnings.warn') as warn: grid = header.grid() @@ -70,5 +73,13 @@ def test_unknown(self): self.assertIs(grid, mock.sentinel.grid) +@tests.skip_data +class Test_integer_constants(tests.IrisTest): + def test_read_ints(self): + test_file_path = tests.get_data_path(('FF', 'structured', 'small')) + ff_header = FFHeader(test_file_path) + self.assertEqual(ff_header.integer_constants.dtype, np.dtype('>i8')) + + if __name__ == "__main__": tests.main() diff --git a/lib/iris/tests/unit/fileformats/ff/test_Grid.py b/lib/iris/tests/unit/fileformats/ff/test_Grid.py index 743373bb61..67432f1a9e 100644 --- a/lib/iris/tests/unit/fileformats/ff/test_Grid.py +++ b/lib/iris/tests/unit/fileformats/ff/test_Grid.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2016, Met Office # # This file is part of Iris. # @@ -16,14 +16,15 @@ # along with Iris. If not, see . """Unit tests for :class:`iris.fileformat.ff.Grid`.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import mock -import numpy as np - -from iris.fileformats.ff import Grid +from iris.fileformats._ff import Grid +from iris.tests import mock class Test___init__(tests.IrisTest): diff --git a/lib/iris/tests/unit/fileformats/ff/test_NewDynamics.py b/lib/iris/tests/unit/fileformats/ff/test_NewDynamics.py index c4506d3085..449d2485dc 100644 --- a/lib/iris/tests/unit/fileformats/ff/test_NewDynamics.py +++ b/lib/iris/tests/unit/fileformats/ff/test_NewDynamics.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2016, Met Office # # This file is part of Iris. # @@ -16,14 +16,16 @@ # along with Iris. If not, see . """Unit tests for :class:`iris.fileformat.ff.NewDynamics`.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import mock import numpy as np -from iris.fileformats.ff import NewDynamics +from iris.fileformats._ff import NewDynamics class Test(tests.IrisTest): diff --git a/lib/iris/tests/unit/fileformats/grib/__init__.py b/lib/iris/tests/unit/fileformats/grib/__init__.py deleted file mode 100644 index 3e362eb635..0000000000 --- a/lib/iris/tests/unit/fileformats/grib/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# (C) British Crown Copyright 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -"""Unit tests for the :mod:`iris.fileformats.grib` package.""" diff --git a/lib/iris/tests/unit/fileformats/grib/grib_save_rules/__init__.py b/lib/iris/tests/unit/fileformats/grib/grib_save_rules/__init__.py deleted file mode 100644 index 8e711f3626..0000000000 --- a/lib/iris/tests/unit/fileformats/grib/grib_save_rules/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# (C) British Crown Copyright 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -"""Unit tests for the :mod:`iris.fileformats.grib.grib_save_rules` module.""" diff --git a/lib/iris/tests/unit/fileformats/grib/grib_save_rules/test__missing_forecast_period.py b/lib/iris/tests/unit/fileformats/grib/grib_save_rules/test__missing_forecast_period.py deleted file mode 100644 index b12f6b3198..0000000000 --- a/lib/iris/tests/unit/fileformats/grib/grib_save_rules/test__missing_forecast_period.py +++ /dev/null @@ -1,59 +0,0 @@ -# (C) British Crown Copyright 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -"""Unit tests for module-level functions.""" - -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -import gribapi -import mock -import numpy as np - -from iris.fileformats.grib.grib_save_rules import _missing_forecast_period -from iris.tests.test_grib_load import TestGribSimple - - -class Test(TestGribSimple): - def test_point(self): - t_coord = mock.Mock() - t_coord.has_bounds = mock.Mock(return_value=False) - t_coord.points = [15] - - cube = mock.Mock() - cube.coord = mock.Mock(return_value=t_coord) - rt, rt_meaning, fp, fp_meaning = _missing_forecast_period(cube) - - t_coord.units.assert_has_call(mock.call.num2date(15)) - self.assertEqual((rt_meaning, fp, fp_meaning), (2, 0, 1)) - - def test_bounds(self): - t_coord = mock.Mock() - t_coord.has_bounds = mock.Mock(return_value=True) - t_coord.points = [15] - t_coord.bounds = np.array([[10, 20]]) - - cube = mock.Mock() - cube.coord = mock.Mock(return_value=t_coord) - rt, rt_meaning, fp, fp_meaning = _missing_forecast_period(cube) - - t_coord.units.assert_has_call(mock.call.num2date(10)) - self.assertEqual((rt_meaning, fp, fp_meaning), (2, 0, 1)) - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/fileformats/grib/grib_save_rules/test__non_missing_forecast_period.py b/lib/iris/tests/unit/fileformats/grib/grib_save_rules/test__non_missing_forecast_period.py deleted file mode 100644 index a6cc9484ec..0000000000 --- a/lib/iris/tests/unit/fileformats/grib/grib_save_rules/test__non_missing_forecast_period.py +++ /dev/null @@ -1,56 +0,0 @@ -# (C) British Crown Copyright 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -"""Unit tests for module-level functions.""" - -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -import gribapi -import mock -import numpy as np - -from iris.fileformats.grib.grib_save_rules import _non_missing_forecast_period -import iris.unit - - -class Test(tests.IrisTest): - def _cube(self, t_bounds=False): - time_coord = iris.coords.DimCoord(15, standard_name='time', - units='hours since epoch') - if t_bounds: - time_coord.bounds = [[8, 100]] - fp_coord = iris.coords.DimCoord(10, standard_name='forecast_period', - units='hours') - cube = iris.cube.Cube([23]) - cube.add_dim_coord(time_coord, 0) - cube.add_aux_coord(fp_coord, 0) - return cube - - def test_time_point(self): - cube = self._cube() - rt, rt_meaning, fp, fp_meaning = _non_missing_forecast_period(cube) - self.assertEqual((rt_meaning, fp, fp_meaning), (1, 10, 1)) - - def test_time_bounds(self): - cube = self._cube(t_bounds=True) - rt, rt_meaning, fp, fp_meaning = _non_missing_forecast_period(cube) - self.assertEqual((rt_meaning, fp, fp_meaning), (1, 3, 1)) - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/fileformats/grib/grib_save_rules/test_non_hybrid_surfaces.py b/lib/iris/tests/unit/fileformats/grib/grib_save_rules/test_non_hybrid_surfaces.py deleted file mode 100644 index 82f2799ab8..0000000000 --- a/lib/iris/tests/unit/fileformats/grib/grib_save_rules/test_non_hybrid_surfaces.py +++ /dev/null @@ -1,49 +0,0 @@ -# (C) British Crown Copyright 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -"""Unit tests for module-level functions.""" - -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -import gribapi -import numpy as np - -import iris -import iris.cube -import iris.coords -import iris.fileformats.grib.grib_save_rules as grib_save_rules - - -class Test_non_hybrid_surfaces(tests.IrisTest): - def test_bounded_altitude_feet(self): - cube = iris.cube.Cube([0]) - cube.add_aux_coord(iris.coords.AuxCoord( - 1500.0, long_name='altitude', units='ft', - bounds=np.array([1000.0, 2000.0]))) - grib = gribapi.grib_new_from_samples("GRIB2") - grib_save_rules.non_hybrid_surfaces(cube, grib) - self.assertEqual( - gribapi.grib_get_double(grib, "scaledValueOfFirstFixedSurface"), - 304.0) - self.assertEqual( - gribapi.grib_get_double(grib, "scaledValueOfSecondFixedSurface"), - 609.0) - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/fileformats/grib/grib_save_rules/test_reference_time.py b/lib/iris/tests/unit/fileformats/grib/grib_save_rules/test_reference_time.py deleted file mode 100644 index 4f797a24fb..0000000000 --- a/lib/iris/tests/unit/fileformats/grib/grib_save_rules/test_reference_time.py +++ /dev/null @@ -1,68 +0,0 @@ -# (C) British Crown Copyright 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -"""Unit tests for module-level functions.""" - -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -import gribapi -import mock - -import iris.fileformats.grib -from iris.fileformats.grib.grib_save_rules import reference_time -import iris.tests.stock as stock -from iris.tests.test_grib_load import TestGribSimple - - -class Test(TestGribSimple): - def test_forecast_period(self): - # The stock cube has a non-compliant forecast_period. - iris.fileformats.grib.hindcast_workaround = True - cube = stock.global_grib2() - cube.coord("forecast_period").points = [36] - - grib = mock.Mock() - mock_gribapi = mock.Mock(spec=gribapi) - with mock.patch('iris.fileformats.grib.grib_save_rules.gribapi', - mock_gribapi): - reference_time(cube, grib) - - mock_gribapi.assert_has_calls( - [mock.call.grib_set_long(grib, "significanceOfReferenceTime", 1), - mock.call.grib_set_long(grib, "dataDate", '19941129'), - mock.call.grib_set_long(grib, "dataTime", '1200')]) - - def test_no_forecast_period(self): - # The stock cube has a non-compliant forecast_period. - iris.fileformats.grib.hindcast_workaround = True - cube = stock.global_grib2() - cube.remove_coord("forecast_period") - - grib = mock.Mock() - mock_gribapi = mock.Mock(spec=gribapi) - with mock.patch('iris.fileformats.grib.grib_save_rules.gribapi', - mock_gribapi): - reference_time(cube, grib) - - mock_gribapi.assert_has_calls( - [mock.call.grib_set_long(grib, "significanceOfReferenceTime", 2), - mock.call.grib_set_long(grib, "dataDate", '19941201'), - mock.call.grib_set_long(grib, "dataTime", '0000')]) - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/fileformats/grib/grib_save_rules/test_type_of_statistical_processing.py b/lib/iris/tests/unit/fileformats/grib/grib_save_rules/test_type_of_statistical_processing.py deleted file mode 100644 index 6c2dfcbfc6..0000000000 --- a/lib/iris/tests/unit/fileformats/grib/grib_save_rules/test_type_of_statistical_processing.py +++ /dev/null @@ -1,52 +0,0 @@ -# (C) British Crown Copyright 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -"""Unit tests for module-level functions.""" - -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -import gribapi -import mock -import numpy as np - -from iris.fileformats.grib.grib_save_rules \ - import type_of_statistical_processing - -from iris.tests.test_grib_load import TestGribSimple - - -class Test(TestGribSimple): - def test_sum(self): - cube = mock.Mock() - cube.cell_methods = [mock.Mock(method='sum', coord_names=['ni'])] - - coord = mock.Mock() - coord.name = mock.Mock(return_value='ni') - - grib = mock.Mock() - mock_gribapi = mock.Mock(spec=gribapi) - with mock.patch('iris.fileformats.grib.grib_save_rules.gribapi', - mock_gribapi): - type_of_statistical_processing(cube, grib, coord) - - mock_gribapi.assert_has_calls(mock.call.grib_set_long( - grib, "typeOfStatisticalProcessing", 1)) - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/fileformats/grib/load_rules/__init__.py b/lib/iris/tests/unit/fileformats/grib/load_rules/__init__.py deleted file mode 100644 index 9a31e5c3e4..0000000000 --- a/lib/iris/tests/unit/fileformats/grib/load_rules/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# (C) British Crown Copyright 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -"""Unit tests for the :mod:`iris.fileformats.grib.load_rules` module.""" diff --git a/lib/iris/tests/unit/fileformats/grib/load_rules/test_convert.py b/lib/iris/tests/unit/fileformats/grib/load_rules/test_convert.py deleted file mode 100644 index 54d645f37f..0000000000 --- a/lib/iris/tests/unit/fileformats/grib/load_rules/test_convert.py +++ /dev/null @@ -1,73 +0,0 @@ -# (C) British Crown Copyright 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -"""Unit tests for :func:`iris.fileformats.grib.load_rules.convert`.""" - -# Import iris tests first so that some things can be initialised before -# importing anything else -import iris.tests as tests - -import mock - -from iris.coords import DimCoord -from iris.tests.test_grib_load import TestGribSimple - - -class Test_GribLevels(TestGribSimple): - def test_grib2_height(self): - grib = self.mock_grib() - grib.edition = 2 - grib.typeOfFirstFixedSurface = 103 - grib.scaledValueOfFirstFixedSurface = 12345 - grib.scaleFactorOfFirstFixedSurface = 0 - grib.typeOfSecondFixedSurface = 255 - cube = self.cube_from_message(grib) - self.assertEqual( - cube.coord('height'), - DimCoord(12345, standard_name="height", units="m")) - - def test_grib2_bounded_height(self): - grib = self.mock_grib() - grib.edition = 2 - grib.typeOfFirstFixedSurface = 103 - grib.scaledValueOfFirstFixedSurface = 12345 - grib.scaleFactorOfFirstFixedSurface = 0 - grib.typeOfSecondFixedSurface = 103 - grib.scaledValueOfSecondFixedSurface = 54321 - grib.scaleFactorOfSecondFixedSurface = 0 - cube = self.cube_from_message(grib) - self.assertEqual( - cube.coord('height'), - DimCoord(33333, standard_name="height", units="m", - bounds=[[12345, 54321]])) - - def test_grib2_diff_bound_types(self): - grib = self.mock_grib() - grib.edition = 2 - grib.typeOfFirstFixedSurface = 103 - grib.scaledValueOfFirstFixedSurface = 12345 - grib.scaleFactorOfFirstFixedSurface = 0 - grib.typeOfSecondFixedSurface = 102 - grib.scaledValueOfSecondFixedSurface = 54321 - grib.scaleFactorOfSecondFixedSurface = 0 - with mock.patch('warnings.warn') as warn: - cube = self.cube_from_message(grib) - warn.assert_called_with( - "Different vertical bound types not yet handled.") - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/fileformats/name_loaders/__init__.py b/lib/iris/tests/unit/fileformats/name_loaders/__init__.py index 28c190dd17..2fbacdc89a 100644 --- a/lib/iris/tests/unit/fileformats/name_loaders/__init__.py +++ b/lib/iris/tests/unit/fileformats/name_loaders/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Unit tests for the :mod:`iris.fileformats.name_loaders` package.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/name_loaders/test__build_cell_methods.py b/lib/iris/tests/unit/fileformats/name_loaders/test__build_cell_methods.py new file mode 100644 index 0000000000..70f967fd42 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/name_loaders/test__build_cell_methods.py @@ -0,0 +1,126 @@ +# (C) British Crown Copyright 2013 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for :func:`iris.fileformats.name_loaders._build_cell_methods`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + + +import iris.coords +from iris.fileformats.name_loaders import _build_cell_methods +from iris.tests import mock + + +class Tests(tests.IrisTest): + def test_nameII_average(self): + av_or_int = ['something average ob bla'] + coord_name = 'foo' + res = _build_cell_methods(av_or_int, coord_name) + self.assertEqual(res, [iris.coords.CellMethod('mean', 'foo')]) + + def test_nameIII_averaged(self): + av_or_int = ['something averaged ob bla'] + coord_name = 'bar' + res = _build_cell_methods(av_or_int, coord_name) + self.assertEqual(res, [iris.coords.CellMethod('mean', 'bar')]) + + def test_nameII_integral(self): + av_or_int = ['something integral ob bla'] + coord_name = 'ensemble' + res = _build_cell_methods(av_or_int, coord_name) + self.assertEqual(res, [iris.coords.CellMethod('sum', 'ensemble')]) + + def test_nameIII_integrated(self): + av_or_int = ['something integrated ob bla'] + coord_name = 'time' + res = _build_cell_methods(av_or_int, coord_name) + self.assertEqual(res, [iris.coords.CellMethod('sum', 'time')]) + + def test_no_averaging(self): + av_or_int = ['No foo averaging', + 'No bar averaging', + 'no', + '', + 'no averaging', + 'no anything at all averaging'] + coord_name = 'time' + res = _build_cell_methods(av_or_int, coord_name) + self.assertEqual(res, [None] * len(av_or_int)) + + def test_nameII_mixed(self): + av_or_int = ['something integral ob bla', + 'no averaging', + 'other average'] + coord_name = 'ensemble' + res = _build_cell_methods(av_or_int, coord_name) + self.assertEqual(res, [iris.coords.CellMethod('sum', 'ensemble'), + None, + iris.coords.CellMethod('mean', 'ensemble')]) + + def test_nameIII_mixed(self): + av_or_int = ['something integrated ob bla', + 'no averaging', + 'other averaged'] + coord_name = 'ensemble' + res = _build_cell_methods(av_or_int, coord_name) + self.assertEqual(res, [iris.coords.CellMethod('sum', 'ensemble'), + None, + iris.coords.CellMethod('mean', 'ensemble')]) + + def test_unrecognised(self): + unrecognised_heading = 'bla else' + av_or_int = ['something average', + unrecognised_heading, + 'something integral'] + coord_name = 'foo' + with mock.patch('warnings.warn') as warn: + res = _build_cell_methods(av_or_int, coord_name) + expected_msg = 'Unknown {} statistic: {!r}. Unable to ' \ + 'create cell method.'.format(coord_name, + unrecognised_heading) + warn.assert_called_with(expected_msg) + + def test_unrecognised_similar_to_no_averaging(self): + unrecognised_headings = ['not averaging', + 'this is not a valid no', + 'nope', + 'no daveraging', + 'no averagingg', + 'no something', + 'noaveraging'] + for unrecognised_heading in unrecognised_headings: + av_or_int = ['something average', + unrecognised_heading, + 'something integral'] + coord_name = 'foo' + with mock.patch('warnings.warn') as warn: + res = _build_cell_methods(av_or_int, coord_name) + expected_msg = 'Unknown {} statistic: {!r}. Unable to ' \ + 'create cell method.'.format(coord_name, + unrecognised_heading) + warn.assert_called_with(expected_msg) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/name_loaders/test__calc_integration_period.py b/lib/iris/tests/unit/fileformats/name_loaders/test__calc_integration_period.py new file mode 100644 index 0000000000..84367f1141 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/name_loaders/test__calc_integration_period.py @@ -0,0 +1,79 @@ +# (C) British Crown Copyright 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for :func:`iris.fileformats.name_loaders.__calc_integration_period`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import datetime + +from iris.fileformats.name_loaders import _calc_integration_period + + +class Test(tests.IrisTest): + def test_30_min_av(self): + time_avgs = [' 30min average'] + result = _calc_integration_period(time_avgs) + expected = [datetime.timedelta(0, (30*60))] + self.assertEqual(result, expected) + + def test_30_min_av_rspace(self): + time_avgs = [' 30min average '] + result = _calc_integration_period(time_avgs) + expected = [datetime.timedelta(0, (30*60))] + self.assertEqual(result, expected) + + def test_30_min_av_lstrip(self): + time_avgs = [' 30min average'.lstrip()] + result = _calc_integration_period(time_avgs) + expected = [datetime.timedelta(0, (30*60))] + self.assertEqual(result, expected) + + def test_3_hour_av(self): + time_avgs = [' 3hr 0min average'] + result = _calc_integration_period(time_avgs) + expected = [datetime.timedelta(0, (3*60*60))] + self.assertEqual(result, expected) + + def test_3_hour_int(self): + time_avgs = [' 3hr 0min integral'] + result = _calc_integration_period(time_avgs) + expected = [datetime.timedelta(0, (3*60*60))] + self.assertEqual(result, expected) + + def test_12_hour_av(self): + time_avgs = [' 12hr 0min average'] + result = _calc_integration_period(time_avgs) + expected = [datetime.timedelta(0, (12*60*60))] + self.assertEqual(result, expected) + + def test_5_day_av(self): + time_avgs = [' 5day 0hr 0min integral'] + result = _calc_integration_period(time_avgs) + expected = [datetime.timedelta(0, (5*24*60*60))] + self.assertEqual(result, expected) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/name_loaders/test__cf_height_from_name.py b/lib/iris/tests/unit/fileformats/name_loaders/test__cf_height_from_name.py index 95e624bbd5..10252fa39a 100644 --- a/lib/iris/tests/unit/fileformats/name_loaders/test__cf_height_from_name.py +++ b/lib/iris/tests/unit/fileformats/name_loaders/test__cf_height_from_name.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2016, Met Office # # This file is part of Iris. # @@ -20,6 +20,9 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests @@ -46,7 +49,7 @@ def test_bounded_height_above_ground(self): res = _cf_height_from_name(data) com = AuxCoord( units='m', points=50.0, bounds=np.array([0., 100.]), - standard_name='height', long_name=None) + standard_name='height', long_name='height above ground level') self.assertEqual(com, res) def test_bounded_flight_level(self): @@ -62,7 +65,7 @@ def test_bounded_height_above_sea_level(self): res = _cf_height_from_name(data) com = AuxCoord( units='m', points=50.0, bounds=np.array([0., 100.]), - standard_name='altitude', long_name=None) + standard_name='altitude', long_name='altitude above sea level') self.assertEqual(com, res) def test_malformed_height_above_ground(self): @@ -95,7 +98,7 @@ def test_float_bounded_height_above_ground(self): res = _cf_height_from_name(data) com = AuxCoord( units='m', points=50.0, bounds=np.array([0., 100.]), - standard_name='height', long_name=None) + standard_name='height', long_name='height above ground level') self.assertEqual(com, res) def test_float_bounded_height_flight_level(self): @@ -113,7 +116,7 @@ def test_float_bounded_height_above_sea_level(self): res = _cf_height_from_name(data) com = AuxCoord( units='m', points=50.0, bounds=np.array([0., 100.]), - standard_name='altitude', long_name=None) + standard_name='altitude', long_name='altitude above sea level') self.assertEqual(com, res) def test_no_match(self): @@ -141,7 +144,7 @@ def test_height_above_ground(self): res = _cf_height_from_name(data) com = AuxCoord( units='m', points=50.0, bounds=None, - standard_name='height', long_name=None) + standard_name='height', long_name='height above ground level') self.assertEqual(com, res) def test_height_flight_level(self): @@ -157,7 +160,7 @@ def test_height_above_sea_level(self): res = _cf_height_from_name(data) com = AuxCoord( units='m', points=50.0, bounds=None, - standard_name='altitude', long_name=None) + standard_name='altitude', long_name='altitude above sea level') self.assertEqual(com, res) def test_malformed_height_above_ground(self): @@ -190,7 +193,7 @@ def test_integer_height_above_ground(self): res = _cf_height_from_name(data) com = AuxCoord( units='m', points=50.0, bounds=None, - standard_name='height', long_name=None) + standard_name='height', long_name='height above ground level') self.assertEqual(com, res) def test_integer_height_flight_level(self): @@ -203,12 +206,30 @@ def test_integer_height_flight_level(self): self.assertEqual(com, res) def test_integer_height_above_sea_level(self): - # Parse height above sea level (agl) when its an integer. + # Parse height above sea level (asl) when its an integer. data = 'Z = 50 m asl' res = _cf_height_from_name(data) com = AuxCoord( units='m', points=50.0, bounds=None, - standard_name='altitude', long_name=None) + standard_name='altitude', long_name='altitude above sea level') + self.assertEqual(com, res) + + def test_enotation_height_above_ground(self): + # Parse height above ground expressed in scientific notation + data = 'Z = 0.0000000E+00 m agl' + res = _cf_height_from_name(data) + com = AuxCoord( + units='m', points=0.0, bounds=None, + standard_name='height', long_name='height above ground level') + self.assertEqual(com, res) + + def test_enotation_height_above_sea_level(self): + # Parse height above sea level expressed in scientific notation + data = 'Z = 0.0000000E+00 m asl' + res = _cf_height_from_name(data) + com = AuxCoord( + units='m', points=0.0, bounds=None, + standard_name='altitude', long_name='altitude above sea level') self.assertEqual(com, res) def test_pressure(self): diff --git a/lib/iris/tests/unit/fileformats/name_loaders/test__generate_cubes.py b/lib/iris/tests/unit/fileformats/name_loaders/test__generate_cubes.py new file mode 100644 index 0000000000..635f458a7e --- /dev/null +++ b/lib/iris/tests/unit/fileformats/name_loaders/test__generate_cubes.py @@ -0,0 +1,104 @@ +# (C) British Crown Copyright 2013 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for :func:`iris.analysis.name_loaders._generate_cubes`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import iris.cube +from iris.fileformats.name_loaders import _generate_cubes, NAMECoord +from iris.tests import mock + + +class TestCellMethods(tests.IrisTest): + def test_cell_methods(self): + header = mock.MagicMock() + column_headings = {'Species': [1, 2, 3], 'Quantity': [4, 5, 6], + "Units": ['m', 'm', 'm'], 'Z': [1, 2, 3]} + coords = mock.MagicMock() + data_arrays = [mock.Mock(), mock.Mock()] + cell_methods = ["cell_method_1", "cell_method_2"] + + self.patch('iris.fileformats.name_loaders._cf_height_from_name') + self.patch('iris.cube.Cube') + cubes = list(_generate_cubes(header, column_headings, coords, + data_arrays, cell_methods)) + + cubes[0].assert_has_calls([mock.call.add_cell_method('cell_method_1')]) + cubes[1].assert_has_calls([mock.call.add_cell_method('cell_method_2')]) + + +class TestCircularLongitudes(tests.IrisTest): + def _simulate_with_coords(self, names, values, dimensions): + header = mock.MagicMock() + column_headings = {'Species': [1, 2, 3], 'Quantity': [4, 5, 6], + "Units": ['m', 'm', 'm'], 'Z': [1, 2, 3]} + coords = [NAMECoord(name, dim, vals) + for name, vals, dim in zip(names, values, dimensions)] + data_arrays = [mock.Mock()] + + self.patch('iris.fileformats.name_loaders._cf_height_from_name') + self.patch('iris.cube.Cube') + cubes = list(_generate_cubes(header, column_headings, coords, + data_arrays)) + return cubes + + def test_non_circular(self): + results = self._simulate_with_coords(names=['longitude'], + values=[[1, 7, 23]], + dimensions=[(0,)]) + self.assertEqual(len(results), 1) + add_coord_calls = results[0].add_dim_coord.call_args_list + self.assertEqual(len(add_coord_calls), 1) + coord = add_coord_calls[0][0][0] + self.assertEqual(coord.circular, False) + + def test_circular(self): + results = self._simulate_with_coords( + names=['longitude'], + values=[[5.0, 95.0, 185.0, 275.0]], + dimensions=[(0,)]) + self.assertEqual(len(results), 1) + add_coord_calls = results[0].add_dim_coord.call_args_list + self.assertEqual(len(add_coord_calls), 1) + coord = add_coord_calls[0][0][0] + self.assertEqual(coord.circular, True) + + def test_lat_lon_byname(self): + results = self._simulate_with_coords( + names=['longitude', 'latitude'], + values=[[5.0, 95.0, 185.0, 275.0], + [5.0, 95.0, 185.0, 275.0]], + dimensions=[(0,), (1,)]) + self.assertEqual(len(results), 1) + add_coord_calls = results[0].add_dim_coord.call_args_list + self.assertEqual(len(add_coord_calls), 2) + lon_coord = add_coord_calls[0][0][0] + lat_coord = add_coord_calls[1][0][0] + self.assertEqual(lon_coord.circular, True) + self.assertEqual(lat_coord.circular, False) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/name_loaders/test_build_cell_methods.py b/lib/iris/tests/unit/fileformats/name_loaders/test_build_cell_methods.py deleted file mode 100644 index 85d26a68cb..0000000000 --- a/lib/iris/tests/unit/fileformats/name_loaders/test_build_cell_methods.py +++ /dev/null @@ -1,65 +0,0 @@ -# (C) British Crown Copyright 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -""" -Unit tests for :func:`iris.fileformats.name_loaders._build_cell_methods`. - -""" - -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -import mock - -import iris.cube -from iris.fileformats.name_loaders import _build_cell_methods - - -class Tests(tests.IrisTest): - def setUp(self): - self.mock_cell = mock.patch('iris.coords.CellMethod') - self.mock_cell.start() - self.addCleanup(self.mock_cell.stop) - - def test_nameII_average(self): - av_or_int = ['something average ob bla'] * 3 - res = _build_cell_methods(av_or_int) - iris.coords.CellMethod.assert_called('average', 'time') - - def test_nameIII_averaged(self): - av_or_int = ['something averaged ob bla'] * 3 - res = _build_cell_methods(av_or_int) - iris.coords.CellMethod.assert_called('average', 'time') - - def test_nameII_integral(self): - av_or_int = ['something integral ob bla'] * 3 - res = _build_cell_methods(av_or_int) - iris.coords.CellMethod.assert_called('sum', 'time') - - def test_nameIII_integrated(self): - av_or_int = ['something integrated ob bla'] * 3 - res = _build_cell_methods(av_or_int) - iris.coords.CellMethod.assert_called('sum', 'time') - - def test_unrecognised(self): - av_or_int = ['something average', 'something integral', 'bla else'] - with self.assertRaises(iris.exceptions.TranslationError): - res = _build_cell_methods(av_or_int) - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/fileformats/name_loaders/test_generate_cubes.py b/lib/iris/tests/unit/fileformats/name_loaders/test_generate_cubes.py deleted file mode 100644 index 9b8d72def5..0000000000 --- a/lib/iris/tests/unit/fileformats/name_loaders/test_generate_cubes.py +++ /dev/null @@ -1,52 +0,0 @@ -# (C) British Crown Copyright 2013, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -""" -Unit tests for :func:`iris.analysis.name_loaders._generate_cubes`. - -""" - -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -import mock - -import iris.cube -import iris.fileformats.name_loaders -from iris.fileformats.name_loaders import _generate_cubes - - -class TestCellMethods(tests.IrisTest): - def test_cell_methods(self): - header = mock.MagicMock() - column_headings = {'Species': [1, 2, 3], 'Quantity': [4, 5, 6], - "Unit": ['m', 'm', 'm'], 'Z': [1, 2, 3]} - coords = mock.MagicMock() - data_arrays = [mock.Mock(), mock.Mock()] - cell_methods = ["cell_method_1", "cell_method_2"] - - with mock.patch('iris.fileformats.name_loaders._cf_height_from_name'): - with mock.patch('iris.cube.Cube'): - cubes = list(_generate_cubes(header, column_headings, coords, - data_arrays, cell_methods)) - - cubes[0].assert_has_call(mock.call.add_cell_method('cell_method_1')) - cubes[1].assert_has_call(mock.call.add_cell_method('cell_method_2')) - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/fileformats/netcdf/__init__.py b/lib/iris/tests/unit/fileformats/netcdf/__init__.py index 87521d0779..64a846365f 100644 --- a/lib/iris/tests/unit/fileformats/netcdf/__init__.py +++ b/lib/iris/tests/unit/fileformats/netcdf/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Unit tests for the :mod:`iris.fileformats.netcdf` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/netcdf/test_Saver.py b/lib/iris/tests/unit/fileformats/netcdf/test_Saver.py index de7606ca2e..76a5c13861 100644 --- a/lib/iris/tests/unit/fileformats/netcdf/test_Saver.py +++ b/lib/iris/tests/unit/fileformats/netcdf/test_Saver.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2018, Met Office # # This file is part of Iris. # @@ -16,19 +16,31 @@ # along with Iris. If not, see . """Unit tests for the `iris.fileformats.netcdf.Saver` class.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import mock +from contextlib import contextmanager + import netCDF4 as nc import numpy as np +from numpy import ma import iris -from iris.coord_systems import GeogCS, TransverseMercator +from iris._lazy_data import as_lazy_data +from iris.coord_systems import (GeogCS, TransverseMercator, RotatedGeogCS, + LambertConformal, Mercator, Stereographic, + LambertAzimuthalEqualArea, + AlbersEqualArea) from iris.coords import DimCoord from iris.cube import Cube from iris.fileformats.netcdf import Saver +from iris.tests import mock +import iris.tests.stock as stock class Test_write(tests.IrisTest): @@ -37,14 +49,39 @@ def _transverse_mercator_cube(self, ellipsoid=None): cube = Cube(data, 'air_pressure_anomaly') trans_merc = TransverseMercator(49.0, -2.0, -400000.0, 100000.0, 0.9996012717, ellipsoid) - coord = DimCoord(range(3), 'projection_y_coordinate', units='m', + coord = DimCoord(np.arange(3), 'projection_y_coordinate', units='m', coord_system=trans_merc) cube.add_dim_coord(coord, 0) - coord = DimCoord(range(4), 'projection_x_coordinate', units='m', + coord = DimCoord(np.arange(4), 'projection_x_coordinate', units='m', coord_system=trans_merc) cube.add_dim_coord(coord, 1) return cube + def _mercator_cube(self, ellipsoid=None): + data = np.arange(12).reshape(3, 4) + cube = Cube(data, 'air_pressure_anomaly') + merc = Mercator(49.0, ellipsoid) + coord = DimCoord(np.arange(3), 'projection_y_coordinate', units='m', + coord_system=merc) + cube.add_dim_coord(coord, 0) + coord = DimCoord(np.arange(4), 'projection_x_coordinate', units='m', + coord_system=merc) + cube.add_dim_coord(coord, 1) + return cube + + def _stereo_cube(self, ellipsoid=None): + data = np.arange(12).reshape(3, 4) + cube = Cube(data, 'air_pressure_anomaly') + stereo = Stereographic(-10.0, 20.0, 500000.0, -200000.0, None, + ellipsoid) + coord = DimCoord(np.arange(3), 'projection_y_coordinate', units='m', + coord_system=stereo) + cube.add_dim_coord(coord, 0) + coord = DimCoord(np.arange(4), 'projection_x_coordinate', units='m', + coord_system=stereo) + cube.add_dim_coord(coord, 1) + return cube + def test_transverse_mercator(self): # Create a Cube with a transverse Mercator coordinate system. ellipsoid = GeogCS(6377563.396, 6356256.909) @@ -62,6 +99,40 @@ def test_transverse_mercator_no_ellipsoid(self): saver.write(cube) self.assertCDL(nc_path) + def test_mercator(self): + # Create a Cube with a Mercator coordinate system. + ellipsoid = GeogCS(6377563.396, 6356256.909) + cube = self._mercator_cube(ellipsoid) + with self.temp_filename('.nc') as nc_path: + with Saver(nc_path, 'NETCDF4') as saver: + saver.write(cube) + self.assertCDL(nc_path) + + def test_stereographic(self): + # Create a Cube with a stereographic coordinate system. + ellipsoid = GeogCS(6377563.396, 6356256.909) + cube = self._stereo_cube(ellipsoid) + with self.temp_filename('.nc') as nc_path: + with Saver(nc_path, 'NETCDF4') as saver: + saver.write(cube) + self.assertCDL(nc_path) + + def test_mercator_no_ellipsoid(self): + # Create a Cube with a Mercator coordinate system. + cube = self._mercator_cube() + with self.temp_filename('.nc') as nc_path: + with Saver(nc_path, 'NETCDF4') as saver: + saver.write(cube) + self.assertCDL(nc_path) + + def test_stereographic_no_ellipsoid(self): + # Create a Cube with a stereographic coordinate system. + cube = self._stereo_cube() + with self.temp_filename('.nc') as nc_path: + with Saver(nc_path, 'NETCDF4') as saver: + saver.write(cube) + self.assertCDL(nc_path) + def _simple_cube(self, dtype): data = np.arange(12, dtype=dtype).reshape(3, 4) points = np.arange(3, dtype=dtype) @@ -77,7 +148,8 @@ def test_little_endian(self): with self.temp_filename('.nc') as nc_path: with Saver(nc_path, 'NETCDF4') as saver: saver.write(cube) - self.assertCDL(nc_path, basename='endian', flags='') + result_path = self.result_path('endian', 'cdl') + self.assertCDL(nc_path, result_path, flags='') def test_big_endian(self): # Create a Cube with big-endian data. @@ -85,7 +157,8 @@ def test_big_endian(self): with self.temp_filename('.nc') as nc_path: with Saver(nc_path, 'NETCDF4') as saver: saver.write(cube) - self.assertCDL(nc_path, basename='endian', flags='') + result_path = self.result_path('endian', 'cdl') + self.assertCDL(nc_path, result_path, flags='') def test_zlib(self): cube = self._simple_cube('>f4') @@ -108,18 +181,19 @@ def test_least_significant_digit(self): with Saver(nc_path, 'NETCDF4') as saver: saver.write(cube, least_significant_digit=1) cube_saved = iris.load_cube(nc_path) - self.assertEquals( + self.assertEqual( cube_saved.attributes['least_significant_digit'], 1) self.assertFalse(np.all(cube.data == cube_saved.data)) self.assertArrayAllClose(cube.data, cube_saved.data, 0.1) def test_default_unlimited_dimensions(self): + # Default is no unlimited dimensions. cube = self._simple_cube('>f4') with self.temp_filename('.nc') as nc_path: with Saver(nc_path, 'NETCDF4') as saver: saver.write(cube) ds = nc.Dataset(nc_path) - self.assertTrue(ds.dimensions['dim0'].isunlimited()) + self.assertFalse(ds.dimensions['dim0'].isunlimited()) self.assertFalse(ds.dimensions['dim1'].isunlimited()) ds.close() @@ -127,9 +201,9 @@ def test_no_unlimited_dimensions(self): cube = self._simple_cube('>f4') with self.temp_filename('.nc') as nc_path: with Saver(nc_path, 'NETCDF4') as saver: - saver.write(cube, unlimited_dimensions=[]) + saver.write(cube, unlimited_dimensions=None) ds = nc.Dataset(nc_path) - for dim in ds.dimensions.itervalues(): + for dim in six.itervalues(ds.dimensions): self.assertFalse(dim.isunlimited()) ds.close() @@ -162,6 +236,604 @@ def test_custom_unlimited_dimensions(self): self.assertTrue(ds.dimensions[dim].isunlimited()) ds.close() + def test_reserved_attributes(self): + cube = self._simple_cube('>f4') + cube.attributes['dimensions'] = 'something something_else' + with self.temp_filename('.nc') as nc_path: + with Saver(nc_path, 'NETCDF4') as saver: + saver.write(cube) + ds = nc.Dataset(nc_path) + res = ds.getncattr('dimensions') + ds.close() + self.assertEqual(res, 'something something_else') + + +class Test_write__valid_x_cube_attributes(tests.IrisTest): + """Testing valid_range, valid_min and valid_max attributes.""" + + def test_valid_range_saved(self): + cube = tests.stock.lat_lon_cube() + cube.data = cube.data.astype('int32') + + vrange = np.array([1, 2], dtype='int32') + cube.attributes['valid_range'] = vrange + with self.temp_filename('.nc') as nc_path: + with Saver(nc_path, 'NETCDF4') as saver: + saver.write(cube, unlimited_dimensions=[]) + ds = nc.Dataset(nc_path) + self.assertArrayEqual(ds.valid_range, vrange) + ds.close() + + def test_valid_min_saved(self): + cube = tests.stock.lat_lon_cube() + cube.data = cube.data.astype('int32') + + cube.attributes['valid_min'] = 1 + with self.temp_filename('.nc') as nc_path: + with Saver(nc_path, 'NETCDF4') as saver: + saver.write(cube, unlimited_dimensions=[]) + ds = nc.Dataset(nc_path) + self.assertArrayEqual(ds.valid_min, 1) + ds.close() + + def test_valid_max_saved(self): + cube = tests.stock.lat_lon_cube() + cube.data = cube.data.astype('int32') + + cube.attributes['valid_max'] = 2 + with self.temp_filename('.nc') as nc_path: + with Saver(nc_path, 'NETCDF4') as saver: + saver.write(cube, unlimited_dimensions=[]) + ds = nc.Dataset(nc_path) + self.assertArrayEqual(ds.valid_max, 2) + ds.close() + + +class Test_write__valid_x_coord_attributes(tests.IrisTest): + """Testing valid_range, valid_min and valid_max attributes.""" + + def test_valid_range_saved(self): + cube = tests.stock.lat_lon_cube() + cube.data = cube.data.astype('int32') + + vrange = np.array([1, 2], dtype='int32') + cube.coord(axis='x').attributes['valid_range'] = vrange + with self.temp_filename('.nc') as nc_path: + with Saver(nc_path, 'NETCDF4') as saver: + saver.write(cube, unlimited_dimensions=[]) + ds = nc.Dataset(nc_path) + self.assertArrayEqual(ds.variables['longitude'].valid_range, + vrange) + ds.close() + + def test_valid_min_saved(self): + cube = tests.stock.lat_lon_cube() + cube.data = cube.data.astype('int32') + + cube.coord(axis='x').attributes['valid_min'] = 1 + with self.temp_filename('.nc') as nc_path: + with Saver(nc_path, 'NETCDF4') as saver: + saver.write(cube, unlimited_dimensions=[]) + ds = nc.Dataset(nc_path) + self.assertArrayEqual(ds.variables['longitude'].valid_min, 1) + ds.close() + + def test_valid_max_saved(self): + cube = tests.stock.lat_lon_cube() + cube.data = cube.data.astype('int32') + + cube.coord(axis='x').attributes['valid_max'] = 2 + with self.temp_filename('.nc') as nc_path: + with Saver(nc_path, 'NETCDF4') as saver: + saver.write(cube, unlimited_dimensions=[]) + ds = nc.Dataset(nc_path) + self.assertArrayEqual(ds.variables['longitude'].valid_max, 2) + ds.close() + + +class Test_write_fill_value(tests.IrisTest): + def _make_cube(self, dtype, lazy=False, masked_value=None, + masked_index=None): + data = np.arange(12, dtype=dtype).reshape(3, 4) + if masked_value is not None: + data = ma.masked_equal(data, masked_value) + if masked_index is not None: + data = np.ma.masked_array(data) + data[masked_index] = ma.masked + if lazy: + data = as_lazy_data(data) + lat = DimCoord(np.arange(3), 'latitude', units='degrees') + lon = DimCoord(np.arange(4), 'longitude', units='degrees') + return Cube(data, standard_name='air_temperature', units='K', + dim_coords_and_dims=[(lat, 0), (lon, 1)]) + + @contextmanager + def _netCDF_var(self, cube, **kwargs): + # Get the netCDF4 Variable for a cube from a temp file + standard_name = cube.standard_name + with self.temp_filename('.nc') as nc_path: + with Saver(nc_path, 'NETCDF4') as saver: + saver.write(cube, **kwargs) + ds = nc.Dataset(nc_path) + var, = [var for var in ds.variables.values() + if var.standard_name == standard_name] + yield var + + def test_fill_value(self): + # Test that a passed fill value is saved as a _FillValue attribute. + cube = self._make_cube('>f4') + fill_value = 12345. + with self._netCDF_var(cube, fill_value=fill_value) as var: + self.assertEqual(fill_value, var._FillValue) + + def test_default_fill_value(self): + # Test that if no fill value is passed then there is no _FillValue. + # attribute. + cube = self._make_cube('>f4') + with self._netCDF_var(cube) as var: + self.assertNotIn('_FillValue', var.ncattrs()) + + def test_mask_fill_value(self): + # Test that masked data saves correctly when given a fill value. + index = (1, 1) + fill_value = 12345. + cube = self._make_cube('>f4', masked_index=index) + with self._netCDF_var(cube, fill_value=fill_value) as var: + self.assertEqual(fill_value, var._FillValue) + self.assertTrue(var[index].mask) + + def test_mask_default_fill_value(self): + # Test that masked data saves correctly using the default fill value. + index = (1, 1) + cube = self._make_cube('>f4', masked_index=index) + with self._netCDF_var(cube) as var: + self.assertNotIn('_FillValue', var.ncattrs()) + self.assertTrue(var[index].mask) + + def test_mask_lazy_fill_value(self): + # Test that masked lazy data saves correctly when given a fill value. + index = (1, 1) + fill_value = 12345. + cube = self._make_cube('>f4', masked_index=index, lazy=True) + with self._netCDF_var(cube, fill_value=fill_value) as var: + self.assertEqual(var._FillValue, fill_value) + self.assertTrue(var[index].mask) + + def test_mask_lazy_default_fill_value(self): + # Test that masked lazy data saves correctly using the default fill + # value. + index = (1, 1) + cube = self._make_cube('>f4', masked_index=index, lazy=True) + with self._netCDF_var(cube) as var: + self.assertNotIn('_FillValue', var.ncattrs()) + self.assertTrue(var[index].mask) + + def test_contains_fill_value_passed(self): + # Test that a warning is raised if the data contains the fill value. + cube = self._make_cube('>f4') + fill_value = 1 + with self.assertWarnsRegexp( + 'contains unmasked data points equal to the fill-value'): + with self._netCDF_var(cube, fill_value=fill_value): + pass + + def test_contains_fill_value_byte(self): + # Test that a warning is raised if the data contains the fill value + # when it is of a byte type. + cube = self._make_cube('>i1') + fill_value = 1 + with self.assertWarnsRegexp( + 'contains unmasked data points equal to the fill-value'): + with self._netCDF_var(cube, fill_value=fill_value): + pass + + def test_contains_default_fill_value(self): + # Test that a warning is raised if the data contains the default fill + # value if no fill_value argument is supplied. + cube = self._make_cube('>f4') + cube.data[0, 0] = nc.default_fillvals['f4'] + with self.assertWarnsRegexp( + 'contains unmasked data points equal to the fill-value'): + with self._netCDF_var(cube): + pass + + def test_contains_default_fill_value_byte(self): + # Test that no warning is raised if the data contains the default fill + # value if no fill_value argument is supplied when the data is of a + # byte type. + cube = self._make_cube('>i1') + with self.assertNoWarningsRegexp(r'\(fill\|mask\)'): + with self._netCDF_var(cube): + pass + + def test_contains_masked_fill_value(self): + # Test that no warning is raised if the data contains the fill_value at + # a masked point. + fill_value = 1 + cube = self._make_cube('>f4', masked_value=fill_value) + with self.assertNoWarningsRegexp(r'\(fill\|mask\)'): + with self._netCDF_var(cube, fill_value=fill_value): + pass + + def test_masked_byte_default_fill_value(self): + # Test that a warning is raised when saving masked byte data with no + # fill value supplied. + cube = self._make_cube('>i1', masked_value=1) + with self.assertNoWarningsRegexp(r'\(fill\|mask\)'): + with self._netCDF_var(cube): + pass + + def test_masked_byte_fill_value_passed(self): + # Test that no warning is raised when saving masked byte data with a + # fill value supplied if the the data does not contain the fill_value. + fill_value = 100 + cube = self._make_cube('>i1', masked_value=2) + with self.assertNoWarningsRegexp(r'\(fill\|mask\)'): + with self._netCDF_var(cube, fill_value=fill_value): + pass + + +class Test_cf_valid_var_name(tests.IrisTest): + def test_no_replacement(self): + self.assertEqual(Saver.cf_valid_var_name('valid_Nam3'), + 'valid_Nam3') + + def test_special_chars(self): + self.assertEqual(Saver.cf_valid_var_name('inv?alid'), + 'inv_alid') + + def test_leading_underscore(self): + self.assertEqual(Saver.cf_valid_var_name('_invalid'), + 'var__invalid') + + def test_leading_number(self): + self.assertEqual(Saver.cf_valid_var_name('2invalid'), + 'var_2invalid') + + def test_leading_invalid(self): + self.assertEqual(Saver.cf_valid_var_name('?invalid'), + 'var__invalid') + + def test_no_hyphen(self): + # CF explicitly prohibits hyphen, even though it is fine in NetCDF. + self.assertEqual(Saver.cf_valid_var_name('valid-netcdf'), + 'valid_netcdf') + + +class _Common__check_attribute_compliance(object): + def setUp(self): + self.container = mock.Mock(name='container', attributes={}) + self.data = np.array(1, dtype='int32') + + patch = mock.patch('netCDF4.Dataset') + mock_netcdf_dataset = patch.start() + self.addCleanup(patch.stop) + + def set_attribute(self, value): + self.container.attributes[self.attribute] = value + + def assertAttribute(self, value): + self.assertEqual( + np.asarray(self.container.attributes[self.attribute]).dtype, + value) + + def check_attribute_compliance_call(self, value): + self.set_attribute(value) + with Saver(mock.Mock(), 'NETCDF4') as saver: + saver.check_attribute_compliance(self.container, self.data) + + +class Test_check_attribute_compliance__valid_range( + _Common__check_attribute_compliance, tests.IrisTest): + + @property + def attribute(self): + return 'valid_range' + + def test_valid_range_type_coerce(self): + value = np.array([1, 2], dtype='float') + self.check_attribute_compliance_call(value) + self.assertAttribute(self.data.dtype) + + def test_valid_range_unsigned_int8_data_signed_range(self): + self.data = self.data.astype('uint8') + value = np.array([1, 2], dtype='int8') + self.check_attribute_compliance_call(value) + self.assertAttribute(value.dtype) + + def test_valid_range_cannot_coerce(self): + value = np.array([1.5, 2.5], dtype='float64') + msg = '"valid_range" is not of a suitable value' + with self.assertRaisesRegexp(ValueError, msg): + self.check_attribute_compliance_call(value) + + def test_valid_range_not_numpy_array(self): + # Ensure we handle the case when not a numpy array is provided. + self.data = self.data.astype('int8') + value = [1, 2] + self.check_attribute_compliance_call(value) + self.assertAttribute(np.int64) + + +class Test_check_attribute_compliance__valid_min( + _Common__check_attribute_compliance, tests.IrisTest): + + @property + def attribute(self): + return 'valid_min' + + def test_valid_range_type_coerce(self): + value = np.array(1, dtype='float') + self.check_attribute_compliance_call(value) + self.assertAttribute(self.data.dtype) + + def test_valid_range_unsigned_int8_data_signed_range(self): + self.data = self.data.astype('uint8') + value = np.array(1, dtype='int8') + self.check_attribute_compliance_call(value) + self.assertAttribute(value.dtype) + + def test_valid_range_cannot_coerce(self): + value = np.array(1.5, dtype='float64') + msg = '"valid_min" is not of a suitable value' + with self.assertRaisesRegexp(ValueError, msg): + self.check_attribute_compliance_call(value) + + def test_valid_range_not_numpy_array(self): + # Ensure we handle the case when not a numpy array is provided. + self.data = self.data.astype('int8') + value = 1 + self.check_attribute_compliance_call(value) + self.assertAttribute(np.int64) + + +class Test_check_attribute_compliance__valid_max( + _Common__check_attribute_compliance, tests.IrisTest): + + @property + def attribute(self): + return 'valid_max' + + def test_valid_range_type_coerce(self): + value = np.array(2, dtype='float') + self.check_attribute_compliance_call(value) + self.assertAttribute(self.data.dtype) + + def test_valid_range_unsigned_int8_data_signed_range(self): + self.data = self.data.astype('uint8') + value = np.array(2, dtype='int8') + self.check_attribute_compliance_call(value) + self.assertAttribute(value.dtype) + + def test_valid_range_cannot_coerce(self): + value = np.array(2.5, dtype='float64') + msg = '"valid_max" is not of a suitable value' + with self.assertRaisesRegexp(ValueError, msg): + self.check_attribute_compliance_call(value) + + def test_valid_range_not_numpy_array(self): + # Ensure we handle the case when not a numpy array is provided. + self.data = self.data.astype('int8') + value = 2 + self.check_attribute_compliance_call(value) + self.assertAttribute(np.int64) + + +class Test_check_attribute_compliance__exception_handlng( + _Common__check_attribute_compliance, tests.IrisTest): + + def test_valid_range_and_valid_min_valid_max_provided(self): + # Conflicting attributes should raise a suitable exception. + self.data = self.data.astype('int8') + self.container.attributes['valid_range'] = [1, 2] + self.container.attributes['valid_min'] = [1] + msg = 'Both "valid_range" and "valid_min"' + with Saver(mock.Mock(), 'NETCDF4') as saver: + with self.assertRaisesRegexp(ValueError, msg): + saver.check_attribute_compliance(self.container, self.data) + + +class Test__cf_coord_identity(tests.IrisTest): + def check_call(self, coord_name, coord_system, units, expected_units): + coord = iris.coords.DimCoord([30, 45], coord_name, units=units, + coord_system=coord_system) + result = Saver._cf_coord_identity(coord) + self.assertEqual(result, (coord.standard_name, coord.long_name, + expected_units)) + + def test_geogcs_latitude(self): + crs = iris.coord_systems.GeogCS(60, 0) + self.check_call('latitude', coord_system=crs, units='degrees', + expected_units='degrees_north') + + def test_geogcs_longitude(self): + crs = iris.coord_systems.GeogCS(60, 0) + self.check_call('longitude', coord_system=crs, units='degrees', + expected_units='degrees_east') + + def test_no_coord_system_latitude(self): + self.check_call('latitude', coord_system=None, units='degrees', + expected_units='degrees_north') + + def test_no_coord_system_longitude(self): + self.check_call('longitude', coord_system=None, units='degrees', + expected_units='degrees_east') + + def test_passthrough_units(self): + crs = iris.coord_systems.LambertConformal(0, 20) + self.check_call('projection_x_coordinate', coord_system=crs, + units='km', expected_units='km') + + +class Test__create_cf_grid_mapping(tests.IrisTest): + def _cube_with_cs(self, coord_system): + """Return a simple 2D cube that uses the given coordinate system.""" + cube = stock.lat_lon_cube() + x, y = cube.coord('longitude'), cube.coord('latitude') + x.coord_system = y.coord_system = coord_system + return cube + + def _grid_mapping_variable(self, coord_system): + """ + Return a mock netCDF variable that represents the conversion + of the given coordinate system. + + """ + cube = self._cube_with_cs(coord_system) + + class NCMock(mock.Mock): + def setncattr(self, name, attr): + setattr(self, name, attr) + + # Calls the actual NetCDF saver with appropriate mocking, returning + # the grid variable that gets created. + grid_variable = NCMock(name='NetCDFVariable') + create_var_fn = mock.Mock(side_effect=[grid_variable]) + dataset = mock.Mock(variables=[], + createVariable=create_var_fn) + saver = mock.Mock(spec=Saver, _coord_systems=[], + _dataset=dataset) + variable = NCMock() + + # This is the method we're actually testing! + Saver._create_cf_grid_mapping(saver, cube, variable) + + self.assertEqual(create_var_fn.call_count, 1) + self.assertEqual(variable.grid_mapping, + grid_variable.grid_mapping_name) + return grid_variable + + def _variable_attributes(self, coord_system): + """ + Return the attributes dictionary for the grid mapping variable + that is created from the given coordinate system. + + """ + mock_grid_variable = self._grid_mapping_variable(coord_system) + + # Get the attributes defined on the mock object. + attributes = sorted(mock_grid_variable.__dict__.keys()) + attributes = [name for name in attributes if not name.startswith('_')] + attributes.remove('method_calls') + return {key: getattr(mock_grid_variable, key) for key in attributes} + + def _test(self, coord_system, expected): + actual = self._variable_attributes(coord_system) + + # To see obvious differences, check that they keys are the same. + self.assertEqual(sorted(actual.keys()), sorted(expected.keys())) + # Now check that the values are equivalent. + self.assertEqual(actual, expected) + + def test_rotated_geog_cs(self): + coord_system = RotatedGeogCS(37.5, 177.5, ellipsoid=GeogCS(6371229.0)) + expected = {'grid_mapping_name': b'rotated_latitude_longitude', + 'north_pole_grid_longitude': 0.0, + 'grid_north_pole_longitude': 177.5, + 'grid_north_pole_latitude': 37.5, + 'longitude_of_prime_meridian': 0.0, + 'earth_radius': 6371229.0, + } + self._test(coord_system, expected) + + def test_spherical_geog_cs(self): + coord_system = GeogCS(6371229.0) + expected = {'grid_mapping_name': b'latitude_longitude', + 'longitude_of_prime_meridian': 0.0, + 'earth_radius': 6371229.0 + } + self._test(coord_system, expected) + + def test_elliptic_geog_cs(self): + coord_system = GeogCS(637, 600) + expected = {'grid_mapping_name': b'latitude_longitude', + 'longitude_of_prime_meridian': 0.0, + 'semi_minor_axis': 600.0, + 'semi_major_axis': 637.0, + } + self._test(coord_system, expected) + + def test_lambert_conformal(self): + coord_system = LambertConformal(central_lat=44, central_lon=2, + false_easting=-2, false_northing=-5, + secant_latitudes=(38, 50), + ellipsoid=GeogCS(6371000)) + expected = {'grid_mapping_name': b'lambert_conformal_conic', + 'latitude_of_projection_origin': 44, + 'longitude_of_central_meridian': 2, + 'false_easting': -2, 'false_northing': -5, + 'standard_parallel': (38, 50), + 'earth_radius': 6371000, + 'longitude_of_prime_meridian': 0, + } + self._test(coord_system, expected) + + def test_laea_cs(self): + coord_system = LambertAzimuthalEqualArea( + latitude_of_projection_origin=52, + longitude_of_projection_origin=10, + false_easting=100, + false_northing=200, + ellipsoid=GeogCS(6377563.396, 6356256.909)) + expected = {'grid_mapping_name': b'lambert_azimuthal_equal_area', + 'latitude_of_projection_origin': 52, + 'longitude_of_projection_origin': 10, + 'false_easting': 100, + 'false_northing': 200, + 'semi_major_axis': 6377563.396, + 'semi_minor_axis': 6356256.909, + 'longitude_of_prime_meridian': 0, + } + self._test(coord_system, expected) + + def test_aea_cs(self): + coord_system = AlbersEqualArea( + latitude_of_projection_origin=52, + longitude_of_central_meridian=10, + false_easting=100, + false_northing=200, + standard_parallels=(38, 50), + ellipsoid=GeogCS(6377563.396, 6356256.909)) + expected = {'grid_mapping_name': b'albers_conical_equal_area', + 'latitude_of_projection_origin': 52, + 'longitude_of_central_meridian': 10, + 'false_easting': 100, + 'false_northing': 200, + 'standard_parallel': (38, 50), + 'semi_major_axis': 6377563.396, + 'semi_minor_axis': 6356256.909, + 'longitude_of_prime_meridian': 0, + } + self._test(coord_system, expected) + + +class Test__create_cf_cell_measure_variable(tests.IrisTest): + # Saving of masked data is disallowed. + def setUp(self): + self.cube = stock.lat_lon_cube() + self.names_map = ['latitude', 'longitude'] + masked_array = np.ma.masked_array([0, 1, 2], mask=[True, False, True]) + self.cm = iris.coords.CellMeasure(masked_array, + measure='area', var_name='cell_area') + self.cube.add_cell_measure(self.cm, data_dims=0) + self.exp_emsg = 'Cell measures with missing data are not supported.' + + def test_masked_data__insitu(self): + # Test that the error is raised in the right place. + with self.temp_filename('.nc') as nc_path: + saver = Saver(nc_path, 'NETCDF4') + with self.assertRaisesRegexp(ValueError, self.exp_emsg): + saver._create_cf_cell_measure_variable(self.cube, + self.names_map, + self.cm) + + def test_masked_data__save_pipeline(self): + # Test that the right error is raised by the saver pipeline. + with self.temp_filename('.nc') as nc_path: + with Saver(nc_path, 'NETCDF4') as saver: + with self.assertRaisesRegexp(ValueError, self.exp_emsg): + saver.write(self.cube) + if __name__ == "__main__": tests.main() diff --git a/lib/iris/tests/unit/fileformats/netcdf/test__FillValueMaskCheckAndStoreTarget.py b/lib/iris/tests/unit/fileformats/netcdf/test__FillValueMaskCheckAndStoreTarget.py new file mode 100644 index 0000000000..7365e2a902 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/netcdf/test__FillValueMaskCheckAndStoreTarget.py @@ -0,0 +1,104 @@ +# (C) British Crown Copyright 2017 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the `iris.fileformats.netcdf._FillValueMaskCheckAndStoreTarget` +class. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.fileformats.netcdf import _FillValueMaskCheckAndStoreTarget +from iris.tests import mock + + +class Test__FillValueMaskCheckAndStoreTarget(tests.IrisTest): + def _call_target(self, fill_value, keys, vals): + inner_target = mock.MagicMock() + target = _FillValueMaskCheckAndStoreTarget(inner_target, + fill_value=fill_value) + + for key, val in zip(keys, vals): + target[key] = val + + calls = [mock.call(key, val) for key, val in zip(keys, vals)] + inner_target.__setitem__.assert_has_calls(calls) + + return target + + def test___setitem__(self): + self._call_target(None, [1], [2]) + + def test_no_fill_value_not_masked(self): + # Test when the fill value is not present and the data is not masked + keys = [slice(0, 10), slice(10, 15)] + vals = [np.arange(10), np.arange(5)] + fill_value = 16 + target = self._call_target(fill_value, keys, vals) + self.assertFalse(target.contains_value) + self.assertFalse(target.is_masked) + + def test_contains_fill_value_not_masked(self): + # Test when the fill value is present and the data is not masked + keys = [slice(0, 10), slice(10, 15)] + vals = [np.arange(10), np.arange(5)] + fill_value = 5 + target = self._call_target(fill_value, keys, vals) + self.assertTrue(target.contains_value) + self.assertFalse(target.is_masked) + + def test_no_fill_value_masked(self): + # Test when the fill value is not present and the data is masked + keys = [slice(0, 10), slice(10, 15)] + vals = [np.arange(10), np.ma.masked_equal(np.arange(5), 3)] + fill_value = 16 + target = self._call_target(fill_value, keys, vals) + self.assertFalse(target.contains_value) + self.assertTrue(target.is_masked) + + def test_contains_fill_value_masked(self): + # Test when the fill value is present and the data is masked + keys = [slice(0, 10), slice(10, 15)] + vals = [np.arange(10), np.ma.masked_equal(np.arange(5), 3)] + fill_value = 5 + target = self._call_target(fill_value, keys, vals) + self.assertTrue(target.contains_value) + self.assertTrue(target.is_masked) + + def test_fill_value_None(self): + # Test when the fill value is None + keys = [slice(0, 10), slice(10, 15)] + vals = [np.arange(10), np.arange(5)] + fill_value = None + target = self._call_target(fill_value, keys, vals) + self.assertFalse(target.contains_value) + + def test_contains_masked_fill_value(self): + # Test when the fill value is present but masked the data is masked + keys = [slice(0, 10), slice(10, 15)] + vals = [np.arange(10), np.ma.masked_equal(np.arange(10, 15), 13)] + fill_value = 13 + target = self._call_target(fill_value, keys, vals) + self.assertFalse(target.contains_value) + self.assertTrue(target.is_masked) diff --git a/lib/iris/tests/unit/fileformats/netcdf/test__get_cf_var_data.py b/lib/iris/tests/unit/fileformats/netcdf/test__get_cf_var_data.py new file mode 100644 index 0000000000..6a1aeb9d61 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/netcdf/test__get_cf_var_data.py @@ -0,0 +1,83 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.fileformats.netcdf._get_cf_var_data` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from dask.array import Array as dask_array +import numpy as np + +from iris._lazy_data import _limited_shape +import iris.fileformats.cf +from iris.fileformats.netcdf import _get_cf_var_data +from iris.tests import mock + + +class Test__get_cf_var_data(tests.IrisTest): + def setUp(self): + self.filename = 'DUMMY' + self.shape = (3, 240, 200) + self.expected_chunks = _limited_shape(self.shape) + + def _make(self, chunksizes): + cf_data = mock.Mock(_FillValue=None) + cf_data.chunking = mock.MagicMock(return_value=chunksizes) + cf_var = mock.MagicMock(spec=iris.fileformats.cf.CFVariable, + dtype=np.dtype('i4'), + cf_data=cf_data, + cf_name='DUMMY_VAR', + shape=self.shape) + return cf_var + + def test_cf_data_type(self): + chunks = [1, 12, 100] + cf_var = self._make(chunks) + lazy_data = _get_cf_var_data(cf_var, self.filename) + self.assertIsInstance(lazy_data, dask_array) + + def test_cf_data_chunks(self): + chunks = [1, 12, 100] + cf_var = self._make(chunks) + lazy_data = _get_cf_var_data(cf_var, self.filename) + lazy_data_chunks = [c[0] for c in lazy_data.chunks] + self.assertArrayEqual(chunks, lazy_data_chunks) + + def test_cf_data_no_chunks(self): + # No chunks means chunks are calculated from the array's shape by + # `iris._lazy_data._limited_shape()`. + chunks = None + cf_var = self._make(chunks) + lazy_data = _get_cf_var_data(cf_var, self.filename) + lazy_data_chunks = [c[0] for c in lazy_data.chunks] + self.assertArrayEqual(lazy_data_chunks, self.expected_chunks) + + def test_cf_data_contiguous(self): + # Chunks 'contiguous' is equivalent to no chunks. + chunks = 'contiguous' + cf_var = self._make(chunks) + lazy_data = _get_cf_var_data(cf_var, self.filename) + lazy_data_chunks = [c[0] for c in lazy_data.chunks] + self.assertArrayEqual(lazy_data_chunks, self.expected_chunks) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/netcdf/test__load_aux_factory.py b/lib/iris/tests/unit/fileformats/netcdf/test__load_aux_factory.py new file mode 100644 index 0000000000..797d6939f3 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/netcdf/test__load_aux_factory.py @@ -0,0 +1,154 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.fileformats.netcdf._load_aux_factory` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np +import warnings + +from iris.coords import DimCoord +from iris.cube import Cube +from iris.fileformats.netcdf import _load_aux_factory +from iris.tests import mock + + +class TestAtmosphereHybridSigmaPressureCoordinate(tests.IrisTest): + def setUp(self): + standard_name = 'atmosphere_hybrid_sigma_pressure_coordinate' + self.requires = dict(formula_type=standard_name) + coordinates = [(mock.sentinel.b, 'b'), (mock.sentinel.ps, 'ps')] + self.provides = dict(coordinates=coordinates) + self.engine = mock.Mock(requires=self.requires, provides=self.provides) + self.cube = mock.create_autospec(Cube, spec_set=True, instance=True) + # Patch out the check_dependencies functionality. + func = 'iris.aux_factory.HybridPressureFactory._check_dependencies' + patcher = mock.patch(func) + patcher.start() + self.addCleanup(patcher.stop) + + def test_formula_terms_ap(self): + self.provides['coordinates'].append((mock.sentinel.ap, 'ap')) + self.requires['formula_terms'] = dict(ap='ap', b='b', ps='ps') + _load_aux_factory(self.engine, self.cube) + # Check cube.add_aux_coord method. + self.assertEqual(self.cube.add_aux_coord.call_count, 0) + # Check cube.add_aux_factory method. + self.assertEqual(self.cube.add_aux_factory.call_count, 1) + args, _ = self.cube.add_aux_factory.call_args + self.assertEqual(len(args), 1) + factory = args[0] + self.assertEqual(factory.delta, mock.sentinel.ap) + self.assertEqual(factory.sigma, mock.sentinel.b) + self.assertEqual(factory.surface_air_pressure, mock.sentinel.ps) + + def test_formula_terms_a_p0(self): + coord_a = DimCoord(np.arange(5), units='Pa') + coord_p0 = DimCoord(10, units='1') + coord_expected = DimCoord(np.arange(5) * 10, units='Pa', + long_name='vertical pressure', var_name='ap') + self.provides['coordinates'].extend([(coord_a, 'a'), (coord_p0, 'p0')]) + self.requires['formula_terms'] = dict(a='a', b='b', ps='ps', p0='p0') + _load_aux_factory(self.engine, self.cube) + # Check cube.coord_dims method. + self.assertEqual(self.cube.coord_dims.call_count, 1) + args, _ = self.cube.coord_dims.call_args + self.assertEqual(len(args), 1) + self.assertIs(args[0], coord_a) + # Check cube.add_aux_coord method. + self.assertEqual(self.cube.add_aux_coord.call_count, 1) + args, _ = self.cube.add_aux_coord.call_args + self.assertEqual(len(args), 2) + self.assertEqual(args[0], coord_expected) + self.assertIsInstance(args[1], mock.Mock) + # Check cube.add_aux_factory method. + self.assertEqual(self.cube.add_aux_factory.call_count, 1) + args, _ = self.cube.add_aux_factory.call_args + self.assertEqual(len(args), 1) + factory = args[0] + self.assertEqual(factory.delta, coord_expected) + self.assertEqual(factory.sigma, mock.sentinel.b) + self.assertEqual(factory.surface_air_pressure, mock.sentinel.ps) + + def test_formula_terms_p0_non_scalar(self): + coord_p0 = DimCoord(np.arange(5)) + self.provides['coordinates'].append((coord_p0, 'p0')) + self.requires['formula_terms'] = dict(p0='p0') + with self.assertRaises(ValueError): + _load_aux_factory(self.engine, self.cube) + + def test_formula_terms_p0_bounded(self): + coord_a = DimCoord(np.arange(5)) + coord_p0 = DimCoord(1, bounds=[0, 2], var_name='p0') + self.provides['coordinates'].extend([(coord_a, 'a'), (coord_p0, 'p0')]) + self.requires['formula_terms'] = dict(a='a', b='b', ps='ps', p0='p0') + with warnings.catch_warnings(record=True) as warn: + warnings.simplefilter('always') + _load_aux_factory(self.engine, self.cube) + self.assertEqual(len(warn), 1) + msg = 'Ignoring atmosphere hybrid sigma pressure scalar ' \ + 'coordinate {!r} bounds.'.format(coord_p0.name()) + self.assertEqual(msg, str(warn[0].message)) + + def _check_no_delta(self): + # Check cube.add_aux_coord method. + self.assertEqual(self.cube.add_aux_coord.call_count, 0) + # Check cube.add_aux_factory method. + self.assertEqual(self.cube.add_aux_factory.call_count, 1) + args, _ = self.cube.add_aux_factory.call_args + self.assertEqual(len(args), 1) + factory = args[0] + # Check that the factory has no delta term + self.assertEqual(factory.delta, None) + self.assertEqual(factory.sigma, mock.sentinel.b) + self.assertEqual(factory.surface_air_pressure, mock.sentinel.ps) + + def test_formula_terms_ap_missing_coords(self): + self.requires['formula_terms'] = dict(ap='ap', b='b', ps='ps') + with mock.patch('warnings.warn') as warn: + _load_aux_factory(self.engine, self.cube) + warn.assert_called_once_with("Unable to find coordinate for variable " + "'ap'") + self._check_no_delta() + + def test_formula_terms_no_delta_terms(self): + self.requires['formula_terms'] = dict(b='b', ps='ps') + _load_aux_factory(self.engine, self.cube) + self._check_no_delta() + + def test_formula_terms_no_p0_term(self): + coord_a = DimCoord(np.arange(5), units='Pa') + self.provides['coordinates'].append((coord_a, 'a')) + self.requires['formula_terms'] = dict(a='a', b='b', ps='ps') + _load_aux_factory(self.engine, self.cube) + self._check_no_delta() + + def test_formula_terms_no_a_term(self): + coord_p0 = DimCoord(10, units='1') + self.provides['coordinates'].append((coord_p0, 'p0')) + self.requires['formula_terms'] = dict(a='p0', b='b', ps='ps') + _load_aux_factory(self.engine, self.cube) + self._check_no_delta() + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/fileformats/netcdf/test__load_cube.py b/lib/iris/tests/unit/fileformats/netcdf/test__load_cube.py index 7cf563bd86..603547b707 100644 --- a/lib/iris/tests/unit/fileformats/netcdf/test__load_cube.py +++ b/lib/iris/tests/unit/fileformats/netcdf/test__load_cube.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2014, Met Office +# (C) British Crown Copyright 2014 - 2018, Met Office # # This file is part of Iris. # @@ -16,88 +16,164 @@ # along with Iris. If not, see . """Unit tests for the `iris.fileformats.netcdf._load_cube` function.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import iris.fileformats.cf -import mock import netCDF4 import numpy as np +from iris.coords import DimCoord +import iris.fileformats.cf from iris.fileformats.netcdf import _load_cube +from iris.tests import mock -class TestFillValue(tests.IrisTest): +class TestCoordAttributes(tests.IrisTest): + @staticmethod + def _patcher(engine, cf, cf_group): + coordinates = [] + for coord in cf_group: + engine.cube.add_aux_coord(coord) + coordinates.append((coord, coord.name())) + engine.provides['coordinates'] = coordinates + def setUp(self): - name = 'iris.fileformats.netcdf._assert_case_specific_facts' - patch = mock.patch(name) + this = 'iris.fileformats.netcdf._assert_case_specific_facts' + patch = mock.patch(this, side_effect=self._patcher) + patch.start() + self.addCleanup(patch.stop) + self.engine = mock.Mock() + self.filename = 'DUMMY' + self.flag_masks = mock.sentinel.flag_masks + self.flag_meanings = mock.sentinel.flag_meanings + self.flag_values = mock.sentinel.flag_values + self.valid_range = mock.sentinel.valid_range + self.valid_min = mock.sentinel.valid_min + self.valid_max = mock.sentinel.valid_max + + def _make(self, names, attrs): + coords = [DimCoord(i, long_name=name) for i, name in enumerate(names)] + shape = (1,) + + cf_group = {} + for name, cf_attrs in zip(names, attrs): + cf_attrs_unused = mock.Mock(return_value=cf_attrs) + cf_group[name] = mock.Mock(cf_attrs_unused=cf_attrs_unused) + cf = mock.Mock(cf_group=cf_group) + + cf_data = mock.Mock(_FillValue=None) + cf_data.chunking = mock.MagicMock(return_value=shape) + cf_var = mock.MagicMock(spec=iris.fileformats.cf.CFVariable, + dtype=np.dtype('i4'), + cf_data=cf_data, + cf_name='DUMMY_VAR', + cf_group=coords, + shape=shape) + return cf, cf_var + + def test_flag_pass_thru(self): + items = [('masks', 'flag_masks', self.flag_masks), + ('meanings', 'flag_meanings', self.flag_meanings), + ('values', 'flag_values', self.flag_values)] + for name, attr, value in items: + names = [name] + attrs = [[(attr, value)]] + cf, cf_var = self._make(names, attrs) + cube = _load_cube(self.engine, cf, cf_var, self.filename) + self.assertEqual(len(cube.coords(name)), 1) + coord = cube.coord(name) + self.assertEqual(len(coord.attributes), 1) + self.assertEqual(list(coord.attributes.keys()), [attr]) + self.assertEqual(list(coord.attributes.values()), [value]) + + def test_flag_pass_thru_multi(self): + names = ['masks', 'meanings', 'values'] + attrs = [[('flag_masks', self.flag_masks), + ('wibble', 'wibble')], + [('flag_meanings', self.flag_meanings), + ('add_offset', 'add_offset')], + [('flag_values', self.flag_values)], + [('valid_range', self.valid_range)], + [('valid_min', self.valid_min)], + [('valid_max', self.valid_max)]] + cf, cf_var = self._make(names, attrs) + cube = _load_cube(self.engine, cf, cf_var, self.filename) + self.assertEqual(len(cube.coords()), 3) + self.assertEqual(set([c.name() for c in cube.coords()]), set(names)) + expected = [attrs[0], + [attrs[1][0]], + attrs[2], + attrs[3], + attrs[4], + attrs[5]] + for name, expect in zip(names, expected): + attributes = cube.coord(name).attributes + self.assertEqual(set(attributes.items()), set(expect)) + + +class TestCubeAttributes(tests.IrisTest): + def setUp(self): + this = 'iris.fileformats.netcdf._assert_case_specific_facts' + patch = mock.patch(this) patch.start() self.addCleanup(patch.stop) - self.engine = mock.Mock() self.cf = None self.filename = 'DUMMY' - - def _make_cf_var(self, dtype): - variable = mock.Mock(spec=netCDF4.Variable, dtype=dtype) + self.flag_masks = mock.sentinel.flag_masks + self.flag_meanings = mock.sentinel.flag_meanings + self.flag_values = mock.sentinel.flag_values + self.valid_range = mock.sentinel.valid_range + self.valid_min = mock.sentinel.valid_min + self.valid_max = mock.sentinel.valid_max + + def _make(self, attrs): + shape = (1,) + cf_attrs_unused = mock.Mock(return_value=attrs) + cf_data = mock.Mock(_FillValue=None) + cf_data.chunking = mock.MagicMock(return_value=shape) cf_var = mock.MagicMock(spec=iris.fileformats.cf.CFVariable, - cf_data=variable, cf_name='DUMMY_VAR', - cf_group=mock.Mock(), dtype=dtype, - shape=mock.MagicMock()) + dtype=np.dtype('i4'), + cf_data=cf_data, + cf_name='DUMMY_VAR', + cf_group=mock.Mock(), + cf_attrs_unused=cf_attrs_unused, + shape=shape) return cf_var - def _test(self, cf_var, expected_fill_value): + def test_flag_pass_thru(self): + attrs = [('flag_masks', self.flag_masks), + ('flag_meanings', self.flag_meanings), + ('flag_values', self.flag_values)] + for key, value in attrs: + cf_var = self._make([(key, value)]) + cube = _load_cube(self.engine, self.cf, cf_var, self.filename) + self.assertEqual(len(cube.attributes), 1) + self.assertEqual(list(cube.attributes.keys()), [key]) + self.assertEqual(list(cube.attributes.values()), [value]) + + def test_flag_pass_thru_multi(self): + attrs = [('flag_masks', self.flag_masks), + ('wibble', 'wobble'), + ('flag_meanings', self.flag_meanings), + ('add_offset', 'add_offset'), + ('flag_values', self.flag_values), + ('standard_name', 'air_temperature'), + ('valid_range', self.valid_range), + ('valid_min', self.valid_min), + ('valid_max', self.valid_max)] + + # Expect everything from above to be returned except those + # corresponding to exclude_ind. + expected = set([attrs[ind] for ind in [0, 1, 2, 4, 6, 7, 8]]) + cf_var = self._make(attrs) cube = _load_cube(self.engine, self.cf, cf_var, self.filename) - self.assertEqual(cube._my_data.fill_value, expected_fill_value) - - def test_from_attribute_dtype_f4(self): - # A _FillValue attribute on the netCDF variable should end up as - # the fill_value for the cube. - dtype = np.dtype('f4') - cf_var = self._make_cf_var(dtype) - cf_var.cf_data._FillValue = mock.sentinel.FILL_VALUE - self._test(cf_var, mock.sentinel.FILL_VALUE) - - def test_from_default_dtype_f4(self): - # Without an explicit _FillValue attribute on the netCDF - # variable, the fill value should be selected from the default - # netCDF fill values. - dtype = np.dtype('f4') - cf_var = self._make_cf_var(dtype) - self._test(cf_var, netCDF4.default_fillvals['f4']) - - def test_from_attribute_dtype_i4(self): - # A _FillValue attribute on the netCDF variable should end up as - # the fill_value for the cube. - dtype = np.dtype('i4') - cf_var = self._make_cf_var(dtype) - cf_var.cf_data._FillValue = mock.sentinel.FILL_VALUE - self._test(cf_var, mock.sentinel.FILL_VALUE) - - def test_from_default_dtype_i4(self): - # Without an explicit _FillValue attribute on the netCDF - # variable, the fill value should be selected from the default - # netCDF fill values. - dtype = np.dtype('i4') - cf_var = self._make_cf_var(dtype) - self._test(cf_var, netCDF4.default_fillvals['i4']) - - def test_from_attribute_with_scale_offset(self): - # The _FillValue attribute still takes priority even when an - # offset/scale transformation takes place on the data. - dtype = np.dtype('i2') - cf_var = self._make_cf_var(dtype) - cf_var.scale_factor = np.float64(1.5) - cf_var.cf_data._FillValue = mock.sentinel.FILL_VALUE - self._test(cf_var, mock.sentinel.FILL_VALUE) - - def test_from_default_with_scale_offset(self): - # The fill value should be related to the *non-scaled* dtype. - dtype = np.dtype('i2') - cf_var = self._make_cf_var(dtype) - cf_var.scale_factor = np.float64(1.5) - self._test(cf_var, netCDF4.default_fillvals['i2']) + self.assertEqual(len(cube.attributes), len(expected)) + self.assertEqual(set(cube.attributes.items()), expected) if __name__ == "__main__": diff --git a/lib/iris/tests/unit/fileformats/netcdf/test_parse_cell_methods.py b/lib/iris/tests/unit/fileformats/netcdf/test_parse_cell_methods.py new file mode 100644 index 0000000000..d682f7b476 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/netcdf/test_parse_cell_methods.py @@ -0,0 +1,132 @@ +# (C) British Crown Copyright 2015 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for :func:`iris.fileformats.netcdf.parse_cell_methods`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +from iris.coords import CellMethod +from iris.fileformats.netcdf import parse_cell_methods +from iris.tests import mock + + +class Test(tests.IrisTest): + def test_simple(self): + cell_method_strings = [ + 'time: mean', + 'time : mean', + ] + expected = (CellMethod(method='mean', coords='time'),) + for cell_method_str in cell_method_strings: + res = parse_cell_methods(cell_method_str) + self.assertEqual(res, expected) + + def test_with_interval(self): + cell_method_strings = [ + 'time: variance (interval: 1 hr)', + 'time : variance (interval: 1 hr)', + ] + expected = (CellMethod(method='variance', coords='time', + intervals='1 hr'),) + for cell_method_str in cell_method_strings: + res = parse_cell_methods(cell_method_str) + self.assertEqual(res, expected) + + def test_multiple(self): + cell_method_strings = [ + 'time: maximum (interval: 1 hr) time: mean (interval: 1 day)', + 'time : maximum (interval: 1 hr) time: mean (interval: 1 day)', + 'time: maximum (interval: 1 hr) time : mean (interval: 1 day)', + 'time : maximum (interval: 1 hr) time : mean (interval: 1 day)', + ] + expected = (CellMethod(method='maximum', coords='time', + intervals='1 hr'), + CellMethod(method='mean', coords='time', + intervals='1 day')) + for cell_method_str in cell_method_strings: + res = parse_cell_methods(cell_method_str) + self.assertEqual(res, expected) + + def test_comment(self): + cell_method_strings = [ + 'time: maximum (interval: 1 hr comment: first bit) ' + 'time: mean (interval: 1 day comment: second bit)', + 'time : maximum (interval: 1 hr comment: first bit) ' + 'time: mean (interval: 1 day comment: second bit)', + 'time: maximum (interval: 1 hr comment: first bit) ' + 'time : mean (interval: 1 day comment: second bit)', + 'time : maximum (interval: 1 hr comment: first bit) ' + 'time : mean (interval: 1 day comment: second bit)', + ] + expected = (CellMethod(method='maximum', coords='time', + intervals='1 hr', comments='first bit'), + CellMethod(method='mean', coords='time', + intervals='1 day', comments='second bit')) + for cell_method_str in cell_method_strings: + res = parse_cell_methods(cell_method_str) + self.assertEqual(res, expected) + + def test_portions_of_cells(self): + cell_method_strings = [ + 'area: mean where sea_ice over sea', + 'area : mean where sea_ice over sea', + ] + expected = (CellMethod(method='mean where sea_ice over sea', + coords='area'),) + for cell_method_str in cell_method_strings: + res = parse_cell_methods(cell_method_str) + self.assertEqual(res, expected) + + def test_climatology(self): + cell_method_strings = [ + 'time: minimum within days time: mean over days', + 'time : minimum within days time: mean over days', + 'time: minimum within days time : mean over days', + 'time : minimum within days time : mean over days', + ] + expected = (CellMethod(method='minimum within days', coords='time'), + CellMethod(method='mean over days', coords='time')) + for cell_method_str in cell_method_strings: + res = parse_cell_methods(cell_method_str) + self.assertEqual(res, expected) + + def test_climatology_with_unknown_method(self): + cell_method_strings = [ + 'time: min within days time: mean over days', + 'time : min within days time: mean over days', + 'time: min within days time : mean over days', + 'time : min within days time : mean over days', + ] + expected = (CellMethod(method='min within days', coords='time'), + CellMethod(method='mean over days', coords='time')) + for cell_method_str in cell_method_strings: + with mock.patch('warnings.warn') as warn: + res = parse_cell_methods(cell_method_str) + self.assertIn("NetCDF variable contains unknown cell method 'min'", + warn.call_args[0][0]) + self.assertEqual(res, expected) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/netcdf/test_save.py b/lib/iris/tests/unit/fileformats/netcdf/test_save.py new file mode 100644 index 0000000000..06f5140058 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/netcdf/test_save.py @@ -0,0 +1,220 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.fileformats.netcdf.save` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import netCDF4 as nc +import numpy as np + +import iris +from iris.coords import DimCoord +from iris.cube import Cube, CubeList +from iris.fileformats.netcdf import save, CF_CONVENTIONS_VERSION +from iris.tests import mock +from iris.tests.stock import lat_lon_cube + + +class Test_conventions(tests.IrisTest): + def setUp(self): + self.cube = Cube([0]) + self.custom_conventions = 'convention1 convention2' + self.cube.attributes['Conventions'] = self.custom_conventions + self.options = iris.config.netcdf + + def test_custom_conventions__ignored(self): + # Ensure that we drop existing conventions attributes and replace with + # CF convention. + with self.temp_filename('.nc') as nc_path: + save(self.cube, nc_path, 'NETCDF4') + ds = nc.Dataset(nc_path) + res = ds.getncattr('Conventions') + ds.close() + self.assertEqual(res, CF_CONVENTIONS_VERSION) + + def test_custom_conventions__allowed(self): + # Ensure that existing conventions attributes are passed through if the + # relevant Iris option is set. + with mock.patch.object(self.options, 'conventions_override', True): + with self.temp_filename('.nc') as nc_path: + save(self.cube, nc_path, 'NETCDF4') + ds = nc.Dataset(nc_path) + res = ds.getncattr('Conventions') + ds.close() + self.assertEqual(res, self.custom_conventions) + + def test_custom_conventions__allowed__missing(self): + # Ensure the default conventions attribute is set if the relevant Iris + # option is set but there is no custom conventions attribute. + del self.cube.attributes['Conventions'] + with mock.patch.object(self.options, 'conventions_override', True): + with self.temp_filename('.nc') as nc_path: + save(self.cube, nc_path, 'NETCDF4') + ds = nc.Dataset(nc_path) + res = ds.getncattr('Conventions') + ds.close() + self.assertEqual(res, CF_CONVENTIONS_VERSION) + + +class Test_attributes(tests.IrisTest): + def test_attributes_arrays(self): + # Ensure that attributes containing NumPy arrays can be equality + # checked and their cubes saved as appropriate. + c1 = Cube([1], attributes={'bar': np.arange(2)}) + c2 = Cube([2], attributes={'bar': np.arange(2)}) + + with self.temp_filename('foo.nc') as nc_out: + save([c1, c2], nc_out) + ds = nc.Dataset(nc_out) + res = ds.getncattr('bar') + ds.close() + self.assertArrayEqual(res, np.arange(2)) + + def test_no_special_attribute_clash(self): + # Ensure that saving multiple cubes with netCDF4 protected attributes + # works as expected. + # Note that here we are testing variable attribute clashes only - by + # saving multiple cubes the attributes are saved as variable + # attributes rather than global attributes. + c1 = Cube([0], var_name='test', attributes={'name': 'bar'}) + c2 = Cube([0], var_name='test_1', attributes={'name': 'bar_1'}) + + with self.temp_filename('foo.nc') as nc_out: + save([c1, c2], nc_out) + ds = nc.Dataset(nc_out) + res = ds.variables['test'].getncattr('name') + res_1 = ds.variables['test_1'].getncattr('name') + ds.close() + self.assertEqual(res, 'bar') + self.assertEqual(res_1, 'bar_1') + + +class Test_unlimited_dims(tests.IrisTest): + def test_no_unlimited_dims(self): + cube = lat_lon_cube() + with self.temp_filename('foo.nc') as nc_out: + save(cube, nc_out) + ds = nc.Dataset(nc_out) + self.assertFalse(ds.dimensions['latitude'].isunlimited()) + + def test_unlimited_dim_latitude(self): + cube = lat_lon_cube() + unlim_dim_name = 'latitude' + with self.temp_filename('foo.nc') as nc_out: + save(cube, nc_out, unlimited_dimensions=[unlim_dim_name]) + ds = nc.Dataset(nc_out) + self.assertTrue(ds.dimensions[unlim_dim_name].isunlimited()) + + +class Test_fill_value(tests.IrisTest): + def setUp(self): + self.standard_names = ['air_temperature', + 'air_potential_temperature', + 'air_temperature_anomaly'] + + def _make_cubes(self): + lat = DimCoord(np.arange(3), 'latitude', units='degrees') + lon = DimCoord(np.arange(4), 'longitude', units='degrees') + data = np.arange(12, dtype='f4').reshape(3, 4) + return CubeList(Cube(data, standard_name=name, units='K', + dim_coords_and_dims=[(lat, 0), (lon, 1)]) + for name in self.standard_names) + + def test_None(self): + # Test that when no fill_value argument is passed, the fill_value + # argument to Saver.write is None or not present. + cubes = self._make_cubes() + with mock.patch('iris.fileformats.netcdf.Saver') as Saver: + save(cubes, 'dummy.nc') + + # Get the Saver.write mock + with Saver() as saver: + write = saver.write + + self.assertEqual(3, write.call_count) + for call in write.mock_calls: + _, _, kwargs = call + if 'fill_value' in kwargs: + self.assertIs(None, kwargs['fill_value']) + + def test_single(self): + # Test that when a single value is passed as the fill_value argument, + # that value is passed to each call to Saver.write + cubes = self._make_cubes() + fill_value = 12345. + with mock.patch('iris.fileformats.netcdf.Saver') as Saver: + save(cubes, 'dummy.nc', fill_value=fill_value) + + # Get the Saver.write mock + with Saver() as saver: + write = saver.write + + self.assertEqual(3, write.call_count) + for call in write.mock_calls: + _, _, kwargs = call + self.assertEqual(fill_value, kwargs['fill_value']) + + def test_multiple(self): + # Test that when a list is passed as the fill_value argument, + # each element is passed to separate calls to Saver.write + cubes = self._make_cubes() + fill_values = [123., 456., 789.] + with mock.patch('iris.fileformats.netcdf.Saver') as Saver: + save(cubes, 'dummy.nc', fill_value=fill_values) + + # Get the Saver.write mock + with Saver() as saver: + write = saver.write + + self.assertEqual(3, write.call_count) + for call, fill_value in zip(write.mock_calls, fill_values): + _, _, kwargs = call + self.assertEqual(fill_value, kwargs['fill_value']) + + def test_single_string(self): + # Test that when a string is passed as the fill_value argument, + # that value is passed to calls to Saver.write + cube = Cube(['abc', 'def', 'hij']) + fill_value = 'xyz' + with mock.patch('iris.fileformats.netcdf.Saver') as Saver: + save(cube, 'dummy.nc', fill_value=fill_value) + + # Get the Saver.write mock + with Saver() as saver: + write = saver.write + + self.assertEqual(1, write.call_count) + _, _, kwargs = write.mock_calls[0] + self.assertEqual(fill_value, kwargs['fill_value']) + + def test_multi_wrong_length(self): + # Test that when a list of a different length to the number of cubes + # is passed as the fill_value argument, an error is raised + cubes = self._make_cubes() + fill_values = [1., 2., 3., 4.] + with mock.patch('iris.fileformats.netcdf.Saver') as Saver: + with self.assertRaises(ValueError): + save(cubes, 'dummy.nc', fill_value=fill_values) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/nimrod_load_rules/__init__.py b/lib/iris/tests/unit/fileformats/nimrod_load_rules/__init__.py new file mode 100644 index 0000000000..b40e3eb2ae --- /dev/null +++ b/lib/iris/tests/unit/fileformats/nimrod_load_rules/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.fileformats.nimrod_load_rules` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/nimrod_load_rules/test_tm_meridian_scaling.py b/lib/iris/tests/unit/fileformats/nimrod_load_rules/test_tm_meridian_scaling.py new file mode 100644 index 0000000000..f6a483df56 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/nimrod_load_rules/test_tm_meridian_scaling.py @@ -0,0 +1,67 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the `iris.fileformats.nimrod_load_rules.tm_meridian_scaling` +function. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.fileformats.nimrod_load_rules import (tm_meridian_scaling, + NIMROD_DEFAULT, + MERIDIAN_SCALING_BNG) +from iris.fileformats.nimrod import NimrodField +from iris.tests import mock + + +class Test(tests.IrisTest): + def setUp(self): + self.field = mock.Mock(tm_meridian_scaling=NIMROD_DEFAULT, + spec=NimrodField, + float32_mdi=-123) + self.cube = mock.Mock() + + def _call_tm_meridian_scaling(self, scaling_value): + self.field.tm_meridian_scaling = scaling_value + tm_meridian_scaling(self.cube, self.field) + + def test_unhandled(self): + with mock.patch('warnings.warn') as warn: + self._call_tm_meridian_scaling(1) + self.assertEqual(warn.call_count, 1) + + @tests.no_warnings + def test_british_national_grid(self): + # A value is not returned in this rule currently. + self.assertEqual(None, + self._call_tm_meridian_scaling(MERIDIAN_SCALING_BNG)) + + def test_null(self): + with mock.patch('warnings.warn') as warn: + self._call_tm_meridian_scaling(NIMROD_DEFAULT) + self._call_tm_meridian_scaling(self.field.float32_mdi) + self.assertEqual(warn.call_count, 0) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/nimrod_load_rules/test_vertical_coord.py b/lib/iris/tests/unit/fileformats/nimrod_load_rules/test_vertical_coord.py new file mode 100644 index 0000000000..3655f59af8 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/nimrod_load_rules/test_vertical_coord.py @@ -0,0 +1,78 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the `iris.fileformats.nimrod_load_rules.vertical_coord` +function. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.fileformats.nimrod_load_rules import (vertical_coord, + NIMROD_DEFAULT, + TranslationWarning) +from iris.fileformats.nimrod import NimrodField +from iris.tests import mock + + +class Test(tests.IrisTest): + NIMROD_LOCATION = 'iris.fileformats.nimrod_load_rules' + + def setUp(self): + self.field = mock.Mock(vertical_coord_type=NIMROD_DEFAULT, + int_mdi=mock.sentinel.int_mdi, + field_code=mock.sentinel.field_code, + spec=NimrodField) + self.cube = mock.Mock() + + def _call_vertical_coord(self, vertical_coord_type): + self.field.vertical_coord_type = vertical_coord_type + vertical_coord(self.cube, self.field) + + def test_unhandled(self): + with mock.patch('warnings.warn') as warn: + self._call_vertical_coord(-1) + warn.assert_called_once_with("Vertical coord -1 not yet handled", + TranslationWarning) + + def test_orography(self): + name = 'orography_vertical_coord' + with mock.patch(self.NIMROD_LOCATION + '.' + name) as orog: + self.field.field_code = 73 + self._call_vertical_coord(None) + orog.assert_called_once_with(self.cube, self.field) + + def test_height(self): + name = 'height_vertical_coord' + with mock.patch(self.NIMROD_LOCATION + '.' + name) as height: + self._call_vertical_coord(0) + height.assert_called_once_with(self.cube, self.field) + + def test_null(self): + with mock.patch('warnings.warn') as warn: + self._call_vertical_coord(NIMROD_DEFAULT) + self._call_vertical_coord(self.field.int_mdi) + self.assertEqual(warn.call_count, 0) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp/__init__.py b/lib/iris/tests/unit/fileformats/pp/__init__.py index e6ad45ee28..4f4fc82340 100644 --- a/lib/iris/tests/unit/fileformats/pp/__init__.py +++ b/lib/iris/tests/unit/fileformats/pp/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Unit tests for the :mod:`iris.fileformats.pp` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/pp/test_PPDataProxy.py b/lib/iris/tests/unit/fileformats/pp/test_PPDataProxy.py new file mode 100644 index 0000000000..0732f296bb --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pp/test_PPDataProxy.py @@ -0,0 +1,52 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.fileformats.pp.PPDataProxy` class.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.fileformats.pp import PPDataProxy, SplittableInt +from iris.tests import mock + + +class Test_lbpack(tests.IrisTest): + def test_lbpack_SplittableInt(self): + lbpack = mock.Mock(spec_set=SplittableInt) + proxy = PPDataProxy(None, None, None, None, + None, lbpack, None, None, None) + self.assertEqual(proxy.lbpack, lbpack) + self.assertIs(proxy.lbpack, lbpack) + + def test_lnpack_raw(self): + lbpack = 4321 + proxy = PPDataProxy(None, None, None, None, + None, lbpack, None, None, None) + self.assertEqual(proxy.lbpack, lbpack) + self.assertIsNot(proxy.lbpack, lbpack) + self.assertIsInstance(proxy.lbpack, SplittableInt) + self.assertEqual(proxy.lbpack.n1, lbpack % 10) + self.assertEqual(proxy.lbpack.n2, lbpack // 10 % 10) + self.assertEqual(proxy.lbpack.n3, lbpack // 100 % 10) + self.assertEqual(proxy.lbpack.n4, lbpack // 1000 % 10) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp/test_PPField.py b/lib/iris/tests/unit/fileformats/pp/test_PPField.py index 64d2c8fdac..1a402a2631 100644 --- a/lib/iris/tests/unit/fileformats/pp/test_PPField.py +++ b/lib/iris/tests/unit/fileformats/pp/test_PPField.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -16,17 +16,22 @@ # along with Iris. If not, see . """Unit tests for the `iris.fileformats.pp.PPField` class.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests +from contextlib import contextmanager import warnings -import mock import numpy as np +import iris.fileformats.pp as pp from iris.fileformats.pp import PPField from iris.fileformats.pp import SplittableInt +from iris.tests import mock # The PPField class is abstract, so to test we define a minimal, # concrete subclass with the `t1` and `t2` properties. @@ -35,26 +40,56 @@ # items when written to disk and get consistent results. +DUMMY_HEADER = [('dummy1', (0, 11)), + ('lbtim', (12,)), + ('dummy2', (13,)), + ('lblrec', (14,)), + ('dummy3', (15, 16)), + ('lbrow', (17,)), + ('dummy4', (18,)), + ('lbext', (19,)), + ('lbpack', (20,)), + ('dummy5', (21, 37)), + ('lbuser', (38, 39, 40, 41, 42, 43, 44,)), + ('brsvd', (45, 46, 47, 48)), + ('bdatum', (49,)), + ('dummy6', (50, 61)), + ('bmdi', (62, )), + ('dummy7', (63,)), + ] + + class TestPPField(PPField): - HEADER_DEFN = [ - ('dummy1', (0, 13)), - ('lblrec', (14,)), - ('dummy2', (15, 18)), - ('lbext', (19,)), - ('lbpack', (20,)), - ('dummy3', (21, 37)), - ('lbuser', (38, 39, 40, 41, 42, 43, 44,)), - ('dummy4', (45, 63)), - ] + HEADER_DEFN = DUMMY_HEADER + HEADER_DICT = dict(DUMMY_HEADER) + + def _ready_for_save(self): + self.dummy1 = 0 + self.dummy2 = 0 + self.dummy3 = 0 + self.dummy4 = 0 + self.dummy5 = 0 + self.dummy6 = 0 + self.dummy7 = 0 + self.lbtim = 0 + self.lblrec = 0 + self.lbrow = 0 + self.lbext = 0 + self.lbpack = 0 + self.lbuser = 0 + self.brsvd = 0 + self.bdatum = 0 + self.bmdi = -1e30 + return self @property def t1(self): - return netcdftime.datetime(2013, 10, 14, 10, 4) + return None @property def t2(self): - return netcdftime.datetime(2013, 10, 14, 10, 5) + return None class Test_save(tests.IrisTest): @@ -62,15 +97,7 @@ def test_float64(self): # Tests down-casting of >f8 data to >f4. def field_checksum(data): - field = TestPPField() - field.dummy1 = 0 - field.dummy2 = 0 - field.dummy3 = 0 - field.dummy4 = 0 - field.lblrec = 0 - field.lbext = 0 - field.lbpack = 0 - field.lbuser = 0 + field = TestPPField()._ready_for_save() field.data = data with self.temp_filename('.pp') as temp_filename: with open(temp_filename, 'wb') as pp_file: @@ -80,11 +107,49 @@ def field_checksum(data): data_64 = np.linspace(0, 1, num=10, endpoint=False).reshape(2, 5) checksum_32 = field_checksum(data_64.astype('>f4')) - with mock.patch('warnings.warn') as warn: + msg = 'Downcasting array precision from float64 to float32 for save.' + with self.assertWarnsRegexp(msg): checksum_64 = field_checksum(data_64.astype('>f8')) + self.assertEqual(checksum_32, checksum_64) - self.assertEquals(checksum_32, checksum_64) - warn.assert_called() + def test_masked_mdi_value_warning(self): + # Check that an unmasked MDI value raises a warning. + field = TestPPField()._ready_for_save() + field.bmdi = -123.4 + # Make float32 data, as float64 default produces an extra warning. + field.data = np.ma.masked_array([1., field.bmdi, 3.], dtype=np.float32) + msg = 'PPField data contains unmasked points' + with self.assertWarnsRegexp(msg): + with self.temp_filename('.pp') as temp_filename: + with open(temp_filename, 'wb') as pp_file: + field.save(pp_file) + + def test_unmasked_mdi_value_warning(self): + # Check that MDI in *unmasked* data raises a warning. + field = TestPPField()._ready_for_save() + field.bmdi = -123.4 + # Make float32 data, as float64 default produces an extra warning. + field.data = np.array([1., field.bmdi, 3.], dtype=np.float32) + msg = 'PPField data contains unmasked points' + with self.assertWarnsRegexp(msg): + with self.temp_filename('.pp') as temp_filename: + with open(temp_filename, 'wb') as pp_file: + field.save(pp_file) + + def test_mdi_masked_value_nowarning(self): + # Check that a *masked* MDI value does not raise a warning. + field = TestPPField()._ready_for_save() + field.bmdi = -123.4 + # Make float32 data, as float64 default produces an extra warning. + field.data = np.ma.masked_array([1., 2., 3.], mask=[0, 1, 0], + dtype=np.float32) + # Set underlying data value at masked point to BMDI value. + field.data.data[1] = field.bmdi + self.assertArrayAllClose(field.data.data[1], field.bmdi) + with self.assertNoWarningsRegexp(r'\(mask\|fill\)'): + with self.temp_filename('.pp') as temp_filename: + with open(temp_filename, 'wb') as pp_file: + field.save(pp_file) class Test_calendar(tests.IrisTest): @@ -103,5 +168,199 @@ def test_365(self): field.lbtim = SplittableInt(4, {'ia': 2, 'ib': 1, 'ic': 0}) self.assertEqual(field.calendar, '365_day') + +class Test_coord_system(tests.IrisTest): + def _check_cs(self, bplat, bplon, rotated): + field = TestPPField() + field.bplat = bplat + field.bplon = bplon + with mock.patch('iris.fileformats.pp.iris.coord_systems') \ + as mock_cs_mod: + result = field.coord_system() + if not rotated: + # It should return a standard unrotated CS. + self.assertTrue(mock_cs_mod.GeogCS.call_count == 1) + self.assertEqual(result, mock_cs_mod.GeogCS()) + else: + # It should return a rotated CS with the correct makeup. + self.assertTrue(mock_cs_mod.GeogCS.call_count == 1) + self.assertTrue(mock_cs_mod.RotatedGeogCS.call_count == 1) + self.assertEqual(result, mock_cs_mod.RotatedGeogCS()) + self.assertEqual(mock_cs_mod.RotatedGeogCS.call_args_list[0], + mock.call(bplat, bplon, + ellipsoid=mock_cs_mod.GeogCS())) + + def test_normal_unrotated(self): + # Check that 'normal' BPLAT,BPLON=90,0 produces an unrotated system. + self._check_cs(bplat=90, bplon=0, rotated=False) + + def test_bplon_180_unrotated(self): + # Check that BPLAT,BPLON=90,180 behaves the same as 90,0. + self._check_cs(bplat=90, bplon=180, rotated=False) + + def test_odd_bplat_rotated(self): + # Show that BPLAT != 90 produces a rotated field. + self._check_cs(bplat=75, bplon=180, rotated=True) + + def test_odd_bplon_rotated(self): + # Show that BPLON != 0 or 180 produces a rotated field. + self._check_cs(bplat=90, bplon=123.45, rotated=True) + + +class Test__init__(tests.IrisTest): + def setUp(self): + header_longs = np.zeros(pp.NUM_LONG_HEADERS, dtype=np.int) + header_floats = np.zeros(pp.NUM_FLOAT_HEADERS, dtype=np.float) + self.header = list(header_longs) + list(header_floats) + + def test_no_headers(self): + field = TestPPField() + self.assertIsNone(field._raw_header) + self.assertIsNone(field.raw_lbtim) + self.assertIsNone(field.raw_lbpack) + + def test_lbtim_lookup(self): + self.assertEqual(TestPPField.HEADER_DICT['lbtim'], (12,)) + + def test_lbpack_lookup(self): + self.assertEqual(TestPPField.HEADER_DICT['lbpack'], (20,)) + + def test_raw_lbtim(self): + raw_lbtim = 4321 + loc, = TestPPField.HEADER_DICT['lbtim'] + self.header[loc] = raw_lbtim + field = TestPPField(header=self.header) + self.assertEqual(field.raw_lbtim, raw_lbtim) + + def test_raw_lbpack(self): + raw_lbpack = 4321 + loc, = TestPPField.HEADER_DICT['lbpack'] + self.header[loc] = raw_lbpack + field = TestPPField(header=self.header) + self.assertEqual(field.raw_lbpack, raw_lbpack) + + +class Test__getattr__(tests.IrisTest): + def setUp(self): + header_longs = np.zeros(pp.NUM_LONG_HEADERS, dtype=np.int) + header_floats = np.zeros(pp.NUM_FLOAT_HEADERS, dtype=np.float) + self.header = list(header_longs) + list(header_floats) + + def test_attr_singular_long(self): + lbrow = 1234 + loc, = TestPPField.HEADER_DICT['lbrow'] + self.header[loc] = lbrow + field = TestPPField(header=self.header) + self.assertEqual(field.lbrow, lbrow) + + def test_attr_multi_long(self): + lbuser = (100, 101, 102, 103, 104, 105, 106) + loc = TestPPField.HEADER_DICT['lbuser'] + self.header[loc[0]:loc[-1] + 1] = lbuser + field = TestPPField(header=self.header) + self.assertEqual(field.lbuser, lbuser) + + def test_attr_singular_float(self): + bdatum = 1234 + loc, = TestPPField.HEADER_DICT['bdatum'] + self.header[loc] = bdatum + field = TestPPField(header=self.header) + self.assertEqual(field.bdatum, bdatum) + + def test_attr_multi_float(self): + brsvd = (100, 101, 102, 103) + loc = TestPPField.HEADER_DICT['brsvd'] + start = loc[0] + stop = loc[-1] + 1 + self.header[start:stop] = brsvd + field = TestPPField(header=self.header) + self.assertEqual(field.brsvd, brsvd) + + def test_attr_lbtim(self): + raw_lbtim = 4321 + loc, = TestPPField.HEADER_DICT['lbtim'] + self.header[loc] = raw_lbtim + field = TestPPField(header=self.header) + result = field.lbtim + self.assertEqual(result, raw_lbtim) + self.assertIsInstance(result, SplittableInt) + result = field._lbtim + self.assertEqual(result, raw_lbtim) + self.assertIsInstance(result, SplittableInt) + + def test_attr_lbpack(self): + raw_lbpack = 4321 + loc, = TestPPField.HEADER_DICT['lbpack'] + self.header[loc] = raw_lbpack + field = TestPPField(header=self.header) + result = field.lbpack + self.assertEqual(result, raw_lbpack) + self.assertIsInstance(result, SplittableInt) + result = field._lbpack + self.assertEqual(result, raw_lbpack) + self.assertIsInstance(result, SplittableInt) + + def test_attr_raw_lbtim_assign(self): + field = TestPPField(header=self.header) + self.assertEqual(field.raw_lbpack, 0) + self.assertEqual(field.lbtim, 0) + raw_lbtim = 4321 + field.lbtim = raw_lbtim + self.assertEqual(field.raw_lbtim, raw_lbtim) + self.assertNotIsInstance(field.raw_lbtim, SplittableInt) + + def test_attr_raw_lbpack_assign(self): + field = TestPPField(header=self.header) + self.assertEqual(field.raw_lbpack, 0) + self.assertEqual(field.lbpack, 0) + raw_lbpack = 4321 + field.lbpack = raw_lbpack + self.assertEqual(field.raw_lbpack, raw_lbpack) + self.assertNotIsInstance(field.raw_lbpack, SplittableInt) + + def test_attr_unknown(self): + with self.assertRaises(AttributeError): + TestPPField().x + + +class Test_lbtim(tests.IrisTest): + def test_get_splittable(self): + headers = [0] * 64 + headers[12] = 12345 + field = TestPPField(headers) + self.assertIsInstance(field.lbtim, SplittableInt) + self.assertEqual(field.lbtim.ia, 123) + self.assertEqual(field.lbtim.ib, 4) + self.assertEqual(field.lbtim.ic, 5) + + def test_set_int(self): + headers = [0] * 64 + headers[12] = 12345 + field = TestPPField(headers) + field.lbtim = 34567 + self.assertIsInstance(field.lbtim, SplittableInt) + self.assertEqual(field.lbtim.ia, 345) + self.assertEqual(field.lbtim.ib, 6) + self.assertEqual(field.lbtim.ic, 7) + self.assertEqual(field.raw_lbtim, 34567) + + def test_set_splittable(self): + # Check that assigning a SplittableInt to lbtim uses the integer + # value. In other words, check that you can't assign an + # arbitrary SplittableInt with crazy named attributes. + headers = [0] * 64 + headers[12] = 12345 + field = TestPPField(headers) + si = SplittableInt(34567, {'foo': 0}) + field.lbtim = si + self.assertIsInstance(field.lbtim, SplittableInt) + with self.assertRaises(AttributeError): + field.lbtim.foo + self.assertEqual(field.lbtim.ia, 345) + self.assertEqual(field.lbtim.ib, 6) + self.assertEqual(field.lbtim.ic, 7) + self.assertEqual(field.raw_lbtim, 34567) + + if __name__ == "__main__": tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp/test__LBProc.py b/lib/iris/tests/unit/fileformats/pp/test__LBProc.py new file mode 100644 index 0000000000..18670874d5 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pp/test__LBProc.py @@ -0,0 +1,226 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for :class:`iris.fileformats.pp._LBProc`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.fileformats.pp import _LBProc +from iris.tests import mock + + +class Test___init__(tests.IrisTest): + def test_int(self): + _LBProc(42) + + def test_str(self): + _LBProc('245') + + def test_negative(self): + msg = 'Negative numbers not supported with splittable integers object' + with self.assertRaisesRegexp(ValueError, msg): + _LBProc(-1) + with self.assertRaisesRegexp(ValueError, msg): + _LBProc('-1') + + def test_invalid_str(self): + with self.assertRaisesRegexp(ValueError, 'invalid literal for int'): + _LBProc('asdf') + + +class Test_flag1(tests.IrisTest): + def test_true(self): + lbproc = _LBProc(1) + with mock.patch('warnings.warn') as warn: + flag = lbproc.flag1 + self.assertEqual(warn.call_count, 1) + self.assertTrue(flag) + + def test_false(self): + lbproc = _LBProc(2) + with mock.patch('warnings.warn') as warn: + flag = lbproc.flag1 + self.assertEqual(warn.call_count, 1) + self.assertFalse(flag) + + def test_many(self): + for i in range(100): + lbproc = _LBProc(i) + with mock.patch('warnings.warn') as warn: + flag = lbproc.flag1 + self.assertEqual(warn.call_count, 1) + self.assertEqual(flag, i & 1) + + +class Test_flag2(tests.IrisTest): + def test_true(self): + lbproc = _LBProc(3) + with mock.patch('warnings.warn') as warn: + flag = lbproc.flag2 + self.assertEqual(warn.call_count, 1) + self.assertTrue(flag) + + def test_false(self): + lbproc = _LBProc(1) + with mock.patch('warnings.warn') as warn: + flag = lbproc.flag2 + self.assertEqual(warn.call_count, 1) + self.assertFalse(flag) + + def test_many(self): + for i in range(100): + lbproc = _LBProc(i) + with mock.patch('warnings.warn') as warn: + flag = lbproc.flag2 + self.assertEqual(warn.call_count, 1) + self.assertEqual(flag, bool(i & 2)) + + +class Test_flag4(tests.IrisTest): + def test_true(self): + lbproc = _LBProc(6) + with mock.patch('warnings.warn') as warn: + flag = lbproc.flag4 + self.assertEqual(warn.call_count, 1) + self.assertTrue(flag) + + def test_false(self): + lbproc = _LBProc(8) + with mock.patch('warnings.warn') as warn: + flag = lbproc.flag4 + self.assertEqual(warn.call_count, 1) + self.assertFalse(flag) + + def test_many(self): + for i in range(100): + lbproc = _LBProc(i) + with mock.patch('warnings.warn') as warn: + flag = lbproc.flag4 + self.assertEqual(warn.call_count, 1) + self.assertEqual(flag, bool(i & 4)) + + +class Test_flag131072(tests.IrisTest): + def test_true(self): + lbproc = _LBProc(135448) + with mock.patch('warnings.warn') as warn: + flag = lbproc.flag131072 + self.assertEqual(warn.call_count, 1) + self.assertTrue(flag) + + def test_false(self): + lbproc = _LBProc(4376) + with mock.patch('warnings.warn') as warn: + flag = lbproc.flag131072 + self.assertEqual(warn.call_count, 1) + self.assertFalse(flag) + + def test_many(self): + for i in range(0, 260000, 1000): + lbproc = _LBProc(i) + with mock.patch('warnings.warn') as warn: + flag = lbproc.flag131072 + self.assertEqual(warn.call_count, 1) + self.assertEqual(flag, bool(i & 131072)) + + +class Test_flag3(tests.IrisTest): + def test_invalid(self): + lbproc = _LBProc(9) + with self.assertRaises(AttributeError): + lbproc.flag3 + + +class Test_flag262144(tests.IrisTest): + def test_invalid(self): + lbproc = _LBProc(9) + with self.assertRaises(AttributeError): + lbproc.flag262144 + + +class Test___int__(tests.IrisTest): + def test(self): + self.assertEqual(int(_LBProc(99)), 99) + + +class Test___eq__(tests.IrisTest): + def test_equal(self): + self.assertTrue(_LBProc(17).__eq__(_LBProc(17))) + + def test_equal_int(self): + self.assertTrue(_LBProc(17).__eq__(17)) + + def test_not_equal(self): + self.assertFalse(_LBProc(17).__eq__(_LBProc(18))) + + def test_not_equal_int(self): + self.assertFalse(_LBProc(17).__eq__(16)) + + +class Test___ne__(tests.IrisTest): + def test_equal(self): + self.assertFalse(_LBProc(7).__ne__(_LBProc(7))) + + def test_equal_int(self): + self.assertFalse(_LBProc(8).__ne__(8)) + + def test_not_equal(self): + self.assertTrue(_LBProc(9).__ne__(_LBProc(14))) + + def test_not_equal_int(self): + self.assertTrue(_LBProc(10).__ne__(15)) + + +class Test___iadd__(tests.IrisTest): + def test(self): + lbproc = _LBProc(12) + lbproc += 8 + self.assertEqual(int(lbproc), 20) + + +class Test___iand__(tests.IrisTest): + def test(self): + lbproc = _LBProc(12) + lbproc &= 8 + self.assertEqual(int(lbproc), 8) + + +class Test___ior__(tests.IrisTest): + def test(self): + lbproc = _LBProc(12) + lbproc |= 1 + self.assertEqual(int(lbproc), 13) + + +class Test___repr__(tests.IrisTest): + def test(self): + lbproc = _LBProc(8641) + self.assertEqual(repr(lbproc), '_LBProc(8641)') + + +class Test___str__(tests.IrisTest): + def test(self): + lbproc = _LBProc(8641) + self.assertEqual(str(lbproc), '8641') + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp/test__convert_constraints.py b/lib/iris/tests/unit/fileformats/pp/test__convert_constraints.py new file mode 100644 index 0000000000..f0cc18f0e5 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pp/test__convert_constraints.py @@ -0,0 +1,103 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.fileformats.pp.load` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import iris +from iris.fileformats.pp import _convert_constraints +from iris.fileformats.pp import STASH +from iris.tests import mock + + +class Test_convert_constraints(tests.IrisTest): + def _single_stash(self): + constraint = iris.AttributeConstraint(STASH='m01s03i236') + return _convert_constraints(constraint) + + def test_single_stash(self): + pp_filter = self._single_stash() + stcube = mock.Mock(stash=STASH.from_msi('m01s03i236')) + self.assertTrue(pp_filter(stcube)) + + def test_stash_object(self): + constraint = iris.AttributeConstraint( + STASH=STASH.from_msi('m01s03i236')) + pp_filter = _convert_constraints(constraint) + stcube = mock.Mock(stash=STASH.from_msi('m01s03i236')) + self.assertTrue(pp_filter(stcube)) + + def test_surface_altitude(self): + # Ensure that surface altitude fields are not filtered. + pp_filter = self._single_stash() + orography_cube = mock.Mock(stash=STASH.from_msi('m01s00i033')) + self.assertTrue(pp_filter(orography_cube)) + + def test_surface_pressure(self): + # Ensure that surface pressure fields are not filtered. + pp_filter = self._single_stash() + pressure_cube = mock.Mock(stash=STASH.from_msi('m01s00i001')) + self.assertTrue(pp_filter(pressure_cube)) + + def test_double_stash(self): + stcube236 = mock.Mock(stash=STASH.from_msi('m01s03i236')) + stcube4 = mock.Mock(stash=STASH.from_msi('m01s00i004')) + stcube7 = mock.Mock(stash=STASH.from_msi('m01s00i007')) + constraints = [iris.AttributeConstraint(STASH='m01s03i236'), + iris.AttributeConstraint(STASH='m01s00i004')] + pp_filter = _convert_constraints(constraints) + self.assertTrue(pp_filter(stcube236)) + self.assertTrue(pp_filter(stcube4)) + self.assertFalse(pp_filter(stcube7)) + + def test_callable_stash(self): + stcube236 = mock.Mock(stash=STASH.from_msi('m01s03i236')) + stcube4 = mock.Mock(stash=STASH.from_msi('m01s00i004')) + stcube7 = mock.Mock(stash=STASH.from_msi('m01s00i007')) + con1 = iris.AttributeConstraint(STASH=lambda s: s.endswith("004")) + con2 = iris.AttributeConstraint(STASH=lambda s: s == "m01s00i007") + constraints = [con1, con2] + pp_filter = _convert_constraints(constraints) + self.assertFalse(pp_filter(stcube236)) + self.assertTrue(pp_filter(stcube4)) + self.assertTrue(pp_filter(stcube7)) + + def test_multiple_with_stash(self): + constraints = [iris.Constraint('air_potential_temperature'), + iris.AttributeConstraint(STASH='m01s00i004')] + pp_filter = _convert_constraints(constraints) + self.assertIsNone(pp_filter) + + def test_no_stash(self): + constraints = [iris.Constraint('air_potential_temperature'), + iris.AttributeConstraint(source='asource')] + pp_filter = _convert_constraints(constraints) + self.assertIsNone(pp_filter) + + def test_no_constraint(self): + constraints = [] + pp_filter = _convert_constraints(constraints) + self.assertIsNone(pp_filter) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp/test__create_field_data.py b/lib/iris/tests/unit/fileformats/pp/test__create_field_data.py index a72f893076..743d52ea0e 100644 --- a/lib/iris/tests/unit/fileformats/pp/test__create_field_data.py +++ b/lib/iris/tests/unit/fileformats/pp/test__create_field_data.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -16,23 +16,26 @@ # along with Iris. If not, see . """Unit tests for the `iris.fileformats.pp._create_field_data` function.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import biggus -import mock import numpy as np import iris.fileformats.pp as pp +from iris.tests import mock class Test__create_field_data(tests.IrisTest): def test_loaded_bytes(self): - # Check that a field with LoadedArrayBytes in _data gets the + # Check that a field with LoadedArrayBytes in core_data gets the # result of a suitable call to _data_bytes_to_shaped_array(). mock_loaded_bytes = mock.Mock(spec=pp.LoadedArrayBytes) - field = mock.Mock(_data=mock_loaded_bytes) + core_data = mock.MagicMock(return_value=mock_loaded_bytes) + field = mock.Mock(core_data=core_data) data_shape = mock.Mock() land_mask = mock.Mock() with mock.patch('iris.fileformats.pp._data_bytes_to_shaped_array') as \ @@ -40,40 +43,48 @@ def test_loaded_bytes(self): convert_bytes.return_value = mock.sentinel.array pp._create_field_data(field, data_shape, land_mask) - self.assertIs(field._data, mock.sentinel.array) + self.assertIs(field.data, mock.sentinel.array) convert_bytes.assert_called_once_with(mock_loaded_bytes.bytes, - field.lbpack, data_shape, + field.lbpack, + field.boundary_packing, + data_shape, mock_loaded_bytes.dtype, field.bmdi, land_mask) def test_deferred_bytes(self): - # Check that a field with DeferredArrayBytes in _data gets a - # biggus array. - deferred_bytes = mock.Mock(spec=pp.DeferredArrayBytes) - deferred_bytes.dtype.newbyteorder.return_value = mock.sentinel.dtype - field = mock.Mock(_data=deferred_bytes) - data_shape = (mock.sentinel.lat, mock.sentinel.lon) + # Check that a field with deferred array bytes in core_data gets a + # dask array. + fname = mock.sentinel.fname + position = mock.sentinel.position + n_bytes = mock.sentinel.n_bytes + newbyteorder = mock.Mock(return_value=mock.sentinel.dtype) + dtype = mock.Mock(newbyteorder=newbyteorder) + deferred_bytes = (fname, position, n_bytes, dtype) + core_data = mock.MagicMock(return_value=deferred_bytes) + field = mock.Mock(core_data=core_data) + data_shape = (100, 120) land_mask = mock.Mock() - proxy = mock.Mock(dtype=mock.sentinel.dtype, shape=data_shape) + proxy = mock.Mock(dtype=np.dtype('f4'), shape=data_shape, + spec=pp.PPDataProxy) # We can't directly inspect the concrete data source underlying - # the biggus array (it's a private attribute), so instead we - # patch the proxy creation and check it's being created and - # invoked correctly. + # the dask array, so instead we patch the proxy creation and check it's + # being created and invoked correctly. with mock.patch('iris.fileformats.pp.PPDataProxy') as PPDataProxy: PPDataProxy.return_value = proxy pp._create_field_data(field, data_shape, land_mask) - # Does the biggus array look OK from the outside? - self.assertIsInstance(field._data, biggus.Array) - self.assertEqual(field._data.shape, data_shape) - self.assertEqual(field._data.dtype, mock.sentinel.dtype) + # The data should be assigned via field.data. As this is a mock object + # we can check the attribute directly. + self.assertEqual(field.data.shape, data_shape) + self.assertEqual(field.data.dtype, np.dtype('f4')) # Is it making use of a correctly configured proxy? # NB. We know it's *using* the result of this call because # that's where the dtype came from above. - PPDataProxy.assert_called_once_with((data_shape), deferred_bytes.dtype, - deferred_bytes.fname, - deferred_bytes.position, - deferred_bytes.n_bytes, - field.lbpack, field.bmdi, + PPDataProxy.assert_called_once_with((data_shape), dtype, + fname, position, + n_bytes, + field.raw_lbpack, + field.boundary_packing, + field.bmdi, land_mask) diff --git a/lib/iris/tests/unit/fileformats/pp/test__data_bytes_to_shaped_array.py b/lib/iris/tests/unit/fileformats/pp/test__data_bytes_to_shaped_array.py index 0fa5467818..4870624902 100644 --- a/lib/iris/tests/unit/fileformats/pp/test__data_bytes_to_shaped_array.py +++ b/lib/iris/tests/unit/fileformats/pp/test__data_bytes_to_shaped_array.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -19,16 +19,20 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests import io -import mock import numpy as np +import numpy.ma as ma import iris.fileformats.pp as pp +from iris.tests import mock class Test__data_bytes_to_shaped_array__lateral_boundary_compression( @@ -45,8 +49,8 @@ def setUp(self): decompressed_mask[y_halo+rim:-(y_halo+rim), x_halo+rim:-(x_halo+rim)] = True - self.decompressed = np.ma.masked_array(decompressed, - mask=decompressed_mask) + self.decompressed = ma.masked_array(decompressed, + mask=decompressed_mask) self.north = decompressed[-(y_halo+rim):, :] self.east = decompressed[y_halo+rim:-(y_halo+rim), -(x_halo+rim):] @@ -64,10 +68,13 @@ def setUp(self): def test_boundary_decompression(self): boundary_packing = mock.Mock(rim_width=4, x_halo=3, y_halo=2) - lbpack = mock.Mock(n1=0, boundary_packing=boundary_packing) - r = pp._data_bytes_to_shaped_array(self.data_payload_bytes, lbpack, + lbpack = mock.Mock(n1=0) + r = pp._data_bytes_to_shaped_array(self.data_payload_bytes, + lbpack, boundary_packing, self.data_shape, - self.decompressed.dtype, -99) + self.decompressed.dtype, + -9223372036854775808) + r = ma.masked_array(r, np.isnan(r), fill_value=-9223372036854775808) self.assertMaskedArrayEqual(r, self.decompressed) @@ -83,17 +90,17 @@ def setUp(self): self.sea_masked_data = np.array([1, 3, 4.5, -4, 5, 0, 1, 2, 3]) # Compute the decompressed land mask data. - self.decomp_land_data = np.ma.masked_array([[0, 1, 0, 0], - [3, 0, 0, 0], - [0, 0, 0, 4.5]], - mask=sea, - dtype=np.float64) + self.decomp_land_data = ma.masked_array([[0, 1, 0, 0], + [3, 0, 0, 0], + [0, 0, 0, 4.5]], + mask=sea, + dtype=np.float64) # Compute the decompressed sea mask data. - self.decomp_sea_data = np.ma.masked_array([[1, -10, 3, 4.5], - [-10, -4, 5, 0], - [1, 2, 3, -10]], - mask=self.land, - dtype=np.float64) + self.decomp_sea_data = ma.masked_array([[1, -10, 3, 4.5], + [-10, -4, 5, 0], + [1, 2, 3, -10]], + mask=self.land, + dtype=np.float64) self.land_mask = mock.Mock(data=self.land, lbrow=self.land.shape[0], @@ -108,7 +115,7 @@ def test_no_land_mask(self): return_value=np.arange(3)): with self.assertRaises(ValueError) as err: pp._data_bytes_to_shaped_array(mock.Mock(), - self.create_lbpack(120), + self.create_lbpack(120), None, (3, 4), np.dtype('>f4'), -999, mask=None) self.assertEqual(str(err.exception), @@ -149,10 +156,12 @@ def check_read_data(self, field_data, lbpack, mask): # Calls pp._data_bytes_to_shaped_array with the necessary mocked # items, an lbpack instance, the correct data shape and mask instance. with mock.patch('numpy.frombuffer', return_value=field_data): - return pp._data_bytes_to_shaped_array(mock.Mock(), + data = pp._data_bytes_to_shaped_array(mock.Mock(), self.create_lbpack(lbpack), + None, mask.shape, np.dtype('>f4'), -999, mask=mask) + return ma.masked_array(data, np.isnan(data), fill_value=-999) if __name__ == "__main__": diff --git a/lib/iris/tests/unit/fileformats/pp/test__field_gen.py b/lib/iris/tests/unit/fileformats/pp/test__field_gen.py index ca4ee802bd..9f81341491 100644 --- a/lib/iris/tests/unit/fileformats/pp/test__field_gen.py +++ b/lib/iris/tests/unit/fileformats/pp/test__field_gen.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -16,19 +16,25 @@ # along with Iris. If not, see . """Unit tests for the `iris.fileformats.pp._field_gen` function.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests import contextlib +import io +import warnings -import mock import numpy as np import iris.fileformats.pp as pp +from iris.tests import mock -class Test__field_gen(tests.IrisTest): +class Test(tests.IrisTest): @contextlib.contextmanager def mock_for_field_gen(self, fields): side_effect_fields = list(fields)[:] @@ -43,8 +49,12 @@ def make_pp_field_override(*args): np.fromfile.return_value = [] return result + if six.PY3: + open_func = 'builtins.open' + else: + open_func = '__builtin__.open' with mock.patch('numpy.fromfile', return_value=[0]), \ - mock.patch('__builtin__.open'), \ + mock.patch(open_func), \ mock.patch('struct.unpack_from', return_value=[4]), \ mock.patch('iris.fileformats.pp.make_pp_field', side_effect=make_pp_field_override): @@ -57,12 +67,13 @@ def gen_fields(self, fields): def test_lblrec_invalid(self): pp_field = mock.Mock(lblrec=2, lbext=0) - with self.assertRaises(ValueError) as err: + with warnings.catch_warnings(record=True) as warn: + warnings.simplefilter('always') self.gen_fields([pp_field]) - self.assertEqual(str(err.exception), - ('LBLREC has a different value to the integer ' - 'recorded after the header in the file (8 ' - 'and 4).')) + self.assertEqual(len(warn), 1) + wmsg = ('LBLREC has a different value to the .* the header in the ' + 'file \(8 and 4\)\. Skipping .*') + six.assertRegex(self, str(warn[0].message), wmsg) def test_read_headers_call(self): # Checks that the two calls to np.fromfile are called in the @@ -71,16 +82,17 @@ def test_read_headers_call(self): lbext=0, lbuser=[0]) with self.mock_for_field_gen([pp_field]): - open_fh = mock.Mock() + open_fh = mock.MagicMock(spec=io.RawIOBase) open.return_value = open_fh next(pp._field_gen('mocked', read_data_bytes=False)) - calls = [mock.call(open_fh, count=45, dtype='>i4'), - mock.call(open_fh, count=19, dtype='>f4')] + with open_fh as open_fh_ctx: + calls = [mock.call(open_fh_ctx, count=45, dtype='>i4'), + mock.call(open_fh_ctx, count=19, dtype='>f4')] np.fromfile.assert_has_calls(calls) - expected_deferred_bytes = pp.DeferredArrayBytes('mocked', - open_fh.tell(), - 4, np.dtype('>f4')) - self.assertEqual(pp_field._data, expected_deferred_bytes) + with open_fh as open_fh_ctx: + expected_deferred_bytes = ('mocked', open_fh_ctx.tell(), + 4, np.dtype('>f4')) + self.assertEqual(pp_field.data, expected_deferred_bytes) def test_read_data_call(self): # Checks that data is read if read_data is True. @@ -88,12 +100,26 @@ def test_read_data_call(self): lbext=0, lbuser=[0]) with self.mock_for_field_gen([pp_field]): - open_fh = mock.Mock() + open_fh = mock.MagicMock(spec=io.RawIOBase) open.return_value = open_fh next(pp._field_gen('mocked', read_data_bytes=True)) - expected_loaded_bytes = pp.LoadedArrayBytes(open_fh.read(), - np.dtype('>f4')) - self.assertEqual(pp_field._data, expected_loaded_bytes) + with open_fh as open_fh_ctx: + expected_loaded_bytes = pp.LoadedArrayBytes(open_fh_ctx.read(), + np.dtype('>f4')) + self.assertEqual(pp_field.data, expected_loaded_bytes) + + def test_invalid_header_release(self): + # Check that an unknown LBREL value just results in a warning + # and the end of the file iteration instead of raising an error. + with self.temp_filename() as temp_path: + np.zeros(65, dtype='i4').tofile(temp_path) + generator = pp._field_gen(temp_path, False) + with mock.patch('warnings.warn') as warn: + with self.assertRaises(StopIteration): + next(generator) + self.assertEqual(warn.call_count, 1) + self.assertIn('header release number', warn.call_args[0][0]) + if __name__ == "__main__": tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp/test__interpret_field.py b/lib/iris/tests/unit/fileformats/pp/test__interpret_field.py index ff4fabb2c1..1828f44a87 100644 --- a/lib/iris/tests/unit/fileformats/pp/test__interpret_field.py +++ b/lib/iris/tests/unit/fileformats/pp/test__interpret_field.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -16,29 +16,35 @@ # along with Iris. If not, see . """Unit tests for the `iris.fileformats.pp._interpret_field` function.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests from copy import deepcopy - -import mock import numpy as np import iris.fileformats.pp as pp +from iris.tests import mock class Test__interpret_fields__land_packed_fields(tests.IrisTest): def setUp(self): + return_value = ('dummy', 0, 0, np.dtype('f4')) + core_data = mock.MagicMock(return_value=return_value) # A field packed using a land/sea mask. - self.pp_field = mock.Mock(lblrec=1, lbext=0, lbuser=[0], + self.pp_field = mock.Mock(lblrec=1, lbext=0, lbuser=[0] * 7, lbrow=0, lbnpt=0, - lbpack=mock.Mock(n2=2)) + raw_lbpack=20, + core_data=core_data) # The field specifying the land/seamask. - self.land_mask_field = mock.Mock(lblrec=1, lbext=0, lbuser=[0], + lbuser = [None, None, None, 30, None, None, 1] # m01s00i030 + self.land_mask_field = mock.Mock(lblrec=1, lbext=0, lbuser=lbuser, lbrow=3, lbnpt=4, - stash='m01s00i030', - data=np.empty((3, 4))) + raw_lbpack=0, + core_data=core_data) def test_non_deferred_fix_lbrow_lbnpt(self): # Checks the fix_lbrow_lbnpt is applied to fields which are not @@ -50,7 +56,7 @@ def test_non_deferred_fix_lbrow_lbnpt(self): self.assertEqual(f1.lbrow, 3) self.assertEqual(f1.lbnpt, 4) # Check the data's shape has been updated too. - self.assertEqual(f1._data.shape, (3, 4)) + self.assertEqual(f1.data.shape, (3, 4)) def test_fix_lbrow_lbnpt_no_mask_available(self): # Check a warning is issued when loading a land masked field @@ -92,11 +98,12 @@ def test_shared_land_mask_field(self): f2 = deepcopy(self.pp_field) self.assertIsNot(f1, f2) with mock.patch('iris.fileformats.pp.PPDataProxy') as PPDataProxy: - PPDataProxy.return_value = mock.MagicMock() + PPDataProxy.return_value = mock.MagicMock(shape=(3, 4), + dtype=np.float32) list(pp._interpret_fields([f1, self.land_mask_field, f2])) for call in PPDataProxy.call_args_list: positional_args = call[0] - self.assertIs(positional_args[7], self.land_mask_field) + self.assertIs(positional_args[8], self.land_mask_field) if __name__ == "__main__": diff --git a/lib/iris/tests/unit/fileformats/pp/test_as_fields.py b/lib/iris/tests/unit/fileformats/pp/test_as_fields.py new file mode 100644 index 0000000000..766ccae0fc --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pp/test_as_fields.py @@ -0,0 +1,51 @@ +# (C) British Crown Copyright 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.fileformats.pp.as_fields` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.coords import DimCoord +from iris.fileformats._ff_cross_references import STASH_TRANS +import iris.fileformats.pp as pp +from iris.tests import mock +import iris.tests.stock as stock + + +class TestAsFields(tests.IrisTest): + def setUp(self): + self.cube = stock.realistic_3d() + + def test_cube_only(self): + fields = pp.as_fields(self.cube) + for field in fields: + self.assertEqual(field.lbcode, 101) + + def test_field_coords(self): + fields = pp.as_fields(self.cube, + field_coords=['grid_longitude', + 'grid_latitude']) + for field in fields: + self.assertEqual(field.lbcode, 101) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp/test_load.py b/lib/iris/tests/unit/fileformats/pp/test_load.py index 957d16e7c2..43bef97feb 100644 --- a/lib/iris/tests/unit/fileformats/pp/test_load.py +++ b/lib/iris/tests/unit/fileformats/pp/test_load.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2016, Met Office # # This file is part of Iris. # @@ -16,13 +16,15 @@ # along with Iris. If not, see . """Unit tests for the `iris.fileformats.pp.load` function.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import mock - import iris.fileformats.pp as pp +from iris.tests import mock class Test_load(tests.IrisTest): @@ -39,7 +41,8 @@ def test_call_structure(self): pp.load('mock', read_data=True) interpret.assert_called_once_with(extract_result) - field_gen.assert_called_once_with('mock', read_data_bytes=True) + field_gen.assert_called_once_with('mock', read_data_bytes=True, + little_ended=False) if __name__ == "__main__": diff --git a/lib/iris/tests/unit/fileformats/pp/test_save.py b/lib/iris/tests/unit/fileformats/pp/test_save.py index 150a978c8b..361c01f936 100644 --- a/lib/iris/tests/unit/fileformats/pp/test_save.py +++ b/lib/iris/tests/unit/fileformats/pp/test_save.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2014, Met Office +# (C) British Crown Copyright 2014 - 2018, Met Office # # This file is part of Iris. # @@ -16,14 +16,21 @@ # along with Iris. If not, see . """Unit tests for the `iris.fileformats.pp.save` function.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import cftime +import cf_units + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import mock - +from iris.coords import DimCoord, CellMethod from iris.fileformats._ff_cross_references import STASH_TRANS import iris.fileformats.pp as pp +from iris.fileformats.pp_save_rules import _lbproc_rules, verify +from iris.tests import mock import iris.tests.stock as stock @@ -46,6 +53,42 @@ def _pp_save_ppfield_values(cube): return pp_field +class TestVertical(tests.IrisTest): + def setUp(self): + self.cube = stock.lat_lon_cube() + + def test_pseudo_level(self): + pseudo_level = 123 + coord = DimCoord(pseudo_level, long_name='pseudo_level', units='1') + self.cube.add_aux_coord(coord) + lbuser5_produced = _pp_save_ppfield_values(self.cube).lbuser[4] + self.assertEqual(pseudo_level, lbuser5_produced) + + def test_soil_level(self): + soil_level = 314 + coord = DimCoord(soil_level, long_name='soil_model_level_number') + self.cube.add_aux_coord(coord) + self.cube.standard_name = 'moisture_content_of_soil_layer' + field = _pp_save_ppfield_values(self.cube) + self.assertEqual(field.lbvc, 6) + self.assertEqual(field.lblev, soil_level) + self.assertEqual(field.blev, soil_level) + self.assertEqual(field.brsvd[0], 0) + self.assertEqual(field.brlev, 0) + + def test_soil_depth(self): + lower, point, upper = 1, 2, 3 + coord = DimCoord(point, standard_name='depth', bounds=[[lower, upper]]) + self.cube.add_aux_coord(coord) + self.cube.standard_name = 'moisture_content_of_soil_layer' + field = _pp_save_ppfield_values(self.cube) + self.assertEqual(field.lbvc, 6) + self.assertEqual(field.lblev, 0) + self.assertEqual(field.blev, point) + self.assertEqual(field.brsvd[0], lower) + self.assertEqual(field.brlev, upper) + + class TestLbfcProduction(tests.IrisTest): def setUp(self): self.cube = stock.lat_lon_cube() @@ -70,6 +113,228 @@ def test_no_stash(self): self.assertNotIn('STASH', self.cube.attributes) self.check_cube_stash_yields_lbfc(None, 0) + def check_cube_name_units_yields_lbfc(self, name, units, lbfc_expected): + self.cube.rename(name) + self.cube.units = units + lbfc_produced = _pp_save_ppfield_values(self.cube).lbfc + self.assertEqual(lbfc_produced, lbfc_expected, + 'Lbfc for ({!r} / {!r}) should be {:d}, ' + 'got {:d}'.format( + name, units, lbfc_expected, lbfc_produced)) + + def test_name_units_to_lbfc(self): + # Check LBFC value produced from name and units. + self.check_cube_name_units_yields_lbfc( + 'sea_ice_temperature', 'K', 209) + + def test_bad_name_units_to_lbfc_0(self): + # Check that badly-formed / unrecognised cases yield LBFC == 0. + self.check_cube_name_units_yields_lbfc('sea_ice_temperature', 'degC', + 0) + self.check_cube_name_units_yields_lbfc('Junk_Name', 'K', + 0) + + +class TestLbsrceProduction(tests.IrisTest): + def setUp(self): + self.cube = stock.lat_lon_cube() + + def check_cube_um_source_yields_lbsrce( + self, source_str=None, um_version_str=None, lbsrce_expected=None): + if source_str is not None: + self.cube.attributes['source'] = source_str + if um_version_str is not None: + self.cube.attributes['um_version'] = um_version_str + lbsrce_produced = _pp_save_ppfield_values(self.cube).lbsrce + self.assertEqual(lbsrce_produced, lbsrce_expected) + + def test_none(self): + self.check_cube_um_source_yields_lbsrce( + None, None, 0) + + def test_source_only_no_version(self): + self.check_cube_um_source_yields_lbsrce( + 'Data from Met Office Unified Model', None, 1111) + + def test_source_only_with_version(self): + self.check_cube_um_source_yields_lbsrce( + 'Data from Met Office Unified Model 12.17', None, 12171111) + + def test_um_version(self): + self.check_cube_um_source_yields_lbsrce( + 'Data from Met Office Unified Model 12.17', '25.36', 25361111) + + +class Test_Save__LbprocProduction(tests.IrisTest): + # This test class is a little different to the others. + # If it called `pp.save` via `_pp_save_ppfield_values` it would run + # `pp_save_rules.verify` and run all the save rules. As this class uses + # a 3D cube with a time coord it would run the time rules, which would fail + # because the mock object does not set up the `pp.lbtim` attribute + # correctly (i.e. as a `SplittableInt` object). + # To work around this we call the lbproc rules directly here. + + def setUp(self): + self.cube = stock.realistic_3d() + self.pp_field = mock.MagicMock(spec=pp.PPField3) + self.pp_field.HEADER_DEFN = pp.PPField3.HEADER_DEFN + self.patch('iris.fileformats.pp.PPField3', + return_value=self.pp_field) + + def test_no_cell_methods(self): + lbproc = _lbproc_rules(self.cube, self.pp_field).lbproc + self.assertEqual(lbproc, 0) + + def test_mean(self): + self.cube.cell_methods = (CellMethod('mean', 'time', '1 hour'),) + lbproc = _lbproc_rules(self.cube, self.pp_field).lbproc + self.assertEqual(lbproc, 128) + + def test_minimum(self): + self.cube.cell_methods = (CellMethod('minimum', 'time', '1 hour'),) + lbproc = _lbproc_rules(self.cube, self.pp_field).lbproc + self.assertEqual(lbproc, 4096) + + def test_maximum(self): + self.cube.cell_methods = (CellMethod('maximum', 'time', '1 hour'),) + lbproc = _lbproc_rules(self.cube, self.pp_field).lbproc + self.assertEqual(lbproc, 8192) + + +class TestTimeMean(tests.IrisTest): + ''' + Tests that time mean cell method is converted to pp appropriately. + + Pattern is pairs of tests - one with time mean method, and one without, to + show divergent behaviour. + + ''' + def test_t1_time_mean(self): + cube = _get_single_time_cube(set_time_mean=True) + tc = cube.coord(axis='t') + expected = tc.units.num2date(0) + + with mock.patch('iris.fileformats.pp.PPField3', + autospec=True) as pp_field: + verify(cube, pp_field) + actual = pp_field.t1 + + self.assertEqual(expected, actual) + + def test_t1_no_time_mean(self): + cube = _get_single_time_cube() + tc = cube.coord(axis='t') + expected = tc.units.num2date(15) + + with mock.patch('iris.fileformats.pp.PPField3', + autospec=True) as pp_field: + verify(cube, pp_field) + actual = pp_field.t1 + + self.assertEqual(expected, actual) + + def test_t2_time_mean(self): + cube = _get_single_time_cube(set_time_mean=True) + tc = cube.coord(axis='t') + expected = tc.units.num2date(30) + + with mock.patch('iris.fileformats.pp.PPField3', + autospec=True) as pp_field: + verify(cube, pp_field) + actual = pp_field.t2 + + self.assertEqual(expected, actual) + + def test_t2_no_time_mean(self): + cube = _get_single_time_cube(set_time_mean=False) + expected = cftime.datetime(0, 0, 0) + + with mock.patch('iris.fileformats.pp.PPField3', + autospec=True) as pp_field: + verify(cube, pp_field) + actual = pp_field.t2 + self.assertEqual(expected, actual) + + def test_lbft_no_forecast_time(self): + # Different pattern here: checking that lbft hasn't been changed from + # the default value. + cube = _get_single_time_cube() + mock_lbft = mock.sentinel.lbft + + with mock.patch('iris.fileformats.pp.PPField3', + autospec=True) as pp_field: + pp_field.lbft = mock_lbft + verify(cube, pp_field) + actual = pp_field.lbft + + assert(mock_lbft is actual) + + def test_lbtim_no_time_mean(self): + cube = _get_single_time_cube() + expected_ib = 0 + expected_ic = 2 # 360 day calendar + + with mock.patch('iris.fileformats.pp.PPField3', + autospec=True) as pp_field: + verify(cube, pp_field) + actual_ib = pp_field.lbtim.ib + actual_ic = pp_field.lbtim.ic + + self.assertEqual(expected_ib, actual_ib) + self.assertEqual(expected_ic, actual_ic) + + def test_lbtim_time_mean(self): + cube = _get_single_time_cube(set_time_mean=True) + expected_ib = 2 # Time mean + expected_ic = 2 # 360 day calendar + + with mock.patch('iris.fileformats.pp.PPField3', + autospec=True) as pp_field: + verify(cube, pp_field) + actual_ib = pp_field.lbtim.ib + actual_ic = pp_field.lbtim.ic + + self.assertEqual(expected_ib, actual_ib) + self.assertEqual(expected_ic, actual_ic) + + def test_lbproc_no_time_mean(self): + cube = _get_single_time_cube() + expected = 0 + + with mock.patch('iris.fileformats.pp.PPField3', + autospec=True) as pp_field: + verify(cube, pp_field) + actual = pp_field.lbproc + + self.assertEqual(expected, actual) + + def test_lbproc_time_mean(self): + cube = _get_single_time_cube(set_time_mean=True) + expected = 128 + + with mock.patch('iris.fileformats.pp.PPField3', + autospec=True) as pp_field: + verify(cube, pp_field) + actual = pp_field.lbproc + + self.assertEqual(expected, actual) + + +def _get_single_time_cube(set_time_mean=False): + cube = stock.realistic_3d()[0:1, :, :] + cube.remove_coord('time') + cube.remove_coord('forecast_period') + tc = DimCoord( + points=[15, ], + standard_name='time', + units=cf_units.Unit('days since epoch', calendar='360_day'), + bounds=[[0, 30], ], + ) + cube.add_dim_coord(tc, 0) + if set_time_mean: + cube.cell_methods = (CellMethod("mean", coords='time'), ) + return cube + if __name__ == "__main__": tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp/test_save_fields.py b/lib/iris/tests/unit/fileformats/pp/test_save_fields.py new file mode 100644 index 0000000000..30d2252848 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pp/test_save_fields.py @@ -0,0 +1,70 @@ +# (C) British Crown Copyright 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.fileformats.pp.save_fields` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +import iris.fileformats.pp as pp +from iris.tests import mock + + +def asave(afilehandle): + afilehandle.write('saved') + + +class TestSaveFields(tests.IrisTest): + def setUp(self): + # Create a test object to stand in for a real PPField. + self.pp_field = mock.MagicMock(spec=pp.PPField3) + # Add minimal content required by the pp.save operation. + self.pp_field.HEADER_DEFN = pp.PPField3.HEADER_DEFN + self.pp_field.data = np.zeros((1, 1)) + self.pp_field.save = asave + + def test_save(self): + if six.PY3: + open_func = 'builtins.open' + else: + open_func = '__builtin__.open' + m = mock.mock_open() + with mock.patch(open_func, m, create=True): + pp.save_fields([self.pp_field], 'foo.pp') + self.assertTrue(mock.call('foo.pp', 'wb') in m.mock_calls) + self.assertTrue(mock.call().write('saved') in m.mock_calls) + + def test_save_append(self): + if six.PY3: + open_func = 'builtins.open' + else: + open_func = '__builtin__.open' + m = mock.mock_open() + with mock.patch(open_func, m, create=True): + pp.save_fields([self.pp_field], 'foo.pp', append=True) + self.assertTrue(mock.call('foo.pp', 'ab') in m.mock_calls) + self.assertTrue(mock.call().write('saved') in m.mock_calls) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp/test_save_pairs_from_cube.py b/lib/iris/tests/unit/fileformats/pp/test_save_pairs_from_cube.py new file mode 100644 index 0000000000..8a2990e883 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pp/test_save_pairs_from_cube.py @@ -0,0 +1,66 @@ +# (C) British Crown Copyright 2015 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.fileformats.pp.save_pairs_from_cube` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import iris.tests.stock as stock + +from iris.fileformats.pp import save_pairs_from_cube + + +class TestSaveFields(tests.IrisTest): + def setUp(self): + self.cube = stock.realistic_3d() + + def test_cube_only(self): + slices_and_fields = save_pairs_from_cube(self.cube) + for aslice, field in slices_and_fields: + self.assertEqual(aslice.shape, (9, 11)) + self.assertEqual(field.lbcode, 101) + + def test_field_coords(self): + slices_and_fields = save_pairs_from_cube( + self.cube, + field_coords=['grid_longitude', + 'grid_latitude']) + for aslice, field in slices_and_fields: + self.assertEqual(aslice.shape, (11, 9)) + self.assertEqual(field.lbcode, 101) + + def test_lazy_data(self): + cube = self.cube.copy() + # "Rebase" the cube onto a lazy version of its data. + cube.data = cube.lazy_data() + # Check that lazy data is preserved in save-pairs generation. + slices_and_fields = save_pairs_from_cube(cube) + for aslice, _ in slices_and_fields: + self.assertTrue(aslice.has_lazy_data()) + + def test_default_bmdi(self): + slices_and_fields = save_pairs_from_cube(self.cube) + _, field = next(slices_and_fields) + self.assertEqual(field.bmdi, -1e30) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp_load_rules/__init__.py b/lib/iris/tests/unit/fileformats/pp_load_rules/__init__.py new file mode 100644 index 0000000000..b102ddcd0f --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pp_load_rules/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2013 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.fileformats.pp_load_rules` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/pp_load_rules/test__all_other_rules.py b/lib/iris/tests/unit/fileformats/pp_load_rules/test__all_other_rules.py new file mode 100644 index 0000000000..dc30769598 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pp_load_rules/test__all_other_rules.py @@ -0,0 +1,236 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the `iris.fileformats.pp_load_rules._all_other_rules` function. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np +from cf_units import Unit, CALENDAR_GREGORIAN, CALENDAR_360_DAY +from cftime import datetime as nc_datetime + +import cartopy.crs as ccrs +import iris +from iris.fileformats.pp_load_rules import _all_other_rules +from iris.fileformats.pp import SplittableInt +from iris.coords import CellMethod, DimCoord, AuxCoord +from iris.tests import mock +from iris.tests.unit.fileformats import TestField + + +# iris.fileformats.pp_load_rules._all_other_rules() returns a tuple of +# of various metadata. This constant is the index into this +# tuple to obtain the cell methods. +CELL_METHODS_INDEX = 5 +DIM_COORDS_INDEX = 6 +AUX_COORDS_INDEX = 7 + + +class TestCellMethods(tests.IrisTest): + def test_time_mean(self): + # lbproc = 128 -> mean + # lbtim.ib = 2 -> simple t1 to t2 interval. + field = mock.MagicMock(lbproc=128, + lbtim=mock.Mock(ia=0, ib=2, ic=3)) + res = _all_other_rules(field)[CELL_METHODS_INDEX] + expected = [CellMethod('mean', 'time')] + self.assertEqual(res, expected) + + def test_hourly_mean(self): + # lbtim.ia = 1 -> hourly + field = mock.MagicMock(lbproc=128, + lbtim=mock.Mock(ia=1, ib=2, ic=3)) + res = _all_other_rules(field)[CELL_METHODS_INDEX] + expected = [CellMethod('mean', 'time', '1 hour')] + self.assertEqual(res, expected) + + def test_daily_mean(self): + # lbtim.ia = 24 -> daily + field = mock.MagicMock(lbproc=128, + lbtim=mock.Mock(ia=24, ib=2, ic=3)) + res = _all_other_rules(field)[CELL_METHODS_INDEX] + expected = [CellMethod('mean', 'time', '24 hour')] + self.assertEqual(res, expected) + + def test_custom_max(self): + field = mock.MagicMock(lbproc=8192, + lbtim=mock.Mock(ia=47, ib=2, ic=3)) + res = _all_other_rules(field)[CELL_METHODS_INDEX] + expected = [CellMethod('maximum', 'time', '47 hour')] + self.assertEqual(res, expected) + + def test_daily_min(self): + # lbproc = 4096 -> min + field = mock.MagicMock(lbproc=4096, + lbtim=mock.Mock(ia=24, ib=2, ic=3)) + res = _all_other_rules(field)[CELL_METHODS_INDEX] + expected = [CellMethod('minimum', 'time', '24 hour')] + self.assertEqual(res, expected) + + def test_time_mean_over_multiple_years(self): + # lbtim.ib = 3 -> interval within a year, over multiple years. + field = mock.MagicMock(lbproc=128, + lbtim=mock.Mock(ia=0, ib=3, ic=3)) + res = _all_other_rules(field)[CELL_METHODS_INDEX] + expected = [CellMethod('mean within years', 'time'), + CellMethod('mean over years', 'time')] + self.assertEqual(res, expected) + + def test_hourly_mean_over_multiple_years(self): + field = mock.MagicMock(lbproc=128, + lbtim=mock.Mock(ia=1, ib=3, ic=3)) + res = _all_other_rules(field)[CELL_METHODS_INDEX] + expected = [CellMethod('mean within years', 'time', '1 hour'), + CellMethod('mean over years', 'time')] + self.assertEqual(res, expected) + + def test_climatology_max(self): + field = mock.MagicMock(lbproc=8192, + lbtim=mock.Mock(ia=24, ib=3, ic=3)) + res = _all_other_rules(field)[CELL_METHODS_INDEX] + expected = [CellMethod('maximum', 'time')] + self.assertEqual(res, expected) + + def test_climatology_max(self): + field = mock.MagicMock(lbproc=4096, + lbtim=mock.Mock(ia=24, ib=3, ic=3)) + res = _all_other_rules(field)[CELL_METHODS_INDEX] + expected = [CellMethod('minimum', 'time')] + self.assertEqual(res, expected) + + def test_other_lbtim_ib(self): + # lbtim.ib = 5 -> non-specific aggregation + field = mock.MagicMock(lbproc=4096, + lbtim=mock.Mock(ia=24, ib=5, ic=3)) + res = _all_other_rules(field)[CELL_METHODS_INDEX] + expected = [CellMethod('minimum', 'time')] + self.assertEqual(res, expected) + + def test_multiple_unordered_lbprocs(self): + field = mock.MagicMock(lbproc=192, bzx=0, bdx=1, lbnpt=3, lbrow=3, + lbtim=mock.Mock(ia=24, ib=5, ic=3), + lbcode=SplittableInt(1), x_bounds=None, + _x_coord_name=lambda: 'longitude', + _y_coord_name=lambda: 'latitude') + res = _all_other_rules(field)[CELL_METHODS_INDEX] + expected = [CellMethod('mean', 'time'), + CellMethod('mean', 'longitude')] + self.assertEqual(res, expected) + + def test_multiple_unordered_rotated_lbprocs(self): + field = mock.MagicMock(lbproc=192, bzx=0, bdx=1, lbnpt=3, lbrow=3, + lbtim=mock.Mock(ia=24, ib=5, ic=3), + lbcode=SplittableInt(101), x_bounds=None, + _x_coord_name=lambda: 'grid_longitude', + _y_coord_name=lambda: 'grid_latitude') + res = _all_other_rules(field)[CELL_METHODS_INDEX] + expected = [CellMethod('mean', 'time'), + CellMethod('mean', 'grid_longitude')] + self.assertEqual(res, expected) + + +class TestCrossSectionalTime(TestField): + def test_lbcode3x23(self): + time_bounds = np.array([[0.875, 1.125], [1.125, 1.375], + [1.375, 1.625], [1.625, 1.875]]) + field = mock.MagicMock( + lbproc=0, bzx=0, bdx=0, lbnpt=3, lbrow=4, + t1=nc_datetime(2000, 1, 2, hour=0, minute=0, second=0), + t2=nc_datetime(2000, 1, 3, hour=0, minute=0, second=0), + lbtim=mock.Mock(ia=1, ib=2, ic=2), + lbcode=SplittableInt(31323, {'iy': slice(0, 2), + 'ix': slice(2, 4)}), + x_bounds=None, + y_bounds=time_bounds, + _x_coord_name=lambda: 'longitude', + _y_coord_name=lambda: 'latitude') + + spec = ['lbtim', 'lbcode', 'lbrow', 'lbnpt', 'lbproc', 'lbsrce', + 'lbuser', 'bzx', 'bdx', 'bdy', 'bmdi', 't1', 't2', 'stash', + 'x_bounds', 'y_bounds', '_x_coord_name', '_y_coord_name'] + field.mock_add_spec(spec) + res = _all_other_rules(field)[DIM_COORDS_INDEX] + + expected_time_points = np.array([1, 1.25, 1.5, 1.75]) + (2000 * 360) + expected_unit = Unit('days since 0000-01-01 00:00:00', + calendar=CALENDAR_360_DAY) + expected = [(DimCoord(expected_time_points, standard_name='time', + units=expected_unit, bounds=time_bounds), 0)] + self.assertCoordsAndDimsListsMatch(res, expected) + + +class TestLBTIMx2x_ZeroYears(TestField): + + _spec = ['lbtim', 'lbcode', 'lbrow', 'lbnpt', 'lbproc', 'lbsrce', + 'lbhem', 'lbuser', 'bzx', 'bdx', 'bdy', 'bmdi', 't1', 't2', + 'stash', 'x_bounds', 'y_bounds', '_x_coord_name', + '_y_coord_name'] + + def _make_field(self, + lbyr=0, lbyrd=0, lbmon=3, lbmond=3, lbft=0, + bdx=1, bdy=1, bmdi=0, + ia=0, ib=2, ic=1, + lbcode=SplittableInt(3)): + return mock.MagicMock( + lbyr=lbyr, lbyrd=lbyrd, lbmon=lbmon, lbmond=lbmond, lbft=lbft, + bdx=bdx, bdy=bdy, bmdi=bmdi, + lbtim=mock.Mock(ia=ia, ib=ib, ic=ic), + lbcode=lbcode) + + def test_month_coord(self): + field = self._make_field() + field.mock_add_spec(self._spec) + res = _all_other_rules(field)[AUX_COORDS_INDEX] + + expected = [(AuxCoord(3, long_name='month_number'), None), + (AuxCoord('Mar', long_name='month', + units=Unit('no unit')), None), + (DimCoord(points=0, standard_name='forecast_period', + units=Unit('hours')), None)] + self.assertCoordsAndDimsListsMatch(res, expected) + + def test_diff_month(self): + field = self._make_field(lbmon=3, lbmond=4) + field.mock_add_spec(self._spec) + res = _all_other_rules(field)[AUX_COORDS_INDEX] + + self.assertCoordsAndDimsListsMatch(res, []) + + def test_nonzero_year(self): + field = self._make_field(lbyr=1) + field.mock_add_spec(self._spec) + res = _all_other_rules(field)[AUX_COORDS_INDEX] + + self.assertCoordsAndDimsListsMatch(res, []) + + def test_nonzero_yeard(self): + field = self._make_field(lbyrd=1) + field.mock_add_spec(self._spec) + res = _all_other_rules(field)[AUX_COORDS_INDEX] + + self.assertCoordsAndDimsListsMatch(res, []) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp_load_rules/test__collapse_degenerate_points_and_bounds.py b/lib/iris/tests/unit/fileformats/pp_load_rules/test__collapse_degenerate_points_and_bounds.py new file mode 100644 index 0000000000..4417182dec --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pp_load_rules/test__collapse_degenerate_points_and_bounds.py @@ -0,0 +1,108 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for +:func:`iris.fileformats.pp_load_rules._collapse_degenerate_points_and_bounds`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.fileformats.pp_load_rules import \ + _collapse_degenerate_points_and_bounds + + +class Test(tests.IrisTest): + def test_scalar(self): + array = np.array(1) + points, bounds = _collapse_degenerate_points_and_bounds(array) + self.assertArrayEqual(points, array) + self.assertIsNone(bounds) + + def test_1d_nochange(self): + array = np.array([1, 1, 3]) + result, _ = _collapse_degenerate_points_and_bounds(array) + self.assertArrayEqual(result, array) + + def test_1d_collapse(self): + array = np.array([1, 1, 1]) + result, _ = _collapse_degenerate_points_and_bounds(array) + self.assertArrayEqual(result, np.array([1])) + + def test_2d_nochange(self): + array = np.array([[1, 2, 3], [4, 5, 6]]) + result, _ = _collapse_degenerate_points_and_bounds(array) + self.assertArrayEqual(result, array) + + def test_2d_collapse_dim0(self): + array = np.array([[1, 2, 3], [1, 2, 3]]) + result, _ = _collapse_degenerate_points_and_bounds(array) + self.assertArrayEqual(result, np.array([[1, 2, 3]])) + + def test_2d_collapse_dim1(self): + array = np.array([[1, 1, 1], [2, 2, 2]]) + result, _ = _collapse_degenerate_points_and_bounds(array) + self.assertArrayEqual(result, np.array([[1], [2]])) + + def test_2d_collapse_both(self): + array = np.array([[3, 3, 3], [3, 3, 3]]) + result, _ = _collapse_degenerate_points_and_bounds(array) + self.assertArrayEqual(result, np.array([[3]])) + + def test_3d(self): + array = np.array([[[3, 3, 3], [4, 4, 4]], [[3, 3, 3], [4, 4, 4]]]) + result, _ = _collapse_degenerate_points_and_bounds(array) + self.assertArrayEqual(result, np.array([[[3], [4]]])) + + def test_multiple_odd_dims(self): + # Test to ensure multiple collapsed dimensions don't interfere. + # make a 5-D array where dimensions 0, 2 and 3 are degenerate. + array = np.arange(3 ** 5).reshape([3] * 5) + array[1:] = array[0:1] + array[:, :, 1:] = array[:, :, 0:1] + array[:, :, :, 1:] = array[:, :, :, 0:1] + result, _ = _collapse_degenerate_points_and_bounds(array) + self.assertEqual(array.shape, (3, 3, 3, 3, 3)) + self.assertEqual(result.shape, (1, 3, 1, 1, 3)) + self.assertTrue(np.all(result == array[0:1, :, 0:1, 0:1, :])) + + def test_bounds_collapse(self): + points = np.array([1, 1, 1]) + bounds = np.array([[0, 1], [0, 1], [0, 1]]) + result_pts, result_bds = \ + _collapse_degenerate_points_and_bounds(points, bounds) + self.assertArrayEqual(result_pts, np.array([1])) + self.assertArrayEqual(result_bds, np.array([[0, 1]])) + + def test_bounds_no_collapse(self): + points = np.array([1, 1, 1]) + bounds = np.array([[0, 1], [0, 1], [0, 2]]) + result_pts, result_bds = \ + _collapse_degenerate_points_and_bounds(points, bounds) + self.assertArrayEqual(result_pts, points) + self.assertArrayEqual(result_bds, bounds) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_scalar_pseudo_level_coords.py b/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_scalar_pseudo_level_coords.py new file mode 100644 index 0000000000..83140476a3 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_scalar_pseudo_level_coords.py @@ -0,0 +1,48 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for +:func:`iris.fileformats.pp_load_rules._convert_pseudo_level_coords`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.coords import DimCoord +from iris.tests.unit.fileformats import TestField + +from iris.fileformats.pp_load_rules import _convert_scalar_pseudo_level_coords + + +class Test(TestField): + def test_valid(self): + coords_and_dims = _convert_scalar_pseudo_level_coords(lbuser5=21) + self.assertEqual(coords_and_dims, + [(DimCoord([21], long_name='pseudo_level'), None)]) + + def test_missing_indicator(self): + coords_and_dims = _convert_scalar_pseudo_level_coords(lbuser5=0) + self.assertEqual(coords_and_dims, []) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_scalar_realization_coords.py b/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_scalar_realization_coords.py new file mode 100644 index 0000000000..5f6f4a4324 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_scalar_realization_coords.py @@ -0,0 +1,48 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for +:func:`iris.fileformats.pp_load_rules._convert_scalar_realization_coords`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.coords import DimCoord +from iris.tests.unit.fileformats import TestField + +from iris.fileformats.pp_load_rules import _convert_scalar_realization_coords + + +class Test(TestField): + def test_valid(self): + coords_and_dims = _convert_scalar_realization_coords(lbrsvd4=21) + self.assertEqual(coords_and_dims, + [(DimCoord([21], standard_name='realization'), None)]) + + def test_missing_indicator(self): + coords_and_dims = _convert_scalar_realization_coords(lbrsvd4=0) + self.assertEqual(coords_and_dims, []) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_time_coords.py b/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_time_coords.py new file mode 100644 index 0000000000..f00b39156f --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_time_coords.py @@ -0,0 +1,567 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for +:func:`iris.fileformats.pp_load_rules._convert_time_coords`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from cf_units import Unit, CALENDAR_GREGORIAN +from cftime import datetime as nc_datetime +import numpy as np + +from iris.coords import DimCoord, AuxCoord +from iris.fileformats.pp import SplittableInt +from iris.fileformats.pp_load_rules import _convert_time_coords +from iris.tests import mock +from iris.tests.unit.fileformats import TestField + + +def _lbtim(ia=0, ib=0, ic=0): + return SplittableInt(ic + 10 * (ib + 10 * ia), {'ia': 2, 'ib': 1, 'ic': 0}) + + +def _lbcode(value=None, ix=None, iy=None): + if value is not None: + result = SplittableInt(value, {'iy': slice(0, 2), 'ix': slice(2, 4)}) + else: + # N.B. if 'value' is None, both ix and iy must be set. + result = SplittableInt(10000 + 100 * ix + iy, + {'iy': slice(0, 2), 'ix': slice(2, 4)}) + return result + + +_EPOCH_HOURS_UNIT = Unit('hours since epoch', calendar=CALENDAR_GREGORIAN) +_HOURS_UNIT = Unit('hours') + + +class TestLBTIMx0x_SingleTimepoint(TestField): + def _check_timepoint(self, lbcode, expect_match=True): + lbtim = _lbtim(ib=0, ic=1) + t1 = nc_datetime(1970, 1, 1, hour=6, minute=0, second=0) + t2 = nc_datetime(0, 0, 0) # not used in result + lbft = None # unused + coords_and_dims = _convert_time_coords( + lbcode=lbcode, lbtim=lbtim, epoch_hours_unit=_EPOCH_HOURS_UNIT, + t1=t1, t2=t2, lbft=lbft) + if expect_match: + expect_result = [ + (DimCoord(24 * 0.25, standard_name='time', + units=_EPOCH_HOURS_UNIT), + None)] + else: + expect_result = [] + self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) + + def test_normal_xy_dims(self): + self._check_timepoint(_lbcode(1)) + + def test_non_time_cross_section(self): + self._check_timepoint(_lbcode(ix=1, iy=2)) + + def test_time_cross_section(self): + self._check_timepoint(_lbcode(ix=1, iy=20), expect_match=False) + + +class TestLBTIMx1x_Forecast(TestField): + def _check_forecast(self, lbcode, expect_match=True): + lbtim = _lbtim(ib=1, ic=1) + # Validity time + t1 = nc_datetime(1970, 1, 10, hour=6, minute=0, second=0) + # Forecast time + t2 = nc_datetime(1970, 1, 9, hour=3, minute=0, second=0) + lbft = None # unused + coords_and_dims = _convert_time_coords( + lbcode=lbcode, lbtim=lbtim, epoch_hours_unit=_EPOCH_HOURS_UNIT, + t1=t1, t2=t2, lbft=lbft) + if expect_match: + expect_result = [ + (DimCoord(24 * 1.125, + standard_name='forecast_period', units='hours'), + None), + (DimCoord(24 * 9.25, + standard_name='time', units=_EPOCH_HOURS_UNIT), + None), + (DimCoord(24 * 8.125, + standard_name='forecast_reference_time', + units=_EPOCH_HOURS_UNIT), + None)] + else: + expect_result = [] + self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) + + def test_normal_xy(self): + self._check_forecast(_lbcode(1)) + + def test_non_time_cross_section(self): + self._check_forecast(_lbcode(ix=1, iy=2)) + + def test_time_cross_section(self): + self._check_forecast(_lbcode(ix=1, iy=20), expect_match=False) + + def test_exact_hours(self): + lbtim = _lbtim(ib=1, ic=1) + t1 = nc_datetime(2015, 1, 20, hour=7, minute=0, second=0) + t2 = nc_datetime(2015, 1, 20, hour=0, minute=0, second=0) + coords_and_dims = _convert_time_coords( + lbcode=_lbcode(1), lbtim=lbtim, epoch_hours_unit=_EPOCH_HOURS_UNIT, + t1=t1, t2=t2, lbft=None) + (fp, _), (t, _), (frt, _) = coords_and_dims + # These should both be exact whole numbers. + self.assertEqual(fp.points[0], 7) + self.assertEqual(t.points[0], 394927) + + def test_not_exact_hours(self): + lbtim = _lbtim(ib=1, ic=1) + t1 = nc_datetime(2015, 1, 20, hour=7, minute=10, second=0) + t2 = nc_datetime(2015, 1, 20, hour=0, minute=0, second=0) + coords_and_dims = _convert_time_coords( + lbcode=_lbcode(1), lbtim=lbtim, epoch_hours_unit=_EPOCH_HOURS_UNIT, + t1=t1, t2=t2, lbft=None) + (fp, _), (t, _), (frt, _) = coords_and_dims + self.assertEqual(fp.points[0], 7.1666666641831398) + self.assertEqual(t.points[0], 394927.16666666418) + + +class TestLBTIMx2x_TimePeriod(TestField): + def _check_period(self, lbcode, expect_match=True): + lbtim = _lbtim(ib=2, ic=1) + # Start time + t1 = nc_datetime(1970, 1, 9, hour=3, minute=0, second=0) + # End time + t2 = nc_datetime(1970, 1, 10, hour=3, minute=0, second=0) + lbft = 2.0 # sample period + coords_and_dims = _convert_time_coords( + lbcode=lbcode, lbtim=lbtim, epoch_hours_unit=_EPOCH_HOURS_UNIT, + t1=t1, t2=t2, lbft=lbft) + if expect_match: + expect_result = [ + (DimCoord(24 * 9.125 - 2.0, + standard_name='forecast_reference_time', + units=_EPOCH_HOURS_UNIT), None), + (DimCoord(standard_name='forecast_period', units='hours', + points=[-10.0], bounds=[-22.0, 2.0]), None), + (DimCoord(standard_name='time', units=_EPOCH_HOURS_UNIT, + points=[24 * 8.625], + bounds=[24 * 8.125, 24 * 9.125]), None)] + else: + expect_result = [] + self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) + + def test_normal_xy(self): + self._check_period(_lbcode(1)) + + def test_non_time_cross_section(self): + self._check_period(_lbcode(ix=1, iy=2)) + + def test_time_cross_section(self): + self._check_period(_lbcode(ix=1, iy=20), expect_match=False) + + +class TestLBTIMx3x_YearlyAggregation(TestField): + def _check_yearly(self, lbcode, expect_match=True): + lbtim = _lbtim(ib=3, ic=1) + # Start time + t1 = nc_datetime(1970, 1, 9, hour=9, minute=0, second=0) + # End time + t2 = nc_datetime(1972, 1, 11, hour=9, minute=0, second=0) + lbft = 3.0 # sample period + coords_and_dims = _convert_time_coords( + lbcode=lbcode, lbtim=lbtim, epoch_hours_unit=_EPOCH_HOURS_UNIT, + t1=t1, t2=t2, lbft=lbft) + if expect_match: + t1_hours = 24 * 8.375 + t2_hours = 24 * (10.375 + 2 * 365) + period_hours = 24.0 * (2 * 365 + 2) + expect_result = [ + (DimCoord([t2_hours - lbft], + standard_name='forecast_reference_time', + units=_EPOCH_HOURS_UNIT), None), + (DimCoord(standard_name='forecast_period', units='hours', + points=[lbft], bounds=[lbft - period_hours, lbft]), + None), + (DimCoord(standard_name='time', units=_EPOCH_HOURS_UNIT, + points=[t2_hours], + bounds=[t1_hours, t2_hours]), None)] + else: + expect_result = [] + self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) + + def test_normal_xy(self): + self._check_yearly(_lbcode(1)) + + def test_non_time_cross_section(self): + self._check_yearly(_lbcode(ix=1, iy=2)) + + def test_time_cross_section(self): + self._check_yearly(_lbcode(ix=1, iy=20), expect_match=False) + + +class TestLBTIMx2x_ZeroYear(TestField): + def test_(self): + lbtim = _lbtim(ib=2, ic=1) + t1 = nc_datetime(0, 1, 1) + t2 = nc_datetime(0, 1, 31, 23, 59, 00) + lbft = 0 + lbcode = _lbcode(1) + coords_and_dims = _convert_time_coords( + lbcode=lbcode, lbtim=lbtim, epoch_hours_unit=_EPOCH_HOURS_UNIT, + t1=t1, t2=t2, lbft=lbft) + self.assertEqual(coords_and_dims, []) + + +class TestLBTIMxxx_Unhandled(TestField): + def test_unrecognised(self): + lbtim = _lbtim(ib=4, ic=1) + t1 = nc_datetime(0, 0, 0) + t2 = nc_datetime(0, 0, 0) + lbft = None + lbcode = _lbcode(0) + coords_and_dims = _convert_time_coords( + lbcode=lbcode, lbtim=lbtim, epoch_hours_unit=_EPOCH_HOURS_UNIT, + t1=t1, t2=t2, lbft=lbft) + self.assertEqual(coords_and_dims, []) + + +class TestLBCODE3xx(TestField): + def test(self): + lbcode = _lbcode(value=31323) + lbtim = _lbtim(ib=2, ic=2) + t1 = nc_datetime(1970, 1, 3, hour=0, minute=0, second=0) + t2 = nc_datetime(1970, 1, 4, hour=0, minute=0, second=0) + lbft = 24 * 4 + coords_and_dims = _convert_time_coords( + lbcode=lbcode, lbtim=lbtim, epoch_hours_unit=_EPOCH_HOURS_UNIT, + t1=t1, t2=t2, lbft=lbft) + t2_hours = 24 * 3 + expected_result = [(DimCoord([t2_hours-lbft], + standard_name='forecast_reference_time', + units=_EPOCH_HOURS_UNIT), None)] + self.assertCoordsAndDimsListsMatch(coords_and_dims, expected_result) + + +class TestArrayInputWithLBTIM_0_0_1(TestField): + def test_t1_list(self): + # lbtim ia = 0, ib = 0, ic = 1 + # with a series of times (t1). + lbcode = _lbcode(1) + lbtim = _lbtim(ia=0, ib=0, ic=1) + hours = np.array([0, 3, 6, 9, 12]) + # Validity time - vector of different values + t1 = [nc_datetime(1970, 1, 9, hour=3 + hour) for hour in hours] + t1_dims = (0,) + # Forecast reference time - scalar (not used) + t2 = nc_datetime(1970, 1, 9, hour=3) + lbft = None + + coords_and_dims = _convert_time_coords( + lbcode=lbcode, lbtim=lbtim, epoch_hours_unit=_EPOCH_HOURS_UNIT, + t1=t1, t2=t2, lbft=lbft, + t1_dims=t1_dims) + + # Expected coords. + time_coord = DimCoord((24 * 8) + 3 + hours, + standard_name='time', + units=_EPOCH_HOURS_UNIT) + expected = [(time_coord, (0,))] + self.assertCoordsAndDimsListsMatch(coords_and_dims, expected) + + +class TestArrayInputWithLBTIM_0_1_1(TestField): + def test_t1_list_t2_scalar(self): + # lbtim ia = 0, ib = 1, ic = 1 + # with a single forecast reference time (t2) and a series + # of validity times (t1). + lbcode = _lbcode(1) + lbtim = _lbtim(ia=0, ib=1, ic=1) + forecast_period_in_hours = np.array([0, 3, 6, 9, 12]) + # Validity time - vector of different values + t1 = [nc_datetime(1970, 1, 9, hour=(3 + fp)) for fp in + forecast_period_in_hours] + t1_dims = (0,) + # Forecast reference time - scalar + t2 = nc_datetime(1970, 1, 9, hour=3) + lbft = None # Not used. + + coords_and_dims = _convert_time_coords( + lbcode=lbcode, lbtim=lbtim, epoch_hours_unit=_EPOCH_HOURS_UNIT, + t1=t1, t2=t2, lbft=lbft, + t1_dims=t1_dims) + + # Expected coords. + fp_coord = DimCoord(forecast_period_in_hours, + standard_name='forecast_period', + units='hours') + time_coord = DimCoord((24 * 8) + 3 + forecast_period_in_hours, + standard_name='time', + units=_EPOCH_HOURS_UNIT) + fref_time_coord = DimCoord((24 * 8) + 3, + standard_name='forecast_reference_time', + units=_EPOCH_HOURS_UNIT) + expected = [(fp_coord, (0,)), + (time_coord, (0,)), + (fref_time_coord, None)] + self.assertCoordsAndDimsListsMatch(coords_and_dims, expected) + + def test_t1_and_t2_list(self): + # lbtim ia = 0, ib = 1, ic = 1 + # with a single repeated forecast reference time (t2) and a series + # of validity times (t1). + lbcode = _lbcode(1) + lbtim = _lbtim(ia=0, ib=1, ic=1) + forecast_period_in_hours = np.array([0, 3, 6, 9, 12]) + # Validity time - vector of different values + t1 = [nc_datetime(1970, 1, 9, hour=(3 + fp)) for fp in + forecast_period_in_hours] + t1_dims = (0,) + # Forecast reference time - vector of same values + t2 = [nc_datetime(1970, 1, 9, hour=3) for _ in + forecast_period_in_hours] + t2_dims = (0,) + lbft = None # Not used. + + coords_and_dims = _convert_time_coords( + lbcode=lbcode, lbtim=lbtim, epoch_hours_unit=_EPOCH_HOURS_UNIT, + t1=t1, t2=t2, lbft=lbft, + t1_dims=t1_dims, t2_dims=t2_dims) + + # Expected coords. + fp_coord = DimCoord(forecast_period_in_hours, + standard_name='forecast_period', + units='hours') + time_coord = DimCoord((24 * 8) + 3 + forecast_period_in_hours, + standard_name='time', + units=_EPOCH_HOURS_UNIT) + fref_time_coord = DimCoord((24 * 8) + 3, + standard_name='forecast_reference_time', + units=_EPOCH_HOURS_UNIT) + expected = [(fp_coord, (0,)), + (time_coord, (0,)), + (fref_time_coord, None)] + self.assertCoordsAndDimsListsMatch(coords_and_dims, expected) + + def test_t1_and_t2_orthogonal_lists(self): + # lbtim ia = 0, ib = 1, ic = 1 + # with a single repeated forecast reference time (t2) and a series + # of validity times (t1). + lbcode = _lbcode(1) + lbtim = _lbtim(ia=0, ib=1, ic=1) + years = np.array([1970, 1971, 1972]) + hours = np.array([3, 6, 9, 12]) + # Validity time - vector of different values + t1 = [nc_datetime(year, 1, 9, hour=12) for year in years] + t1_dims = (0,) + # Forecast reference time - vector of different values + t2 = [nc_datetime(1970, 1, 9, hour=hour) for hour in hours] + t2_dims = (1,) + lbft = None # Not used. + + coords_and_dims = _convert_time_coords( + lbcode=lbcode, lbtim=lbtim, epoch_hours_unit=_EPOCH_HOURS_UNIT, + t1=t1, t2=t2, lbft=lbft, + t1_dims=t1_dims, t2_dims=t2_dims) + + # Expected coords. + points = [[(year - 1970) * 365 * 24 + 12 - hour for hour + in hours] for year in years] + fp_coord = AuxCoord(points, + standard_name='forecast_period', + units='hours') + points = (years - 1970) * 24 * 365 + (24 * 8) + 12 + time_coord = DimCoord(points, + standard_name='time', + units=_EPOCH_HOURS_UNIT) + points = (24 * 8) + hours + fref_time_coord = DimCoord(points, + standard_name='forecast_reference_time', + units=_EPOCH_HOURS_UNIT) + expected = [(fp_coord, (0, 1)), # Spans dims 0 and 1. + (time_coord, (0,)), + (fref_time_coord, (1,))] + self.assertCoordsAndDimsListsMatch(coords_and_dims, expected) + + def test_t1_multi_dim_list_t2_scalar(self): + # Another case of lbtim ia = 0, ib = 1, ic = 1 but + # with a changing forecast reference time (t2) and + # validity time (t1). + lbcode = _lbcode(1) + lbtim = _lbtim(ia=0, ib=1, ic=1) + forecast_period_in_hours = np.array([0, 3, 6, 9, 12]) + years = np.array([1970, 1971, 1972]) + # Validity time - 2d array of different values + t1 = [[nc_datetime(year, 1, 9, hour=(3 + fp)) for fp in + forecast_period_in_hours] for year in years] + t1_dims = (0, 1) + # Forecast reference time - vector of different values + t2 = nc_datetime(1970, 1, 9, hour=3) + lbft = None # Not used. + + coords_and_dims = _convert_time_coords( + lbcode=lbcode, lbtim=lbtim, epoch_hours_unit=_EPOCH_HOURS_UNIT, + t1=t1, t2=t2, lbft=lbft, + t1_dims=t1_dims) + + # Expected coords. + fp_coord = AuxCoord([forecast_period_in_hours + + (year - 1970) * 365 * 24 for year in years], + standard_name='forecast_period', + units='hours') + time_coord = AuxCoord([(24 * 8) + 3 + forecast_period_in_hours + + (year - 1970) * 365 * 24 for year in years], + standard_name='time', + units=_EPOCH_HOURS_UNIT) + fref_time_coord = DimCoord((24 * 8) + 3, + standard_name='forecast_reference_time', + units=_EPOCH_HOURS_UNIT) + expected = [(fp_coord, (0, 1)), + (time_coord, (0, 1)), + (fref_time_coord, None)] + self.assertCoordsAndDimsListsMatch(coords_and_dims, expected) + + def test_t1_and_t2_nparrays(self): + # lbtim ia = 0, ib = 1, ic = 1 + # with a single repeated forecast reference time (t2) and a series + # of validity times (t1). + lbcode = _lbcode(1) + lbtim = _lbtim(ia=0, ib=1, ic=1) + forecast_period_in_hours = np.array([0, 3, 6, 9, 12]) + # Validity time - vector of different values + t1 = np.array([nc_datetime(1970, 1, 9, hour=(3 + fp)) for fp in + forecast_period_in_hours]) + t1_dims = (0,) + # Forecast reference time - vector of same values + t2 = np.array([nc_datetime(1970, 1, 9, hour=3) for _ in + forecast_period_in_hours]) + t2_dims = (0,) + lbft = None # Not used. + + coords_and_dims = _convert_time_coords( + lbcode=lbcode, lbtim=lbtim, epoch_hours_unit=_EPOCH_HOURS_UNIT, + t1=t1, t2=t2, lbft=lbft, + t1_dims=t1_dims, t2_dims=t2_dims) + + # Expected coords. + fp_coord = DimCoord(forecast_period_in_hours, + standard_name='forecast_period', + units='hours') + time_coord = DimCoord((24 * 8) + 3 + forecast_period_in_hours, + standard_name='time', + units=_EPOCH_HOURS_UNIT) + fref_time_coord = DimCoord((24 * 8) + 3, + standard_name='forecast_reference_time', + units=_EPOCH_HOURS_UNIT) + expected = [(fp_coord, (0,)), + (time_coord, (0,)), + (fref_time_coord, None)] + self.assertCoordsAndDimsListsMatch(coords_and_dims, expected) + + +class TestArrayInputWithLBTIM_0_2_1(TestField): + def test_t1_list_t2_scalar(self): + lbtim = _lbtim(ib=2, ic=1) + lbcode = _lbcode(1) + hours = np.array([0, 3, 6, 9]) + # Start times - vector + t1 = [nc_datetime(1970, 1, 9, hour=9 + hour) for + hour in hours] + t1_dims = (0,) + # End time - scalar + t2 = nc_datetime(1970, 1, 11, hour=9) + lbft = 3.0 # Sample period + + coords_and_dims = _convert_time_coords( + lbcode=lbcode, lbtim=lbtim, epoch_hours_unit=_EPOCH_HOURS_UNIT, + t1=t1, t2=t2, lbft=lbft, + t1_dims=t1_dims) + + # Expected coords. + points = lbft - (48 - hours) / 2.0 + bounds = np.array([lbft - (48 - hours), + np.ones_like(hours) * lbft]).transpose() + fp_coord = AuxCoord(points, + standard_name='forecast_period', + units='hours', + bounds=bounds) + points = 9 * 24 + 9 + (hours / 2.0) + bounds = np.array([8 * 24 + 9 + hours, + np.ones_like(hours) * 10 * 24 + 9]).transpose() + time_coord = AuxCoord(points, + standard_name='time', + units=_EPOCH_HOURS_UNIT, + bounds=bounds) + points = 10 * 24 + 9 - lbft + fref_time_coord = DimCoord(points, + standard_name='forecast_reference_time', + units=_EPOCH_HOURS_UNIT) + expected = [(fp_coord, (0,)), + (time_coord, (0,)), + (fref_time_coord, None)] + self.assertCoordsAndDimsListsMatch(coords_and_dims, expected) + + +class TestArrayInputWithLBTIM_0_3_1(TestField): + def test_t1_scalar_t2_list(self): + lbtim = _lbtim(ib=3, ic=1) + lbcode = _lbcode(1) + years = np.array([1972, 1973, 1974]) + # Start times - scalar + t1 = nc_datetime(1970, 1, 9, hour=9) + # End time - vector + t2 = [nc_datetime(year, 1, 11, hour=9) for + year in years] + t2_dims = (0,) + lbft = 3.0 # Sample period + + coords_and_dims = _convert_time_coords( + lbcode=lbcode, lbtim=lbtim, epoch_hours_unit=_EPOCH_HOURS_UNIT, + t1=t1, t2=t2, lbft=lbft, + t2_dims=t2_dims) + + # Expected coords. + points = np.ones_like(years) * lbft + bounds = np.array([lbft - ((years - 1970) * 365 * 24 + 2 * 24), + points]).transpose() + fp_coord = AuxCoord(points, + standard_name='forecast_period', + units='hours', + bounds=bounds) + points = (years - 1970) * 365 * 24 + 10 * 24 + 9 + bounds = np.array([np.ones_like(points) * (8 * 24 + 9), + points]).transpose() + # The time coordinate is an AuxCoord as the lower bound for each + # cell is the same so it does not meet the monotonicity requirement. + time_coord = AuxCoord(points, + standard_name='time', + units=_EPOCH_HOURS_UNIT, + bounds=bounds) + fref_time_coord = DimCoord(points - lbft, + standard_name='forecast_reference_time', + units=_EPOCH_HOURS_UNIT) + expected = [(fp_coord, (0,)), + (time_coord, (0,)), + (fref_time_coord, (0,))] + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_vertical_coords.py b/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_vertical_coords.py new file mode 100644 index 0000000000..03fb30f8ba --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_vertical_coords.py @@ -0,0 +1,497 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for +:func:`iris.fileformats.pp_load_rules._convert_vertical_coords`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.coords import DimCoord, AuxCoord +from iris.aux_factory import HybridPressureFactory, HybridHeightFactory +from iris.fileformats.pp import SplittableInt, STASH +from iris.fileformats.pp_load_rules import Reference, _convert_vertical_coords +from iris.tests.unit.fileformats import TestField + + +def _lbcode(value=None, ix=None, iy=None): + if value is not None: + result = SplittableInt(value, {'iy': slice(0, 2), 'ix': slice(2, 4)}) + else: + # N.B. if 'value' is None, both ix and iy must be set. + result = SplittableInt(10000 + 100 * ix + iy, + {'iy': slice(0, 2), 'ix': slice(2, 4)}) + return result + + +class TestLBVC001_Height(TestField): + def _check_height(self, blev, stash, + expect_normal=True, expect_fixed_height=None, dim=None): + lbvc = 1 + lbcode = _lbcode(0) # effectively unused in this case + lblev, bhlev, bhrlev, brsvd1, brsvd2, brlev = \ + None, None, None, None, None, None + coords_and_dims, factories = _convert_vertical_coords( + lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, + bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, + brlev=brlev, dim=dim) + if expect_normal: + expect_result = [ + (DimCoord(blev, standard_name='height', units='m', + attributes={'positive': 'up'}), + dim)] + elif expect_fixed_height: + expect_result = [ + (DimCoord(expect_fixed_height, standard_name='height', + units='m', attributes={'positive': 'up'}), + None)] + else: + expect_result = [] + self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) + self.assertEqual(factories, []) + + def test_normal_height__present(self): + self._check_height(blev=12.3, stash=STASH(1, 1, 1)) + + def test_normal_height__present_vector(self): + data = [12.3, 123.4, 1234.5] + dim = 0 + for blev in [data, np.asarray(data)]: + for dim_i in [dim, (dim,)]: + self._check_height(blev=blev, stash=STASH(1, 1, 1), dim=dim_i) + + def test_normal_height__absent(self): + self._check_height(blev=-1, stash=STASH(1, 1, 1), + expect_normal=False) + + def test_normal_height__absent_vector(self): + data = [-1, -1, -1] + dim = 1 + for blev in [data, np.asarray(data)]: + for dim_i in [dim, (dim,)]: + self._check_height(blev=blev, stash=STASH(1, 1, 1), + expect_normal=False, dim=dim_i) + + def test_normal_height__absent_mixed_vector(self): + data = [-1, 12.3, -1, 123.4] + dim = 2 + for blev in [data, np.asarray(data)]: + for dim_i in [dim, (dim,)]: + self._check_height(blev=blev, stash=STASH(1, 1, 1), + expect_normal=False, dim=dim_i) + + def test_implied_height_1m5(self): + self._check_height(blev=75.2, stash=STASH(1, 3, 236), + expect_normal=False, expect_fixed_height=1.5) + + def test_implied_height_1m5__vector(self): + data = [1, 2, 3, 4] + dim = 3 + for blev in [data, np.asarray(data)]: + for dim_i in [dim, (dim,)]: + self._check_height(blev=blev, stash=STASH(1, 3, 236), + expect_normal=False, + expect_fixed_height=1.5, dim=dim_i) + + def test_implied_height_10m(self): + self._check_height(blev=75.2, stash=STASH(1, 3, 225), + expect_normal=False, expect_fixed_height=10.0) + + def test_implied_height_10m__vector(self): + data = list(range(10)) + dim = 4 + for blev in [data, np.asarray(data)]: + for dim_i in [dim, (dim,)]: + self._check_height(blev=blev, stash=STASH(1, 3, 225), + expect_normal=False, + expect_fixed_height=10.0, dim=dim_i) + + +class TestLBVC002_Depth(TestField): + def _check_depth(self, lbcode, lblev=23.0, blev=123.4, brlev=0.0, + brsvd1=0.0, expect_bounds=True, expect_match=True, + expect_mixed=False, dim=None): + lbvc = 2 + stash = STASH(1, 1, 1) + bhlev, bhrlev, brsvd2 = None, None, None + coords_and_dims, factories = _convert_vertical_coords( + lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, + bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, + brlev=brlev, dim=dim) + if expect_match: + expect_result = [ + (DimCoord(lblev, + standard_name='model_level_number', + attributes={'positive': 'down'}), dim)] + if expect_bounds: + brsvd1 = np.atleast_1d(brsvd1) + brlev = np.atleast_1d(brlev) + if expect_mixed: + lower = np.where(brsvd1 == brlev, blev, brsvd1) + upper = np.where(brsvd1 == brlev, blev, brlev) + else: + lower, upper = brsvd1, brlev + bounds = np.vstack((lower, upper)).T + expect_result.append( + (DimCoord(blev, standard_name='depth', + units='m', + bounds=bounds, + attributes={'positive': 'down'}), dim)) + else: + expect_result.append( + (DimCoord(blev, standard_name='depth', units='m', + attributes={'positive': 'down'}), dim)) + else: + expect_result = [] + self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) + self.assertEqual(factories, []) + + def test_unbounded(self): + self._check_depth(_lbcode(1), lblev=23.0, expect_bounds=False) + + def test_unbounded__vector(self): + lblev = [1, 2, 3] + blev = [10, 20, 30] + brsvd1 = [5, 15, 25] + brlev = [5, 15, 25] + self._check_depth(_lbcode(1), lblev=lblev, blev=blev, brsvd1=brsvd1, + brlev=brlev, expect_bounds=False, dim=1) + + def test_unbounded__vector_no_depth(self): + lblev = [1, 2, 3] + blev = [10, 20, 30] + brsvd1 = [5, 15, 25] + brlev = [5, 15, 666] # not all equal or all unequal! + self._check_depth(_lbcode(1), lblev=lblev, blev=blev, brsvd1=brsvd1, + brlev=brlev, expect_mixed=True, dim=0) + + def test_bounded(self): + self._check_depth(_lbcode(1), lblev=23.0, brlev=22.5, brsvd1=23.5, + expect_bounds=True) + + def test_bounded__vector(self): + lblev = [1, 2, 3] + blev = [10, 20, 30] + brsvd1 = [5, 15, 25] + brlev = [15, 25, 35] + self._check_depth(_lbcode(1), lblev=lblev, blev=blev, brsvd1=brsvd1, + brlev=brlev, expect_bounds=True, dim=1) + + def test_cross_section(self): + self._check_depth(_lbcode(ix=1, iy=2), lblev=23.0, + expect_match=False) + + def test_cross_section__vector(self): + lblev = [1, 2, 3] + blev = [10, 20, 30] + brsvd1 = [5, 15, 25] + brlev = [15, 25, 35] + self._check_depth(_lbcode(ix=1, iy=2), lblev=lblev, blev=blev, + brsvd1=brsvd1, brlev=brlev, + expect_match=False, dim=1) + + +class TestLBVC006_SoilLevel(TestField): + def _check_soil_level(self, lbcode, lblev=12.3, expect_match=True, + dim=None): + lbvc = 6 + stash = STASH(1, 1, 1) + brsvd1, brlev = 0, 0 + if hasattr(lblev, '__iter__'): + brsvd1 = [0] * len(lblev) + brlev = [0] * len(lblev) + blev, bhlev, bhrlev, brsvd2 = None, None, None, None + coords_and_dims, factories = _convert_vertical_coords( + lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, + bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, + brlev=brlev, dim=dim) + expect_result = [] + if expect_match: + coord = DimCoord(lblev, long_name='soil_model_level_number', + attributes={'positive': 'down'}) + expect_result = [(coord, dim)] + self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) + self.assertEqual(factories, []) + + def test_normal(self): + self._check_soil_level(_lbcode(0)) + + def test_normal__vector(self): + lblev = np.arange(10) + self._check_soil_level(_lbcode(0), lblev=lblev, dim=0) + + def test_cross_section(self): + self._check_soil_level(_lbcode(ix=1, iy=2), expect_match=False) + + def test_cross_section__vector(self): + lblev = np.arange(10) + self._check_soil_level(_lbcode(ix=1, iy=2), lblev=lblev, + expect_match=False, dim=0) + + +class TestLBVC006_SoilDepth(TestField): + def _check_soil_depth(self, lbcode, blev=0.05, brsvd1=0, brlev=0.1, + expect_match=True, dim=None): + lbvc = 6 + stash = STASH(1, 1, 1) + lblev, bhlev, bhrlev, brsvd2 = None, None, None, None + coords_and_dims, factories = _convert_vertical_coords( + lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, + bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, + brlev=brlev, dim=dim) + expect_result = [] + if expect_match: + coord = DimCoord(blev, standard_name='depth', + bounds=np.vstack((brsvd1, brlev)).T, + units='m', attributes={'positive': 'down'}) + expect_result = [(coord, dim)] + self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) + self.assertEqual(factories, []) + + def test_normal(self): + self._check_soil_depth(_lbcode(0)) + + def test_normal__vector(self): + points = np.arange(10) + self._check_soil_depth(_lbcode(0), blev=points, + brsvd1=points - 1, brlev=points + 1, dim=0) + + def test_bad_bounds(self): + points = [-0.5, 0.5] + lower = [-1, 1] + upper = [-1, 1] + self._check_soil_depth(_lbcode(0), blev=points, + brsvd1=lower, brlev=upper, dim=0, + expect_match=False) + + def test_cross_section(self): + self._check_soil_depth(_lbcode(ix=1, iy=2), expect_match=False) + + def test_cross_section__vector(self): + points = np.arange(10) + self._check_soil_depth(_lbcode(ix=1, iy=2), blev=points, + brsvd1=points - 1, brlev=points + 1, + expect_match=False, dim=0) + + +class TestLBVC008_Pressure(TestField): + def _check_pressure(self, lbcode, blev=250.3, expect_match=True, dim=None): + lbvc = 8 + stash = STASH(1, 1, 1) + lblev, bhlev, bhrlev, brsvd1, brsvd2, brlev = \ + None, None, None, None, None, None + coords_and_dims, factories = _convert_vertical_coords( + lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, + bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, + brlev=brlev, dim=dim) + if expect_match: + expect_result = [ + (DimCoord(blev, long_name='pressure', units='hPa'), dim)] + else: + expect_result = [] + self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) + self.assertEqual(factories, []) + + def test_normal(self): + self._check_pressure(_lbcode(0)) + + def test_normal__vector(self): + blev = [10, 100, 1000, 10000] + self._check_pressure(_lbcode(0), blev=blev, dim=2) + + def test_non_pressure_cross_section(self): + self._check_pressure(_lbcode(ix=10, iy=11)) + + def test_non_pressure_cross_section__vector(self): + blev = np.arange(10) + self._check_pressure(_lbcode(ix=10, iy=11), blev=blev, dim=0) + + def test_pressure_cross_section(self): + self._check_pressure(_lbcode(ix=10, iy=1), expect_match=False) + + def test_pressure_cross_section__vector(self): + blev = np.arange(10) + self._check_pressure(_lbcode(ix=10, iy=1), blev=blev, dim=1, + expect_match=False) + + +class TestLBVC019_PotentialTemperature(TestField): + def _check_potm(self, lbcode, blev=130.6, expect_match=True, dim=None): + lbvc = 19 + stash = STASH(1, 1, 1) + lblev, bhlev, bhrlev, brsvd1, brsvd2, brlev = \ + None, None, None, None, None, None + coords_and_dims, factories = _convert_vertical_coords( + lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, + bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, + brlev=brlev, dim=dim) + if expect_match: + expect_result = [ + (DimCoord(blev, standard_name='air_potential_temperature', + units='K', attributes={'positive': 'up'}), dim)] + else: + expect_result = [] + self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) + self.assertEqual(factories, []) + + def test_normal(self): + self._check_potm(_lbcode(0)) + + def test_normal__vector(self): + blev = list(range(10)) + self._check_potm(_lbcode(0), blev=blev, dim=0) + + def test_cross_section(self): + self._check_potm(_lbcode(ix=10, iy=11), expect_match=False) + + def test_cross_section__vector(self): + blev = np.arange(5) + 100 + self._check_potm(_lbcode(ix=10, iy=11), blev=blev, dim=1, + expect_match=False) + + +class TestLBVC009_HybridPressure(TestField): + def _check(self, lblev=37.0, + bhlev=850.1, bhrlev=810.0, brsvd2=875.0, + blev=0.15, brlev=0.11, brsvd1=0.19, + expect_match=True, dim=None): + lbvc = 9 + lbcode = _lbcode(0) # unused + stash = STASH(1, 1, 1) # unused + coords_and_dims, factories = _convert_vertical_coords( + lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, + bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, + brlev=brlev, dim=dim) + expect_coords_and_dims = [ + (DimCoord(lblev, + standard_name='model_level_number', + attributes={'positive': 'up'}), dim)] + + bhrlev = np.atleast_1d(bhrlev) + brsvd2 = np.atleast_1d(brsvd2) + expect_coords_and_dims.append( + (DimCoord(bhlev, + long_name='level_pressure', + units='Pa', + bounds=np.vstack((bhrlev, brsvd2)).T), dim)) + brlev = np.atleast_1d(brlev) + brsvd1 = np.atleast_1d(brsvd1) + expect_coords_and_dims.append( + (AuxCoord(blev, + long_name='sigma', + bounds=np.vstack((brlev, brsvd1)).T), dim)) + expect_factories = [(HybridPressureFactory, + [{'long_name': 'level_pressure'}, + {'long_name': 'sigma'}, + Reference('surface_air_pressure')])] + self.assertCoordsAndDimsListsMatch(coords_and_dims, + expect_coords_and_dims) + self.assertEqual(factories, expect_factories) + + def test_normal(self): + self._check() + + def test_normal__vector(self): + lblev = list(range(3)) + bhlev = [10, 20, 30] + bhrlev = [5, 15, 25] + brsvd2 = [15, 25, 35] + blev = [100, 200, 300] + brlev = [50, 150, 250] + brsvd1 = [150, 250, 350] + self._check(lblev=lblev, bhlev=bhlev, bhrlev=bhrlev, brsvd2=brsvd2, + blev=blev, brlev=brlev, brsvd1=brsvd1, dim=0) + + +class TestLBVC065_HybridHeight(TestField): + def _check(self, lblev=37.0, + blev=9596.3, brlev=9500.0, brsvd1=9800.0, + bhlev=0.35, bhrlev=0.31, brsvd2=0.39, + dim=None): + lbvc = 65 + lbcode = _lbcode(0) # unused + stash = STASH(1, 1, 1) # unused + coords_and_dims, factories = _convert_vertical_coords( + lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, + bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, + brlev=brlev, dim=dim) + expect_coords_and_dims = [ + (DimCoord(lblev, + standard_name='model_level_number', + attributes={'positive': 'up'}), dim)] + brlev = np.atleast_1d(brlev) + brsvd1 = np.atleast_1d(brsvd1) + expect_coords_and_dims.append( + (DimCoord(blev, + long_name='level_height', units='m', + bounds=np.vstack((brlev, brsvd1)).T, + attributes={'positive': 'up'}), dim)) + bhrlev = np.atleast_1d(bhrlev) + brsvd2 = np.atleast_1d(brsvd2) + expect_coords_and_dims.append( + (AuxCoord(bhlev, + long_name='sigma', + bounds=np.vstack((bhrlev, brsvd2)).T), dim)) + expect_factories = [(HybridHeightFactory, + [{'long_name': 'level_height'}, + {'long_name': 'sigma'}, + Reference('orography')])] + self.assertCoordsAndDimsListsMatch(coords_and_dims, + expect_coords_and_dims) + self.assertEqual(factories, expect_factories) + + def test_normal(self): + self._check() + + def test_normal__vector(self): + npts = 5 + lblev = np.arange(npts) + blev = np.arange(npts) + 10 + brlev = np.arange(npts) + 5 + brsvd1 = np.arange(npts) + 15 + bhlev = np.arange(npts) + 12 + bhrlev = np.arange(npts) + 6 + brsvd2 = np.arange(npts) + 18 + self._check(lblev=lblev, blev=blev, brlev=brlev, brsvd1=brsvd1, + bhlev=bhlev, bhrlev=bhrlev, brsvd2=brsvd2, dim=1) + + +class TestLBVCxxx_Unhandled(TestField): + def test_unknown_lbvc(self): + lbvc = 999 + blev, lblev, bhlev, bhrlev, brsvd1, brsvd2, brlev = \ + None, None, None, None, None, None, None + lbcode = _lbcode(0) # unused + stash = STASH(1, 1, 1) # unused + coords_and_dims, factories = _convert_vertical_coords( + lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, + bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, + brlev=brlev) + self.assertEqual(coords_and_dims, []) + self.assertEqual(factories, []) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp_load_rules/test__dim_or_aux.py b/lib/iris/tests/unit/fileformats/pp_load_rules/test__dim_or_aux.py new file mode 100644 index 0000000000..3eaa77026e --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pp_load_rules/test__dim_or_aux.py @@ -0,0 +1,57 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for :func:`iris.fileformats.pp_load_rules._dim_or_aux`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.coords import DimCoord, AuxCoord +from iris.fileformats.pp_load_rules import _dim_or_aux + + +class Test(tests.IrisTest): + def setUp(self): + self.mono = list(range(5)) + self.non_mono = [0, 1, 3, 2, 4] + self.std_name = 'depth' + self.units = 'm' + self.attr = {'positive': 'up', + 'wibble': 'wobble'} + + def test_dim_monotonic(self): + result = _dim_or_aux(self.mono, standard_name=self.std_name, + units=self.units, attributes=self.attr.copy()) + expected = DimCoord(self.mono, standard_name=self.std_name, + units=self.units, attributes=self.attr) + self.assertEqual(result, expected) + + def test_dim_non_monotonic(self): + result = _dim_or_aux(self.non_mono, standard_name=self.std_name, + units=self.units, attributes=self.attr.copy()) + attr = self.attr.copy() + del attr['positive'] + expected = AuxCoord(self.non_mono, standard_name=self.std_name, + units=self.units, attributes=attr) + self.assertEqual(result, expected) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp_load_rules/test__model_level_number.py b/lib/iris/tests/unit/fileformats/pp_load_rules/test__model_level_number.py new file mode 100644 index 0000000000..3970eff1df --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pp_load_rules/test__model_level_number.py @@ -0,0 +1,44 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for :func:`iris.fileformats.pp_load_rules._model_level_number`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.fileformats.pp_load_rules import _model_level_number + + +class Test_9999(tests.IrisTest): + def test(self): + self.assertEqual(_model_level_number(9999), 0) + + +class Test_lblev(tests.IrisTest): + def test(self): + for val in range(9999): + self.assertEqual(_model_level_number(val), val) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp_load_rules/test__reduced_points_and_bounds.py b/lib/iris/tests/unit/fileformats/pp_load_rules/test__reduced_points_and_bounds.py new file mode 100644 index 0000000000..85ce2f7217 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pp_load_rules/test__reduced_points_and_bounds.py @@ -0,0 +1,105 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for +:func:`iris.fileformats.pp_load_rules._reduce_points_and_bounds`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.fileformats.pp_load_rules import _reduce_points_and_bounds + + +class Test(tests.IrisTest): + def test_scalar(self): + array = np.array(1) + dims, result, bounds = _reduce_points_and_bounds(array) + self.assertArrayEqual(result, array) + self.assertEqual(dims, None) + self.assertIsNone(bounds) + + def test_1d_nochange(self): + array = np.array([1, 2, 3]) + dims, result, _ = _reduce_points_and_bounds(array) + self.assertArrayEqual(result, array) + self.assertEqual(dims, (0,)) + + def test_1d_collapse(self): + array = np.array([1, 1, 1]) + dims, result, _ = _reduce_points_and_bounds(array) + self.assertArrayEqual(result, np.array(1)) + self.assertEqual(dims, None) + + def test_2d_nochange(self): + array = np.array([[1, 2, 3], [4, 5, 6]]) + dims, result, _ = _reduce_points_and_bounds(array) + self.assertArrayEqual(result, array) + self.assertEqual(dims, (0, 1)) + + def test_2d_collapse_dim0(self): + array = np.array([[1, 2, 3], [1, 2, 3]]) + dims, result, _ = _reduce_points_and_bounds(array) + self.assertArrayEqual(result, np.array([1, 2, 3])) + self.assertEqual(dims, (1,)) + + def test_2d_collapse_dim1(self): + array = np.array([[1, 1, 1], [2, 2, 2]]) + dims, result, _ = _reduce_points_and_bounds(array) + self.assertArrayEqual(result, np.array([1, 2])) + self.assertEqual(dims, (0,)) + + def test_2d_collapse_both(self): + array = np.array([[3, 3, 3], [3, 3, 3]]) + dims, result, _ = _reduce_points_and_bounds(array) + self.assertArrayEqual(result, np.array(3)) + self.assertEqual(dims, None) + + def test_3d(self): + array = np.array([[[3, 3, 3], [4, 4, 4]], [[3, 3, 3], [4, 4, 4]]]) + dims, result, _ = _reduce_points_and_bounds(array) + self.assertArrayEqual(result, np.array([3, 4])) + self.assertEqual(dims, (1,)) + + def test_bounds_collapse(self): + points = np.array([1, 1, 1]) + bounds = np.array([[0, 2], [0, 2], [0, 2]]) + result_dims, result_pts, result_bds = \ + _reduce_points_and_bounds(points, (bounds[..., 0], bounds[..., 1])) + self.assertArrayEqual(result_pts, np.array(1)) + self.assertArrayEqual(result_bds, np.array([0, 2])) + self.assertEqual(result_dims, None) + + def test_bounds_no_collapse(self): + points = np.array([1, 2, 3]) + bounds = np.array([[0, 2], [1, 3], [2, 4]]) + result_dims, result_pts, result_bds = \ + _reduce_points_and_bounds(points, (bounds[..., 0], bounds[..., 1])) + self.assertArrayEqual(result_pts, points) + self.assertArrayEqual(result_bds, bounds) + self.assertEqual(result_dims, (0,)) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp_load_rules/test__reshape_vector_args.py b/lib/iris/tests/unit/fileformats/pp_load_rules/test__reshape_vector_args.py new file mode 100644 index 0000000000..35bbce376b --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pp_load_rules/test__reshape_vector_args.py @@ -0,0 +1,151 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for +:func:`iris.fileformats.pp_load_rules._reshape_vector_args`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.fileformats.pp_load_rules import _reshape_vector_args + + +class TestEmpty(tests.IrisTest): + def test(self): + result = _reshape_vector_args([]) + self.assertEqual(result, []) + + +class TestSingleArg(tests.IrisTest): + def _check(self, result, expected): + self.assertEqual(len(result), len(expected)) + for result_arr, expected_arr in zip(result, expected): + self.assertArrayEqual(result_arr, expected_arr) + + def test_nochange(self): + points = np.array([[1, 2, 3], [4, 5, 6]]) + result = _reshape_vector_args([(points, (0, 1))]) + expected = [points] + self._check(result, expected) + + def test_bad_dimensions(self): + points = np.array([[1, 2, 3], [4, 5, 6]]) + with self.assertRaisesRegexp(ValueError, 'Length'): + _reshape_vector_args([(points, (0, 1, 2))]) + + def test_scalar(self): + points = 5 + result = _reshape_vector_args([(points, ())]) + expected = [points] + self._check(result, expected) + + def test_nonarray(self): + points = [[1, 2, 3], [4, 5, 6]] + result = _reshape_vector_args([(points, (0, 1))]) + expected = [np.array(points)] + self._check(result, expected) + + def test_transpose(self): + points = np.array([[1, 2, 3], [4, 5, 6]]) + result = _reshape_vector_args([(points, (1, 0))]) + expected = [points.T] + self._check(result, expected) + + def test_extend(self): + points = np.array([[1, 2, 3, 4], [21, 22, 23, 24], [31, 32, 33, 34]]) + result = _reshape_vector_args([(points, (1, 3))]) + expected = [points.reshape(1, 3, 1, 4)] + self._check(result, expected) + + +class TestMultipleArgs(tests.IrisTest): + def _check(self, result, expected): + self.assertEqual(len(result), len(expected)) + for result_arr, expected_arr in zip(result, expected): + self.assertArrayEqual(result_arr, expected_arr) + + def test_nochange(self): + a1 = np.array([[1, 2, 3], [4, 5, 6]]) + a2 = np.array([[0, 2, 4], [7, 8, 9]]) + result = _reshape_vector_args([(a1, (0, 1)), (a2, (0, 1))]) + expected = [a1, a2] + self._check(result, expected) + + def test_array_and_scalar(self): + a1 = [[1, 2, 3], [3, 4, 5]] + a2 = 5 + result = _reshape_vector_args([(a1, (0, 1)), (a2, ())]) + expected = [a1, np.array([[5]])] + self._check(result, expected) + + def test_transpose(self): + a1 = np.array([[1, 2, 3], [4, 5, 6]]) + a2 = np.array([[0, 2, 4], [7, 8, 9]]) + result = _reshape_vector_args([(a1, (0, 1)), (a2, (1, 0))]) + expected = [a1, a2.T] + self._check(result, expected) + + def test_incompatible(self): + # Does not enforce compatibility of results. + a1 = np.array([1, 2]) + a2 = np.array([1, 2, 3]) + result = _reshape_vector_args([(a1, (0,)), (a2, (0,))]) + expected = [a1, a2] + self._check(result, expected) + + def test_extend(self): + a1 = np.array([[1, 2, 3], [4, 5, 6]]) + a2 = np.array([11, 12, 13]) + result = _reshape_vector_args([(a1, (0, 1)), (a2, (1,))]) + expected = [a1, a2.reshape(1, 3)] + self._check(result, expected) + + def test_extend_transpose(self): + a1 = np.array([[1, 2, 3], [4, 5, 6]]) + a2 = np.array([11, 12, 13]) + result = _reshape_vector_args([(a1, (1, 0)), (a2, (1,))]) + expected = [a1.T, a2.reshape(1, 3)] + self._check(result, expected) + + def test_double_extend(self): + a1 = np.array([[1, 2, 3], [4, 5, 6]]) + a2 = np.array(1) + result = _reshape_vector_args([(a1, (0, 2)), (a2, ())]) + expected = [a1.reshape(2, 1, 3), a2.reshape(1, 1, 1)] + self._check(result, expected) + + def test_triple(self): + a1 = np.array([[1, 2, 3, 4]]) + a2 = np.array([3, 4]) + a3 = np.array(7) + result = _reshape_vector_args([(a1, (0, 2)), (a2, (1,)), (a3, ())]) + expected = [a1.reshape(1, 1, 4), + a2.reshape(1, 2, 1), + a3.reshape(1, 1, 1)] + self._check(result, expected) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp_load_rules/test_convert.py b/lib/iris/tests/unit/fileformats/pp_load_rules/test_convert.py new file mode 100644 index 0000000000..c1f8bdb891 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pp_load_rules/test_convert.py @@ -0,0 +1,346 @@ +# (C) British Crown Copyright 2013 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for :func:`iris.fileformats.pp_load_rules.convert`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import types +import cftime + +import cf_units +import numpy as np + +from iris.fileformats.pp_load_rules import convert +from iris.util import guess_coord_axis +from iris.fileformats.pp import SplittableInt +from iris.fileformats.pp import STASH +from iris.fileformats.pp import PPField3 +from iris.tests import mock +import iris.tests.unit.fileformats + + +class TestLBCODE(iris.tests.unit.fileformats.TestField): + @staticmethod + def _is_cross_section_height_coord(coord): + return (coord.standard_name == 'height' and + coord.units == 'km' and + coord.attributes['positive'] == 'up') + + def test_cross_section_height_bdy_zero(self): + lbcode = SplittableInt(19902, {'iy': slice(0, 2), 'ix': slice(2, 4)}) + points = np.array([10, 20, 30, 40]) + bounds = np.array([[0, 15], [15, 25], [25, 35], [35, 45]]) + field = mock.MagicMock(lbcode=lbcode, bdy=0, y=points, y_bounds=bounds) + self._test_for_coord(field, convert, + TestLBCODE._is_cross_section_height_coord, + expected_points=points, + expected_bounds=bounds) + + def test_cross_section_height_bdy_bmdi(self): + lbcode = SplittableInt(19902, {'iy': slice(0, 2), 'ix': slice(2, 4)}) + points = np.array([10, 20, 30, 40]) + bounds = np.array([[0, 15], [15, 25], [25, 35], [35, 45]]) + bmdi = -1.07374e+09 + field = mock.MagicMock(lbcode=lbcode, bdy=bmdi, bmdi=bmdi, + y=points, y_bounds=bounds) + self._test_for_coord(field, convert, + TestLBCODE._is_cross_section_height_coord, + expected_points=points, + expected_bounds=bounds) + + +class TestLBVC(iris.tests.unit.fileformats.TestField): + @staticmethod + def _is_potm_level_coord(coord): + return (coord.standard_name == 'air_potential_temperature' and + coord.attributes['positive'] == 'up') + + @staticmethod + def _is_model_level_number_coord(coord): + return (coord.standard_name == 'model_level_number' and + coord.units.is_dimensionless() and + coord.attributes['positive'] == 'up') + + @staticmethod + def _is_level_pressure_coord(coord): + return (coord.name() == 'level_pressure' and + coord.units == 'Pa') + + @staticmethod + def _is_sigma_coord(coord): + return (coord.name() == 'sigma' and + coord.units.is_dimensionless()) + + @staticmethod + def _is_soil_model_level_number_coord(coord): + return (coord.long_name == 'soil_model_level_number' and + coord.units.is_dimensionless() and + coord.attributes['positive'] == 'down') + + @staticmethod + def _is_soil_depth_coord(coord): + return (coord.standard_name == 'depth' and + coord.units == 'm' and + coord.attributes['positive'] == 'down') + + def test_soil_levels(self): + level = 1234 + field = mock.MagicMock(lbvc=6, lblev=level, brsvd=[0, 0], brlev=0) + self._test_for_coord(field, convert, + self._is_soil_model_level_number_coord, + expected_points=[level], + expected_bounds=None) + + def test_soil_depth(self): + lower, point, upper = 1.2, 3.4, 5.6 + field = mock.MagicMock(lbvc=6, blev=point, brsvd=[lower, 0], + brlev=upper) + self._test_for_coord(field, convert, + self._is_soil_depth_coord, + expected_points=[point], + expected_bounds=[[lower, upper]]) + + def test_hybrid_pressure_model_level_number(self): + level = 5678 + field = mock.MagicMock(lbvc=9, lblev=level, + blev=20, brlev=23, bhlev=42, + bhrlev=45, brsvd=[17, 40]) + self._test_for_coord(field, convert, + TestLBVC._is_model_level_number_coord, + expected_points=[level], + expected_bounds=None) + + def test_hybrid_pressure_delta(self): + delta_point = 12.0 + delta_lower_bound = 11.0 + delta_upper_bound = 13.0 + field = mock.MagicMock(lbvc=9, lblev=5678, + blev=20, brlev=23, bhlev=delta_point, + bhrlev=delta_lower_bound, + brsvd=[17, delta_upper_bound]) + self._test_for_coord(field, convert, + TestLBVC._is_level_pressure_coord, + expected_points=[delta_point], + expected_bounds=[[delta_lower_bound, + delta_upper_bound]]) + + def test_hybrid_pressure_sigma(self): + sigma_point = 0.5 + sigma_lower_bound = 0.6 + sigma_upper_bound = 0.4 + field = mock.MagicMock(lbvc=9, lblev=5678, + blev=sigma_point, brlev=sigma_lower_bound, + bhlev=12, bhrlev=11, + brsvd=[sigma_upper_bound, 13]) + self._test_for_coord(field, convert, TestLBVC._is_sigma_coord, + expected_points=[sigma_point], + expected_bounds=[[sigma_lower_bound, + sigma_upper_bound]]) + + def test_potential_temperature_levels(self): + potm_value = 27.32 + field = mock.MagicMock(lbvc=19, blev=potm_value) + self._test_for_coord(field, convert, TestLBVC._is_potm_level_coord, + expected_points=np.array([potm_value]), + expected_bounds=None) + + +class TestLBTIM(iris.tests.unit.fileformats.TestField): + def test_365_calendar(self): + f = mock.MagicMock(lbtim=SplittableInt(4, {'ia': 2, 'ib': 1, 'ic': 0}), + lbyr=2013, lbmon=1, lbdat=1, lbhr=12, lbmin=0, + lbsec=0, + t1=cftime.datetime(2013, 1, 1, 12, 0, 0), + t2=cftime.datetime(2013, 1, 2, 12, 0, 0), + spec=PPField3) + f.time_unit = six.create_bound_method(PPField3.time_unit, f) + f.calendar = cf_units.CALENDAR_365_DAY + (factories, references, standard_name, long_name, units, + attributes, cell_methods, dim_coords_and_dims, + aux_coords_and_dims) = convert(f) + + def is_t_coord(coord_and_dims): + coord, dims = coord_and_dims + return coord.standard_name == 'time' + + coords_and_dims = list(filter(is_t_coord, aux_coords_and_dims)) + self.assertEqual(len(coords_and_dims), 1) + coord, dims = coords_and_dims[0] + self.assertEqual(guess_coord_axis(coord), 'T') + self.assertEqual(coord.units.calendar, '365_day') + + def base_field(self): + field = PPField3(header=mock.MagicMock()) + field.lbfc = 0 + field.bdx = 1 + field.bdy = 1 + field.bmdi = 999 + field.lbproc = 0 + field.lbvc = 0 + field.lbuser = [0] * 7 + field.lbrsvd = [0] * 4 + field.brsvd = [0] * 4 + field.lbsrce = 0 + field.lbcode = 0 + return field + + @staticmethod + def is_forecast_period(coord): + return (coord.standard_name == 'forecast_period' and + coord.units == 'hours') + + @staticmethod + def is_time(coord): + return (coord.standard_name == 'time' and + coord.units == 'hours since epoch') + + def test_time_mean_ib2(self): + field = self.base_field() + field.lbtim = 21 + # Implicit reference time: 1970-01-02 06:00 + field.lbft = 9 + # t1 + field.lbyr, field.lbmon, field.lbdat = 1970, 1, 2 + field.lbhr, field.lbmin, field.lbsec = 12, 0, 0 + # t2 + field.lbyrd, field.lbmond, field.lbdatd = 1970, 1, 2 + field.lbhrd, field.lbmind, field.lbsecd = 15, 0, 0 + + self._test_for_coord(field, convert, self.is_forecast_period, + expected_points=[7.5], + expected_bounds=[[6, 9]]) + + self._test_for_coord(field, convert, self.is_time, + expected_points=[24 + 13.5], + expected_bounds=[[36, 39]]) + + def test_time_mean_ib3(self): + field = self.base_field() + field.lbtim = 31 + # Implicit reference time: 1970-01-02 06:00 + field.lbft = lbft = ((365 + 1) * 24 + 15) - (24 + 6) + # t1 + field.lbyr, field.lbmon, field.lbdat = 1970, 1, 2 + field.lbhr, field.lbmin, field.lbsec = 12, 0, 0 + # t2 + field.lbyrd, field.lbmond, field.lbdatd = 1971, 1, 2 + field.lbhrd, field.lbmind, field.lbsecd = 15, 0, 0 + + self._test_for_coord(field, convert, self.is_forecast_period, + expected_points=[lbft], + expected_bounds=[[36 - 30, lbft]]) + + self._test_for_coord(field, convert, self.is_time, + expected_points=[lbft + 30], + expected_bounds=[[36, lbft + 30]]) + + +class TestLBRSVD(iris.tests.unit.fileformats.TestField): + @staticmethod + def _is_realization(coord): + return (coord.standard_name == 'realization' and coord.units == '1') + + def test_realization(self): + lbrsvd = [0] * 4 + lbrsvd[3] = 71 + points = np.array([71]) + bounds = None + field = mock.MagicMock(lbrsvd=lbrsvd) + self._test_for_coord(field, convert, + TestLBRSVD._is_realization, + expected_points=points, + expected_bounds=bounds) + + +class TestLBSRCE(iris.tests.IrisTest): + def check_um_source_attrs(self, lbsrce, + source_str=None, um_version_str=None): + field = mock.MagicMock(lbsrce=lbsrce) + (factories, references, standard_name, long_name, units, + attributes, cell_methods, dim_coords_and_dims, + aux_coords_and_dims) = convert(field) + if source_str is not None: + self.assertEqual(attributes['source'], source_str) + else: + self.assertNotIn('source', attributes) + if um_version_str is not None: + self.assertEqual(attributes['um_version'], um_version_str) + else: + self.assertNotIn('um_version', attributes) + + def test_none(self): + self.check_um_source_attrs(lbsrce=8123, + source_str=None, um_version_str=None) + + def test_no_um_version(self): + self.check_um_source_attrs( + lbsrce=1111, + source_str='Data from Met Office Unified Model', + um_version_str=None) + + def test_um_version(self): + self.check_um_source_attrs( + lbsrce=12071111, + source_str='Data from Met Office Unified Model', + um_version_str='12.7') + + +class Test_STASH_CF(iris.tests.unit.fileformats.TestField): + def test_stash_cf_air_temp(self): + lbuser = [1, 0, 0, 16203, 0, 0, 1] + lbfc = 16 + stash = STASH(lbuser[6], lbuser[3] // 1000, lbuser[3] % 1000) + field = mock.MagicMock(lbuser=lbuser, lbfc=lbfc, stash=stash) + (factories, references, standard_name, long_name, units, + attributes, cell_methods, dim_coords_and_dims, + aux_coords_and_dims) = convert(field) + self.assertEqual(standard_name, 'air_temperature') + self.assertEqual(units, 'K') + + def test_no_std_name(self): + lbuser = [1, 0, 0, 0, 0, 0, 0] + lbfc = 0 + stash = STASH(lbuser[6], lbuser[3] // 1000, lbuser[3] % 1000) + field = mock.MagicMock(lbuser=lbuser, lbfc=lbfc, stash=stash) + (factories, references, standard_name, long_name, units, + attributes, cell_methods, dim_coords_and_dims, + aux_coords_and_dims) = convert(field) + self.assertIsNone(standard_name) + self.assertIsNone(units) + + +class Test_LBFC_CF(iris.tests.unit.fileformats.TestField): + def test_fc_cf_air_temp(self): + lbuser = [1, 0, 0, 0, 0, 0, 0] + lbfc = 16 + stash = STASH(lbuser[6], lbuser[3] // 1000, lbuser[3] % 1000) + field = mock.MagicMock(lbuser=lbuser, lbfc=lbfc, stash=stash) + (factories, references, standard_name, long_name, units, + attributes, cell_methods, dim_coords_and_dims, + aux_coords_and_dims) = convert(field) + self.assertEqual(standard_name, 'air_temperature') + self.assertEqual(units, 'K') + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp_rules/test_convert.py b/lib/iris/tests/unit/fileformats/pp_rules/test_convert.py deleted file mode 100644 index 9ea3f789b2..0000000000 --- a/lib/iris/tests/unit/fileformats/pp_rules/test_convert.py +++ /dev/null @@ -1,157 +0,0 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -"""Unit tests for :func:`iris.fileformats.pp_rules.convert`.""" - -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -import mock -import types - -import numpy as np - -from iris.fileformats.pp_rules import convert -from iris.util import guess_coord_axis -from iris.fileformats.pp import SplittableInt -from iris.fileformats.pp import PPField3 -import iris.unit - - -class TestLBVC(tests.IrisTest): - @staticmethod - def _is_potm_level_coord(coord): - return (coord.standard_name == 'air_potential_temperature' and - coord.attributes['positive'] == 'up') - - @staticmethod - def _is_model_level_number_coord(coord): - return (coord.standard_name == 'model_level_number' and - coord.units.is_dimensionless() and - coord.attributes['positive'] == 'up') - - @staticmethod - def _is_level_pressure_coord(coord): - return (coord.name() == 'level_pressure' and - coord.units == 'Pa') - - @staticmethod - def _is_sigma_coord(coord): - return (coord.name() == 'sigma' and - coord.units.is_dimensionless()) - - @staticmethod - def _is_soil_model_level_number_coord(coord): - return (coord.long_name == 'soil_model_level_number' and - coord.units.is_dimensionless() and - coord.attributes['positive'] == 'down') - - def _test_for_coord(self, field, coord_predicate, expected_points, - expected_bounds): - (factories, references, standard_name, long_name, units, - attributes, cell_methods, dim_coords_and_dims, - aux_coords_and_dims) = convert(field) - - # Check for one and only one matching coordinate. - matching_coords = [coord for coord, _ in aux_coords_and_dims if - coord_predicate(coord)] - self.assertEqual(len(matching_coords), 1) - coord = matching_coords[0] - - # Check points and bounds. - if expected_points is not None: - self.assertArrayEqual(coord.points, expected_points) - - if expected_bounds is None: - self.assertIsNone(coord.bounds) - else: - self.assertArrayEqual(coord.bounds, expected_bounds) - - def test_soil_levels(self): - level = 1234 - field = mock.MagicMock(lbvc=6, lblev=level) - self._test_for_coord(field, TestLBVC._is_soil_model_level_number_coord, - expected_points=np.array([level]), - expected_bounds=None) - - def test_hybrid_pressure_model_level_number(self): - level = 5678 - field = mock.MagicMock(lbvc=9, lblev=level, - blev=20, brlev=23, bhlev=42, - bhrlev=45, brsvd=[17, 40]) - self._test_for_coord(field, TestLBVC._is_model_level_number_coord, - expected_points=np.array([level]), - expected_bounds=None) - - def test_hybrid_pressure_delta(self): - delta_point = 12.0 - delta_lower_bound = 11.0 - delta_upper_bound = 13.0 - field = mock.MagicMock(lbvc=9, lblev=5678, - blev=20, brlev=23, bhlev=delta_point, - bhrlev=delta_lower_bound, - brsvd=[17, delta_upper_bound]) - self._test_for_coord(field, TestLBVC._is_level_pressure_coord, - expected_points=np.array([delta_point]), - expected_bounds=np.array([[delta_lower_bound, - delta_upper_bound]])) - - def test_hybrid_pressure_sigma(self): - sigma_point = 0.5 - sigma_lower_bound = 0.6 - sigma_upper_bound = 0.4 - field = mock.MagicMock(lbvc=9, lblev=5678, - blev=sigma_point, brlev=sigma_lower_bound, - bhlev=12, bhrlev=11, - brsvd=[sigma_upper_bound, 13]) - self._test_for_coord(field, TestLBVC._is_sigma_coord, - expected_points=np.array([sigma_point]), - expected_bounds=np.array([[sigma_lower_bound, - sigma_upper_bound]])) - - def test_potential_temperature_levels(self): - potm_value = 27.32 - field = mock.MagicMock(lbvc=19, blev=potm_value) - self._test_for_coord(field, TestLBVC._is_potm_level_coord, - expected_points=np.array([potm_value]), - expected_bounds=None) - - -class TestLBTIM(tests.IrisTest): - def test_365_calendar(self): - f = mock.MagicMock(lbtim=SplittableInt(4, {'ia': 2, 'ib': 1, 'ic': 0}), - lbyr=2013, lbmon=1, lbdat=1, lbhr=12, lbmin=0, - lbsec=0, - spec=PPField3) - f.time_unit = types.MethodType(PPField3.time_unit, f) - f.calendar = iris.unit.CALENDAR_365_DAY - (factories, references, standard_name, long_name, units, - attributes, cell_methods, dim_coords_and_dims, - aux_coords_and_dims) = convert(f) - - def is_t_coord(coord_and_dims): - coord, dims = coord_and_dims - return coord.standard_name == 'time' - - coords_and_dims = filter(is_t_coord, aux_coords_and_dims) - self.assertEqual(len(coords_and_dims), 1) - coord, dims = coords_and_dims[0] - self.assertEqual(guess_coord_axis(coord), 'T') - self.assertEqual(coord.units.calendar, '365_day') - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/fileformats/pyke_rules/__init__.py b/lib/iris/tests/unit/fileformats/pyke_rules/__init__.py new file mode 100644 index 0000000000..d2c5491557 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pyke_rules/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.fileformats._pyke_rules` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/__init__.py b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/__init__.py new file mode 100644 index 0000000000..41e23dca1c --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/__init__.py @@ -0,0 +1,23 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the :mod:`iris.fileformats._pyke_rules.compiled_krb` module. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/__init__.py b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/__init__.py new file mode 100644 index 0000000000..34e18a1b25 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.fileformats.fc_rules_cf_fc` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_auxiliary_coordinate.py b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_auxiliary_coordinate.py new file mode 100644 index 0000000000..4bb653f23f --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_auxiliary_coordinate.py @@ -0,0 +1,269 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test function :func:`iris.fileformats._pyke_rules.compiled_krb.\ +fc_rules_cf_fc.build_auxilliary_coordinate`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import numpy as np + +from iris.coords import AuxCoord +from iris.fileformats.cf import CFVariable +from iris.fileformats._pyke_rules.compiled_krb.fc_rules_cf_fc import \ + build_auxiliary_coordinate +from iris.tests import mock + + +class TestBoundsVertexDim(tests.IrisTest): + def setUp(self): + # Create coordinate cf variables and pyke engine. + points = np.arange(6).reshape(2, 3) + + cf_data = self._make_cf_data(points) + self.cf_coord_var = mock.Mock( + spec=CFVariable, + dimensions=('foo', 'bar'), + cf_name='wibble', + cf_data=cf_data, + standard_name=None, + long_name='wibble', + units='m', + shape=points.shape, + dtype=points.dtype, + __getitem__=lambda self, key: points[key]) + + self.engine = mock.Mock( + cube=mock.Mock(), + cf_var=mock.Mock(dimensions=('foo', 'bar'), + cf_data=cf_data), + filename='DUMMY', + provides=dict(coordinates=[])) + + # Create patch for deferred loading that prevents attempted + # file access. This assumes that self.cf_bounds_var is + # defined in the test case. + def patched__getitem__(proxy_self, keys): + variable = None + for var in (self.cf_coord_var, self.cf_bounds_var): + if proxy_self.variable_name == var.cf_name: + return var[keys] + raise RuntimeError() + + self.deferred_load_patch = mock.patch( + 'iris.fileformats.netcdf.NetCDFDataProxy.__getitem__', + new=patched__getitem__) + + @staticmethod + def _make_cf_data(vals): + cf_data = mock.Mock(_FillValue=None) + cf_data.chunking = mock.MagicMock(return_value=vals.shape) + return cf_data + + def test_slowest_varying_vertex_dim(self): + # Create the bounds cf variable. + bounds = np.arange(24).reshape(4, 2, 3) + cf_data = self._make_cf_data(bounds) + self.cf_bounds_var = mock.Mock( + spec=CFVariable, + dimensions=('nv', 'foo', 'bar'), + cf_name='wibble_bnds', + cf_data=cf_data, + shape=bounds.shape, + dtype=bounds.dtype, + __getitem__=lambda self, key: bounds[key]) + + # Expected bounds on the resulting coordinate should be rolled so that + # the vertex dimension is at the end. + expected_bounds = np.rollaxis(bounds, 0, bounds.ndim) + expected_coord = AuxCoord( + self.cf_coord_var[:], + long_name=self.cf_coord_var.long_name, + var_name=self.cf_coord_var.cf_name, + units=self.cf_coord_var.units, + bounds=expected_bounds) + + # Patch the helper function that retrieves the bounds cf variable. + # This avoids the need for setting up further mocking of cf objects. + get_cf_bounds_var_patch = mock.patch( + 'iris.fileformats._pyke_rules.compiled_krb.' + 'fc_rules_cf_fc.get_cf_bounds_var', + return_value=self.cf_bounds_var) + + # Asserts must lie within context manager because of deferred loading. + with self.deferred_load_patch, get_cf_bounds_var_patch: + build_auxiliary_coordinate(self.engine, self.cf_coord_var) + + # Test that expected coord is built and added to cube. + self.engine.cube.add_aux_coord.assert_called_with( + expected_coord, [0, 1]) + + # Test that engine.provides container is correctly populated. + expected_list = [(expected_coord, self.cf_coord_var.cf_name)] + self.assertEqual(self.engine.provides['coordinates'], + expected_list) + + def test_fastest_varying_vertex_dim(self): + bounds = np.arange(24).reshape(2, 3, 4) + cf_data = self._make_cf_data(bounds) + self.cf_bounds_var = mock.Mock( + spec=CFVariable, + dimensions=('foo', 'bar', 'nv'), + cf_name='wibble_bnds', + cf_data=cf_data, + shape=bounds.shape, + dtype=bounds.dtype, + __getitem__=lambda self, key: bounds[key]) + + expected_coord = AuxCoord( + self.cf_coord_var[:], + long_name=self.cf_coord_var.long_name, + var_name=self.cf_coord_var.cf_name, + units=self.cf_coord_var.units, + bounds=bounds) + + get_cf_bounds_var_patch = mock.patch( + 'iris.fileformats._pyke_rules.compiled_krb.' + 'fc_rules_cf_fc.get_cf_bounds_var', + return_value=self.cf_bounds_var) + + # Asserts must lie within context manager because of deferred loading. + with self.deferred_load_patch, get_cf_bounds_var_patch: + build_auxiliary_coordinate(self.engine, self.cf_coord_var) + + # Test that expected coord is built and added to cube. + self.engine.cube.add_aux_coord.assert_called_with( + expected_coord, [0, 1]) + + # Test that engine.provides container is correctly populated. + expected_list = [(expected_coord, self.cf_coord_var.cf_name)] + self.assertEqual(self.engine.provides['coordinates'], + expected_list) + + def test_fastest_with_different_dim_names(self): + # Despite the dimension names ('x', and 'y') differing from the coord's + # which are 'foo' and 'bar' (as permitted by the cf spec), + # this should still work because the vertex dim is the fastest varying. + bounds = np.arange(24).reshape(2, 3, 4) + cf_data = self._make_cf_data(bounds) + self.cf_bounds_var = mock.Mock( + spec=CFVariable, + dimensions=('x', 'y', 'nv'), + cf_name='wibble_bnds', + cf_data=cf_data, + shape=bounds.shape, + dtype=bounds.dtype, + __getitem__=lambda self, key: bounds[key]) + + expected_coord = AuxCoord( + self.cf_coord_var[:], + long_name=self.cf_coord_var.long_name, + var_name=self.cf_coord_var.cf_name, + units=self.cf_coord_var.units, + bounds=bounds) + + get_cf_bounds_var_patch = mock.patch( + 'iris.fileformats._pyke_rules.compiled_krb.' + 'fc_rules_cf_fc.get_cf_bounds_var', + return_value=self.cf_bounds_var) + + # Asserts must lie within context manager because of deferred loading. + with self.deferred_load_patch, get_cf_bounds_var_patch: + build_auxiliary_coordinate(self.engine, self.cf_coord_var) + + # Test that expected coord is built and added to cube. + self.engine.cube.add_aux_coord.assert_called_with( + expected_coord, [0, 1]) + + # Test that engine.provides container is correctly populated. + expected_list = [(expected_coord, self.cf_coord_var.cf_name)] + self.assertEqual(self.engine.provides['coordinates'], + expected_list) + + +class TestDtype(tests.IrisTest): + def setUp(self): + # Create coordinate cf variables and pyke engine. + points = np.arange(6).reshape(2, 3) + cf_data = mock.Mock(_FillValue=None) + cf_data.chunking = mock.MagicMock(return_value=points.shape) + + self.cf_coord_var = mock.Mock( + spec=CFVariable, + dimensions=('foo', 'bar'), + cf_name='wibble', + cf_data=cf_data, + standard_name=None, + long_name='wibble', + units='m', + shape=points.shape, + dtype=points.dtype, + __getitem__=lambda self, key: points[key]) + + self.engine = mock.Mock( + cube=mock.Mock(), + cf_var=mock.Mock(dimensions=('foo', 'bar')), + filename='DUMMY', + provides=dict(coordinates=[])) + + def patched__getitem__(proxy_self, keys): + if proxy_self.variable_name == self.cf_coord_var.cf_name: + return self.cf_coord_var[keys] + raise RuntimeError() + + self.deferred_load_patch = mock.patch( + 'iris.fileformats.netcdf.NetCDFDataProxy.__getitem__', + new=patched__getitem__) + + def test_scale_factor_add_offset_int(self): + self.cf_coord_var.scale_factor = 3 + self.cf_coord_var.add_offset = 5 + + with self.deferred_load_patch: + build_auxiliary_coordinate(self.engine, self.cf_coord_var) + + coord, _ = self.engine.provides['coordinates'][0] + self.assertEqual(coord.dtype.kind, 'i') + + def test_scale_factor_float(self): + self.cf_coord_var.scale_factor = 3. + + with self.deferred_load_patch: + build_auxiliary_coordinate(self.engine, self.cf_coord_var) + + coord, _ = self.engine.provides['coordinates'][0] + self.assertEqual(coord.dtype.kind, 'f') + + def test_add_offset_float(self): + self.cf_coord_var.add_offset = 5. + + with self.deferred_load_patch: + build_auxiliary_coordinate(self.engine, self.cf_coord_var) + + coord, _ = self.engine.provides['coordinates'][0] + self.assertEqual(coord.dtype.kind, 'f') + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_cube_metadata.py b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_cube_metadata.py new file mode 100644 index 0000000000..5c2892cea7 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_cube_metadata.py @@ -0,0 +1,88 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test function :func:`iris.fileformats._pyke_rules.compiled_krb.\ +fc_rules_cf_fc.build_cube_metadata`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import numpy as np + +from iris.cube import Cube +from iris.fileformats._pyke_rules.compiled_krb.fc_rules_cf_fc import \ + build_cube_metadata +from iris.tests import mock + + +class TestInvalidGlobalAttributes(tests.IrisTest): + @staticmethod + def _make_engine(global_attributes=None): + if global_attributes is None: + global_attributes = {} + + cf_group = mock.Mock(global_attributes=global_attributes) + + cf_var = mock.Mock( + cf_name='wibble', + standard_name=None, + long_name=None, + units='m', + dtype=np.float64, + cell_methods=None, + cf_group=cf_group) + + engine = mock.Mock( + cube=Cube([23]), + cf_var=cf_var) + + return engine + + def test_valid(self): + global_attributes = {'Conventions': 'CF-1.5', + 'comment': 'Mocked test object'} + engine = self._make_engine(global_attributes) + build_cube_metadata(engine) + expected = global_attributes + self.assertEqual(engine.cube.attributes, expected) + + def test_invalid(self): + global_attributes = {'Conventions': 'CF-1.5', + 'comment': 'Mocked test object', + 'calendar': 'standard'} + engine = self._make_engine(global_attributes) + with mock.patch('warnings.warn') as warn: + build_cube_metadata(engine) + # Check for a warning. + self.assertEqual(warn.call_count, 1) + self.assertIn("Skipping global attribute 'calendar'", + warn.call_args[0][0]) + # Check resulting attributes. The invalid entry 'calendar' + # should be filtered out. + global_attributes.pop('calendar') + expected = global_attributes + self.assertEqual(engine.cube.attributes, expected) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_dimension_coordinate.py b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_dimension_coordinate.py new file mode 100644 index 0000000000..38239ea9a0 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_dimension_coordinate.py @@ -0,0 +1,484 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test function :func:`iris.fileformats._pyke_rules.compiled_krb.\ +fc_rules_cf_fc.build_dimension_coordinate`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import warnings + +import numpy as np + +from iris.coords import AuxCoord, DimCoord +from iris.fileformats._pyke_rules.compiled_krb.fc_rules_cf_fc import \ + build_dimension_coordinate +from iris.tests import mock + + +class RulesTestMixin(object): + def setUp(self): + # Create dummy pyke engine. + self.engine = mock.Mock( + cube=mock.Mock(), + cf_var=mock.Mock(dimensions=('foo', 'bar')), + filename='DUMMY', + provides=dict(coordinates=[])) + + # Create patch for deferred loading that prevents attempted + # file access. This assumes that self.cf_coord_var and + # self.cf_bounds_var are defined in the test case. + def patched__getitem__(proxy_self, keys): + for var in (self.cf_coord_var, self.cf_bounds_var): + if proxy_self.variable_name == var.cf_name: + return var[keys] + raise RuntimeError() + + self.deferred_load_patch = mock.patch( + 'iris.fileformats.netcdf.NetCDFDataProxy.__getitem__', + new=patched__getitem__) + + # Patch the helper function that retrieves the bounds cf variable. + # This avoids the need for setting up further mocking of cf objects. + def get_cf_bounds_var(coord_var): + return self.cf_bounds_var + + self.get_cf_bounds_var_patch = mock.patch( + 'iris.fileformats._pyke_rules.compiled_krb.' + 'fc_rules_cf_fc.get_cf_bounds_var', + new=get_cf_bounds_var) + + +class TestCoordConstruction(tests.IrisTest, RulesTestMixin): + def setUp(self): + # Call parent setUp explicitly, because of how unittests work. + RulesTestMixin.setUp(self) + + bounds = np.arange(12).reshape(6, 2) + self.cf_bounds_var = mock.Mock( + dimensions=('x', 'nv'), + cf_name='wibble_bnds', + shape=bounds.shape, + __getitem__=lambda self, key: bounds[key]) + self.bounds = bounds + + def _set_cf_coord_var(self, points): + self.cf_coord_var = mock.Mock( + dimensions=('foo',), + cf_name='wibble', + standard_name=None, + long_name='wibble', + units='m', + shape=points.shape, + dtype=points.dtype, + __getitem__=lambda self, key: points[key]) + + def test_dim_coord_construction(self): + self._set_cf_coord_var(np.arange(6)) + + expected_coord = DimCoord( + self.cf_coord_var[:], + long_name=self.cf_coord_var.long_name, + var_name=self.cf_coord_var.cf_name, + units=self.cf_coord_var.units, + bounds=self.bounds) + + # Asserts must lie within context manager because of deferred loading. + with self.deferred_load_patch, self.get_cf_bounds_var_patch: + build_dimension_coordinate(self.engine, self.cf_coord_var) + + # Test that expected coord is built and added to cube. + self.engine.cube.add_dim_coord.assert_called_with( + expected_coord, [0]) + + def test_dim_coord_construction_masked_array(self): + self._set_cf_coord_var(np.ma.array( + np.arange(6), + mask=[True, False, False, False, False, False], + fill_value=-999, + )) + + expected_coord = DimCoord( + np.array([-999, 1, 2, 3, 4, 5]), + long_name=self.cf_coord_var.long_name, + var_name=self.cf_coord_var.cf_name, + units=self.cf_coord_var.units, + bounds=self.bounds) + + with warnings.catch_warnings(record=True) as w: + # Asserts must lie within context manager because of deferred + # loading. + with self.deferred_load_patch, self.get_cf_bounds_var_patch: + build_dimension_coordinate(self.engine, self.cf_coord_var) + + # Test that expected coord is built and added to cube. + self.engine.cube.add_dim_coord.assert_called_with( + expected_coord, [0]) + + # Assert warning is raised + assert len(w) == 1 + assert 'Gracefully filling' in w[0].message.args[0] + + def test_dim_coord_construction_masked_array_mask_does_nothing(self): + self._set_cf_coord_var(np.ma.array( + np.arange(6), + mask=False, + )) + + expected_coord = DimCoord( + self.cf_coord_var[:], + long_name=self.cf_coord_var.long_name, + var_name=self.cf_coord_var.cf_name, + units=self.cf_coord_var.units, + bounds=self.bounds) + + with warnings.catch_warnings(record=True) as w: + # Asserts must lie within context manager because of deferred + # loading. + with self.deferred_load_patch, self.get_cf_bounds_var_patch: + build_dimension_coordinate(self.engine, self.cf_coord_var) + + # Test that expected coord is built and added to cube. + self.engine.cube.add_dim_coord.assert_called_with( + expected_coord, [0]) + + # Assert no warning is raised + assert len(w) == 0 + + def test_dim_coord_construction_masked_bounds_mask_does_nothing(self): + self.bounds = np.ma.array(np.arange(12).reshape(6, 2), mask=False) + self._set_cf_coord_var(np.arange(6)) + + expected_coord = DimCoord( + self.cf_coord_var[:], + long_name=self.cf_coord_var.long_name, + var_name=self.cf_coord_var.cf_name, + units=self.cf_coord_var.units, + bounds=self.bounds) + + with warnings.catch_warnings(record=True) as w: + # Asserts must lie within context manager because of deferred + # loading. + with self.deferred_load_patch, self.get_cf_bounds_var_patch: + build_dimension_coordinate(self.engine, self.cf_coord_var) + + # Test that expected coord is built and added to cube. + self.engine.cube.add_dim_coord.assert_called_with( + expected_coord, [0]) + + # Assert no warning is raised + assert len(w) == 0 + + def test_aux_coord_construction(self): + # Use non monotonically increasing coordinates to force aux coord + # construction. + self._set_cf_coord_var(np.array([1, 3, 2, 4, 6, 5])) + + expected_coord = AuxCoord( + self.cf_coord_var[:], + long_name=self.cf_coord_var.long_name, + var_name=self.cf_coord_var.cf_name, + units=self.cf_coord_var.units, + bounds=self.bounds) + + warning_patch = mock.patch('warnings.warn') + + # Asserts must lie within context manager because of deferred loading. + with warning_patch, self.deferred_load_patch, \ + self.get_cf_bounds_var_patch: + build_dimension_coordinate(self.engine, self.cf_coord_var) + + # Test that expected coord is built and added to cube. + self.engine.cube.add_aux_coord.assert_called_with( + expected_coord, [0]) + self.assertIn("creating 'wibble' auxiliary coordinate instead", + warnings.warn.call_args[0][0]) + + +class TestBoundsVertexDim(tests.IrisTest, RulesTestMixin): + def setUp(self): + # Call parent setUp explicitly, because of how unittests work. + RulesTestMixin.setUp(self) + # Create test coordinate cf variable. + points = np.arange(6) + self.cf_coord_var = mock.Mock( + dimensions=('foo',), + cf_name='wibble', + standard_name=None, + long_name='wibble', + units='m', + shape=points.shape, + dtype=points.dtype, + __getitem__=lambda self, key: points[key]) + + def test_slowest_varying_vertex_dim(self): + # Create the bounds cf variable. + bounds = np.arange(12).reshape(2, 6) + self.cf_bounds_var = mock.Mock( + dimensions=('nv', 'foo'), + cf_name='wibble_bnds', + shape=bounds.shape, + __getitem__=lambda self, key: bounds[key]) + + # Expected bounds on the resulting coordinate should be rolled so that + # the vertex dimension is at the end. + expected_bounds = bounds.transpose() + expected_coord = DimCoord( + self.cf_coord_var[:], + long_name=self.cf_coord_var.long_name, + var_name=self.cf_coord_var.cf_name, + units=self.cf_coord_var.units, + bounds=expected_bounds) + + # Asserts must lie within context manager because of deferred loading. + with self.deferred_load_patch, self.get_cf_bounds_var_patch: + build_dimension_coordinate(self.engine, self.cf_coord_var) + + # Test that expected coord is built and added to cube. + self.engine.cube.add_dim_coord.assert_called_with( + expected_coord, [0]) + + # Test that engine.provides container is correctly populated. + expected_list = [(expected_coord, self.cf_coord_var.cf_name)] + self.assertEqual(self.engine.provides['coordinates'], + expected_list) + + def test_fastest_varying_vertex_dim(self): + bounds = np.arange(12).reshape(6, 2) + self.cf_bounds_var = mock.Mock( + dimensions=('foo', 'nv'), + cf_name='wibble_bnds', + shape=bounds.shape, + __getitem__=lambda self, key: bounds[key]) + + expected_coord = DimCoord( + self.cf_coord_var[:], + long_name=self.cf_coord_var.long_name, + var_name=self.cf_coord_var.cf_name, + units=self.cf_coord_var.units, + bounds=bounds) + + # Asserts must lie within context manager because of deferred loading. + with self.deferred_load_patch, self.get_cf_bounds_var_patch: + build_dimension_coordinate(self.engine, self.cf_coord_var) + + # Test that expected coord is built and added to cube. + self.engine.cube.add_dim_coord.assert_called_with( + expected_coord, [0]) + + # Test that engine.provides container is correctly populated. + expected_list = [(expected_coord, self.cf_coord_var.cf_name)] + self.assertEqual(self.engine.provides['coordinates'], + expected_list) + + def test_fastest_with_different_dim_names(self): + # Despite the dimension names 'x' differing from the coord's + # which is 'foo' (as permitted by the cf spec), + # this should still work because the vertex dim is the fastest varying. + bounds = np.arange(12).reshape(6, 2) + self.cf_bounds_var = mock.Mock( + dimensions=('x', 'nv'), + cf_name='wibble_bnds', + shape=bounds.shape, + __getitem__=lambda self, key: bounds[key]) + + expected_coord = DimCoord( + self.cf_coord_var[:], + long_name=self.cf_coord_var.long_name, + var_name=self.cf_coord_var.cf_name, + units=self.cf_coord_var.units, + bounds=bounds) + + # Asserts must lie within context manager because of deferred loading. + with self.deferred_load_patch, self.get_cf_bounds_var_patch: + build_dimension_coordinate(self.engine, self.cf_coord_var) + + # Test that expected coord is built and added to cube. + self.engine.cube.add_dim_coord.assert_called_with( + expected_coord, [0]) + + # Test that engine.provides container is correctly populated. + expected_list = [(expected_coord, self.cf_coord_var.cf_name)] + self.assertEqual(self.engine.provides['coordinates'], + expected_list) + + +class TestCircular(tests.IrisTest, RulesTestMixin): + # Test the rules logic for marking a coordinate "circular". + def setUp(self): + # Call parent setUp explicitly, because of how unittests work. + RulesTestMixin.setUp(self) + self.cf_bounds_var = None + + def _make_vars(self, points, bounds=None, units='degrees'): + points = np.array(points) + self.cf_coord_var = mock.Mock( + dimensions=('foo',), + cf_name='wibble', + standard_name=None, + long_name='wibble', + units=units, + shape=points.shape, + dtype=points.dtype, + __getitem__=lambda self, key: points[key]) + if bounds: + bounds = np.array(bounds).reshape( + self.cf_coord_var.shape + (2,)) + self.cf_bounds_var = mock.Mock( + dimensions=('x', 'nv'), + cf_name='wibble_bnds', + shape=bounds.shape, + __getitem__=lambda self, key: bounds[key]) + + def _check_circular(self, circular, *args, **kwargs): + if 'coord_name' in kwargs: + coord_name = kwargs.pop('coord_name') + else: + coord_name = 'longitude' + self._make_vars(*args, **kwargs) + with self.deferred_load_patch, self.get_cf_bounds_var_patch: + build_dimension_coordinate(self.engine, self.cf_coord_var, + coord_name=coord_name) + self.assertEqual(self.engine.cube.add_dim_coord.call_count, 1) + coord, dims = self.engine.cube.add_dim_coord.call_args[0] + self.assertEqual(coord.circular, circular) + + def check_circular(self, *args, **kwargs): + self._check_circular(True, *args, **kwargs) + + def check_noncircular(self, *args, **kwargs): + self._check_circular(False, *args, **kwargs) + + def test_single_zero_noncircular(self): + self.check_noncircular([0.0]) + + def test_single_lt_modulus_noncircular(self): + self.check_noncircular([-1.0]) + + def test_single_eq_modulus_circular(self): + self.check_circular([360.0]) + + def test_single_gt_modulus_circular(self): + self.check_circular([361.0]) + + def test_single_bounded_noncircular(self): + self.check_noncircular([180.0], bounds=[90.0, 240.0]) + + def test_single_bounded_circular(self): + self.check_circular([180.0], bounds=[90.0, 450.0]) + + def test_multiple_unbounded_circular(self): + self.check_circular([0.0, 90.0, 180.0, 270.0]) + + def test_non_angle_noncircular(self): + points = [0.0, 90.0, 180.0, 270.0] + self.check_noncircular(points, units='m') + + def test_non_longitude_noncircular(self): + points = [0.0, 90.0, 180.0, 270.0] + self.check_noncircular(points, coord_name='depth') + + def test_multiple_unbounded_irregular_noncircular(self): + self.check_noncircular([0.0, 90.0, 189.999, 270.0]) + + def test_multiple_unbounded_offset_circular(self): + self.check_circular([45.0, 135.0, 225.0, 315.0]) + + def test_multiple_unbounded_shortrange_circular(self): + self.check_circular([0.0, 90.0, 180.0, 269.9999]) + + def test_multiple_bounded_circular(self): + self.check_circular([0.0, 120.3, 240.0], + bounds=[[-45.0, 50.0], + [100.0, 175.0], + [200.0, 315.0]]) + + def test_multiple_bounded_noncircular(self): + self.check_noncircular([0.0, 120.3, 240.0], + bounds=[[-45.0, 50.0], + [100.0, 175.0], + [200.0, 355.0]]) + + +class TestCircularScalar(tests.IrisTest, RulesTestMixin): + def setUp(self): + RulesTestMixin.setUp(self) + + def _make_vars(self, bounds): + # Create cf vars for the coordinate and its bounds. + # Note that for a scalar the shape of the array from + # the cf var is (), rather than (1,). + points = np.array([0.]) + self.cf_coord_var = mock.Mock( + dimensions=(), + cf_name='wibble', + standard_name=None, + long_name='wibble', + units='degrees', + shape=(), + dtype=points.dtype, + __getitem__=lambda self, key: points[key]) + + bounds = np.array(bounds) + self.cf_bounds_var = mock.Mock( + dimensions=(u'bnds'), + cf_name='wibble_bnds', + shape=bounds.shape, + __getitem__=lambda self, key: bounds[key]) + + def _assert_circular(self, value): + with self.deferred_load_patch, self.get_cf_bounds_var_patch: + build_dimension_coordinate(self.engine, self.cf_coord_var, + coord_name='longitude') + self.assertEqual(self.engine.cube.add_aux_coord.call_count, 1) + coord, dims = self.engine.cube.add_aux_coord.call_args[0] + self.assertEqual(coord.circular, value) + + def test_two_bounds_noncircular(self): + self._make_vars([0., 180.]) + self._assert_circular(False) + + def test_two_bounds_circular(self): + self._make_vars([0., 360.]) + self._assert_circular(True) + + def test_two_bounds_circular_decreasing(self): + self._make_vars([360., 0.]) + self._assert_circular(True) + + def test_two_bounds_circular_alt(self): + self._make_vars([-180., 180.]) + self._assert_circular(True) + + def test_two_bounds_circular_alt_decreasing(self): + self._make_vars([180., -180.]) + self._assert_circular(True) + + def test_four_bounds(self): + self._make_vars([0., 10., 20., 30.]) + self._assert_circular(False) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_mercator_coordinate_system.py b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_mercator_coordinate_system.py new file mode 100644 index 0000000000..f09a3323e3 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_mercator_coordinate_system.py @@ -0,0 +1,76 @@ +# (C) British Crown Copyright 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test function :func:`iris.fileformats._pyke_rules.compiled_krb.\ +fc_rules_cf_fc.build_mercator_coordinate_system`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import numpy as np + +import iris +from iris.coord_systems import Mercator +from iris.fileformats._pyke_rules.compiled_krb.fc_rules_cf_fc import \ + build_mercator_coordinate_system +from iris.tests import mock + + +class TestBuildMercatorCoordinateSystem(tests.IrisTest): + def test_valid(self): + cf_grid_var = mock.Mock( + spec=[], + longitude_of_projection_origin=-90, + semi_major_axis=6377563.396, + semi_minor_axis=6356256.909) + + cs = build_mercator_coordinate_system(None, cf_grid_var) + + expected = Mercator( + longitude_of_projection_origin=( + cf_grid_var.longitude_of_projection_origin), + ellipsoid=iris.coord_systems.GeogCS( + cf_grid_var.semi_major_axis, + cf_grid_var.semi_minor_axis)) + self.assertEqual(cs, expected) + + def test_inverse_flattening(self): + cf_grid_var = mock.Mock( + spec=[], + longitude_of_projection_origin=-90, + semi_major_axis=6377563.396, + inverse_flattening=299.3249646) + + cs = build_mercator_coordinate_system(None, cf_grid_var) + + expected = Mercator( + longitude_of_projection_origin=( + cf_grid_var.longitude_of_projection_origin), + ellipsoid=iris.coord_systems.GeogCS( + cf_grid_var.semi_major_axis, + inverse_flattening=cf_grid_var.inverse_flattening)) + self.assertEqual(cs, expected) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_stereographic_coordinate_system.py b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_stereographic_coordinate_system.py new file mode 100644 index 0000000000..68e1aa29a9 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_stereographic_coordinate_system.py @@ -0,0 +1,88 @@ +# (C) British Crown Copyright 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test function :func:`iris.fileformats._pyke_rules.compiled_krb.\ +fc_rules_cf_fc.build_sterographic_coordinate_system`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import numpy as np + +import iris +from iris.coord_systems import Stereographic +from iris.fileformats._pyke_rules.compiled_krb.fc_rules_cf_fc import \ + build_stereographic_coordinate_system +from iris.tests import mock + + +class TestBuildStereographicCoordinateSystem(tests.IrisTest): + def test_valid(self): + cf_grid_var = mock.Mock( + spec=[], + latitude_of_projection_origin=0, + longitude_of_projection_origin=0, + false_easting=-100, + false_northing=200, + scale_factor_at_projection_origin=1, + semi_major_axis=6377563.396, + semi_minor_axis=6356256.909) + + cs = build_stereographic_coordinate_system(None, cf_grid_var) + + expected = Stereographic( + central_lat=cf_grid_var.latitude_of_projection_origin, + central_lon=cf_grid_var.longitude_of_projection_origin, + false_easting=cf_grid_var.false_easting, + false_northing=cf_grid_var.false_northing, + ellipsoid=iris.coord_systems.GeogCS( + cf_grid_var.semi_major_axis, + cf_grid_var.semi_minor_axis)) + self.assertEqual(cs, expected) + + def test_inverse_flattening(self): + cf_grid_var = mock.Mock( + spec=[], + latitude_of_projection_origin=0, + longitude_of_projection_origin=0, + false_easting=-100, + false_northing=200, + scale_factor_at_projection_origin=1, + semi_major_axis=6377563.396, + inverse_flattening=299.3249646) + + cs = build_stereographic_coordinate_system(None, cf_grid_var) + + expected = Stereographic( + central_lat=cf_grid_var.latitude_of_projection_origin, + central_lon=cf_grid_var.longitude_of_projection_origin, + false_easting=cf_grid_var.false_easting, + false_northing=cf_grid_var.false_northing, + ellipsoid=iris.coord_systems.GeogCS( + cf_grid_var.semi_major_axis, + inverse_flattening=cf_grid_var.inverse_flattening)) + self.assertEqual(cs, expected) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_get_attr_units.py b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_get_attr_units.py new file mode 100644 index 0000000000..dc9dd0cb45 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_get_attr_units.py @@ -0,0 +1,65 @@ +# (C) British Crown Copyright 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test function :func:`iris.fileformats._pyke_rules.compiled_krb.\ +fc_rules_cf_fc.build_cube_metadata`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import numpy as np + +from iris.fileformats._pyke_rules.compiled_krb.fc_rules_cf_fc import \ + get_attr_units +from iris.tests import mock + + +class TestGetAttrUnits(tests.IrisTest): + @staticmethod + def _make_cf_var(global_attributes=None): + if global_attributes is None: + global_attributes = {} + + cf_group = mock.Mock(global_attributes=global_attributes) + + cf_var = mock.Mock( + cf_name='sound_frequency', + standard_name=None, + long_name=None, + units=u'\u266b', + dtype=np.float64, + cell_methods=None, + cf_group=cf_group) + return cf_var + + def test_unicode_character(self): + attributes = {} + expected_attributes = {'invalid_units': u'\u266b'} + cf_var = self._make_cf_var() + attr_units = get_attr_units(cf_var, attributes) + self.assertEqual(attr_units, 'unknown') + self.assertEqual(attributes, expected_attributes) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_has_supported_mercator_parameters.py b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_has_supported_mercator_parameters.py new file mode 100644 index 0000000000..30dcec5e31 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_has_supported_mercator_parameters.py @@ -0,0 +1,152 @@ +# (C) British Crown Copyright 2016 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test function :func:`iris.fileformats._pyke_rules.compiled_krb.\ +fc_rules_cf_fc.has_supported_mercator_parameters`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import warnings + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import numpy as np +import six + +from iris.fileformats._pyke_rules.compiled_krb.fc_rules_cf_fc import \ + has_supported_mercator_parameters +from iris.tests import mock + + +def _engine(cf_grid_var, cf_name): + cf_group = {cf_name: cf_grid_var} + cf_var = mock.Mock(cf_group=cf_group) + return mock.Mock(cf_var=cf_var) + + +class TestHasSupportedMercatorParameters(tests.IrisTest): + + def test_valid(self): + cf_name = 'mercator' + cf_grid_var = mock.Mock( + spec=[], + longitude_of_projection_origin=-90, + false_easting=0, + false_northing=0, + scale_factor_at_projection_origin=1, + semi_major_axis=6377563.396, + semi_minor_axis=6356256.909) + engine = _engine(cf_grid_var, cf_name) + + is_valid = has_supported_mercator_parameters(engine, cf_name) + + self.assertTrue(is_valid) + + def test_invalid_scale_factor(self): + # Iris does not yet support scale factors other than one for + # Mercator projections + cf_name = 'mercator' + cf_grid_var = mock.Mock( + spec=[], + longitude_of_projection_origin=0, + false_easting=0, + false_northing=0, + scale_factor_at_projection_origin=0.9, + semi_major_axis=6377563.396, + semi_minor_axis=6356256.909) + engine = _engine(cf_grid_var, cf_name) + + with warnings.catch_warnings(record=True) as warns: + warnings.simplefilter("always") + is_valid = has_supported_mercator_parameters(engine, cf_name) + + self.assertFalse(is_valid) + self.assertEqual(len(warns), 1) + six.assertRegex(self, str(warns[0]), 'Scale factor') + + def test_invalid_standard_parallel(self): + # Iris does not yet support standard parallels other than zero for + # Mercator projections + cf_name = 'mercator' + cf_grid_var = mock.Mock( + spec=[], + longitude_of_projection_origin=0, + false_easting=0, + false_northing=0, + standard_parallel=30, + semi_major_axis=6377563.396, + semi_minor_axis=6356256.909) + engine = _engine(cf_grid_var, cf_name) + + with warnings.catch_warnings(record=True) as warns: + warnings.simplefilter("always") + is_valid = has_supported_mercator_parameters(engine, cf_name) + + self.assertFalse(is_valid) + self.assertEqual(len(warns), 1) + six.assertRegex(self, str(warns[0]), 'Standard parallel') + + def test_invalid_false_easting(self): + # Iris does not yet support false eastings other than zero for + # Mercator projections + cf_name = 'mercator' + cf_grid_var = mock.Mock( + spec=[], + longitude_of_projection_origin=0, + false_easting=100, + false_northing=0, + scale_factor_at_projection_origin=1, + semi_major_axis=6377563.396, + semi_minor_axis=6356256.909) + engine = _engine(cf_grid_var, cf_name) + + with warnings.catch_warnings(record=True) as warns: + warnings.simplefilter("always") + is_valid = has_supported_mercator_parameters(engine, cf_name) + + self.assertFalse(is_valid) + self.assertEqual(len(warns), 1) + six.assertRegex(self, str(warns[0]), 'False easting') + + def test_invalid_false_northing(self): + # Iris does not yet support false northings other than zero for + # Mercator projections + cf_name = 'mercator' + cf_grid_var = mock.Mock( + spec=[], + longitude_of_projection_origin=0, + false_easting=0, + false_northing=100, + scale_factor_at_projection_origin=1, + semi_major_axis=6377563.396, + semi_minor_axis=6356256.909) + engine = _engine(cf_grid_var, cf_name) + + with warnings.catch_warnings(record=True) as warns: + warnings.simplefilter("always") + is_valid = has_supported_mercator_parameters(engine, cf_name) + + self.assertFalse(is_valid) + self.assertEqual(len(warns), 1) + six.assertRegex(self, str(warns[0]), 'False northing') + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_has_supported_stereographic_parameters.py b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_has_supported_stereographic_parameters.py new file mode 100644 index 0000000000..4bd3c733d4 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_has_supported_stereographic_parameters.py @@ -0,0 +1,89 @@ +# (C) British Crown Copyright 2016 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test function :func:`iris.fileformats._pyke_rules.compiled_krb.\ +fc_rules_cf_fc.has_supported_stereographic_parameters`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import warnings + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import numpy as np +import six + +from iris.coord_systems import Stereographic +from iris.fileformats._pyke_rules.compiled_krb.fc_rules_cf_fc import \ + has_supported_stereographic_parameters +from iris.tests import mock + + +def _engine(cf_grid_var, cf_name): + cf_group = {cf_name: cf_grid_var} + cf_var = mock.Mock(cf_group=cf_group) + return mock.Mock(cf_var=cf_var) + + +class TestHasSupportedStereographicParameters(tests.IrisTest): + def test_valid(self): + cf_name = 'stereographic' + cf_grid_var = mock.Mock( + spec=[], + latitude_of_projection_origin=0, + longitude_of_projection_origin=0, + false_easting=-100, + false_northing=200, + scale_factor_at_projection_origin=1, + semi_major_axis=6377563.396, + semi_minor_axis=6356256.909) + engine = _engine(cf_grid_var, cf_name) + + is_valid = has_supported_stereographic_parameters(engine, cf_name) + + self.assertTrue(is_valid) + + def test_invalid_scale_factor(self): + # Iris does not yet support scale factors other than one for + # stereographic projections + cf_name = 'stereographic' + cf_grid_var = mock.Mock( + spec=[], + latitude_of_projection_origin=0, + longitude_of_projection_origin=0, + false_easting=-100, + false_northing=200, + scale_factor_at_projection_origin=0.9, + semi_major_axis=6377563.396, + semi_minor_axis=6356256.909) + engine = _engine(cf_grid_var, cf_name) + + with warnings.catch_warnings(record=True) as warns: + warnings.simplefilter("always") + is_valid = has_supported_stereographic_parameters(engine, cf_name) + + self.assertFalse(is_valid) + self.assertEqual(len(warns), 1) + six.assertRegex(self, str(warns[0]), 'Scale factor') + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_reorder_bounds_data.py b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_reorder_bounds_data.py new file mode 100644 index 0000000000..be43927b5c --- /dev/null +++ b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_reorder_bounds_data.py @@ -0,0 +1,68 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test function :func:`iris.fileformats._pyke_rules.compiled_krb.\ +fc_rules_cf_fc.reorder_bounds_data`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import numpy as np + +from iris.fileformats._pyke_rules.compiled_krb.fc_rules_cf_fc import \ + reorder_bounds_data +from iris.tests import mock + + +class Test(tests.IrisTest): + def test_fastest_varying(self): + bounds_data = np.arange(24).reshape(2, 3, 4) + cf_bounds_var = mock.Mock(dimensions=('foo', 'bar', 'nv'), + cf_name='wibble_bnds') + cf_coord_var = mock.Mock(dimensions=('foo', 'bar')) + + res = reorder_bounds_data(bounds_data, cf_bounds_var, cf_coord_var) + # Vertex dimension (nv) is already at the end. + self.assertArrayEqual(res, bounds_data) + + def test_slowest_varying(self): + bounds_data = np.arange(24).reshape(4, 2, 3) + cf_bounds_var = mock.Mock(dimensions=('nv', 'foo', 'bar')) + cf_coord_var = mock.Mock(dimensions=('foo', 'bar')) + + res = reorder_bounds_data(bounds_data, cf_bounds_var, cf_coord_var) + # Move zeroth dimension (nv) to the end. + expected = np.rollaxis(bounds_data, 0, bounds_data.ndim) + self.assertArrayEqual(res, expected) + + def test_different_dim_names(self): + bounds_data = np.arange(24).reshape(2, 3, 4) + cf_bounds_var = mock.Mock(dimensions=('foo', 'bar', 'nv'), + cf_name='wibble_bnds') + cf_coord_var = mock.Mock(dimensions=('x', 'y'), cf_name='wibble') + with self.assertRaisesRegexp(ValueError, 'dimension names'): + reorder_bounds_data(bounds_data, cf_bounds_var, cf_coord_var) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/fileformats/rules/__init__.py b/lib/iris/tests/unit/fileformats/rules/__init__.py new file mode 100644 index 0000000000..0b2f03add2 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/rules/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.fileformats.rules` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/rules/test_Loader.py b/lib/iris/tests/unit/fileformats/rules/test_Loader.py new file mode 100644 index 0000000000..eec203e66e --- /dev/null +++ b/lib/iris/tests/unit/fileformats/rules/test_Loader.py @@ -0,0 +1,55 @@ +# (C) British Crown Copyright 2015 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for :class:`iris.fileformats.rules.Loader`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.fileformats.rules import Loader +from iris.tests import mock + + +class Test___init__(tests.IrisTest): + def test_normal(self): + with mock.patch('warnings.warn') as warn: + loader = Loader(mock.sentinel.GEN_FUNC, + mock.sentinel.GEN_FUNC_KWARGS, + mock.sentinel.CONVERTER) + self.assertEqual(warn.call_count, 0) + self.assertIs(loader.field_generator, mock.sentinel.GEN_FUNC) + self.assertIs(loader.field_generator_kwargs, + mock.sentinel.GEN_FUNC_KWARGS) + self.assertIs(loader.converter, mock.sentinel.CONVERTER) + + def test_normal_with_explicit_none(self): + with mock.patch('warnings.warn') as warn: + loader = Loader(mock.sentinel.GEN_FUNC, + mock.sentinel.GEN_FUNC_KWARGS, + mock.sentinel.CONVERTER) + self.assertEqual(warn.call_count, 0) + self.assertIs(loader.field_generator, mock.sentinel.GEN_FUNC) + self.assertIs(loader.field_generator_kwargs, + mock.sentinel.GEN_FUNC_KWARGS) + self.assertIs(loader.converter, mock.sentinel.CONVERTER) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/fileformats/rules/test__make_cube.py b/lib/iris/tests/unit/fileformats/rules/test__make_cube.py new file mode 100644 index 0000000000..d4b3e554ce --- /dev/null +++ b/lib/iris/tests/unit/fileformats/rules/test__make_cube.py @@ -0,0 +1,75 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for :func:`iris.fileformats.rules._make_cube`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import six +import warnings + +from iris.fileformats.rules import ConversionMetadata +from iris.tests import mock +import numpy as np + +from iris.fileformats.rules import _make_cube + + +class Test(tests.IrisTest): + def test_invalid_units(self): + # Mock converter() function that returns an invalid + # units string amongst the collection of other elements. + factories = None + references = None + standard_name = None + long_name = None + units = 'wibble' # Invalid unit. + attributes = dict(source='test') + cell_methods = None + dim_coords_and_dims = None + aux_coords_and_dims = None + metadata = ConversionMetadata(factories, references, + standard_name, long_name, units, + attributes, cell_methods, + dim_coords_and_dims, aux_coords_and_dims) + converter = mock.Mock(return_value=metadata) + + data = np.arange(3.) + field = mock.Mock(core_data=lambda: data, + bmdi=9999., + realised_dtype=data.dtype) + with warnings.catch_warnings(record=True) as warn: + warnings.simplefilter("always") + cube, factories, references = _make_cube(field, converter) + + # Check attributes dictionary is correctly populated. + expected_attributes = attributes.copy() + expected_attributes['invalid_units'] = units + self.assertEqual(cube.attributes, expected_attributes) + + # Check warning was raised. + self.assertEqual(len(warn), 1) + exp_emsg = 'invalid units {!r}'.format(units) + six.assertRegex(self, str(warn[0]), exp_emsg) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/structured_array_identification/__init__.py b/lib/iris/tests/unit/fileformats/structured_array_identification/__init__.py new file mode 100644 index 0000000000..b1e8bb1621 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/structured_array_identification/__init__.py @@ -0,0 +1,24 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the +:mod:`iris.fileformats._structured_array_identification` module. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/structured_array_identification/test_ArrayStructure.py b/lib/iris/tests/unit/fileformats/structured_array_identification/test_ArrayStructure.py new file mode 100644 index 0000000000..1a969349b0 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/structured_array_identification/test_ArrayStructure.py @@ -0,0 +1,232 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the +:mod:`iris.fileformats._structured_array_identification.ArrayStructure` class. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.fileformats._structured_array_identification import \ + ArrayStructure, _UnstructuredArrayException + + +def construct_nd(sub_array, sub_dim, shape): + # Given a 1D array, a shape, and the axis/dimension that the 1D array + # represents on the bigger array, construct a numpy array which is + # filled appropriately. + assert sub_array.ndim == 1 + sub_shape = [1 if dim != sub_dim else -1 for dim in range(len(shape))] + return sub_array.reshape(sub_shape) * np.ones(shape) + + +class TestArrayStructure_from_array(tests.IrisTest): + def struct_from_arr(self, nd_array): + return ArrayStructure.from_array(nd_array.flatten()) + + def test_1d_len_0(self): + a = np.arange(0) + self.assertEqual(self.struct_from_arr(a), ArrayStructure(1, a)) + + def test_1d_len_1(self): + a = np.arange(1) + self.assertEqual(self.struct_from_arr(a), ArrayStructure(1, a)) + + def test_1d(self): + a = np.array([-1, 3, 1, 2]) + self.assertEqual(self.struct_from_arr(a), ArrayStructure(1, a)) + + def test_1d_ones(self): + a = np.ones(10) + self.assertEqual(self.struct_from_arr(a), ArrayStructure(1, [1])) + + def test_1d_range(self): + a = np.arange(6) + self.assertEqual(self.struct_from_arr(a), + ArrayStructure(1, list(range(6)))) + + def test_3d_ones(self): + a = np.ones([10, 2, 1]) + self.assertEqual(self.struct_from_arr(a), ArrayStructure(1, [1])) + + def test_1d_over_2d_first_dim_manual(self): + sub = np.array([10, 10, 20, 20]) + self.assertEqual(self.struct_from_arr(sub), + ArrayStructure(2, [10, 20])) + + def test_3d_first_dimension(self): + flattened = np.array([1, 1, 1, 2, 2, 2]) + self.assertEqual(ArrayStructure.from_array(flattened), + ArrayStructure(3, [1, 2])) + + def test_1d_over_2d_first_dim(self): + sub = np.array([-1, 3, 1, 2]) + a = construct_nd(sub, 0, (4, 2)) + self.assertEqual(self.struct_from_arr(a), ArrayStructure(2, sub)) + + def test_1d_over_2d_second_dim(self): + sub = np.array([-1, 3, 1, 2]) + a = construct_nd(sub, 1, (2, 4)) + self.assertEqual(self.struct_from_arr(a), ArrayStructure(1, sub)) + + def test_1d_over_3d_first_dim(self): + sub = np.array([-1, 3, 1, 2]) + a = construct_nd(sub, 0, (4, 2, 3)) + self.assertEqual(self.struct_from_arr(a), ArrayStructure(6, sub)) + + def test_1d_over_3d_second_dim(self): + sub = np.array([-1, 3, 1, 2]) + a = construct_nd(sub, 1, (2, 4, 3)) + self.assertEqual(self.struct_from_arr(a), ArrayStructure(3, sub)) + + def test_1d_over_3d_third_dim(self): + sub = np.array([-1, 3, 1, 2]) + a = construct_nd(sub, 2, (3, 2, 4)) + self.assertEqual(self.struct_from_arr(a), ArrayStructure(1, sub)) + + def test_irregular_3d(self): + sub = np.array([-1, 3, 1, 2]) + a = construct_nd(sub, 2, (3, 2, 4)) + a[0, 0, 0] = 5 + self.assertEqual(self.struct_from_arr(a), None) + + def test_repeated_3d(self): + sub = np.array([-1, 3, 1, 2]) + a = construct_nd(sub, 2, (3, 2, 4)) + a[:, 0, 0] = 1 + self.assertEqual(self.struct_from_arr(a), None) + + def test_rolled_3d(self): + # Shift the 3D array on by one, making the array 1d. + sub = np.arange(4) + a = construct_nd(sub, 0, (4, 2, 3)) + a = np.roll(a.flatten(), 1) + self.assertEqual(self.struct_from_arr(a), None) + + def test_len_1_3d(self): + # Setup a case which triggers an IndexError when identifying + # the stride, but the result should still be correct. + sub = np.arange(2) + a = construct_nd(sub, 1, (1, 1, 1)) + self.assertEqual(self.struct_from_arr(a), ArrayStructure(1, sub)) + + def test_not_an_array(self): + # Support lists as an argument. + self.assertEqual(ArrayStructure.from_array([1, 2, 3]), + ArrayStructure(1, [1, 2, 3])) + + def test_multi_dim_array(self): + with self.assertRaises(ValueError): + ArrayStructure.from_array(np.arange(12).reshape(3, 4)) + + +class nd_array_and_dims_cases(object): + """ + Defines the test functionality for nd_array_and_dims. This class + isn't actually the test case - see the C order and F order subclasses + for those. + + """ + def test_scalar_len1_first_dim(self): + struct = ArrayStructure(1, [1]) + orig = np.array([1, 1, 1]) + + array, dims = struct.nd_array_and_dims(orig, (1, 3), order=self.order) + self.assertArrayEqual(array, [1]) + self.assertEqual(dims, ()) + + def test_scalar_non_len1_first_dim(self): + struct = ArrayStructure(1, [1]) + orig = np.array([1, 1, 1]) + + array, dims = struct.nd_array_and_dims(orig, (3, 1), order=self.order) + self.assertArrayEqual(array, [1]) + self.assertEqual(dims, ()) + + def test_single_vector(self): + orig = construct_nd(np.array([1, 2]), 0, (2, 1, 3)) + flattened = orig.flatten(order=self.order) + struct = ArrayStructure.from_array(flattened) + array, dims = struct.nd_array_and_dims(flattened, (2, 1, 3), + order=self.order) + self.assertArrayEqual(array, [1, 2]) + self.assertEqual(dims, (0, )) + + def test_single_vector_3rd_dim(self): + orig = construct_nd(np.array([1, 2, 3]), 2, (4, 1, 3)) + flattened = orig.flatten(order=self.order) + + struct = ArrayStructure.from_array(flattened) + array, dims = struct.nd_array_and_dims(flattened, (4, 1, 3), + order=self.order) + self.assertArrayEqual(array, [1, 2, 3]) + self.assertEqual(dims, (2, )) + + def test_orig_array_and_target_shape_inconsistent(self): + # An array structure which has a length which is a product + # of potential dimensions should not result in an array + struct = ArrayStructure(2, [1, 2, 3]) + orig = np.array([1, 1, 2, 2, 3, 3]) + + msg = 'Original array and target shape do not match up.' + with self.assertRaisesRegexp(ValueError, msg): + struct.nd_array_and_dims(orig, (2, 3, 2), order=self.order) + + def test_array_bigger_than_expected(self): + # An array structure which has a length which is a product + # of potential dimensions should not result in an array + struct = ArrayStructure(2, [1, 2, 3, 4, 5, 6]) + orig = np.array([1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6]) + + with self.assertRaises(_UnstructuredArrayException): + struct.nd_array_and_dims(orig, (2, 3, 2), order=self.order) + + def test_single_vector_extra_dimension(self): + orig = construct_nd(np.array([1, 2]), 1, (3, 2)) + flattened = orig.flatten(order=self.order) + + struct = ArrayStructure.from_array(flattened) + + # Add another dimension on flattened, making it a (6, 2). + input_array = np.vstack([flattened, flattened + 100]).T + + array, dims = struct.nd_array_and_dims(input_array, (3, 1, 2, 1), + order=self.order) + self.assertArrayEqual(array, [[1, 101], [2, 102]]) + self.assertEqual(dims, (2, )) + + +class TestArrayStructure_nd_array_and_dims_f_order(tests.IrisTest, + nd_array_and_dims_cases): + order = 'f' + + +class TestArrayStructure_nd_array_and_dims_c_order(tests.IrisTest, + nd_array_and_dims_cases): + order = 'c' + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/structured_array_identification/test_GroupStructure.py b/lib/iris/tests/unit/fileformats/structured_array_identification/test_GroupStructure.py new file mode 100644 index 0000000000..e0ec0f54f4 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/structured_array_identification/test_GroupStructure.py @@ -0,0 +1,191 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the +:mod:`iris.fileformats._structured_array_identification.GroupStructure` class. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.fileformats._structured_array_identification import (GroupStructure, + ArrayStructure) + + +def regular_array_structures(shape, names='abcdefg'): + # Construct column major appropriate ArrayStructures for the given + # shape. + running_product = 1 + array_structures = {} + for name, dim_len in zip(names, shape): + array_structures[name] = ArrayStructure(running_product, + np.arange(dim_len)) + running_product *= dim_len + return array_structures + + +class TestGroupStructure_from_component_arrays(tests.IrisTest): + def test_different_sizes(self): + arrays = {'a': np.arange(6), 'b': np.arange(5)} + msg = 'All array elements must have the same size.' + with self.assertRaisesRegexp(ValueError, msg): + GroupStructure.from_component_arrays(arrays) + + def test_structure_creation(self): + # Test that the appropriate dictionary containing ArrayStructures is + # computed when constructing a GroupStructure from_component_arrays. + array = np.arange(6) + expected_structure = {'a': ArrayStructure.from_array(array)} + + grp = GroupStructure.from_component_arrays({'a': array}) + + self.assertEqual(grp.length, 6) + self.assertEqual(grp._cmpt_structure, expected_structure) + + +class TestGroupStructure_possible_structures(tests.IrisTest): + def test_simple_3d_structure(self): + # Construct a structure representing a (3, 2, 4) group and assert + # that the result is of the expected form. + array_structures = {'a': ArrayStructure(1, [1, -1, 2]), + 'b': ArrayStructure(3, [1, -1]), + 'c': ArrayStructure(6, [1, -1, 2, 3])} + structure = GroupStructure(24, array_structures, array_order='f') + expected = ([('a', array_structures['a']), + ('b', array_structures['b']), + ('c', array_structures['c'])],) + self.assertEqual(structure.possible_structures(), expected) + + def assert_potentials(self, length, array_structures, expected): + structure = GroupStructure(length, array_structures, array_order='f') + allowed = structure.possible_structures() + names = [[name for (name, _) in allowed_structure] + for allowed_structure in allowed] + self.assertEqual(names, expected) + + def test_multiple_potentials(self): + # More than one potential dimension for dim 1. + array_structures = regular_array_structures((4, 2, 3)) + array_structures['shared b'] = ArrayStructure(4, [-10, 4]) + self.assert_potentials(24, array_structures, [['a', 'b', 'c'], + ['a', 'shared b', 'c']]) + + def test_alternate_potentials(self): + # More than one potential dimension for dim 1. + array_structures = regular_array_structures((4, 2, 3)) + array_structures.update(regular_array_structures((6, 4), names='xy')) + self.assert_potentials(24, array_structures, [['x', 'y'], + ['a', 'b', 'c']]) + + def test_shared_first_dimension(self): + # One 2d potential as well as one 3d, using the same first dimension. + array_structures = regular_array_structures((4, 2, 3)) + array_structures['bc combined'] = ArrayStructure(4, np.arange(6)) + self.assert_potentials(24, array_structures, [['a', 'bc combined'], + ['a', 'b', 'c']]) + + def test_non_viable_element(self): + # One 2d potential as well as one 3d, using the same first dimension. + array_structures = regular_array_structures((4, 2, 3)) + array_structures.pop('c') + array_structures['strange_length'] = ArrayStructure(4, np.arange(5)) + self.assert_potentials(24, array_structures, []) + + def test_completely_unstructured_element(self): + # One of the arrays is entirely unstructured. + array_structures = regular_array_structures((4, 2, 3)) + array_structures['unstructured'] = None + self.assert_potentials(24, array_structures, [['a', 'b', 'c']]) + + +class TestGroupStructure_build_arrays(tests.IrisTest): + def assert_built_array(self, name, result, expected): + ex_arr, ex_dims = expected + re_arr, re_dims = result[name] + self.assertEqual(ex_dims, re_dims) + self.assertArrayEqual(ex_arr, re_arr) + + def test_build_arrays_regular_f_order(self): + # Construct simple orthogonal 1d array structures, adding a trailing + # dimension to the second, and assert the result of build_arrays + # produces the required result. + elements = regular_array_structures((2, 3)) + + a = elements['a'].construct_array(6) + b = elements['b'].construct_array(6) + # Make b 2 dimensional. + b = np.vstack([b, b + 100]).T + + grp = GroupStructure(6, elements, array_order='f') + + result = grp.build_arrays((2, 3), {'a': a, 'b': b}) + self.assert_built_array('a', result, ([0, 1], (0,))) + self.assert_built_array('b', result, ([[0, 100], [1, 101], [2, 102]], + (1,))) + + def test_build_arrays_unstructured(self): + # Check that an unstructured array gets reshaped appropriately. + grp = GroupStructure(6, {'a': None}, array_order='c') + orig = np.array([1, 2, 3, 4, 5, 6]).reshape(2, 3) + r = grp.build_arrays((2, 3), {'a': orig.flatten(order='c')}) + self.assert_built_array('a', r, (orig, (0, 1))) + + def test_build_arrays_unstructured_ndim_f_order(self): + # Passing an unstructured array to build_arrays, should result in the + # appropriately shaped array, plus any trailing dimensions. + grp = GroupStructure(6, {'a': None}, array_order='f') + orig = np.array([1, 2, 3, 4, 5, 6]).reshape(2, 3) + orig = np.dstack([orig, orig + 10]) + r = grp.build_arrays((2, 3), {'a': orig.reshape((-1, 2), order='f')}) + self.assert_built_array('a', r, (orig, (0, 1))) + + def test_build_arrays_unstructured_ndim_c_order(self): + # Passing an unstructured array to build_arrays, should result in the + # appropriately shaped array, plus any trailing dimensions. + grp = GroupStructure(6, {'a': None}, array_order='c') + orig = np.array([1, 2, 3, 4, 5, 6]).reshape(2, 3) + orig = np.dstack([orig, orig + 10]) + r = grp.build_arrays((2, 3), {'a': orig.reshape((-1, 2), order='c')}) + self.assert_built_array('a', r, (orig, (0, 1))) + + def test_structured_array_not_applicable(self): + # Just because an array has a possible structure, does not mean it + # gets used. Check that 'd' which would make a good 1D array, doesn't + # get used in a specific shape. + elements = regular_array_structures((2, 2, 3)) + elements['d'] = ArrayStructure(3, np.arange(4)) + grp = GroupStructure(12, elements, array_order='f') + + d = np.array([0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3]).reshape((3, 4), + order='f') + expected = np.array([[[0, 1, 2], [0, 2, 3]], [[0, 1, 3], [1, 2, 3]]]) + r = grp.build_arrays((2, 2, 3), {'a': np.arange(12), + 'b': np.arange(12), + 'c': np.arange(12), + 'd': d.flatten(order='f')}) + self.assert_built_array('d', r, (expected, (0, 1, 2))) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/test_rules.py b/lib/iris/tests/unit/fileformats/test_rules.py new file mode 100644 index 0000000000..39f6ab35c6 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/test_rules.py @@ -0,0 +1,253 @@ +# (C) British Crown Copyright 2010 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test iris.fileformats.rules.py - metadata translation rules. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import types + +import numpy as np + +from iris.aux_factory import HybridHeightFactory +from iris.cube import Cube +from iris.fileformats.rules import (ConcreteReferenceTarget, + ConversionMetadata, Factory, Loader, + Reference, ReferenceTarget, load_cubes, + scalar_cell_method) +from iris.coords import CellMethod +from iris.tests import mock +import iris.tests.stock as stock + + +class TestConcreteReferenceTarget(tests.IrisTest): + def test_attributes(self): + with self.assertRaises(TypeError): + target = ConcreteReferenceTarget() + + target = ConcreteReferenceTarget('foo') + self.assertEqual(target.name, 'foo') + self.assertIsNone(target.transform) + + def transform(_): + return _ + + target = ConcreteReferenceTarget('foo', transform) + self.assertEqual(target.name, 'foo') + self.assertIs(target.transform, transform) + + def test_single_cube_no_transform(self): + target = ConcreteReferenceTarget('foo') + src = stock.simple_2d() + target.add_cube(src) + self.assertIs(target.as_cube(), src) + + def test_single_cube_with_transform(self): + def transform(cube): + return {'long_name': 'wibble'} + + target = ConcreteReferenceTarget('foo', transform) + src = stock.simple_2d() + target.add_cube(src) + dest = target.as_cube() + self.assertEqual(dest.long_name, 'wibble') + self.assertNotEqual(dest, src) + dest.long_name = src.long_name + self.assertEqual(dest, src) + + @tests.skip_data + def test_multiple_cubes_no_transform(self): + target = ConcreteReferenceTarget('foo') + src = stock.realistic_4d() + for i in range(src.shape[0]): + target.add_cube(src[i]) + dest = target.as_cube() + self.assertIsNot(dest, src) + self.assertEqual(dest, src) + + @tests.skip_data + def test_multiple_cubes_with_transform(self): + def transform(cube): + return {'long_name': 'wibble'} + + target = ConcreteReferenceTarget('foo', transform) + src = stock.realistic_4d() + for i in range(src.shape[0]): + target.add_cube(src[i]) + dest = target.as_cube() + self.assertEqual(dest.long_name, 'wibble') + self.assertNotEqual(dest, src) + dest.long_name = src.long_name + self.assertEqual(dest, src) + + +class TestLoadCubes(tests.IrisTest): + def test_simple_factory(self): + # Test the creation process for a factory definition which only + # uses simple dict arguments. + + # Make a minimal fake data object that passes as lazy data. + core_data_array = mock.Mock(compute=None, dtype=np.dtype('f4')) + # Make a fake PPField which will be supplied to our converter. + field = mock.Mock(core_data=mock.Mock(return_value=core_data_array), + realised_dtype=np.dtype('f4'), + bmdi=None) + + def field_generator(filename): + return [field] + + # A fake conversion function returning: + # 1) A parameter cube needing a simple factory construction. + aux_factory = mock.Mock() + factory = mock.Mock() + factory.args = [{'name': 'foo'}] + factory.factory_class = lambda *args: \ + setattr(aux_factory, 'fake_args', args) or aux_factory + + def converter(field): + return ConversionMetadata([factory], [], '', '', '', {}, [], [], + []) + # Finish by making a fake Loader + fake_loader = Loader(field_generator, {}, converter) + cubes = load_cubes(['fake_filename'], None, fake_loader) + + # Check the result is a generator with a single entry. + self.assertIsInstance(cubes, types.GeneratorType) + try: + # Suppress the normal Cube.coord() and Cube.add_aux_factory() + # methods. + coord_method = Cube.coord + add_aux_factory_method = Cube.add_aux_factory + Cube.coord = lambda self, **args: args + Cube.add_aux_factory = lambda self, aux_factory: \ + setattr(self, 'fake_aux_factory', aux_factory) + + cubes = list(cubes) + finally: + Cube.coord = coord_method + Cube.add_aux_factory = add_aux_factory_method + self.assertEqual(len(cubes), 1) + # Check the "cube" has an "aux_factory" added, which itself + # must have been created with the correct arguments. + self.assertTrue(hasattr(cubes[0], 'fake_aux_factory')) + self.assertIs(cubes[0].fake_aux_factory, aux_factory) + self.assertTrue(hasattr(aux_factory, 'fake_args')) + self.assertEqual(aux_factory.fake_args, ({'name': 'foo'},)) + + @tests.skip_data + def test_cross_reference(self): + # Test the creation process for a factory definition which uses + # a cross-reference. + + param_cube = stock.realistic_4d_no_derived() + orog_coord = param_cube.coord('surface_altitude') + param_cube.remove_coord(orog_coord) + + orog_cube = param_cube[0, 0, :, :] + orog_cube.data = orog_coord.points + orog_cube.rename('surface_altitude') + orog_cube.units = orog_coord.units + orog_cube.attributes = orog_coord.attributes + + # We're going to test for the presence of the hybrid height + # stuff later, so let's make sure it's not already there! + assert len(param_cube.aux_factories) == 0 + assert not param_cube.coords('surface_altitude') + + # The fake PPFields which will be supplied to our converter. + press_field = mock.Mock( + core_data=mock.Mock(return_value=param_cube.data), + bmdi=-1e20, realised_dtype=param_cube.dtype) + + orog_field = mock.Mock( + core_data=mock.Mock(return_value=orog_cube.data), + bmdi=-1e20, realised_dtype=orog_cube.dtype) + + def field_generator(filename): + return [press_field, orog_field] + + # A fake rule set returning: + # 1) A parameter cube needing an "orography" reference + # 2) An "orography" cube + + def converter(field): + if field is press_field: + src = param_cube + factories = [Factory(HybridHeightFactory, + [Reference('orography')])] + references = [] + else: + src = orog_cube + factories = [] + references = [ReferenceTarget('orography', None)] + dim_coords_and_dims = [(coord, src.coord_dims(coord)[0]) + for coord in src.dim_coords] + aux_coords_and_dims = [(coord, src.coord_dims(coord)) + for coord in src.aux_coords] + return ConversionMetadata(factories, references, src.standard_name, + src.long_name, src.units, src.attributes, + src.cell_methods, dim_coords_and_dims, + aux_coords_and_dims) + # Finish by making a fake Loader + fake_loader = Loader(field_generator, {}, converter) + cubes = load_cubes(['fake_filename'], None, fake_loader) + + # Check the result is a generator containing two Cubes. + self.assertIsInstance(cubes, types.GeneratorType) + cubes = list(cubes) + self.assertEqual(len(cubes), 2) + # Check the "cube" has an "aux_factory" added, which itself + # must have been created with the correct arguments. + self.assertEqual(len(cubes[1].aux_factories), 1) + self.assertEqual(len(cubes[1].coords('surface_altitude')), 1) + + +class Test_scalar_cell_method(tests.IrisTest): + """ Tests for iris.fileformats.rules.scalar_cell_method() function """ + def setUp(self): + self.cube = stock.simple_2d() + self.cm = CellMethod('mean', 'foo', '1 hour') + self.cube.cell_methods = (self.cm, ) + + def test_cell_method_found(self): + actual = scalar_cell_method(self.cube, 'mean', 'foo') + self.assertEqual(actual, self.cm) + + def test_method_different(self): + actual = scalar_cell_method(self.cube, 'average', 'foo') + self.assertIsNone(actual) + + def test_coord_name_different(self): + actual = scalar_cell_method(self.cube, 'average', 'bar') + self.assertIsNone(actual) + + def test_double_coord_fails(self): + self.cube.cell_methods = (CellMethod('mean', ('foo', 'bar'), + ('1 hour', '1 hour')), ) + actual = scalar_cell_method(self.cube, 'mean', 'foo') + self.assertIsNone(actual) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/um/__init__.py b/lib/iris/tests/unit/fileformats/um/__init__.py new file mode 100644 index 0000000000..bdff68c328 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/um/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.fileformats.um` package.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/um/fast_load/__init__.py b/lib/iris/tests/unit/fileformats/um/fast_load/__init__.py new file mode 100644 index 0000000000..451e19c8d8 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/um/fast_load/__init__.py @@ -0,0 +1,23 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the module :mod:`iris.fileformats.um._fast_load`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/um/fast_load/test_FieldCollation.py b/lib/iris/tests/unit/fileformats/um/fast_load/test_FieldCollation.py new file mode 100644 index 0000000000..ea004cdd99 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/um/fast_load/test_FieldCollation.py @@ -0,0 +1,82 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the class +:class:`iris.fileformats.um._fast_load.FieldCollation`. + +This only tests the additional functionality for recording file locations of +PPFields that make loaded cubes. +The original class is the baseclass of this, now renamed 'BasicFieldCollation'. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised +# before importing anything else. +import iris.tests as tests + +import numpy as np + +import iris + +from iris.tests.integration.fast_load.test_fast_load import Mixin_FieldTest + + +class TestFastCallbackLocationInfo(Mixin_FieldTest, tests.IrisTest): + do_fast_loads = True + + def setUp(self): + # Call parent setup. + super(TestFastCallbackLocationInfo, self).setUp() + + # Create a basic load test case. + self.callback_collations = [] + self.callback_filepaths = [] + + def fast_load_callback(cube, collation, filename): + self.callback_collations.append(collation) + self.callback_filepaths.append(filename) + + flds = self.fields(c_t='11112222', c_h='11221122', phn='01010101') + self.test_filepath = self.save_fieldcubes(flds) + iris.load(self.test_filepath, callback=fast_load_callback) + + def test_callback_collations_filepaths(self): + self.assertEqual(len(self.callback_collations), 2) + self.assertEqual(self.callback_collations[0].data_filepath, + self.test_filepath) + self.assertEqual(self.callback_collations[1].data_filepath, + self.test_filepath) + + def test_callback_collations_field_indices(self): + self.assertEqual( + self.callback_collations[0].data_field_indices.dtype, np.int64) + self.assertArrayEqual( + self.callback_collations[0].data_field_indices, + [[1, 3], [5, 7]]) + + self.assertEqual( + self.callback_collations[1].data_field_indices.dtype, np.int64) + self.assertArrayEqual( + self.callback_collations[1].data_field_indices, + [[0, 2], [4, 6]]) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/fileformats/um/fast_load/test__convert_collation.py b/lib/iris/tests/unit/fileformats/um/fast_load/test__convert_collation.py new file mode 100644 index 0000000000..d164bc5000 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/um/fast_load/test__convert_collation.py @@ -0,0 +1,325 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for :func:`iris.fileformats.um._fast_load._convert_collation`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import cf_units +import cftime +import numpy as np + +from iris.fileformats.um._fast_load \ + import _convert_collation as convert_collation +import iris.aux_factory +import iris.coord_systems +import iris.coords +import iris.fileformats.pp +import iris.fileformats.rules +from iris.tests import mock + + +COORD_SYSTEM = iris.coord_systems.GeogCS(6371229.0) +LATITUDE = iris.coords.DimCoord([15, 0, -15], 'latitude', units='degrees', + coord_system=COORD_SYSTEM) +LONGITUDE = iris.coords.DimCoord([0, 20, 40, 60], 'longitude', units='degrees', + coord_system=COORD_SYSTEM, circular=True) + + +class Test(tests.IrisTest): + def _field(self): + # Create PP field for X wind on a regular lat-lon grid. + header = [0] * 64 + # Define the regular lat-lon grid. + header[15] = 1 # LBCODE + header[17] = 3 # LBROW + header[18] = 4 # LBNPT + header[55] = 90 # BPLAT + header[58] = 30 # BZY + header[59] = -15 # BDY + header[60] = -20 # BZX + header[61] = 20 # BDX + # Define the STASH code m01s00i002. + header[41] = 2 # LBUSER(4) + header[44] = 1 # LBUSER(7) + field = iris.fileformats.pp.PPField3(header) + return field + + def _check_phenomenon(self, metadata, factory=None): + if factory is None: + self.assertEqual(metadata.factories, []) + else: + self.assertEqual(metadata.factories, [factory]) + self.assertEqual(metadata.references, []) + self.assertEqual(metadata.standard_name, 'x_wind') + self.assertIsNone(metadata.long_name) + self.assertEqual(metadata.units, cf_units.Unit('m s-1')) + self.assertEqual(metadata.attributes, {'STASH': (1, 0, 2)}) + self.assertEqual(metadata.cell_methods, []) + + def test_all_scalar(self): + field = self._field() + field.lbtim = 11 + field.t1 = cftime.datetime(1970, 1, 1, 18) + field.t2 = cftime.datetime(1970, 1, 1, 12) + collation = mock.Mock(fields=[field], vector_dims_shape=(), + element_arrays_and_dims={}) + metadata = convert_collation(collation) + self._check_phenomenon(metadata) + coords_and_dims = [(LONGITUDE, 1), + (LATITUDE, 0)] + self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) + coords_and_dims = [ + (iris.coords.DimCoord(18, 'time', units='hours since epoch'), + None), + (iris.coords.DimCoord(12, 'forecast_reference_time', + units='hours since epoch'), None), + (iris.coords.DimCoord(6, 'forecast_period', units='hours'), None) + ] + self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) + + def test_vector_t1(self): + field = self._field() + field.lbtim = 11 + field.t2 = cftime.datetime(1970, 1, 1, 12) + t1 = ([cftime.datetime(1970, 1, 1, 18), + cftime.datetime(1970, 1, 2, 0), + cftime.datetime(1970, 1, 2, 6)], [0]) + collation = mock.Mock(fields=[field], vector_dims_shape=(3,), + element_arrays_and_dims={'t1': t1}) + metadata = convert_collation(collation) + self._check_phenomenon(metadata) + coords_and_dims = [(LONGITUDE, 2), + (LATITUDE, 1), + (iris.coords.DimCoord([18, 24, 30], 'time', + units='hours since epoch'), + (0,)) + ] + self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) + coords_and_dims = [ + (iris.coords.DimCoord(12, 'forecast_reference_time', + units='hours since epoch'), None), + (iris.coords.DimCoord([6, 12, 18], 'forecast_period', + units='hours'), (0,)) + ] + self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) + + def test_vector_t2(self): + field = self._field() + field.lbtim = 11 + field.t1 = cftime.datetime(1970, 1, 1, 18) + t2 = ([cftime.datetime(1970, 1, 1, 12), + cftime.datetime(1970, 1, 1, 15), + cftime.datetime(1970, 1, 1, 18)], [0]) + collation = mock.Mock(fields=[field], vector_dims_shape=(3,), + element_arrays_and_dims={'t2': t2}) + metadata = convert_collation(collation) + self._check_phenomenon(metadata) + coords_and_dims = [(LONGITUDE, 2), + (LATITUDE, 1), + (iris.coords.DimCoord([12, 15, 18], + 'forecast_reference_time', + units='hours since epoch'), + (0,)) + ] + self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) + coords_and_dims = [ + (iris.coords.DimCoord(18, 'time', units='hours since epoch'), + None), + (iris.coords.DimCoord([6, 3, 0.], 'forecast_period', + units='hours'), + (0,)) + ] + self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) + + def test_vector_lbft(self): + field = self._field() + field.lbtim = 21 + field.t1 = cftime.datetime(1970, 1, 1, 12) + field.t2 = cftime.datetime(1970, 1, 1, 18) + lbft = ([18, 15, 12], [0]) + collation = mock.Mock(fields=[field], vector_dims_shape=(3,), + element_arrays_and_dims={'lbft': lbft}) + metadata = convert_collation(collation) + self._check_phenomenon(metadata) + coords_and_dims = [(LONGITUDE, 2), + (LATITUDE, 1), + (iris.coords.DimCoord([0, 3, 6], + 'forecast_reference_time', + units='hours since epoch'), + (0,))] + coords_and_dims = [ + (iris.coords.DimCoord(15, 'time', units='hours since epoch', + bounds=[[12, 18]]), None), + (iris.coords.DimCoord([15, 12, 9], 'forecast_period', + units='hours', + bounds=[[12, 18], [9, 15], [6, 12]]), + (0,)) + ] + self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) + + def test_vector_t1_and_t2(self): + field = self._field() + field.lbtim = 11 + t1 = ([cftime.datetime(1970, 1, 2, 6), + cftime.datetime(1970, 1, 2, 9), + cftime.datetime(1970, 1, 2, 12)], [1]) + t2 = ([cftime.datetime(1970, 1, 1, 12), + cftime.datetime(1970, 1, 2, 0)], [0]) + collation = mock.Mock(fields=[field], vector_dims_shape=(2, 3), + element_arrays_and_dims={'t1': t1, 't2': t2}) + metadata = convert_collation(collation) + self._check_phenomenon(metadata) + coords_and_dims = [(LONGITUDE, 3), + (LATITUDE, 2), + (iris.coords.DimCoord([30, 33, 36], 'time', + units='hours since epoch'), + (1,)), + (iris.coords.DimCoord([12, 24], + 'forecast_reference_time', + units='hours since epoch'), + (0,))] + self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) + coords_and_dims = [ + (iris.coords.AuxCoord([[18, 21, 24], [6, 9, 12]], + 'forecast_period', units='hours'), (0, 1)) + ] + self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) + + def test_vertical_pressure(self): + field = self._field() + field.lbvc = 8 + blev = ([1000, 850, 700], (0,)) + lblev = ([1000, 850, 700], (0,)) + collation = mock.Mock(fields=[field], vector_dims_shape=(3,), + element_arrays_and_dims={'blev': blev, + 'lblev': lblev}) + metadata = convert_collation(collation) + self._check_phenomenon(metadata) + coords_and_dims = [(LONGITUDE, 2), + (LATITUDE, 1), + (iris.coords.DimCoord([1000, 850, 700], + long_name='pressure', + units='hPa'), + (0,))] + self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) + coords_and_dims = [] + self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) + + def test_soil_level(self): + field = self._field() + field.lbvc = 6 + points = [10, 20, 30] + lower = [0] * 3 + upper = [0] * 3 + lblev = (points, (0,)) + brsvd1 = (lower, (0,)) + brlev = (upper, (0,)) + collation = mock.Mock(fields=[field], vector_dims_shape=(3,), + element_arrays_and_dims={'lblev': lblev, + 'brsvd1': brsvd1, + 'brlev': brlev}) + metadata = convert_collation(collation) + self._check_phenomenon(metadata) + level = iris.coords.DimCoord(points, + long_name='soil_model_level_number', + attributes={'positive': 'down'}) + coords_and_dims = [(LONGITUDE, 2), + (LATITUDE, 1), + (level, (0,))] + self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) + coords_and_dims = [] + self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) + + def test_soil_depth(self): + field = self._field() + field.lbvc = 6 + points = [10, 20, 30] + lower = [0, 15, 25] + upper = [15, 25, 35] + blev = (points, (0,)) + brsvd1 = (lower, (0,)) + brlev = (upper, (0,)) + collation = mock.Mock(fields=[field], vector_dims_shape=(3,), + element_arrays_and_dims={'blev': blev, + 'brsvd1': brsvd1, + 'brlev': brlev}) + metadata = convert_collation(collation) + self._check_phenomenon(metadata) + depth = iris.coords.DimCoord(points, standard_name='depth', + bounds=np.vstack((lower, upper)).T, + units='m', + attributes={'positive': 'down'}) + coords_and_dims = [(LONGITUDE, 2), + (LATITUDE, 1), + (depth, (0,))] + self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) + coords_and_dims = [] + self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) + + def test_vertical_hybrid_height(self): + field = self._field() + field.lbvc = 65 + blev = ([5, 18, 38], (0,)) + lblev = ([1000, 850, 700], (0,)) + brsvd1 = ([10, 26, 50], (0,)) + brsvd2 = ([0.9989, 0.9970, 0.9944], (0,)) + brlev = ([0, 10, 26], (0,)) + bhrlev = ([1, 0.9989, 0.9970], (0,)) + lblev = ([1, 2, 3], (0,)) + bhlev = ([0.9994, 0.9979, 0.9957], (0,)) + collation = mock.Mock(fields=[field], vector_dims_shape=(3,), + element_arrays_and_dims={'blev': blev, + 'lblev': lblev, + 'brsvd1': brsvd1, + 'brsvd2': brsvd2, + 'brlev': brlev, + 'bhrlev': bhrlev, + 'lblev': lblev, + 'bhlev': bhlev}) + metadata = convert_collation(collation) + factory = iris.fileformats.rules.Factory( + iris.aux_factory.HybridHeightFactory, + [{'long_name': 'level_height'}, {'long_name': 'sigma'}, + iris.fileformats.rules.Reference('orography')]) + self._check_phenomenon(metadata, factory) + coords_and_dims = [(LONGITUDE, 2), + (LATITUDE, 1), + (iris.coords.DimCoord([1, 2, 3], + 'model_level_number', + attributes={'positive': 'up'} + ), + (0,))] + self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) + coords_and_dims = [ + (iris.coords.DimCoord([5, 18, 38], long_name='level_height', + units='m', bounds=[[0, 10], [10, 26], + [26, 50]], + attributes={'positive': 'up'}), (0,)), + (iris.coords.AuxCoord([0.9994, 0.9979, 0.9957], long_name='sigma', + bounds=[[1, 0.9989], [0.9989, 0.9970], + [0.9970, 0.9944]]), (0,)) + ] + self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/fileformats/um/fast_load_structured_fields/__init__.py b/lib/iris/tests/unit/fileformats/um/fast_load_structured_fields/__init__.py new file mode 100644 index 0000000000..6da232322c --- /dev/null +++ b/lib/iris/tests/unit/fileformats/um/fast_load_structured_fields/__init__.py @@ -0,0 +1,24 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the module +:mod:`iris.fileformats.um._fast_load_structured_fields`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/um/fast_load_structured_fields/test_BasicFieldCollation.py b/lib/iris/tests/unit/fileformats/um/fast_load_structured_fields/test_BasicFieldCollation.py new file mode 100644 index 0000000000..087ec53446 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/um/fast_load_structured_fields/test_BasicFieldCollation.py @@ -0,0 +1,216 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the class +:class:`iris.fileformats.um._fast_load_structured_fields.BasicFieldCollation`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised +# before importing anything else. +import iris.tests as tests + +from iris._lazy_data import as_lazy_data +from cftime import datetime +import numpy as np + +from iris.fileformats.um._fast_load_structured_fields \ + import BasicFieldCollation +import iris.fileformats.pp + + +class Test___init__(tests.IrisTest): + def test_no_fields(self): + with self.assertRaises(AssertionError): + BasicFieldCollation([]) + + +class Test_fields(tests.IrisTest): + def test_preserve_members(self): + fields = ('foo', 'bar', 'wibble') + collation = BasicFieldCollation(fields) + self.assertEqual(collation.fields, fields) + + +def _make_field(lbyr=None, lbyrd=None, lbft=None, + blev=None, bhlev=None, data=None): + header = [0] * 64 + if lbyr is not None: + header[0] = lbyr + header[1] = 1 + header[2] = 1 + if lbyrd is not None: + header[6] = lbyrd + header[7] = 1 + header[8] = 1 + if lbft is not None: + header[13] = lbft + if blev is not None: + header[51] = blev + if bhlev is not None: + header[53] = bhlev + field = iris.fileformats.pp.PPField3(header) + if data is not None: + _data = _make_data(data) + field.data = _data + return field + + +def _make_data(fill_value): + shape = (10, 10) + return as_lazy_data(np.ones(shape)*fill_value) + + +class Test_data(tests.IrisTest): + # Test order of the data attribute when fastest-varying element is changed. + def test_t1_varies_faster(self): + collation = BasicFieldCollation( + [_make_field(lbyr=2013, lbyrd=2000, data=0), + _make_field(lbyr=2014, lbyrd=2000, data=1), + _make_field(lbyr=2015, lbyrd=2000, data=2), + _make_field(lbyr=2013, lbyrd=2001, data=3), + _make_field(lbyr=2014, lbyrd=2001, data=4), + _make_field(lbyr=2015, lbyrd=2001, data=5)]) + result = collation.data[:, :, 0, 0] + expected = [[0, 1, 2], [3, 4, 5]] + self.assertArrayEqual(result, expected) + + def test_t2_varies_faster(self): + collation = BasicFieldCollation( + [_make_field(lbyr=2013, lbyrd=2000, data=0), + _make_field(lbyr=2013, lbyrd=2001, data=1), + _make_field(lbyr=2013, lbyrd=2002, data=2), + _make_field(lbyr=2014, lbyrd=2000, data=3), + _make_field(lbyr=2014, lbyrd=2001, data=4), + _make_field(lbyr=2014, lbyrd=2002, data=5)]) + result = collation.data[:, :, 0, 0] + expected = [[0, 1, 2], [3, 4, 5]] + self.assertArrayEqual(result, expected) + + +class Test_element_arrays_and_dims(tests.IrisTest): + def test_single_field(self): + field = _make_field(2013) + collation = BasicFieldCollation([field]) + self.assertEqual(collation.element_arrays_and_dims, {}) + + def test_t1(self): + collation = BasicFieldCollation([_make_field(lbyr=2013), + _make_field(lbyr=2014)]) + result = collation.element_arrays_and_dims + self.assertEqual(list(result.keys()), ['t1']) + values, dims = result['t1'] + self.assertArrayEqual(values, [datetime(2013, 1, 1), + datetime(2014, 1, 1)]) + self.assertEqual(dims, (0,)) + + def test_t1_and_t2(self): + collation = BasicFieldCollation([_make_field(lbyr=2013, lbyrd=2000), + _make_field(lbyr=2014, lbyrd=2001), + _make_field(lbyr=2015, lbyrd=2002)]) + result = collation.element_arrays_and_dims + self.assertEqual(set(result.keys()), set(['t1', 't2'])) + values, dims = result['t1'] + self.assertArrayEqual(values, [datetime(2013, 1, 1), + datetime(2014, 1, 1), + datetime(2015, 1, 1)]) + self.assertEqual(dims, (0,)) + values, dims = result['t2'] + self.assertArrayEqual(values, [datetime(2000, 1, 1), + datetime(2001, 1, 1), + datetime(2002, 1, 1)]) + self.assertEqual(dims, (0,)) + + def test_t1_and_t2_and_lbft(self): + collation = BasicFieldCollation( + [_make_field(lbyr=1, lbyrd=15, lbft=6), + _make_field(lbyr=1, lbyrd=16, lbft=9), + _make_field(lbyr=11, lbyrd=25, lbft=6), + _make_field(lbyr=11, lbyrd=26, lbft=9)]) + result = collation.element_arrays_and_dims + self.assertEqual(set(result.keys()), set(['t1', 't2', 'lbft'])) + values, dims = result['t1'] + self.assertArrayEqual(values, [datetime(1, 1, 1), + datetime(11, 1, 1)]) + self.assertEqual(dims, (0,)) + values, dims = result['t2'] + self.assertArrayEqual(values, + [[datetime(15, 1, 1), datetime(16, 1, 1)], + [datetime(25, 1, 1), datetime(26, 1, 1)]]) + self.assertEqual(dims, (0, 1)) + values, dims = result['lbft'] + self.assertArrayEqual(values, [6, 9]) + self.assertEqual(dims, (1,)) + + def test_blev(self): + collation = BasicFieldCollation([_make_field(blev=1), + _make_field(blev=2)]) + result = collation.element_arrays_and_dims + keys = set(['blev', 'brsvd1', 'brsvd2', 'brlev', + 'bhrlev', 'lblev', 'bhlev']) + self.assertEqual(set(result.keys()), keys) + values, dims = result['blev'] + self.assertArrayEqual(values, [1, 2]) + self.assertEqual(dims, (0,)) + + def test_bhlev(self): + collation = BasicFieldCollation([_make_field(blev=0, bhlev=1), + _make_field(blev=1, bhlev=2)]) + result = collation.element_arrays_and_dims + keys = set(['blev', 'brsvd1', 'brsvd2', 'brlev', + 'bhrlev', 'lblev', 'bhlev']) + self.assertEqual(set(result.keys()), keys) + values, dims = result['bhlev'] + self.assertArrayEqual(values, [1, 2]) + self.assertEqual(dims, (0,)) + + +class Test__time_comparable_int(tests.IrisTest): + def test(self): + # Define a list of date-time tuples, which should remain both all + # distinct and in ascending order when converted... + test_date_tuples = [ + # Increment each component in turn to check that all are handled. + (2004, 1, 1, 0, 0, 0), + (2004, 1, 1, 0, 0, 1), + (2004, 1, 1, 0, 1, 0), + (2004, 1, 1, 1, 0, 0), + (2004, 1, 2, 0, 0, 0), + (2004, 2, 1, 0, 0, 0), + # Go across 2004-02-29 leap-day, and on to "Feb 31 .. Mar 1". + (2004, 2, 27, 0, 0, 0), + (2004, 2, 28, 0, 0, 0), + (2004, 2, 29, 0, 0, 0), + (2004, 2, 30, 0, 0, 0), + (2004, 2, 31, 0, 0, 0), + (2004, 3, 1, 0, 0, 0), + (2005, 1, 1, 0, 0, 0)] + + collation = BasicFieldCollation(['foo', 'bar']) + test_date_ints = [collation._time_comparable_int(*test_tuple) + for test_tuple in test_date_tuples] + # Check all values are distinct. + self.assertEqual(len(test_date_ints), len(set(test_date_ints), )) + # Check all values are in order. + self.assertEqual(test_date_ints, sorted(test_date_ints)) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/um/fast_load_structured_fields/test_group_structured_fields.py b/lib/iris/tests/unit/fileformats/um/fast_load_structured_fields/test_group_structured_fields.py new file mode 100644 index 0000000000..0d3413189c --- /dev/null +++ b/lib/iris/tests/unit/fileformats/um/fast_load_structured_fields/test_group_structured_fields.py @@ -0,0 +1,144 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the function :func:\ +`iris.fileformats.um._fast_load_structured_fields.group_structured_fields`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised +# before importing anything else. +import iris.tests as tests + +import numpy as np + +import iris +from iris.fileformats.um._fast_load_structured_fields import \ + group_structured_fields +from iris.tests import mock + + +def _convert_to_vector(value, length, default): + """ + Return argument (or default) in a list of length 'length'. + + The 'value' arg must either be scalar, or a list of length 'length'. + A value of None is replaced by the default. + If scalar, the value is replicated to the required length. + + """ + if value is None: + value = default + if hasattr(value, '__len__'): + assert len(value) == length + else: + value = [value] * length + return value + + +class Test__grouping(tests.IrisTest): + def _dummy_fields_iter(self, stashes=None, models=None, lbprocs=None): + # Make a group of test fields, and return an iterator over it. + a_vec = [vec for vec in (stashes, models, lbprocs) if vec is not None] + number = len(a_vec[0]) + stashes = _convert_to_vector(stashes, number, default=31) + models = _convert_to_vector(models, number, default=71) + lbprocs = _convert_to_vector(lbprocs, number, default=91) + self.test_fields = [ + mock.MagicMock(lbuser=[0, 0, 0, x_stash, 0, 0, x_model], + lbproc=x_lbproc, + i_field=ind + 1001) + for ind, x_stash, x_model, x_lbproc in zip( + range(number), stashes, models, lbprocs)] + return (fld for fld in self.test_fields) + + def _group_result(self, fields): + # Run the testee, but returning just the groups (not FieldCollations). + result = list(group_structured_fields(fields, collation_class=tuple)) + return result + + def _test_fields(self, item): + # Convert nested tuples/lists of field-numbers into fields. + if isinstance(item, int): + result = self.test_fields[item - 1001] + else: + result = type(item)(self._test_fields(el) for el in item) + return result + + def test_none(self): + null_iter = (x for x in []) + result = self._group_result(null_iter) + self.assertEqual(result, []) + + def test_one(self): + fields_iter = self._dummy_fields_iter(stashes=[1]) + result = self._group_result(fields_iter) + self.assertEqual(result, self._test_fields([(1001,)])) + + def test_allsame(self): + fields_iter = self._dummy_fields_iter(stashes=[1, 1, 1]) + result = self._group_result(fields_iter) + self.assertEqual(result, self._test_fields([(1001, 1002, 1003)])) + + def test_stashes_different(self): + fields_iter = self._dummy_fields_iter(stashes=[1, 1, 22, 1, 22, 333]) + result = self._group_result(fields_iter) + self.assertEqual(result, self._test_fields([(1001, 1002, 1004), + (1003, 1005), + (1006,)])) + + def test_models_different(self): + fields_iter = self._dummy_fields_iter(models=[10, 21, 10]) + result = self._group_result(fields_iter) + self.assertEqual(result, self._test_fields([(1001, 1003), (1002,)])) + + def test_lbprocs_different(self): + fields_iter = self._dummy_fields_iter(lbprocs=[991, 995, 991]) + result = self._group_result(fields_iter) + self.assertEqual(result, self._test_fields([(1001, 1003), (1002,)])) + + def test_2d_combines(self): + fields_iter = self._dummy_fields_iter( + stashes=[11, 11, 15, 11], + lbprocs=[31, 42, 31, 42]) + result = self._group_result(fields_iter) + self.assertEqual(result, self._test_fields([(1001,), + (1002, 1004), + (1003,)])) + + def test_sortorder(self): + fields_iter = self._dummy_fields_iter(stashes=[11, 7, 12]) + result = self._group_result(fields_iter) + self.assertEqual(result, self._test_fields([(1002,), + (1001,), + (1003,)])) + + def test_sortorder_2d(self): + fields_iter = self._dummy_fields_iter( + stashes=[11, 11, 12], + lbprocs=[31, 9, 1]) + result = self._group_result(fields_iter) + self.assertEqual(result, self._test_fields([(1002,), + (1001,), + (1003,)])) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/um/optimal_array_structuring/__init__.py b/lib/iris/tests/unit/fileformats/um/optimal_array_structuring/__init__.py new file mode 100644 index 0000000000..e2bd3f6190 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/um/optimal_array_structuring/__init__.py @@ -0,0 +1,24 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the module +:mod:`iris.fileformats.um._optimal_array_structuring`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/um/optimal_array_structuring/test_optimal_array_structure.py b/lib/iris/tests/unit/fileformats/um/optimal_array_structuring/test_optimal_array_structure.py new file mode 100644 index 0000000000..8558bb763a --- /dev/null +++ b/lib/iris/tests/unit/fileformats/um/optimal_array_structuring/test_optimal_array_structure.py @@ -0,0 +1,219 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the function +:func:`iris.fileformats.um._optimal_array_structuring.optimal_array_structure`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised +# before importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.fileformats.um._optimal_array_structuring import \ + optimal_array_structure, _optimal_dimensioning_structure + + +class Test__optimal_dimensioning_structure(object): + pass + + +class Test_optimal_array_structure(tests.IrisTest): + def _check_arrays_and_dims(self, result, spec): + self.assertEqual(set(result.keys()), set(spec.keys())) + for keyname in spec.keys(): + result_array, result_dims = result[keyname] + spec_array, spec_dims = spec[keyname] + self.assertEqual(result_dims, spec_dims, + 'element dims differ for "{}": ' + 'result={!r}, expected {!r}'.format( + keyname, result_dims, spec_dims)) + self.assertArrayEqual(result_array, spec_array, + 'element arrays differ for "{}": ' + 'result={!r}, expected {!r}'.format( + keyname, result_array, spec_array)) + + def test_none(self): + with self.assertRaises(IndexError): + result = optimal_array_structure([], []) + + def test_one(self): + # A single value does not make a dimension (no length-1 dims). + elements = [('a', np.array([1]))] + shape, primaries, elems_and_dims = optimal_array_structure(elements) + self.assertEqual(shape, ()) + self.assertEqual(primaries, set()) + self.assertEqual(elems_and_dims, {}) + + def test_1d(self): + elements = [('a', np.array([1, 2, 4]))] + shape, primaries, elems_and_dims = optimal_array_structure(elements) + self.assertEqual(shape, (3,)) + self.assertEqual(primaries, set('a')) + self._check_arrays_and_dims(elems_and_dims, + {'a': (np.array([1, 2, 4]), (0,))}) + + def test_1d_actuals(self): + # Test use of alternate element values for array construction. + elements = [('a', np.array([1, 2, 4]))] + actual_values = [('a', np.array([7, 3, 9]))] + shape, primaries, elems_and_dims = optimal_array_structure( + elements, actual_values) + self.assertEqual(shape, (3,)) + self.assertEqual(primaries, set('a')) + self._check_arrays_and_dims(elems_and_dims, + {'a': (np.array([7, 3, 9]), (0,))}) + + def test_actuals_mismatch_fail(self): + elements = [('a', np.array([1, 2, 4]))] + actual_values = [('b', np.array([7, 3, 9]))] + with self.assertRaisesRegexp(ValueError, 'Names.* do not match.*'): + shape, primaries, elems_and_dims = optimal_array_structure( + elements, actual_values) + + def test_2d(self): + elements = [('a', np.array([2, 2, 2, 3, 3, 3])), + ('b', np.array([7, 8, 9, 7, 8, 9]))] + shape, primaries, elems_and_dims = optimal_array_structure(elements) + self.assertEqual(shape, (2, 3,)) + self.assertEqual(primaries, set(['a', 'b'])) + self._check_arrays_and_dims(elems_and_dims, + {'a': (np.array([2, 3]), (0,)), + 'b': (np.array([7, 8, 9]), (1,))}) + + def test_2d_with_element_values(self): + # Confirm that elements values are used in the output when supplied. + elements = [('a', np.array([2, 2, 2, 3, 3, 3])), + ('b', np.array([7, 8, 9, 7, 8, 9]))] + elements_values = [('a', np.array([6, 6, 6, 8, 8, 8])), + ('b', np.array([3, 4, 5, 3, 4, 5]))] + shape, primaries, elems_and_dims = \ + optimal_array_structure(elements, elements_values) + self.assertEqual(shape, (2, 3,)) + self.assertEqual(primaries, set(['a', 'b'])) + self._check_arrays_and_dims(elems_and_dims, + {'a': (np.array([6, 8]), (0,)), + 'b': (np.array([3, 4, 5]), (1,))}) + + def test_non_2d(self): + # An incomplete 2d expansion just becomes 1d + elements = [('a', np.array([2, 2, 2, 3, 3])), + ('b', np.array([7, 8, 9, 7, 8]))] + shape, primaries, elems_and_dims = optimal_array_structure(elements) + self.assertEqual(shape, (5,)) + self.assertEqual(primaries, set()) + self._check_arrays_and_dims(elems_and_dims, + {'a': (np.array([2, 2, 2, 3, 3]), (0,)), + 'b': (np.array([7, 8, 9, 7, 8]), (0,))}) + + def test_degenerate(self): + # A all-same vector does not appear in the output. + elements = [('a', np.array([1, 2, 3])), + ('b', np.array([4, 4, 4]))] + shape, primaries, elems_and_dims = optimal_array_structure(elements) + self.assertEqual(shape, (3,)) + self.assertEqual(primaries, set(['a'])) + self._check_arrays_and_dims(elems_and_dims, + {'a': (np.array([1, 2, 3]), (0,))}) + + def test_1d_duplicates(self): + # When two have the same structure, the first is 'the dimension'. + elements = [('a', np.array([1, 3, 4])), + ('b', np.array([6, 7, 9]))] + shape, primaries, elems_and_dims = optimal_array_structure(elements) + self.assertEqual(shape, (3,)) + self.assertEqual(primaries, set('a')) + self._check_arrays_and_dims(elems_and_dims, + {'a': (np.array([1, 3, 4]), (0,)), + 'b': (np.array([6, 7, 9]), (0,))}) + + def test_1d_duplicates_order(self): + # Same as previous but reverse passed order of elements 'a' and 'b'. + elements = [('b', np.array([6, 7, 9])), + ('a', np.array([1, 3, 4]))] + shape, primaries, elems_and_dims = optimal_array_structure(elements) + self.assertEqual(shape, (3,)) + # The only difference is the one chosen as 'principal' + self.assertEqual(primaries, set('b')) + self._check_arrays_and_dims(elems_and_dims, + {'a': (np.array([1, 3, 4]), (0,)), + 'b': (np.array([6, 7, 9]), (0,))}) + + def test_3_way(self): + elements = [('t1', np.array([2, 3, 4])), + ('t2', np.array([4, 5, 6])), + ('period', np.array([9, 8, 7]))] + shape, primaries, elems_and_dims = optimal_array_structure(elements) + self.assertEqual(shape, (3,)) + self.assertEqual(primaries, set(['t1'])) + self._check_arrays_and_dims(elems_and_dims, + {'t1': (np.array([2, 3, 4]), (0,)), + 't2': (np.array([4, 5, 6]), (0,)), + 'period': (np.array([9, 8, 7]), (0,))}) + + def test_mixed_dims(self): + elements = [('t1', np.array([1, 1, 11, 11])), + ('t2', np.array([15, 16, 25, 26])), + ('ft', np.array([15, 16, 15, 16]))] + shape, primaries, elems_and_dims = optimal_array_structure(elements) + self.assertEqual(shape, (2, 2)) + self.assertEqual(primaries, set(['t1', 'ft'])) + self._check_arrays_and_dims( + elems_and_dims, + {'t1': (np.array([1, 11]), (0,)), + 't2': (np.array([[15, 16], [25, 26]]), (0, 1)), + 'ft': (np.array([15, 16]), (1,))}) + + def test_missing_dim(self): + # Case with no dimension element for dimension 1. + elements = [('t1', np.array([1, 1, 11, 11])), + ('t2', np.array([15, 16, 25, 26]))] + shape, primaries, elems_and_dims = optimal_array_structure(elements) + self.assertEqual(shape, (4,)) + # The potential 2d nature can not be recognised. + # 't1' is auxiliary, as it has duplicate values over the dimension. + self.assertEqual(primaries, set(['t2'])) + self._check_arrays_and_dims( + elems_and_dims, + {'t1': (np.array([1, 1, 11, 11]), (0,)), + 't2': (np.array([15, 16, 25, 26]), (0,))}) + + def test_optimal_structure_decision(self): + # Checks the optimal structure decision logic is working correctly: + # given the arrays we have here we would expect 'a' to be the primary + # dimension, as it has higher priority for being supplied first. + elements = [('a', np.array([1, 1, 1, 2, 2, 2])), + ('b', np.array([0, 1, 2, 0, 1, 2])), + ('c', np.array([11, 11, 11, 14, 14, 14])), + ('d', np.array([10, 10, 10, 10, 10, 10]))] + shape, primaries, elems_and_dims = optimal_array_structure(elements) + self.assertEqual(shape, (2, 3)) + self.assertEqual(primaries, set(['a', 'b'])) + self._check_arrays_and_dims( + elems_and_dims, + {'a': (np.array([1, 2]), (0,)), + 'c': (np.array([11, 14]), (0,)), + 'b': (np.array([0, 1, 2]), (1,))}) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/um/test_um_to_pp.py b/lib/iris/tests/unit/fileformats/um/test_um_to_pp.py new file mode 100644 index 0000000000..2bd932220e --- /dev/null +++ b/lib/iris/tests/unit/fileformats/um/test_um_to_pp.py @@ -0,0 +1,65 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the function +:func:`iris.fileformats.um.um_to_pp`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised +# before importing anything else. +import iris.tests as tests + +from iris.fileformats.um import um_to_pp +from iris.tests import mock + + +class Test_call(tests.IrisTest): + def test__call(self): + # Check that the function creates an FF2PP and returns the result + # of iterating over it. + + # Make a real (test) iterator object, as otherwise iter() complains... + mock_iterator = (1 for x in ()) + # Make a mock for the iter() call of an FF2PP object. + mock_iter_call = mock.MagicMock(return_value=mock_iterator) + # Make a mock FF2PP object instance. + mock_ff2pp_instance = mock.MagicMock(__iter__=mock_iter_call) + # Make the mock FF2PP class. + mock_ff2pp_class = mock.MagicMock(return_value=mock_ff2pp_instance) + + # Call um_to_pp while patching the um._ff_replacement.FF2PP class. + test_path = '/any/old/file.name' + with mock.patch('iris.fileformats.um._ff_replacement.FF2PP', + mock_ff2pp_class): + result = um_to_pp(test_path) + + # Check that it called FF2PP in the expected way. + self.assertEqual(mock_ff2pp_class.call_args_list, + [mock.call('/any/old/file.name', read_data=False)]) + self.assertEqual(mock_ff2pp_instance.__iter__.call_args_list, + [mock.call()]) + + # Check that it returned the expected result. + self.assertIs(result, mock_iterator) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/io/__init__.py b/lib/iris/tests/unit/io/__init__.py index cbce8a7f0b..200e0a3189 100644 --- a/lib/iris/tests/unit/io/__init__.py +++ b/lib/iris/tests/unit/io/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2014, Met Office +# (C) British Crown Copyright 2014 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Unit tests for the :mod:`iris.io` package.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/io/test_expand_filespecs.py b/lib/iris/tests/unit/io/test_expand_filespecs.py new file mode 100644 index 0000000000..d27ff5a8e7 --- /dev/null +++ b/lib/iris/tests/unit/io/test_expand_filespecs.py @@ -0,0 +1,102 @@ +# (C) British Crown Copyright 2017 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.io.expand_filespecs` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import os +import tempfile +import shutil +import textwrap + +import iris.io as iio + + +class TestExpandFilespecs(tests.IrisTest): + def setUp(self): + tests.IrisTest.setUp(self) + self.tmpdir = os.path.realpath(tempfile.mkdtemp()) + self.fnames = ['a.foo', 'b.txt'] + for fname in self.fnames: + with open(os.path.join(self.tmpdir, fname), 'w') as fh: + fh.write('anything') + + def tearDown(self): + shutil.rmtree(self.tmpdir) + + def test_absolute_path(self): + result = iio.expand_filespecs([os.path.join(self.tmpdir, '*')]) + expected = [os.path.join(self.tmpdir, fname) for fname in self.fnames] + self.assertEqual(result, expected) + + def test_double_slash(self): + product = iio.expand_filespecs(['//' + os.path.join(self.tmpdir, '*')]) + predicted = [os.path.join(self.tmpdir, fname) for fname in self.fnames] + self.assertEqual(product, predicted) + + def test_relative_path(self): + cwd = os.getcwd() + try: + os.chdir(self.tmpdir) + item_out = iio.expand_filespecs(['*']) + item_in = [os.path.join(self.tmpdir, fname) + for fname in self.fnames] + self.assertEqual(item_out, item_in) + finally: + os.chdir(cwd) + + def test_return_order(self): + # It is really quite important what order we return the + # files. They should be in the order that was provided, + # so that we can control the order of load (for instance, + # this can be used with PP files to ensure that there is + # a surface reference). + patterns = [os.path.join(self.tmpdir, 'a.*'), + os.path.join(self.tmpdir, 'b.*')] + expected = [os.path.join(self.tmpdir, fname) + for fname in ['a.foo', 'b.txt']] + result = iio.expand_filespecs(patterns) + self.assertEqual(result, expected) + result = iio.expand_filespecs(patterns[::-1]) + self.assertEqual(result, expected[::-1]) + + def test_no_files_found(self): + msg = r'\/no_exist.txt\" didn\'t match any files' + with self.assertRaisesRegexp(IOError, msg): + iio.expand_filespecs([os.path.join(self.tmpdir, 'no_exist.txt')]) + + def test_files_and_none(self): + with self.assertRaises(IOError) as err: + iio.expand_filespecs( + [os.path.join(self.tmpdir, 'does_not_exist.txt'), + os.path.join(self.tmpdir, '*')]) + expected = textwrap.dedent(""" + One or more of the files specified did not exist: + * "{0}/does_not_exist.txt" didn\'t match any files + - "{0}/*" matched 2 file(s) + """).strip().format(self.tmpdir) + + self.assertStringEqual(str(err.exception), expected) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/io/test_run_callback.py b/lib/iris/tests/unit/io/test_run_callback.py index 841fe95d4f..ce69f479c1 100644 --- a/lib/iris/tests/unit/io/test_run_callback.py +++ b/lib/iris/tests/unit/io/test_run_callback.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2014, Met Office +# (C) British Crown Copyright 2014 - 2015, Met Office # # This file is part of Iris. # @@ -16,13 +16,16 @@ # along with Iris. If not, see . """Unit tests for the `iris.io.run_callback` function.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests -import mock import iris.exceptions import iris.io +from iris.tests import mock class Test_run_callback(tests.IrisTest): @@ -68,7 +71,9 @@ def test_bad_signature(self): def callback(cube): pass with self.assertRaisesRegexp(TypeError, - 'takes exactly 1 argument '): + # exactly == Py2, positional == Py3 + 'takes (exactly )?1 (positional )?' + 'argument '): iris.io.run_callback(callback, None, None, None) def test_callback_args(self): diff --git a/lib/iris/tests/unit/lazy_data/__init__.py b/lib/iris/tests/unit/lazy_data/__init__.py new file mode 100644 index 0000000000..9eed1ff4c0 --- /dev/null +++ b/lib/iris/tests/unit/lazy_data/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris._lazy_data` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/lazy_data/test_as_concrete_data.py b/lib/iris/tests/unit/lazy_data/test_as_concrete_data.py new file mode 100644 index 0000000000..3d64e038b5 --- /dev/null +++ b/lib/iris/tests/unit/lazy_data/test_as_concrete_data.py @@ -0,0 +1,95 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Test function :func:`iris._lazy data.as_concrete_data`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np +import numpy.ma as ma + +from iris._lazy_data import as_concrete_data, as_lazy_data, is_lazy_data +from iris.tests import mock + + +class MyProxy(object): + def __init__(self, a): + self.shape = a.shape + self.dtype = a.dtype + self.a = a + + def __getitem__(self, keys): + return self.a[keys] + + +class Test_as_concrete_data(tests.IrisTest): + def test_concrete_input_data(self): + data = np.arange(24).reshape((4, 6)) + result = as_concrete_data(data) + self.assertIs(data, result) + self.assertFalse(is_lazy_data(result)) + + def test_concrete_masked_input_data(self): + data = ma.masked_array([10, 12, 8, 2], mask=[True, True, False, True]) + result = as_concrete_data(data) + self.assertIs(data, result) + self.assertFalse(is_lazy_data(result)) + + def test_lazy_data(self): + data = np.arange(24).reshape((2, 12)) + lazy_array = as_lazy_data(data) + self.assertTrue(is_lazy_data(lazy_array)) + result = as_concrete_data(lazy_array) + self.assertFalse(is_lazy_data(result)) + self.assertArrayEqual(result, data) + + def test_lazy_mask_data(self): + data = np.arange(24).reshape((2, 12)) + fill_value = 1234 + mask_data = ma.masked_array(data, fill_value=fill_value) + lazy_array = as_lazy_data(mask_data) + self.assertTrue(is_lazy_data(lazy_array)) + result = as_concrete_data(lazy_array) + self.assertFalse(is_lazy_data(result)) + self.assertMaskedArrayEqual(result, mask_data) + self.assertEqual(result.fill_value, fill_value) + + def test_lazy_scalar_proxy(self): + a = np.array(5) + proxy = MyProxy(a) + lazy_array = as_lazy_data(proxy) + self.assertTrue(is_lazy_data(lazy_array)) + result = as_concrete_data(lazy_array) + self.assertFalse(is_lazy_data(result)) + self.assertEqual(result, a) + + def test_lazy_scalar_proxy_masked(self): + a = np.ma.masked_array(5, True) + proxy = MyProxy(a) + lazy_array = as_lazy_data(proxy) + self.assertTrue(is_lazy_data(lazy_array)) + result = as_concrete_data(lazy_array) + self.assertFalse(is_lazy_data(result)) + self.assertMaskedArrayEqual(result, a) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/lazy_data/test_as_lazy_data.py b/lib/iris/tests/unit/lazy_data/test_as_lazy_data.py new file mode 100644 index 0000000000..7acb0b6284 --- /dev/null +++ b/lib/iris/tests/unit/lazy_data/test_as_lazy_data.py @@ -0,0 +1,113 @@ +# (C) British Crown Copyright 2017 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Test the function :func:`iris._lazy data.as_lazy_data`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import dask.array as da +import numpy as np +import numpy.ma as ma + +from iris._lazy_data import as_lazy_data, _MAX_CHUNK_SIZE, _limited_shape +from iris.tests import mock + + +class Test_as_lazy_data(tests.IrisTest): + def test_lazy(self): + data = da.from_array(np.arange(24).reshape((2, 3, 4)), + chunks=_MAX_CHUNK_SIZE) + result = as_lazy_data(data) + self.assertIsInstance(result, da.core.Array) + + def test_real(self): + data = np.arange(24).reshape((2, 3, 4)) + result = as_lazy_data(data) + self.assertIsInstance(result, da.core.Array) + + def test_masked(self): + data = np.ma.masked_greater(np.arange(24), 10) + result = as_lazy_data(data) + self.assertIsInstance(result, da.core.Array) + + def test_non_default_chunks(self): + data = np.arange(24) + chunks = 12 + lazy_data = as_lazy_data(data, chunks=chunks) + result, = np.unique(lazy_data.chunks) + self.assertEqual(result, chunks) + + def test_non_default_chunks__chunks_already_set(self): + chunks = 12 + data = da.from_array(np.arange(24), chunks=chunks) + lazy_data = as_lazy_data(data) + result, = np.unique(lazy_data.chunks) + self.assertEqual(result, chunks) + + def test_with_masked_constant(self): + masked_data = ma.masked_array([8], mask=True) + masked_constant = masked_data[0] + result = as_lazy_data(masked_constant) + self.assertIsInstance(result, da.core.Array) + + @staticmethod + def _dummydata(shape): + return mock.Mock(spec=da.core.Array, + dtype=np.dtype('f4'), + shape=shape) + + def test_chunk_size_limiting(self): + # Check the default chunksizes for large data. + given_shapes_and_resulting_chunks = [ + ((16, 1024, 1024), (16, 1024, 1024)), # largest unmodified + ((17, 1011, 1022), (8, 1011, 1022)), + ((16, 1024, 1025), (8, 1024, 1025)), + ((1, 17, 1011, 1022), (1, 8, 1011, 1022)), + ((17, 1, 1011, 1022), (8, 1, 1011, 1022)), + ((11, 2, 1011, 1022), (5, 2, 1011, 1022)) + ] + err_fmt = 'Result of reducing shape {} was {}, expected {}' + for (shape, expected) in given_shapes_and_resulting_chunks: + chunks = _limited_shape(shape) + msg = err_fmt.format(shape, chunks, expected) + self.assertEqual(chunks, expected, msg) + + def test_default_chunks_limiting(self): + # Check that chunking is limited when no specific 'chunks' given. + limitcall_patch = self.patch('iris._lazy_data._limited_shape') + test_shape = (3, 2, 4) + data = self._dummydata(test_shape) + as_lazy_data(data) + self.assertEqual(limitcall_patch.call_args_list, + [mock.call(test_shape)]) + + def test_large_specific_chunk_passthrough(self): + # Check that even a too-large specific 'chunks' arg is honoured. + limitcall_patch = self.patch('iris._lazy_data._limited_shape') + huge_test_shape = (1001, 1002, 1003, 1004) + data = self._dummydata(huge_test_shape) + result = as_lazy_data(data, chunks=huge_test_shape) + self.assertEqual(limitcall_patch.call_args_list, []) + self.assertEqual(result.shape, huge_test_shape) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/lazy_data/test_co_realise_cubes.py b/lib/iris/tests/unit/lazy_data/test_co_realise_cubes.py new file mode 100644 index 0000000000..03782cda85 --- /dev/null +++ b/lib/iris/tests/unit/lazy_data/test_co_realise_cubes.py @@ -0,0 +1,86 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Test function :func:`iris._lazy data.co_realise_cubes`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from mock import MagicMock +import numpy as np + +from iris.cube import Cube +from iris._lazy_data import as_lazy_data + +from iris._lazy_data import co_realise_cubes + + +class ArrayAccessCounter(object): + def __init__(self, array): + self.dtype = array.dtype + self.shape = array.shape + self._array = array + self.access_count = 0 + + def __getitem__(self, keys): + self.access_count += 1 + return self._array[keys] + + +class Test_co_realise_cubes(tests.IrisTest): + def test_empty(self): + # Ensure that 'no args' case does not raise an error. + co_realise_cubes() + + def test_basic(self): + real_data = np.arange(3.) + cube = Cube(as_lazy_data(real_data)) + co_realise_cubes(cube) + self.assertFalse(cube.has_lazy_data()) + self.assertArrayAllClose(cube.core_data(), real_data) + + def test_multi(self): + real_data = np.arange(3.) + cube_base = Cube(as_lazy_data(real_data)) + cube_inner = cube_base + 1 + result_a = cube_base + 1 + result_b = cube_inner + 1 + co_realise_cubes(result_a, result_b) + # Check that target cubes were realised. + self.assertFalse(result_a.has_lazy_data()) + self.assertFalse(result_b.has_lazy_data()) + # Check that other cubes referenced remain lazy. + self.assertTrue(cube_base.has_lazy_data()) + self.assertTrue(cube_inner.has_lazy_data()) + + def test_combined_access(self): + wrapped_array = ArrayAccessCounter(np.arange(3.)) + lazy_array = as_lazy_data(wrapped_array) + derived_a = lazy_array + 1 + derived_b = lazy_array + 2 + cube_a = Cube(derived_a) + cube_b = Cube(derived_b) + co_realise_cubes(cube_a, cube_b) + # Though used twice, the source data should only get fetched once. + self.assertEqual(wrapped_array.access_count, 1) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/lazy_data/test_is_lazy_data.py b/lib/iris/tests/unit/lazy_data/test_is_lazy_data.py new file mode 100644 index 0000000000..40ef6213ff --- /dev/null +++ b/lib/iris/tests/unit/lazy_data/test_is_lazy_data.py @@ -0,0 +1,44 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Test function :func:`iris._lazy data.is_lazy_data`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import dask.array as da +import numpy as np + +from iris._lazy_data import is_lazy_data, _MAX_CHUNK_SIZE + + +class Test_is_lazy_data(tests.IrisTest): + def test_lazy(self): + values = np.arange(30).reshape((2, 5, 3)) + lazy_array = da.from_array(values, chunks=_MAX_CHUNK_SIZE) + self.assertTrue(is_lazy_data(lazy_array)) + + def test_real(self): + real_array = np.arange(24).reshape((2, 3, 4)) + self.assertFalse(is_lazy_data(real_array)) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/lazy_data/test_lazy_elementwise.py b/lib/iris/tests/unit/lazy_data/test_lazy_elementwise.py new file mode 100644 index 0000000000..e813320758 --- /dev/null +++ b/lib/iris/tests/unit/lazy_data/test_lazy_elementwise.py @@ -0,0 +1,65 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Test function :func:`iris._lazy data.lazy_elementwise`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris._lazy_data import as_lazy_data, is_lazy_data + +from iris._lazy_data import lazy_elementwise + + +def _test_elementwise_op(array): + # Promotes the type of a bool argument, but not a float. + return array + 1 + + +class Test_lazy_elementwise(tests.IrisTest): + def test_basic(self): + concrete_array = np.arange(30).reshape((2, 5, 3)) + lazy_array = as_lazy_data(concrete_array) + wrapped = lazy_elementwise(lazy_array, _test_elementwise_op) + self.assertTrue(is_lazy_data(wrapped)) + self.assertArrayAllClose(wrapped.compute(), + _test_elementwise_op(concrete_array)) + + def test_dtype_same(self): + concrete_array = np.array([3.], dtype=np.float16) + lazy_array = as_lazy_data(concrete_array) + wrapped = lazy_elementwise(lazy_array, _test_elementwise_op) + self.assertTrue(is_lazy_data(wrapped)) + self.assertEqual(wrapped.dtype, np.float16) + self.assertEqual(wrapped.compute().dtype, np.float16) + + def test_dtype_change(self): + concrete_array = np.array([True, False]) + lazy_array = as_lazy_data(concrete_array) + wrapped = lazy_elementwise(lazy_array, _test_elementwise_op) + self.assertTrue(is_lazy_data(wrapped)) + self.assertEqual(wrapped.dtype, np.int) + self.assertEqual(wrapped.compute().dtype, wrapped.dtype) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/lazy_data/test_multidim_lazy_stack.py b/lib/iris/tests/unit/lazy_data/test_multidim_lazy_stack.py new file mode 100644 index 0000000000..6dc409794a --- /dev/null +++ b/lib/iris/tests/unit/lazy_data/test_multidim_lazy_stack.py @@ -0,0 +1,64 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Test function :func:`iris._lazy data.multidim_lazy_stack`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import dask.array as da +import numpy as np + +from iris._lazy_data import as_concrete_data, as_lazy_data, multidim_lazy_stack + + +class Test_multidim_lazy_stack(tests.IrisTest): + def _check(self, stack_shape): + vals = np.arange(np.prod(stack_shape)).reshape(stack_shape) + stack = np.empty(stack_shape, 'object') + # Define the shape of each element in the stack. + stack_element_shape = (4, 5) + expected = np.empty(stack_shape + stack_element_shape, + dtype=int) + for index, val in np.ndenumerate(vals): + stack[index] = as_lazy_data(val * np.ones(stack_element_shape)) + + expected[index] = val + result = multidim_lazy_stack(stack) + self.assertEqual(result.shape, stack_shape + stack_element_shape) + self.assertIsInstance(result, da.core.Array) + result = as_concrete_data(result) + self.assertArrayAllClose(result, expected) + + def test_0d_lazy_stack(self): + shape = () + self._check(shape) + + def test_1d_lazy_stack(self): + shape = (2,) + self._check(shape) + + def test_2d_lazy_stack(self): + shape = (3, 2) + self._check(shape) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/lazy_data/test_non_lazy.py b/lib/iris/tests/unit/lazy_data/test_non_lazy.py new file mode 100644 index 0000000000..7a736a0584 --- /dev/null +++ b/lib/iris/tests/unit/lazy_data/test_non_lazy.py @@ -0,0 +1,51 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Test function :func:`iris._lazy data.non_lazy`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris._lazy_data import as_lazy_data, is_lazy_data, non_lazy + + +class Test_non_lazy(tests.IrisTest): + def setUp(self): + self.array = np.arange(8).reshape(2, 4) + self.lazy_array = as_lazy_data(self.array) + self.func = non_lazy(lambda array: array.sum(axis=0)) + self.func_result = [4, 6, 8, 10] + + def test_lazy_input(self): + result = self.func(self.lazy_array) + self.assertFalse(is_lazy_data(result)) + self.assertArrayEqual(result, self.func_result) + + def test_non_lazy_input(self): + # Check that a non-lazy input doesn't trip up the functionality. + result = self.func(self.array) + self.assertFalse(is_lazy_data(result)) + self.assertArrayEqual(result, self.func_result) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/merge/__init__.py b/lib/iris/tests/unit/merge/__init__.py index e27307e69e..9889079c83 100644 --- a/lib/iris/tests/unit/merge/__init__.py +++ b/lib/iris/tests/unit/merge/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2014, Met Office +# (C) British Crown Copyright 2014 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Unit tests for the :mod:`iris._merge` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/merge/test_ProtoCube.py b/lib/iris/tests/unit/merge/test_ProtoCube.py index 465a3c12c5..2247e2f1e7 100644 --- a/lib/iris/tests/unit/merge/test_ProtoCube.py +++ b/lib/iris/tests/unit/merge/test_ProtoCube.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2014, Met Office +# (C) British Crown Copyright 2014 - 2017, Met Office # # This file is part of Iris. # @@ -16,13 +16,16 @@ # along with Iris. If not, see . """Unit tests for the `iris._merge.ProtoCube` class.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests import abc -import mock import numpy as np import numpy.ma as ma @@ -31,7 +34,7 @@ from iris.aux_factory import HybridHeightFactory, HybridPressureFactory from iris.coords import DimCoord, AuxCoord from iris.exceptions import MergeError -from iris.unit import Unit +from iris.tests import mock def example_cube(): @@ -41,15 +44,13 @@ def example_cube(): units='K', attributes={'mint': 'thin'}) -class Mixin_register(object): - __metaclass__ = abc.ABCMeta - +class Mixin_register(six.with_metaclass(abc.ABCMeta, object)): @property def cube1(self): return example_cube() @abc.abstractproperty - def cube2(): + def cube2(self): pass @abc.abstractproperty @@ -85,7 +86,8 @@ def test_error(self): self.assertTrue(result) -class Test_register__match(Mixin_register, tests.IrisTest): +@tests.iristest_timing_decorator +class Test_register__match(Mixin_register, tests.IrisTest_nometa): @property def fragments(self): return [] @@ -95,7 +97,8 @@ def cube2(self): return example_cube() -class Test_register__standard_name(Mixin_register, tests.IrisTest): +@tests.iristest_timing_decorator +class Test_register__standard_name(Mixin_register, tests.IrisTest_nometa): @property def fragments(self): return ['cube.standard_name', 'air_temperature', 'air_density'] @@ -107,7 +110,8 @@ def cube2(self): return cube -class Test_register__long_name(Mixin_register, tests.IrisTest): +@tests.iristest_timing_decorator +class Test_register__long_name(Mixin_register, tests.IrisTest_nometa): @property def fragments(self): return ['cube.long_name', 'screen_air_temp', 'Belling'] @@ -119,7 +123,8 @@ def cube2(self): return cube -class Test_register__var_name(Mixin_register, tests.IrisTest): +@tests.iristest_timing_decorator +class Test_register__var_name(Mixin_register, tests.IrisTest_nometa): @property def fragments(self): return ['cube.var_name', "'airtemp'", "'airtemp2'"] @@ -131,7 +136,8 @@ def cube2(self): return cube -class Test_register__units(Mixin_register, tests.IrisTest): +@tests.iristest_timing_decorator +class Test_register__units(Mixin_register, tests.IrisTest_nometa): @property def fragments(self): return ['cube.units', "'K'", "'C'"] @@ -143,7 +149,9 @@ def cube2(self): return cube -class Test_register__attributes_unequal(Mixin_register, tests.IrisTest): +@tests.iristest_timing_decorator +class Test_register__attributes_unequal(Mixin_register, + tests.IrisTest_nometa): @property def fragments(self): return ['cube.attributes', "'mint'"] @@ -155,7 +163,9 @@ def cube2(self): return cube -class Test_register__attributes_unequal_array(Mixin_register, tests.IrisTest): +@tests.iristest_timing_decorator +class Test_register__attributes_unequal_array(Mixin_register, + tests.IrisTest_nometa): @property def fragments(self): return ['cube.attributes', "'mint'"] @@ -173,7 +183,9 @@ def cube2(self): return cube -class Test_register__attributes_superset(Mixin_register, tests.IrisTest): +@tests.iristest_timing_decorator +class Test_register__attributes_superset(Mixin_register, + tests.IrisTest_nometa): @property def fragments(self): return ['cube.attributes', "'stuffed'"] @@ -185,7 +197,9 @@ def cube2(self): return cube -class Test_register__attributes_multi_diff(Mixin_register, tests.IrisTest): +@tests.iristest_timing_decorator +class Test_register__attributes_multi_diff(Mixin_register, + tests.IrisTest_nometa): @property def fragments(self): return ['cube.attributes', "'sam'", "'mint'"] @@ -208,7 +222,8 @@ def cube2(self): return cube -class Test_register__cell_method(Mixin_register, tests.IrisTest): +@tests.iristest_timing_decorator +class Test_register__cell_method(Mixin_register, tests.IrisTest_nometa): @property def fragments(self): return ['cube.cell_methods'] @@ -220,7 +235,8 @@ def cube2(self): return cube -class Test_register__data_shape(Mixin_register, tests.IrisTest): +@tests.iristest_timing_decorator +class Test_register__data_shape(Mixin_register, tests.IrisTest_nometa): @property def fragments(self): return ['cube.shape', '(2,)', '(3,)'] @@ -232,7 +248,8 @@ def cube2(self): return cube -class Test_register__data_dtype(Mixin_register, tests.IrisTest): +@tests.iristest_timing_decorator +class Test_register__data_dtype(Mixin_register, tests.IrisTest_nometa): @property def fragments(self): return ['cube data dtype', 'int32', 'int8'] @@ -244,24 +261,6 @@ def cube2(self): return cube -class Test_register__fill_value(Mixin_register, tests.IrisTest): - @property - def fragments(self): - return ['cube data fill_value', '654', '12345'] - - @property - def cube1(self): - cube = example_cube() - cube.data = ma.array(cube.data, fill_value=654) - return cube - - @property - def cube2(self): - cube = example_cube() - cube.data = ma.array(cube.data, fill_value=12345) - return cube - - class _MergeTest(object): # A mixin test class for common test methods implementation. @@ -275,7 +274,7 @@ def check_merge_fails_with_message(self): return str(arc.exception) def check_fail(self, *substrs): - if isinstance(substrs, basestring): + if isinstance(substrs, six.string_types): substrs = [substrs] msg = self.check_merge_fails_with_message() for substr in substrs: @@ -298,7 +297,6 @@ def test_noise(self): cube2 = self.cube1[1:] cube2.data = cube2.data.astype(np.int8) cube2.data = ma.array(cube2.data) - cube2.data.fill_value = 12345 cube2.standard_name = "air_pressure" cube2.var_name = "Nudge" cube2.attributes['stuffed'] = 'yes' @@ -361,6 +359,14 @@ def test_factory_defns_both_extra(self): self.cube1.add_aux_factory(mock.MagicMock(spec=HybridPressureFactory)) self.check_fail("cube.aux_factories", "differ") + def test_factory_defns_one_missing_term(self): + self.cube1.add_aux_factory(mock.MagicMock(spec=HybridPressureFactory)) + no_delta_factory = mock.MagicMock(spec=HybridPressureFactory) + no_delta_factory.delta = None + self.cube2.add_aux_factory(no_delta_factory) + + self.check_fail("cube.aux_factories", "differ") + def test_noise(self): cube2 = self.cube2 diff --git a/lib/iris/tests/unit/plot/__init__.py b/lib/iris/tests/unit/plot/__init__.py new file mode 100644 index 0000000000..459d9b8c64 --- /dev/null +++ b/lib/iris/tests/unit/plot/__init__.py @@ -0,0 +1,124 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.plot` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.plot import _broadcast_2d as broadcast +from iris.coords import AuxCoord +from iris.tests.stock import simple_2d, lat_lon_cube + + +@tests.skip_plot +class TestGraphicStringCoord(tests.GraphicsTest): + def setUp(self): + super(TestGraphicStringCoord, self).setUp() + self.cube = simple_2d(with_bounds=True) + self.cube.add_aux_coord(AuxCoord(list('abcd'), + long_name='str_coord'), 1) + self.lat_lon_cube = lat_lon_cube() + + def tick_loc_and_label(self, axis_name, axes=None): + # Intentional lazy import so that subclasses can have an opportunity + # to change the backend. + import matplotlib.pyplot as plt + + # Draw the plot to 'fix' the ticks. + if axes: + axes.figure.canvas.draw() + else: + axes = plt.gca() + plt.draw() + axis = getattr(axes, axis_name) + + locations = axis.get_majorticklocs() + labels = [tick.get_text() for tick in axis.get_ticklabels()] + return list(zip(locations, labels)) + + def assertBoundsTickLabels(self, axis, axes=None): + actual = self.tick_loc_and_label(axis, axes) + expected = [(-1.0, 'a'), (0.0, 'a'), (1.0, 'b'), + (2.0, 'c'), (3.0, 'd'), (4.0, u'')] + self.assertEqual(expected, actual) + + def assertPointsTickLabels(self, axis, axes=None): + actual = self.tick_loc_and_label(axis, axes) + expected = [(0.0, 'a'), (1.0, 'b'), (2.0, 'c'), (3.0, 'd')] + self.assertEqual(expected, actual) + + +@tests.skip_plot +class MixinCoords(object): + """ + Mixin class of common plotting tests providing 2-dimensional + permutations of coordinates and anonymous dimensions. + + """ + def _check(self, u, v, data=None): + self.assertEqual(self.mpl_patch.call_count, 1) + if data is not None: + (actual_u, actual_v, actual_data), _ = self.mpl_patch.call_args + self.assertArrayEqual(actual_data, data) + else: + (actual_u, actual_v), _ = self.mpl_patch.call_args + self.assertArrayEqual(actual_u, u) + self.assertArrayEqual(actual_v, v) + + def test_foo_bar(self): + self.draw_func(self.cube, coords=('foo', 'bar')) + u, v = broadcast(self.foo, self.bar) + self._check(u, v, self.data) + + def test_bar_foo(self): + self.draw_func(self.cube, coords=('bar', 'foo')) + u, v = broadcast(self.bar, self.foo) + self._check(u, v, self.dataT) + + def test_foo_0(self): + self.draw_func(self.cube, coords=('foo', 0)) + u, v = broadcast(self.foo, self.bar_index) + self._check(u, v, self.data) + + def test_1_bar(self): + self.draw_func(self.cube, coords=(1, 'bar')) + u, v = broadcast(self.foo_index, self.bar) + self._check(u, v, self.data) + + def test_1_0(self): + self.draw_func(self.cube, coords=(1, 0)) + u, v = broadcast(self.foo_index, self.bar_index) + self._check(u, v, self.data) + + def test_0_foo(self): + self.draw_func(self.cube, coords=(0, 'foo')) + u, v = broadcast(self.bar_index, self.foo) + self._check(u, v, self.dataT) + + def test_bar_1(self): + self.draw_func(self.cube, coords=('bar', 1)) + u, v = broadcast(self.bar, self.foo_index) + self._check(u, v, self.dataT) + + def test_0_1(self): + self.draw_func(self.cube, coords=(0, 1)) + u, v = broadcast(self.bar_index, self.foo_index) + self._check(u, v, self.dataT) diff --git a/lib/iris/tests/unit/plot/_blockplot_common.py b/lib/iris/tests/unit/plot/_blockplot_common.py new file mode 100644 index 0000000000..dc69a5c991 --- /dev/null +++ b/lib/iris/tests/unit/plot/_blockplot_common.py @@ -0,0 +1,121 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Common test code for `iris.plot.pcolor` and `iris.plot.pcolormesh`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.tests import mock +from iris.tests.stock import simple_2d +from iris.tests.unit.plot import MixinCoords + + +class MixinStringCoordPlot(object): + # Mixin for common string-coord tests on pcolor/pcolormesh. + # To use, make a class that inherits from this *and* + # :class:`iris.tests.unit.plot.TestGraphicStringCoord`, + # and defines "self.blockplot_func()", to return the `iris.plot` function. + def test_yaxis_labels(self): + self.blockplot_func()(self.cube, coords=('bar', 'str_coord')) + self.assertBoundsTickLabels('yaxis') + + def test_xaxis_labels(self): + self.blockplot_func()(self.cube, coords=('str_coord', 'bar')) + self.assertBoundsTickLabels('xaxis') + + def test_xaxis_labels_with_axes(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + ax.set_xlim(0, 3) + self.blockplot_func()(self.cube, coords=('str_coord', 'bar'), axes=ax) + plt.close(fig) + self.assertPointsTickLabels('xaxis', ax) + + def test_yaxis_labels_with_axes(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + ax.set_ylim(0, 3) + self.blockplot_func()(self.cube, axes=ax, coords=('bar', 'str_coord')) + plt.close(fig) + self.assertPointsTickLabels('yaxis', ax) + + def test_geoaxes_exception(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + self.assertRaises(TypeError, self.blockplot_func(), + self.lat_lon_cube, axes=ax) + plt.close(fig) + + +class Mixin2dCoordsPlot(MixinCoords): + # Mixin for common coordinate tests on pcolor/pcolormesh. + # To use, make a class that inherits from this *and* + # :class:`iris.tests.IrisTest`, + # and defines "self.blockplot_func()", to return the `iris.plot` function. + def blockplot_setup(self): + # We have a 2d cube with dimensionality (bar: 3; foo: 4) + self.cube = simple_2d(with_bounds=True) + coord = self.cube.coord('foo') + self.foo = coord.contiguous_bounds() + self.foo_index = np.arange(coord.points.size + 1) + coord = self.cube.coord('bar') + self.bar = coord.contiguous_bounds() + self.bar_index = np.arange(coord.points.size + 1) + self.data = self.cube.data + self.dataT = self.data.T + self.draw_func = self.blockplot_func() + patch_target_name = 'matplotlib.pyplot.' + self.draw_func.__name__ + self.mpl_patch = self.patch(patch_target_name) + + +class Mixin2dCoordsContigTol(object): + # Mixin for contiguity tolerance argument to pcolor/pcolormesh. + # To use, make a class that inherits from this *and* + # :class:`iris.tests.IrisTest`, + # and defines "self.blockplot_func()", to return the `iris.plot` function, + # and defines "self.additional_kwargs" for expected extra call args. + def test_contig_tol(self): + # Patch the inner call to ensure contiguity_tolerance is passed. + cube_argument = mock.sentinel.passed_arg + expected_result = mock.sentinel.returned_value + blockplot_patch = self.patch( + 'iris.plot._draw_2d_from_bounds', + mock.Mock(return_value=expected_result)) + # Make the call + draw_func = self.blockplot_func() + other_kwargs = self.additional_kwargs + result = draw_func(cube_argument, contiguity_tolerance=0.0123) + drawfunc_name = draw_func.__name__ + # Check details of the call that was made. + self.assertEqual( + blockplot_patch.call_args_list, + [mock.call(drawfunc_name, cube_argument, + contiguity_tolerance=0.0123, **other_kwargs)]) + self.assertEqual(result, expected_result) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/plot/test__check_bounds_contiguity_and_mask.py b/lib/iris/tests/unit/plot/test__check_bounds_contiguity_and_mask.py new file mode 100644 index 0000000000..75c2b5be2f --- /dev/null +++ b/lib/iris/tests/unit/plot/test__check_bounds_contiguity_and_mask.py @@ -0,0 +1,113 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.plot._check_bounds_contiguity_and_mask` +function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import mock + +import numpy as np +import numpy.ma as ma + +from iris.coords import DimCoord +from iris.tests.stock import (sample_2d_latlons, + make_bounds_discontiguous_at_point) + +from iris.plot import _check_bounds_contiguity_and_mask + + +if tests.MPL_AVAILABLE: + import iris.plot as iplt + + +@tests.skip_plot +class Test_check_bounds_contiguity_and_mask(tests.IrisTest): + def test_1d_not_checked(self): + # Test a 1D coordinate, which is not checked as atol is not set. + coord = DimCoord([1, 3, 5], bounds=[[0, 2], [2, 4], [5, 6]]) + data = np.array([278, 300, 282]) + # Make sure contiguity checking doesn't throw an error + _check_bounds_contiguity_and_mask(coord, data) + + def test_1d_contiguous(self): + # Test that a 1D coordinate which is contiguous does not fail. + coord = DimCoord([1, 3, 5], bounds=[[0, 2], [2, 4], [4, 6]]) + data = np.array([278, 300, 282]) + _check_bounds_contiguity_and_mask(coord, data, atol=1e-3) + + def test_1d_discontigous_masked(self): + # Test a 1D coordinate which is discontiguous but masked at + # discontiguities. + coord = DimCoord([1, 3, 5], bounds=[[0, 2], [2, 4], [5, 6]]) + data = ma.array(np.array([278, 300, 282]), mask=[0, 1, 0]) + _check_bounds_contiguity_and_mask(coord, data, atol=1e-3) + + def test_1d_discontigous_unmasked(self): + # Test a 1D coordinate which is discontiguous and unmasked at + # discontiguities. + coord = DimCoord([1, 3, 5], bounds=[[0, 2], [2, 4], [5, 6]]) + data = ma.array(np.array([278, 300, 282]), mask=[1, 0, 0]) + msg = 'coordinate are not contiguous and data is not masked where ' \ + 'the discontiguity occurs' + with self.assertRaisesRegexp(ValueError, msg): + _check_bounds_contiguity_and_mask(coord, data, atol=1e-3) + + def test_2d_contiguous(self): + # Test that a 2D coordinate which is contiguous does not throw + # an error. + cube = sample_2d_latlons() + _check_bounds_contiguity_and_mask(cube.coord('longitude'), cube.data) + + def test_2d_contiguous_atol(self): + # Check the atol is passed correctly. + cube = sample_2d_latlons() + with mock.patch('iris.coords.Coord._discontiguity_in_bounds' + ) as discontiguity_check: + # Discontiguity returns two objects that are unpacked in + # `_check_bounds_contiguity_and_mask`. + discontiguity_check.return_value = [True, None] + _check_bounds_contiguity_and_mask(cube.coord('longitude'), + cube.data, atol=1e-3) + discontiguity_check.assert_called_with(atol=1e-3) + + def test_2d_discontigous_masked(self): + # Test that a 2D coordinate which is discontiguous but masked at + # discontiguities doesn't error. + cube = sample_2d_latlons() + make_bounds_discontiguous_at_point(cube, 3, 4) + _check_bounds_contiguity_and_mask(cube.coord('longitude'), cube.data) + + def test_2d_discontigous_unmasked(self): + # Test a 2D coordinate which is discontiguous and unmasked at + # discontiguities. + cube = sample_2d_latlons() + make_bounds_discontiguous_at_point(cube, 3, 4) + msg = 'coordinate are not contiguous' + cube.data[3, 4] = ma.nomask + with self.assertRaisesRegexp(ValueError, msg): + _check_bounds_contiguity_and_mask(cube.coord('longitude'), + cube.data) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/plot/test__fixup_dates.py b/lib/iris/tests/unit/plot/test__fixup_dates.py new file mode 100644 index 0000000000..15d154d198 --- /dev/null +++ b/lib/iris/tests/unit/plot/test__fixup_dates.py @@ -0,0 +1,88 @@ +# (C) British Crown Copyright 2016 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.plot._fixup_dates` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from cf_units import Unit +import datetime +import cftime + +from iris.coords import AuxCoord +from iris.plot import _fixup_dates + + +class Test(tests.IrisTest): + def coord(self, calendar): + unit = Unit('hours since 2000-04-13 00:00:00', calendar=calendar) + coord = AuxCoord([1, 2, 3], 'time', units=unit) + + def test_gregorian_calendar(self): + unit = Unit('hours since 2000-04-13 00:00:00', calendar='gregorian') + coord = AuxCoord([1, 3, 6], 'time', units=unit) + result = _fixup_dates(coord, coord.points) + expected = [datetime.datetime(2000, 4, 13, 1), + datetime.datetime(2000, 4, 13, 3), + datetime.datetime(2000, 4, 13, 6)] + self.assertArrayEqual(result, expected) + + def test_gregorian_calendar_sub_second(self): + unit = Unit('seconds since 2000-04-13 00:00:00', calendar='gregorian') + coord = AuxCoord([1, 1.25, 1.5], 'time', units=unit) + result = _fixup_dates(coord, coord.points) + expected = [datetime.datetime(2000, 4, 13, 0, 0, 1), + datetime.datetime(2000, 4, 13, 0, 0, 1), + datetime.datetime(2000, 4, 13, 0, 0, 2)] + self.assertArrayEqual(result, expected) + + @tests.skip_nc_time_axis + def test_360_day_calendar(self): + unit = Unit('days since 2000-02-25 00:00:00', calendar='360_day') + coord = AuxCoord([3, 4, 5], 'time', units=unit) + result = _fixup_dates(coord, coord.points) + expected_datetimes = [cftime.datetime(2000, 2, 28), + cftime.datetime(2000, 2, 29), + cftime.datetime(2000, 2, 30)] + self.assertArrayEqual([cdt.datetime for cdt in result], + expected_datetimes) + + @tests.skip_nc_time_axis + def test_365_day_calendar(self): + unit = Unit('minutes since 2000-02-25 00:00:00', calendar='365_day') + coord = AuxCoord([30, 60, 150], 'time', units=unit) + result = _fixup_dates(coord, coord.points) + expected_datetimes = [cftime.datetime(2000, 2, 25, 0, 30), + cftime.datetime(2000, 2, 25, 1, 0), + cftime.datetime(2000, 2, 25, 2, 30)] + self.assertArrayEqual([cdt.datetime for cdt in result], + expected_datetimes) + + @tests.skip_nc_time_axis + def test_360_day_calendar_attribute(self): + unit = Unit('days since 2000-02-01 00:00:00', calendar='360_day') + coord = AuxCoord([0, 3, 6], 'time', units=unit) + result = _fixup_dates(coord, coord.points) + self.assertEqual(result[0].calendar, '360_day') + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/plot/test__get_plot_defn.py b/lib/iris/tests/unit/plot/test__get_plot_defn.py new file mode 100644 index 0000000000..2947933c7d --- /dev/null +++ b/lib/iris/tests/unit/plot/test__get_plot_defn.py @@ -0,0 +1,56 @@ +# (C) British Crown Copyright 2017 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.plot._get_plot_defn` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import iris.coords +from iris.tests.stock import simple_2d, simple_2d_w_multidim_coords + +if tests.MPL_AVAILABLE: + import iris.plot as iplt + + +@tests.skip_plot +class Test_get_plot_defn(tests.IrisTest): + def test_axis_order_xy(self): + cube_xy = simple_2d() + defn = iplt._get_plot_defn(cube_xy, iris.coords.POINT_MODE) + self.assertEqual([coord.name() for coord in defn.coords], + ['bar', 'foo']) + + def test_axis_order_yx(self): + cube_yx = simple_2d() + cube_yx.transpose() + defn = iplt._get_plot_defn(cube_yx, iris.coords.POINT_MODE) + self.assertEqual([coord.name() for coord in defn.coords], + ['foo', 'bar']) + + def test_2d_coords(self): + cube = simple_2d_w_multidim_coords() + defn = iplt._get_plot_defn(cube, iris.coords.BOUND_MODE) + self.assertEqual([coord.name() for coord in defn.coords], + ['bar', 'foo']) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/plot/test__get_plot_defn_custom_coords_picked.py b/lib/iris/tests/unit/plot/test__get_plot_defn_custom_coords_picked.py new file mode 100644 index 0000000000..d0ce55a389 --- /dev/null +++ b/lib/iris/tests/unit/plot/test__get_plot_defn_custom_coords_picked.py @@ -0,0 +1,93 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.plot._get_plot_defn_custom_coords_picked` +function.""" + + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.coords import BOUND_MODE, POINT_MODE +from iris.tests.stock import (simple_2d, simple_2d_w_multidim_coords, + hybrid_height) + + +if tests.MPL_AVAILABLE: + import iris.plot as iplt + + +@tests.skip_plot +class Test_get_plot_defn_custom_coords_picked(tests.IrisTest): + def test_1d_coords(self): + cube = simple_2d() + defn = iplt._get_plot_defn_custom_coords_picked(cube, ('foo', 'bar'), + POINT_MODE) + self.assertEqual([coord.name() for coord in defn.coords], + ['bar', 'foo']) + self.assertFalse(defn.transpose) + + def test_1d_coords_swapped(self): + cube = simple_2d() + defn = iplt._get_plot_defn_custom_coords_picked(cube, ('bar', 'foo'), + POINT_MODE) + self.assertEqual([coord.name() for coord in defn.coords], + ['foo', 'bar']) + self.assertTrue(defn.transpose) + + def test_1d_coords_as_integers(self): + cube = simple_2d() + defn = iplt._get_plot_defn_custom_coords_picked(cube, (1, 0), + POINT_MODE) + self.assertEqual([coord for coord in defn.coords], [0, 1]) + self.assertFalse(defn.transpose) + + def test_1d_coords_as_integers_swapped(self): + cube = simple_2d() + defn = iplt._get_plot_defn_custom_coords_picked(cube, (0, 1), + POINT_MODE) + self.assertEqual([coord for coord in defn.coords], [1, 0]) + self.assertTrue(defn.transpose) + + def test_2d_coords(self): + cube = simple_2d_w_multidim_coords() + defn = iplt._get_plot_defn_custom_coords_picked(cube, ('foo', 'bar'), + BOUND_MODE) + self.assertEqual([coord.name() for coord in defn.coords], + ['bar', 'foo']) + self.assertFalse(defn.transpose) + + def test_2d_coords_as_integers(self): + cube = simple_2d_w_multidim_coords() + defn = iplt._get_plot_defn_custom_coords_picked(cube, (0, 1), + BOUND_MODE) + self.assertEqual([coord for coord in defn.coords], [1, 0]) + self.assertTrue(defn.transpose) + + def test_span_check(self): + cube = hybrid_height() + emsg = 'don\'t span the 2 data dimensions' + with self.assertRaisesRegexp(ValueError, emsg): + iplt._get_plot_defn_custom_coords_picked( + cube, ('sigma', 'level_height'), POINT_MODE) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/plot/test_contour.py b/lib/iris/tests/unit/plot/test_contour.py new file mode 100644 index 0000000000..c996aff197 --- /dev/null +++ b/lib/iris/tests/unit/plot/test_contour.py @@ -0,0 +1,85 @@ +# (C) British Crown Copyright 2014 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.plot.contour` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.tests.stock import simple_2d +from iris.tests.unit.plot import TestGraphicStringCoord, MixinCoords + +if tests.MPL_AVAILABLE: + import iris.plot as iplt + + +@tests.skip_plot +class TestStringCoordPlot(TestGraphicStringCoord): + def test_yaxis_labels(self): + iplt.contour(self.cube, coords=('bar', 'str_coord')) + self.assertPointsTickLabels('yaxis') + + def test_xaxis_labels(self): + iplt.contour(self.cube, coords=('str_coord', 'bar')) + self.assertPointsTickLabels('xaxis') + + def test_yaxis_labels_with_axes(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + iplt.contour(self.cube, axes=ax, coords=('bar', 'str_coord')) + plt.close(fig) + self.assertPointsTickLabels('yaxis', ax) + + def test_xaxis_labels_with_axes(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + iplt.contour(self.cube, axes=ax, coords=('str_coord', 'bar')) + plt.close(fig) + self.assertPointsTickLabels('xaxis', ax) + + def test_geoaxes_exception(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + self.assertRaises(TypeError, iplt.contour, self.lat_lon_cube, axes=ax) + plt.close(fig) + + +@tests.skip_plot +class TestCoords(tests.IrisTest, MixinCoords): + def setUp(self): + # We have a 2d cube with dimensionality (bar: 3; foo: 4) + self.cube = simple_2d(with_bounds=False) + self.foo = self.cube.coord('foo').points + self.foo_index = np.arange(self.foo.size) + self.bar = self.cube.coord('bar').points + self.bar_index = np.arange(self.bar.size) + self.data = self.cube.data + self.dataT = self.data.T + self.mpl_patch = self.patch('matplotlib.pyplot.contour') + self.draw_func = iplt.contour + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/plot/test_contourf.py b/lib/iris/tests/unit/plot/test_contourf.py new file mode 100644 index 0000000000..9231cb5f9d --- /dev/null +++ b/lib/iris/tests/unit/plot/test_contourf.py @@ -0,0 +1,89 @@ +# (C) British Crown Copyright 2014 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.plot.contourf` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.tests import mock +from iris.tests.stock import simple_2d +from iris.tests.unit.plot import TestGraphicStringCoord, MixinCoords + +if tests.MPL_AVAILABLE: + import iris.plot as iplt + + +@tests.skip_plot +class TestStringCoordPlot(TestGraphicStringCoord): + def test_yaxis_labels(self): + iplt.contourf(self.cube, coords=('bar', 'str_coord')) + self.assertPointsTickLabels('yaxis') + + def test_xaxis_labels(self): + iplt.contourf(self.cube, coords=('str_coord', 'bar')) + self.assertPointsTickLabels('xaxis') + + def test_yaxis_labels_with_axes(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + iplt.contourf(self.cube, axes=ax, coords=('bar', 'str_coord')) + plt.close(fig) + self.assertPointsTickLabels('yaxis', ax) + + def test_xaxis_labels_with_axes(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + iplt.contourf(self.cube, axes=ax, coords=('str_coord', 'bar')) + plt.close(fig) + self.assertPointsTickLabels('xaxis', ax) + + def test_geoaxes_exception(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + self.assertRaises(TypeError, iplt.contourf, + self.lat_lon_cube, axes=ax) + plt.close(fig) + + +@tests.skip_plot +class TestCoords(tests.IrisTest, MixinCoords): + def setUp(self): + # We have a 2d cube with dimensionality (bar: 3; foo: 4) + self.cube = simple_2d(with_bounds=False) + self.foo = self.cube.coord('foo').points + self.foo_index = np.arange(self.foo.size) + self.bar = self.cube.coord('bar').points + self.bar_index = np.arange(self.bar.size) + self.data = self.cube.data + self.dataT = self.data.T + mocker = mock.Mock(alpha=0, antialiased=False) + self.mpl_patch = self.patch('matplotlib.pyplot.contourf', + return_value=mocker) + self.draw_func = iplt.contourf + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/plot/test_outline.py b/lib/iris/tests/unit/plot/test_outline.py new file mode 100644 index 0000000000..d5f63981a1 --- /dev/null +++ b/lib/iris/tests/unit/plot/test_outline.py @@ -0,0 +1,90 @@ +# (C) British Crown Copyright 2014 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.plot.outline` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.tests.stock import simple_2d +from iris.tests.unit.plot import TestGraphicStringCoord, MixinCoords + +if tests.MPL_AVAILABLE: + import iris.plot as iplt + + +@tests.skip_plot +class TestStringCoordPlot(TestGraphicStringCoord): + def test_yaxis_labels(self): + iplt.outline(self.cube, coords=('bar', 'str_coord')) + self.assertBoundsTickLabels('yaxis') + + def test_xaxis_labels(self): + iplt.outline(self.cube, coords=('str_coord', 'bar')) + self.assertBoundsTickLabels('xaxis') + + def test_xaxis_labels_with_axes(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + ax.set_xlim(0, 3) + iplt.outline(self.cube, coords=('str_coord', 'bar'), axes=ax) + plt.close(fig) + self.assertPointsTickLabels('xaxis', ax) + + def test_yaxis_labels_with_axes(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + ax.set_ylim(0, 3) + iplt.outline(self.cube, axes=ax, coords=('bar', 'str_coord')) + plt.close(fig) + self.assertPointsTickLabels('yaxis', ax) + + def test_geoaxes_exception(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + self.assertRaises(TypeError, iplt.outline, + self.lat_lon_cube, axes=ax) + plt.close(fig) + + +@tests.skip_plot +class TestCoords(tests.IrisTest, MixinCoords): + def setUp(self): + # We have a 2d cube with dimensionality (bar: 3; foo: 4) + self.cube = simple_2d(with_bounds=True) + coord = self.cube.coord('foo') + self.foo = coord.contiguous_bounds() + self.foo_index = np.arange(coord.points.size + 1) + coord = self.cube.coord('bar') + self.bar = coord.contiguous_bounds() + self.bar_index = np.arange(coord.points.size + 1) + self.data = self.cube.data + self.dataT = self.data.T + self.mpl_patch = self.patch('matplotlib.pyplot.pcolormesh') + self.draw_func = iplt.outline + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/plot/test_pcolor.py b/lib/iris/tests/unit/plot/test_pcolor.py new file mode 100644 index 0000000000..da9a461ade --- /dev/null +++ b/lib/iris/tests/unit/plot/test_pcolor.py @@ -0,0 +1,64 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.plot.pcolor` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.tests.stock import simple_2d +from iris.tests.unit.plot import TestGraphicStringCoord +from iris.tests.unit.plot._blockplot_common import \ + MixinStringCoordPlot, Mixin2dCoordsPlot, Mixin2dCoordsContigTol + + +if tests.MPL_AVAILABLE: + import iris.plot as iplt + PLOT_FUNCTION_TO_TEST = iplt.pcolor + + +@tests.skip_plot +class TestStringCoordPlot(MixinStringCoordPlot, TestGraphicStringCoord): + def blockplot_func(self): + return PLOT_FUNCTION_TO_TEST + + +@tests.skip_plot +class Test2dCoords(tests.IrisTest, Mixin2dCoordsPlot): + def setUp(self): + self.blockplot_setup() + + def blockplot_func(self): + return PLOT_FUNCTION_TO_TEST + + +@tests.skip_plot +class Test2dContigTol(tests.IrisTest, Mixin2dCoordsContigTol): + # Extra call kwargs expected. + additional_kwargs = dict(antialiased=True, snap=False) + + def blockplot_func(self): + return PLOT_FUNCTION_TO_TEST + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/plot/test_pcolormesh.py b/lib/iris/tests/unit/plot/test_pcolormesh.py new file mode 100644 index 0000000000..613a559415 --- /dev/null +++ b/lib/iris/tests/unit/plot/test_pcolormesh.py @@ -0,0 +1,64 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.plot.pcolormesh` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.tests.stock import simple_2d +from iris.tests.unit.plot import TestGraphicStringCoord +from iris.tests.unit.plot._blockplot_common import \ + MixinStringCoordPlot, Mixin2dCoordsPlot, Mixin2dCoordsContigTol + + +if tests.MPL_AVAILABLE: + import iris.plot as iplt + PLOT_FUNCTION_TO_TEST = iplt.pcolormesh + + +@tests.skip_plot +class TestStringCoordPlot(MixinStringCoordPlot, TestGraphicStringCoord): + def blockplot_func(self): + return PLOT_FUNCTION_TO_TEST + + +@tests.skip_plot +class Test2dCoords(tests.IrisTest, Mixin2dCoordsPlot): + def setUp(self): + self.blockplot_setup() + + def blockplot_func(self): + return PLOT_FUNCTION_TO_TEST + + +@tests.skip_plot +class Test2dContigTol(tests.IrisTest, Mixin2dCoordsContigTol): + # Extra call kwargs expected -- unlike 'pcolor', there are none. + additional_kwargs = {} + + def blockplot_func(self): + return PLOT_FUNCTION_TO_TEST + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/plot/test_plot.py b/lib/iris/tests/unit/plot/test_plot.py new file mode 100644 index 0000000000..c052958945 --- /dev/null +++ b/lib/iris/tests/unit/plot/test_plot.py @@ -0,0 +1,273 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.plot.plot` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.tests.unit.plot import TestGraphicStringCoord +import iris.coords as coords +import iris.coord_systems as ics + +if tests.MPL_AVAILABLE: + import iris.plot as iplt + import matplotlib.pyplot as plt + from matplotlib.path import Path + import matplotlib.transforms as mtranforms + import cartopy.mpl.geoaxes + import cartopy.crs as ccrs + + +@tests.skip_plot +class TestStringCoordPlot(TestGraphicStringCoord): + def setUp(self): + super(TestStringCoordPlot, self).setUp() + self.cube = self.cube[0, :] + self.lat_lon_cube = self.lat_lon_cube[0, :] + + def test_yaxis_labels(self): + iplt.plot(self.cube, self.cube.coord('str_coord')) + self.assertBoundsTickLabels('yaxis') + + def test_xaxis_labels(self): + iplt.plot(self.cube.coord('str_coord'), self.cube) + self.assertBoundsTickLabels('xaxis') + + def test_yaxis_labels_with_axes(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + iplt.plot(self.cube, self.cube.coord('str_coord'), axes=ax) + plt.close(fig) + self.assertBoundsTickLabels('yaxis', ax) + + def test_xaxis_labels_with_axes(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + iplt.plot(self.cube.coord('str_coord'), self.cube, axes=ax) + plt.close(fig) + self.assertBoundsTickLabels('xaxis', ax) + + def test_plot_longitude(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + iplt.plot(self.lat_lon_cube.coord('longitude'), + self.lat_lon_cube, axes=ax) + plt.close(fig) + + +@tests.skip_plot +class TestTrajectoryWrap(tests.IrisTest): + """ + Test that a line plot of geographic coordinates wraps around the end of the + coordinates rather than plotting accross the map. + + """ + + def setUp(self): + plt.figure() + self.geog_cs = ics.GeogCS(6371229.0) + self.plate_carree = self.geog_cs.as_cartopy_projection() + + def lon_lat_coords(self, lons, lats, cs=None): + if cs is None: + cs = self.geog_cs + return (coords.AuxCoord(lons, 'longitude', units='degrees', + coord_system=cs), + coords.AuxCoord(lats, 'latitude', units='degrees', + coord_system=cs)) + + def assertPathsEqual(self, expected, actual): + """ + Assert that the given paths are equal once STOP vertices have been + removed + + """ + expected = expected.cleaned() + actual = actual.cleaned() + # Remove Path.STOP vertices + everts = expected.vertices[np.where(expected.codes != Path.STOP)] + averts = actual.vertices[np.where(actual.codes != Path.STOP)] + self.assertArrayAlmostEqual(everts, averts) + self.assertArrayEqual(expected.codes, actual.codes) + + def check_paths(self, expected_path, expected_path_crs, lines, + axes): + """ + Check that the paths in `lines` match the given expected paths when + plotted on the given geoaxes + + """ + + self.assertEqual(1, len(lines), + 'Expected a single line, got {}'.format(len(lines))) + line, = lines + inter_proj_transform = cartopy.mpl.geoaxes.InterProjectionTransform( + expected_path_crs, axes.projection) + ax_transform = inter_proj_transform + axes.transData + + expected = ax_transform.transform_path(expected_path) + actual = line.get_transform().transform_path(line.get_path()) + + self.assertPathsEqual(expected, actual) + + def test_simple(self): + lon, lat = self.lon_lat_coords([359, 1], [0, 0]) + expected_path = Path([[-1, 0], + [1, 0]], + [Path.MOVETO, Path.LINETO]) + + lines = iplt.plot(lon, lat) + + self.check_paths(expected_path, self.plate_carree, lines, plt.gca()) + + def test_reverse(self): + lon, lat = self.lon_lat_coords([1, 359], [0, 0]) + expected_path = Path([[1, 0], + [-1, 0]], + [Path.MOVETO, Path.LINETO]) + + lines = iplt.plot(lon, lat) + + self.check_paths(expected_path, self.plate_carree, lines, plt.gca()) + + def test_multi(self): + lon, lat = self.lon_lat_coords([1, 359, 2, 358], [0, 0, 0, 0]) + expected_path = Path([[1, 0], + [-1, 0], + [2, 0], + [-2, 0]], + [Path.MOVETO, Path.LINETO, Path.LINETO, + Path.LINETO]) + + lines = iplt.plot(lon, lat) + + self.check_paths(expected_path, self.plate_carree, lines, + plt.gca()) + + def test_many_wraps(self): + lon, lat = self.lon_lat_coords([350, 10, 180, 350, 10, 180, 10, 350], + [0, 0, 0, 0, 0, 0, 0, 0]) + expected_path = Path([[350, 0], + [370, 0], + [540, 0], + [710, 0], + [730, 0], + [900, 0], + [730, 0], + [710, 0]], + [Path.MOVETO, Path.LINETO, Path.LINETO, + Path.LINETO, Path.LINETO, Path.LINETO, + Path.LINETO, Path.LINETO]) + + lines = iplt.plot(lon, lat) + + self.check_paths(expected_path, self.plate_carree, lines, + plt.gca()) + + def test_180(self): + lon, lat = self.lon_lat_coords([179, -179], [0, 0]) + expected_path = Path([[179, 0], + [181, 0]], + [Path.MOVETO, Path.LINETO]) + + lines = iplt.plot(lon, lat) + + self.check_paths(expected_path, self.plate_carree, lines, plt.gca()) + + def test_shifted_projection(self): + lon, lat = self.lon_lat_coords([359, 1], [0, 0]) + expected_path = Path([[-1, 0], + [1, 0]], + [Path.MOVETO, Path.LINETO]) + + shifted_plate_carree = ccrs.PlateCarree(180) + + plt.axes(projection=shifted_plate_carree) + lines = iplt.plot(lon, lat) + + self.check_paths(expected_path, self.plate_carree, lines, plt.gca()) + + def test_shifted_projection_180(self): + lon, lat = self.lon_lat_coords([179, -179], [0, 0]) + expected_path = Path([[179, 0], + [181, 0]], + [Path.MOVETO, Path.LINETO]) + + shifted_plate_carree = ccrs.PlateCarree(180) + + plt.axes(projection=shifted_plate_carree) + lines = iplt.plot(lon, lat) + + self.check_paths(expected_path, self.plate_carree, lines, plt.gca()) + + def test_long(self): + lon, lat = self.lon_lat_coords([271, 89], [0, 0]) + expected_path = Path([[-89, 0], + [89, 0]], + [Path.MOVETO, Path.LINETO]) + + lines = iplt.plot(lon, lat) + + self.check_paths(expected_path, self.plate_carree, lines, plt.gca()) + + def _test_rotated(self, grid_north_pole_latitude=90, + grid_north_pole_longitude=0, + north_pole_grid_longitude=0): + cs = ics.RotatedGeogCS(grid_north_pole_latitude, + grid_north_pole_longitude, + north_pole_grid_longitude) + glon = coords.AuxCoord([359, 1], 'grid_longitude', units='degrees', + coord_system=cs) + glat = coords.AuxCoord([0, 0], 'grid_latitude', units='degrees', + coord_system=cs) + expected_path = Path([[-1, 0], + [1, 0]], + [Path.MOVETO, Path.LINETO]) + + plt.figure() + lines = iplt.plot(glon, glat) + # Matplotlib won't immediately set up the correct transform to allow us + # to compare paths. Calling set_global(), which calls set_xlim() and + # set_ylim(), will trigger Matplotlib to set up the transform. + ax = plt.gca() + ax.set_global() + + crs = cs.as_cartopy_crs() + self.check_paths(expected_path, crs, lines, ax) + + def test_rotated_90(self): + self._test_rotated(north_pole_grid_longitude=90) + + def test_rotated_180(self): + self._test_rotated(north_pole_grid_longitude=180) + + def test_rotated(self): + self._test_rotated(grid_north_pole_latitude=-30, + grid_north_pole_longitude=120, + north_pole_grid_longitude=45) + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/plot/test_points.py b/lib/iris/tests/unit/plot/test_points.py new file mode 100644 index 0000000000..a22cd98a69 --- /dev/null +++ b/lib/iris/tests/unit/plot/test_points.py @@ -0,0 +1,88 @@ +# (C) British Crown Copyright 2014 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.plot.points` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.tests.stock import simple_2d +from iris.tests.unit.plot import TestGraphicStringCoord, MixinCoords + +if tests.MPL_AVAILABLE: + import iris.plot as iplt + + +@tests.skip_plot +class TestStringCoordPlot(TestGraphicStringCoord): + def test_yaxis_labels(self): + iplt.points(self.cube, coords=('bar', 'str_coord')) + self.assertBoundsTickLabels('yaxis') + + def test_xaxis_labels(self): + iplt.points(self.cube, coords=('str_coord', 'bar')) + self.assertBoundsTickLabels('xaxis') + + def test_xaxis_labels_with_axes(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + ax.set_xlim(0, 3) + iplt.points(self.cube, coords=('str_coord', 'bar'), axes=ax) + plt.close(fig) + self.assertPointsTickLabels('xaxis', ax) + + def test_yaxis_labels_with_axes(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + ax.set_ylim(0, 3) + iplt.points(self.cube, coords=('bar', 'str_coord'), axes=ax) + plt.close(fig) + self.assertPointsTickLabels('yaxis', ax) + + def test_geoaxes_exception(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + self.assertRaises(TypeError, iplt.points, + self.lat_lon_cube, axes=ax) + plt.close(fig) + + +@tests.skip_plot +class TestCoords(tests.IrisTest, MixinCoords): + def setUp(self): + # We have a 2d cube with dimensionality (bar: 3; foo: 4) + self.cube = simple_2d(with_bounds=False) + self.foo = self.cube.coord('foo').points + self.foo_index = np.arange(self.foo.size) + self.bar = self.cube.coord('bar').points + self.bar_index = np.arange(self.bar.size) + self.data = None + self.dataT = None + self.mpl_patch = self.patch('matplotlib.pyplot.scatter') + self.draw_func = iplt.points + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/plot/test_scatter.py b/lib/iris/tests/unit/plot/test_scatter.py new file mode 100644 index 0000000000..44cf228227 --- /dev/null +++ b/lib/iris/tests/unit/plot/test_scatter.py @@ -0,0 +1,74 @@ +# (C) British Crown Copyright 2014 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.plot.scatter` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests +from iris.tests.unit.plot import TestGraphicStringCoord + +if tests.MPL_AVAILABLE: + import iris.plot as iplt + + +@tests.skip_plot +class TestStringCoordPlot(TestGraphicStringCoord): + def setUp(self): + super(TestStringCoordPlot, self).setUp() + self.cube = self.cube[0, :] + self.lat_lon_cube = self.lat_lon_cube[0, :] + + def test_xaxis_labels(self): + iplt.scatter(self.cube.coord('str_coord'), self.cube) + self.assertBoundsTickLabels('xaxis') + + def test_yaxis_labels(self): + iplt.scatter(self.cube, self.cube.coord('str_coord')) + self.assertBoundsTickLabels('yaxis') + + def test_xaxis_labels_with_axes(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + ax.set_xlim(0, 3) + iplt.scatter(self.cube.coord('str_coord'), self.cube, axes=ax) + plt.close(fig) + self.assertPointsTickLabels('xaxis', ax) + + def test_yaxis_labels_with_axes(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + ax.set_ylim(0, 3) + iplt.scatter(self.cube, self.cube.coord('str_coord'), axes=ax) + plt.close(fig) + self.assertPointsTickLabels('yaxis', ax) + + def test_scatter_longitude(self): + import matplotlib.pyplot as plt + fig = plt.figure() + ax = fig.add_subplot(111) + iplt.scatter(self.lat_lon_cube, + self.lat_lon_cube.coord('longitude'), axes=ax) + plt.close(fig) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/quickplot/__init__.py b/lib/iris/tests/unit/quickplot/__init__.py new file mode 100644 index 0000000000..697881cf4d --- /dev/null +++ b/lib/iris/tests/unit/quickplot/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.quickplot` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/quickplot/test_contour.py b/lib/iris/tests/unit/quickplot/test_contour.py new file mode 100644 index 0000000000..bc7075100a --- /dev/null +++ b/lib/iris/tests/unit/quickplot/test_contour.py @@ -0,0 +1,62 @@ +# (C) British Crown Copyright 2014 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.quickplot.contour` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.tests.stock import simple_2d +from iris.tests.unit.plot import TestGraphicStringCoord, MixinCoords + +if tests.MPL_AVAILABLE: + import iris.quickplot as qplt + + +@tests.skip_plot +class TestStringCoordPlot(TestGraphicStringCoord): + def test_yaxis_labels(self): + qplt.contour(self.cube, coords=('bar', 'str_coord')) + self.assertPointsTickLabels('yaxis') + + def test_xaxis_labels(self): + qplt.contour(self.cube, coords=('str_coord', 'bar')) + self.assertPointsTickLabels('xaxis') + + +@tests.skip_plot +class TestCoords(tests.IrisTest, MixinCoords): + def setUp(self): + # We have a 2d cube with dimensionality (bar: 3; foo: 4) + self.cube = simple_2d(with_bounds=False) + self.foo = self.cube.coord('foo').points + self.foo_index = np.arange(self.foo.size) + self.bar = self.cube.coord('bar').points + self.bar_index = np.arange(self.bar.size) + self.data = self.cube.data + self.dataT = self.data.T + self.mpl_patch = self.patch('matplotlib.pyplot.contour') + self.draw_func = qplt.contour + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/quickplot/test_contourf.py b/lib/iris/tests/unit/quickplot/test_contourf.py new file mode 100644 index 0000000000..72acd6716b --- /dev/null +++ b/lib/iris/tests/unit/quickplot/test_contourf.py @@ -0,0 +1,67 @@ +# (C) British Crown Copyright 2014 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.quickplot.contourf` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.tests import mock +from iris.tests.stock import simple_2d +from iris.tests.unit.plot import TestGraphicStringCoord, MixinCoords + +if tests.MPL_AVAILABLE: + import iris.quickplot as qplt + + +@tests.skip_plot +class TestStringCoordPlot(TestGraphicStringCoord): + def test_yaxis_labels(self): + qplt.contourf(self.cube, coords=('bar', 'str_coord')) + self.assertPointsTickLabels('yaxis') + + def test_xaxis_labels(self): + qplt.contourf(self.cube, coords=('str_coord', 'bar')) + self.assertPointsTickLabels('xaxis') + + +@tests.skip_plot +class TestCoords(tests.IrisTest, MixinCoords): + def setUp(self): + # We have a 2d cube with dimensionality (bar: 3; foo: 4) + self.cube = simple_2d(with_bounds=False) + self.foo = self.cube.coord('foo').points + self.foo_index = np.arange(self.foo.size) + self.bar = self.cube.coord('bar').points + self.bar_index = np.arange(self.bar.size) + self.data = self.cube.data + self.dataT = self.data.T + mocker = mock.Mock(alpha=0, antialiased=False) + self.mpl_patch = self.patch('matplotlib.pyplot.contourf', + return_value=mocker) + # Also need to mock the colorbar. + self.patch('matplotlib.pyplot.colorbar') + self.draw_func = qplt.contourf + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/quickplot/test_outline.py b/lib/iris/tests/unit/quickplot/test_outline.py new file mode 100644 index 0000000000..aba6874877 --- /dev/null +++ b/lib/iris/tests/unit/quickplot/test_outline.py @@ -0,0 +1,64 @@ +# (C) British Crown Copyright 2014 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.quickplot.outline` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.tests.stock import simple_2d +from iris.tests.unit.plot import TestGraphicStringCoord, MixinCoords + +if tests.MPL_AVAILABLE: + import iris.quickplot as qplt + + +@tests.skip_plot +class TestStringCoordPlot(TestGraphicStringCoord): + def test_yaxis_labels(self): + qplt.outline(self.cube, coords=('bar', 'str_coord')) + self.assertBoundsTickLabels('yaxis') + + def test_xaxis_labels(self): + qplt.outline(self.cube, coords=('str_coord', 'bar')) + self.assertBoundsTickLabels('xaxis') + + +@tests.skip_plot +class TestCoords(tests.IrisTest, MixinCoords): + def setUp(self): + # We have a 2d cube with dimensionality (bar: 3; foo: 4) + self.cube = simple_2d(with_bounds=True) + coord = self.cube.coord('foo') + self.foo = coord.contiguous_bounds() + self.foo_index = np.arange(coord.points.size + 1) + coord = self.cube.coord('bar') + self.bar = coord.contiguous_bounds() + self.bar_index = np.arange(coord.points.size + 1) + self.data = self.cube.data + self.dataT = self.data.T + self.mpl_patch = self.patch('matplotlib.pyplot.pcolormesh') + self.draw_func = qplt.outline + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/quickplot/test_pcolor.py b/lib/iris/tests/unit/quickplot/test_pcolor.py new file mode 100644 index 0000000000..46fdc8ce56 --- /dev/null +++ b/lib/iris/tests/unit/quickplot/test_pcolor.py @@ -0,0 +1,65 @@ +# (C) British Crown Copyright 2014 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.quickplot.pcolor` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.tests.stock import simple_2d +from iris.tests.unit.plot import TestGraphicStringCoord, MixinCoords + +if tests.MPL_AVAILABLE: + import iris.quickplot as qplt + + +@tests.skip_plot +class TestStringCoordPlot(TestGraphicStringCoord): + def test_yaxis_labels(self): + qplt.pcolor(self.cube, coords=('bar', 'str_coord')) + self.assertBoundsTickLabels('yaxis') + + def test_xaxis_labels(self): + qplt.pcolor(self.cube, coords=('str_coord', 'bar')) + self.assertBoundsTickLabels('xaxis') + + +@tests.skip_plot +class TestCoords(tests.IrisTest, MixinCoords): + def setUp(self): + # We have a 2d cube with dimensionality (bar: 3; foo: 4) + self.cube = simple_2d(with_bounds=True) + coord = self.cube.coord('foo') + self.foo = coord.contiguous_bounds() + self.foo_index = np.arange(coord.points.size + 1) + coord = self.cube.coord('bar') + self.bar = coord.contiguous_bounds() + self.bar_index = np.arange(coord.points.size + 1) + self.data = self.cube.data + self.dataT = self.data.T + self.mpl_patch = self.patch('matplotlib.pyplot.pcolor', + return_value=None) + self.draw_func = qplt.pcolor + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/quickplot/test_pcolormesh.py b/lib/iris/tests/unit/quickplot/test_pcolormesh.py new file mode 100644 index 0000000000..af51816a56 --- /dev/null +++ b/lib/iris/tests/unit/quickplot/test_pcolormesh.py @@ -0,0 +1,65 @@ +# (C) British Crown Copyright 2014 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.quickplot.pcolormesh` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.tests.stock import simple_2d +from iris.tests.unit.plot import TestGraphicStringCoord, MixinCoords + +if tests.MPL_AVAILABLE: + import iris.quickplot as qplt + + +@tests.skip_plot +class TestStringCoordPlot(TestGraphicStringCoord): + def test_yaxis_labels(self): + qplt.pcolormesh(self.cube, coords=('bar', 'str_coord')) + self.assertBoundsTickLabels('yaxis') + + def test_xaxis_labels(self): + qplt.pcolormesh(self.cube, coords=('str_coord', 'bar')) + self.assertBoundsTickLabels('xaxis') + + +@tests.skip_plot +class TestCoords(tests.IrisTest, MixinCoords): + def setUp(self): + # We have a 2d cube with dimensionality (bar: 3; foo: 4) + self.cube = simple_2d(with_bounds=True) + coord = self.cube.coord('foo') + self.foo = coord.contiguous_bounds() + self.foo_index = np.arange(coord.points.size + 1) + coord = self.cube.coord('bar') + self.bar = coord.contiguous_bounds() + self.bar_index = np.arange(coord.points.size + 1) + self.data = self.cube.data + self.dataT = self.data.T + self.mpl_patch = self.patch('matplotlib.pyplot.pcolormesh', + return_value=None) + self.draw_func = qplt.pcolormesh + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/quickplot/test_plot.py b/lib/iris/tests/unit/quickplot/test_plot.py new file mode 100644 index 0000000000..d360387b3d --- /dev/null +++ b/lib/iris/tests/unit/quickplot/test_plot.py @@ -0,0 +1,47 @@ +# (C) British Crown Copyright 2014 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.quickplot.plot` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests +from iris.tests.unit.plot import TestGraphicStringCoord + +if tests.MPL_AVAILABLE: + import iris.quickplot as qplt + + +@tests.skip_plot +class TestStringCoordPlot(TestGraphicStringCoord): + def setUp(self): + super(TestStringCoordPlot, self).setUp() + self.cube = self.cube[0, :] + + def test_yaxis_labels(self): + qplt.plot(self.cube, self.cube.coord('str_coord')) + self.assertBoundsTickLabels('yaxis') + + def test_xaxis_labels(self): + qplt.plot(self.cube.coord('str_coord'), self.cube) + self.assertBoundsTickLabels('xaxis') + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/quickplot/test_points.py b/lib/iris/tests/unit/quickplot/test_points.py new file mode 100644 index 0000000000..eaf0f383cb --- /dev/null +++ b/lib/iris/tests/unit/quickplot/test_points.py @@ -0,0 +1,62 @@ +# (C) British Crown Copyright 2014 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.quickplot.points` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.tests.stock import simple_2d +from iris.tests.unit.plot import TestGraphicStringCoord, MixinCoords + +if tests.MPL_AVAILABLE: + import iris.quickplot as qplt + + +@tests.skip_plot +class TestStringCoordPlot(TestGraphicStringCoord): + def test_yaxis_labels(self): + qplt.points(self.cube, coords=('bar', 'str_coord')) + self.assertBoundsTickLabels('yaxis') + + def test_xaxis_labels(self): + qplt.points(self.cube, coords=('str_coord', 'bar')) + self.assertBoundsTickLabels('xaxis') + + +@tests.skip_plot +class TestCoords(tests.IrisTest, MixinCoords): + def setUp(self): + # We have a 2d cube with dimensionality (bar: 3; foo: 4) + self.cube = simple_2d(with_bounds=False) + self.foo = self.cube.coord('foo').points + self.foo_index = np.arange(self.foo.size) + self.bar = self.cube.coord('bar').points + self.bar_index = np.arange(self.bar.size) + self.data = None + self.dataT = None + self.mpl_patch = self.patch('matplotlib.pyplot.scatter') + self.draw_func = qplt.points + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/quickplot/test_scatter.py b/lib/iris/tests/unit/quickplot/test_scatter.py new file mode 100644 index 0000000000..5879e0631c --- /dev/null +++ b/lib/iris/tests/unit/quickplot/test_scatter.py @@ -0,0 +1,47 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.quickplot.scatter` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests +from iris.tests.unit.plot import TestGraphicStringCoord + +if tests.MPL_AVAILABLE: + import iris.quickplot as qplt + + +@tests.skip_plot +class TestStringCoordPlot(TestGraphicStringCoord): + def setUp(self): + super(TestStringCoordPlot, self).setUp() + self.cube = self.cube[0, :] + + def test_xaxis_labels(self): + qplt.scatter(self.cube.coord('str_coord'), self.cube) + self.assertBoundsTickLabels('xaxis') + + def test_yaxis_labels(self): + qplt.scatter(self.cube, self.cube.coord('str_coord')) + self.assertBoundsTickLabels('yaxis') + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/test_Future.py b/lib/iris/tests/unit/test_Future.py index c3a35e12d4..707c39c7b9 100644 --- a/lib/iris/tests/unit/test_Future.py +++ b/lib/iris/tests/unit/test_Future.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -16,42 +16,95 @@ # along with Iris. If not, see . """Unit tests for the `iris.Future` class.""" +from __future__ import (absolute_import, division, print_function) +import six +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests +import warnings + from iris import Future class Test___setattr__(tests.IrisTest): - def test_valid_attribute(self): + def test_valid_clip_latitudes(self): future = Future() - new_value = not future.cell_datetime_objects - future.cell_datetime_objects = new_value - self.assertEqual(future.cell_datetime_objects, new_value) + new_value = not future.clip_latitudes + msg = "'Future' property 'clip_latitudes' is deprecated" + with self.assertWarnsRegexp(msg): + future.clip_latitudes = new_value + self.assertEqual(future.clip_latitudes, new_value) def test_invalid_attribute(self): future = Future() with self.assertRaises(AttributeError): future.numberwang = 7 + def test_netcdf_promote(self): + future = Future() + exp_emsg = "'Future' property 'netcdf_promote' is deprecated" + with self.assertWarnsRegexp(exp_emsg): + future.netcdf_promote = True + + def test_invalid_netcdf_promote(self): + future = Future() + exp_emsg = "'Future' property 'netcdf_promote' has been deprecated" + with self.assertRaisesRegexp(AttributeError, exp_emsg): + future.netcdf_promote = False + + def test_netcdf_no_unlimited(self): + future = Future() + exp_emsg = "'Future' property 'netcdf_no_unlimited' is deprecated" + with self.assertWarnsRegexp(exp_emsg): + future.netcdf_no_unlimited = True + + def test_invalid_netcdf_no_unlimited(self): + future = Future() + exp_emsg = \ + "'Future' property 'netcdf_no_unlimited' has been deprecated" + with self.assertRaisesRegexp(AttributeError, exp_emsg): + future.netcdf_no_unlimited = False + + def test_cell_datetime_objects(self): + future = Future() + new_value = not future.cell_datetime_objects + with warnings.catch_warnings(record=True) as warn: + warnings.simplefilter('always') + future.cell_datetime_objects = new_value + self.assertEqual(future.cell_datetime_objects, new_value) + exp_wmsg = "'Future' property 'cell_datetime_objects' is deprecated" + six.assertRegex(self, str(warn[0]), exp_wmsg) + class Test_context(tests.IrisTest): def test_no_args(self): - future = Future(cell_datetime_objects=False) - self.assertFalse(future.cell_datetime_objects) - with future.context(): + # Catch the deprecation when explicitly setting `cell_datetime_objects` + # as the test is still useful even though the Future property is + # deprecated. + with warnings.catch_warnings(): + warnings.simplefilter('ignore') + future = Future(cell_datetime_objects=False) + self.assertFalse(future.cell_datetime_objects) + with future.context(): + self.assertFalse(future.cell_datetime_objects) + future.cell_datetime_objects = True + self.assertTrue(future.cell_datetime_objects) self.assertFalse(future.cell_datetime_objects) - future.cell_datetime_objects = True - self.assertTrue(future.cell_datetime_objects) - self.assertFalse(future.cell_datetime_objects) def test_with_arg(self): - future = Future(cell_datetime_objects=False) - self.assertFalse(future.cell_datetime_objects) - with future.context(cell_datetime_objects=True): - self.assertTrue(future.cell_datetime_objects) - self.assertFalse(future.cell_datetime_objects) + # Catch the deprecation when explicitly setting `cell_datetime_objects` + # as the test is still useful even though the Future property is + # deprecated. + with warnings.catch_warnings(): + warnings.simplefilter('ignore') + future = Future(cell_datetime_objects=False) + self.assertFalse(future.cell_datetime_objects) + with future.context(cell_datetime_objects=True): + self.assertTrue(future.cell_datetime_objects) + self.assertFalse(future.cell_datetime_objects) def test_invalid_arg(self): future = Future() @@ -67,13 +120,18 @@ def test_exception(self): class LocalTestException(Exception): pass - future = Future(cell_datetime_objects=False) - try: - with future.context(cell_datetime_objects=True): - raise LocalTestException() - except LocalTestException: - pass - self.assertEqual(future.cell_datetime_objects, False) + # Catch the deprecation when explicitly setting `cell_datetime_objects` + # as the test is still useful even though the Future property is + # deprecated. + with warnings.catch_warnings(): + warnings.simplefilter('ignore') + future = Future(cell_datetime_objects=False) + try: + with future.context(cell_datetime_objects=True): + raise LocalTestException() + except LocalTestException: + pass + self.assertEqual(future.cell_datetime_objects, False) if __name__ == "__main__": diff --git a/lib/iris/tests/unit/test_sample_data_path.py b/lib/iris/tests/unit/test_sample_data_path.py new file mode 100644 index 0000000000..af2730ac2c --- /dev/null +++ b/lib/iris/tests/unit/test_sample_data_path.py @@ -0,0 +1,101 @@ +# (C) British Crown Copyright 2016 - 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for :func:`iris.sample_data_path` class.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import os +import os.path +import shutil +import tempfile + +from iris import sample_data_path +from iris.tests import mock + + +def _temp_file(sample_dir): + # Return the full path to a new genuine file within our + # temporary directory. + sample_handle, sample_path = tempfile.mkstemp(dir=sample_dir) + os.close(sample_handle) + return sample_path + + +@tests.skip_sample_data +class TestIrisSampleData_path(tests.IrisTest): + def setUp(self): + self.sample_dir = tempfile.mkdtemp() + + def tearDown(self): + shutil.rmtree(self.sample_dir) + + def test_path(self): + with mock.patch('iris_sample_data.path', self.sample_dir): + import iris_sample_data + self.assertEqual(iris_sample_data.path, self.sample_dir) + + def test_call(self): + sample_file = _temp_file(self.sample_dir) + with mock.patch('iris_sample_data.path', self.sample_dir): + result = sample_data_path(os.path.basename(sample_file)) + self.assertEqual(result, sample_file) + + def test_file_not_found(self): + with mock.patch('iris_sample_data.path', self.sample_dir): + with self.assertRaisesRegexp(ValueError, + 'Sample data .* not found'): + sample_data_path('foo') + + def test_file_absolute(self): + with mock.patch('iris_sample_data.path', self.sample_dir): + with self.assertRaisesRegexp(ValueError, 'Absolute path'): + sample_data_path(os.path.abspath('foo')) + + def test_glob_ok(self): + sample_path = _temp_file(self.sample_dir) + sample_glob = '?' + os.path.basename(sample_path)[1:] + with mock.patch('iris_sample_data.path', self.sample_dir): + result = sample_data_path(sample_glob) + self.assertEqual(result, os.path.join(self.sample_dir, + sample_glob)) + + def test_glob_not_found(self): + with mock.patch('iris_sample_data.path', self.sample_dir): + with self.assertRaisesRegexp(ValueError, + 'Sample data .* not found'): + sample_data_path('foo.*') + + def test_glob_absolute(self): + with mock.patch('iris_sample_data.path', self.sample_dir): + with self.assertRaisesRegexp(ValueError, 'Absolute path'): + sample_data_path(os.path.abspath('foo.*')) + + +class TestIrisSampleDataMissing(tests.IrisTest): + def test_no_iris_sample_data(self): + self.patch('iris.iris_sample_data', None) + with self.assertRaisesRegexp(ImportError, 'Please install'): + sample_data_path('') + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/tests/__init__.py b/lib/iris/tests/unit/tests/__init__.py new file mode 100644 index 0000000000..de508654d4 --- /dev/null +++ b/lib/iris/tests/unit/tests/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.tests` package.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/tests/test_IrisTest.py b/lib/iris/tests/unit/tests/test_IrisTest.py new file mode 100644 index 0000000000..9b4436eb74 --- /dev/null +++ b/lib/iris/tests/unit/tests/test_IrisTest.py @@ -0,0 +1,147 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :mod:`iris.tests.IrisTest` class.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +from abc import ABCMeta, abstractproperty + +import numpy as np + + +class _MaskedArrayEquality(six.with_metaclass(ABCMeta, object)): + def setUp(self): + self.arr1 = np.ma.array([1, 2, 3, 4], mask=[False, True, True, False]) + self.arr2 = np.ma.array([1, 3, 2, 4], mask=[False, True, True, False]) + + @abstractproperty + def _func(self): + pass + + def test_strict_comparison(self): + # Comparing both mask and data array completely. + with self.assertRaises(AssertionError): + self._func(self.arr1, self.arr2, strict=True) + + def test_non_strict_comparison(self): + # Checking masked array equality and all unmasked array data values. + self._func(self.arr1, self.arr2, strict=False) + + def test_default_strict_arg_comparison(self): + self._func(self.arr1, self.arr2) + + def test_nomask(self): + # Test that an assertion is raised when comparing a masked array + # containing masked and unmasked values with a masked array with + # 'nomask'. + arr1 = np.ma.array([1, 2, 3, 4]) + with self.assertRaises(AssertionError): + self._func(arr1, self.arr2, strict=False) + + def test_nomask_unmasked(self): + # Ensure that a masked array with 'nomask' can compare with an entirely + # unmasked array. + arr1 = np.ma.array([1, 2, 3, 4]) + arr2 = np.ma.array([1, 2, 3, 4], mask=False) + self._func(arr1, arr2, strict=False) + + def test_different_mask_strict(self): + # Differing masks, equal data + arr2 = self.arr1.copy() + arr2[0] = np.ma.masked + with self.assertRaises(AssertionError): + self._func(self.arr1, arr2, strict=True) + + def test_different_mask_nonstrict(self): + # Differing masks, equal data + arr2 = self.arr1.copy() + arr2[0] = np.ma.masked + with self.assertRaises(AssertionError): + self._func(self.arr1, arr2, strict=False) + + +@tests.iristest_timing_decorator +class Test_assertMaskedArrayEqual(_MaskedArrayEquality, + tests.IrisTest_nometa): + @property + def _func(self): + return self.assertMaskedArrayEqual + + +class Test_assertMaskedArrayEqual__Nonmaasked(tests.IrisTest): + def test_nonmasked_same(self): + # Masked test can be used on non-masked arrays. + arr1 = np.array([1, 2]) + self.assertMaskedArrayEqual(arr1, arr1) + + def test_masked_nonmasked_same(self): + # Masked test can be used between masked + non-masked arrays, and will + # consider them equal, when mask=None. + arr1 = np.ma.masked_array([1, 2]) + arr2 = np.array([1, 2]) + self.assertMaskedArrayEqual(arr1, arr2) + + def test_masked_nonmasked_different(self): + arr1 = np.ma.masked_array([1, 2]) + arr2 = np.array([1, 3]) + with self.assertRaisesRegexp(AssertionError, 'Arrays are not equal'): + self.assertMaskedArrayEqual(arr1, arr2) + + def test_nonmasked_masked_same(self): + # Masked test can be used between masked + non-masked arrays, and will + # consider them equal, when mask=None. + arr1 = np.array([1, 2]) + arr2 = np.ma.masked_array([1, 2]) + self.assertMaskedArrayEqual(arr1, arr2) + + def test_masked_nonmasked_same_falsemask(self): + # Masked test can be used between masked + non-masked arrays, and will + # consider them equal, when mask=False. + arr1 = np.ma.masked_array([1, 2], mask=False) + arr2 = np.array([1, 2]) + self.assertMaskedArrayEqual(arr1, arr2) + + def test_masked_nonmasked_same_emptymask(self): + # Masked test can be used between masked + non-masked arrays, and will + # consider them equal, when mask=zeros. + arr1 = np.ma.masked_array([1, 2], mask=[False, False]) + arr2 = np.array([1, 2]) + self.assertMaskedArrayEqual(arr1, arr2) + + +@tests.iristest_timing_decorator +class Test_assertMaskedArrayAlmostEqual(_MaskedArrayEquality, + tests.IrisTest_nometa): + @property + def _func(self): + return self.assertMaskedArrayAlmostEqual + + def test_decimal(self): + arr1, arr2 = np.ma.array([100.0]), np.ma.array([100.003]) + self.assertMaskedArrayAlmostEqual(arr1, arr2, decimal=2) + with self.assertRaises(AssertionError): + self.assertMaskedArrayAlmostEqual(arr1, arr2, decimal=3) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/time/test_PartialDateTime.py b/lib/iris/tests/unit/time/test_PartialDateTime.py index d86a4e5330..e70aef68fc 100644 --- a/lib/iris/tests/unit/time/test_PartialDateTime.py +++ b/lib/iris/tests/unit/time/test_PartialDateTime.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office +# (C) British Crown Copyright 2013 - 2018, Met Office # # This file is part of Iris. # @@ -16,6 +16,10 @@ # along with Iris. If not, see . """Unit tests for the `iris.time.PartialDateTime` class.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests @@ -23,9 +27,9 @@ import datetime import operator -import mock -import netcdftime +import cftime +from iris.tests import mock from iris.time import PartialDateTime @@ -46,7 +50,7 @@ def test_keyword_args(self): class Test___repr__(tests.IrisTest): def test_full(self): - pd = PartialDateTime(*range(7)) + pd = PartialDateTime(*list(range(7))) result = repr(pd) self.assertEqual(result, 'PartialDateTime(year=0, month=1, day=2,' ' hour=3, minute=4, second=5,' @@ -67,7 +71,7 @@ class Test_timetuple(tests.IrisTest): def test_exists(self): # Check that the PartialDateTime class implements a timetuple (needed # because of http://bugs.python.org/issue8005). - pd = PartialDateTime(*range(7)) + pd = PartialDateTime(*list(range(7))) self.assertTrue(hasattr(pd, 'timetuple')) @@ -155,7 +159,7 @@ def negate(expected): expected = not expected return expected - return {name: negate(value) for name, value in expectations.iteritems()} + return {name: negate(value) for name, value in six.iteritems(expectations)} EQ_EXPECTATIONS = {'no_difference': True, 'item1_lo': False, 'item1_hi': False, @@ -185,14 +189,14 @@ def setUp(self): self.op = operator.eq self.expected_value = EQ_EXPECTATIONS - def test_netcdftime_equal(self): + def test_cftime_equal(self): pdt = PartialDateTime(month=3, microsecond=2) - other = netcdftime.datetime(year=2013, month=3, day=20, second=2) + other = cftime.datetime(year=2013, month=3, day=20, second=2) self.assertTrue(pdt == other) - def test_netcdftime_not_equal(self): + def test_cftime_not_equal(self): pdt = PartialDateTime(month=3, microsecond=2) - other = netcdftime.datetime(year=2013, month=4, day=20, second=2) + other = cftime.datetime(year=2013, month=4, day=20, second=2) self.assertFalse(pdt == other) @@ -207,14 +211,14 @@ def setUp(self): self.op = operator.gt self.expected_value = GT_EXPECTATIONS - def test_netcdftime_greater(self): + def test_cftime_greater(self): pdt = PartialDateTime(month=3, microsecond=2) - other = netcdftime.datetime(year=2013, month=2, day=20, second=3) + other = cftime.datetime(year=2013, month=2, day=20, second=3) self.assertTrue(pdt > other) - def test_netcdftime_not_greater(self): + def test_cftime_not_greater(self): pdt = PartialDateTime(month=3, microsecond=2) - other = netcdftime.datetime(year=2013, month=3, day=20, second=3) + other = cftime.datetime(year=2013, month=3, day=20, second=3) self.assertFalse(pdt > other) diff --git a/lib/iris/tests/unit/util/__init__.py b/lib/iris/tests/unit/util/__init__.py index ad11c3d325..4e39e45ea8 100644 --- a/lib/iris/tests/unit/util/__init__.py +++ b/lib/iris/tests/unit/util/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -15,3 +15,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Iris. If not, see . """Unit tests for the :mod:`iris.util` module.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/util/test__coord_regular.py b/lib/iris/tests/unit/util/test__coord_regular.py new file mode 100644 index 0000000000..61770a9900 --- /dev/null +++ b/lib/iris/tests/unit/util/test__coord_regular.py @@ -0,0 +1,116 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test elements of :mod:`iris.util` that deal with checking coord regularity. +Specifically, this module tests the following functions: + + * :func:`iris.util.is_regular`, + * :func:`iris.util.regular_step`, and + * :func:`iris.util.points_step`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import inspect + +import numpy as np + +from iris.coords import AuxCoord, DimCoord +from iris.exceptions import CoordinateNotRegularError, CoordinateMultiDimError +from iris.util import is_regular, regular_step, points_step + + +class Test_is_regular(tests.IrisTest): + def test_coord_with_regular_step(self): + coord = DimCoord(np.arange(5)) + result = is_regular(coord) + self.assertTrue(result) + + def test_coord_with_irregular_step(self): + # Check that a `CoordinateNotRegularError` is captured. + coord = AuxCoord(np.array([2, 5, 1, 4])) + result = is_regular(coord) + self.assertFalse(result) + + def test_scalar_coord(self): + # Check that a `ValueError` is captured. + coord = DimCoord(5) + result = is_regular(coord) + self.assertFalse(result) + + def test_coord_with_string_points(self): + # Check that a `TypeError` is captured. + coord = AuxCoord(['a', 'b', 'c']) + result = is_regular(coord) + self.assertFalse(result) + + +class Test_regular_step(tests.IrisTest): + def test_basic(self): + dtype = np.float64 + points = np.arange(5, dtype=dtype) + coord = DimCoord(points) + expected = np.mean(np.diff(points)) + result = regular_step(coord) + self.assertEqual(expected, result) + self.assertEqual(result.dtype, dtype) + + def test_2d_coord(self): + coord = AuxCoord(np.arange(8).reshape(2, 4)) + exp_emsg = 'Expected 1D coord' + with self.assertRaisesRegexp(CoordinateMultiDimError, exp_emsg): + regular_step(coord) + + def test_scalar_coord(self): + coord = DimCoord(5) + exp_emsg = 'non-scalar coord' + with self.assertRaisesRegexp(ValueError, exp_emsg): + regular_step(coord) + + def test_coord_with_irregular_step(self): + name = 'latitude' + coord = AuxCoord(np.array([2, 5, 1, 4]), standard_name=name) + exp_emsg = '{} is not regular'.format(name) + with self.assertRaisesRegexp(CoordinateNotRegularError, exp_emsg): + regular_step(coord) + + +class Test_points_step(tests.IrisTest): + def test_regular_points(self): + regular_points = np.arange(5) + exp_avdiff = np.mean(np.diff(regular_points)) + result_avdiff, result = points_step(regular_points) + self.assertEqual(exp_avdiff, result_avdiff) + self.assertTrue(result) + + def test_irregular_points(self): + irregular_points = np.array([2, 5, 1, 4]) + exp_avdiff = np.mean(np.diff(irregular_points)) + result_avdiff, result = points_step(irregular_points) + self.assertEqual(exp_avdiff, result_avdiff) + self.assertFalse(result) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/util/test__is_circular.py b/lib/iris/tests/unit/util/test__is_circular.py new file mode 100644 index 0000000000..f212b6c2ca --- /dev/null +++ b/lib/iris/tests/unit/util/test__is_circular.py @@ -0,0 +1,42 @@ +# (C) British Crown Copyright 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Test function :func:`iris.util._is_circular`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import numpy as np + +from iris.util import _is_circular + + +class Test(tests.IrisTest): + def test_simple(self): + data = np.arange(12) * 30 + self.assertTrue(_is_circular(data, 360)) + + def test_negative_diff(self): + data = (np.arange(96) * -3.749998) + 3.56249908e+02 + self.assertTrue(_is_circular(data, 360)) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/util/test__slice_data_with_keys.py b/lib/iris/tests/unit/util/test__slice_data_with_keys.py new file mode 100644 index 0000000000..c652ec8ace --- /dev/null +++ b/lib/iris/tests/unit/util/test__slice_data_with_keys.py @@ -0,0 +1,405 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test function :func:`iris.util._slice_data_with_keys`. + +Note: much of the functionality really belongs to the other routines, +:func:`iris.util._build_full_slice_given_keys`, and +:func:`column_slices_generator`. +However, it is relatively simple to test multiple aspects of all three here +in combination. + +""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import numpy as np + +from iris.util import _slice_data_with_keys +from iris._lazy_data import as_lazy_data, as_concrete_data + + +class DummyArray(object): + # A dummy array-like that records the keys of indexing calls. + def __init__(self, shape, _indexing_record_list=None): + self.shape = shape + self.ndim = len(shape) + if _indexing_record_list is None: + _indexing_record_list = [] + self._getitem_call_keys = _indexing_record_list + + def __getitem__(self, keys): + # Add the indexing keys to the call list. + self._getitem_call_keys.append(keys) + # Return a new object with the correct derived shape, and record its + # indexing operations in the same key list as this. + shape_array = np.zeros(self.shape) + shape_array = shape_array.__getitem__(keys) + new_shape = shape_array.shape + return DummyArray(new_shape, + _indexing_record_list=self._getitem_call_keys) + + +class Indexer(object): + # An object to make __getitem__ arglists from indexing operations. + def __getitem__(self, keys): + return keys + + +# An Indexer object for generating indexing keys in a nice visible way. +Index = Indexer() + + +class MixinIndexingTest(object): + def check(self, shape, keys, expect_call_keys=None, expect_map=None): + data = DummyArray(shape) + dim_map, _ = _slice_data_with_keys(data, keys) + if expect_call_keys is not None: + calls_got = data._getitem_call_keys + # Check that the indexing keys applied were the expected ones. + equal = len(calls_got) == len(expect_call_keys) + for act_call, expect_call in zip(calls_got, expect_call_keys): + equal &= len(act_call) == len(expect_call) + # A problem here is that in each call, some keys may be + # *arrays*, and arrays can't be compared in the "normal" + # way. So we must use np.all for comparison :-( + for act_key, expect_key in zip(act_call, expect_call): + equal &= (np.asanyarray(act_key).dtype == + np.asanyarray(expect_key).dtype and + np.all(act_key == expect_key)) + errmsg = 'Different key lists:\n{!s}\n!=\n{!s}\n' + + def showkeys(keys_list): + msg = '[\n ' + msg += '\n '.join(str(x) for x in keys_list) + msg += '\n]' + return msg + + self.assertTrue(equal, errmsg.format(showkeys(calls_got), + showkeys(expect_call_keys))) + if expect_map is not None: + self.assertEqual(dim_map, expect_map) + + +class Test_indexing(MixinIndexingTest, tests.IrisTest): + # Check the indexing operations performed for various requested keys. + + def test_0d_nokeys(self): + # Performs *no* underlying indexing operation. + self.check((), Index[()], + []) + + def test_1d_int(self): + self.check((4,), Index[2], + [(2,)]) + + def test_1d_all(self): + self.check((3,), Index[:], + [(slice(None),)]) + + def test_1d_tuple(self): + # The call makes tuples into 1-D arrays, and a trailing Ellipsis is + # added (for the 1-D case only). + self.check((3,), Index[(2, 0, 1), ], + [(np.array([2, 0, 1]), Ellipsis)]) + + def test_fail_1d_2keys(self): + msg = 'More slices .* than dimensions' + with self.assertRaisesRegexp(IndexError, msg): + self.check((3,), Index[1, 2]) + + def test_fail_empty_slice(self): + msg = 'Cannot index with zero length slice' + with self.assertRaisesRegexp(IndexError, msg): + self.check((3,), Index[1:1]) + + def test_2d_tuple(self): + # Like the above, but there is an extra no-op at the start and no + # trailing Ellipsis is generated. + self.check((3, 2), Index[(2, 0, 1), ], + [(slice(None), slice(None)), + (np.array([2, 0, 1]), slice(None))]) + + def test_2d_two_tuples(self): + # Could be treated as fancy indexing, but must not be ! + # Two separate 2-D indexing operations. + self.check((3, 2), Index[(2, 0, 1, 1), (0, 1, 0, 1)], + [(np.array([2, 0, 1, 1]), slice(None)), + (slice(None), np.array([0, 1, 0, 1]))]) + + def test_2d_tuple_and_value(self): + # The two keys are applied in separate operations, and in the reverse + # order (?) : The second op is then slicing a 1-D array, not 2-D. + self.check((3, 5), Index[(2, 0, 1), 3], + [(slice(None), 3), + (np.array([2, 0, 1]), Ellipsis)]) + + def test_2d_single_int(self): + self.check((3, 4), Index[2], + [(2, slice(None))]) + + def test_2d_multiple_int(self): + self.check((3, 4), Index[2, 1:3], + [(2, slice(1, 3))]) + + def test_3d_1int(self): + self.check((3, 4, 5), Index[2], + [(2, slice(None), slice(None))]) + + def test_3d_2int(self): + self.check((3, 4, 5), Index[2, 3], + [(2, 3, slice(None))]) + + def test_3d_tuple_and_value(self): + # The two keys are applied in separate operations, and in the reverse + # order (?) : The second op is slicing a 2-D array, not 3-D. + self.check((3, 5, 7), Index[(2, 0, 1), 4], + [(slice(None), 4, slice(None)), + (np.array([2, 0, 1]), slice(None))]) + + def test_3d_ellipsis_last(self): + self.check((3, 4, 5), Index[2, ...], + [(2, slice(None), slice(None))]) + + def test_3d_ellipsis_first_1int(self): + self.check((3, 4, 5), Index[..., 2], + [(slice(None), slice(None), 2)]) + + def test_3d_ellipsis_first_2int(self): + self.check((3, 4, 5), Index[..., 2, 3], + [(slice(None), 2, 3)]) + + def test_3d_multiple_tuples(self): + # Where there are TWO or more tuple keys, this could be misinterpreted + # as 'fancy' indexing : It should resolve into multiple calls. + self.check((3, 4, 5), Index[(1, 2, 1), :, (2, 2, 3)], + [(slice(None), slice(None), slice(None)), + (np.array([1, 2, 1]), slice(None), slice(None)), + (slice(None), slice(None), np.array([2, 2, 3])), + ]) + # NOTE: there seem to be an extra initial [:, :, :]. + # That's just what it does at present. + + +class Test_dimensions_mapping(MixinIndexingTest, tests.IrisTest): + # Check the dimensions map returned for various requested keys. + + def test_1d_nochange(self): + self.check((3,), Index[1:2], + expect_map={None: None, 0: 0}) + + def test_1d_1int_losedim0(self): + self.check((3,), Index[1], + expect_map={None: None, 0: None}) + + def test_1d_tuple_nochange(self): + # A selection index leaves the dimension intact. + self.check((3,), Index[(1, 0, 1, 2), ], + expect_map={None: None, 0: 0}) + + def test_1d_1tuple_nochange(self): + # A selection index with only one value in it *still* leaves the + # dimension intact. + self.check((3,), Index[(2,), ], + expect_map={None: None, 0: 0}) + + def test_1d_slice_nochange(self): + # A slice leaves the dimension intact. + self.check((3,), Index[1:7], + expect_map={None: None, 0: 0}) + + def test_2d_nochange(self): + self.check((3, 4), Index[:, :], + expect_map={None: None, 0: 0, 1: 1}) + + def test_2d_losedim0(self): + self.check((3, 4), Index[1, :], + expect_map={None: None, 0: None, 1: 0}) + + def test_2d_losedim1(self): + self.check((3, 4), Index[1:4, 2], + expect_map={None: None, 0: 0, 1: None}) + + def test_2d_loseboth(self): + # Two indices give scalar result. + self.check((3, 4), Index[1, 2], + expect_map={None: None, 0: None, 1: None}) + + def test_3d_losedim1(self): + # Cutting out the middle dim. + self.check((3, 4, 2), Index[:, 2], + expect_map={None: None, 0: 0, 1: None, 2: 1}) + + +class TestResults(tests.IrisTest): + # Integration-style test, exercising (mostly) the same cases as above, + # but checking actual results, for both real and lazy array inputs. + + def check(self, real_data, keys, expect_result, expect_map): + real_data = np.array(real_data) + lazy_data = as_lazy_data(real_data, real_data.shape) + real_dim_map, real_result = _slice_data_with_keys(real_data, keys) + lazy_dim_map, lazy_result = _slice_data_with_keys(lazy_data, keys) + lazy_result = as_concrete_data(lazy_result) + self.assertArrayEqual(real_result, expect_result) + self.assertArrayEqual(lazy_result, expect_result) + self.assertEqual(real_dim_map, expect_map) + self.assertEqual(lazy_dim_map, expect_map) + + def test_1d_int(self): + self.check([1, 2, 3, 4], Index[2], + [3], + {None: None, 0: None}) + + def test_1d_all(self): + self.check([1, 2, 3], Index[:], + [1, 2, 3], + {None: None, 0: 0}) + + def test_1d_tuple(self): + self.check([1, 2, 3], Index[(2, 0, 1, 0), ], + [3, 1, 2, 1], + {None: None, 0: 0}) + + def test_fail_1d_2keys(self): + msg = 'More slices .* than dimensions' + with self.assertRaisesRegexp(IndexError, msg): + self.check([1, 2, 3], Index[1, 2], None, None) + + def test_fail_empty_slice(self): + msg = 'Cannot index with zero length slice' + with self.assertRaisesRegexp(IndexError, msg): + self.check([1, 2, 3], Index[1:1], None, None) + + def test_2d_tuple(self): + self.check([[11, 12], [21, 22], [31, 32]], + Index[(2, 0, 1), ], + [[31, 32], [11, 12], [21, 22]], + {None: None, 0: 0, 1: 1}) + + def test_2d_two_tuples(self): + # Could be treated as fancy indexing, but must not be ! + # Two separate 2-D indexing operations. + self.check([[11, 12, 13], [21, 22, 23], [31, 32, 33]], + Index[(2, 0), (0, 1, 0, 1)], + [[31, 32, 31, 32], [11, 12, 11, 12]], + {None: None, 0: 0, 1: 1}) + + def test_2d_tuple_and_value(self): + # The two keys are applied in separate operations, and in the reverse + # order (?) : The second op is then slicing a 1-D array, not 2-D. + self.check([[11, 12, 13, 14], [21, 22, 23, 24], [31, 32, 33, 34]], + Index[(2, 0, 1), 3], + [34, 14, 24], + {None: None, 0: 0, 1: None}) + + def test_2d_single_int(self): + self.check([[11, 12, 13], [21, 22, 23], [31, 32, 33]], + Index[1], + [21, 22, 23], + {None: None, 0: None, 1: 0}) + + def test_2d_int_slice(self): + self.check([[11, 12, 13], [21, 22, 23], [31, 32, 33]], + Index[2, 1:3], + [32, 33], + {None: None, 0: None, 1: 0}) + + def test_3d_1int(self): + self.check([[[111, 112, 113], [121, 122, 123]], + [[211, 212, 213], [221, 222, 223]], + [[311, 312, 313], [321, 322, 323]]], + Index[1], + [[211, 212, 213], [221, 222, 223]], + {None: None, 0: None, 1: 0, 2: 1}) + + def test_3d_2int(self): + self.check([[[111, 112, 113], [121, 122, 123], [131, 132, 133]], + [[211, 212, 213], [221, 222, 223], [231, 232, 233]]], + Index[1, 2], + [231, 232, 233], + {None: None, 0: None, 1: None, 2: 0}) + + def test_3d_tuple_and_value(self): + # The two keys are applied in separate operations, and in the reverse + # order (?) : The second op is slicing a 2-D array, not 3-D. + self.check([[[111, 112, 113, 114], [121, 122, 123, 124]], + [[211, 212, 213, 214], [221, 222, 223, 224]], + [[311, 312, 313, 314], [321, 322, 323, 324]]], + Index[(2, 0, 1), 1], + [[321, 322, 323, 324], + [121, 122, 123, 124], + [221, 222, 223, 224]], + {None: None, 0: 0, 1: None, 2: 1}) + + def test_3d_ellipsis_last(self): + self.check([[[111, 112, 113], [121, 122, 123]], + [[211, 212, 213], [221, 222, 223]], + [[311, 312, 313], [321, 322, 323]]], + Index[2, ...], + [[311, 312, 313], [321, 322, 323]], + {None: None, 0: None, 1: 0, 2: 1}) + + def test_3d_ellipsis_first_1int(self): + self.check([[[111, 112, 113, 114], [121, 122, 123, 124]], + [[211, 212, 213, 214], [221, 222, 223, 224]], + [[311, 312, 313, 314], [321, 322, 323, 324]]], + Index[..., 2], + [[113, 123], + [213, 223], + [313, 323]], + {None: None, 0: 0, 1: 1, 2: None}) + + def test_3d_ellipsis_mid_1int(self): + self.check([[[111, 112, 113], [121, 122, 123]], + [[211, 212, 213], [221, 222, 223]], + [[311, 312, 313], [321, 322, 323]]], + Index[..., 1, ...], + [[121, 122, 123], + [221, 222, 223], + [321, 322, 323]], + {None: None, 0: 0, 1: None, 2: 1}) + + def test_3d_ellipsis_first_2int(self): + self.check([[[111, 112, 113], [121, 122, 123]], + [[211, 212, 213], [221, 222, 223]], + [[311, 312, 313], [321, 322, 323]]], + Index[..., 1, 2], + [123, 223, 323], + {None: None, 0: 0, 1: None, 2: None}) + + def test_3d_multiple_tuples(self): + # Where there are TWO or more tuple keys, this could be misinterpreted + # as 'fancy' indexing : It should resolve into multiple calls. + self.check([[[111, 112, 113, 114], [121, 122, 123, 124]], + [[211, 212, 213, 214], [221, 222, 223, 224]], + [[311, 312, 313, 314], [321, 322, 323, 324]]], + Index[(1, 2, 1), :, (2, 2, 3)], + [[[213, 213, 214], [223, 223, 224]], + [[313, 313, 314], [323, 323, 324]], + [[213, 213, 214], [223, 223, 224]]], + {None: None, 0: 0, 1: 1, 2: 2}) + # NOTE: there seem to be an extra initial [:, :, :]. + # That's just what it does at present. + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/util/test_array_equal.py b/lib/iris/tests/unit/util/test_array_equal.py index 6c20fafe04..31fd9dd842 100644 --- a/lib/iris/tests/unit/util/test_array_equal.py +++ b/lib/iris/tests/unit/util/test_array_equal.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2014, Met Office +# (C) British Crown Copyright 2014 - 2015, Met Office # # This file is part of Iris. # @@ -16,6 +16,9 @@ # along with Iris. If not, see . """Test function :func:`iris.util.array_equal`.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # import iris tests first so that some things can be initialised before # importing anything else import iris.tests as tests @@ -57,28 +60,28 @@ def test_nd(self): self.assertFalse(array_equal(array_a, array_c)) def test_masked_is_ignored(self): - array_a = np.ma.masked_array([1, 2, 3], mask=[1, 0, 1]) - array_b = np.ma.masked_array([2, 2, 2], mask=[1, 0, 1]) + array_a = ma.masked_array([1, 2, 3], mask=[1, 0, 1]) + array_b = ma.masked_array([2, 2, 2], mask=[1, 0, 1]) self.assertFalse(array_equal(array_a, array_b)) def test_fully_masked_arrays(self): - array_a = np.ma.masked_array(np.arange(24).reshape(2, 3, 4), mask=True) - array_b = np.ma.masked_array(np.arange(24).reshape(2, 3, 4), mask=True) + array_a = ma.masked_array(np.arange(24).reshape(2, 3, 4), mask=True) + array_b = ma.masked_array(np.arange(24).reshape(2, 3, 4), mask=True) self.assertTrue(array_equal(array_a, array_b)) def test_fully_masked_0d_arrays(self): - array_a = np.ma.masked_array(3, mask=True) - array_b = np.ma.masked_array(3, mask=True) + array_a = ma.masked_array(3, mask=True) + array_b = ma.masked_array(3, mask=True) self.assertTrue(array_equal(array_a, array_b)) def test_fully_masked_string_arrays(self): - array_a = np.ma.masked_array(['a', 'b', 'c'], mask=True) - array_b = np.ma.masked_array(['a', 'b', 'c'], mask=[1, 1, 1]) + array_a = ma.masked_array(['a', 'b', 'c'], mask=True) + array_b = ma.masked_array(['a', 'b', 'c'], mask=[1, 1, 1]) self.assertTrue(array_equal(array_a, array_b)) def test_partially_masked_string_arrays(self): - array_a = np.ma.masked_array(['a', 'b', 'c'], mask=[1, 0, 1]) - array_b = np.ma.masked_array(['a', 'b', 'c'], mask=[1, 0, 1]) + array_a = ma.masked_array(['a', 'b', 'c'], mask=[1, 0, 1]) + array_b = ma.masked_array(['a', 'b', 'c'], mask=[1, 0, 1]) self.assertTrue(array_equal(array_a, array_b)) def test_string_arrays_equal(self): diff --git a/lib/iris/tests/unit/util/test_broadcast_to_shape.py b/lib/iris/tests/unit/util/test_broadcast_to_shape.py index c136f0c8aa..6fe2fccf20 100644 --- a/lib/iris/tests/unit/util/test_broadcast_to_shape.py +++ b/lib/iris/tests/unit/util/test_broadcast_to_shape.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -16,6 +16,8 @@ # along with Iris. If not, see . """Test function :func:`iris.util.broadcast_to_shape`.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before # importing anything else @@ -40,8 +42,8 @@ def test_added_dimensions(self): # the existing dimensions a = np.random.random([2, 3]) b = broadcast_to_shape(a, (5, 2, 4, 3), (1, 3)) - for i in xrange(5): - for j in xrange(4): + for i in range(5): + for j in range(4): self.assertArrayEqual(b[i, :, j, :], a) def test_added_dimensions_transpose(self): @@ -49,8 +51,8 @@ def test_added_dimensions_transpose(self): # transposed a = np.random.random([2, 3]) b = broadcast_to_shape(a, (5, 3, 4, 2), (3, 1)) - for i in xrange(5): - for j in xrange(4): + for i in range(5): + for j in range(4): self.assertArrayEqual(b[i, :, j, :].T, a) def test_masked(self): @@ -58,8 +60,8 @@ def test_masked(self): a = np.random.random([2, 3]) m = ma.array(a, mask=[[0, 1, 0], [0, 1, 1]]) b = broadcast_to_shape(m, (5, 3, 4, 2), (3, 1)) - for i in xrange(5): - for j in xrange(4): + for i in range(5): + for j in range(4): self.assertMaskedArrayEqual(b[i, :, j, :].T, m) def test_masked_degenerate(self): @@ -67,8 +69,8 @@ def test_masked_degenerate(self): a = np.random.random([2, 3]) m = ma.array(a) b = broadcast_to_shape(m, (5, 3, 4, 2), (3, 1)) - for i in xrange(5): - for j in xrange(4): + for i in range(5): + for j in range(4): self.assertMaskedArrayEqual(b[i, :, j, :].T, m) diff --git a/lib/iris/tests/unit/util/test_column_slices_generator.py b/lib/iris/tests/unit/util/test_column_slices_generator.py new file mode 100644 index 0000000000..1bf338aef9 --- /dev/null +++ b/lib/iris/tests/unit/util/test_column_slices_generator.py @@ -0,0 +1,50 @@ +# (C) British Crown Copyright 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Test function :func:`iris.util.column_slices_generator`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import numpy as np + +from iris.util import column_slices_generator + + +class Test_int_types(tests.IrisTest): + def _test(self, key): + full_slice = (key,) + ndims = 1 + mapping, iterable = column_slices_generator(full_slice, ndims) + self.assertEqual(mapping, {0: None, None: None}) + self.assertEqual(list(iterable), [(0,)]) + + def test_int(self): + self._test(0) + + def test_int_32(self): + self._test(np.int32(0)) + + def test_int_64(self): + self._test(np.int64(0)) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/util/test_demote_dim_coord_to_aux_coord.py b/lib/iris/tests/unit/util/test_demote_dim_coord_to_aux_coord.py new file mode 100644 index 0000000000..a840b5c419 --- /dev/null +++ b/lib/iris/tests/unit/util/test_demote_dim_coord_to_aux_coord.py @@ -0,0 +1,84 @@ +# (C) British Crown Copyright 2010 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Test function :func:`iris.util.demote_dim_coord_to_aux_coord`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import unittest + +import iris +import iris.tests.stock as stock +from iris.util import demote_dim_coord_to_aux_coord + + +class Test(tests.IrisTest): + def test_argument_is_basestring(self): + cube_a = stock.simple_3d() + cube_b = cube_a.copy() + demote_dim_coord_to_aux_coord(cube_b, cube_b.coord('wibble')) + self.assertEqual(cube_b.dim_coords, + (cube_a.coord('latitude'), cube_a.coord('longitude'))) + + @tests.skip_data + def test_argument_is_coord_instance(self): + cube_a = stock.realistic_4d() + cube_b = cube_a.copy() + coord = cube_b.coord('model_level_number').copy() + demote_dim_coord_to_aux_coord(cube_b, coord) + self.assertEqual(cube_b.dim_coords, + (cube_a.coord('time'), + cube_a.coord('grid_latitude'), + cube_a.coord('grid_longitude'))) + + def test_old_dim_coord_is_now_aux_coord(self): + cube_a = stock.hybrid_height() + cube_b = cube_a.copy() + demote_dim_coord_to_aux_coord(cube_b, 'level_height') + self.assertTrue(cube_a.coord('level_height') in cube_b.aux_coords) + + def test_coord_of_that_name_does_not_exist(self): + cube_a = stock.simple_2d_w_multidim_and_scalars() + with self.assertRaises(iris.exceptions.CoordinateNotFoundError): + demote_dim_coord_to_aux_coord(cube_a, 'wibble') + + def test_coord_does_not_exist(self): + cube_a = stock.simple_2d_w_multidim_and_scalars() + cube_b = cube_a.copy() + coord = cube_b.coord('dim1').copy() + coord.rename('new') + demote_dim_coord_to_aux_coord(cube_b, coord) + self.assertEqual(cube_a, cube_b) + + def test_argument_is_wrong_type(self): + cube_a = stock.simple_1d() + with self.assertRaises(TypeError): + demote_dim_coord_to_aux_coord(cube_a, 0.0) + + def test_trying_to_demote_a_scalar_coord(self): + cube_a = stock.simple_2d_w_multidim_and_scalars() + cube_b = cube_a.copy() + demote_dim_coord_to_aux_coord(cube_b, 'an_other') + self.assertEqual(cube_a, cube_b) + + +if __name__ == '__main__': + unittest.main() diff --git a/lib/iris/tests/unit/util/test_describe_diff.py b/lib/iris/tests/unit/util/test_describe_diff.py index 87c252260c..f91d76d4e9 100644 --- a/lib/iris/tests/unit/util/test_describe_diff.py +++ b/lib/iris/tests/unit/util/test_describe_diff.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -16,12 +16,15 @@ # along with Iris. If not, see . """Test function :func:`iris.util.describe_diff`.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + # import iris tests first so that some things can be initialised before # importing anything else import iris.tests as tests import numpy as np -import StringIO import iris.cube from iris.util import describe_diff @@ -33,9 +36,9 @@ def setUp(self): self.cube_b = self.cube_a.copy() def _compare_result(self, cube_a, cube_b): - result_strIO = StringIO.StringIO() - describe_diff(cube_a, cube_b, output_file=result_strIO) - return result_strIO.getvalue() + result_sio = six.StringIO() + describe_diff(cube_a, cube_b, output_file=result_sio) + return result_sio.getvalue() def test_noncommon_array_attributes(self): # test non-common array attribute diff --git a/lib/iris/tests/unit/util/test_file_is_newer_than.py b/lib/iris/tests/unit/util/test_file_is_newer_than.py index d770bd5097..9a7c9ac20d 100644 --- a/lib/iris/tests/unit/util/test_file_is_newer_than.py +++ b/lib/iris/tests/unit/util/test_file_is_newer_than.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -18,6 +18,11 @@ Test function :func:`iris.util.test_file_is_newer`. """ + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + # import iris tests first so that some things can be initialised before # importing anything else import iris.tests as tests @@ -62,7 +67,7 @@ def _test(self, boolean_result, result_name, source_names): """Test expected result of executing with given args.""" # Make args into full paths result_path = self._name2path(result_name) - if isinstance(source_names, basestring): + if isinstance(source_names, six.string_types): source_paths = self._name2path(source_names) else: source_paths = [self._name2path(name) @@ -116,14 +121,14 @@ def test_error_missing_result(self): def test_error_missing_source(self): with self.assertRaises(IOError) as error_trap: self._test(False, 'example_result', ['older_sour*', 'non_exist']) - self.assertTrue(error_trap.exception.message.startswith( - 'One or more of the files specified did not exist')) + self.assertIn('One or more of the files specified did not exist', + str(error_trap.exception)) def test_error_missing_wild(self): with self.assertRaises(IOError) as error_trap: self._test(False, 'example_result', ['older_sour*', 'unknown_*']) - self.assertTrue(error_trap.exception.message.startswith( - 'One or more of the files specified did not exist')) + self.assertIn('One or more of the files specified did not exist', + str(error_trap.exception)) if __name__ == '__main__': diff --git a/lib/iris/tests/unit/util/test_find_discontiguities.py b/lib/iris/tests/unit/util/test_find_discontiguities.py new file mode 100644 index 0000000000..eeaae1596c --- /dev/null +++ b/lib/iris/tests/unit/util/test_find_discontiguities.py @@ -0,0 +1,99 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Test function :func:`iris.util.find_discontiguities""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np + +from iris.tests.stock import simple_3d +from iris.tests.stock import sample_2d_latlons +from iris.tests.stock import make_bounds_discontiguous_at_point + +from iris.util import find_discontiguities + + +def full2d_global(): + return sample_2d_latlons(transformed=True) + + +@tests.skip_data +class Test(tests.IrisTest): + def setUp(self): + # Set up a 2d lat-lon cube with 2d coordinates that have been + # transformed so they are not in a regular lat-lon grid. + # Then generate a discontiguity at a single lat-lon point. + self.testcube_discontig = full2d_global() + make_bounds_discontiguous_at_point(self.testcube_discontig, 3, 3) + # Repeat that for a discontiguity in the grid 'Y' direction. + self.testcube_discontig_along_y = full2d_global() + make_bounds_discontiguous_at_point(self.testcube_discontig_along_y, + 2, 4, in_y=True) + + def test_find_discontiguities(self): + # Check that the mask we generate when making the discontiguity + # matches that generated by find_discontiguities + cube = self.testcube_discontig + expected = cube.data.mask + returned = find_discontiguities(cube) + self.assertTrue(np.all(expected == returned)) + + def test_find_discontiguities_in_y(self): + # Check that the mask we generate when making the discontiguity + # matches that generated by find_discontiguities + cube = self.testcube_discontig_along_y + expected = cube.data.mask + returned = find_discontiguities(cube) + self.assertTrue(np.all(expected == returned)) + + def test_find_discontiguities_1d_coord(self): + # Check that an error is raised when we try and use + # find_discontiguities on 1D coordinates: + cube = simple_3d() + with self.assertRaises(NotImplementedError): + find_discontiguities(cube) + + def test_find_discontiguities_with_atol(self): + cube = self.testcube_discontig + # Choose a very large absolute tolerance which will result in fine + # discontiguities being disregarded + atol = 100 + # Construct an array the size of the points array filled with 'False' + # to represent a mask showing no discontiguities + expected = np.zeros(cube.shape, dtype=bool) + returned = find_discontiguities(cube, abs_tol=atol) + self.assertTrue(np.all(expected == returned)) + + def test_find_discontiguities_with_rtol(self): + cube = self.testcube_discontig + # Choose a very large relative tolerance which will result in fine + # discontiguities being disregarded + rtol = 1000 + # Construct an array the size of the points array filled with 'False' + # to represent a mask showing no discontiguities + expected = np.zeros(cube.shape, dtype=bool) + returned = find_discontiguities(cube, rel_tol=rtol) + self.assertTrue(np.all(expected == returned)) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/util/test_mask_cube.py b/lib/iris/tests/unit/util/test_mask_cube.py new file mode 100644 index 0000000000..ce14662174 --- /dev/null +++ b/lib/iris/tests/unit/util/test_mask_cube.py @@ -0,0 +1,61 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Test function :func:`iris.util.mask_cube""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import numpy as np +import numpy.ma as ma + +from iris.util import mask_cube +from iris.tests.stock import sample_2d_latlons +from iris.tests.stock import make_bounds_discontiguous_at_point + + +def full2d_global(): + return sample_2d_latlons(transformed=True) + + +@tests.skip_data +class Test(tests.IrisTest): + def setUp(self): + # Set up a 2d cube with a masked discontiguity to test masking + # of 2-dimensional cubes + self.cube_2d = full2d_global() + make_bounds_discontiguous_at_point(self.cube_2d, 3, 3) + + def test_mask_cube_2d(self): + # This tests the masking of a 2d data array + cube = self.cube_2d + discontiguity_array = ma.getmaskarray(cube.data).copy() + expected = cube.copy() + + # Remove mask so that we can pass an unmasked data set to + # mask_discontiguities, and check that it masks the correct point by + # comparing with masked data + cube.data.mask = ma.nomask + returned = mask_cube(cube, discontiguity_array) + self.assertTrue(np.all(expected.data.mask == returned.data.mask)) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/tests/unit/util/test_new_axis.py b/lib/iris/tests/unit/util/test_new_axis.py index 44fe47b8a7..0f40d92426 100644 --- a/lib/iris/tests/unit/util/test_new_axis.py +++ b/lib/iris/tests/unit/util/test_new_axis.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -16,11 +16,16 @@ # along with Iris. If not, see . """Test function :func:`iris.util.new_axis`.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests +import iris.tests.stock as stock import copy +from iris._lazy_data import as_lazy_data import numpy as np import unittest @@ -131,6 +136,23 @@ def test_maint_factory(self): self.assertEqual(res, com) self._assert_cube_notis(res, cube) + def test_lazy_data(self): + cube = iris.cube.Cube(as_lazy_data(self.data)) + cube.add_aux_coord(iris.coords.DimCoord([1], standard_name='time')) + res = new_axis(cube, 'time') + self.assertTrue(cube.has_lazy_data()) + self.assertTrue(res.has_lazy_data()) + self.assertEqual(res.shape, (1,) + cube.shape) + + def test_masked_unit_array(self): + cube = stock.simple_3d_mask() + test_cube = cube[0, 0, 0] + test_cube = new_axis(test_cube, 'longitude') + test_cube = new_axis(test_cube, 'latitude') + data_shape = test_cube.data.shape + mask_shape = test_cube.data.mask.shape + self.assertEqual(data_shape, mask_shape) + if __name__ == '__main__': unittest.main() diff --git a/lib/iris/tests/unit/util/test_promote_aux_coord_to_dim_coord.py b/lib/iris/tests/unit/util/test_promote_aux_coord_to_dim_coord.py new file mode 100644 index 0000000000..d66dc792c5 --- /dev/null +++ b/lib/iris/tests/unit/util/test_promote_aux_coord_to_dim_coord.py @@ -0,0 +1,108 @@ +# (C) British Crown Copyright 2010 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Test function :func:`iris.util.promote_aux_coord_to_dim_coord`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import unittest + +import iris +import iris.tests.stock as stock +from iris.util import promote_aux_coord_to_dim_coord + + +class Test(tests.IrisTest): + def test_dimension_already_has_dimcoord(self): + cube_a = stock.hybrid_height() + cube_b = cube_a.copy() + promote_aux_coord_to_dim_coord(cube_b, 'model_level_number') + self.assertEqual(cube_b.dim_coords, + (cube_a.coord('model_level_number'),)) + + def test_old_dim_coord_is_now_aux_coord(self): + cube_a = stock.hybrid_height() + cube_b = cube_a.copy() + promote_aux_coord_to_dim_coord(cube_b, 'model_level_number') + self.assertTrue(cube_a.coord('level_height') in cube_b.aux_coords) + + @tests.skip_data + def test_argument_is_coord_instance(self): + cube_a = stock.realistic_4d() + cube_b = cube_a.copy() + promote_aux_coord_to_dim_coord(cube_b, cube_b.coord('level_height')) + self.assertEqual(cube_b.dim_coords, + (cube_a.coord('time'), cube_a.coord('level_height'), + cube_a.coord('grid_latitude'), + cube_a.coord('grid_longitude'))) + + @tests.skip_data + def test_dimension_is_anonymous(self): + cube_a = stock.realistic_4d() + cube_b = cube_a.copy() + cube_b.remove_coord('model_level_number') + promote_aux_coord_to_dim_coord(cube_b, 'level_height') + self.assertEqual(cube_b.dim_coords, + (cube_a.coord('time'), cube_a.coord('level_height'), + cube_a.coord('grid_latitude'), + cube_a.coord('grid_longitude'))) + + def test_already_a_dim_coord(self): + cube_a = stock.simple_2d_w_multidim_and_scalars() + cube_b = cube_a.copy() + promote_aux_coord_to_dim_coord(cube_b, 'dim1') + self.assertEqual(cube_a, cube_b) + + def test_coord_of_that_name_does_not_exist(self): + cube_a = stock.simple_2d_w_multidim_and_scalars() + with self.assertRaises(iris.exceptions.CoordinateNotFoundError): + promote_aux_coord_to_dim_coord(cube_a, 'wibble') + + def test_coord_does_not_exist(self): + cube_a = stock.simple_2d_w_multidim_and_scalars() + coord = cube_a.coord('dim1').copy() + coord.rename('new') + with self.assertRaises(ValueError): + promote_aux_coord_to_dim_coord(cube_a, coord) + + def test_argument_is_wrong_type(self): + cube_a = stock.simple_1d() + with self.assertRaises(TypeError): + promote_aux_coord_to_dim_coord(cube_a, 0.0) + + def test_trying_to_promote_a_multidim_coord(self): + cube_a = stock.simple_2d_w_multidim_coords() + with self.assertRaises(ValueError): + promote_aux_coord_to_dim_coord(cube_a, 'bar') + + def test_trying_to_promote_a_scalar_coord(self): + cube_a = stock.simple_2d_w_multidim_and_scalars() + with self.assertRaises(ValueError): + promote_aux_coord_to_dim_coord(cube_a, 'an_other') + + def test_trying_to_promote_a_nonmonotonic_coord(self): + cube_a = stock.hybrid_height() + with self.assertRaises(ValueError): + promote_aux_coord_to_dim_coord(cube_a, 'surface_altitude') + + +if __name__ == '__main__': + unittest.main() diff --git a/lib/iris/tests/unit/util/test_reverse.py b/lib/iris/tests/unit/util/test_reverse.py new file mode 100644 index 0000000000..f5a21d259b --- /dev/null +++ b/lib/iris/tests/unit/util/test_reverse.py @@ -0,0 +1,185 @@ +# (C) British Crown Copyright 2018, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Test function :func:`iris.util.reverse`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import unittest + +import iris +from iris.util import reverse +import numpy as np + + +class Test_array(tests.IrisTest): + def test_simple_array(self): + a = np.arange(12).reshape(3, 4) + self.assertArrayEqual(a[::-1], reverse(a, 0)) + self.assertArrayEqual(a[::-1, ::-1], reverse(a, [0, 1])) + self.assertArrayEqual(a[:, ::-1], reverse(a, 1)) + self.assertArrayEqual(a[:, ::-1], reverse(a, [1])) + + msg = 'Reverse was expecting a single axis or a 1d array *' + with self.assertRaisesRegexp(ValueError, msg): + reverse(a, []) + + msg = 'An axis value out of range for the number of dimensions *' + with self.assertRaisesRegexp(ValueError, msg): + reverse(a, -1) + with self.assertRaisesRegexp(ValueError, msg): + reverse(a, 10) + with self.assertRaisesRegexp(ValueError, msg): + reverse(a, [-1]) + with self.assertRaisesRegexp(ValueError, msg): + reverse(a, [0, -1]) + + msg = 'To reverse an array, provide an int *' + with self.assertRaisesRegexp(TypeError, msg): + reverse(a, 'latitude') + + def test_single_array(self): + a = np.arange(36).reshape(3, 4, 3) + self.assertArrayEqual(a[::-1], reverse(a, 0)) + self.assertArrayEqual(a[::-1, ::-1], reverse(a, [0, 1])) + self.assertArrayEqual(a[:, ::-1, ::-1], reverse(a, [1, 2])) + self.assertArrayEqual(a[..., ::-1], reverse(a, 2)) + + msg = 'Reverse was expecting a single axis or a 1d array *' + with self.assertRaisesRegexp(ValueError, msg): + reverse(a, []) + + msg = 'An axis value out of range for the number of dimensions *' + with self.assertRaisesRegexp(ValueError, msg): + reverse(a, -1) + with self.assertRaisesRegexp(ValueError, msg): + reverse(a, 10) + with self.assertRaisesRegexp(ValueError, msg): + reverse(a, [-1]) + with self.assertRaisesRegexp(ValueError, msg): + reverse(a, [0, -1]) + + with self.assertRaisesRegexp( + TypeError, 'To reverse an array, provide an int *'): + reverse(a, 'latitude') + + +class Test_cube(tests.IrisTest): + def setUp(self): + # On this cube pair, the coordinates to perform operations on have + # matching long names but the points array on one cube is reversed + # with respect to that on the other. + data = np.arange(12).reshape(3, 4) + self.a1 = iris.coords.DimCoord([1, 2, 3], long_name='a') + self.b1 = iris.coords.DimCoord([1, 2, 3, 4], long_name='b') + a2 = iris.coords.DimCoord([3, 2, 1], long_name='a') + b2 = iris.coords.DimCoord([4, 3, 2, 1], long_name='b') + self.span = iris.coords.AuxCoord(np.arange(12).reshape(3, 4), + long_name='spanning') + + self.cube1 = iris.cube.Cube( + data, dim_coords_and_dims=[(self.a1, 0), (self.b1, 1)], + aux_coords_and_dims=[(self.span, (0, 1))]) + + self.cube2 = iris.cube.Cube( + data, dim_coords_and_dims=[(a2, 0), (b2, 1)]) + + def test_cube_dim(self): + cube1_reverse0 = reverse(self.cube1, 0) + cube1_reverse1 = reverse(self.cube1, 1) + cube1_reverse_both = reverse(self.cube1, (0, 1)) + + self.assertArrayEqual(self.cube1.data[::-1], cube1_reverse0.data) + self.assertArrayEqual(self.cube2.coord('a').points, + cube1_reverse0.coord('a').points) + self.assertArrayEqual(self.cube1.coord('b').points, + cube1_reverse0.coord('b').points) + + self.assertArrayEqual(self.cube1.data[:, ::-1], cube1_reverse1.data) + self.assertArrayEqual(self.cube1.coord('a').points, + cube1_reverse1.coord('a').points) + self.assertArrayEqual(self.cube2.coord('b').points, + cube1_reverse1.coord('b').points) + + self.assertArrayEqual(self.cube1.data[::-1, ::-1], + cube1_reverse_both.data) + self.assertArrayEqual(self.cube2.coord('a').points, + cube1_reverse_both.coord('a').points) + self.assertArrayEqual(self.cube2.coord('b').points, + cube1_reverse_both.coord('b').points) + + def test_cube_coord(self): + cube1_reverse0 = reverse(self.cube1, self.a1) + cube1_reverse1 = reverse(self.cube1, 'b') + cube1_reverse_both = reverse(self.cube1, (self.a1, self.b1)) + cube1_reverse_spanning = reverse(self.cube1, 'spanning') + + self.assertArrayEqual(self.cube1.data[::-1], cube1_reverse0.data) + self.assertArrayEqual(self.cube2.coord('a').points, + cube1_reverse0.coord('a').points) + self.assertArrayEqual(self.cube1.coord('b').points, + cube1_reverse0.coord('b').points) + + self.assertArrayEqual(self.cube1.data[:, ::-1], cube1_reverse1.data) + self.assertArrayEqual(self.cube1.coord('a').points, + cube1_reverse1.coord('a').points) + self.assertArrayEqual(self.cube2.coord('b').points, + cube1_reverse1.coord('b').points) + + self.assertArrayEqual(self.cube1.data[::-1, ::-1], + cube1_reverse_both.data) + self.assertArrayEqual(self.cube2.coord('a').points, + cube1_reverse_both.coord('a').points) + self.assertArrayEqual(self.cube2.coord('b').points, + cube1_reverse_both.coord('b').points) + + self.assertArrayEqual(self.cube1.data[::-1, ::-1], + cube1_reverse_spanning.data) + self.assertArrayEqual(self.cube2.coord('a').points, + cube1_reverse_spanning.coord('a').points) + self.assertArrayEqual(self.cube2.coord('b').points, + cube1_reverse_spanning.coord('b').points) + self.assertArrayEqual( + self.span.points[::-1, ::-1], + cube1_reverse_spanning.coord('spanning').points) + + msg = 'Expected to find exactly 1 latitude coordinate, but found none.' + with self.assertRaisesRegexp( + iris.exceptions.CoordinateNotFoundError, msg): + reverse(self.cube1, 'latitude') + + msg = 'Reverse was expecting a single axis or a 1d array *' + with self.assertRaisesRegexp(ValueError, msg): + reverse(self.cube1, []) + + msg = ('coords_or_dims must be int, str, coordinate or sequence of ' + 'these. Got cube.') + with self.assertRaisesRegexp(TypeError, msg): + reverse(self.cube1, self.cube1) + + msg = ('coords_or_dims must be int, str, coordinate or sequence of ' + 'these.') + with self.assertRaisesRegexp(TypeError, msg): + reverse(self.cube1, 3.) + + +if __name__ == '__main__': + unittest.main() diff --git a/lib/iris/tests/unit/util/test_rolling_window.py b/lib/iris/tests/unit/util/test_rolling_window.py index aaa876f941..cee5fad7a9 100644 --- a/lib/iris/tests/unit/util/test_rolling_window.py +++ b/lib/iris/tests/unit/util/test_rolling_window.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office +# (C) British Crown Copyright 2013 - 2015, Met Office # # This file is part of Iris. # @@ -16,6 +16,8 @@ # along with Iris. If not, see . """Test function :func:`iris.util.rolling_window`.""" +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa # import iris tests first so that some things can be initialised before # importing anything else diff --git a/lib/iris/tests/unit/util/test_squeeze.py b/lib/iris/tests/unit/util/test_squeeze.py new file mode 100644 index 0000000000..a1bc8d271e --- /dev/null +++ b/lib/iris/tests/unit/util/test_squeeze.py @@ -0,0 +1,66 @@ +# (C) British Crown Copyright 2010 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Test function :func:`iris.util.squeeze`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import unittest + +import iris +import iris.tests.stock as stock + + +class Test(tests.IrisTest): + + def setUp(self): + self.cube = stock.simple_2d_w_multidim_and_scalars() + + def test_no_change(self): + self.assertEqual(self.cube, iris.util.squeeze(self.cube)) + + def test_squeeze_one_dim(self): + cube_3d = iris.util.new_axis(self.cube, scalar_coord='an_other') + cube_2d = iris.util.squeeze(cube_3d) + + self.assertEqual(self.cube, cube_2d) + + def test_squeeze_two_dims(self): + cube_3d = iris.util.new_axis(self.cube, scalar_coord='an_other') + cube_4d = iris.util.new_axis(cube_3d, scalar_coord='air_temperature') + + self.assertEqual(self.cube, iris.util.squeeze(cube_4d)) + + def test_squeeze_one_anonymous_dim(self): + cube_3d = iris.util.new_axis(self.cube) + cube_2d = iris.util.squeeze(cube_3d) + + self.assertEqual(self.cube, cube_2d) + + def test_squeeze_to_scalar_cube(self): + cube_scalar = self.cube[0, 0] + cube_1d = iris.util.new_axis(cube_scalar) + + self.assertEqual(cube_scalar, iris.util.squeeze(cube_1d)) + + +if __name__ == '__main__': + unittest.main() diff --git a/lib/iris/tests/unit/util/test_unify_time_units.py b/lib/iris/tests/unit/util/test_unify_time_units.py new file mode 100644 index 0000000000..a0a9f77a58 --- /dev/null +++ b/lib/iris/tests/unit/util/test_unify_time_units.py @@ -0,0 +1,124 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Test function :func:`iris.util.array_equal`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +import copy + +import cf_units +import numpy as np + +import iris +import iris.tests.stock as stock +from iris.util import unify_time_units + + +class Test(tests.IrisTest): + def simple_1d_time_cubes(self, calendar='gregorian'): + coord_points = [1, 2, 3, 4, 5] + data_points = [273, 275, 278, 277, 274] + reftimes = ['hours since 1970-01-01 00:00:00', + 'hours since 1970-01-02 00:00:00'] + list_of_cubes = [] + for reftime in reftimes: + cube = iris.cube.Cube(np.array(data_points, dtype=np.float32), + standard_name='air_temperature', + units='K') + unit = cf_units.Unit(reftime, calendar=calendar) + coord = iris.coords.DimCoord(points=np.array(coord_points, + dtype=np.float32), + standard_name='time', + units=unit) + cube.add_dim_coord(coord, 0) + list_of_cubes.append(cube) + return list_of_cubes + + def _common(self, expected, result, coord_name='time'): + # This tests time-like coords only. + for cube in result: + try: + epoch = cube.coord(coord_name).units.origin + except iris.exceptions.CoordinateNotFoundError: + pass + else: + self.assertEqual(expected, epoch) + + def test_cubelist_with_time_coords(self): + # Tests an :class:`iris.cube.CubeList` containing cubes with time + # coords against a time string and a time coord. + cubelist = iris.cube.CubeList(self.simple_1d_time_cubes()) + expected = 'hours since 1970-01-01 00:00:00' + unify_time_units(cubelist) + self._common(expected, cubelist) + + def test_list_of_cubes_with_time_coords(self): + # Tests an iterable containing cubes with time coords against a time + # string and a time coord. + list_of_cubes = self.simple_1d_time_cubes() + expected = 'hours since 1970-01-01 00:00:00' + unify_time_units(list_of_cubes) + self._common(expected, list_of_cubes) + + @tests.skip_data + def test_no_time_coord_in_cubes(self): + path0 = tests.get_data_path(('PP', 'aPPglob1', 'global.pp')) + path1 = tests.get_data_path(('PP', 'aPPglob1', 'global_t_forecast.pp')) + cube0 = iris.load_cube(path0) + cube1 = iris.load_cube(path1) + cubes = iris.cube.CubeList([cube0, cube1]) + result = copy.copy(cubes) + unify_time_units(result) + self.assertEqual(cubes, result) + + def test_time_coord_only_in_some_cubes(self): + list_of_cubes = self.simple_1d_time_cubes() + cube = stock.simple_2d() + list_of_cubes.append(cube) + expected = 'hours since 1970-01-01 00:00:00' + unify_time_units(list_of_cubes) + self._common(expected, list_of_cubes) + + def test_multiple_time_coords_in_cube(self): + cube0, cube1 = self.simple_1d_time_cubes() + units = cf_units.Unit('days since 1980-05-02 00:00:00', + calendar='gregorian') + aux_coord = iris.coords.AuxCoord( + 72, standard_name='forecast_reference_time', units=units) + cube1.add_aux_coord(aux_coord) + cubelist = iris.cube.CubeList([cube0, cube1]) + expected = 'hours since 1970-01-01 00:00:00' + unify_time_units(cubelist) + self._common(expected, cubelist) + self._common(expected, cubelist, coord_name='forecast_reference_time') + + def test_multiple_calendars(self): + cube0, cube1 = self.simple_1d_time_cubes() + cube2, cube3 = self.simple_1d_time_cubes(calendar='360_day') + cubelist = iris.cube.CubeList([cube0, cube1, cube2, cube3]) + expected = 'hours since 1970-01-01 00:00:00' + unify_time_units(cubelist) + self._common(expected, cubelist) + + +if __name__ == '__main__': + tests.main() diff --git a/lib/iris/time.py b/lib/iris/time.py index 4f25edc406..ef02b4dbfc 100644 --- a/lib/iris/time.py +++ b/lib/iris/time.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2014, Met Office +# (C) British Crown Copyright 2013 - 2018, Met Office # # This file is part of Iris. # @@ -18,12 +18,11 @@ Time handling. """ -import collections -import datetime -import functools -import operator -import netcdftime +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import functools @functools.total_ordering @@ -36,7 +35,7 @@ class PartialDateTime(object): Comparisons are defined against any other class with all of the attributes: year, month, day, hour, minute, and second. Notably, this includes :class:`datetime.datetime` and - :class:`netcdftime.datetime`. Comparison also extends to the + :class:`cftime.datetime`. Comparison also extends to the microsecond attribute for classes, such as :class:`datetime.datetime`, which define it. diff --git a/lib/iris/unit.py b/lib/iris/unit.py deleted file mode 100644 index 0b8b358e34..0000000000 --- a/lib/iris/unit.py +++ /dev/null @@ -1,1968 +0,0 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -""" -Units of measure. - -Provision of a wrapper class to support Unidata/UCAR UDUNITS-2, and the -netcdftime calendar functionality. - -See also: `UDUNITS-2 -`_. - -""" - -from __future__ import division - -import copy -import ctypes -import ctypes.util -import warnings - -import netcdftime -import numpy as np - -import iris.config -import iris.util - - -__all__ = ['Unit', 'date2num', 'decode_time', 'encode_clock', 'encode_date', - 'encode_time', 'num2date'] - - -######################################################################## -# -# module level constants -# -######################################################################## - -# -# default constants -# -IRIS_EPOCH = '1970-01-01 00:00:00' -_STRING_BUFFER_DEPTH = 128 -_UNKNOWN_UNIT_STRING = 'unknown' -_UNKNOWN_UNIT_SYMBOL = '?' -_UNKNOWN_UNIT = [_UNKNOWN_UNIT_STRING, _UNKNOWN_UNIT_SYMBOL, '???', ''] -_NO_UNIT_STRING = 'no_unit' -_NO_UNIT_SYMBOL = '-' -_NO_UNIT = [_NO_UNIT_STRING, _NO_UNIT_SYMBOL, 'no unit', 'no-unit', 'nounit'] -_UNIT_DIMENSIONLESS = '1' -_OP_SINCE = ' since ' -_CATEGORY_UNKNOWN, _CATEGORY_NO_UNIT, _CATEGORY_UDUNIT = range(3) - - -# -# libudunits2 constants -# -# ut_status enumerations -_UT_STATUS = ['UT_SUCCESS', 'UT_BAD_ARG', 'UT_EXISTS', 'UT_NO_UNIT', - 'UT_OS', 'UT_NOT_SAME_NAME', 'UT_MEANINGLESS', 'UT_NO_SECOND', - 'UT_VISIT_ERROR', 'UT_CANT_FORMAT', 'UT_SYNTAX', 'UT_UNKNOWN', - 'UT_OPEN_ARG', 'UT_OPEN_ENV', 'UT_OPEN_DEFAULT', 'UT_PARSE'] - -# explicit function names -_UT_HANDLER = 'ut_set_error_message_handler' -_UT_IGNORE = 'ut_ignore' - -# ut_encoding enumerations -UT_ASCII = 0 -UT_ISO_8859_1 = 1 -UT_LATIN1 = 1 -UT_UTF8 = 2 -UT_NAMES = 4 -UT_DEFINITION = 8 - -UT_FORMATS = [UT_ASCII, UT_ISO_8859_1, UT_LATIN1, UT_UTF8, UT_NAMES, - UT_DEFINITION] - -# -# netcdftime constants -# -CALENDAR_STANDARD = 'standard' -CALENDAR_GREGORIAN = 'gregorian' -CALENDAR_PROLEPTIC_GREGORIAN = 'proleptic_gregorian' -CALENDAR_NO_LEAP = 'noleap' -CALENDAR_JULIAN = 'julian' -CALENDAR_ALL_LEAP = 'all_leap' -CALENDAR_365_DAY = '365_day' -CALENDAR_366_DAY = '366_day' -CALENDAR_360_DAY = '360_day' - -CALENDARS = [CALENDAR_STANDARD, CALENDAR_GREGORIAN, - CALENDAR_PROLEPTIC_GREGORIAN, CALENDAR_NO_LEAP, CALENDAR_JULIAN, - CALENDAR_ALL_LEAP, CALENDAR_365_DAY, CALENDAR_366_DAY, - CALENDAR_360_DAY] - -# -# ctypes types -# -FLOAT32 = ctypes.c_float -FLOAT64 = ctypes.c_double - -######################################################################## -# -# module level variables -# -######################################################################## - -# cache for ctypes foreign shared library handles -_lib_c = None -_lib_ud = None -_ud_system = None - -# cache for libc shared library functions -_strerror = None - -# class cache for libudunits2 shared library functions -_cv_convert_float = None -_cv_convert_floats = None -_cv_convert_double = None -_cv_convert_doubles = None -_cv_free = None -_ut_are_convertible = None -_ut_clone = None -_ut_compare = None -_ut_decode_time = None -_ut_divide = None -_ut_encode_clock = None -_ut_encode_date = None -_ut_encode_time = None -_ut_format = None -_ut_free = None -_ut_get_converter = None -_ut_get_status = None -_ut_get_unit_by_name = None -_ut_ignore = None -_ut_invert = None -_ut_is_dimensionless = None -_ut_log = None -_ut_multiply = None -_ut_offset = None -_ut_offset_by_time = None -_ut_parse = None -_ut_raise = None -_ut_read_xml = None -_ut_root = None -_ut_scale = None -_ut_set_error_message_handler = None - -######################################################################## -# -# module level statements -# -######################################################################## - -# -# load the libc shared library -# -if _lib_c is None: - _lib_c = ctypes.CDLL(ctypes.util.find_library('libc')) - - # - # cache common shared library functions - # - _strerror = _lib_c.strerror - _strerror.restype = ctypes.c_char_p - -# -# load the libudunits2 shared library -# -if _lib_ud is None: - _lib_ud = iris.config.get_option( - 'System', 'udunits2_path', - default=ctypes.util.find_library('udunits2')) - _lib_ud = ctypes.CDLL(_lib_ud, use_errno=True) - - # - # cache common shared library functions - # - _cv_convert_float = _lib_ud.cv_convert_float - _cv_convert_float.argtypes = [ctypes.c_void_p, ctypes.c_float] - _cv_convert_float.restype = ctypes.c_float - - _cv_convert_floats = _lib_ud.cv_convert_floats - _cv_convert_floats.argtypes = [ctypes.c_void_p, ctypes.c_void_p, - ctypes.c_ulong, ctypes.c_void_p] - _cv_convert_floats.restype = ctypes.c_void_p - - _cv_convert_double = _lib_ud.cv_convert_double - _cv_convert_double.argtypes = [ctypes.c_void_p, ctypes.c_double] - _cv_convert_double.restype = ctypes.c_double - - _cv_convert_doubles = _lib_ud.cv_convert_doubles - _cv_convert_doubles.argtypes = [ctypes.c_void_p, ctypes.c_void_p, - ctypes.c_ulong, ctypes.c_void_p] - _cv_convert_doubles.restype = ctypes.c_void_p - - _cv_free = _lib_ud.cv_free - _cv_free.argtypes = [ctypes.c_void_p] - - _ut_are_convertible = _lib_ud.ut_are_convertible - _ut_are_convertible.argtypes = [ctypes.c_void_p, ctypes.c_void_p] - - _ut_clone = _lib_ud.ut_clone - _ut_clone.argtypes = [ctypes.c_void_p] - _ut_clone.restype = ctypes.c_void_p - - _ut_compare = _lib_ud.ut_compare - _ut_compare.argtypes = [ctypes.c_void_p, ctypes.c_void_p] - _ut_compare.restype = ctypes.c_int - - _ut_decode_time = _lib_ud.ut_decode_time - _ut_decode_time.restype = None - - _ut_divide = _lib_ud.ut_divide - _ut_divide.argtypes = [ctypes.c_void_p, ctypes.c_void_p] - _ut_divide.restype = ctypes.c_void_p - - _ut_encode_clock = _lib_ud.ut_encode_clock - _ut_encode_clock.restype = ctypes.c_double - - _ut_encode_date = _lib_ud.ut_encode_date - _ut_encode_date.restype = ctypes.c_double - - _ut_encode_time = _lib_ud.ut_encode_time - _ut_encode_time.restype = ctypes.c_double - - _ut_format = _lib_ud.ut_format - _ut_format.argtypes = [ctypes.c_void_p, ctypes.c_char_p, - ctypes.c_ulong, ctypes.c_uint] - - _ut_free = _lib_ud.ut_free - _ut_free.argtypes = [ctypes.c_void_p] - _ut_free.restype = None - - _ut_get_converter = _lib_ud.ut_get_converter - _ut_get_converter.argtypes = [ctypes.c_void_p, ctypes.c_void_p] - _ut_get_converter.restype = ctypes.c_void_p - - _ut_get_status = _lib_ud.ut_get_status - - _ut_get_unit_by_name = _lib_ud.ut_get_unit_by_name - _ut_get_unit_by_name.argtypes = [ctypes.c_void_p, ctypes.c_char_p] - _ut_get_unit_by_name.restype = ctypes.c_void_p - - _ut_invert = _lib_ud.ut_invert - _ut_invert.argtypes = [ctypes.c_void_p] - _ut_invert.restype = ctypes.c_void_p - - _ut_is_dimensionless = _lib_ud.ut_is_dimensionless - _ut_is_dimensionless.argtypes = [ctypes.c_void_p] - - _ut_log = _lib_ud.ut_log - _ut_log.argtypes = [ctypes.c_double, ctypes.c_void_p] - _ut_log.restype = ctypes.c_void_p - - _ut_multiply = _lib_ud.ut_multiply - _ut_multiply.argtypes = [ctypes.c_void_p, ctypes.c_void_p] - _ut_multiply.restype = ctypes.c_void_p - - _ut_offset = _lib_ud.ut_offset - _ut_offset.argtypes = [ctypes.c_void_p, ctypes.c_double] - _ut_offset.restype = ctypes.c_void_p - - _ut_offset_by_time = _lib_ud.ut_offset_by_time - _ut_offset_by_time.argtypes = [ctypes.c_void_p, ctypes.c_double] - _ut_offset_by_time.restype = ctypes.c_void_p - - _ut_parse = _lib_ud.ut_parse - _ut_parse.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int] - _ut_parse.restype = ctypes.c_void_p - - _ut_raise = _lib_ud.ut_raise - _ut_raise.argtypes = [ctypes.c_void_p, ctypes.c_int] - _ut_raise.restype = ctypes.c_void_p - - _ut_read_xml = _lib_ud.ut_read_xml - _ut_read_xml.argtypes = [ctypes.c_char_p] - _ut_read_xml.restype = ctypes.c_void_p - - _ut_root = _lib_ud.ut_root - _ut_root.argtypes = [ctypes.c_void_p, ctypes.c_int] - _ut_root.restype = ctypes.c_void_p - - _ut_scale = _lib_ud.ut_scale - _ut_scale.argtypes = [ctypes.c_double, ctypes.c_void_p] - _ut_scale.restype = ctypes.c_void_p - - # convenience dictionary for the Unit convert method - _cv_convert_scalar = {FLOAT32: _cv_convert_float, - FLOAT64: _cv_convert_double} - _cv_convert_array = {FLOAT32: _cv_convert_floats, - FLOAT64: _cv_convert_doubles} - _numpy2ctypes = {np.float32: FLOAT32, np.float64: FLOAT64} - _ctypes2numpy = {v: k for k, v in _numpy2ctypes.iteritems()} -# -# load the UDUNITS-2 xml-formatted unit-database -# -if not _ud_system: - _func_type = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_char_p, - use_errno=True) - _set_handler_type = ctypes.CFUNCTYPE(_func_type, _func_type) - _ut_set_error_message_handler = _set_handler_type((_UT_HANDLER, _lib_ud)) - _ut_ignore = _func_type((_UT_IGNORE, _lib_ud)) - # ignore standard UDUNITS-2 start-up preamble redirected to stderr stream - _default_handler = _ut_set_error_message_handler(_ut_ignore) - # load the unit-database - _ud_system = _ut_read_xml(None) - # reinstate old error handler - _ut_set_error_message_handler(_default_handler) - del _func_type - if not _ud_system: - _status_msg = 'UNKNOWN' - _error_msg = '' - _status = _ut_get_status() - try: - _status_msg = _UT_STATUS[_status] - except IndexError: - pass - _errno = ctypes.get_errno() - if _errno != 0: - _error_msg = ': "%s"' % _strerror(_errno) - ctypes.set_errno(0) - raise OSError('[%s] Failed to open UDUNITS-2 XML unit database %s' % ( - _status_msg, _error_msg)) - - -######################################################################## -# -# module level function definitions -# -######################################################################## - -def encode_time(year, month, day, hour, minute, second): - """ - Return date/clock time encoded as a double precision value. - - Encoding performed using UDUNITS-2 hybrid Gregorian/Julian calendar. - Dates on or after 1582-10-15 are assumed to be Gregorian dates; - dates before that are assumed to be Julian dates. In particular, the - year 1 BCE is immediately followed by the year 1 CE. - - Args: - - * year (int): - Year value to be encoded. - * month (int): - Month value to be encoded. - * day (int): - Day value to be encoded. - * hour (int): - Hour value to be encoded. - * minute (int): - Minute value to be encoded. - * second (int): - Second value to be encoded. - - Returns: - float. - - For example: - - >>> import iris.unit as unit - >>> unit.encode_time(1970, 1, 1, 0, 0, 0) - -978307200.0 - - """ - - return _ut_encode_time(ctypes.c_int(year), ctypes.c_int(month), - ctypes.c_int(day), ctypes.c_int(hour), - ctypes.c_int(minute), ctypes.c_double(second)) - - -def encode_date(year, month, day): - """ - Return date encoded as a double precision value. - - Encoding performed using UDUNITS-2 hybrid Gergorian/Julian calendar. - Dates on or after 1582-10-15 are assumed to be Gregorian dates; - dates before that are assumed to be Julian dates. In particular, the - year 1 BCE is immediately followed by the year 1 CE. - - Args: - - * year (int): - Year value to be encoded. - * month (int): - Month value to be encoded. - * day (int): - Day value to be encoded. - - Returns: - float. - - For example: - - >>> import iris.unit as unit - >>> unit.encode_date(1970, 1, 1) - -978307200.0 - - """ - - return _ut_encode_date(ctypes.c_int(year), ctypes.c_int(month), - ctypes.c_int(day)) - - -def encode_clock(hour, minute, second): - """ - Return clock time encoded as a double precision value. - - Args: - - * hour (int): - Hour value to be encoded. - * minute (int): - Minute value to be encoded. - * second (int): - Second value to be encoded. - - Returns: - float. - - For example: - - >>> import iris.unit as unit - >>> unit.encode_clock(0, 0, 0) - 0.0 - - """ - - return _ut_encode_clock(ctypes.c_int(hour), ctypes.c_int(minute), - ctypes.c_double(second)) - - -def decode_time(time): - """ - Decode a double precision date/clock time value into its component - parts and return as tuple. - - Decode time into it's year, month, day, hour, minute, second, and - resolution component parts. Where resolution is the uncertainty of - the time in seconds. - - Args: - - * time (float): Date/clock time encoded as a double precision value. - - Returns: - tuple of (year, month, day, hour, minute, second, resolution). - - For example: - - >>> import iris.unit as unit - >>> unit.decode_time(unit.encode_time(1970, 1, 1, 0, 0, 0)) - (1970, 1, 1, 0, 0, 0.0, 1.086139178596568e-07) - - """ - - year = ctypes.c_int() - month = ctypes.c_int() - day = ctypes.c_int() - hour = ctypes.c_int() - minute = ctypes.c_int() - second = ctypes.c_double() - resolution = ctypes.c_double() - _ut_decode_time(ctypes.c_double(time), ctypes.pointer(year), - ctypes.pointer(month), ctypes.pointer(day), - ctypes.pointer(hour), ctypes.pointer(minute), - ctypes.pointer(second), ctypes.pointer(resolution)) - return (year.value, month.value, day.value, hour.value, minute.value, - second.value, resolution.value) - - -def julian_day2date(julian_day, calendar): - """ - Return a netcdftime datetime-like object representing the Julian day. - - If calendar is 'standard' or 'gregorian', Julian day follows - Julian calendar on and before 1582-10-5, Gregorian calendar after - 1582-10-15. - If calendar is 'proleptic_gregorian', Julian Day follows Gregorian - calendar. - If calendar is 'julian', Julian Day follows Julian calendar. - - The datetime object is a 'real' datetime object if the date falls in - the Gregorian calendar (i.e. calendar is 'proleptic_gregorian', or - calendar is 'standard'/'gregorian' and the date is after 1582-10-15). - Otherwise, it's a 'phony' datetime object which is actually an instance - of netcdftime.datetime. - - Algorithm: - Meeus, Jean (1998) Astronomical Algorithms (2nd Edition). - Willmann-Bell, Virginia. p. 63. - - Args: - - * julian_day (float): - Julian day with a resolution of 1 second. - * calendar (string): - Name of the calendar, see iris.unit.CALENDARS. - - Returns: - datetime or netcdftime.datetime. - - For example: - - >>> import iris.unit as unit - >>> import datetime - >>> unit.julian_day2date( - ... unit.date2julian_day(datetime.datetime(1970, 1, 1, 0, 0, 0), - ... unit.CALENDAR_STANDARD), - ... unit.CALENDAR_STANDARD) - datetime.datetime(1970, 1, 1, 0, 0) - - """ - - return netcdftime.DateFromJulianDay(julian_day, calendar) - - -def date2julian_day(date, calendar): - """ - Return the Julian day (resolution of 1 second) from a netcdftime - datetime-like object. - - If calendar is 'standard' or 'gregorian', Julian day follows Julian - calendar on and before 1582-10-5, Gregorian calendar after 1582-10-15. - If calendar is 'proleptic_gregorian', Julian day follows Gregorian - calendar. - If calendar is 'julian', Julian day follows Julian calendar. - - Algorithm: - Meeus, Jean (1998) Astronomical Algorithms (2nd Edition). - Willmann-Bell, Virginia. p. 63. - - Args: - - * date (netcdftime.date): - Date and time representation. - * calendar (string): - Name of the calendar, see iris.unit.CALENDARS. - - Returns: - float. - - For example: - - >>> import iris.unit as unit - >>> import datetime - >>> unit.date2julian_day(datetime.datetime(1970, 1, 1, 0, 0, 0), - ... unit.CALENDAR_STANDARD) - 2440587.5 - - """ - - return netcdftime.JulianDayFromDate(date, calendar) - - -def date2num(date, unit, calendar): - """ - Return numeric time value (resolution of 1 second) encoding of - datetime object. - - The units of the numeric time values are described by the unit and - calendar arguments. The datetime objects must be in UTC with no - time-zone offset. If there is a time-zone offset in unit, it will be - applied to the returned numeric values. - - Like the :func:`matplotlib.dates.date2num` function, except that it allows - for different units and calendars. Behaves the same as if - unit = 'days since 0001-01-01 00:00:00' and - calendar = 'proleptic_gregorian'. - - Args: - - * date (datetime): - A datetime object or a sequence of datetime objects. - The datetime objects should not include a time-zone offset. - * unit (string): - A string of the form ' since ' describing - the time units. The can be days, hours, minutes or seconds. - The is a date/time reference point. A valid choice - would be unit='hours since 1800-01-01 00:00:00 -6:00'. - * calendar (string): - Name of the calendar, see iris.unit.CALENDARS. - - Returns: - float, or numpy.ndarray of float. - - For example: - - >>> import iris.unit as unit - >>> import datetime - >>> dt1 = datetime.datetime(1970, 1, 1, 6, 0, 0) - >>> dt2 = datetime.datetime(1970, 1, 1, 7, 0, 0) - >>> unit.date2num(dt1, 'hours since 1970-01-01 00:00:00', - ... unit.CALENDAR_STANDARD) - 6.0 - >>> unit.date2num([dt1, dt2], 'hours since 1970-01-01 00:00:00', - ... unit.CALENDAR_STANDARD) - array([ 6., 7.]) - - """ - - # - # ensure to strip out any 'UTC' postfix which is generated by - # UDUNITS-2 formatted output and causes the netcdftime parser - # to choke - # - unit_string = unit.rstrip(" UTC") - if unit_string.endswith(" since epoch"): - unit_string = unit_string.replace("epoch", IRIS_EPOCH) - return netcdftime.date2num(date, unit_string, calendar) - - -def num2date(time_value, unit, calendar): - """ - Return datetime encoding of numeric time value (resolution of 1 second). - - The units of the numeric time value are described by the unit and - calendar arguments. The returned datetime object represent UTC with - no time-zone offset, even if the specified unit contain a time-zone - offset. - - Like the :func:`matplotlib.dates.num2date` function, except that it allows - for different units and calendars. Behaves the same if - unit = 'days since 001-01-01 00:00:00'} - calendar = 'proleptic_gregorian'. - - The datetime instances returned are 'real' python datetime - objects if the date falls in the Gregorian calendar (i.e. - calendar='proleptic_gregorian', or calendar = 'standard' or 'gregorian' - and the date is after 1582-10-15). Otherwise, they are 'phony' datetime - objects which support some but not all the methods of 'real' python - datetime objects. This is because the python datetime module cannot - use the 'proleptic_gregorian' calendar, even before the switch - occured from the Julian calendar in 1582. The datetime instances - do not contain a time-zone offset, even if the specified unit - contains one. - - Args: - - * time_value (float): - Numeric time value/s. Maximum resolution is 1 second. - * unit (sting): - A string of the form ' since ' - describing the time units. The can be days, hours, - minutes or seconds. The is the date/time reference - point. A valid choice would be - unit='hours since 1800-01-01 00:00:00 -6:00'. - * calendar (string): - Name of the calendar, see iris.unit.CALENDARS. - - Returns: - datetime, or numpy.ndarray of datetime object. - - For example: - - >>> import iris.unit as unit - >>> import datetime - >>> unit.num2date(6, 'hours since 1970-01-01 00:00:00', - ... unit.CALENDAR_STANDARD) - datetime.datetime(1970, 1, 1, 6, 0) - >>> unit.num2date([6, 7], 'hours since 1970-01-01 00:00:00', - ... unit.CALENDAR_STANDARD) - array([datetime.datetime(1970, 1, 1, 6, 0), - datetime.datetime(1970, 1, 1, 7, 0)], dtype=object) - - """ - - # - # ensure to strip out any 'UTC' postfix which is generated by - # UDUNITS-2 formatted output and causes the netcdftime parser - # to choke - # - unit_string = unit.rstrip(" UTC") - if unit_string.endswith(" since epoch"): - unit_string = unit_string.replace("epoch", IRIS_EPOCH) - return netcdftime.num2date(time_value, unit_string, calendar) - - -def _handler(func): - """Set the error message handler.""" - - _ut_set_error_message_handler(func) - - -######################################################################## -# -# unit wrapper class for unidata/ucar UDUNITS-2 -# -######################################################################## - -def _Unit(category, ut_unit, calendar=None, origin=None): - unit = iris.util._OrderedHashable.__new__(Unit) - unit._init(category, ut_unit, calendar, origin) - return unit - - -_CACHE = {} - - -def as_unit(unit): - """ - Returns a Unit corresponding to the given unit. - - .. note:: - - If the given unit is already a Unit it will be returned unchanged. - - """ - if isinstance(unit, Unit): - result = unit - else: - result = None - use_cache = isinstance(unit, basestring) or unit is None - if use_cache: - result = _CACHE.get(unit) - if result is None: - result = Unit(unit) - if use_cache: - _CACHE[unit] = result - return result - - -def is_time(unit): - """ - Determine whether the unit is a related SI Unit of time. - - Args: - - * unit (string/Unit): Unit to be compared. - - Returns: - Boolean. - - For example: - - >>> import iris.unit as unit - >>> unit.is_time('hours') - True - >>> unit.is_time('meters') - False - - """ - return as_unit(unit).is_time() - - -def is_vertical(unit): - """ - Determine whether the unit is a related SI Unit of pressure or distance. - - Args: - - * unit (string/Unit): Unit to be compared. - - Returns: - Boolean. - - For example: - - >>> import iris.unit as unit - >>> unit.is_vertical('millibar') - True - >>> unit.is_vertical('km') - True - - """ - return as_unit(unit).is_vertical() - - -class Unit(iris.util._OrderedHashable): - """ - A class to represent S.I. units and support common operations to - manipulate such units in a consistent manner as per UDUNITS-2. - - These operations include scaling the unit, offsetting the unit by a - constant or time, inverting the unit, raising the unit by a power, - taking a root of the unit, taking a log of the unit, multiplying the - unit by a constant or another unit, dividing the unit by a constant - or another unit, comparing units, copying units and converting unit - data to single precision or double precision floating point numbers. - - This class also supports time and calendar defintion and manipulation. - - """ - # Declare the attribute names relevant to the _OrderedHashable behaviour. - _names = ('category', 'ut_unit', 'calendar', 'origin') - - category = None - 'Is this an unknown unit, a no-unit, or a UDUNITS-2 unit.' - - ut_unit = None - 'Reference to the ctypes quantity defining the UDUNITS-2 unit.' - - calendar = None - 'Represents the unit calendar name, see iris.unit.CALENDARS' - - origin = None - 'The original string used to create this unit.' - - __slots__ = () - - def __init__(self, unit, calendar=None): - """ - Create a wrapper instance for UDUNITS-2. - - An optional calendar may be provided for a unit which defines a - time reference of the form ' since ' - i.e. unit='days since 1970-01-01 00:00:00'. For a unit that is a - time reference, the default calendar is 'standard'. - - Accepted calendars are as follows, - - * 'standard' or 'gregorian' - Mixed Gregorian/Julian calendar as - defined by udunits. - * 'proleptic_gregorian' - A Gregorian calendar extended to dates - before 1582-10-15. A year is a leap year if either, - 1. It is divisible by 4 but not by 100, or - 2. It is divisible by 400. - * 'noleap' or '365_day' - A Gregorian calendar without leap - years i.e. all years are 365 days long. - * 'all_leap' or '366_day' - A Gregorian calendar with every year - being a leap year i.e. all years are 366 days long. - * '360_day' - All years are 360 days divided into 30 day months. - * 'julian' - Proleptic Julian calendar, extended to dates after - 1582-10-5. A year is a leap year if it is divisible by 4. - - Args: - - * unit: - Specify the unit as defined by UDUNITS-2. - * calendar (string): - Describes the calendar used in time calculations. The - default is 'standard' or 'gregorian' for a time reference - unit. - - Returns: - - Unit object. - - Units should be set to "no_unit" for values which are strings. - Units can also be set to "unknown" (or None). - For example: - - >>> from iris.unit import Unit - >>> volts = Unit('volts') - >>> no_unit = Unit('no_unit') - >>> unknown = Unit('unknown') - >>> unknown = Unit(None) - - """ - ut_unit = None - calendar_ = None - - if unit is None: - unit = '' - else: - unit = str(unit).strip() - - if unit.lower().endswith(' utc'): - unit = unit[:unit.lower().rfind(' utc')] - - if unit.endswith(" since epoch"): - unit = unit.replace("epoch", IRIS_EPOCH) - - if unit.lower() in _UNKNOWN_UNIT: - # TODO - removing the option of an unknown unit. Currently - # the auto generated MOSIG rules are missing units on a - # number of phenomena which would lead to errors. - # Will be addressed by work on metadata translation. - category = _CATEGORY_UNKNOWN - unit = _UNKNOWN_UNIT_STRING - elif unit.lower() in _NO_UNIT: - category = _CATEGORY_NO_UNIT - unit = _NO_UNIT_STRING - else: - category = _CATEGORY_UDUNIT - ut_unit = _ut_parse(_ud_system, unit, UT_ASCII) - # _ut_parse returns 0 on failure - if ut_unit is None: - self._raise_error('Failed to parse unit "%s"' % unit) - if _OP_SINCE in unit.lower(): - if calendar is None: - calendar_ = CALENDAR_GREGORIAN - elif calendar in CALENDARS: - calendar_ = calendar - else: - raise ValueError('{!r} is an unsupported calendar.'.format( - calendar)) - self._init(category, ut_unit, calendar_, unit) - - def _raise_error(self, msg): - """ - Retrieve the UDUNITS-2 ut_status, the implementation-defined string - corresponding to UDUNITS-2 errno and raise generic exception. - - """ - status_msg = 'UNKNOWN' - error_msg = '' - if _lib_ud: - status = _ut_get_status() - try: - status_msg = _UT_STATUS[status] - except IndexError: - pass - errno = ctypes.get_errno() - if errno != 0: - error_msg = ': "%s"' % _strerror(errno) - ctypes.set_errno(0) - - raise ValueError('[%s] %s %s' % (status_msg, msg, error_msg)) - - # NOTE: - # "__getstate__" and "__setstate__" functions are defined here to - # provide a custom interface for Pickle - # : Pickle "normal" behaviour is just to save/reinstate the object - # dictionary - # : that won't work here, because the "ut_unit" attribute is an - # object handle - # - the corresponding udunits object only exists in the original - # invocation - def __getstate__(self): - # state capture method for Pickle.dump() - # - return the instance data needed to reconstruct a Unit value - return {'unit_text': self.origin, 'calendar': self.calendar} - - def __setstate__(self, state): - # object reconstruction method for Pickle.load() - # intercept the Pickle.load() operation and call own __init__ again - # - this is to ensure a valid ut_unit attribute (as these - # handles aren't persistent) - self.__init__(state['unit_text'], calendar=state['calendar']) - - def __del__(self): - # NB. If Python is terminating then the module global "_ut_free" - # may have already been deleted ... so we check before using it. - if _ut_free: - _ut_free(self.ut_unit) - - def __copy__(self): - return self - - def __deepcopy__(self, memo): - return self - - def is_time(self): - """ - Determine whether this unit is a related SI Unit of time. - - Returns: - Boolean. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('hours') - >>> u.is_time() - True - >>> v = unit.Unit('meter') - >>> v.is_time() - False - - """ - if self.is_unknown() or self.is_no_unit(): - result = False - else: - day = _ut_get_unit_by_name(_ud_system, 'day') - result = _ut_are_convertible(self.ut_unit, day) != 0 - return result - - def is_vertical(self): - """ - Determine whether the unit is a related SI Unit of pressure or - distance. - - Returns: - Boolean. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('millibar') - >>> u.is_vertical() - True - >>> v = unit.Unit('km') - >>> v.is_vertical() - True - - """ - if self.is_unknown() or self.is_no_unit(): - result = False - else: - bar = _ut_get_unit_by_name(_ud_system, 'bar') - result = _ut_are_convertible(self.ut_unit, bar) != 0 - if not result: - meter = _ut_get_unit_by_name(_ud_system, 'meter') - result = _ut_are_convertible(self.ut_unit, meter) != 0 - return result - - def is_udunits(self): - """Return whether the unit is a vaild unit of UDUNITS.""" - return self.ut_unit is not None - - def is_time_reference(self): - """ - Return whether the unit is a time reference unit of the form - ' since ' - i.e. unit='days since 1970-01-01 00:00:00' - - Returns: - Boolean. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('days since epoch') - >>> u.is_time_reference() - True - - """ - return self.calendar is not None - - def title(self, value): - """ - Return the unit value as a title string. - - Args: - - * value (float): Unit value to be incorporated into title string. - - Returns: - string. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('hours since epoch', - ... calendar=unit.CALENDAR_STANDARD) - >>> u.title(10) - '1970-01-01 10:00:00' - - """ - if self.is_time_reference(): - dt = self.num2date(value) - result = dt.strftime('%Y-%m-%d %H:%M:%S') - else: - result = '%s %s' % (str(value), self) - return result - - @property - def modulus(self): - """ - *(read-only)* Return the modulus value of the unit. - - Convenience method that returns the unit modulus value as follows, - * 'radians' - pi*2 - * 'degrees' - 360.0 - * Otherwise None. - - Returns: - float. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('degrees') - >>> u.modulus - 360.0 - - """ - - if self == 'radians': - result = np.pi * 2 - elif self == 'degrees': - result = 360.0 - else: - result = None - return result - - def is_convertible(self, other): - """ - Return whether two units are convertible. - - Args: - - * other (Unit): Unit to be compared. - - Returns: - Boolean. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('meters') - >>> v = unit.Unit('kilometers') - >>> u.is_convertible(v) - True - - """ - other = as_unit(other) - if self.is_unknown() or self.is_no_unit() or other.is_unknown() or \ - other.is_no_unit(): - result = False - else: - result = (self.calendar == other.calendar and - _ut_are_convertible(self.ut_unit, other.ut_unit) != 0) - return result - - def is_dimensionless(self): - """ - Return whether the unit is dimensionless. - - Returns: - Boolean. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('meters') - >>> u.is_dimensionless() - False - >>> u = unit.Unit('1') - >>> u.is_dimensionless() - True - - """ - return (self.category == _CATEGORY_UDUNIT and - bool(_ut_is_dimensionless(self.ut_unit))) - - def is_unknown(self): - """ - Return whether the unit is defined to be an *unknown* unit. - - Returns: - Boolean. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('unknown') - >>> u.is_unknown() - True - >>> u = unit.Unit('meters') - >>> u.is_unknown() - False - - """ - return self.category == _CATEGORY_UNKNOWN - - def is_no_unit(self): - """ - Return whether the unit is defined to be a *no_unit* unit. - - Typically, a quantity such as a string, will have no associated - unit to describe it. Such a class of quantity may be defined - using the *no_unit* unit. - - Returns: - Boolean. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('no unit') - >>> u.is_no_unit() - True - >>> u = unit.Unit('meters') - >>> u.is_no_unit() - False - - """ - return self.category == _CATEGORY_NO_UNIT - - def format(self, option=None): - """ - Return a formatted string representation of the binary unit. - - Args: - - * option (iris.unit.UT_FORMATS): - Set the encoding option of the formatted string representation. - Valid encoding options may be one of the following enumerations: - - * Unit.UT_ASCII - * Unit.UT_ISO_8859_1 - * Unit.UT_LATIN1 - * Unit.UT_UTF8 - * Unit.UT_NAMES - * Unit.UT_DEFINITION - - Multiple options may be combined within a list. The default - option is iris.unit.UT_ASCII. - - Returns: - string. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('meters') - >>> u.format() - 'm' - >>> u.format(unit.UT_NAMES) - 'meter' - >>> u.format(unit.UT_DEFINITION) - 'm' - - """ - if self.is_unknown(): - return _UNKNOWN_UNIT_STRING - elif self.is_no_unit(): - return _NO_UNIT_STRING - else: - bitmask = UT_ASCII - if option is not None: - if not isinstance(option, list): - option = [option] - for i in option: - bitmask |= i - string_buffer = ctypes.create_string_buffer(_STRING_BUFFER_DEPTH) - depth = _ut_format(self.ut_unit, string_buffer, - ctypes.sizeof(string_buffer), bitmask) - if depth < 0: - self._raise_error('Failed to format %r' % self) - return string_buffer.value - - @property - def name(self): - """ - *(read-only)* The full name of the unit. - - Formats the binary unit into a string representation using - method :func:`iris.unit.Unit.format` with keyword argument - option=iris.unit.UT_NAMES. - - Returns: - string. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('watts') - >>> u.name - 'watt' - - """ - return self.format(UT_NAMES) - - @property - def symbol(self): - """ - *(read-only)* The symbolic representation of the unit. - - Formats the binary unit into a string representation using - method :func:`iris.unit.Unit.format`. - - Returns: - string. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('watts') - >>> u.symbol - 'W' - - """ - if self.is_unknown(): - result = _UNKNOWN_UNIT_SYMBOL - elif self.is_no_unit(): - result = _NO_UNIT_SYMBOL - else: - result = self.format() - return result - - @property - def definition(self): - """ - *(read-only)* The symbolic decomposition of the unit. - - Formats the binary unit into a string representation using - method :func:`iris.unit.Unit.format` with keyword argument - option=iris.unit.UT_DEFINITION. - - Returns: - string. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('watts') - >>> u.definition - 'm2.kg.s-3' - - """ - if self.is_unknown(): - result = _UNKNOWN_UNIT_SYMBOL - elif self.is_no_unit(): - result = _NO_UNIT_SYMBOL - else: - result = self.format(UT_DEFINITION) - return result - - def offset_by_time(self, origin): - """ - Returns the time unit offset with respect to the time origin. - - Args: - - * origin (float): Time origin as returned by the - :func:`iris.unit.encode_time` method. - - Returns: - None. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('hours') - >>> u.offset_by_time(unit.encode_time(1970, 1, 1, 0, 0, 0)) - Unit('hour since 1970-01-01 00:00:00.0000000 UTC') - - """ - - if not isinstance(origin, (int, float, long)): - raise TypeError('a numeric type for the origin argument is' - ' required') - ut_unit = _ut_offset_by_time(self.ut_unit, ctypes.c_double(origin)) - if not ut_unit: - self._raise_error('Failed to offset %r' % self) - calendar = None - return _Unit(_CATEGORY_UDUNIT, ut_unit, calendar) - - def invert(self): - """ - Invert the unit i.e. find the reciprocal of the unit, and return - the Unit result. - - Returns: - Unit. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('meters') - >>> u.invert() - Unit('meter^-1') - - """ - if self.is_unknown(): - result = self - elif self.is_no_unit(): - raise ValueError("Cannot invert a 'no-unit'.") - else: - ut_unit = _ut_invert(self.ut_unit) - if not ut_unit: - self._raise_error('Failed to invert %r' % self) - calendar = None - result = _Unit(_CATEGORY_UDUNIT, ut_unit, calendar) - return result - - def root(self, root): - """ - Returns the given root of the unit. - - Args: - - * root (int/long): Value by which the unit root is taken. - - Returns: - None. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('meters^2') - >>> u.root(2) - Unit('meter') - - .. note:: - - Taking a fractional root of a unit is not supported. - - """ - try: - root = ctypes.c_int(root) - except TypeError: - raise TypeError('An int or long type for the root argument' - ' is required') - - if self.is_unknown(): - result = self - elif self.is_no_unit(): - raise ValueError("Cannot take the logarithm of a 'no-unit'.") - else: - # only update the unit if it is not scalar - if self == Unit('1'): - result = self - else: - ut_unit = _ut_root(self.ut_unit, root) - if not ut_unit: - self._raise_error('Failed to take the root of %r' % self) - calendar = None - result = _Unit(_CATEGORY_UDUNIT, ut_unit, calendar) - return result - - def log(self, base): - """ - Returns the logorithmic unit corresponding to the given - logorithmic base. - - Args: - - * base (int/float/long): Value of the logorithmic base. - - Returns: - None. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('meters') - >>> u.log(2) - Unit('lb(re 1 meter)') - - """ - try: - base = ctypes.c_double(base) - except TypeError: - raise TypeError('A numeric type for the base argument is required') - - if self.is_unknown(): - result = self - elif self.is_no_unit(): - raise ValueError("Cannot take the logarithm of a 'no-unit'.") - else: - ut_unit = _ut_log(base, self.ut_unit) - if not ut_unit: - msg = 'Failed to calculate logorithmic base of %r' % self - self._raise_error(msg) - calendar = None - result = _Unit(_CATEGORY_UDUNIT, ut_unit, calendar) - return result - - def __str__(self): - """ - Returns a simple string representation of the unit. - - Returns: - string. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('meters') - >>> str(u) - 'meters' - - """ - return self.origin or self.name - - def __repr__(self): - """ - Returns a string representation of the unit object. - - Returns: - string. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('meters') - >>> repr(u) - "Unit('meters')" - - """ - - if self.calendar is None: - result = "%s('%s')" % (self.__class__.__name__, self) - else: - result = "%s('%s', calendar='%s')" % (self.__class__.__name__, - self, self.calendar) - return result - - def _offset_common(self, offset): - try: - offset = ctypes.c_double(offset) - except TypeError: - result = NotImplemented - else: - if self.is_unknown(): - result = self - elif self.is_no_unit(): - raise ValueError("Cannot offset a 'no-unit'.") - else: - ut_unit = _ut_offset(self.ut_unit, offset) - if not ut_unit: - self._raise_error('Failed to offset %r' % self) - calendar = None - result = _Unit(_CATEGORY_UDUNIT, ut_unit, calendar) - return result - - def __add__(self, other): - return self._offset_common(other) - - def __sub__(self, other): - try: - other = -other - except TypeError: - result = NotImplemented - else: - result = self._offset_common(-other) - return result - - def _op_common(self, other, op_func): - # Convienience method to create a new unit from an operation between - # the units 'self' and 'other'. - - op_label = op_func.__name__.split('_')[1] - - other = as_unit(other) - - if self.is_no_unit() or other.is_no_unit(): - raise ValueError("Cannot %s a 'no-unit'." % op_label) - - if self.is_unknown() or other.is_unknown(): - result = _Unit(_CATEGORY_UNKNOWN, None) - else: - ut_unit = op_func(self.ut_unit, other.ut_unit) - if not ut_unit: - msg = 'Failed to %s %r by %r' % (op_label, self, other) - self._raise_error(msg) - calendar = None - result = _Unit(_CATEGORY_UDUNIT, ut_unit, calendar) - return result - - def __rmul__(self, other): - # NB. Because we've subclassed a tuple, we need to define this to - # prevent the default tuple-repetition behaviour. - # ie. 2 * ('a', 'b') -> ('a', 'b', 'a', 'b') - return self * other - - def __mul__(self, other): - """ - Multiply the self unit by the other scale factor or unit and - return the Unit result. - - Note that, multiplication involving an 'unknown' unit will always - result in an 'unknown' unit. - - Args: - - * other (int/float/long/string/Unit): Multiplication scale - factor or unit. - - Returns: - Unit. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('meters') - >>> v = unit.Unit('hertz') - >>> u*v - Unit('meter-second^-1') - - """ - return self._op_common(other, _ut_multiply) - - def __div__(self, other): - """ - Divide the self unit by the other scale factor or unit and - return the Unit result. - - Note that, division involving an 'unknown' unit will always - result in an 'unknown' unit. - - Args: - - * other (int/float/long/string/Unit): Division scale factor or unit. - - Returns: - Unit. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('m.s-1') - >>> v = unit.Unit('hertz') - >>> u/v - Unit('meter') - - """ - return self._op_common(other, _ut_divide) - - def __truediv__(self, other): - """ - Divide the self unit by the other scale factor or unit and - return the Unit result. - - Note that, division involving an 'unknown' unit will always - result in an 'unknown' unit. - - Args: - - * other (int/float/long/string/Unit): Division scale factor or unit. - - Returns: - Unit. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('m.s-1') - >>> v = unit.Unit('hertz') - >>> u/v - Unit('meter') - - """ - return self.__div__(other) - - def __pow__(self, power): - """ - Raise the unit by the given power and return the Unit result. - - Note that, UDUNITS-2 does not support raising a - non-dimensionless unit by a fractional power. - Approximate floating point power behaviour has been implemented - specifically for Iris. - - Args: - - * power (int/float/long): Value by which the unit power is raised. - - Returns: - Unit. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('meters') - >>> u**2 - Unit('meter^2') - - """ - try: - power = float(power) - except ValueError: - raise TypeError('A numeric value is required for the power' - ' argument.') - - if self.is_unknown(): - result = self - elif self.is_no_unit(): - raise ValueError("Cannot raise the power of a 'no-unit'.") - elif self == Unit('1'): - # 1 ** N -> 1 - result = self - else: - # UDUNITS-2 does not support floating point raise/root. - # But if the power is of the form 1/N, where N is an integer - # (within a certain acceptable accuracy) then we can find the Nth - # root. - if not iris.util.approx_equal(power, 0.0) and abs(power) < 1: - if not iris.util.approx_equal(1 / power, round(1 / power)): - raise ValueError('Cannot raise a unit by a decimal.') - root = int(round(1 / power)) - result = self.root(root) - else: - # Failing that, check for powers which are (very nearly) simple - # integer values. - if not iris.util.approx_equal(power, round(power)): - msg = 'Cannot raise a unit by a decimal (got %s).' % power - raise ValueError(msg) - power = int(round(power)) - - ut_unit = _ut_raise(self.ut_unit, ctypes.c_int(power)) - if not ut_unit: - self._raise_error('Failed to raise the power of %r' % self) - result = _Unit(_CATEGORY_UDUNIT, ut_unit) - return result - - def _identity(self): - # Redefine the comparison/hash/ordering identity as used by - # iris.util._OrderedHashable. - return (self.name, self.calendar) - - def __eq__(self, other): - """ - Compare the two units for equality and return the boolean result. - - Args: - - * other (string/Unit): Unit to be compared. - - Returns: - Boolean. - - For example: - - >>> from iris.unit import Unit - >>> Unit('meters') == Unit('millimeters') - False - >>> Unit('meters') == 'm' - True - - """ - other = as_unit(other) - - # Compare category (i.e. unknown, no_unit, etc.). - if self.category != other.category: - return False - - # Compare calendar as UDUNITS cannot handle calendars. - if self.calendar != other.calendar: - return False - - # Compare UDUNITS. - res = _ut_compare(self.ut_unit, other.ut_unit) - return res == 0 - - def __ne__(self, other): - """ - Compare the two units for inequality and return the boolean result. - - Args: - - * other (string/Unit): Unit to be compared. - - Returns: - Boolean. - - For example: - - >>> from iris.unit import Unit - >>> Unit('meters') != Unit('millimeters') - True - >>> Unit('meters') != 'm' - False - - """ - return not self == other - - def convert(self, value, other, ctype=FLOAT64): - """ - Converts a single value or numpy array of values from the current unit - to the other target unit. - - If the units are not convertible, then no conversion will take place. - - Args: - - * value (int/float/long/numpy.ndarray): - Value/s to be converted. - * other (string/Unit): - Target unit to convert to. - * ctype (ctypes.c_float/ctypes.c_double): - Floating point 32-bit single-precision (iris.unit.FLOAT32) or - 64-bit double-precision (iris.unit.FLOAT64) of conversion. The - default is 64-bit double-precision conversion. - - Returns: - float or numpy.ndarray of appropriate float type. - - For example: - - >>> import iris.unit as unit - >>> import numpy as np - >>> c = unit.Unit('deg_c') - >>> f = unit.Unit('deg_f') - >>> print c.convert(0, f) - 32.0 - >>> c.convert(0, f, unit.FLOAT32) - 32.0 - >>> a64 = np.arange(10, dtype=np.float64) - >>> c.convert(a64, f) - array([ 32. , 33.8, 35.6, 37.4, 39.2, 41. , 42.8, 44.6, \ - 46.4, 48.2]) - >>> a32 = np.arange(10, dtype=np.float32) - >>> c.convert(a32, f) - array([ 32. , 33.79999924, 35.59999847, 37.40000153, - 39.20000076, 41. , 42.79999924, 44.59999847, - 46.40000153, 48.20000076], dtype=float32) - - .. note:: - - Conversion is done *in-place* for numpy arrays. Also note that, - conversion between unit calendars is not permitted. - - """ - result = None - other = as_unit(other) - value_copy = copy.deepcopy(value) - - if self == other: - return value - - if self.is_convertible(other): - # Use utime for converting reference times that are not using a - # gregorian calendar as it handles these and udunits does not. - if self.is_time_reference() and self.calendar is not 'gregorian': - ut1 = self.utime() - ut2 = other.utime() - result = ut2.date2num(ut1.num2date(value_copy)) - else: - ut_converter = _ut_get_converter(self.ut_unit, other.ut_unit) - if ut_converter: - if isinstance(value_copy, np.ndarray): - # Can only handle array of np.float32 or np.float64 so - # cast array of ints to array of floats of requested - # precision. - if issubclass(value_copy.dtype.type, np.integer): - value_copy = value_copy.astype( - _ctypes2numpy[ctype]) - # strict type check of numpy array - if value_copy.dtype.type not in _numpy2ctypes.keys(): - raise TypeError( - "Expect a numpy array of '%s' or '%s'" % - tuple(sorted(_numpy2ctypes.keys()))) - ctype = _numpy2ctypes[value_copy.dtype.type] - pointer = value_copy.ctypes.data_as( - ctypes.POINTER(ctype)) - # Utilise global convenience dictionary - # _cv_convert_array - _cv_convert_array[ctype](ut_converter, pointer, - value_copy.size, pointer) - result = value_copy - else: - if ctype not in _cv_convert_scalar.keys(): - raise ValueError('Invalid target type. Can only ' - 'convert to float or double.') - # Utilise global convenience dictionary - # _cv_convert_scalar - result = _cv_convert_scalar[ctype](ut_converter, - ctype(value_copy)) - _cv_free(ut_converter) - else: - self._raise_error('Failed to convert %r to %r' % - (self, other)) - else: - raise ValueError("Unable to convert from '%s' to '%s'." % - (self, other)) - return result - - def utime(self): - """ - Returns a netcdftime.utime object which performs conversions of - numeric time values to/from datetime objects given the current - calendar and unit time reference. - - The current unit time reference must be of the form: - ' since ' - i.e. 'hours since 1970-01-01 00:00:00' - - Returns: - netcdftime.utime. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('hours since 1970-01-01 00:00:00', - ... calendar=unit.CALENDAR_STANDARD) - >>> ut = u.utime() - >>> ut.num2date(2) - datetime.datetime(1970, 1, 1, 2, 0) - - """ - - # - # ensure to strip out non-parsable 'UTC' postfix which - # is generated by UDUNITS-2 formatted output - # - if self.calendar is None: - raise ValueError('Unit has undefined calendar') - return netcdftime.utime(str(self).rstrip(" UTC"), self.calendar) - - def date2num(self, date): - """ - Returns the numeric time value calculated from the datetime - object using the current calendar and unit time reference. - - The current unit time reference must be of the form: - ' since ' - i.e. 'hours since 1970-01-01 00:00:00' - - Works for scalars, sequences and numpy arrays. Returns a scalar - if input is a scalar, else returns a numpy array. - - Args: - - * date (datetime): - A datetime object or a sequence of datetime objects. - The datetime objects should not include a time-zone offset. - - Returns: - float or numpy.ndarray of float. - - For example: - - >>> import iris.unit as unit - >>> import datetime - >>> u = unit.Unit('hours since 1970-01-01 00:00:00', - ... calendar=unit.CALENDAR_STANDARD) - >>> u.date2num(datetime.datetime(1970, 1, 1, 5)) - 5.00000000372529 - >>> u.date2num([datetime.datetime(1970, 1, 1, 5), - ... datetime.datetime(1970, 1, 1, 6)]) - array([ 5., 6.]) - - """ - - cdf_utime = self.utime() - return cdf_utime.date2num(date) - - def num2date(self, time_value): - """ - Returns a datetime-like object calculated from the numeric time - value using the current calendar and the unit time reference. - - The current unit time reference must be of the form: - ' since ' - i.e. 'hours since 1970-01-01 00:00:00' - - The datetime objects returned are 'real' Python datetime objects - if the date falls in the Gregorian calendar (i.e. the calendar - is 'standard', 'gregorian', or 'proleptic_gregorian' and the - date is after 1582-10-15). Otherwise a 'phoney' datetime-like - object (netcdftime.datetime) is returned which can handle dates - that don't exist in the Proleptic Gregorian calendar. - - Works for scalars, sequences and numpy arrays. Returns a scalar - if input is a scalar, else returns a numpy array. - - Args: - - * time_value (float): Numeric time value/s. Maximum resolution - is 1 second. - - Returns: - datetime, or numpy.ndarray of datetime object. - - For example: - - >>> import iris.unit as unit - >>> u = unit.Unit('hours since 1970-01-01 00:00:00', - ... calendar=unit.CALENDAR_STANDARD) - >>> u.num2date(6) - datetime.datetime(1970, 1, 1, 6, 0) - >>> u.num2date([6, 7]) - array([datetime.datetime(1970, 1, 1, 6, 0), - datetime.datetime(1970, 1, 1, 7, 0)], dtype=object) - - """ - cdf_utime = self.utime() - return cdf_utime.num2date(time_value) diff --git a/lib/iris/util.py b/lib/iris/util.py index 436c85b25f..9c478b15c4 100644 --- a/lib/iris/util.py +++ b/lib/iris/util.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2014, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of Iris. # @@ -19,68 +19,29 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + import abc import collections +from contextlib import contextmanager import copy +import functools import inspect import os import os.path import sys import tempfile -import time -import warnings +import cf_units import numpy as np import numpy.ma as ma import iris +import iris.coords import iris.exceptions - - -def broadcast_weights(weights, array, dims): - """ - Broadcast a weights array to the shape of another array. - - Each dimension of the weights array must correspond to a dimension - of the other array. - - .. deprecated:: 1.6 - - Please use :func:`~iris.util.broadcast_to_shape()`. - - Args: - - * weights (:class:`numpy.ndarray`-like): - An array of weights to broadcast. - - * array (:class:`numpy.ndarray`-like): - An array whose shape is the target shape for *weights*. - - * dims (:class:`list` :class:`tuple` etc.): - A sequence of dimension indices, specifying which dimensions of - *array* are represented in *weights*. The order the dimensions - are given in is not important, but the order of the dimensions - in *weights* should be the same as the relative ordering of the - corresponding dimensions in *array*. For example, if *array* is - 4d with dimensions (ntime, nlev, nlat, nlon) and *weights* - provides latitude-longitude grid weightings then *dims* could be - set to [2, 3] or [3, 2] but *weights* must have shape - (nlat, nlon) since the latitude dimension comes before the - longitude dimension in *array*. - - """ - warnings.warn('broadcast_weights() is deprecated and will be removed ' - 'in a future release. Consider converting existing code ' - 'to use broadcast_to_shape() as a replacement.', - stacklevel=2) - # Create a shape array, which *weights* can be re-shaped to, allowing - # them to be broadcast with *array*. - weights_shape = np.ones(array.ndim) - for dim in dims: - if dim is not None: - weights_shape[dim] = array.shape[dim] - # Broadcast the arrays together. - return np.broadcast_arrays(weights.reshape(weights_shape), array)[0] +import iris.cube def broadcast_to_shape(array, shape, dim_map): @@ -280,7 +241,7 @@ def guess_coord_axis(coord): """ Returns a "best guess" axis name of the coordinate. - Heuristic categoration of the coordinate into either label + Heuristic categorisation of the coordinate into either label 'T', 'Z', 'Y', 'X' or None. Args: @@ -300,8 +261,8 @@ def guess_coord_axis(coord): elif coord.standard_name in ('latitude', 'grid_latitude', 'projection_y_coordinate'): axis = 'Y' - elif (coord.units.is_convertible('hPa') - or coord.attributes.get('positive') in ('up', 'down')): + elif (coord.units.is_convertible('hPa') or + coord.attributes.get('positive') in ('up', 'down')): axis = 'Z' elif coord.units.is_time_reference(): axis = 'T' @@ -334,7 +295,7 @@ def rolling_window(a, window=1, step=1, axis=-1): Examples:: - >>> x=np.arange(10).reshape((2,5)) + >>> x = np.arange(10).reshape((2, 5)) >>> rolling_window(x, 3) array([[[0, 1, 2], [1, 2, 3], [2, 3, 4]], [[5, 6, 7], [6, 7, 8], [7, 8, 9]]]) @@ -355,7 +316,7 @@ def rolling_window(a, window=1, step=1, axis=-1): if step < 1: raise ValueError("`step` must be at least 1.") axis = axis % a.ndim - num_windows = (a.shape[axis] - window + step) / step + num_windows = (a.shape[axis] - window + step) // step shape = a.shape[:axis] + (num_windows, window) + a.shape[axis + 1:] strides = (a.strides[:axis] + (step * a.strides[axis], a.strides[axis]) + a.strides[axis + 1:]) @@ -428,12 +389,12 @@ def between(lh, rh, lh_inclusive=True, rh_inclusive=True): between_3_and_6 = between(3, 6) for i in range(10): - print i, between_3_and_6(i) + print(i, between_3_and_6(i)) between_3_and_6 = between(3, 6, rh_inclusive=False) for i in range(10): - print i, between_3_and_6(i) + print(i, between_3_and_6(i)) """ if lh_inclusive and rh_inclusive: @@ -446,22 +407,25 @@ def between(lh, rh, lh_inclusive=True, rh_inclusive=True): return lambda c: lh < c < rh -def reverse(array, axes): +def reverse(cube_or_array, coords_or_dims): """ - Reverse the array along the given axes. + Reverse the cube or array along the given dimensions. Args: - * array - The array to reverse - * axes - A single value or array of values of axes to reverse + * cube_or_array: :class:`iris.cube.Cube` or :class:`numpy.ndarray` + The cube or array to reverse. + * coords_or_dims: int, str, :class:`iris.coords.Coord` or sequence of these + Identify one or more dimensions to reverse. If cube_or_array is a + numpy array, use int or a sequence of ints, as in the examples below. + If cube_or_array is a Cube, a Coord or coordinate name (or sequence of + these) may be specified instead. :: >>> import numpy as np >>> a = np.arange(24).reshape(2, 3, 4) - >>> print a + >>> print(a) [[[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] @@ -469,7 +433,7 @@ def reverse(array, axes): [[12 13 14 15] [16 17 18 19] [20 21 22 23]]] - >>> print reverse(a, 1) + >>> print(reverse(a, 1)) [[[ 8 9 10 11] [ 4 5 6 7] [ 0 1 2 3]] @@ -477,7 +441,7 @@ def reverse(array, axes): [[20 21 22 23] [16 17 18 19] [12 13 14 15]]] - >>> print reverse(a, [1, 2]) + >>> print(reverse(a, [1, 2])) [[[11 10 9 8] [ 7 6 5 4] [ 3 2 1 0]] @@ -487,20 +451,42 @@ def reverse(array, axes): [15 14 13 12]]] """ - index = [slice(None, None)] * array.ndim - axes = np.array(axes, ndmin=1) - if axes.ndim != 1: + index = [slice(None, None)] * cube_or_array.ndim + + if isinstance(coords_or_dims, iris.cube.Cube): + raise TypeError('coords_or_dims must be int, str, coordinate or ' + 'sequence of these. Got cube.') + + if iris.cube._is_single_item(coords_or_dims): + coords_or_dims = [coords_or_dims] + + axes = set() + for coord_or_dim in coords_or_dims: + if isinstance(coord_or_dim, int): + axes.add(coord_or_dim) + elif isinstance(cube_or_array, np.ndarray): + raise TypeError( + 'To reverse an array, provide an int or sequence of ints.') + else: + try: + axes.update(cube_or_array.coord_dims(coord_or_dim)) + except AttributeError: + raise TypeError('coords_or_dims must be int, str, coordinate ' + 'or sequence of these.') + + axes = np.array(list(axes), ndmin=1) + if axes.ndim != 1 or axes.size == 0: raise ValueError('Reverse was expecting a single axis or a 1d array ' 'of axes, got %r' % axes) - if np.min(axes) < 0 or np.max(axes) > array.ndim-1: + if np.min(axes) < 0 or np.max(axes) > cube_or_array.ndim-1: raise ValueError('An axis value out of range for the number of ' 'dimensions from the given array (%s) was received. ' - 'Got: %r' % (array.ndim, axes)) + 'Got: %r' % (cube_or_array.ndim, axes)) for axis in axes: index[axis] = slice(None, None, -1) - return array[tuple(index)] + return cube_or_array[tuple(index)] def monotonic(array, strict=False, return_direction=False): @@ -526,6 +512,7 @@ def monotonic(array, strict=False, return_direction=False): If the return_direction flag was given then the returned value will be: + ``(monotonic_status, direction)`` """ @@ -583,7 +570,7 @@ def column_slices_generator(full_slice, ndims): dimension_mapping = {None: None} _count_current_dim = 0 for i, i_key in enumerate(full_slice): - if isinstance(i_key, int): + if isinstance(i_key, (int, np.integer)): dimension_mapping[i] = None else: dimension_mapping[i] = _count_current_dim @@ -591,14 +578,15 @@ def column_slices_generator(full_slice, ndims): # Get all of the dimensions for which a tuple of indices were provided # (numpy.ndarrays are treated in the same way tuples in this case) - is_tuple_style_index = lambda key: isinstance(key, tuple) or \ - (isinstance(key, np.ndarray) and key.ndim == 1) + def is_tuple_style_index(key): + return (isinstance(key, tuple) or + (isinstance(key, np.ndarray) and key.ndim == 1)) tuple_indices = [i for i, key in enumerate(full_slice) if is_tuple_style_index(key)] # stg1: Take a copy of the full_slice specification, turning all tuples # into a full slice - if tuple_indices != range(len(full_slice)): + if tuple_indices != list(range(len(full_slice))): first_slice = list(full_slice) for tuple_index in tuple_indices: first_slice[tuple_index] = slice(None, None) @@ -607,15 +595,11 @@ def column_slices_generator(full_slice, ndims): list_of_slices.append(first_slice) - data_ndims = max(dimension_mapping.values()) - if data_ndims is not None: - data_ndims += 1 - # stg2 iterate over each of the tuples for tuple_index in tuple_indices: # Create a list with the indices to span the whole data array that we # currently have - spanning_slice_with_tuple = [slice(None, None)] * data_ndims + spanning_slice_with_tuple = [slice(None, None)] * _count_current_dim # Replace the slice(None, None) with our current tuple spanning_slice_with_tuple[dimension_mapping[tuple_index]] = \ full_slice[tuple_index] @@ -692,6 +676,52 @@ def _build_full_slice_given_keys(keys, ndim): return full_slice +def _slice_data_with_keys(data, keys): + """ + Index an array-like object as "data[keys]", with orthogonal indexing. + + Args: + + * data (array-like): + array to index. + + * keys (list): + list of indexes, as received from a __getitem__ call. + + This enforces an orthogonal interpretation of indexing, which means that + both 'real' (numpy) arrays and other array-likes index in the same way, + instead of numpy arrays doing 'fancy indexing'. + + Returns (dim_map, data_region), where : + + * dim_map (dict) : + A dimension map, as returned by :func:`column_slices_generator`. + i.e. "dim_map[old_dim_index]" --> "new_dim_index" or None. + + * data_region (array-like) : + The sub-array. + + .. Note:: + + Avoids copying the data, where possible. + + """ + # Combines the use of _build_full_slice_given_keys and + # column_slices_generator. + # By slicing on only one index at a time, this also mostly avoids copying + # the data, except some cases when a key contains a list of indices. + n_dims = len(data.shape) + full_slice = _build_full_slice_given_keys(keys, n_dims) + dims_mapping, slices_iter = column_slices_generator(full_slice, n_dims) + for this_slice in slices_iter: + data = data[this_slice] + if data.ndim > 0 and min(data.shape) < 1: + # Disallow slicings where a dimension has no points, like "[5:5]". + raise IndexError('Cannot index with zero length slice.') + + return dims_mapping, data + + def _wrap_function_for_method(function, docstring=None): """ Returns a wrapper function modified to be suitable for use as a @@ -721,16 +751,16 @@ def _wrap_function_for_method(function, docstring=None): simple_arg_source = ', '.join(basic_args + simple_default_args + var_arg + var_kw) source = ('def %s(%s):\n return function(%s)' % - (function.func_name, arg_source, simple_arg_source)) + (function.__name__, arg_source, simple_arg_source)) # Compile the wrapper function # NB. There's an outstanding bug with "exec" where the locals and globals # dictionaries must be the same if we're to get closure behaviour. my_locals = {'function': function} - exec source in my_locals, my_locals + exec(source, my_locals, my_locals) # Update the docstring if required, and return the modified function - wrapper = my_locals[function.func_name] + wrapper = my_locals[function.__name__] if docstring is None: wrapper.__doc__ = function.__doc__ else: @@ -765,7 +795,7 @@ def __new__(cls, name, bases, namespace): # Create a default __init__ method for the class method_source = ('def __init__(self, %s):\n ' 'self._init_from_tuple((%s,))' % (args, args)) - exec method_source in namespace + exec(method_source, namespace) # Ensure the class has a "helper constructor" with explicit # arguments. @@ -773,13 +803,15 @@ def __new__(cls, name, bases, namespace): # Create a default _init method for the class method_source = ('def _init(self, %s):\n ' 'self._init_from_tuple((%s,))' % (args, args)) - exec method_source in namespace + exec(method_source, namespace) return super(_MetaOrderedHashable, cls).__new__( cls, name, bases, namespace) -class _OrderedHashable(collections.Hashable): +@functools.total_ordering +class _OrderedHashable(six.with_metaclass(_MetaOrderedHashable, + collections.Hashable)): """ Convenience class for creating "immutable", hashable, and ordered classes. @@ -798,9 +830,6 @@ class _OrderedHashable(collections.Hashable): """ - # The metaclass adds default __init__ methods when appropriate. - __metaclass__ = _MetaOrderedHashable - @abc.abstractproperty def _names(self): """ @@ -852,12 +881,11 @@ def __ne__(self, other): # Provide default ordering semantics - def __cmp__(self, other): + def __lt__(self, other): if isinstance(other, _OrderedHashable): - result = cmp(self._identity(), other._identity()) + return self._identity() < other._identity() else: - result = NotImplemented - return result + return NotImplemented def create_temp_filename(suffix=''): @@ -925,93 +953,6 @@ def clip_string(the_str, clip_length=70, rider="..."): return first_part + remainder[:termination_point] + rider -def ensure_array(a): - if not isinstance(a, (np.ndarray, ma.core.MaskedArray)): - a = np.array([a]) - return a - - -class _Timers(object): - # See help for timers, below. - - def __init__(self): - self.timers = {} - - def start(self, name, step_name): - self.stop(name) - timer = self.timers.setdefault(name, {}) - timer[step_name] = time.time() - timer["active_timer_step"] = step_name - - def restart(self, name, step_name): - self.stop(name) - timer = self.timers.setdefault(name, {}) - timer[step_name] = time.time() - timer.get(step_name, 0) - timer["active_timer_step"] = step_name - - def stop(self, name): - if name in self.timers and "active_timer_step" in self.timers[name]: - timer = self.timers[name] - active = timer["active_timer_step"] - start = timer[active] - timer[active] = time.time() - start - return self.get(name) - - def get(self, name): - result = (name, []) - if name in self.timers: - result = (name, ", ".join(["'%s':%8.5f" % (k, v) - for k, v in self.timers[name].items() - if k != "active_timer_step"])) - return result - - def reset(self, name): - self.timers[name] = {} - - -timers = _Timers() -""" -Provides multiple named timers, each composed of multiple named steps. - -Only one step is active at a time, so calling start(timer_name, step_name) -will stop the current step and start the new one. - -Example Usage: - - from iris.util import timers - - def little_func(param): - - timers.restart("little func", "init") - init() - - timers.restart("little func", "main") - main(param) - - timers.restart("little func", "cleanup") - cleanup() - - timers.stop("little func") - - def my_big_func(): - - timers.start("big func", "input") - input() - - timers.start("big func", "processing") - little_func(123) - little_func(456) - - timers.start("big func", "output") - output() - - print timers.stop("big func") - - print timers.get("little func") - -""" - - def format_array(arr): """ Returns the given array as a string, using the python builtin str @@ -1022,16 +963,44 @@ def format_array(arr): For customisations, use the :mod:`numpy.core.arrayprint` directly. """ - if arr.size > 85: - summary_insert = "..., " - else: - summary_insert = "" + + summary_insert = "" + summary_threshold = 85 + edge_items = 3 ffunc = str - return np.core.arrayprint._formatArray(arr, ffunc, len(arr.shape), - max_line_len=50, - next_line_prefix='\t\t', - separator=', ', edge_items=3, - summary_insert=summary_insert)[:-1] + formatArray = np.core.arrayprint._formatArray + max_line_len = 50 + legacy = '1.13' + if arr.size > summary_threshold: + summary_insert = '...' + options = np.get_printoptions() + options['legacy'] = legacy + with _printopts_context(**options): + result = formatArray( + arr, ffunc, max_line_len, + next_line_prefix='\t\t', separator=', ', + edge_items=edge_items, + summary_insert=summary_insert, + legacy=legacy) + + return result + + +@contextmanager +def _printopts_context(**kwargs): + """ + Update the numpy printoptions for the life of this context manager. + + Note: this function can be removed with numpy>=1.15 thanks to + https://github.com/numpy/numpy/pull/10406 + + """ + original_opts = np.get_printoptions() + np.set_printoptions(**kwargs) + try: + yield + finally: + np.set_printoptions(**original_opts) def new_axis(src_cube, scalar_coord=None): @@ -1061,18 +1030,23 @@ def new_axis(src_cube, scalar_coord=None): >>> ncube.shape (1, 360, 360) - .. warning:: - - Calling this method will trigger any deferred loading, causing the - data array of the cube to be loaded into memory. - """ if scalar_coord is not None: scalar_coord = src_cube.coord(scalar_coord) # Indexing numpy arrays requires loading deferred data here returning a # copy of the data with a new leading dimension. - new_cube = iris.cube.Cube(src_cube.data[None]) + # If the source cube is a Masked Constant, it is changed here to a Masked + # Array to allow the mask to gain an extra dimension with the data. + if src_cube.has_lazy_data(): + new_cube = iris.cube.Cube(src_cube.lazy_data()[None]) + else: + if isinstance(src_cube.data, ma.core.MaskedConstant): + new_data = ma.array([np.nan], mask=[True]) + else: + new_data = src_cube.data[None] + new_cube = iris.cube.Cube(new_data) + new_cube.metadata = src_cube.metadata for coord in src_cube.aux_coords: @@ -1142,7 +1116,7 @@ def as_compatible_shape(src_cube, target_cube): 'to restore cube dimensions.') new_shape = [1] * target_cube.ndim - for dim_from, dim_to in dim_mapping.iteritems(): + for dim_from, dim_to in six.iteritems(dim_mapping): if dim_to is not None: new_shape[dim_from] = src_cube.shape[dim_to] @@ -1162,9 +1136,16 @@ def as_compatible_shape(src_cube, target_cube): # for subsequent use in creating updated aux_factories. coord_mapping = {} + reverse_mapping = {v: k for k, v in dim_mapping.items() if v is not None} + def add_coord(coord): """Closure used to add a suitably reshaped coord to new_cube.""" - dims = target_cube.coord_dims(coord) + all_dims = target_cube.coord_dims(coord) + src_dims = [dim for dim in src_cube.coord_dims(coord) if + src_cube.shape[dim] > 1] + mapped_dims = [reverse_mapping[dim] for dim in src_dims] + length1_dims = [dim for dim in all_dims if new_cube.shape[dim] == 1] + dims = length1_dims + mapped_dims shape = [new_cube.shape[dim] for dim in dims] if not shape: shape = [1] @@ -1194,6 +1175,38 @@ def add_coord(coord): return new_cube +def squeeze(cube): + """ + Removes any dimension of length one. If it has an associated DimCoord or + AuxCoord, this becomes a scalar coord. + + Args: + + * cube (:class:`iris.cube.Cube`) + Source cube to remove length 1 dimension(s) from. + + Returns: + A new :class:`iris.cube.Cube` instance without any dimensions of + length 1. + + For example:: + + >>> cube.shape + (1, 360, 360) + >>> ncube = iris.util.squeeze(cube) + >>> ncube.shape + (360, 360) + + """ + + slices = [0 if cube.shape[dim] == 1 else slice(None) + for dim in range(cube.ndim)] + + squeezed = cube[tuple(slices)] + + return squeezed + + def file_is_newer_than(result_path, source_paths): """ Return whether the 'result' file has a later modification time than all of @@ -1235,7 +1248,7 @@ def file_is_newer_than(result_path, source_paths): """ # Accept a string as a single source path - if isinstance(source_paths, basestring): + if isinstance(source_paths, six.string_types): source_paths = [source_paths] # Fix our chosen timestamp function file_date = os.path.getmtime @@ -1269,10 +1282,409 @@ def regular_step(coord): if coord.shape[0] < 2: raise ValueError("Expected a non-scalar coord") - diffs = coord.points[1:] - coord.points[:-1] - avdiff = np.mean(diffs) - if not np.allclose(diffs, avdiff, rtol=0.001): - # TODO: This value is set for test_analysis to pass... + avdiff, regular = points_step(coord.points) + if not regular: msg = "Coord %s is not regular" % coord.name() raise iris.exceptions.CoordinateNotRegularError(msg) return avdiff.astype(coord.points.dtype) + + +def points_step(points): + """Determine whether a NumPy array has a regular step.""" + diffs = np.diff(points) + avdiff = np.mean(diffs) + # TODO: This value for `rtol` is set for test_analysis to pass... + regular = np.allclose(diffs, avdiff, rtol=0.001) + return avdiff, regular + + +def unify_time_units(cubes): + """ + Performs an in-place conversion of the time units of all time coords in the + cubes in a given iterable. One common epoch is defined for each calendar + found in the cubes to prevent units being defined with inconsistencies + between epoch and calendar. + + Each epoch is defined from the first suitable time coordinate found in the + input cubes. + + Arg: + + * cubes: + An iterable containing :class:`iris.cube.Cube` instances. + + """ + epochs = {} + + for cube in cubes: + for time_coord in cube.coords(): + if time_coord.units.is_time_reference(): + epoch = epochs.setdefault(time_coord.units.calendar, + time_coord.units.origin) + new_unit = cf_units.Unit(epoch, time_coord.units.calendar) + time_coord.convert_units(new_unit) + + +def _is_circular(points, modulus, bounds=None): + """ + Determine whether the provided points or bounds are circular in nature + relative to the modulus value. + + If the bounds are provided then these are checked for circularity rather + than the points. + + Args: + + * points: + :class:`numpy.ndarray` of point values. + + * modulus: + Circularity modulus value. + + Kwargs: + + * bounds: + :class:`numpy.ndarray` of bound values. + + Returns: + Boolean. + + """ + circular = False + if bounds is not None: + # Set circular to True if the bounds ends are equivalent. + first_bound = last_bound = None + if bounds.ndim == 1 and bounds.shape[-1] == 2: + first_bound = bounds[0] % modulus + last_bound = bounds[1] % modulus + elif bounds.ndim == 2 and bounds.shape[-1] == 2: + first_bound = bounds[0, 0] % modulus + last_bound = bounds[-1, 1] % modulus + + if first_bound is not None and last_bound is not None: + circular = np.allclose(first_bound, last_bound, + rtol=1.0e-5) + else: + # set circular if points are regular and last+1 ~= first + if len(points) > 1: + diffs = list(set(np.diff(points))) + diff = np.mean(diffs) + abs_tol = np.abs(diff * 1.0e-4) + diff_approx_equal = np.max(np.abs(diffs - diff)) < abs_tol + if diff_approx_equal: + circular_value = (points[-1] + diff) % modulus + try: + np.testing.assert_approx_equal(points[0], + circular_value, + significant=4) + circular = True + except AssertionError: + if points[0] == 0: + try: + np.testing.assert_approx_equal(modulus, + circular_value, + significant=4) + circular = True + except AssertionError: + pass + else: + # XXX - Inherited behaviour from NetCDF PyKE rules. + # We need to decide whether this is valid! + circular = points[0] >= modulus + return circular + + +def promote_aux_coord_to_dim_coord(cube, name_or_coord): + """ + Promotes an AuxCoord on the cube to a DimCoord. This AuxCoord must be + associated with a single cube dimension. If the AuxCoord is associated + with a dimension that already has a DimCoord, that DimCoord gets + demoted to an AuxCoord. + + Args: + + * cube + An instance of :class:`iris.cube.Cube` + + * name_or_coord: + Either + + (a) An instance of :class:`iris.coords.AuxCoord` + + or + + (b) the :attr:`standard_name`, :attr:`long_name`, or + :attr:`var_name` of an instance of an instance of + :class:`iris.coords.AuxCoord`. + + For example:: + + >>> print cube + air_temperature / (K) (time: 12; latitude: 73; longitude: 96) + Dimension coordinates: + time x - - + latitude - x - + longitude - - x + Auxiliary coordinates: + year x - - + >>> promote_aux_coord_to_dim_coord(cube, 'year') + >>> print cube + air_temperature / (K) (year: 12; latitude: 73; longitude: 96) + Dimension coordinates: + year x - - + latitude - x - + longitude - - x + Auxiliary coordinates: + time x - - + + """ + + if isinstance(name_or_coord, six.string_types): + aux_coord = cube.coord(name_or_coord) + elif isinstance(name_or_coord, iris.coords.Coord): + aux_coord = name_or_coord + else: + # Don't know how to handle this type + msg = ("Don't know how to handle coordinate of type {}. " + "Ensure all coordinates are of type six.string_types or " + "iris.coords.Coord.") + msg = msg.format(type(name_or_coord)) + raise TypeError(msg) + + if aux_coord in cube.dim_coords: + # nothing to do + return + + if aux_coord not in cube.aux_coords: + msg = ("Attempting to promote an AuxCoord ({}) " + "which does not exist in the cube.") + msg = msg.format(aux_coord.name()) + raise ValueError(msg) + + coord_dim = cube.coord_dims(aux_coord) + + if len(coord_dim) != 1: + msg = ("Attempting to promote an AuxCoord ({}) " + "which is associated with {} dimensions.") + msg = msg.format(aux_coord.name(), len(coord_dim)) + raise ValueError(msg) + + try: + dim_coord = iris.coords.DimCoord.from_coord(aux_coord) + except ValueError as valerr: + msg = ("Attempt to promote an AuxCoord ({}) fails " + "when attempting to create a DimCoord from the " + "AuxCoord because: {}") + msg = msg.format(aux_coord.name(), str(valerr)) + raise ValueError(msg) + + old_dim_coord = cube.coords(dim_coords=True, + contains_dimension=coord_dim[0]) + + if len(old_dim_coord) == 1: + demote_dim_coord_to_aux_coord(cube, old_dim_coord[0]) + + # order matters here: don't want to remove + # the aux_coord before have tried to make + # dim_coord in case that fails + cube.remove_coord(aux_coord) + + cube.add_dim_coord(dim_coord, coord_dim) + + +def demote_dim_coord_to_aux_coord(cube, name_or_coord): + """ + Demotes a dimension coordinate on the cube to an auxiliary coordinate. + + The DimCoord is demoted to an auxiliary coordinate on the cube. + The dimension of the cube that was associated with the DimCoord becomes + anonymous. The class of the coordinate is left as DimCoord, it is not + recast as an AuxCoord instance. + + Args: + + * cube + An instance of :class:`iris.cube.Cube` + + * name_or_coord: + Either + + (a) An instance of :class:`iris.coords.DimCoord` + + or + + (b) the :attr:`standard_name`, :attr:`long_name`, or + :attr:`var_name` of an instance of an instance of + :class:`iris.coords.DimCoord`. + + For example:: + + >>> print cube + air_temperature / (K) (time: 12; latitude: 73; longitude: 96) + Dimension coordinates: + time x - - + latitude - x - + longitude - - x + Auxiliary coordinates: + year x - - + >>> demote_dim_coord_to_aux_coord(cube, 'time') + >>> print cube + air_temperature / (K) (-- : 12; latitude: 73; longitude: 96) + Dimension coordinates: + latitude - x - + longitude - - x + Auxiliary coordinates: + time x - - + year x - - + + """ + + if isinstance(name_or_coord, six.string_types): + dim_coord = cube.coord(name_or_coord) + elif isinstance(name_or_coord, iris.coords.Coord): + dim_coord = name_or_coord + else: + # Don't know how to handle this type + msg = ("Don't know how to handle coordinate of type {}. " + "Ensure all coordinates are of type six.string_types or " + "iris.coords.Coord.") + msg = msg.format(type(name_or_coord)) + raise TypeError(msg) + + if dim_coord not in cube.dim_coords: + # nothing to do + return + + coord_dim = cube.coord_dims(dim_coord) + + cube.remove_coord(dim_coord) + + cube.add_aux_coord(dim_coord, coord_dim) + + +@functools.wraps(np.meshgrid) +def _meshgrid(*xi, **kwargs): + """ + @numpy v1.13, the dtype of each output nD coordinate is the same as its + associated input 1D coordinate. This is not the case prior to numpy v1.13, + where the output dtype is cast up to its highest resolution, regardlessly. + + This convenience function ensures consistent meshgrid behaviour across + numpy versions. + + Reference: https://github.com/numpy/numpy/pull/5302 + + """ + mxi = np.meshgrid(*xi, **kwargs) + for i, (mxii, xii) in enumerate(zip(mxi, xi)): + if mxii.dtype != xii.dtype: + mxi[i] = mxii.astype(xii.dtype) + return mxi + + +def find_discontiguities(cube, rel_tol=1e-5, abs_tol=1e-8): + """ + Searches coord for discontiguities in the bounds array, returned as a + boolean array (True where discontiguities are present). + + Args: + + * cube (`iris.cube.Cube`): + The cube to be checked for discontinuities in its 'x' and 'y' + coordinates. + + Kwargs: + + * rel_tol (float): + The relative equality tolerance to apply in coordinate bounds + checking. + + * abs_tol (float): + The absolute value tolerance to apply in coordinate bounds + checking. + + Returns: + + * result (`numpy.ndarray` of bool) : + true/false map of which cells in the cube XY grid have + discontiguities in the coordinate points array. + + This can be used as the input array for + :func:`iris.util.mask_discontiguities`. + + Examples:: + + # Find any unknown discontiguities in your cube's x and y arrays: + discontiguities = iris.util.find_discontiguities(cube) + + # Pass the resultant boolean array to `iris.util.mask_discontiguities` + # with a cube slice; this will use the boolean array to mask + # any discontiguous data points before plotting: + masked_cube_slice = iris.util.mask_discontiguities(cube[0], + discontiguities) + + # Plot the masked cube slice: + iplt.pcolormesh(masked_cube_slice) + + """ + lats_and_lons = ['latitude', 'grid_latitude', + 'longitude', 'grid_longitude'] + spatial_coords = [coord for coord in cube.aux_coords if + coord.name() in lats_and_lons] + dim_err_msg = 'Discontiguity searches are currently only supported for ' \ + '2-dimensional coordinates.' + if len(spatial_coords) != 2: + raise NotImplementedError(dim_err_msg) + + # Check which dimensions are spanned by each coordinate. + for coord in spatial_coords: + if coord.ndim != 2: + raise NotImplementedError(dim_err_msg) + else: + span = set(cube.coord_dims(coord)) + if not span: + msg = 'The coordinate {!r} doesn\'t span a data dimension.' + raise ValueError(msg.format(coord.name())) + + # Check that the 2d coordinate arrays are the same shape as each other + if len(spatial_coords) == 2: + assert spatial_coords[0].points.shape == spatial_coords[1].points.shape + + # Set up unmasked boolean array the same size as the coord points array: + bad_points_boolean = np.zeros(spatial_coords[0].points.shape, dtype=bool) + + for coord in spatial_coords: + _, (diffs_x, diffs_y) = coord._discontiguity_in_bounds(rtol=rel_tol, + atol=abs_tol) + + bad_points_boolean[:, :-1] = np.logical_or(bad_points_boolean[:, :-1], + diffs_x) + # apply mask for y-direction discontiguities: + bad_points_boolean[:-1, :] = np.logical_or(bad_points_boolean[:-1, :], + diffs_y) + return bad_points_boolean + + +def mask_cube(cube, points_to_mask): + """ + Masks any cells in the data array which correspond to cells marked `True` + in the `points_to_mask` array. + + Args: + + * cube (`iris.cube.Cube`): + A 2-dimensional instance of :class:`iris.cube.Cube`. + + * points_to_mask (`numpy.ndarray` of bool): + A 2d boolean array of Truth values representing points to mask in the + x and y arrays of the cube. + + Returns: + + * result (`iris.cube.Cube`): + A cube whose data array is masked at points specified by input array. + + """ + cube.data = ma.masked_array(cube.data) + cube.data[points_to_mask] = ma.masked + return cube diff --git a/requirements/all.txt b/requirements/all.txt new file mode 100644 index 0000000000..657be9ce19 --- /dev/null +++ b/requirements/all.txt @@ -0,0 +1,17 @@ +# Dependencies for a feature complete installation +# ------------------------------------------------ + +# esmpy regridding not available through pip. +#conda: esmpy>=7.0 (only python=2) +#gdal : under review -- not tested at present +mo_pack +nc-time-axis +pandas +stratify #conda: python-stratify +pyugrid + +#conda: graphviz + +# Iris sample data is not available through pip. It can be installed from +# https://github.com/SciTools/iris-sample-data/archive/master.zip +#conda: iris-sample-data diff --git a/requirements/core.txt b/requirements/core.txt new file mode 100644 index 0000000000..f938159cc8 --- /dev/null +++ b/requirements/core.txt @@ -0,0 +1,14 @@ +# Absolute minimal dependencies for iris +# -------------------------------------- + +# Without these, iris won't even import. + +cartopy +#conda: proj4<5 +cf_units>=2 +cftime +dask[array] #conda: dask +matplotlib>=2,<3 +netcdf4 +numpy>=1.14,!=1.15.2 +scipy diff --git a/requirements/docs.txt b/requirements/docs.txt new file mode 100644 index 0000000000..6966869c70 --- /dev/null +++ b/requirements/docs.txt @@ -0,0 +1 @@ +sphinx diff --git a/requirements/extensions.txt b/requirements/extensions.txt new file mode 100644 index 0000000000..0f3d0e0379 --- /dev/null +++ b/requirements/extensions.txt @@ -0,0 +1,9 @@ +# Iris extensions (i.e. key tools that depend on Iris) +# ---------------------------------------------------- + +# Note: pip can handle the circularity of these extensions, but conda will +# struggle. To install these extensions, ensure iris[core] has been installed +# first. + +iris_grib;python_version<"3" #conda: +gdal diff --git a/requirements/gen_conda_requirements.py b/requirements/gen_conda_requirements.py new file mode 100644 index 0000000000..e7ad2654d5 --- /dev/null +++ b/requirements/gen_conda_requirements.py @@ -0,0 +1,91 @@ +# (C) British Crown Copyright 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +import argparse +import os.path + + +REQS_DIR = os.path.dirname(__file__) +CONDA_PATTERN = '#conda:' + + +def read_conda_reqs(fname, options): + lines = [] + with open(fname, 'r') as fh: + for line in fh: + line = line.strip() + if CONDA_PATTERN in line: + line_start = line.index(CONDA_PATTERN) + len(CONDA_PATTERN) + line = line[line_start:].strip() + if 'only python=2' in line: + if 'python=2' in options: + line = line.replace('(only python=2)', '') + lines.append(line) + else: + continue + else: + lines.append(line) + else: + lines.append(line) + return lines + + +def compute_requirements(requirement_names=('core', ), options=None): + conda_reqs_lines = [] + + if 'python=2' in options: + conda_reqs_lines.append('python=2.*') + else: + conda_reqs_lines.append('# Python 3 conda configuration') + + for req_name in requirement_names: + fname = os.path.join(REQS_DIR, '{}.txt'.format(req_name)) + if not os.path.exists(fname): + raise RuntimeError('Unable to find the requirements file for {} ' + 'in {}'.format(req_name, fname)) + conda_reqs_lines.extend(read_conda_reqs(fname, options)) + conda_reqs_lines.append('') + + return conda_reqs_lines + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--verbosity", help="increase output verbosity") + parser.add_argument( + "--groups", nargs='*', default=[], + help=("Gather requirements for these given named groups " + "(as found in the requirements/ folder)")) + parser.add_argument( + "--py2", action="store_true", + help="Build the conda requirements for a python 2 installation") + + args = parser.parse_args() + + requirement_names = args.groups + requirement_names.insert(0, 'core') + requirement_names.insert(0, 'setup') + + options = [] + if args.py2: + options.append('python=2') + + print('\n'.join(compute_requirements(requirement_names, options))) + + +if __name__ == '__main__': + main() diff --git a/requirements/setup.txt b/requirements/setup.txt new file mode 100644 index 0000000000..552f54318c --- /dev/null +++ b/requirements/setup.txt @@ -0,0 +1,6 @@ +# Dependencies necessary to run setup.py of iris +# ---------------------------------------------- + +setuptools +# pyke (not pip installable) #conda: pyke +six diff --git a/requirements/test.txt b/requirements/test.txt new file mode 100644 index 0000000000..38d7410a9b --- /dev/null +++ b/requirements/test.txt @@ -0,0 +1,9 @@ +# Dependencies needed to run the iris tests +#------------------------------------------ + +mock +nose +pep8 +filelock +imagehash>=4.0 +requests diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000000..6e8bd69f88 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,47 @@ +[flake8] +ignore = E402,\ # Due to conditional imports + E226 # Due to whitespace around operators (e.g. 2*x + 3) +exclude = */iris/std_names.py,\ + */iris/fileformats/cf.py,\ + */iris/fileformats/dot.py,\ + */iris/fileformats/pp_load_rules.py,\ + */iris/fileformats/rules.py,\ + */iris/fileformats/um_cf_map.py,\ + */iris/fileformats/_pyke_rules/compiled_krb/*,\ + */iris/io/__init__.py,\ + */iris/io/format_picker.py,\ + */iris/tests/__init__.py,\ + */iris/tests/pp.py,\ + */iris/tests/stock.py,\ + */iris/tests/system_test.py,\ + */iris/tests/test_analysis.py,\ + */iris/tests/test_analysis_calculus.py,\ + */iris/tests/test_basic_maths.py,\ + */iris/tests/test_cartography.py,\ + */iris/tests/test_cdm.py,\ + */iris/tests/test_cell.py,\ + */iris/tests/test_cf.py,\ + */iris/tests/test_constraints.py,\ + */iris/tests/test_coord_api.py,\ + */iris/tests/test_coord_categorisation.py,\ + */iris/tests/test_coordsystem.py,\ + */iris/tests/test_cube_to_pp.py,\ + */iris/tests/test_file_load.py,\ + */iris/tests/test_file_save.py,\ + */iris/tests/test_grib_save.py,\ + */iris/tests/test_grib_save_rules.py,\ + */iris/tests/test_hybrid.py,\ + */iris/tests/test_intersect.py,\ + */iris/tests/test_io_init.py,\ + */iris/tests/test_iterate.py,\ + */iris/tests/test_load.py,\ + */iris/tests/test_merge.py,\ + */iris/tests/test_pp_cf.py,\ + */iris/tests/test_pp_module.py,\ + */iris/tests/test_pp_stash.py,\ + */iris/tests/test_pp_to_cube.py,\ + */iris/tests/test_quickplot.py,\ + */iris/tests/test_std_names.py,\ + */iris/tests/test_uri_callback.py,\ + */iris/tests/test_util.py + diff --git a/setup.py b/setup.py index a8215a5ba1..05982e6cb6 100644 --- a/setup.py +++ b/setup.py @@ -1,36 +1,37 @@ -import contextlib -from distutils.command import build_ext, build_py -from distutils.core import setup, Command -from distutils.sysconfig import get_config_var +from __future__ import print_function + +from contextlib import contextmanager from distutils.util import convert_path -import fnmatch -import multiprocessing import os +from shutil import copyfile import sys +import textwrap -import nose -import numpy as np -import setuptools - +from setuptools import setup, Command +from setuptools.command.develop import develop as develop_cmd +from setuptools.command.build_py import build_py -exclude_dirs = ['compiled_krb'] # Returns the package and all its sub-packages def find_package_tree(root_path, root_package): + root_path = root_path.replace('/', os.path.sep) packages = [root_package] - root_count = len(root_path.split('/')) + root_count = len(root_path.split(os.path.sep)) for (dir_path, dir_names, file_names) in os.walk(convert_path(root_path)): # Prune dir_names *in-place* to prevent unwanted directory recursion for dir_name in list(dir_names): contains_init_file = os.path.isfile(os.path.join(dir_path, dir_name, '__init__.py')) - if dir_name in exclude_dirs or not contains_init_file: + if not contains_init_file: + dir_names.remove(dir_name) + # Exclude compiled PyKE rules, but keep associated unit tests. + if dir_name == 'compiled_krb' and 'tests' not in dir_path: dir_names.remove(dir_name) if dir_names: - prefix = dir_path.split('/')[root_count:] + prefix = dir_path.split(os.path.sep)[root_count:] packages.extend(['.'.join([root_package] + prefix + [dir_name]) - for dir_name in dir_names]) + for dir_name in dir_names]) return packages @@ -40,102 +41,57 @@ def file_walk_relative(top, remove=''): the given prefix from the root/file result. """ + top = top.replace('/', os.path.sep) + remove = remove.replace('/', os.path.sep) for root, dirs, files in os.walk(top): for file in files: yield os.path.join(root, file).replace(remove, '') -def std_name_cmd(target_dir): - script_path = os.path.join('tools', 'generate_std_names.py') - xml_path = os.path.join('etc', 'cf-standard-name-table.xml') - module_path = os.path.join(target_dir, 'iris', 'std_names.py') - cmd = (sys.executable, script_path, xml_path, module_path) - return cmd - - -class TestRunner(setuptools.Command): - """Run the Iris tests under nose and multiprocessor for performance""" - description = "run tests under nose and multiprocessor for performance" - user_options = [('no-data', 'n', 'Override the paths to the data ' - 'repositories so it appears to the ' - 'tests that it does not exist.'), - ('system-tests', 's', 'Run only the limited subset of ' - 'system tests.'), - ('stop', 'x', 'Stop running tests after the first ' - 'error or failure'), - ('example-tests', 'e', 'Also run the example code tests.') - ] - - boolean_options = ['no-data', 'system-tests', 'stop', 'example-tests'] - - def initialize_options(self): - self.no_data = False - self.system_tests = False - self.stop = False - self.example_tests = False - - def finalize_options(self): - if self.no_data: - print "Running tests in no-data mode..." - - # This enviroment variable will be propagated to all the processes that - # nose.run creates allowing us to simluate the absence of test data - os.environ["override_test_data_repository"] = "true" - if self.system_tests: - print "Running system tests..." - if self.stop: - print "Stopping tests after the first error or failure" - - def run(self): - if self.distribution.tests_require: - self.distribution.fetch_build_eggs(self.distribution.tests_require) - - script_path = sys.path[0] - tests = [] - lib_dir = os.path.join(script_path, 'lib') - for mod in os.listdir(lib_dir): - path = os.path.join(lib_dir, mod) - if mod != '.svn' and os.path.exists(os.path.join(path, 'tests')): - tests.append('%s.tests' % mod) - if self.example_tests: - tests.append(os.path.join(script_path, 'docs', 'iris', - 'example_tests')) - - if not tests: - raise CommandError('No tests found in %s/*/tests' % lib_dir) - - if self.system_tests: - regexp_pat = r'--match=^[Ss]ystem' - else: - regexp_pat = r'--match=^([Tt]est(?![Mm]ixin)|[Ss]ystem)' - - n_processors = max(multiprocessing.cpu_count() - 1, 1) - - args = ['', None, '--processes=%s' % n_processors, - '--verbosity=2', regexp_pat, - '--process-timeout=250'] - if self.stop: - args.append('--stop') - - result = True - for test in tests: - args[1] = test - print - print 'Running test discovery on %s with %s processors.' % (test, n_processors) - # run the tests at module level i.e. my_module.tests - # - test must start with test/Test and must not contain the word Mixin. - result &= nose.run(argv=args) - if result is False: - exit(1) - - -class MakeStdNames(Command): +@contextmanager +def temporary_path(directory): """ - Generates the CF standard name module containing mappings from - CF standard name to associated metadata. + Context manager that adds and subsequently removes the given directory + to sys.path """ - description = "generate CF standard name module" + sys.path.insert(0, directory) + try: + yield + finally: + del sys.path[0] + + +# Add full path so Python doesn't load any __init__.py in the intervening +# directories, thereby saving setup.py from additional dependencies. +with temporary_path('lib/iris/tests/runner'): + from _runner import TestRunner # noqa: + +SETUP_DIR = os.path.dirname(__file__) + +def pip_requirements(name): + fname = os.path.join(SETUP_DIR, 'requirements', '{}.txt'.format(name)) + if not os.path.exists(fname): + raise RuntimeError('Unable to find the {} requirements file at {}' + ''.format(name, fname)) + reqs = [] + with open(fname, 'r') as fh: + for line in fh: + line = line.strip() + if not line or line.startswith('#'): + continue + reqs.append(line) + return reqs + + +class SetupTestRunner(TestRunner, Command): + pass + + +class BaseCommand(Command): + """A valid no-op command for setuptools & distutils.""" + + description = 'A no-op command.' user_options = [] def initialize_options(self): @@ -145,109 +101,161 @@ def finalize_options(self): pass def run(self): - cmd = std_name_cmd('lib') - self.spawn(cmd) - - -class MakePykeRules(Command): - """ - Compile the PyKE CF-NetCDF loader rule base. - - """ - description = "compile CF-NetCDF loader rule base" - user_options = [] - - def initialize_options(self): pass - def finalize_options(self): - pass - @staticmethod - def _pyke_rule_compile(): - """Compile the PyKE rule base.""" - from pyke import knowledge_engine - import iris.fileformats._pyke_rules - knowledge_engine.engine(iris.fileformats._pyke_rules) +class CleanSource(BaseCommand): + description = 'clean orphaned pyc/pyo files from the source directory' def run(self): - # Compile the PyKE rules. - MakePykeRules._pyke_rule_compile() + for root_path, dir_names, file_names in os.walk('lib'): + for file_name in file_names: + if file_name.endswith('pyc') or file_name.endswith('pyo'): + compiled_path = os.path.join(root_path, file_name) + source_path = compiled_path[:-1] + if not os.path.exists(source_path): + print('Cleaning', compiled_path) + os.remove(compiled_path) + + +def compile_pyke_rules(cmd, directory): + # Call out to the python executable to pre-compile the Pyke rules. + # Significant effort was put in to trying to get these to compile + # within this build process but there was no obvious way of finding + # a workaround to the issue presented in + # https://github.com/SciTools/iris/issues/2481. + + shelled_code = textwrap.dedent("""\ + + import os + + # Monkey patch the load method to avoid "ModuleNotFoundError: No module + # named 'iris.fileformats._pyke_rules.compiled_krb'". In this instance + # we simply don't want the knowledge engine, so we turn the load method + # into a no-op. + from pyke.target_pkg import target_pkg + target_pkg.load = lambda *args, **kwargs: None + + # Compile the rules by hand, without importing iris. That way we can + # avoid the need for all of iris' dependencies being installed. + os.chdir(os.path.join('{bld_dir}', 'iris', 'fileformats', '_pyke_rules')) + + # Import pyke *after* changing directory. Without this we get the compiled + # rules in the wrong place. Identified in + # https://github.com/SciTools/iris/pull/2891#issuecomment-341404187 + from pyke import knowledge_engine + knowledge_engine.engine('') + """.format(bld_dir=directory)).split('\n') + shelled_code = '; '.join( + [line for line in shelled_code + if not line.strip().startswith('#') and line.strip()]) + args = [sys.executable, '-c', shelled_code] + cmd.spawn(args) -class MissingHeaderError(Exception): - """ - Raised when one or more files do not have the required copyright - and licence header. - """ - pass +def copy_copyright(cmd, directory): + # Copy the COPYRIGHT information into the package root + iris_build_dir = os.path.join(directory, 'iris') + for fname in ['COPYING', 'COPYING.LESSER']: + copyfile(fname, os.path.join(iris_build_dir, fname)) -class BuildPyWithExtras(build_py.build_py): - """ - Adds the creation of the CF standard names module and compilation - of the PyKE rules to the standard "build_py" command. +def build_std_names(cmd, directory): + # Call out to tools/generate_std_names.py to build std_names module. - """ - @contextlib.contextmanager - def temporary_path(self): - """ - Context manager that adds and subsequently removes the build - directory to the beginning of the module search path. - - """ - sys.path.insert(0, self.build_lib) - try: - yield - finally: - del sys.path[0] + script_path = os.path.join('tools', 'generate_std_names.py') + xml_path = os.path.join('etc', 'cf-standard-name-table.xml') + module_path = os.path.join(directory, 'iris', 'std_names.py') + args = (sys.executable, script_path, xml_path, module_path) - def run(self): - # Run the main build command first to make sure all the target - # directories are in place. - build_py.build_py.run(self) + cmd.spawn(args) - # Now build the std_names module. - cmd = std_name_cmd(self.build_lib) - self.spawn(cmd) - # Compile the PyKE rules. - with self.temporary_path(): - MakePykeRules._pyke_rule_compile() +def custom_cmd(command_to_override, functions, help_doc=""): + """ + Allows command specialisation to include calls to the given functions. + """ + class ExtendedCommand(command_to_override): + description = help_doc or command_to_override.description + + def run(self): + # Run the original command first to make sure all the target + # directories are in place. + command_to_override.run(self) + + # build_lib is defined if we are building the package. Otherwise + # we want to to the work in-place. + dest = getattr(self, 'build_lib', None) + if dest is None: + print(' [Running in-place]') + # Pick the source dir instead (currently in the sub-dir "lib") + dest = 'lib' + + for func in functions: + func(self, dest) + + return ExtendedCommand + + +def extract_version(): + version = None + fnme = os.path.join(SETUP_DIR, 'lib', 'iris', '__init__.py') + with open(fnme) as fd: + for line in fd: + if (line.startswith('__version__')): + _, version = line.split('=') + version = version.strip()[1:-1] # Remove quotation characters + break + return version + + +custom_commands = { + 'test': SetupTestRunner, + 'develop': custom_cmd( + develop_cmd, [build_std_names, compile_pyke_rules]), + 'build_py': custom_cmd( + build_py, + [build_std_names, compile_pyke_rules, copy_copyright]), + 'std_names': + custom_cmd(BaseCommand, [build_std_names], + help_doc="generate CF standard name module"), + 'pyke_rules': + custom_cmd(BaseCommand, [compile_pyke_rules], + help_doc="compile CF-NetCDF loader rules"), + 'clean_source': CleanSource, + } + + +pypi_name = 'scitools-iris' + +with open(os.path.join(SETUP_DIR, 'README.md'), 'r') as fh: + description = ''.join(fh.readlines()) setup( - name='Iris', - version='1.7.0-dev', - url='http://scitools.github.com/iris', + name=pypi_name, + version=extract_version(), + url='http://scitools.org.uk/iris/', author='UK Met Office', - + author_email='scitools-iris-dev@googlegroups.com', + description="A powerful, format-agnostic, community-driven Python " + "library for analysing and visualising Earth science data", + long_description=description, + long_description_content_type='text/markdown', packages=find_package_tree('lib/iris', 'iris'), package_dir={'': 'lib'}, - package_data={ - 'iris': list(file_walk_relative('lib/iris/etc', remove='lib/iris/')) + \ - list(file_walk_relative('lib/iris/tests/results', - remove='lib/iris/')) + \ - ['fileformats/_pyke_rules/*.k?b'] + \ - ['tests/stock*.npz'] - }, - data_files=[('iris', ['CHANGES', 'COPYING', 'COPYING.LESSER'])], - tests_require=['nose'], - features={ - 'unpack': setuptools.Feature( - "use of UKMO unpack library", - standard=False, - ext_modules=[ - setuptools.Extension( - 'iris.fileformats.pp_packing', - ['src/iris/fileformats/pp_packing/pp_packing.c'], - libraries=['mo_unpack'], - include_dirs=[np.get_include()] - ) - ] - ) - }, - cmdclass={'test': TestRunner, 'build_py': BuildPyWithExtras, - 'std_names': MakeStdNames, 'pyke_rules': MakePykeRules}, + include_package_data=True, + cmdclass=custom_commands, + + zip_safe=False, + + setup_requires=pip_requirements('setup'), + install_requires=pip_requirements('setup') + pip_requirements('core'), + tests_require=['{}[test]'.format(pypi_name)], + extras_require = { + 'test': pip_requirements('test'), + 'all': pip_requirements('all'), + 'extensions': pip_requirements('extensions'), + }, ) diff --git a/src/iris/fileformats/pp_packing/pp_packing.c b/src/iris/fileformats/pp_packing/pp_packing.c deleted file mode 100644 index 1d83fb3737..0000000000 --- a/src/iris/fileformats/pp_packing/pp_packing.c +++ /dev/null @@ -1,216 +0,0 @@ -// (C) British Crown Copyright 2010 - 2012, Met Office -// -// This file is part of Iris. -// -// Iris is free software: you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License as published by the -// Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Iris is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Iris. If not, see . -#include - -#include - -#include -#include - -static PyObject *wgdos_unpack_py(PyObject *self, PyObject *args); -static PyObject *rle_decode_py(PyObject *self, PyObject *args); - -#define BYTES_PER_INT_UNPACK_PPFIELD 4 -#define LBPACK_WGDOS_PACKED 1 -#define LBPACK_RLE_PACKED 4 - - - -void initpp_packing(void) -{ - - /* The module doc string */ - PyDoc_STRVAR(pp_packing__doc__, - "This extension module provides access to the underlying libmo_unpack library functionality.\n" - "" - ); - - PyDoc_STRVAR(wgdos_unpack__doc__, - "Unpack PP field data that has been packed using WGDOS archive method.\n" - "\n" - "Provides access to the libmo_unpack library function Wgdos_Unpack.\n" - "\n" - "Args:\n\n" - "* data (numpy.ndarray):\n" - " The raw field byte array to be unpacked.\n" - "* lbrow (int):\n" - " The number of rows in the grid.\n" - "* lbnpt (int):\n" - " The number of points (columns) per row in the grid.\n" - "* bmdi (float):\n" - " The value used in the field to indicate missing data points.\n" - "\n" - "Returns:\n" - " numpy.ndarray, 2d array containing normal unpacked field data.\n" - "" - ); - - - PyDoc_STRVAR(rle_decode__doc__, - "Uncompress PP field data that has been compressed using Run Length Encoding.\n" - "\n" - "Provides access to the libmo_unpack library function runlenDecode.\n" - "Decodes the field by expanding out the missing data points represented\n" - "by a single missing data value followed by a value indicating the length\n" - "of the run of missing data values.\n" - "\n" - "Args:\n\n" - "* data (numpy.ndarray):\n" - " The raw field byte array to be uncompressed.\n" - "* lbrow (int):\n" - " The number of rows in the grid.\n" - "* lbnpt (int):\n" - " The number of points (columns) per row in the grid.\n" - "* bmdi (float):\n" - " The value used in the field to indicate missing data points.\n" - "\n" - "Returns:\n" - " numpy.ndarray, 2d array containing normal uncompressed field data.\n" - "" - ); - - /* ==== Set up the module's methods table ====================== */ - static PyMethodDef pp_packingMethods[] = { - {"wgdos_unpack", wgdos_unpack_py, METH_VARARGS, wgdos_unpack__doc__}, - {"rle_decode", rle_decode_py, METH_VARARGS, rle_decode__doc__}, - {NULL, NULL, 0, NULL} /* marks the end of this structure */ - }; - - - Py_InitModule3("pp_packing", pp_packingMethods, pp_packing__doc__); - import_array(); // Must be present for NumPy. -} - - -/* wgdos_unpack(byte_array, lbrow, lbnpt, mdi) */ -static PyObject *wgdos_unpack_py(PyObject *self, PyObject *args) -{ - char *bytes_in=NULL; - PyArrayObject *npy_array_out=NULL; - int bytes_in_len; - npy_intp dims[2]; - int lbrow, lbnpt, npts; - float mdi; - - if (!PyArg_ParseTuple(args, "s#iif", &bytes_in, &bytes_in_len, &lbrow, &lbnpt, &mdi)) return NULL; - - // Unpacking algorithm accepts an int - so assert that lbrow*lbnpt does not overflow - if (lbrow > 0 && lbnpt >= INT_MAX / (lbrow+1)) { - PyErr_SetString(PyExc_ValueError, "Resulting unpacked PP field is larger than PP supports."); - return NULL; - } else{ - npts = lbnpt*lbrow; - } - - /* Do the unpack of the given byte array */ - float *dataout = (float*)calloc(npts, sizeof(float)); - - if (dataout == NULL) { - PyErr_SetString(PyExc_ValueError, "Unable to allocate memory for wgdos_unpacking."); - return NULL; - } - - function func; // function is defined by wgdosstuff. - set_function_name(__func__, &func, 0); - int status = unpack_ppfield(mdi, 0, bytes_in, LBPACK_WGDOS_PACKED, npts, dataout, &func); - - /* Raise an exception if there was a problem with the WGDOS algorithm */ - if (status != 0) { - free(dataout); - PyErr_SetString(PyExc_ValueError, "WGDOS unpack encountered an error."); - return NULL; - } - else { - /* The data came back fine, so make a Numpy array and return it */ - dims[0]=lbrow; - dims[1]=lbnpt; - npy_array_out=(PyArrayObject *) PyArray_SimpleNewFromData(2, dims, NPY_FLOAT, dataout); - - if (npy_array_out == NULL) { - PyErr_SetString(PyExc_ValueError, "Failed to make the numpy array for the packed data."); - return NULL; - } - - // give ownership of dataout to the Numpy array - Numpy will then deal with memory cleanup. - npy_array_out->flags = npy_array_out->flags | NPY_OWNDATA; - - return (PyObject *)npy_array_out; - } -} - - -/* A null function required by the wgdos unpack library */ -void MO_syslog(int value, char* message, const function* const caller) -{ - /* printf("MESSAGE %d %s: %s\n", value, caller, message); */ - return; -} - - -/* rle_decode(byte_array, lbrow, lbnpt, mdi) */ -static PyObject *rle_decode_py(PyObject *self, PyObject *args) -{ - char *bytes_in=NULL; - PyArrayObject *npy_array_out=NULL; - int bytes_in_len; - npy_intp dims[2]; - int lbrow, lbnpt, npts; - float mdi; - - if (!PyArg_ParseTuple(args, "s#iif", &bytes_in, &bytes_in_len, &lbrow, &lbnpt, &mdi)) return NULL; - - // Unpacking algorithm accepts an int - so assert that lbrow*lbnpt does not overflow - if (lbrow > 0 && lbnpt >= INT_MAX / (lbrow+1)) { - PyErr_SetString(PyExc_ValueError, "Resulting unpacked PP field is larger than PP supports."); - return NULL; - } else{ - npts = lbnpt*lbrow; - } - - float *dataout = (float*)calloc(npts, sizeof(float)); - - if (dataout == NULL) { - PyErr_SetString(PyExc_ValueError, "Unable to allocate memory for wgdos_unpacking."); - return NULL; - } - - function func; // function is defined by wgdosstuff. - set_function_name(__func__, &func, 0); - int status = unpack_ppfield(mdi, (bytes_in_len/BYTES_PER_INT_UNPACK_PPFIELD), bytes_in, LBPACK_RLE_PACKED, npts, dataout, &func); - - /* Raise an exception if there was a problem with the REL algorithm */ - if (status != 0) { - free(dataout); - PyErr_SetString(PyExc_ValueError, "RLE decode encountered an error."); - return NULL; - } - else { - /* The data came back fine, so make a Numpy array and return it */ - dims[0]=lbrow; - dims[1]=lbnpt; - npy_array_out=(PyArrayObject *) PyArray_SimpleNewFromData(2, dims, NPY_FLOAT, dataout); - - if (npy_array_out == NULL) { - PyErr_SetString(PyExc_ValueError, "Failed to make the numpy array for the packed data."); - return NULL; - } - - // give ownership of dataout to the Numpy array - Numpy will then deal with memory cleanup. - npy_array_out->flags = npy_array_out->flags | NPY_OWNDATA; - return (PyObject *)npy_array_out; - } -} diff --git a/tools/gen_helpers.py b/tools/gen_helpers.py new file mode 100644 index 0000000000..e4d7687f15 --- /dev/null +++ b/tools/gen_helpers.py @@ -0,0 +1,61 @@ +# (C) British Crown Copyright 2013 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +from datetime import datetime +import os +import os.path + +HEADER = \ + '''# (C) British Crown Copyright 2013 - {}, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +# +# DO NOT EDIT: AUTO-GENERATED''' + + +def absolute_path(path): + return os.path.abspath(os.path.join(os.path.dirname(__file__), path)) + + +def prep_module_file(module_path): + """ + prepare a module file, creating directory if needed and writing the + header into that file + + """ + module_path = absolute_path(module_path) + module_dir = os.path.dirname(module_path) + if not os.path.isdir(module_dir): + os.makedirs(module_dir) + with open(module_path, 'w') as module_file: + module_file.write(HEADER.format(datetime.utcnow().year)) diff --git a/tools/gen_stash_refs.py b/tools/gen_stash_refs.py new file mode 100644 index 0000000000..6db1f25491 --- /dev/null +++ b/tools/gen_stash_refs.py @@ -0,0 +1,145 @@ +# (C) British Crown Copyright 2013 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +import json +import urllib +import urllib2 + +from iris.fileformats.pp import STASH + +import gen_helpers + + +HEADER = ''' +""" +Auto-generated from iris/tools/gen_stash_refs.py +Relates grid code and field code to the stash code. + +""" +''' + + +CODE_PREAMBLE = ("\nfrom __future__ import " + "(absolute_import, division, print_function)\n" + "from six.moves import " + "(filter, input, map, range, zip) # noqa\n\n" + "from collections import namedtuple\n\n\n" + "Stash = namedtuple('Stash', " + "'grid_code field_code pseudo_level_type')\n\n\n") + + +def _value_from_xref(xref, name): + """Return the value for the key name from xref. + + Will return 0 if the key does not look like an integer. + """ + + result = xref.get(name) + try: + int(result) + except (ValueError, TypeError): + result = 0 + return result + + +def write_cross_reference_module(module_path, xrefs): + gen_helpers.prep_module_file(module_path) + with open(module_path, 'a') as module_file: + module_file.write(HEADER) + module_file.write(CODE_PREAMBLE) + module_file.write('STASH_TRANS = {\n') + for xref in xrefs: + stash = xref.get('stash') + try: + STASH.from_msi(stash.replace('"', '')) + except ValueError: + msg = ('stash code is not of a recognised' + '"m??s??i???" form: {}'.format(stash)) + print(msg) + grid = xref.get('grid') + if grid is not None: + try: + int(grid) + except ValueError: + msg = ('grid code retrieved from STASH lookup' + 'is not an integer: {}'.format(grid)) + print(msg) + else: + grid = 0 + + lbfc = _value_from_xref(xref, 'lbfcn') + pseudT = _value_from_xref(xref, 'pseudT') + + module_file.write( + ' "{}": Stash({}, {}, {}),\n'.format(stash, + grid, + lbfc, + pseudT)) + module_file.write('}\n') + + +def stash_grid_retrieve(): + """return a dictionary of stash codes and rel;ated information from + the Met Office Reference Registry + """ + baseurl = 'http://reference.metoffice.gov.uk/system/query?query=' + query = '''prefix rdf: +prefix rdfs: +prefix skos: + +SELECT ?stash ?grid ?lbfcn ?pseudT +WHERE { + ?stashcode rdf:type ; + skos:notation ?stash ; + ?gridcode . +OPTIONAL { ?gridcode skos:notation ?grid .} +OPTIONAL {?stashcode ?lbfc . + ?lbfc skos:notation ?lbfcn .} +OPTIONAL {?stashcode ?pseudT_id . + ?pseudT_id skos:notation ?pseudT . } +} +order by ?stash''' + + encquery = urllib.quote_plus(query) + out_format = '&output=json' + url = baseurl + encquery + out_format + + response = urllib2.urlopen(url) + stash = json.loads(response.read()) + + ## heads will be of the form [u'stash', u'grid', u'lbfcn', u'pseudT'] + ## as defined in the query string + heads = stash['head']['vars'] + + stashcodes = [] + + for result in stash['results']['bindings']: + res = {} + for head in heads: + if head in result: + res[head] = result[head]['value'] + stashcodes.append(res) + return stashcodes + + +if __name__ == '__main__': + xrefs = stash_grid_retrieve() + outfile = '../lib/iris/fileformats/_ff_cross_references.py' + write_cross_reference_module(outfile, xrefs) diff --git a/tools/gen_translations.py b/tools/gen_translations.py new file mode 100644 index 0000000000..5a710c5220 --- /dev/null +++ b/tools/gen_translations.py @@ -0,0 +1,239 @@ +# (C) British Crown Copyright 2014 - 2017, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Processing of metarelate metOcean content to provide Iris encodings of +metOcean mapping translations. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +from datetime import datetime +import os.path +import requests +import sys + +from metarelate.fuseki import FusekiServer + +from translator import (FORMAT_URIS, FieldcodeCFMappings, StashCFNameMappings, + StashCFHeightConstraintMappings, + CFFieldcodeMappings, + GRIB1LocalParamCFConstrainedMappings, + GRIB1LocalParamCFMappings, GRIB2ParamCFMappings, + CFConstrainedGRIB1LocalParamMappings, + CFGRIB2ParamMappings, CFGRIB1LocalParamMappings) + +HEADER = """# (C) British Crown Copyright 2013 - {year}, Met Office +# +# This file is part of {name}. +# +# {name} is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# {name} is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with {name}. If not, see . +# +# DO NOT EDIT: AUTO-GENERATED +# Created on {datestamp} from +# http://www.metarelate.net/metOcean +# at commit {git_sha} +# https://github.com/metarelate/metOcean/commit/{git_sha} +{doc_string} + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +from collections import namedtuple + + +CFName = namedtuple('CFName', 'standard_name long_name units') +""" + +HEADER_GRIB = """ +DimensionCoordinate = namedtuple('DimensionCoordinate', + 'standard_name units points') + +G1LocalParam = namedtuple('G1LocalParam', 'edition t2version centre iParam') +G2Param = namedtuple('G2Param', 'edition discipline category number') +""" + +DOC_STRING_GRIB = r'''""" +Provides GRIB/CF phenomenon translations. + +"""''' + +DOC_STRING_UM = r'''""" +Provides UM/CF phenomenon translations. + +"""''' + +YEAR = datetime.utcnow().year + +def _retrieve_mappings(fuseki, source, target): + """ + Interrogate the metarelate triple store for all + phenomenon translation mappings from the source + scheme to the target scheme. + + Args: + * fuseki: + The :class:`metrelate.fuseki.FusekiServer` instance. + * source: + The source metarelate metadata type for the mapping. + * target: + The target metarelate metadata type for the mapping. + + Return: + The sequence of :class:`metarelate.Mapping` + instances. + + """ + suri = 'http://www.metarelate.net/sparql/metOcean' + msg = 'Retrieving {!r} to {!r} mappings ...' + print(msg.format(source, target)) + return fuseki.retrieve_mappings(source, target, service=suri) + + +def build_um_cf_map(fuseki, now, git_sha, base_dir): + """ + Encode the UM/CF phenomenon translation mappings + within the specified file. + + Args: + * fuseki: + The :class:`metarelate.fuseki.FusekiServer` instance. + * now: + Time stamp to write into the file + * git_sha: + The git SHA1 of the metarelate commit + * base_dir: + The root directory of the Iris source. + + """ + filename = os.path.join(base_dir, 'lib', 'iris', 'fileformats', + 'um_cf_map.py') + + # Create the base directory. + if not os.path.exists(os.path.dirname(filename)): + os.makedirs(os.path.dirname(filename)) + + # Create the file to contain UM/CF translations. + with open(filename, 'w') as fh: + fh.write(HEADER.format(year=YEAR, doc_string=DOC_STRING_UM, + datestamp=now, git_sha=git_sha, name='Iris')) + fh.write('\n') + + # Encode the relevant UM to CF translations. + maps = _retrieve_mappings(fuseki, FORMAT_URIS['umf'], + FORMAT_URIS['cff']) + # create the collections, then call lines on each one + # for thread safety during lines and encode + fccf = FieldcodeCFMappings(maps) + stcf = StashCFNameMappings(maps) + stcfhcon = StashCFHeightConstraintMappings(maps) + fh.writelines(fccf.lines(fuseki)) + fh.writelines(stcf.lines(fuseki)) + fh.writelines(stcfhcon.lines(fuseki)) + + # Encode the relevant CF to UM translations. + maps = _retrieve_mappings(fuseki, FORMAT_URIS['cff'], + FORMAT_URIS['umf']) + # create the collections, then call lines on each one + # for thread safety during lines and encode + cffc = CFFieldcodeMappings(maps) + fh.writelines(cffc.lines(fuseki)) + + +def build_grib_cf_map(fuseki, now, git_sha, base_dir): + """ + Encode the GRIB/CF phenomenon translation mappings + within the specified file. + + Args: + * fuseki: + The :class:`metarelate.fuseki.FusekiServer` instance. + * now: + Time stamp to write into the file + * git_sha: + The git SHA1 of the metarelate commit + * base_dir: + The root directory of the Iris source. + + """ + filename = os.path.join(base_dir, 'lib', 'iris', 'fileformats', + 'grib', '_grib_cf_map.py') + if not os.path.exists(os.path.dirname(filename)): + os.makedirs(os.path.dirname(filename)) + + # Create the file to contain GRIB/CF translations. + with open(filename, 'w') as fh: + fh.write(HEADER.format(year=YEAR, doc_string=DOC_STRING_GRIB, + datestamp=now, git_sha=git_sha, + name='Iris')) + fh.write(HEADER_GRIB) + fh.write('\n') + + # Encode the relevant GRIB to CF translations. + maps = _retrieve_mappings(fuseki, FORMAT_URIS['gribm'], + FORMAT_URIS['cff']) + # create the collections, then call lines on each one + # for thread safety during lines and encode + g1cfc = GRIB1LocalParamCFConstrainedMappings(maps) + g1c = GRIB1LocalParamCFMappings(maps) + g2c = GRIB2ParamCFMappings(maps) + fh.writelines(g1cfc.lines(fuseki)) + fh.writelines(g1c.lines(fuseki)) + fh.writelines(g2c.lines(fuseki)) + + # Encode the relevant CF to GRIB translations. + maps = _retrieve_mappings(fuseki, FORMAT_URIS['cff'], + FORMAT_URIS['gribm']) + # create the collections, then call lines on each one + # for thread safety during lines and encode + cfcg1 = CFConstrainedGRIB1LocalParamMappings(maps) + cg1 = CFGRIB1LocalParamMappings(maps) + cg2 = CFGRIB2ParamMappings(maps) + fh.writelines(cfcg1.lines(fuseki)) + fh.writelines(cg1.lines(fuseki)) + fh.writelines(cg2.lines(fuseki)) + + +def main(): + now = datetime.utcnow().strftime('%d %B %Y %H:%m') + git_sha = requests.get('http://www.metarelate.net/metOcean/latest_sha').text + gen_path = os.path.abspath(sys.modules['__main__'].__file__) + iris_path = os.path.dirname(os.path.dirname(gen_path)) + with FusekiServer() as fuseki: + build_um_cf_map(fuseki, now, git_sha, iris_path) + build_grib_cf_map(fuseki, now, git_sha, iris_path) + + if (git_sha != + requests.get('http://www.metarelate.net/metOcean/latest_sha').text): + raise ValueError('The metarelate translation store has altered during' + 'your retrieval, the results may not be stable.\n' + 'Please rerun your retrieval.') + +if __name__ == '__main__': + main() diff --git a/tools/generate_std_names.py b/tools/generate_std_names.py index aed9388dea..ba00ef23b7 100644 --- a/tools/generate_std_names.py +++ b/tools/generate_std_names.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2013, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -28,13 +28,17 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + import argparse import pprint import xml.etree.ElementTree as ET STD_VALUES_FILE_TEMPLATE = ''' -# (C) British Crown Copyright 2010 - 2012, Met Office +# (C) British Crown Copyright 2010 - 2015, Met Office # # This file is part of Iris. # @@ -69,6 +73,9 @@ """ +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + STD_NAMES = '''.lstrip() @@ -100,7 +107,7 @@ def to_dict(infile, outfile): for section in process_name_table(tree, 'alias', 'entry_id'): aliases.update(section) - for key, valued in aliases.iteritems(): + for key, valued in six.iteritems(aliases): values.update({ key : {'canonical_units' : values.get(valued['entry_id']).get('canonical_units')} }) @@ -111,11 +118,17 @@ def to_dict(infile, outfile): if __name__ == "__main__": parser = argparse.ArgumentParser( description='Create Python code from CF standard name XML.') - parser.add_argument('input', type=argparse.FileType(), - metavar='INPUT', + parser.add_argument('input', metavar='INPUT', help='Path to CF standard name XML') - parser.add_argument('output', type=argparse.FileType('w'), - metavar='OUTPUT', + parser.add_argument('output', metavar='OUTPUT', help='Path to resulting Python code') args = parser.parse_args() - to_dict(args.input, args.output) + + if six.PY2: + encoding = {} + else: + encoding = {'encoding': 'utf-8'} + + with open(args.input, 'r', **encoding) as in_fh: + with open(args.output, 'w', **encoding) as out_fh: + to_dict(in_fh, out_fh) diff --git a/tools/translator/__init__.py b/tools/translator/__init__.py new file mode 100644 index 0000000000..26e66c75d4 --- /dev/null +++ b/tools/translator/__init__.py @@ -0,0 +1,1128 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Provides the framework to support the encoding of metarelate mapping +translations. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa +import six + +from abc import ABCMeta, abstractmethod, abstractproperty +from collections import deque, namedtuple +import copy +from six.moves.queue import Queue +import re +from threading import Thread +import warnings + +from metarelate.fuseki import FusekiServer, WorkerThread, MAXTHREADS +import metarelate + +# known format identifier URIs +FORMAT_URIS = {'cff': '', + 'gribm': '', + 'umf': ''} + +CFName = namedtuple('CFName', 'standard_name long_name units') +DimensionCoordinate = namedtuple('DimensionCoordinate', + 'standard_name units points') +G1LocalParam = namedtuple('G1LocalParam', 'edition t2version centre iParam') +G2Param = namedtuple('G2Param', 'edition discipline category number') + + +class MappingEncodeWorker(WorkerThread): + """Worker thread class for handling EncodableMap instances""" + def dowork(self, resource): + resource.encode(self.fuseki_process) + + +class EncodableMap(object): + """ + A metarelate mapping able to encode itself as a string for use in Iris, + as defined by a translator Mappings subclass + + """ + def __init__(self, mapping, sourcemsg, targetmsg, sourceid, targetid): + """ + Args: + * mapping: + A :class:`metarelate.Mapping` instance representing a translation. + * sourcemsg: + The code snippet message for the source of the translation for + formatting + * targetmsg: + The code snippet message for the target of the translation for + formatting + * sourceid: + A dictionary of required key:value pairs required by the sourcemsg + * targetid: + A dictionary of required key:value pairs required by the targetmsg + + """ + self.mapping = mapping + self.sourcemsg = sourcemsg + self.targetmsg = targetmsg + self.sourceid = sourceid + self.targetid = targetid + self.encoding = None + + def encode(self, fuseki_process): + """ + Return a string of the Python source code required to represent an + entry in a dictionary mapping source to target. + + Args: + * fuseki_process: + A :class:`metarelate.fuseki.FusekiServer` instance. + + """ + sids, tids = self.mapping.get_identifiers(fuseki_process) + self.sourceid.update(sids) + self.targetid.update(tids) + self.encoding = '{}: {}'.format(self.sourcemsg.format(**self.sourceid), + self.targetmsg.format(**self.targetid)) + + +class Mappings(six.with_metaclass(ABCMeta, object)): + """ + Abstract base class to support the encoding of specific metarelate + mapping translations. + + """ + + def __init__(self, mappings): + """ + Filter the given sequence of mappings for those member + :class:`metarelate.Mapping` translations containing a source + :class:`metarelate.Component` with a matching + :attribute:`Mapping.source_scheme` and a target + :class:`metarelate.Component` with a matching + :attribute:`Mapping.target_scheme`. + + Also see :method:`Mapping.valid_mapping` for further matching + criterion for candidate metarelate mapping translations. + + Args: + * mappings: + Iterator of :class:`metarelate.Mapping` instances. + + """ + temp = [] + # Filter the mappings for the required type of translations. + for mapping in mappings: + source = mapping.source + target = mapping.target + sourcemsg, targetmsg = self.msg_strings() + sourceid, targetid = self.get_initial_id_nones() + if source.com_type == self.source_scheme and \ + target.com_type == self.target_scheme and \ + self.valid_mapping(mapping): + temp.append(EncodableMap(mapping, sourcemsg, targetmsg, + sourceid, targetid)) + self.mappings = temp + if len(self) == 0: + msg = '{!r} contains no mappings.' + warnings.warn(msg.format(self.__class__.__name__)) + + def _sort_lines(self, payload): + """ + Return the payload, unsorted. + + """ + return payload + + def lines(self, fuseki_process): + """ + Provides an iterator generating the encoded string representation + of each member of this metarelate mapping translation. + + Returns: + An iterator of string. + + """ + msg = '\tGenerating phenomenon translation {!r}.' + print(msg.format(self.mapping_name)) + lines = ['\n%s = {\n' % self.mapping_name] + # Retrieve encodings for the collection of mapping instances. + # Retrieval is threaded as it is heavily bound by resource resolution + # over http. + # Queue for metarelate mapping instances + mapenc_queue = Queue() + for mapping in self.mappings: + mapenc_queue.put(mapping) + # deque to contain the results of the jobs processed from the queue + mapencs = deque() + # run worker threads + for i in range(MAXTHREADS): + MappingEncodeWorker(mapenc_queue, mapencs, fuseki_process).start() + # block progress until the queue is empty + mapenc_queue.join() + # end of threaded retrieval process. + + # now sort the payload + payload = [mapenc.encoding for mapenc in mapencs] + payload.sort(key=self._key) + lines.extend(payload) + lines.append(' }\n') + return iter(lines) + + def __len__(self): + return len(self.mappings) + + def _key(self, line): + """Method to provide the sort key of the mappings order.""" + return line + + @abstractproperty + def mapping_name(self): + """ + Abstract property that specifies the name of the dictionary + to contain the encoding of this metarelate mapping translation. + + """ + + @abstractproperty + def source_scheme(self): + """ + Abstract property that specifies the name of the scheme for + the source :class:`metarelate.Component` defining this metarelate + mapping translation. + + """ + + @abstractproperty + def target_scheme(self): + """ + Abstract property that specifies the name of the scheme for + the target :class:`metarelate.Component` defining this metarelate + mapping translation. + + """ + + @abstractmethod + def valid_mapping(self, mapping): + """ + Abstract method that determines whether the provided + :class:`metarelate.Mapping` is a translation from the required + source :class:`metarelate.Component` to the required target + :class:`metarelate.Component`. + + """ + + def get_initial_id_nones(self): + """ + Return the identifier items which may not exist, in the translation + database, and are needed for a msg_string. These must exist, even + even if not written from the database. + + Returns two dictionaries to use as the start point for + population from the database. + + """ + sourceid = {} + targetid = {} + return sourceid, targetid + + def is_cf(self, comp): + """ + Determines whether the provided component from a mapping + represents a simple CF component of the given kind. + + Args: + * component: + A :class:`metarelate.Component` or + :class:`metarelate.Component` instance. + + Returns: + Boolean. + + """ + kind = FORMAT_URIS['cff'] + result = False + result = hasattr(comp, 'com_type') and \ + comp.com_type == kind and \ + hasattr(comp, 'units') and \ + len(comp) in [1, 2] + return result + + def is_cf_constrained(self, comp): + """ + Determines whether the provided component from a mapping + represents a compound CF component for a phenomenon and + one, single valued dimension coordinate. + + Args: + * component: + A :class:`metarelate.Component` instance. + + Returns: + Boolean. + + """ + ftype = FORMAT_URIS['cff'] + result = False + cffield = hasattr(comp, 'com_type') and comp.com_type == ftype and \ + hasattr(comp, 'units') and (hasattr(comp, 'standard_name') or + hasattr(comp, 'long_name')) + dimcoord = hasattr(comp, 'dim_coord') and \ + isinstance(comp.dim_coord, metarelate.ComponentProperty) and \ + comp.dim_coord.component.com_type.notation == 'DimCoord' + result = cffield and dimcoord + return result + + def is_cf_height_constrained(self, comp): + item_sn = metarelate.Item((''), + 'standard_name') + item_h = metarelate.Item((''), + 'height') + snprop = metarelate.StatementProperty(item_sn, item_h) + item_u = metarelate.Item((''), + 'units') + uprop = metarelate.StatementProperty(item_u, + metarelate.Item('"m"', 'm')) + pts_pred = metarelate.Item((''), + 'points') + result = False + if self.is_cf_constrained(comp): + props = comp.dim_coord.component.properties + if len(props) == 3: + if snprop in props and uprop in props: + preds = [prop.predicate for prop in props] + if pts_pred in preds: + result = True + return result + + def is_fieldcode(self, component): + """ + Determines whether the provided concept from a mapping + represents a simple UM concept for a field-code. + + Args: + * concept: + A :class:`metarelate.Component` instance. + + Returns: + Boolean. + + """ + result = False + result = hasattr(component, 'lbfc') and len(component) == 1 + return result + + def is_grib1_local_param(self, component): + """ + Determines whether the provided component from a mapping + represents a simple GRIB edition 1 component for a local + parameter. + + Args: + * component: + A :class:`metarelate.Component` instance. + + Returns: + Boolean. + + """ + result = len(component) == 1 and hasattr(component, 'grib1_parameter') + return result + + def is_grib2_param(self, component): + """ + Determines whether the provided component from a mapping + represents a simple GRIB edition 2 component for a parameter. + + Args: + * component: + A :class:`metarelate.Component` instance. + + Returns: + Boolean. + + """ + + result = len(component) == 1 and hasattr(component, 'grib2_parameter') + return result + + def is_stash(self, component): + """ + Determines whether the provided concept for a mapping + represents a simple UM concept for a stash-code. + + Args: + * concept: + A :class:`metarelate.Component` instance. + + Returns: + Boolean. + + """ + result = False + result = hasattr(component, 'stash') and len(component) == 1 + return result + + +def _cfn(line): + """ + Helper function to parse dictionary lines using the CFName named tuple. + Matches to the line ' CFName({standard_name}, {long_name}, {units}:*) + giving access to these named parts + + """ + match = re.match('^ CFName\((.+), (.+), (.+)\):.+,', line) + if match is None: + raise ValueError('encoding not sortable') + standard_name, long_name, units = match.groups() + if standard_name == 'None': + standard_name = None + if long_name == 'None': + long_name = None + return [standard_name, long_name, units] + + +class CFFieldcodeMappings(Mappings): + """ + Represents a container for CF phenomenon to UM field-code metarelate + mapping translations. + + Encoding support is provided to generate the Python dictionary source + code representation of these mappings from CF standard name, long name, + and units to UM field-code. + + """ + def _key(self, line): + """Provides the sort key of the mappings order.""" + return _cfn(line) + + def msg_strings(self): + return (' CFName({standard_name!r}, {long_name!r}, ' + '{units!r})', + '{lbfc},\n') + + def get_initial_id_nones(self): + sourceid = {'standard_name': None, 'long_name': None} + targetid = {} + return sourceid, targetid + + @property + def mapping_name(self): + """ + Property that specifies the name of the dictionary to contain the + encoding of this metarelate mapping translation. + + """ + return 'CF_TO_LBFC' + + @property + def source_scheme(self): + """ + Property that specifies the name of the scheme for the source + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['cff'] + + @property + def target_scheme(self): + """ + Property that specifies the name of the scheme for the target + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['umf'] + + def valid_mapping(self, mapping): + """ + Determine whether the provided :class:`metarelate.Mapping` represents a + CF to UM field-code translation. + + Args: + * mapping: + A :class:`metarelate.Mapping` instance. + + Returns: + Boolean. + + """ + return self.is_cf(mapping.source) and self.is_fieldcode(mapping.target) + + +class FieldcodeCFMappings(Mappings): + """ + Represents a container for UM field-code to CF phenomenon metarelate + mapping translations. + + Encoding support is provided to generate the Python dictionary source + code representation of these mappings from UM field-code to + CF standard name, long name, and units. + + """ + def _key(self, line): + """Provides the sort key of the mappings order.""" + return int(line.split(':')[0].strip()) + + def msg_strings(self): + return (' {lbfc}', + 'CFName({standard_name!r}, {long_name!r}, {units!r}),\n') + + def get_initial_id_nones(self): + sourceid = {} + targetid = {'standard_name': None, 'long_name': None} + return sourceid, targetid + + @property + def mapping_name(self): + """ + Property that specifies the name of the dictionary to contain the + encoding of this metarelate mapping translation. + + """ + return 'LBFC_TO_CF' + + @property + def source_scheme(self): + """ + Property that specifies the name of the scheme for the source + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['umf'] + + @property + def target_scheme(self): + """ + Property that specifies the name of the scheme for the target + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['cff'] + + def valid_mapping(self, mapping): + """ + Determine whether the provided :class:`metarelate.Mapping` represents a + UM field-code to CF translation. + + Args: + * mapping: + A :class:`metarelate.Mapping` instance. + + Returns: + Boolean. + + """ + return self.is_fieldcode(mapping.source) and self.is_cf(mapping.target) + + +class StashCFNameMappings(Mappings): + """ + Represents a container for UM stash-code to CF phenomenon metarelate + mapping translations. + + Encoding support is provided to generate the Python dictionary source + code representation of these mappings from UM stash-code to CF + standard name, long name, and units. + + """ + def _key(self, line): + """Provides the sort key of the mappings order.""" + return line.split(':')[0].strip() + + def msg_strings(self): + return(' {stash!r}', + 'CFName({standard_name!r}, ' + '{long_name!r}, {units!r}),\n') + + def get_initial_id_nones(self): + sourceid = {} + targetid = {'standard_name': None, 'long_name': None} + return sourceid, targetid + + @property + def mapping_name(self): + """ + Property that specifies the name of the dictionary to contain the + encoding of this metarelate mapping translation. + + """ + return 'STASH_TO_CF' + + @property + def source_scheme(self): + """ + Property that specifies the name of the scheme for the source + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['umf'] + + @property + def target_scheme(self): + """ + Property that specifies the name of the scheme for the target + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['cff'] + + def valid_mapping(self, mapping): + """ + Determine whether the provided :class:`metarelate.Mapping` represents a + UM stash-code to CF translation. + + Args: + * mapping: + A :class:`metarelate.Mapping` instance. + + Returns: + Boolean. + + """ + return (self.is_stash(mapping.source) and + (self.is_cf(mapping.target) or + self.is_cf_constrained(mapping.target))) + + +class StashCFHeightConstraintMappings(Mappings): + """ + Represents a container for UM stash-code to CF phenomenon metarelate + mapping translations where a singular height constraint is defined by + the STASH code. + + Encoding support is provided to generate the Python dictionary source + code representation of these mappings from UM stash-code to CF + standard name, long name, and units. + + """ + def _key(self, line): + """Provides the sort key of the mappings order.""" + return line.split(':')[0].strip() + + def msg_strings(self): + return(' {stash!r}', + '{dim_coord[points]},\n') + + def get_initial_id_nones(self): + sourceid = {} + targetid = {} + return sourceid, targetid + + @property + def mapping_name(self): + """ + Property that specifies the name of the dictionary to contain the + encoding of this metarelate mapping translation. + + """ + return 'STASHCODE_IMPLIED_HEIGHTS' + + @property + def source_scheme(self): + """ + Property that specifies the name of the scheme for the source + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['umf'] + + @property + def target_scheme(self): + """ + Property that specifies the name of the scheme for the target + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['cff'] + + def valid_mapping(self, mapping): + """ + Determine whether the provided :class:`metarelate.Mapping` represents a + UM stash-code to CF translation. + + Args: + * mapping: + A :class:`metarelate.Mapping` instance. + + Returns: + Boolean. + + """ + return (self.is_stash(mapping.source) and + self.is_cf_height_constrained(mapping.target)) + + +class GRIB1LocalParamCFMappings(Mappings): + """ + Represents a container for GRIB (edition 1) local parameter to + CF phenomenon metarelate mapping translations. + + Encoding support is provided to generate the Python dictionary source + code representation of these mappings from GRIB1 edition, table II version, + centre and indicator of parameter to CF standard name, long name and units. + + """ + def _key(self, line): + """Provides the sort key of the mappings order.""" + matchstr = ('^ G1LocalParam\(([0-9]+), ([0-9]+), ' + '([0-9]+), ([0-9]+)\):.*') + match = re.match(matchstr, line) + if match is None: + raise ValueError('encoding not sortable') + return [int(i) for i in match.groups()] + + def msg_strings(self): + return (' G1LocalParam({editionNumber}, {table2version}, ' + '{centre}, {indicatorOfParameter})', + 'CFName({standard_name!r}, ' + '{long_name!r}, {units!r}),\n') + + def get_initial_id_nones(self): + sourceid = {} + targetid = {'standard_name': None, 'long_name': None} + return sourceid, targetid + + @property + def mapping_name(self): + """ + Property that specifies the name of the dictionary to contain the + encoding of this metarelate mapping translation. + + """ + return 'GRIB1_LOCAL_TO_CF' + + @property + def source_scheme(self): + """ + Property that specifies the name of the scheme for the source + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['gribm'] + + @property + def target_scheme(self): + """ + Property that specifies the name of the scheme for the target + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['cff'] + + def valid_mapping(self, mapping): + """ + Determine whether the provided :class:`metarelate.Mapping` represents a + GRIB1 local parameter to CF phenomenon translation. + + Args: + * mapping: + A :class:`metarelate.Mapping` instance. + + Returns: + Boolean. + + """ + return self.is_grib1_local_param(mapping.source) and \ + self.is_cf(mapping.target) + + +class CFGRIB1LocalParamMappings(Mappings): + """ + Represents a container for CF phenomenon to GRIB (edition 1) local + parameter metarelate mapping translations. + + Encoding support is provided to generate the Python dictionary source + code representation of these mappings from CF standard name, long name + and units to GRIB1 edition, table II version, centre and indicator of + parameter. + + """ + def _key(self, line): + """Provides the sort key of the mappings order.""" + return _cfn(line) + + def msg_strings(self): + return (' CFName({standard_name!r}, {long_name!r}, ' + '{units!r})', + 'G1LocalParam({editionNumber}, {table2version}, ' + '{centre}, {indicatorOfParameter}),\n') + + def get_initial_id_nones(self): + sourceid = {'standard_name': None, 'long_name': None} + targetid = {} + return sourceid, targetid + + @property + def mapping_name(self): + """ + Property that specifies the name of the dictionary to contain the + encoding of this metarelate mapping translation. + + """ + return 'CF_TO_GRIB1_LOCAL' + + @property + def source_scheme(self): + """ + Property that specifies the name of the scheme for the source + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['cff'] + + @property + def target_scheme(self): + """ + Property that specifies the name of the scheme for the target + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['gribm'] + + def valid_mapping(self, mapping): + """ + Determine whether the provided :class:`metarelate.Mapping` represents a + CF phenomenon to GRIB1 local parameter translation. + + Args: + * mapping: + A :class:`metarelate.Mapping` instance. + + Returns: + Boolean. + + """ + return self.is_cf(mapping.source) and \ + self.is_grib1_local_param(mapping.target) + + +class GRIB1LocalParamCFConstrainedMappings(Mappings): + """ + Represents a container for GRIB (edition 1) local parameter to + CF phenomenon and dimension coordinate constraint metarelate mapping + translations. + + Encoding support is provided to generate the Python dictionary source + code representation of these mappings from GRIB1 edition, table II version, + centre and indicator of parameter to CF phenomenon standard name, long name + and units, and CF dimension coordinate standard name, units and points. + + """ + def _key(self, line): + """Provides the sort key of the mappings order.""" + return line.split(':')[0].strip() + + def msg_strings(self): + return (' G1LocalParam({editionNumber}, {table2version}, ' + '{centre}, {indicatorOfParameter})', + '(CFName({standard_name!r}, ' + '{long_name!r}, {units!r}), ' + 'DimensionCoordinate({dim_coord[standard_name]!r}, ' + '{dim_coord[units]!r}, {dim_coord[points]})),\n') + + def get_initial_id_nones(self): + sourceid = {} + targetid = {'standard_name': None, 'long_name': None} + return sourceid, targetid + + @property + def mapping_name(self): + """ + Property that specifies the name of the dictionary to contain the + encoding of this metarelate mapping translation. + + """ + return 'GRIB1_LOCAL_TO_CF_CONSTRAINED' + + @property + def source_scheme(self): + """ + Property that specifies the name of the scheme for the source + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['gribm'] + + @property + def target_scheme(self): + """ + Property that specifies the name of the scheme for the target + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['cff'] + + def valid_mapping(self, mapping): + """ + Determine whether the provided :class:`metarelate.Mapping` represents a + GRIB1 local parameter to CF phenomenon and dimension coordinate + translation. + + Args: + * mapping: + A :class:`metarelate.Mapping` instance. + + Returns: + Boolean. + + """ + return self.is_grib1_local_param(mapping.source) and \ + self.is_cf_constrained(mapping.target) + + +class CFConstrainedGRIB1LocalParamMappings(Mappings): + """ + Represents a container for CF phenomenon and dimension coordinate + constraint to GRIB (edition 1) local parameter metarelate mapping + translations. + + Encoding support is provided to generate the Python dictionary source + code representation of these mappings from CF phenomenon standard name, + long name and units, and CF dimension coordinate standard name, units and + points to GRIB1 edition, table II version, centre and indicator of + parameter. + + """ + def _key(self, line): + """Provides the sort key of the mappings order.""" + return line.split(':')[0].strip() + + def msg_strings(self): + return (' (CFName({standard_name!r}, ' + '{long_name!r}, {units!r}), ' + 'DimensionCoordinate({dim_coord[standard_name]!r}, ' + '{dim_coord[units]!r}, {dim_coord[points]}))', + 'G1LocalParam({editionNumber}, {table2version}, ' + '{centre}, {indicatorOfParameter}),\n') + + def get_initial_id_nones(self): + sourceid = {'standard_name': None, 'long_name': None} + targetid = {} + return sourceid, targetid + + @property + def mapping_name(self): + """ + Property that specifies the name of the dictionary to contain the + encoding of this metarelate mapping translation. + + """ + return 'CF_CONSTRAINED_TO_GRIB1_LOCAL' + + @property + def source_scheme(self): + """ + Property that specifies the name of the scheme for the source + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['cff'] + + @property + def target_scheme(self): + """ + Property that specifies the name of the scheme for the target + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['gribm'] + + def valid_mapping(self, mapping): + """ + Determine whether the provided :class:`metarelate.Mapping` represents a + CF phenomenon and dimension coordinate to GRIB1 local parameter + translation. + + Args: + * mapping: + A :class:`metarelate.Mapping` instance. + + Returns: + Boolean. + + """ + return self.is_cf_constrained(mapping.source) and \ + self.is_grib1_local_param(mapping.target) + + +class GRIB2ParamCFMappings(Mappings): + """ + Represents a container for GRIB (edition 2) parameter to CF phenomenon + metarelate mapping translations. + + Encoding support is provided to generate the Python dictionary source + code representation of these mappings from GRIB2 edition, discipline, + parameter category and indicator of parameter to CF standard name, + long name and units. + + """ + def _key(self, line): + """Provides the sort key of the mappings order.""" + matchstr = ('^ G2Param\(([0-9]+), ([0-9]+), ([0-9]+), ' + '([0-9]+)\):.*') + match = re.match(matchstr, line) + if match is None: + raise ValueError('encoding not sortable') + return [int(i) for i in match.groups()] + + def msg_strings(self): + return (' G2Param({editionNumber}, {discipline}, ' + '{parameterCategory}, {parameterNumber})', + 'CFName({standard_name!r}, {long_name!r}, ' + '{units!r}),\n') + + def get_initial_id_nones(self): + sourceid = {} + targetid = {'standard_name': None, 'long_name': None} + return sourceid, targetid + + @property + def mapping_name(self): + """ + Property that specifies the name of the dictionary to contain the + encoding of this metarelate mapping translation. + + """ + return 'GRIB2_TO_CF' + + @property + def source_scheme(self): + """ + Property that specifies the name of the scheme for the source + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['gribm'] + + @property + def target_scheme(self): + """ + Property that specifies the name of the scheme for the target + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['cff'] + + def valid_mapping(self, mapping): + """ + Determine whether the provided :class:`metarelate.Mapping` represents a + GRIB2 parameter to CF phenomenon translation. + + Args: + * mapping: + A :class:`metarelate.Mapping` instance. + + Returns: + Boolean. + + """ + return self.is_grib2_param(mapping.source) and \ + self.is_cf(mapping.target) + + +class CFGRIB2ParamMappings(Mappings): + """ + Represents a container for CF phenomenon to GRIB (edition 2) parameter + metarelate mapping translations. + + Encoding support is provided to generate the Python dictionary source + code representation of these mappings from CF standard name, long name + and units to GRIB2 edition, discipline, parameter category and indicator + of parameter. + + """ + def _key(self, line): + """Provides the sort key of the mappings order.""" + return _cfn(line) + + def msg_strings(self): + return (' CFName({standard_name!r}, {long_name!r}, ' + '{units!r})', + 'G2Param({editionNumber}, {discipline}, ' + '{parameterCategory}, {parameterNumber}),\n') + + def get_initial_id_nones(self): + sourceid = {'standard_name': None, 'long_name': None} + targetid = {} + return sourceid, targetid + + @property + def mapping_name(self): + """ + Property that specifies the name of the dictionary to contain the + encoding of this metarelate mapping translation. + + """ + return 'CF_TO_GRIB2' + + @property + def source_scheme(self): + """ + Property that specifies the name of the scheme for the source + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['cff'] + + @property + def target_scheme(self): + """ + Property that specifies the name of the scheme for the target + :class:`metarelate.Component` defining this metarelate mapping + translation. + + """ + return FORMAT_URIS['gribm'] + + def valid_mapping(self, mapping): + """ + Determine whether the provided :class:`metarelate.Mapping` represents a + CF phenomenon to GRIB2 parameter translation. + + Args: + * mapping: + A :class:`metarelate.Mapping` instance. + + Returns: + Boolean. + + """ + return self.is_cf(mapping.source) and \ + self.is_grib2_param(mapping.target)